示例#1
0
        public static void lua_AddEntityRagdoll(int entID, int setupIndex)
        {
            var ent = EngineWorld.GetEntityByID((uint)entID);

            if (ent != null)
            {
                var ragdollSetup = new RDSetup();

                if (!ragdollSetup.GetSetup(setupIndex))
                {
                    ConsoleInfo.Instance.Warning(SYSWARN_NO_RAGDOLL_SETUP, setupIndex);
                }
                else
                {
                    if (!ent.CreateRagdoll(ragdollSetup))
                    {
                        ConsoleInfo.Instance.Warning(SYSWARN_CANT_CREATE_RAGDOLL, entID);
                    }
                }
            }
            else
            {
                ConsoleInfo.Instance.Warning(SYSWARN_NO_ENTITY, entID);
            }
        }
示例#2
0
        public bool CreateRagdoll(RDSetup setup)
        {
            // No entity, setup or body count overflow - bypass function.

            if (setup == null || setup.BodySetup.Count > Bf.BoneTags.Count)
            {
                return false;
            }

            var result = true;

            // If ragdoll already exists, overwrite it with new one.

            if (Bt.BtJoints.Count > 0)
            {
                result = DeleteRagdoll();
            }

            // Setup bodies.
            Bt.BtJoints.Clear();
            // update current character animation and full fix body to avoid starting ragdoll partially inside the wall or floor...
            UpdateCurrentBoneFrame(Bf, Transform);
            Bt.NoFixAll = false;
            Bt.NoFixBodyParts = 0x00000000;
#if NOPE
            int map_size = m_bf.animations.model->collision_map.size();             // does not works, strange...
            m_bf.animations.model->collision_map.size() = m_bf.animations.model->mesh_count;
            fixPenetrations(nullptr);
            m_bf.animations.model->collision_map.size() = map_size;
#else
            FixPenetrations(Vector3.Zero);
#endif

            for(var i = 0; i < setup.BodySetup.Count; i++)
            {
                // TODO: First check useless?
                if(i >= Bf.BoneTags.Count || Bt.BtBody[i] == null)
                {
                    result = false;
                    continue; // If body is absent, return false and bypass this body setup.
                }

                var inertia = BulletSharp.Math.Vector3.Zero;
                var mass = setup.BodySetup[i].Mass;

                BtEngineDynamicsWorld.RemoveRigidBody(Bt.BtBody[i]);

                Bt.BtBody[i].CollisionShape.CalculateLocalInertia(mass, out inertia);
                Bt.BtBody[i].SetMassProps(mass, inertia);

                Bt.BtBody[i].UpdateInertiaTensor();
                Bt.BtBody[i].ClearForces();

                Bt.BtBody[i].LinearFactor = BulletSharp.Math.Vector3.One;
                Bt.BtBody[i].AngularFactor = BulletSharp.Math.Vector3.One;

                Bt.BtBody[i].SetDamping(setup.BodySetup[i].Damping[0], setup.BodySetup[i].Damping[1]);
                Bt.BtBody[i].Restitution = setup.BodySetup[i].Restitution;
                Bt.BtBody[i].Friction = setup.BodySetup[i].Friction;

                Bt.BtBody[i].SetSleepingThresholds(RD_DEFAULT_SLEEPING_THRESHOLD, RD_DEFAULT_SLEEPING_THRESHOLD);

                if(Bf.BoneTags[i].Parent == null)
                {
                    var r = GetInnerBBRadius(Bf.BoneTags[i].MeshBase.BBMin, Bf.BoneTags[i].MeshBase.BBMax);
                    Bt.BtBody[i].CcdMotionThreshold = 0.8f * r;
                    Bt.BtBody[i].CcdSweptSphereRadius = r;
                }
            }

            UpdateRigidBody(true);
            for(var i = 0; i < Bf.BoneTags.Count; i++)
            {
                BtEngineDynamicsWorld.AddRigidBody(Bt.BtBody[i]);
                Bt.BtBody[i].Activate();
                Bt.BtBody[i].LinearVelocity = Speed.ToBullet();
                if (i < Bt.GhostObjects.Count && Bt.GhostObjects[i] != null)
                {
                    BtEngineDynamicsWorld.RemoveCollisionObject(Bt.GhostObjects[i]);
                    BtEngineDynamicsWorld.AddCollisionObject(Bt.GhostObjects[i], CollisionFilterGroups.None, CollisionFilterGroups.None);
                }
            }

            // Setup constraints.
            Bt.BtJoints.Resize(setup.JointSetup.Count);

            for(var i = 0; i < setup.JointSetup.Count; i++)
            {
                if(setup.JointSetup[i].BodyIndex >= Bf.BoneTags.Count || Bt.BtBody[setup.JointSetup[i].BodyIndex] == null)
                {
                    result = false;
                    break; // If body 1 or body 2 are absent, return false and bypass this joint.
                }

                var localA = new Transform();
                var localB = new Transform();
                var btB = Bf.BoneTags[setup.JointSetup[i].BodyIndex];
                var btA = btB.Parent;
                if(btA == null)
                {
                    result = false;
                    break;
                }
#if NOPE
                localA.setFromOpenGLMatrix(btB->transform);
                localB.setIdentity();
#else
                Helper.SetEulerZYX(ref localA.Basis, setup.JointSetup[i].Body1Angle);
                //localA.Origin = setup.JointSetup[i].Body1Offset;
                localA.Origin = btB.Transform.Origin;

                Helper.SetEulerZYX(ref localB.Basis, setup.JointSetup[i].Body2Angle);
                //localB.Origin = setup.JointSetup[i].Body2Offset;
                localB.Origin = Vector3.Zero;
#endif

                switch(setup.JointSetup[i].JointType)
                {
                    case RDJointSetup.Type.Point:
                        Bt.BtJoints[i] = new Point2PointConstraint(Bt.BtBody[btA.Index], Bt.BtBody[btB.Index],
                            localA.Origin.ToBullet(), localB.Origin.ToBullet());
                        break;

                        case RDJointSetup.Type.Hinge:
                        var hingeC = new HingeConstraint(Bt.BtBody[btA.Index], Bt.BtBody[btB.Index], ((Matrix4) localA).ToBullet(),
                            ((Matrix4) localB).ToBullet());
                        hingeC.SetLimit(setup.JointSetup[i].JointLimit[0], setup.JointSetup[i].JointLimit[1], 0.9f, 0.3f, 0.3f);
                        Bt.BtJoints[i] = hingeC;
                        break;

                    case RDJointSetup.Type.Cone:
                        var coneC = new ConeTwistConstraint(Bt.BtBody[btA.Index], Bt.BtBody[btB.Index], ((Matrix4)localA).ToBullet(),
                            ((Matrix4)localB).ToBullet());
                        coneC.SetLimit(setup.JointSetup[i].JointLimit[0], setup.JointSetup[i].JointLimit[1], setup.JointSetup[i].JointLimit[2], 0.9f, 0.3f, 0.7f);
                        Bt.BtJoints[i] = coneC;
                        break;
                }

                Bt.BtJoints[i].SetParam(ConstraintParam.StopCfm, setup.JointCfm, -1);
                Bt.BtJoints[i].SetParam(ConstraintParam.StopErp, setup.JointErp, -1);

                Bt.BtJoints[i].DebugDrawSize = 64.0f;
                BtEngineDynamicsWorld.AddConstraint(Bt.BtJoints[i], true);
            }

            if(!result)
            {
                DeleteRagdoll(); // PARANOID: Clean up the mess, if something went wrong.
            }
            else
            {
                TypeFlags |= ENTITY_TYPE.Dynamic;
            }
            return result;
        }