Пример #1
0
        public void Weld(MyPhysicsBody other, bool recreateShape = true)
        {
            if (other.WeldInfo.Parent == this) //already welded to this
            {
                return;
            }

            if (other.IsWelded && !IsWelded)
            {
                other.Weld(this);
                return;
            }

            if (IsWelded)
            {
                WeldInfo.Parent.Weld(other);
                return;
            }
            if (other.WeldInfo.Children.Count > 0)
            {
                Debug.Fail("Welding other welded gorup");
                other.UnweldAll(false); //they should end in same group and get welded
            }
            ProfilerShort.Begin("Weld");
            HkShape thisShape;
            bool    firstWelded = WeldInfo.Children.Count == 0;

            if (firstWelded)
            {
                //RemoveConstraints(RigidBody);
                WeldedRigidBody = RigidBody;
                thisShape       = RigidBody.GetShape();
                if (HavokWorld != null)
                {
                    HavokWorld.RemoveRigidBody(WeldedRigidBody);
                }
                RigidBody = HkRigidBody.Clone(WeldedRigidBody);
                if (HavokWorld != null)
                {
                    HavokWorld.AddRigidBody(RigidBody);
                }
                HkShape.SetUserData(thisShape, RigidBody);
                Entity.OnPhysicsChanged += WeldedEntity_OnPhysicsChanged;
                WeldInfo.UpdateMassProps(RigidBody);
                //Entity.OnClose += Entity_OnClose;
            }
            else
            {
                thisShape = GetShape();
            }

            other.Deactivate();

            var transform = other.Entity.WorldMatrix * Entity.WorldMatrixInvScaled;

            other.WeldInfo.Transform = transform;
            other.WeldInfo.UpdateMassProps(other.RigidBody);
            Debug.Assert(other.WeldedRigidBody == null);
            other.WeldedRigidBody = other.RigidBody;
            other.RigidBody       = RigidBody;
            other.WeldInfo.Parent = this;
            other.ClusterObjectID = ClusterObjectID;
            WeldInfo.Children.Add(other);

            //if(recreateShape)
            //    RecreateWeldedShape(thisShape);

            ProfilerShort.BeginNextBlock("OnPhysicsChanged");
            //(other.Entity as MyEntity).RaisePhysicsChanged();
            //other.Entity.OnPhysicsChanged += WeldedEntity_OnPhysicsChanged;
            //Debug.Assert(other.m_constraints.Count == 0, "Constraints left in welded body");
            ProfilerShort.BeginNextBlock("RemoveConstraints");
            ProfilerShort.End();
            OnWelded(other);
            other.OnWelded(this);
        }
        public void SwitchToRagdollMode(bool deadMode = true, int firstRagdollSubID = 1)
        {
            Debug.Assert(Enabled, "Trying to switch to ragdoll mode, but Physics are not enabled");

            if (MyFakes.ENABLE_RAGDOLL_DEBUG)
            {
                Debug.WriteLine("MyPhysicsBody.SwitchToRagdollMode");
                MyLog.Default.WriteLine("MyPhysicsBody.SwitchToRagdollMode");
            }

            if (HavokWorld == null || !Enabled)
            {
                SwitchToRagdollModeOnActivate = true;
                m_ragdollDeadMode             = deadMode;
                return;
            }

            if (IsRagdollModeActive)
            {
                Debug.Fail("Ragdoll mode is already active!");
                return;
            }

            Matrix havokMatrix = Entity.WorldMatrix;

            havokMatrix.Translation = WorldToCluster(havokMatrix.Translation);
            Debug.Assert(havokMatrix.IsValid() && havokMatrix != Matrix.Zero, "Invalid world matrix!");

            if (RagdollSystemGroupCollisionFilterID == 0)
            {
                RagdollSystemGroupCollisionFilterID = m_world.GetCollisionFilter().GetNewSystemGroup();
            }

            Ragdoll.SetToKeyframed();   // this will disable the bodies to get the impulse when repositioned

            Ragdoll.GenerateRigidBodiesCollisionFilters(deadMode ? MyPhysics.CollisionLayers.CharacterCollisionLayer : MyPhysics.CollisionLayers.RagdollCollisionLayer, RagdollSystemGroupCollisionFilterID, firstRagdollSubID);

            Ragdoll.ResetToRigPose();

            Ragdoll.SetWorldMatrix(havokMatrix);

            if (deadMode)
            {
                Ragdoll.SetToDynamic();
            }

            if (deadMode)
            {
                foreach (HkRigidBody body in Ragdoll.RigidBodies)
                {
                    // set the velocities for the bodies
                    body.AngularVelocity = AngularVelocity;
                    body.LinearVelocity  = LinearVelocity;
                }
            }
            else
            {
                Ragdoll.ResetVelocities();
            }

            if (CharacterProxy != null && deadMode)
            {
                CharacterProxy.Deactivate(HavokWorld);
                CharacterProxy.Dispose();
                CharacterProxy = null;
            }

            if (RigidBody != null && deadMode)
            {
                RigidBody.Deactivate();
                HavokWorld.RemoveRigidBody(RigidBody);
                RigidBody.Dispose();
                RigidBody = null;
            }

            if (RigidBody2 != null && deadMode)
            {
                RigidBody2.Deactivate();
                HavokWorld.RemoveRigidBody(RigidBody2);
                RigidBody2.Dispose();
                RigidBody2 = null;
            }

            foreach (var body in Ragdoll.RigidBodies)
            {
                body.UserObject = deadMode ? this : null;

                // TODO: THIS SHOULD BE SET IN THE RAGDOLL MODEL AND NOT DEFINING IT FOR EVERY MODEL HERE
                body.Motion.SetDeactivationClass(deadMode ? HkSolverDeactivation.High : HkSolverDeactivation.Medium);// - TODO: Find another way - this is deprecated by Havok
            }

            Ragdoll.OptimizeInertiasOfConstraintTree();

            if (!Ragdoll.InWorld)
            {
                //Ragdoll.RecreateConstraints();
                HavokWorld.AddRagdoll(Ragdoll);
            }

            Ragdoll.EnableConstraints();
            Ragdoll.Activate();
            m_ragdollDeadMode = deadMode;

            if (MyFakes.ENABLE_RAGDOLL_DEBUG)
            {
                Debug.WriteLine("MyPhysicsBody.SwitchToRagdollMode - FINISHED");
                MyLog.Default.WriteLine("MyPhysicsBody.SwitchToRagdollMode - FINISHED");
            }
        }
Пример #3
0
        public void Unweld(MyPhysicsBody other, bool insertToWorld = true, bool recreateShape = true)
        {
            Debug.Assert(other.IsWelded && RigidBody != null && other.WeldedRigidBody != null, "Invalid welding state!");

            if (IsWelded)
            {
                WeldInfo.Parent.Unweld(other, insertToWorld, recreateShape);
                Debug.Assert(other.IsWelded);
                return;
            }

            if (other.IsInWorld || RigidBody == null || other.WeldedRigidBody == null)
            {
                WeldInfo.Children.Remove(other);
                return;
            }
            var rbWorldMatrix = RigidBody.GetRigidBodyMatrix();

            //other.Entity.OnPhysicsChanged -= WeldedEntity_OnPhysicsChanged;

            other.WeldInfo.Parent = null;
            Debug.Assert(WeldInfo.Children.Contains(other));
            WeldInfo.Children.Remove(other);

            var body = other.RigidBody;

            Debug.Assert(body == RigidBody);
            other.RigidBody       = other.WeldedRigidBody;
            other.WeldedRigidBody = null;
            if (!other.RigidBody.IsDisposed)
            {
                other.RigidBody.SetWorldMatrix(other.WeldInfo.Transform * rbWorldMatrix);
                other.RigidBody.LinearVelocity      = body.LinearVelocity;
                other.WeldInfo.MassElement.Tranform = Matrix.Identity;
                other.WeldInfo.Transform            = Matrix.Identity;
            }
            else
            {
                Debug.Fail("Disposed welded body");
            }
            //RemoveConstraints(other.RigidBody);

            other.ClusterObjectID = MyHavokCluster.CLUSTERED_OBJECT_ID_UNITIALIZED;
            if (insertToWorld)
            {
                other.Activate();
                other.OnMotion(other.RigidBody, 0);
            }

            if (WeldInfo.Children.Count == 0)
            {
                recreateShape                   = false;
                Entity.OnPhysicsChanged        -= WeldedEntity_OnPhysicsChanged;
                Entity.OnClose                 -= Entity_OnClose;
                WeldedRigidBody.LinearVelocity  = RigidBody.LinearVelocity;
                WeldedRigidBody.AngularVelocity = RigidBody.AngularVelocity;
                if (HavokWorld != null)
                {
                    HavokWorld.RemoveRigidBody(RigidBody);
                }
                RigidBody.Dispose();
                RigidBody       = WeldedRigidBody;
                WeldedRigidBody = null;
                RigidBody.SetWorldMatrix(rbWorldMatrix);
                WeldInfo.Transform = Matrix.Identity;
                if (HavokWorld != null)
                {
                    HavokWorld.AddRigidBody(RigidBody);
                }
                else if (!Entity.MarkedForClose)
                {
                    Activate();
                }

                if (RigidBody2 != null)
                {
                    RigidBody2.SetShape(RigidBody.GetShape());
                }
            }
            if (RigidBody != null && recreateShape)
            {
                RecreateWeldedShape(GetShape());
            }
            OnUnwelded(other);
            other.OnUnwelded(this);
            Debug.Assert(!other.IsWelded);
        }