private void RunHash() { _keysToRemove.Clear(); foreach (KeyValuePair <long, List <Geom> > pair in _hash) { // If there are no geometries in the list. Remove it. // If there are any geometries in the list, process them. List <Geom> list = pair.Value; if (list.Count == 0) { _keysToRemove.Add(pair.Key); } else { for (int i = 0; i < list.Count - 1; i++) { Geom geometryA = list[i]; for (int j = i + 1; j < list.Count; j++) { Geom geometryB = list[j]; if (!geometryA.body.Enabled || !geometryB.body.Enabled) { continue; } if ((geometryA.CollisionGroup == geometryB.CollisionGroup) && geometryA.CollisionGroup != 0 && geometryB.CollisionGroup != 0) { continue; } if (!geometryA.CollisionEnabled || !geometryB.CollisionEnabled) { continue; } if (geometryA.body.isStatic && geometryB.body.isStatic) { continue; } if (geometryA.body == geometryB.body) { continue; } if (((geometryA.CollisionCategories & geometryB.CollidesWith) == CollisionCategory.None) & ((geometryB.CollisionCategories & geometryA.CollidesWith) == CollisionCategory.None)) { continue; } if (geometryA.IsGeometryIgnored(geometryB) || geometryB.IsGeometryIgnored(geometryA)) { continue; } long key = PairID.GetId(geometryA.id, geometryB.id); if (!_filter.ContainsKey(key)) { _filter.Add(key, null); //Check if there is intersection bool intersection = AABB.Intersect(ref geometryA.AABB, ref geometryB.AABB); //User can cancel collision if (OnBroadPhaseCollision != null) { intersection = OnBroadPhaseCollision(geometryA, geometryB); } if (!intersection) { continue; } _physicsSimulator.ArbiterList.AddArbiterForGeomPair(_physicsSimulator, geometryA, geometryB); } } } list.Clear(); } } _filter.Clear(); //Remove all the empty lists from the hash for (int index = 0; index < _keysToRemove.Count; ++index) { _hash.Remove(_keysToRemove[index]); } }
private void DetectInternal(bool doX) { List <Stub> stubs = (doX) ? (_xStubs) : (_yStubs); _currentBodies.Clear(); for (int index = 0; index < stubs.Count; index++) { Stub stub = stubs[index]; Wrapper wrapper1 = stub.Wrapper; if (stub.Begin) { //set the min and max values if (doX) { wrapper1.SetY(); } else { wrapper1.SetX(); } Geom geometryA = wrapper1.Geom; for (LinkedListNode <Wrapper> node = _currentBodies.First; node != null; node = node.Next) { Wrapper wrapper2 = node.Value; Geom geometryB = wrapper2.Geom; if (wrapper1.Min <= wrapper2.Max && wrapper2.Min <= wrapper1.Max) { if (!geometryA.body.Enabled || !geometryB.body.Enabled) { continue; } if ((geometryA.CollisionGroup == geometryB.CollisionGroup) && geometryA.CollisionGroup != 0 && geometryB.CollisionGroup != 0) { continue; } if (!geometryA.CollisionEnabled || !geometryB.CollisionEnabled) { continue; } if (geometryA.body.isStatic && geometryB.body.isStatic) { continue; } if (geometryA.body == geometryB.body) { continue; } if (((geometryA.CollisionCategories & geometryB.CollidesWith) == CollisionCategory.None) & ((geometryB.CollisionCategories & geometryA.CollidesWith) == CollisionCategory.None)) { continue; } if (geometryA.IsGeometryIgnored(geometryB) || geometryB.IsGeometryIgnored(geometryA)) { continue; } bool intersection = true; //Call the OnBroadPhaseCollision event first. If the user aborts the collision //it will not create an arbiter if (OnBroadPhaseCollision != null) { intersection = OnBroadPhaseCollision(geometryA, geometryB); } if (!intersection) { continue; } _physicsSimulator.ArbiterList.AddArbiterForGeomPair(_physicsSimulator, geometryA, geometryB); } } if (wrapper1.ShouldAddNode) { _currentBodies.AddLast(wrapper1.Node); } } else { if (wrapper1.ShouldAddNode) { _currentBodies.Remove(wrapper1.Node); } } } }
public void MoveUnderConsiderationToOverlaps() { for (int i = 0; i < Count; i++) { if (this[i].UnderConsideration.Count == 0) { continue; } Geom geometryA = this[i].Geometry; // First transfer those under consideration to overlaps, // for, they have been considered... int startIndex = this[i].Overlaps.Count; this[i].Overlaps.AddRange(this[i].UnderConsideration); this[i].UnderConsideration.Clear(); for (int j = startIndex; j < this[i].Overlaps.Count; j++) { Geom geometryB = this[i].Overlaps[j]; // It is possible that we may test the same pair of geometries // for both extents (x and y), however, I'm banking on that // one of the extents has probably already been cached and // therefore, won't be checked. if (!geometryA.body.Enabled || !geometryB.body.Enabled) { continue; } if ((geometryA.CollisionGroup == geometryB.CollisionGroup) && geometryA.CollisionGroup != 0 && geometryB.CollisionGroup != 0) { continue; } if (!geometryA.CollisionEnabled || !geometryB.CollisionEnabled) { continue; } if (geometryA.body.isStatic && geometryB.body.isStatic) { continue; } if (geometryA.body == geometryB.body) { continue; } if (((geometryA.CollisionCategories & geometryB.CollidesWith) == CollisionCategory.None) & ((geometryB.CollisionCategories & geometryA.CollidesWith) == CollisionCategory.None)) { continue; } if (geometryA.IsGeometryIgnored(geometryB) || geometryB.IsGeometryIgnored(geometryA)) { continue; } //TMP AABB aabb1 = new AABB(); AABB aabb2 = new AABB(); aabb1.min = geometryA.AABB.min; aabb1.max = geometryA.AABB.max; aabb2.min = geometryB.AABB.min; aabb2.max = geometryB.AABB.max; aabb1.min.X -= _floatTolerance; aabb1.min.Y -= _floatTolerance; aabb1.max.X += _floatTolerance; aabb1.max.Y += _floatTolerance; aabb2.min.X -= _floatTolerance; aabb2.min.Y -= _floatTolerance; aabb2.max.X += _floatTolerance; aabb2.max.Y += _floatTolerance; if (!AABB.Intersect(ref aabb1, ref aabb2)) { continue; } //Call the OnBroadPhaseCollision event first. If the user aborts the collision //it will not create an arbiter if (Owner.OnBroadPhaseCollision != null) { if (Owner.OnBroadPhaseCollision(geometryA, geometryB)) { Owner.CollisionPairs.AddPair(geometryA, geometryB); } } else { Owner.CollisionPairs.AddPair(geometryA, geometryB); } } } }
/// <summary> /// Updates this instance. /// </summary> public void Update() { //Iterate all the geoms and check against the next for (int i = 0; i < _physicsSimulator.GeomList.Count - 1; i++) { for (int j = i + 1; j < _physicsSimulator.GeomList.Count; j++) { _geometryA = _physicsSimulator.GeomList[i]; _geometryB = _physicsSimulator.GeomList[j]; if (!_geometryA.body.Enabled || !_geometryB.body.Enabled) { continue; } if ((_geometryA.CollisionGroup == _geometryB.CollisionGroup) && _geometryA.CollisionGroup != 0 && _geometryB.CollisionGroup != 0) { continue; } if (!_geometryA.CollisionEnabled || !_geometryB.CollisionEnabled) { continue; } if (_geometryA.body.isStatic && _geometryB.body.isStatic) { continue; } if (_geometryA.body == _geometryB.body) { continue; } if (((_geometryA.CollisionCategories & _geometryB.CollidesWith) == CollisionCategory.None) & ((_geometryB.CollisionCategories & _geometryA.CollidesWith) == CollisionCategory.None)) { continue; } if (_geometryA.IsGeometryIgnored(_geometryB) || _geometryB.IsGeometryIgnored(_geometryA)) { continue; } //Assume intersection bool intersection = true; //Check if there is no intersection if (_geometryA.AABB.min.X > _geometryB.AABB.max.X || _geometryB.AABB.min.X > _geometryA.AABB.max.X) { intersection = false; } else if (_geometryA.AABB.min.Y > _geometryB.AABB.Max.Y || _geometryB.AABB.min.Y > _geometryA.AABB.Max.Y) { intersection = false; } //Call the OnBroadPhaseCollision event first. If the user aborts the collision //it will not create an arbiter if (OnBroadPhaseCollision != null) { intersection = OnBroadPhaseCollision(_geometryA, _geometryB); } //If the user aborted the intersection, continue to the next geometry. if (!intersection) { continue; } Arbiter arbiter = _physicsSimulator.arbiterPool.Fetch(); arbiter.ConstructArbiter(_geometryA, _geometryB, _physicsSimulator); if (!_physicsSimulator.ArbiterList.Contains(arbiter)) { _physicsSimulator.ArbiterList.Add(arbiter); } else { _physicsSimulator.arbiterPool.Insert(arbiter); } } } }