private void Collide(Geom geometry1, Geom geometry2, ContactList contactList)
        {
            int vertexIndex = -1;

            //Iterate the second geometry vertices
            for (int i = 0; i < geometry2.worldVertices.Count; i++)
            {
                if (contactList.Count == _physicsSimulator.maxContactsToDetect)
                {
                    break;
                }

                //grid can be null for "one-way" collision (points)
                if (geometry1.grid == null)
                {
                    break;
                }

                vertexIndex += 1;
                _vertRef     = geometry2.WorldVertices[i];
                geometry1.TransformToLocalCoordinates(ref _vertRef, out _localVertex);

                //The geometry intersects when distance <= 0
                //Continue in the list if the current vector does not intersect
                if (!geometry1.Intersect(ref _localVertex, out _feature))
                {
                    continue;
                }

                //If the second geometry's current vector intersects with the first geometry
                //create a new contact and add it to the contact list.
                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);
                }
            }

            //Iterate the first geometry vertices
            for (int i = 0; i < geometry1.WorldVertices.Count; i++)
            {
                if (contactList.Count == _physicsSimulator.maxContactsToDetect)
                {
                    break;
                }

                //grid can be null for "one-way" collision (points)
                if (geometry2.grid == null)
                {
                    break;
                }

                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 (contactCount > _physicsSimulator.maxContactsToResolve)
            {
                contactList.RemoveRange(_physicsSimulator.maxContactsToResolve,
                                        contactCount - _physicsSimulator.maxContactsToResolve);
            }

            //allow user to cancel collision if desired
            if (geometry1.OnCollision != null)
            {
                //If the contactlist is populated, this means that there is an collision.
                if (contactList.Count > 0)
                {
                    if (!geometry1.OnCollision(geometry1, geometry2, contactList))
                    {
                        //The user aborted the collision. Clear the contact list as we don't need it anymore.
                        contactList.Clear();
                    }
                }
            }

            //allow user to cancel collision if desired
            if (geometry2.OnCollision != null)
            {
                if (contactList.Count > 0)
                {
                    if (!geometry2.OnCollision(geometry2, geometry1, contactList))
                    {
                        contactList.Clear();
                    }
                }
            }
        }
Beispiel #2
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();
                    }
                }
            }
        }