Exemplo n.º 1
0
        private void Collide(Geom geometry1, Geom geometry2, ContactList contactList)
        {
            int vertexIndex = -1;

            for (int i = 0; i < geometry2.worldVertices.Count; i++)
            {
                if (contactList.Count == _physicsSimulator.maxContactsToDetect)
                {
                    break;
                }
                if (geometry1.grid == null)
                {
                    break;
                } //grid can be null for "one-way" collision (points)

                vertexIndex += 1;
                _vertRef     = geometry2.WorldVertices[i];
                geometry1.TransformToLocalCoordinates(ref _vertRef, out _localVertex);
                if (!geometry1.Intersect(ref _localVertex, out _feature))
                {
                    continue;
                }

                if (_feature.Distance < 0f)
                {
                    geometry1.TransformNormalToWorld(ref _feature.Normal, out _feature.Normal);
                    Contact contact = new Contact(geometry2.WorldVertices[i], _feature.Normal, _feature.Distance,
                                                  new ContactId(2, vertexIndex, 1));
                    contactList.Add(contact);
                }
            }

            for (int i = 0; i < geometry1.WorldVertices.Count; i++)
            {
                if (contactList.Count == _physicsSimulator.maxContactsToDetect)
                {
                    break;
                }
                if (geometry2.grid == null)
                {
                    break;
                } //grid can be null for "one-way" collision (points)

                vertexIndex += 1;

                _vertRef = geometry1.WorldVertices[i];
                geometry2.TransformToLocalCoordinates(ref _vertRef, out _localVertex);
                if (!geometry2.Intersect(ref _localVertex, out _feature))
                {
                    continue;
                }

                if (_feature.Distance < 0f)
                {
                    geometry2.TransformNormalToWorld(ref _feature.Normal, out _feature.Normal);
                    _feature.Normal = -_feature.Normal;
                    Contact contact = new Contact(geometry1.WorldVertices[i], _feature.Normal, _feature.Distance,
                                                  new ContactId(2, vertexIndex, 1));
                    contactList.Add(contact);
                }
            }

            //sort _contact list by seperation (amount of penetration)
            contactList.Sort(_contactComparer);

            //resolve deepest contacts first
            int contactCount = contactList.Count;

            if (contactList.Count > _physicsSimulator.maxContactsToResolve)
            {
                contactList.RemoveRange(_physicsSimulator.maxContactsToResolve,
                                        contactCount - _physicsSimulator.maxContactsToResolve);
            }

            //allow user to cancel collision if desired
            if (geometry1.Collision != null)
            {
                if (contactList.Count > 0)
                {
                    if (!geometry1.Collision(geometry1, geometry2, contactList))
                    {
                        contactList.Clear();
                    }
                }
            }

            //allow user to cancel collision if desired
            if (geometry2.Collision != null)
            {
                if (contactList.Count > 0)
                {
                    if (!geometry2.Collision(geometry2, geometry1, contactList))
                    {
                        contactList.Clear();
                    }
                }
            }
        }