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 void Distribute() { int nodePeakCount = PeakCount; for (int j = 0; j < nodePeakCount; j++) { if (ContainedObjects.arrayAllocation[j]) { id1 = this[j]; for (int k = j + 1; k < nodePeakCount; k++) { if (ContainedObjects.arrayAllocation[k]) { id2 = this [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 != Partition._Version)) { pair.CheckAndDistributeCollision (); pair.PartitionVersion = Partition._Version; } } } } } }
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 Assimilate(LSBody body) { if (CachedIDs.Count > 0) { id = CachedIDs.Pop (); } else { id = PeakCount; PeakCount++; } SimObjectExists [id] = true; SimObjects [id] = body; body.ID = id; for (i = 0; i < id; i++) { other = SimObjects [i]; if (!Physics2D.GetIgnoreLayerCollision (other.cachedGameObject.layer, body.cachedGameObject.layer)) { colPairIndex = i * MaxSimObjects + id; pair = CollisionPairs[colPairIndex]; if (pair == null) { pair = new CollisionPair (); CollisionPairs [colPairIndex] = pair; } FastCollisionPairs.Add (pair); pair.Initialize (other, body); CollisionPairCount++; } } for (j = id + 1; j < PeakCount; j++) { other = SimObjects [j]; if (!Physics2D.GetIgnoreLayerCollision (other.cachedGameObject.layer, body.cachedGameObject.layer)) { colPairIndex = id * MaxSimObjects + j; pair = CollisionPairs[colPairIndex]; if (pair == null) { pair = new CollisionPair (); CollisionPairs [colPairIndex] = pair; } FastCollisionPairs.Add (pair); pair.Initialize (body, other); CollisionPairCount++; } } AssimilatedCount++; }
public bool IsPositionCovered(Vector2d position) { //Checks if this body covers a position //Different techniques for different shapes switch (this.Shape) { case ColliderType.Circle: long maxDistance = this.Radius + FixedMath.Half; maxDistance *= maxDistance; if ((this._position - position).FastMagnitude() > maxDistance) { return(false); } goto case ColliderType.AABox; case ColliderType.AABox: return(position.x + FixedMath.Half >= this.XMin && position.x - FixedMath.Half <= this.XMax && position.y + FixedMath.Half >= this.YMin && position.y - FixedMath.Half <= this.YMax); break; case ColliderType.Polygon: for (int i = this.EdgeNorms.Length - 1; i >= 0; i--) { Vector2d norm = this.EdgeNorms [i]; long posProj = norm.Dot(position); long polyMin, polyMax; CollisionPair.ProjectPolygon(norm.x, norm.y, this, out polyMin, out polyMax); if (posProj >= polyMin && posProj <= polyMax) { } else { return(false); } } return(true); break; } return(false); }
public void Distribute() { int nodePeakCount = PeakCount; for (int j = 0; j < nodePeakCount; j++) { id1 = ContainedObjects [j]; for (int k = j + 1; k < nodePeakCount; k++) { id2 = ContainedObjects [k]; pair = PhysicsManager.GetCollisionPair(id1, id2); if (System.Object.ReferenceEquals(null, pair) == false && (pair.PartitionVersion != Partition._Version)) { pair.CheckAndDistributeCollision(); pair.PartitionVersion = Partition._Version; } } } }
public static void Dessimilate(LSBody body) { if (!SimObjectExists [body.ID]) { Debug.LogWarning("Object with ID" + body.ID.ToString() + "cannot be dessimilated because it it not assimilated"); return; } SimObjectExists [body.ID] = false; CachedIDs.Add(body.ID); for (i = 0; i < FastCollisionPairs.Count; i++) { pair = FastCollisionPairs.innerArray [i]; if (pair.Body1 == body || pair.Body2 == body) { pair.Deactivate(); } } AssimilatedCount--; }
public InstanceCollisionPair(ushort version, CollisionPair pair) { Version = version; Pair = pair; }
private static void CreatePair(LSBody body1, LSBody body2, int pairIndex) { pair = CollisionPairs [pairIndex]; if (pair == null) { pair = new CollisionPair (); CollisionPairs [pairIndex] = pair; } FastCollisionPairs.Add (pair); pair.Initialize (body1, body2); }
public static void Dessimilate(LSBody body) { if (!SimObjectExists [body.ID]) { Debug.LogWarning ("Object with ID" + body.ID.ToString () + "cannot be dessimilated because it it not assimilated"); return; } SimObjectExists [body.ID] = false; CachedIDs.Add (body.ID); for (i = 0; i < FastCollisionPairs.Count; i++) { pair = FastCollisionPairs.innerArray [i]; if (pair.Body1 == body || pair.Body2 == body) { pair.Deactivate (); } } AssimilatedCount--; body.Deactivate (); }
static void DeactivatePair(CollisionPair collisionPair) { PhysicsManager.DeactivateCollisionPair(collisionPair); }
public void CheckAndDistributeCollision() { if (!Active) { return; } if (_ranIndex < 0) { _ranIndex = PhysicsManager.RanCollisionPairs.Add(new PhysicsManager.InstanceCollisionPair(_Version, this)); } IsCollidingChanged = false; LastFrame = LockstepManager.FrameCount; CurrentCollisionPair = this; if (CullCounter <= 0) { GenerateCircleValues(); if (CheckHeight()) { bool result = CheckCollision(); if (result != IsColliding) { IsColliding = result; IsCollidingChanged = true; } if (CheckCollision()) { DistributeCollision(); } } Body1.NotifyContact(Body2, IsColliding, IsCollidingChanged); Body2.NotifyContact(Body1, IsColliding, IsCollidingChanged); if (IsColliding == false) { //A negative cull counter means a Body is preventing culling if (CullCounter >= 0) { if (PreventDistanceCull) { CullCounter = (short)( (LockstepManager.FrameCount - LastCollidedFrame) / PhysicsManager.CullTimeStep); if (CullCounter > PhysicsManager.CullTimeMax) { CullCounter = PhysicsManager.CullTimeMax; } } else { //Set number of frames until next collision check based on distance var distCull = ( ((FastDistance - FastDistanceOffset) >> FixedMath.SHIFT_AMOUNT) / PhysicsManager.CullDistanceStep + PhysicsManager.CullDistributor ); if (distCull > PhysicsManager.CullDistanceMax) { distCull = PhysicsManager.CullDistanceMax; } if (distCull < 0) { distCull = 0; } var timeCull = (LockstepManager.FrameCount - LastCollidedFrame) / PhysicsManager.CullTimeStep; if (timeCull > PhysicsManager.CullTimeMax) { timeCull = PhysicsManager.CullTimeMax; } CullCounter = (short)(timeCull + distCull); } } } else { LastCollidedFrame = LockstepManager.FrameCount; } } else { if (Body1.PartitionChanged || Body2.PartitionChanged) { //New partition so collision culling may not be calculated yet CullCounter = 0; CheckAndDistributeCollision(); } else { //Culled and counter 1 step closer until checking again CullCounter--; } } }
public bool Overlaps(FastList <Vector2d> outputIntersectionPoints) { outputIntersectionPoints.FastClear(); //Checks if this object overlaps the line formed by p1 and p2 switch (this.Shape) { case ColliderType.Circle: { bool overlaps = false; //Check if the circle completely fits between the line long projPos = this._position.Dot(cacheAxis.x, cacheAxis.y); //Circle withing bounds? if (projPos >= axisMin && projPos <= axisMax) { long projPerp = this._position.Dot(cacheAxisNormal.x, cacheAxisNormal.y); long perpDif = (cacheProjPerp - projPerp); long perpDist = perpDif.Abs(); if (perpDist <= _radius) { overlaps = true; } if (overlaps) { long sin = (perpDif); long cos = FixedMath.Sqrt(_radius.Mul(_radius) - sin.Mul(sin)); if (cos == 0) { outputIntersectionPoints.Add((cacheAxis * projPos) + perpVector); } else { outputIntersectionPoints.Add(cacheAxis * (projPos - cos) + perpVector); outputIntersectionPoints.Add(cacheAxis * (projPos + cos) + perpVector); } } } else { //If not, check distances to points long p1Dist = _position.FastDistance(cacheP1.x, cacheP2.y); if (p1Dist <= this.FastRadius) { outputIntersectionPoints.Add(cacheP1); overlaps = true; } long p2Dist = _position.FastDistance(cacheP2.x, cacheP2.y); if (p2Dist <= this.FastRadius) { outputIntersectionPoints.Add(cacheP2); overlaps = true; } } return(overlaps); } break; case ColliderType.AABox: { } break; case ColliderType.Polygon: { bool intersected = false; for (int i = 0; i < this.Vertices.Length; i++) { int edgeIndex = i; Vector2d pivot = this.RealPoints [edgeIndex]; Vector2d edge = this.Edges [edgeIndex]; long proj1 = 0; int nextIndex = edgeIndex + 1 < this.RealPoints.Length ? edgeIndex + 1 : 0; Vector2d nextPoint = RealPoints [nextIndex]; long proj2 = (nextPoint - pivot).Dot(edge); long min; long max; if (proj1 < proj2) { min = proj1; max = proj2; } else { min = proj2; max = proj1; } long lineProj1 = (cacheP1 - pivot).Dot(edge); long lineProj2 = (cacheP2 - pivot).Dot(edge); long lineMin; long lineMax; if (lineProj1 < lineProj2) { lineMin = lineProj1; lineMax = lineProj2; } else { lineMin = lineProj2; lineMax = lineProj1; } if (CollisionPair.CheckOverlap(min, max, lineMin, lineMax)) { Vector2d edgeNorm = this.EdgeNorms [edgeIndex]; long normProj = 0; long normLineProj1 = (cacheP1 - pivot).Dot(edgeNorm); long normLineProj2 = (cacheP2 - pivot).Dot(edgeNorm); long normLineMin; long normLineMax; if (normLineProj1 < normLineProj2) { normLineMin = normLineProj1; normLineMax = normLineProj2; } else { normLineMin = normLineProj2; normLineMax = normLineProj1; } if (normProj >= normLineMin && normProj <= normLineMax) { long revProj1 = pivot.Dot(LSBody.cacheAxisNormal); long revProj2 = nextPoint.Dot(cacheAxisNormal); long revMin; long revMax; if (revProj1 < revProj2) { revMin = revProj1; revMax = revProj2; } else { revMin = revProj2; revMax = revProj1; } if (LSBody.cacheProjPerp >= revMin && LSBody.cacheProjPerp <= revMax) { intersected = true; if (LSBody.calculateIntersections) { long fraction = normLineProj1.Abs().Div(normLineMax - normLineMin); long intersectionProj = FixedMath.Lerp(lineProj1, lineProj2, fraction); outputIntersectionPoints.Add(edge * intersectionProj + pivot); if (outputIntersectionPoints.Count == 2) { break; } } } } } } return(intersected); } break; } return(false); }
public void CheckAndDistributeCollision() { if (!Active) return; CurrentCollisionPair = this; if (CheckCollision ()) { if (IsColliding == false) { if (Body1.OnContactEnter != null) Body1.OnContactEnter (Body2); if (Body2.OnContactEnter != null) Body2.OnContactEnter (Body1); IsColliding = true; } else { } DistributeCollision (); } else { if (IsColliding) { if (Body1.OnContactExit != null) { Body1.OnContactExit (Body2); } if (Body2.OnContactExit != null) { Body2.OnContactExit (Body1); } IsColliding = false; } else { } } }
public static void RemovePairReferences(CollisionPair pair) { pair.Body1.CollisionPairs.Remove(pair.Body2.ID); pair.Body2.CollisionPairHolders.Remove(pair.Body1.ID); }
public static void PoolPair(CollisionPair pair) { pair.Deactivate(); if (LockstepManager.PoolingEnabled) CachedCollisionPairs.Add(pair); }
public static void Simulate() { CollisionIterationRemain = (CollisionPairCount) / CollisionIterationSpread + 1; if (CollisionIterationCount == CollisionIterationSpread) { CollisionIterationCount = 0; CollisionIterationMark = 0; } else { CollisionIterationMark += CollisionIterationRemain; } CurCount = 0; for (i = 0; i < FastCollisionPairs.Count; i++) { pair = FastCollisionPairs[i]; CurCount++; if (CollisionIterationRemain == 0 || CurCount < CollisionIterationMark) { pair.DistributeCollision(); } else { pair.CheckAndDistributeCollision(); CollisionIterationRemain--; } } if (CollisionIterationCount == 0) { for (i = 0; i < PeakCount; i++) { if (SimObjectExists [i]) { LSBody b1 = SimObjects [i]; b1.EarlySimulate(); if (b1.PositionChanged) { Partition.Body = b1; Partition.PartitionObject(); } b1.Simulate(); } } Partition.EstablishPartitions(); } else { for (i = 0; i < PeakCount; i++) { if (SimObjectExists [i]) { LSBody b1 = SimObjects [i]; b1.EarlySimulate(); b1.Simulate(); } } } CollisionIterationCount++; }
public static void Simulate() { CollisionIterationRemain = (CollisionPairCount) / CollisionIterationSpread + 1; if (CollisionIterationCount == CollisionIterationSpread) { CollisionIterationCount = 0; CollisionIterationMark = 0; } else { CollisionIterationMark += CollisionIterationRemain; } CurCount = 0; for (i = 0; i < FastCollisionPairs.Count; i++) { pair = FastCollisionPairs[i]; CurCount ++; if (CollisionIterationRemain == 0 || CurCount < CollisionIterationMark) { pair.DistributeCollision (); } else { pair.CheckAndDistributeCollision (); CollisionIterationRemain--; } } if (CollisionIterationCount == 0) { for (i = 0; i < PeakCount; i++) { if (SimObjectExists [i]) { LSBody b1 = SimObjects [i]; b1.EarlySimulate (); if (b1.PositionChanged) { Partition.Body = b1; Partition.PartitionObject (); } b1.Simulate (); } } Partition.EstablishPartitions (); } else { for (i = 0; i < PeakCount; i++) { if (SimObjectExists [i]) { LSBody b1 = SimObjects [i]; b1.EarlySimulate (); b1.Simulate (); } } } CollisionIterationCount++; }
public void CheckAndDistributeCollision() { if (!Active || Body1.HasParent || Body2.HasParent) { return; } CurrentCollisionPair = this; if (CheckCollision ()) { if (IsColliding == false) { if (Body1.OnContactEnter .IsNotNull ()) { Body1.OnContactEnter (Body2); } if (Body2.OnContactEnter .IsNotNull ()) { Body2.OnContactEnter (Body1); } IsColliding = true; } else { } DistributeCollision (); } else { if (IsColliding) { if (Body1.OnContactExit .IsNotNull ()) { Body1.OnContactExit (Body2); } if (Body2.OnContactExit .IsNotNull ()) { Body2.OnContactExit (Body1); } IsColliding = false; } else { } } }