private void FillHash() { //Average used to optimize cell size if AutoAdjustCellSize = true. float average = 0; for (int i = 0; i < _physicsSimulator.GeomList.Count; i++) { Geom geom = _physicsSimulator.GeomList[i]; //Note: Could do some checking here for geometries that should not be included in the hashmap AABB aabb = geom.AABB; if (AutoAdjustCellSize) { average += Math.Max(aabb.Max.X - aabb.Min.X, aabb.Max.Y - aabb.Min.Y); } int minX = (int)(aabb.Min.X * _cellSizeInv); int maxX = (int)(aabb.Max.X * _cellSizeInv) + 1; int minY = (int)(aabb.Min.Y * _cellSizeInv); int maxY = (int)(aabb.Max.Y * _cellSizeInv) + 1; for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { long key = PairID.GetHash(x, y); List <Geom> list; if (!_hash.TryGetValue(key, out list)) { list = new List <Geom>(); _hash.Add(key, list); } list.Add(geom); } } } if (AutoAdjustCellSize) { CellSize = 2 * average / (_physicsSimulator.GeomList.Count); } }
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]); } }