public Entity CreateDebugEntity(PhysicsComponent component, bool alwaysAddOffset = false)
        {
            if (component?.ColliderShape == null) return null;

            if (component.DebugEntity != null) return null;

            var debugEntity = new Entity();

            var skinnedElement = component as PhysicsSkinnedComponentBase;
            if (skinnedElement != null && skinnedElement.BoneIndex != -1)
            {
                Vector3 scale, pos;
                Quaternion rot;
                skinnedElement.BoneWorldMatrixOut.Decompose(out scale, out rot, out pos);
                debugEntity.Transform.Position = pos;
                debugEntity.Transform.Rotation = rot;
            }
            else
            {
                Vector3 scale, pos;
                Quaternion rot;
                component.Entity.Transform.WorldMatrix.Decompose(out scale, out rot, out pos);
                debugEntity.Transform.Position = pos;
                debugEntity.Transform.Rotation = rot;
            }

            var rigidBody = component as RigidbodyComponent;

            //don't add offset for non bone dynamic and kinematic as it is added already in the updates
            var colliderEntity = CreateChildEntity(component, component.ColliderShape, alwaysAddOffset || rigidBody == null);
            if (colliderEntity != null) debugEntity.AddChild(colliderEntity);

            return debugEntity;
        }
Example #2
0
        public Collision(PhysicsComponent colliderA, PhysicsComponent colliderB)
        {
            ColliderA = colliderA;
            ColliderB = colliderB;

            NewContactChannel = new Channel<ContactPoint> { Preference = ChannelPreference.PreferSender };
            ContactUpdateChannel = new Channel<ContactPoint> { Preference = ChannelPreference.PreferSender };
            ContactEndedChannel = new Channel<ContactPoint> { Preference = ChannelPreference.PreferSender };
        }
        public Entity CreateDebugEntity(PhysicsComponent component)
        {
            if (component?.ColliderShape == null) return null;

            if (component.DebugEntity != null) return null;

            var debugEntity = new Entity();

            var colliderEntity = CreateChildEntity(component, component.ColliderShape, true);
            if (colliderEntity == null) return null;

            debugEntity.AddChild(colliderEntity);

            if (component.CanScaleShape)
            {
                debugEntity.Transform.Scale = component.ColliderShape.Scaling;
            }

            var skinnedElement = component as PhysicsSkinnedComponentBase;
            if (skinnedElement != null && skinnedElement.BoneIndex != -1)
            {
                Vector3 scale, pos;
                Quaternion rot;
                skinnedElement.BoneWorldMatrixOut.Decompose(out scale, out rot, out pos);
                debugEntity.Transform.Position = pos;
                debugEntity.Transform.Rotation = rot;
            }
            else
            {
                Vector3 scale, pos;
                Quaternion rot;
                component.Entity.Transform.WorldMatrix.Decompose(out scale, out rot, out pos);
                debugEntity.Transform.Position = pos;
                debugEntity.Transform.Rotation = rot;
            }

            return debugEntity;
        }
Example #4
0
 internal void RemoveCollider(PhysicsComponent component)
 {
     collisionWorld.RemoveCollisionObject(component.NativeCollisionObject);
 }
Example #5
0
 internal void AddCollider(PhysicsComponent component, CollisionFilterGroupFlags group, CollisionFilterGroupFlags mask)
 {
     collisionWorld.AddCollisionObject(component.NativeCollisionObject, (BulletSharp.CollisionFilterGroups)group, (BulletSharp.CollisionFilterGroups)mask);
 }
Example #6
0
 internal bool InternalEquals(PhysicsComponent a, PhysicsComponent b)
 {
     return (ColliderA == a && ColliderB == b) || (ColliderB == a && ColliderA == b);
 }
        private Entity CreateChildEntity(PhysicsComponent component, ColliderShape shape, bool addOffset = false)
        {
            if (shape  == null)
                return null;

            switch (shape.Type)
            {
                case ColliderShapeTypes.StaticPlane:
                    {
                        //Hmm TODO maybe can draw an infinite plane??
                        return null;
                    }
                case ColliderShapeTypes.Compound:
                    {
                        var entity = new Entity();

                        //We got to recurse
                        var compound = (CompoundColliderShape)shape;
                        for (var i = 0; i < compound.Count; i++)
                        {
                            var subShape = compound[i];
                            var subEntity = CreateChildEntity(component, subShape, true);

                            subEntity.Transform.UseTRS = false;
                            entity.AddChild(subEntity);
                        }

                        entity.Transform.LocalMatrix = Matrix.Identity;
                        entity.Transform.UseTRS = false;

                        return entity;
                    }
                default:
                    {
                        var mat = triggerMaterial;

                        if (component is RigidbodyComponent)
                        {
                            mat = ((RigidbodyComponent)component).IsKinematic ? kinematicMaterial : dynamicMaterial;

                        }
                        else if (component is CharacterComponent)
                        {
                            mat = characterMaterial;
                        }
                        else if (component is StaticColliderComponent)
                        {
                            mat = staticMaterial;
                        }

                        var entity = new Entity
                        {
                            new ModelComponent
                            {
                                Model = new Model
                                {
                                    mat,
                                    new Mesh
                                    {
                                        Draw = shape.CreateDebugPrimitive(graphicsDevice)
                                    }
                                }
                            }
                        };

                        var offset = addOffset ? Matrix.RotationQuaternion(shape.LocalRotation)*Matrix.Translation(shape.LocalOffset) : Matrix.Identity;

                        if (shape.Type == ColliderShapeTypes.ConvexHull)
                        {
                            var hullDesc = (ConvexHullColliderShape)shape;

                            entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * Matrix.Scaling(hullDesc.Scaling) * offset;
                        }
                        else
                        {
                            entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * offset;
                        }
                        entity.Transform.UseTRS = false;

                        return entity;
                    }
            }
        }
        private Entity CreateChildEntity(PhysicsComponent component, ColliderShape shape, bool addOffset)
        {
            if (shape == null)
                return null;

            switch (shape.Type)
            {
                case ColliderShapeTypes.Compound:
                    {
                        var entity = new Entity();

                        //We got to recurse
                        var compound = (CompoundColliderShape)shape;
                        for (var i = 0; i < compound.Count; i++)
                        {
                            var subShape = compound[i];
                            var subEntity = CreateChildEntity(component, subShape, true); //always add offsets to compounds
                            if (subEntity != null)
                            {
                                entity.AddChild(subEntity);
                            }
                        }

                        entity.Transform.LocalMatrix = Matrix.Identity;
                        entity.Transform.UseTRS = false;

                        compound.DebugEntity = entity;

                        return entity;
                    }
                case ColliderShapeTypes.Box:
                case ColliderShapeTypes.Capsule:
                case ColliderShapeTypes.ConvexHull:
                case ColliderShapeTypes.Cylinder:
                case ColliderShapeTypes.Sphere:
                case ColliderShapeTypes.Cone:
                    {
                        var mat = triggerMaterial;

                        var rigidbodyComponent = component as RigidbodyComponent;
                        if (rigidbodyComponent != null)
                        {
                            mat = rigidbodyComponent.IsKinematic ? kinematicMaterial : dynamicMaterial;
                            mat = rigidbodyComponent.IsTrigger ? triggerMaterial : mat;
                        }
                        else if (component is CharacterComponent)
                        {
                            mat = characterMaterial;
                        }
                        else if (component is StaticColliderComponent)
                        {
                            var staticCollider = (StaticColliderComponent)component;
                            mat = staticCollider.IsTrigger ? triggerMaterial : staticMaterial;
                        }

                        MeshDraw draw;
                        var type = shape.GetType();
                        if (type == typeof(CapsuleColliderShape) || type == typeof(ConvexHullColliderShape))
                        {
                            if (!debugMeshCache2.TryGetValue(shape, out draw))
                            {
                                draw = shape.CreateDebugPrimitive(graphicsDevice);
                                debugMeshCache2[shape] = draw;
                            }
                        }
                        else
                        {
                            if (!debugMeshCache.TryGetValue(shape.GetType(), out draw))
                            {
                                draw = shape.CreateDebugPrimitive(graphicsDevice);
                                debugMeshCache[shape.GetType()] = draw;
                            }
                        }

                        var entity = new Entity
                        {
                            new ModelComponent
                            {
                                Model = new Model
                                {
                                    mat,
                                    new Mesh
                                    {
                                        Draw = draw
                                    }
                                }
                            }
                        };

                        var offset = addOffset ? Matrix.RotationQuaternion(shape.LocalRotation) * Matrix.Translation(shape.LocalOffset) : Matrix.Identity;

                        entity.Transform.LocalMatrix = shape.DebugPrimitiveMatrix * offset * Matrix.Scaling(shape.Scaling);

                        entity.Transform.UseTRS = false;

                        shape.DebugEntity = entity;

                        return entity;
                    }
                default:
                    return null;
            }
        }
Example #9
0
        unsafe internal void ContactTest(PhysicsComponent component)
        {
            foreach (var collision in component.Collisions)
            {
                skippedCollisions.Add(collision);
            }

            IntPtr buffer;
            int bufferSize;
            collisionWorld.GetCollisions(component.NativeCollisionObject, out buffer, out bufferSize);

            var contacts = (ContactData*) buffer;
            for (var i = 0; i < bufferSize; i++)
            {
                var contact = contacts[i];
                var obj0 = BulletSharp.CollisionObject.GetManaged((IntPtr)contact.ColliderA);
                var obj1 = BulletSharp.CollisionObject.GetManaged((IntPtr)contact.ColliderB);
                var component0 = (PhysicsComponent)obj0.UserObject;
                var component1 = (PhysicsComponent)obj1.UserObject;

                if (((int)component0.CanCollideWith & (int)component1.CollisionGroup) != 0 || ((int)component1.CanCollideWith & (int)component0.CollisionGroup) != 0)
                {
                    var skip = false;
                    foreach (var collision in component0.Collisions)
                    {
                        if ((collision.ColliderA == component0 && collision.ColliderB == component1) || (collision.ColliderA == component1 && collision.ColliderB == component0))
                        {
                            var oldContact = collision.Contacts[0];
                            oldContact.Distance = contact.Distance;
                            oldContact.Normal = new Vector3(contact.NormalX, contact.NormalY, contact.NormalZ);
                            oldContact.PositionOnA = new Vector3(contact.PositionOnAx, contact.PositionOnAy, contact.PositionOnAz);
                            oldContact.PositionOnB = new Vector3(contact.PositionOnBx, contact.PositionOnBy, contact.PositionOnBz);
                            updatedContactsCache.Add(oldContact);

                            skippedCollisions.Remove(collision);
                            skip = true;
                            break;
                        }
                    }

                    if (skip)
                    {
                        continue;
                    }

                    var newCollision = new Collision
                    {
                        Contacts = new TrackingCollection<ContactPoint>(),
                        ColliderA = component0,
                        ColliderB = component1
                    };

                    //todo this has to change
                    var newContact = new ContactPoint
                    {
                        Collision = newCollision,
                        Distance = contact.Distance,
                        LifeTime = 0,
                        Normal = new Vector3(contact.NormalX, contact.NormalY, contact.NormalZ),
                        PositionOnA = new Vector3(contact.PositionOnAx, contact.PositionOnAy, contact.PositionOnAz),
                        PositionOnB = new Vector3(contact.PositionOnBx, contact.PositionOnBy, contact.PositionOnBz)
                    };
                    newCollision.Contacts.Add(newContact);

                    component0.Collisions.Add(newCollision);
                    component1.Collisions.Add(newCollision);

                    newCollisionsCache.Add(newCollision);

                    newContactsFastCache.Add(newContact);

                    newCollisions.Add(newCollision);
                }
            }
        }
Example #10
0
        internal void CleanContacts(PhysicsComponent component)
        {
            previousToRemove.Clear(true);

            foreach (var previousFrameContact in previousFrameContacts)
            {
                var obj0 = BulletSharp.CollisionObject.GetManaged(previousFrameContact.ColliderA);
                var obj1 = BulletSharp.CollisionObject.GetManaged(previousFrameContact.ColliderB);
                var component0 = (PhysicsComponent)obj0.UserObject;
                var component1 = (PhysicsComponent)obj1.UserObject;
                if (component == component0 || component == component1)
                {
                    previousToRemove.Add(previousFrameContact);
                    ContactRemoval(previousFrameContact, component0, component1);
                }
            }

            foreach (var contactPoint in previousToRemove)
            {
                previousFrameContacts.Remove(contactPoint);
            }
        }
Example #11
0
 internal unsafe void ContactTest(PhysicsComponent component)
 {
     IntPtr buffer;
     int bufferSize;
     collisionWorld.GetCollisions(component.NativeCollisionObject, out buffer, out bufferSize);
     var contacts = (ContactPoint*) buffer;
     for (var i = 0; i < bufferSize; i++)
     {
         var contact = contacts[i];
         currentFrameContacts.Add(contact);
     }
 }
Example #12
0
        private void ContactRemoval(ContactPoint contact, PhysicsComponent component0, PhysicsComponent component1)
        {
            Collision existingPair = null;
            foreach (var x in component0.Collisions)
            {
                if (x.InternalEquals(component0, component1))
                {
                    existingPair = x;
                    break;
                }
            }
            if (existingPair == null)
            {
#if DEBUG
                //should not happen?
                throw new Exception("Pair not present.");
#else
                return;
#endif
            }

            if (existingPair.Contacts.Contains(contact))
            {
                existingPair.Contacts.Remove(contact);
                removedContactsCache.Add(contact);

                contactToCollision.Remove(contact);

                if (existingPair.Contacts.Count == 0)
                {
                    component0.Collisions.Remove(existingPair);
                    component1.Collisions.Remove(existingPair);
                    removedCollisionsCache.Add(existingPair);
                }
            }
            else
            {
#if DEBUG
                //should not happen?
                throw new Exception("Contact not in pair.");
#endif
            }
        }