Example #1
0
 //This is valid for Dynamic rigidbodies (called once at initialization)
 //and Kinematic rigidbodies, called every simulation tick (if body not sleeping) to let the physics engine know where the kinematic body is.
 private static void RigidBodyGetWorldTransform(PhysicsElement element, out Matrix physicsTransform)
 {
     if (element.BoneIndex == -1)
     {
         element.DerivePhysicsTransformation(out physicsTransform);
     }
     else
     {
         element.DeriveBonePhysicsTransformation(out physicsTransform);
     }
 }
Example #2
0
 //This is called by the physics engine to update the transformation of Dynamic rigidbodies.
 private static void RigidBodySetWorldTransform(PhysicsElement element, Matrix physicsTransform)
 {
     if (element.BoneIndex == -1)
     {
         element.UpdateTransformationComponent(physicsTransform);
     }
     else
     {
         element.UpdateBoneTransformation(physicsTransform);
     }
 }
Example #3
0
        void NewElement(PhysicsElement element, AssociatedData data, Entity entity)
        {
            if (element.Shape == null)
            {
                return;                        //no shape no purpose
            }
            var shape = element.Shape.Shape;

            element.Data      = data;
            element.BoneIndex = -1;

            if (!element.Sprite && element.LinkedBoneName != null && data.ModelComponent != null)
            {
                //find the linked bone, if can't be found we just skip this element
                for (var index = 0; index < data.ModelComponent.ModelViewHierarchy.Nodes.Length; index++)
                {
                    var node = data.ModelComponent.ModelViewHierarchy.Nodes[index];
                    if (node.Name != element.LinkedBoneName)
                    {
                        continue;
                    }
                    element.BoneIndex = index;
                    break;
                }

                if (element.BoneIndex == -1)
                {
                    throw new Exception("The specified LinkedBoneName doesn't exist in the model hierarchy.");
                }
            }

            //complex hierarchy models not implemented yet
            if (element.BoneIndex != -1)
            {
                throw new NotImplementedException("Physics on complex hierarchy model's bones is not implemented yet.");
            }

            var defaultGroups = element.CanCollideWith == 0 || element.CollisionGroup == 0;

            switch (element.Type)
            {
            case PhysicsElement.Types.PhantomCollider:
            {
                var c = physicsSystem.PhysicsEngine.CreateCollider(shape);

                element.Collider = c;                   //required by the next call
                element.Collider.EntityObject = entity; //required by the next call
                element.UpdatePhysicsTransformation();  //this will set position and rotation of the collider

                c.IsTrigger = true;

                if (defaultGroups)
                {
                    physicsSystem.PhysicsEngine.AddCollider(c);
                }
                else
                {
                    physicsSystem.PhysicsEngine.AddCollider(c, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElement.Types.StaticCollider:
            {
                var c = physicsSystem.PhysicsEngine.CreateCollider(shape);

                element.Collider = c;                   //required by the next call
                element.Collider.EntityObject = entity; //required by the next call
                element.UpdatePhysicsTransformation();  //this will set position and rotation of the collider

                c.IsTrigger = false;

                if (defaultGroups)
                {
                    physicsSystem.PhysicsEngine.AddCollider(c);
                }
                else
                {
                    physicsSystem.PhysicsEngine.AddCollider(c, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElement.Types.StaticRigidBody:
            {
                var rb = physicsSystem.PhysicsEngine.CreateRigidBody(shape);

                rb.EntityObject = entity;
                rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform);
                rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform);
                element.Collider             = rb;
                element.UpdatePhysicsTransformation();         //this will set position and rotation of the collider

                rb.Type = RigidBodyTypes.Static;

                if (defaultGroups)
                {
                    physicsSystem.PhysicsEngine.AddRigidBody(rb);
                }
                else
                {
                    physicsSystem.PhysicsEngine.AddRigidBody(rb, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElement.Types.DynamicRigidBody:
            {
                var rb = physicsSystem.PhysicsEngine.CreateRigidBody(shape);

                rb.EntityObject = entity;
                rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform);
                rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform);
                element.Collider             = rb;
                element.UpdatePhysicsTransformation();         //this will set position and rotation of the collider

                rb.Type = RigidBodyTypes.Dynamic;
                rb.Mass = 1.0f;

                if (defaultGroups)
                {
                    physicsSystem.PhysicsEngine.AddRigidBody(rb);
                }
                else
                {
                    physicsSystem.PhysicsEngine.AddRigidBody(rb, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElement.Types.KinematicRigidBody:
            {
                var rb = physicsSystem.PhysicsEngine.CreateRigidBody(shape);

                rb.EntityObject = entity;
                rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform);
                rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform);
                element.Collider             = rb;
                element.UpdatePhysicsTransformation();         //this will set position and rotation of the collider

                rb.Type = RigidBodyTypes.Kinematic;
                rb.Mass = 0.0f;

                if (defaultGroups)
                {
                    physicsSystem.PhysicsEngine.AddRigidBody(rb);
                }
                else
                {
                    physicsSystem.PhysicsEngine.AddRigidBody(rb, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElement.Types.CharacterController:
            {
                var ch = physicsSystem.PhysicsEngine.CreateCharacter(shape, element.StepHeight);

                element.Collider = ch;
                element.Collider.EntityObject = entity;
                element.UpdatePhysicsTransformation();         //this will set position and rotation of the collider

                if (defaultGroups)
                {
                    physicsSystem.PhysicsEngine.AddCharacter(ch);
                }
                else
                {
                    physicsSystem.PhysicsEngine.AddCharacter(ch, (CollisionFilterGroups)element.CollisionGroup, element.CanCollideWith);
                }

                characters.Add(element);
            }
            break;
            }

            elements.Add(element);
        }
Example #4
0
 //This is valid for Dynamic rigidbodies (called once at initialization)
 //and Kinematic rigidbodies (called every simulation tick (if body not sleeping) to let the physics engine know where the kinematic body is)
 static void RigidBodyGetWorldTransform(PhysicsElement element, out Matrix physicsTransform)
 {
     physicsTransform = element.DerivePhysicsTransformation();
 }
Example #5
0
 //This is called by the physics engine to update the transformation of Dynamic rigidbodies
 static void RigidBodySetWorldTransform(PhysicsElement element, Matrix physicsTransform)
 {
     element.UpdateTransformationComponent(physicsTransform);
 }
Example #6
0
        private void DrawDebugCompound(ref Matrix viewProj, CompoundColliderShape compound, PhysicsElement element)
        {
            for (var i = 0; i < compound.Count; i++)
            {
                var subShape = compound[i];
                switch (subShape.Type)
                {
                case ColliderShapeTypes.StaticPlane:
                    continue;

                case ColliderShapeTypes.Compound:
                    DrawDebugCompound(ref viewProj, (CompoundColliderShape)compound[i], element);
                    break;

                default:
                {
                    var physTrans = element.BoneIndex == -1 ? element.Collider.PhysicsWorldTransform : element.BoneWorldMatrix;
                    physTrans = Matrix.Multiply(subShape.PositiveCenterMatrix, physTrans);

                    //must account collider shape scaling
                    Matrix worldTrans;
                    Matrix.Multiply(ref subShape.DebugPrimitiveScaling, ref physTrans, out worldTrans);

                    physicsSystem.PhysicsEngine.DebugEffect.WorldViewProj = worldTrans * viewProj;
                    physicsSystem.PhysicsEngine.DebugEffect.Color         = element.Collider.IsActive ? Color.Green : Color.Red;
                    physicsSystem.PhysicsEngine.DebugEffect.UseUv         = subShape.Type != ColliderShapeTypes.ConvexHull;

                    physicsSystem.PhysicsEngine.DebugEffect.Apply();

                    subShape.DebugPrimitive.Draw();
                }
                break;
                }
            }
        }
Example #7
0
        void DeleteElement(PhysicsElement element, bool now = false)
        {
            //might be possible that this element was not valid during creation so it would be already null
            if (element.Collider == null)
            {
                return;
            }

            var toDispose = new List <IDisposable>();

            elements.Remove(element);

            switch (element.Type)
            {
            case PhysicsElement.Types.PhantomCollider:
            case PhysicsElement.Types.StaticCollider:
            {
                physicsSystem.PhysicsEngine.RemoveCollider(element.Collider);
            }
            break;

            case PhysicsElement.Types.StaticRigidBody:
            case PhysicsElement.Types.DynamicRigidBody:
            case PhysicsElement.Types.KinematicRigidBody:
            {
                var rb          = (RigidBody)element.Collider;
                var constraints = rb.LinkedConstraints.ToArray();
                foreach (var c in constraints)
                {
                    physicsSystem.PhysicsEngine.RemoveConstraint(c);
                    toDispose.Add(c);
                }

                physicsSystem.PhysicsEngine.RemoveRigidBody(rb);
            }
            break;

            case PhysicsElement.Types.CharacterController:
            {
                characters.Remove(element);
                physicsSystem.PhysicsEngine.RemoveCharacter((Character)element.Collider);
            }
            break;
            }

            toDispose.Add(element.Collider);
            element.Collider = null;

            //dispose in another thread for better performance
            if (!now)
            {
                TaskList.Dispatch(toDispose, 4, 128, (i, disposable) => disposable.Dispose());
            }
            else
            {
                foreach (var d in toDispose)
                {
                    d.Dispose();
                }
            }
        }
Example #8
0
        private void NewElement(PhysicsElement element, AssociatedData data, Entity entity)
        {
            if (element.Shape == null || element.Shape.Descriptions == null || element.Shape.Shape == null)
            {
                return;                                                                                             //no shape no purpose
            }
            var shape = element.Shape.Shape;

            element.Data      = data;
            element.BoneIndex = -1;

            if (!element.LinkedBoneName.IsNullOrEmpty())
            {
                element.BoneIndex = data.ModelComponent.ModelViewHierarchy.Nodes.IndexOf(x => x.Name == element.LinkedBoneName);

                if (element.BoneIndex == -1)
                {
                    throw new Exception("The specified LinkedBoneName doesn't exist in the model hierarchy.");
                }

                element.BoneWorldMatrixOut = element.BoneWorldMatrix = data.ModelComponent.ModelViewHierarchy.NodeTransformations[element.BoneIndex].WorldMatrix;
            }

            var defaultGroups = element.CanCollideWith == 0 || element.CollisionGroup == 0;

            switch (element.Type)
            {
            case PhysicsElement.Types.PhantomCollider:
            {
                var c = Simulation.CreateCollider(shape);

                element.Collider        = c;           //required by the next call
                element.Collider.Entity = entity;      //required by the next call
                element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider

                c.IsTrigger = true;

                if (defaultGroups)
                {
                    simulation.AddCollider(c);
                }
                else
                {
                    simulation.AddCollider(c, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElement.Types.StaticCollider:
            {
                var c = Simulation.CreateCollider(shape);

                element.Collider        = c;           //required by the next call
                element.Collider.Entity = entity;      //required by the next call
                element.UpdatePhysicsTransformation(); //this will set position and rotation of the collider

                c.IsTrigger = false;

                if (defaultGroups)
                {
                    simulation.AddCollider(c);
                }
                else
                {
                    simulation.AddCollider(c, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElement.Types.StaticRigidBody:
            {
                var rb = Simulation.CreateRigidBody(shape);

                rb.Entity = entity;
                rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform);
                rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform);
                element.Collider             = rb;
                element.UpdatePhysicsTransformation();         //this will set position and rotation of the collider

                rb.Type = RigidBodyTypes.Static;

                if (defaultGroups)
                {
                    simulation.AddRigidBody(rb);
                }
                else
                {
                    simulation.AddRigidBody(rb, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElement.Types.DynamicRigidBody:
            {
                var rb = Simulation.CreateRigidBody(shape);

                rb.Entity = entity;
                rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform);
                rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform);
                element.Collider             = rb;
                element.UpdatePhysicsTransformation();         //this will set position and rotation of the collider

                rb.Type = RigidBodyTypes.Dynamic;
                rb.Mass = 1.0f;

                if (defaultGroups)
                {
                    simulation.AddRigidBody(rb);
                }
                else
                {
                    simulation.AddRigidBody(rb, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElement.Types.KinematicRigidBody:
            {
                var rb = Simulation.CreateRigidBody(shape);

                rb.Entity = entity;
                rb.GetWorldTransformCallback = (out Matrix transform) => RigidBodyGetWorldTransform(element, out transform);
                rb.SetWorldTransformCallback = transform => RigidBodySetWorldTransform(element, transform);
                element.Collider             = rb;
                element.UpdatePhysicsTransformation();         //this will set position and rotation of the collider

                rb.Type = RigidBodyTypes.Kinematic;
                rb.Mass = 0.0f;

                if (defaultGroups)
                {
                    simulation.AddRigidBody(rb);
                }
                else
                {
                    simulation.AddRigidBody(rb, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElement.Types.CharacterController:
            {
                var ch = Simulation.CreateCharacter(shape, element.StepHeight);

                element.Collider        = ch;
                element.Collider.Entity = entity;
                element.UpdatePhysicsTransformation();         //this will set position and rotation of the collider

                if (defaultGroups)
                {
                    simulation.AddCharacter(ch);
                }
                else
                {
                    simulation.AddCharacter(ch, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith);
                }

                characters.Add(element);
            }
            break;
            }

            elements.Add(element);
            if (element.BoneIndex != -1)
            {
                boneElements.Add(element);
            }
        }