Exemple #1
0
        //This is called by the physics engine to update the transformation of Dynamic rigidbodies.
        private static void RigidBodySetWorldTransform(PhysicsElementBase element, ref Matrix physicsTransform)
        {
            element.Data.PhysicsComponent.Simulation.SimulationProfiler.Mark();
            element.Data.PhysicsComponent.Simulation.UpdatedRigidbodies++;

            if (element.BoneIndex == -1)
            {
                element.UpdateTransformationComponent(ref physicsTransform);
            }
            else
            {
                element.UpdateBoneTransformation(ref physicsTransform);
            }

            if (element.DebugEntity == null)
            {
                return;
            }

            Vector3    scale, pos;
            Quaternion rot;

            physicsTransform.Decompose(out scale, out rot, out pos);
            element.DebugEntity.Transform.Position = pos;
            element.DebugEntity.Transform.Rotation = rot;
        }
Exemple #2
0
        public Entity CreateDebugEntity(PhysicsElementBase physicsElement)
        {
            if (physicsElement?.ColliderShape == null)
            {
                return(null);
            }

            if (physicsElement.DebugEntity != null)
            {
                return(null);
            }

            var debugEntity = new Entity();

            var colliderEntity = CreateChildEntity(physicsElement.ColliderShape, physicsElement.Type, true);

            if (colliderEntity == null)
            {
                return(null);
            }

            debugEntity.AddChild(colliderEntity);

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

            var skinnedElement = physicsElement as PhysicsSkinnedElementBase;

            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;
                physicsElement.Data.TransformComponent.WorldMatrix.Decompose(out scale, out rot, out pos);
                debugEntity.Transform.Position = pos;
                debugEntity.Transform.Rotation = rot;
            }

            return(debugEntity);
        }
        public Entity CreateDebugEntity(PhysicsElementBase physicsElement)
        {
            if (physicsElement?.ColliderShape == null) return null;

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

            var debugEntity = new Entity();

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

            debugEntity.AddChild(colliderEntity);

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

            var skinnedElement = physicsElement as PhysicsSkinnedElementBase;
            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;
                physicsElement.Data.TransformComponent.WorldMatrix.Decompose(out scale, out rot, out pos);
                debugEntity.Transform.Position = pos;
                debugEntity.Transform.Rotation = rot;
            }

            return debugEntity;
        }
Exemple #4
0
        private void DeleteElement(PhysicsElementBase element)
        {
            element.Data = null;

            //might be possible that this element was not valid during creation so it would be already null
            if (element.InternalCollider == null)
            {
                return;
            }

            var toDispose = new List <IDisposable>();

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

            switch (element.Type)
            {
            case PhysicsElementBase.Types.PhantomCollider:
            case PhysicsElementBase.Types.StaticCollider:
            {
                simulation.RemoveCollider(element.Collider);
            }
            break;

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

                simulation.RemoveRigidBody(rb);
            }
            break;

            case PhysicsElementBase.Types.CharacterController:
            {
                characters.Remove(element);
                simulation.RemoveCharacter((Character)element.Collider);
            }
            break;
            }

            toDispose.Add(element.Collider);
            if (element.ColliderShape != null && !element.ColliderShape.IsPartOfAsset)
            {
                toDispose.Add(element.ColliderShape);
            }
            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();
                }
            }
        }
Exemple #5
0
        private void NewElement(PhysicsElementBase element, AssociatedData data, Entity entity)
        {
            element.Data = data;

            if (element.ColliderShapes.Count == 0)
            {
                return;                                    //no shape no purpose
            }
            if (element.ColliderShape == null)
            {
                element.ComposeShape();
            }
            var shape = element.ColliderShape;

            if (shape == null)
            {
                return;                //no shape no purpose
            }
            element.BoneIndex = -1;

            var skinnedElement = element as PhysicsSkinnedElementBase;

            if (skinnedElement != null && !skinnedElement.NodeName.IsNullOrEmpty() && data.ModelComponent?.Skeleton != null)
            {
                if (!data.BoneMatricesUpdated)
                {
                    Vector3    position, scaling;
                    Quaternion rotation;
                    entity.Transform.WorldMatrix.Decompose(out scaling, out rotation, out position);
                    var isScalingNegative = scaling.X * scaling.Y * scaling.Z < 0.0f;
                    data.ModelComponent.Skeleton.NodeTransformations[0].LocalMatrix       = entity.Transform.WorldMatrix;
                    data.ModelComponent.Skeleton.NodeTransformations[0].IsScalingNegative = isScalingNegative;
                    data.ModelComponent.Skeleton.UpdateMatrices();
                    data.BoneMatricesUpdated = true;
                }

                skinnedElement.BoneIndex = data.ModelComponent.Skeleton.Nodes.IndexOf(x => x.Name == skinnedElement.NodeName);

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

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

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

            switch (element.Type)
            {
            case PhysicsElementBase.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, CollisionFilterGroupFlags.DefaultFilter, CollisionFilterGroupFlags.AllFilter);
                }
                else
                {
                    simulation.AddCollider(c, (CollisionFilterGroupFlags)element.CollisionGroup, element.CanCollideWith);
                }
            }
            break;

            case PhysicsElementBase.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

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

            case PhysicsElementBase.Types.StaticRigidBody:
            {
                var rb = simulation.CreateRigidBody(shape);

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

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

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

            case PhysicsElementBase.Types.DynamicRigidBody:
            {
                var rb = simulation.CreateRigidBody(shape);

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

                rb.Type = RigidBodyTypes.Dynamic;
                if (rb.Mass == 0.0f)
                {
                    rb.Mass = 1.0f;
                }

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

            case PhysicsElementBase.Types.KinematicRigidBody:
            {
                var rb = simulation.CreateRigidBody(shape);

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

                rb.Type = RigidBodyTypes.Kinematic;
                if (rb.Mass == 0.0f)
                {
                    rb.Mass = 1.0f;
                }

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

            case PhysicsElementBase.Types.CharacterController:
            {
                var charElem = (CharacterElement)element;
                var ch       = simulation.CreateCharacter(shape, charElem.StepHeight);

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

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

                characters.Add(element);
            }
            break;
            }

            if (colliderShapesRendering)
            {
                element.AddDebugEntity(sceneSystem.SceneInstance.Scene);
            }

            elements.Add(element);
            if (element.BoneIndex != -1)
            {
                boneElements.Add(skinnedElement);
            }
        }
        private Entity CreateChildEntity(ColliderShape shape, PhysicsElementBase.Types type, 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(subShape, type, true);

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

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

                        return entity;
                    }
                default:
                    {
                        Material mat;
                        switch (type)
                        {
                            case PhysicsElementBase.Types.PhantomCollider:
                                mat = triggerMaterial;
                                break;

                            case PhysicsElementBase.Types.StaticCollider:
                            case PhysicsElementBase.Types.StaticRigidBody:
                                mat = staticMaterial;
                                break;

                            case PhysicsElementBase.Types.DynamicRigidBody:
                                mat = dynamicMaterial;
                                break;

                            case PhysicsElementBase.Types.KinematicRigidBody:
                                mat = kinematicMaterial;
                                break;

                            case PhysicsElementBase.Types.CharacterController:
                                mat = characterMaterial;
                                break;

                            default:
                                throw new ArgumentOutOfRangeException("type", type, null);
                        }

                        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;
                    }
            }
        }