public static void EstablishPartitions() { for (i = 0; i < Count * Count; i++) { node = Nodes[i]; ListLength = node.Count; if (ListLength == 0) { continue; } for (j = 0; j < ListLength; j++) { id1 = node.innerArray[j]; for (k = j + 1; k < ListLength; k++) { id2 = node.innerArray[k]; if (id1 < id2) { pair = PhysicsManager.CollisionPairs[id1 * PhysicsManager.MaxSimObjects + id2]; } else { pair = PhysicsManager.CollisionPairs[id2 * PhysicsManager.MaxSimObjects + id1]; } if (pair == null) { continue; } pair.SamePartition = true; } } } }
public static void Initialize() { for (i = 0; i < Count * Count; i++) { Nodes[i] = new PartitionNode(); } }
public static void Initialize() { for (i = 0; i < Count * Count; i++) { Nodes[i] = new PartitionNode (); } }
public static void UpdateObject(LSBody Body, bool repartition = true) { GetGridBounds(Body); if ( repartition == false || (Body.PastGridXMin != GridXMin || Body.PastGridXMax != GridXMax || Body.PastGridYMin != GridYMin || Body.PastGridYMax != GridYMax)) { //Remove from all partitions no longer located on for (int o = Body.PastGridXMin; o <= Body.PastGridXMax; o++) { for (int p = Body.PastGridYMin; p <= Body.PastGridYMax; p++) { PartitionNode node = GetNode(o, p); if (Body.Immovable) { node.RemoveImmovable(Body.ID); } else { node.Remove(Body.ID); } } } if (repartition) { PartitionObject(Body, true); } } }
public static void EstablishPartitions() { for (i = 0 ; i < Count * Count; i++) { node = Nodes[i]; ListLength = node.Count; if (ListLength == 0) continue; for (j = 0; j < ListLength; j++) { id1 = node.innerArray[j]; for (k = j + 1; k < ListLength; k++) { id2 = node.innerArray[k]; if (id1 < id2) { pair = PhysicsManager.CollisionPairs[id1 * PhysicsManager.MaxSimObjects + id2]; } else { pair = PhysicsManager.CollisionPairs[id2 * PhysicsManager.MaxSimObjects + id1]; } if (pair == null) continue; pair.SamePartition = true; } } } }
/// <summary> /// Finds all dynamic bodies touching a defined circle. /// </summary> /// <param name="radius">Radius.</param> /// <param name="output">Output.</param> public static void CircleCast(Vector2d position, long radius, FastList <LSBody> output) { long xMin = position.x - radius, xmax = position.x + radius; long yMin = position.y - radius, yMax = position.y + radius; //Find the partition tiles we have to search in first int gridXMin, gridXMax, gridYMin, gridYMax; Partition.GetGridBounds(xMin, xmax, yMin, yMax, out gridXMin, out gridXMax, out gridYMin, out gridYMax); for (int i = gridXMin; i <= gridXMax; i++) { for (int j = gridYMin; j <= gridYMax; j++) { PartitionNode node = Partition.GetNode(i, j); for (int k = 0; k < node.ContainedDynamicObjects.Count; k++) { var body = PhysicsManager.SimObjects [node.ContainedDynamicObjects [k]]; long minFastDist = body.Radius + radius; //unnormalized distance value for comparison minFastDist *= minFastDist; if (body.Position.FastDistance(position) <= minFastDist) { //Body touches circle! output.Add(body); } } } } }
public static void PartitionObject(LSBody Body, bool gridBoundsCalculated = false) { if (gridBoundsCalculated == false) { GetGridBounds(Body); } Body.PastGridXMin = GridXMin; Body.PastGridXMax = GridXMax; Body.PastGridYMin = GridYMin; Body.PastGridYMax = GridYMax; for (int i = GridXMin; i <= GridXMax; i++) { for (int j = GridYMin; j <= GridYMax; j++) { PartitionNode node = GetNode(i, j); Body.PartitionChanged = true; if (Body.Immovable) { node.AddImmovable(Body.ID); } else { node.Add(Body.ID); } } } }
public static IEnumerable <LSBody> RaycastAll(Vector2d start, Vector2d end) { _Version++; LSBody.PrepareAxisCheck(start, end); foreach (FractionalLineAlgorithm.Coordinate coor in GetRelevantNodeCoordinates(start, end)) { int indexX = coor.X; int indexY = coor.Y; if (!Partition.CheckValid(coor.X, coor.Y)) { break; } PartitionNode node = Partition.GetNode(indexX, indexY); for (int i = node.ContainedDynamicObjects.Count - 1; i >= 0; i--) { LSBody body = PhysicsManager.SimObjects[node.ContainedDynamicObjects[i]]; if (body.IsNotNull() && body.RaycastVersion != _Version) { if (Conditional.IsNull() || Conditional()) { body.RaycastVersion = _Version; if (body.Overlaps(bufferIntersectionPoints)) { yield return(body); } } } } } Conditional = null; yield break; }
public static void CheckAndDistributeCollisions() { _Version++; for (i = 0; i < Count * Count; i++) { node = Nodes [i]; ListLength = node.Count; if (ListLength == 0) continue; for (j = 0; j < ListLength; j++) { id1 = node.innerArray [j]; for (k = j + 1; k < ListLength; k++) { id2 = node.innerArray [k]; if (id1 < id2) { pair = PhysicsManager.CollisionPairs [id1 * PhysicsManager.MaxSimObjects + id2]; } else { pair = PhysicsManager.CollisionPairs [id2 * PhysicsManager.MaxSimObjects + id1]; } if (System.Object.ReferenceEquals (null, pair) == false && (pair.PartitionVersion != _Version)) { pair.CheckAndDistributeCollision (); pair.PartitionVersion = _Version; } } } } }
public static int AddNode(PartitionNode node) { int activationID = ActivatedNodes.Add(node); AllocatedNodes.Add(node); return(activationID); }
public static void CheckAndDistributeCollisions() { _Version++; for (i = 0; i < Count * Count; i++) { node = Nodes [i]; ListLength = node.Count; if (ListLength == 0) { continue; } for (j = 0; j < ListLength; j++) { id1 = node.innerArray [j]; for (k = j + 1; k < ListLength; k++) { id2 = node.innerArray [k]; if (id1 < id2) { pair = PhysicsManager.CollisionPairs [id1 * PhysicsManager.MaxSimObjects + id2]; } else { pair = PhysicsManager.CollisionPairs [id2 * PhysicsManager.MaxSimObjects + id1]; } if (System.Object.ReferenceEquals(null, pair) == false && (pair.PartitionVersion != _Version)) { pair.CheckAndDistributeCollision(); pair.PartitionVersion = _Version; } } } } }
public static void Setup() { _Version = 1; for (int i = 0; i < Count * Count; i++) { Nodes [i] = new PartitionNode(); } }
public static PartitionNode GetNode(int indexX, int indexY) { PartitionNode node = Nodes [indexX, indexY]; if (node.IsNull()) { node = new PartitionNode(); Nodes [indexX, indexY] = node; } return(node); }
public static void CheckAndDistributeCollisions() { _Version++; for (int i = ActivatedNodes.PeakCount - 1; i >= 0; i--) { if (ActivatedNodes.arrayAllocation [i]) { PartitionNode node = ActivatedNodes [i]; node.Distribute(); } } }
public static void GetTouchingPartitions(LSBody Body, FastList <PartitionNode> output) { GetGridBounds(Body); for (int i = GridXMin; i <= GridXMax; i++) { for (int j = GridYMin; j <= GridYMax; j++) { PartitionNode node = GetNode(i, j); output.Add(node); } } }
public static void CheckAndDistributeCollisions() { count = 0; _Version++; for (int i = ActivatedNodes.PeakCount - 1; i >= 0; i--) { if (ActivatedNodes.arrayAllocation [i]) { PartitionNode node = ActivatedNodes [i]; node.Distribute(); } } //Debug.Log (count + " pairs checked"); }
public static void UpdateObject(LSBody Body) { GridXMin = (Body.XMin - OffsetX) >> ShiftSize; GridXMax = ((Body.XMax - OffsetX) >> ShiftSize); GridYMin = ((Body.YMin - OffsetY) >> ShiftSize); GridYMax = ((Body.YMax - OffsetY) >> ShiftSize); #if UNITY_EDITOR if (GridXMin < 0 || GridXMax >= Count || GridYMin < 0 || GridYMax >= Count) { Debug.LogError("Body with ID " + Body.ID.ToString() + " is out of partition bounds."); return; } #endif if (Body.PastGridXMin != GridXMin || Body.PastGridXMax != GridXMax || Body.PastGridYMin != GridYMin || Body.PastGridYMax != GridYMax) { for (long o = Body.PastGridXMin; o <= Body.PastGridXMax; o++) { for (long p = Body.PastGridYMin; p <= Body.PastGridYMax; p++) { PartitionNode node = Nodes [o * Count + p]; node.Remove(Body.ID); } } for (long i = GridXMin; i <= GridXMax; i++) { for (long j = GridYMin; j <= GridYMax; j++) { PartitionNode node = Nodes [i * Count + j]; node.Add(Body.ID); } } Body.PastGridXMin = GridXMin; Body.PastGridXMax = GridXMax; Body.PastGridYMin = GridYMin; Body.PastGridYMax = GridYMax; } }
public static void PartitionObject(LSBody Body) { GetGridBounds(Body); Body.PastGridXMin = GridXMin; Body.PastGridXMax = GridXMax; Body.PastGridYMin = GridYMin; Body.PastGridYMax = GridYMax; for (int i = GridXMin; i <= GridXMax; i++) { for (int j = GridYMin; j <= GridYMax; j++) { PartitionNode node = GetNode(i, j); node.Add(Body.ID); } } }
public static void PartitionObject(LSBody Body) { GridXMin = ((Body.XMin - OffsetX) >> ShiftSize); GridXMax = ((Body.XMax - OffsetX) >> ShiftSize); GridYMin = ((Body.YMin - OffsetY) >> ShiftSize); GridYMax = ((Body.YMax - OffsetY) >> ShiftSize); Body.PastGridXMin = GridXMin; Body.PastGridXMax = GridXMax; Body.PastGridYMin = GridYMin; Body.PastGridYMax = GridYMax; for (long i = GridXMin; i <= GridXMax; i++) { for (long j = GridYMin; j <= GridYMax; j++) { PartitionNode node = Nodes [i * Count + j]; node.Add(Body.ID); } } }
public static void UpdateObject(LSBody Body, bool repartition = true) { GetGridBounds(Body); if (Body.PastGridXMin != GridXMin || Body.PastGridXMax != GridXMax || Body.PastGridYMin != GridYMin || Body.PastGridYMax != GridYMax) { for (int o = Body.PastGridXMin; o <= Body.PastGridXMax; o++) { for (int p = Body.PastGridYMin; p <= Body.PastGridYMax; p++) { PartitionNode node = GetNode(o, p); node.Remove(Body.ID); } } if (repartition) { PartitionObject(Body, true); } } }
public static void UpdateObject(LSBody Body) { GetGridBounds(Body); if (Body.PastGridXMin != GridXMin || Body.PastGridXMax != GridXMax || Body.PastGridYMin != GridYMin || Body.PastGridYMax != GridYMax) { for (int o = Body.PastGridXMin; o <= Body.PastGridXMax; o++) { for (int p = Body.PastGridYMin; p <= Body.PastGridYMax; p++) { PartitionNode node = GetNode(o, p); node.Remove(Body.ID); } } for (int i = GridXMin; i <= GridXMax; i++) { for (int j = GridYMin; j <= GridYMax; j++) { PartitionNode node = GetNode(i, j); node.Add(Body.ID); } } Body.PastGridXMin = GridXMin; Body.PastGridXMax = GridXMax; Body.PastGridYMin = GridYMin; Body.PastGridYMax = GridYMax; } }
public static IEnumerable <LSBody> RaycastAll(Vector2d start, Vector2d end) { LSBody.PrepareAxisCheck(start, end); foreach (FractionalLineAlgorithm.Coordinate coor in GetRelevantNodeCoordinates(start, end)) { int indexX = coor.X; int indexY = coor.Y; if (!Partition.CheckValid(coor.X, coor.Y)) { break; } PartitionNode node = Partition.GetNode(indexX, indexY); for (int i = node.ContainedObjects.Count - 1; i >= 0; i--) { LSBody body = PhysicsManager.SimObjects [node.ContainedObjects [i]]; if (body.Overlaps()) { yield return(body); } } } yield break; }
public static void PartitionObject(LSBody Body) { GridXMin = Body.XMin <= Body.FutureXMin ? ((Body.XMin - OffsetX) >> ShiftSize) : ((Body.FutureXMin - OffsetX) >> ShiftSize); GridXMax = Body.XMax >= Body.FutureXMax ? ((Body.XMax - OffsetX) >> ShiftSize) : ((Body.FutureXMax - OffsetX) >> ShiftSize); GridYMin = Body.YMin <= Body.FutureXMin ? ((Body.YMin - OffsetY) >> ShiftSize) : ((Body.FutureYMin - OffsetY) >> ShiftSize); GridYMax = Body.YMax >= Body.FutureYMax ? ((Body.YMax - OffsetY) >> ShiftSize) : ((Body.FutureYMax - OffsetY) >> ShiftSize); #if UNITY_EDITOR if (GridXMin < 0 || GridXMax >= Count || GridYMin < 0 || GridYMax >= Count) { Debug.LogError ("Body with ID " + Body.ID.ToString () + " is out of partition bounds."); return; } #endif if (Body.PastGridXMin != GridXMin || Body.PastGridXMax != GridXMax || Body.PastGridYMin != GridYMin || Body.PastGridYMax != GridYMax) { for (o = Body.PastGridXMin; o <= Body.PastGridXMax; o++) { for (p = Body.PastGridYMin; p <= Body.PastGridYMax; p++) { node = Nodes [o * Count + p]; node.Remove (Body.ID); } } for (i = GridXMin; i <= GridXMax; i++) { for (j = GridYMin; j <= GridYMax; j++) { node = Nodes [i * Count + j]; node.Add (Body.ID); } } Body.PastGridXMin = GridXMin; Body.PastGridXMax = GridXMax; Body.PastGridYMin = GridYMin; Body.PastGridYMax = GridYMax; } }
private bool InternalRaycast(Vector2d From, Vector2d To, int ExceptionID) { _Version++; MadeContact = false; Hits.FastClear(); const int StepSize = 1 << Partition.ShiftSize; x0 = From.x; y0 = From.y; x1 = To.x; y1 = To.y; if (y1 > y0) { compare1 = y1 - y0; } else { compare1 = y0 - y1; } if (x1 > x0) { compare2 = x1 - x0; } else { compare2 = x0 - x1; } steep = compare1 > compare2; if (steep) { t = x0; // swap x0 and y0 x0 = y0; y0 = t; t = x1; // swap x1 and y1 x1 = y1; y1 = t; } if (x0 > x1) { t = x0; // swap x0 and x1 x0 = x1; x1 = t; t = y0; // swap y0 and y1 y0 = y1; y1 = t; } dx = x1 - x0; dy = (y1 - y0); if (dy < 0) { dy = -dy; } error = dx / 2; ystep = (y0 < y1) ? StepSize : -StepSize; y = y0; AxisX = From.x - To.x; AxisY = From.y - To.y; Mag = FixedMath.Sqrt((AxisX * AxisX + AxisY * AxisY) >> FixedMath.SHIFT_AMOUNT); if (Mag == 0) { return(false); } AxisX = FixedMath.Div(AxisX, Mag); AxisY = FixedMath.Div(AxisY, Mag); AxisMin = Vector2d.Dot(AxisX, AxisY, From.x, From.y); AxisMax = Vector2d.Dot(AxisX, AxisY, To.x, To.y); if (AxisMin > AxisMax) { SwapValue = AxisMin; AxisMin = AxisMax; AxisMax = SwapValue; } PerpProj = Vector2d.Dot(-AxisY, AxisX, From.x, From.y); XMin = From.x; XMax = To.x; if (XMin > XMax) { SwapValue = XMin; XMin = XMax; XMax = SwapValue; } YMin = From.y; YMax = To.y; if (YMin > YMax) { SwapValue = YMin; YMin = YMax; YMax = SwapValue; } x = x0; while (true) { if (steep) { retX = (y - Partition.OffsetX) / StepSize; retY = (x - Partition.OffsetY) / StepSize; } else { retX = (x - Partition.OffsetX) / StepSize; retY = (y - Partition.OffsetY) / StepSize; } PartitionNode node = Partition.Nodes [retX * Partition.Count + retY]; if (node.Count > 0) { for (i = 0; i < node.Count; i++) { DidHit = false; LSBody body = PhysicsManager.SimObjects [node [i]]; if (body.RaycastVersion != _Version && body.ID != ExceptionID) { body.RaycastVersion = _Version; switch (body.Shape) { case ColliderType.Circle: Projection = Vector2d.Dot(AxisX, AxisY, body.Position.x, body.Position.y); TestMin = Projection - body.Radius; TestMax = Projection + body.Radius; if (TestMin < AxisMax) { if (TestMax > AxisMin) { Projection = Vector2d.Dot(-AxisY, AxisX, body.Position.x, body.Position.y); TestMin = Projection - body.Radius; TestMax = Projection + body.Radius; if (PerpProj < TestMax && PerpProj > TestMin) { DidHit = true; } } } break; case ColliderType.AABox: if (AxisMin < body.XMax) { if (AxisMax > body.XMin) { if (PerpProj < body.YMax) { if (PerpProj > body.YMin) { DidHit = true; } } } } break; } if (DidHit) { Hits.Add(body); MadeContact = true; break; } } } } error = error - dy; if (error < 0) { y += ystep; error += dx; } if (x >= x1) { break; } x += StepSize; } return(MadeContact); }
public static void Setup() { _Version = 1; for (int i = 0; i < Count * Count; i++) { Nodes [i] = new PartitionNode (); } }