Пример #1
0
        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);
                    }
                }
            }
        }
Пример #3
0
            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);
                    }
                }
            }
        }