Ejemplo n.º 1
0
    public PassiveRagdollSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;

      // Add game objects which allow to shoot balls and grab rigid bodies.
      _ballShooterObject = new BallShooterObject(Services) { Speed = 10 };
      GameObjectService.Objects.Add(_ballShooterObject);
      _grabObject = new GrabObject(Services);
      GameObjectService.Objects.Add(_grabObject);

      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the world space pose of the whole ragdoll. And copy the bone poses of the
      // current skeleton pose.
      _ragdoll.Pose = _meshNode.PoseWorld;
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      // Uncomment to disable dynamic movement (for debugging during ragdoll creation):
      //foreach (var body in _ragdoll.Bodies)
      //  if (body != null)
      //    body.MotionType = MotionType.Kinematic;

      // In this sample we use a passive ragdoll where we need joints to hold the
      // limbs together and limits to restrict angular movement.
      _ragdoll.EnableJoints();
      _ragdoll.EnableLimits();

      // Set all motors to constraint motors that only use damping. This adds a damping
      // effect to all ragdoll limbs.
      foreach (RagdollMotor motor in _ragdoll.Motors)
      {
        if (motor != null)
        {
          motor.Mode = RagdollMotorMode.Constraint;
          motor.ConstraintDamping = 5;
          motor.ConstraintSpring = 0;
        }
      }
      _ragdoll.EnableMotors();

      // Add rigid bodies and the constraints of the ragdoll to the simulation.
      _ragdoll.AddToSimulation(Simulation);

      // Add a rigid body.
      var box = new RigidBody(new BoxShape(0.4f, 0.4f, 0.4f))
      {
        Name = "Box",
        Pose = new Pose(new Vector3F(0, 3, 0)),
      };
      Simulation.RigidBodies.Add(box);
    }
Ejemplo n.º 2
0
        private static void AddJoint(Ragdoll ragdoll, Skeleton skeleton, AvatarBone parentBone, AvatarBone childBone, float errorReduction, float softness)
        {
            int parentIndex = (int)parentBone;
            int childIndex  = (int)childBone;

            // To define AnchorPositionALocal/AnchorPositionBLocal:
            // To get the AnchorPositionALocal we apply jointPosesAbsolute[indexA].Inverse to
            // convert the joint pose from model space into the joints space of parentBone. Then we apply
            // ragdoll.BodyOffsets[boneAIndex].Inverse to convert from joint space to body space. The result is
            // the joint position of B in body space of A.
            // To get AnchorPositionBLocal, we only have to apply the inverse offset.

            BallJoint joint = new BallJoint
            {
                BodyA                = ragdoll.Bodies[parentIndex],
                BodyB                = ragdoll.Bodies[childIndex],
                CollisionEnabled     = false,
                AnchorPositionALocal = (ragdoll.BodyOffsets[parentIndex].Inverse * skeleton.GetBindPoseAbsoluteInverse(parentIndex) * skeleton.GetBindPoseAbsoluteInverse(childIndex).Inverse).Translation,
                AnchorPositionBLocal = ragdoll.BodyOffsets[childIndex].Inverse.Position,
                ErrorReduction       = errorReduction,
                Softness             = softness,
            };

            ragdoll.Joints[childIndex] = joint;
        }
Ejemplo n.º 3
0
    public CollisionDetectionOnlyRagdollSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;
      SetCamera(new Vector3F(0, 1, 6), 0, 0);

      // Add a game object which allows to shoot balls.
      _ballShooterObject = new BallShooterObject(Services);
      GameObjectService.Objects.Add(_ballShooterObject);

      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      var animations = _meshNode.Mesh.Animations;
      var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the world space pose of the whole ragdoll. 
      _ragdoll.Pose = _meshNode.PoseWorld;
      // And copy the bone poses of the current skeleton pose.
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      foreach (var body in _ragdoll.Bodies)
      {
        if (body != null)
        {
          // Set all bodies to kinematic - they should not be affected by forces.
          body.MotionType = MotionType.Kinematic;

          // Disable collision response.
          body.CollisionResponseEnabled = false;
        }
      }

      // In this sample, we do not need joints, limits or motors.
      _ragdoll.DisableJoints();
      _ragdoll.DisableLimits();
      _ragdoll.DisableMotors();

      // Add ragdoll rigid bodies to the simulation.
      _ragdoll.AddToSimulation(Simulation);
    }
Ejemplo n.º 4
0
        private static void AddTwistSwingLimit(Ragdoll ragdoll, Skeleton skeleton, AvatarBone parentBone, AvatarBone childBone, Matrix33F orientationA, Matrix33F orientationB, Vector3F minimum, Vector3F maximum)
        {
            int parentIndex = (int)parentBone;
            int childIndex  = (int)childBone;

            // The difficult part is to define the constraint anchor orientation.
            // Here is how we do it:
            // When we look at the front side of an Avatar in bind pose, the x-axis is parallel
            // to the arms. y points up and z is normal to the those axes.
            //
            // To define orientationA/B:
            // The anchor x-axis is the twist axis. That means, this is already the correct axis
            // for the hands (wrist joints) and orientationA/B are therefore Matrix33F.Identity.
            // For the Head, the twist axis must point up. Therefore orientationA/B must be a 90°
            // rotation about z to rotate the twist axis up.
            // For the shoulder-elbow connection, orientationA is Matrix.Identity. The swing cone must
            // not be parallel to the arm axis (because the elbow cannot bend backwards). Therefore,
            // orientationB defines a rotation that rotates the twist axis (= swing cone center) to the
            // front.
            //
            // To define AnchorOrientationALocal/AnchorOrientationBLocal:
            // AnchorOrientationALocal must be a rotation matrix that transforms a vector from local
            // constraint anchor space to local body space of A.
            // orientationA defines the constraint anchor orientation in model space.
            // With jointPosesAbsolute[boneAIndex].Orientation.Transposed, we convert from model space
            // to joint space. With ragdoll.BodyOffsets[boneAIndex].Orientation.Transposed, we convert from joint
            // space to body space. The combined rotation matrix converts from constraint anchor space
            // to body space.

            var limit = new TwistSwingLimit
            {
                BodyA = ragdoll.Bodies[parentIndex],
                BodyB = ragdoll.Bodies[childIndex],
                AnchorOrientationALocal = ragdoll.BodyOffsets[parentIndex].Orientation.Transposed * skeleton.GetBindPoseAbsoluteInverse(parentIndex).Rotation.ToRotationMatrix33() * orientationA,
                AnchorOrientationBLocal = ragdoll.BodyOffsets[childIndex].Orientation.Transposed * skeleton.GetBindPoseAbsoluteInverse(childIndex).Rotation.ToRotationMatrix33() * orientationB,
                Minimum        = minimum,
                Maximum        = maximum,
                ErrorReduction = 0.2f,
                Softness       = 0.001f
            };

            ragdoll.Limits[childIndex] = limit;
        }
Ejemplo n.º 5
0
    public AutoRagdollShapesSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      var animations = _meshNode.Mesh.Animations;
      var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      var animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);
      animationController.AutoRecycle();
      animationController.UpdateAndApply();

      // Create a ragdoll for the Dude model.
      _ragdoll = CreateRagdoll(_meshNode);

      // Set the world space pose of the whole ragdoll. 
      _ragdoll.Pose = _meshNode.PoseWorld;
      // And copy the bone poses of the current skeleton pose.
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      foreach (var body in _ragdoll.Bodies)
      {
        if (body != null)
        {
          // Set all bodies to kinematic - they should not be affected by forces.
          body.MotionType = MotionType.Kinematic;

          // Disable collision response.
          body.CollisionResponseEnabled = false;
        }
      }

      // Add ragdoll rigid bodies to the simulation.
      _ragdoll.AddToSimulation(Simulation);
    }
Ejemplo n.º 6
0
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

              if (_avatarPose == null)
              {
            if (_avatarRenderer.State == AvatarRendererState.Ready)
            {
              _avatarPose = new AvatarPose(_avatarRenderer);

              // Create a ragdoll for the avatar.
              _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation);

              // Set the world space pose of the whole ragdoll. And copy the bone poses of the
              // current skeleton pose.
              _ragdoll.Pose = _pose;
              _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose);

              // In this sample we use a passive ragdoll where we need joints to hold the
              // limbs together and limits to control the angular movement.
              _ragdoll.EnableJoints();
              _ragdoll.EnableLimits();

              // Set all motors to constraint motors that only use damping. This adds a damping
              // effect to all ragdoll limbs.
              foreach (RagdollMotor motor in _ragdoll.Motors)
              {
            if (motor != null)
            {
              motor.Mode = RagdollMotorMode.Constraint;
              motor.ConstraintDamping = 5;
              motor.ConstraintSpring = 0;
            }
              }
              _ragdoll.EnableMotors();

              // Add rigid bodies and the constraints of the ragdoll to the simulation.
              _ragdoll.AddToSimulation(Simulation);
            }
              }
        }
Ejemplo n.º 7
0
        private static void AddAngularLimit(Ragdoll ragdoll, Skeleton skeleton, AvatarBone parentBone, AvatarBone childBone, Matrix33F orientationA, Matrix33F orientationB, Vector3F minimum, Vector3F maximum)
        {
            // Similar to AddTwistSwingLimit

            int parentIndex = (int)parentBone;
            int childIndex  = (int)childBone;

            var limit = new AngularLimit
            {
                BodyA = ragdoll.Bodies[parentIndex],
                BodyB = ragdoll.Bodies[childIndex],
                AnchorOrientationALocal = ragdoll.BodyOffsets[parentIndex].Orientation.Transposed * skeleton.GetBindPoseAbsoluteInverse(parentIndex).Rotation.ToRotationMatrix33() * orientationA,
                AnchorOrientationBLocal = ragdoll.BodyOffsets[childIndex].Orientation.Transposed * skeleton.GetBindPoseAbsoluteInverse(childIndex).Rotation.ToRotationMatrix33() * orientationB,
                Minimum        = minimum,
                Maximum        = maximum,
                ErrorReduction = new Vector3F(0.2f),
                Softness       = new Vector3F(0.001f)
            };

            ragdoll.Limits[childIndex] = limit;
        }
Ejemplo n.º 8
0
        private static void AddMotor(Ragdoll ragdoll, AvatarBone parentBone, AvatarBone childBone)
        {
            // A quaternion motor controls the relative orientation between two bodies. The target
            // orientation is specified with a quaternion. The target orientations are set in
            // SetMotorTargets.

            // We can use the motors to achieve following results:
            // - No motors: The ragdoll joints are not damped and the bones swing a lot (within the
            //   allowed limits).
            // - Damping: If DampingConstant > 0 and SpringConstant == 0, the relative bone rotations
            //   are damped. This simulates joint friction and muscles forces acting against the movement.
            // - Springs: If DampingConstant > 0 and SpringConstant > 0, the motors try to move the
            //   ragdoll limbs to a pose defined by the TargetOrientations of the motors. This could be,
            //   for example, a defensive pose of a character.
            // - Animation: Like "Springs" but the TargetOrientation is changed in each frame. This
            //   way the ragdoll performs a user defined animation while still reacting to impacts.

            int parentIndex = (int)parentBone;
            int childIndex  = (int)childBone;

            var motor = new RagdollMotor(childIndex, parentIndex);

            ragdoll.Motors[childIndex] = motor;
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Initializes the ragdoll for the given skeleton pose.
        /// </summary>
        /// <param name="skeletonPose">The skeleton pose.</param>
        /// <param name="ragdoll">The ragdoll.</param>
        /// <param name="simulation">The simulation in which the ragdoll will be used.</param>
        public static void Create(SkeletonPose skeletonPose, Ragdoll ragdoll, Simulation simulation)
        {
            var skeleton = skeletonPose.Skeleton;

              const float totalMass = 80; // The total mass of the ragdoll.
              const int numberOfBodies = 17;

              // Get distance from foot to head as a measure for the size of the ragdoll.
              int head = skeleton.GetIndex("Head");
              int footLeft = skeleton.GetIndex("L_Ankle1");
              var headPosition = skeletonPose.GetBonePoseAbsolute(head).Translation;
              var footPosition = skeletonPose.GetBonePoseAbsolute(footLeft).Translation;
              var headToFootDistance = (headPosition - footPosition).Length;

              // We use the same mass properties for all bodies. This is not realistic but more stable
              // because large mass differences or thin bodies (arms!) are less stable.
              // We use the mass properties of sphere proportional to the size of the model.
              var massFrame = MassFrame.FromShapeAndMass(new SphereShape(headToFootDistance / 8), Vector3F.One, totalMass / numberOfBodies, 0.1f, 1);

              var material = new UniformMaterial();

              #region ----- Add Bodies and Body Offsets -----

              var numberOfBones = skeleton.NumberOfBones;
              ragdoll.Bodies.AddRange(Enumerable.Repeat<RigidBody>(null, numberOfBones));
              ragdoll.BodyOffsets.AddRange(Enumerable.Repeat(Pose.Identity, numberOfBones));

              var pelvis = skeleton.GetIndex("Pelvis");
              ragdoll.Bodies[pelvis] = new RigidBody(new BoxShape(0.3f, 0.4f, 0.55f), massFrame, material);
              ragdoll.BodyOffsets[pelvis] = new Pose(new Vector3F(0.0f, 0, 0));

              var backLower = skeleton.GetIndex("Spine");
              ragdoll.Bodies[backLower] = new RigidBody(new BoxShape(0.36f, 0.4f, 0.55f), massFrame, material);
              ragdoll.BodyOffsets[backLower] = new Pose(new Vector3F(0.18f, 0, 0));

              var backUpper = skeleton.GetIndex("Spine2");
              ragdoll.Bodies[backUpper] = new RigidBody(new BoxShape(0.5f, 0.4f, 0.65f), massFrame, material);
              ragdoll.BodyOffsets[backUpper] = new Pose(new Vector3F(0.25f, 0, 0));

              var neck = skeleton.GetIndex("Neck");
              ragdoll.Bodies[neck] = new RigidBody(new CapsuleShape(0.12f, 0.3f), massFrame, material);
              ragdoll.BodyOffsets[neck] = new Pose(new Vector3F(0.15f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
              ragdoll.Bodies[neck].CollisionObject.Enabled = false;

              ragdoll.Bodies[head] = new RigidBody(new SphereShape(0.2f), massFrame, material);
              ragdoll.BodyOffsets[head] = new Pose(new Vector3F(0.15f, 0.02f, 0));

              var armUpperLeft = skeleton.GetIndex("L_UpperArm");
              ragdoll.Bodies[armUpperLeft] = new RigidBody(new CapsuleShape(0.12f, 0.6f), massFrame, material);
              ragdoll.BodyOffsets[armUpperLeft] = new Pose(new Vector3F(0.2f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

              var armLowerLeft = skeleton.GetIndex("L_Forearm");
              ragdoll.Bodies[armLowerLeft] = new RigidBody(new CapsuleShape(0.08f, 0.5f), massFrame, material);
              ragdoll.BodyOffsets[armLowerLeft] = new Pose(new Vector3F(0.2f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

              var handLeft = skeleton.GetIndex("L_Hand");
              ragdoll.Bodies[handLeft] = new RigidBody(new BoxShape(0.2f, 0.06f, 0.15f), massFrame, material);
              ragdoll.BodyOffsets[handLeft] = new Pose(new Vector3F(0.1f, 0, 0));

              var armUpperRight = skeleton.GetIndex("R_UpperArm");
              ragdoll.Bodies[armUpperRight] = new RigidBody(new CapsuleShape(0.12f, 0.6f), massFrame, material);
              ragdoll.BodyOffsets[armUpperRight] = new Pose(new Vector3F(0.2f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

              var armLowerRight = skeleton.GetIndex("R_Forearm");
              ragdoll.Bodies[armLowerRight] = new RigidBody(new CapsuleShape(0.08f, 0.5f), massFrame, material);
              ragdoll.BodyOffsets[armLowerRight] = new Pose(new Vector3F(0.2f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

              var handRight = skeleton.GetIndex("R_Hand");
              ragdoll.Bodies[handRight] = new RigidBody(new BoxShape(0.2f, 0.06f, 0.15f), massFrame, material);
              ragdoll.BodyOffsets[handRight] = new Pose(new Vector3F(0.1f, 0, 0));

              var legUpperLeft = skeleton.GetIndex("L_Thigh1");
              ragdoll.Bodies[legUpperLeft] = new RigidBody(new CapsuleShape(0.16f, 0.8f), massFrame, material);
              ragdoll.BodyOffsets[legUpperLeft] = new Pose(new Vector3F(0.4f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

              var legLowerLeft = skeleton.GetIndex("L_Knee2");
              ragdoll.Bodies[legLowerLeft] = new RigidBody(new CapsuleShape(0.12f, 0.65f), massFrame, material);
              ragdoll.BodyOffsets[legLowerLeft] = new Pose(new Vector3F(0.32f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

              //var footLeft = skeleton.GetIndex("L_Ankle1");
              ragdoll.Bodies[footLeft] = new RigidBody(new BoxShape(0.20f, 0.5f, 0.3f), massFrame, material);
              ragdoll.BodyOffsets[footLeft] = new Pose(new Vector3F(0.16f, 0.15f, 0));

              var legUpperRight = skeleton.GetIndex("R_Thigh");
              ragdoll.Bodies[legUpperRight] = new RigidBody(new CapsuleShape(0.16f, 0.8f), massFrame, material);
              ragdoll.BodyOffsets[legUpperRight] = new Pose(new Vector3F(0.4f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

              var legLowerRight = skeleton.GetIndex("R_Knee");
              ragdoll.Bodies[legLowerRight] = new RigidBody(new CapsuleShape(0.12f, 0.65f), massFrame, material);
              ragdoll.BodyOffsets[legLowerRight] = new Pose(new Vector3F(0.32f, 0, 0), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));

              var footRight = skeleton.GetIndex("R_Ankle");
              ragdoll.Bodies[footRight] = new RigidBody(new BoxShape(0.20f, 0.5f, 0.3f), massFrame, material);
              ragdoll.BodyOffsets[footRight] = new Pose(new Vector3F(0.16f, 0.15f, 0));
              #endregion

              #region ----- Set Collision Filters -----

              // Collisions between connected bodies will be disabled in AddJoint(). (A BallJoint
              // has a property CollisionEnabled which decides whether connected bodies can
              // collide.)
              // But we need to disable some more collision between bodies that are not directly
              // connected but still too close to each other.
              var filter = (ICollisionFilter)simulation.CollisionDomain.CollisionDetection.CollisionFilter;
              filter.Set(ragdoll.Bodies[backUpper].CollisionObject, ragdoll.Bodies[head].CollisionObject, false);
              filter.Set(ragdoll.Bodies[armUpperRight].CollisionObject, ragdoll.Bodies[backLower].CollisionObject, false);
              filter.Set(ragdoll.Bodies[armUpperLeft].CollisionObject, ragdoll.Bodies[backLower].CollisionObject, false);
              filter.Set(ragdoll.Bodies[legUpperLeft].CollisionObject, ragdoll.Bodies[legUpperRight].CollisionObject, false);
              #endregion

              #region ----- Add Joints -----

              AddJoint(skeletonPose, ragdoll, pelvis, backLower);
              AddJoint(skeletonPose, ragdoll, backLower, backUpper);
              AddJoint(skeletonPose, ragdoll, backUpper, neck);
              AddJoint(skeletonPose, ragdoll, neck, head);
              AddJoint(skeletonPose, ragdoll, backUpper, armUpperLeft);
              AddJoint(skeletonPose, ragdoll, armUpperLeft, armLowerLeft);
              AddJoint(skeletonPose, ragdoll, armLowerLeft, handLeft);
              AddJoint(skeletonPose, ragdoll, backUpper, armUpperRight);
              AddJoint(skeletonPose, ragdoll, armUpperRight, armLowerRight);
              AddJoint(skeletonPose, ragdoll, armLowerRight, handRight);
              AddJoint(skeletonPose, ragdoll, pelvis, legUpperLeft);
              AddJoint(skeletonPose, ragdoll, legUpperLeft, legLowerLeft);
              AddJoint(skeletonPose, ragdoll, legLowerLeft, footLeft);
              AddJoint(skeletonPose, ragdoll, pelvis, legUpperRight);
              AddJoint(skeletonPose, ragdoll, legUpperRight, legLowerRight);
              AddJoint(skeletonPose, ragdoll, legLowerRight, footRight);
              #endregion

              #region ----- Add Limits -----

              // Choosing limits is difficult.
              // We create hinge limits with AngularLimits in the back and in the knee.
              // For all other joints we use TwistSwingLimits with symmetric cones.

              AddAngularLimit(skeletonPose, ragdoll, pelvis, backLower, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.3f));
              AddAngularLimit(skeletonPose, ragdoll, backLower, backUpper, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.4f));
              AddAngularLimit(skeletonPose, ragdoll, backUpper, neck, new Vector3F(0, 0, -0.3f), new Vector3F(0, 0, 0.3f));
              AddTwistSwingLimit(ragdoll, neck, head, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.5f, -0.7f), new Vector3F(0.1f, 0.5f, 0.7f));

              var parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(backUpper).Inverse;
              var childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(armUpperLeft).Inverse;
              var bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute;
              AddTwistSwingLimit(ragdoll, backUpper, armUpperLeft, bindPoseRelative.Orientation * Matrix33F.CreateRotationY(-0.5f) * Matrix33F.CreateRotationZ(-0.5f), Matrix33F.Identity, new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(0.7f, 1.2f, 1.2f));

              AddTwistSwingLimit(ragdoll, armUpperLeft, armLowerLeft, Matrix33F.CreateRotationZ(-1.2f), Matrix33F.Identity, new Vector3F(-0.3f, -1.2f, -1.2f), new Vector3F(0.3f, 1.2f, 1.2f));
              AddTwistSwingLimit(ragdoll, armLowerLeft, handLeft, Matrix33F.Identity, Matrix33F.CreateRotationX(+ConstantsF.PiOver2), new Vector3F(-0.3f, -0.7f, -0.7f), new Vector3F(0.3f, 0.7f, 0.7f));

              parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(backUpper).Inverse;
              childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(armUpperRight).Inverse;
              bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute;
              AddTwistSwingLimit(ragdoll, backUpper, armUpperRight, bindPoseRelative.Orientation * Matrix33F.CreateRotationY(0.5f) * Matrix33F.CreateRotationZ(-0.5f), Matrix33F.Identity, new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(0.7f, 1.2f, 1.2f));

              AddTwistSwingLimit(ragdoll, armUpperRight, armLowerRight, Matrix33F.CreateRotationZ(-1.2f), Matrix33F.Identity, new Vector3F(-0.3f, -1.2f, -1.2f), new Vector3F(0.3f, 1.2f, 1.2f));
              AddTwistSwingLimit(ragdoll, armLowerRight, handRight, Matrix33F.Identity, Matrix33F.CreateRotationX(-ConstantsF.PiOver2), new Vector3F(-0.3f, -0.7f, -0.7f), new Vector3F(0.3f, 0.7f, 0.7f));

              parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(pelvis).Inverse;
              childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(legUpperLeft).Inverse;
              bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute;
              AddTwistSwingLimit(ragdoll, pelvis, legUpperLeft, bindPoseRelative.Orientation * Matrix33F.CreateRotationZ(1.2f), Matrix33F.Identity, new Vector3F(-0.1f, -0.7f, -1.5f), new Vector3F(+0.1f, +0.7f, +1.5f));

              AddAngularLimit(skeletonPose, ragdoll, legUpperLeft, legLowerLeft, new Vector3F(0, 0, -2.2f), new Vector3F(0, 0, 0.0f));
              AddTwistSwingLimit(ragdoll, legLowerLeft, footLeft, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.3f, -0.7f), new Vector3F(0.1f, 0.3f, 0.7f));

              parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(pelvis).Inverse;
              childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(legUpperRight).Inverse;
              bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute;
              AddTwistSwingLimit(ragdoll, pelvis, legUpperRight, bindPoseRelative.Orientation * Matrix33F.CreateRotationZ(1.2f), Matrix33F.Identity, new Vector3F(-0.1f, -0.7f, -1.5f), new Vector3F(+0.1f, +0.7f, +1.5f));

              AddAngularLimit(skeletonPose, ragdoll, legUpperRight, legLowerRight, new Vector3F(0, 0, -2.2f), new Vector3F(0, 0, 0.0f));
              AddTwistSwingLimit(ragdoll, legLowerRight, footRight, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.1f, -0.3f, -0.7f), new Vector3F(0.1f, 0.3f, 0.7f));
              #endregion

              #region ----- Add Motors -----

              ragdoll.Motors.AddRange(Enumerable.Repeat<RagdollMotor>(null, numberOfBones));
              ragdoll.Motors[pelvis] = new RagdollMotor(pelvis, -1);
              ragdoll.Motors[backLower] = new RagdollMotor(backLower, pelvis);
              ragdoll.Motors[backUpper] = new RagdollMotor(backUpper, backLower);
              ragdoll.Motors[neck] = new RagdollMotor(neck, backUpper);
              ragdoll.Motors[head] = new RagdollMotor(head, neck);
              ragdoll.Motors[armUpperLeft] = new RagdollMotor(armUpperLeft, backUpper);
              ragdoll.Motors[armLowerLeft] = new RagdollMotor(armLowerLeft, armUpperLeft);
              ragdoll.Motors[handLeft] = new RagdollMotor(handLeft, armLowerLeft);
              ragdoll.Motors[armUpperRight] = new RagdollMotor(armUpperRight, backUpper);
              ragdoll.Motors[armLowerRight] = new RagdollMotor(armLowerRight, armUpperRight);
              ragdoll.Motors[handRight] = new RagdollMotor(handRight, armLowerRight);
              ragdoll.Motors[legUpperLeft] = new RagdollMotor(legUpperLeft, pelvis);
              ragdoll.Motors[legLowerLeft] = new RagdollMotor(legLowerLeft, legUpperLeft);
              ragdoll.Motors[footLeft] = new RagdollMotor(footLeft, legLowerLeft);
              ragdoll.Motors[legUpperRight] = new RagdollMotor(legUpperRight, pelvis);
              ragdoll.Motors[legLowerRight] = new RagdollMotor(legLowerRight, legUpperRight);
              ragdoll.Motors[footRight] = new RagdollMotor(footRight, legLowerRight);
              #endregion
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Adds a BallJoint between the specified bones.
        /// </summary>
        /// <param name="skeletonPose">The skeleton pose.</param>
        /// <param name="ragdoll">The ragdoll.</param>
        /// <param name="parent">The parent.</param>
        /// <param name="child">The child.</param>
        private static void AddJoint(SkeletonPose skeletonPose, Ragdoll ragdoll, int parent, int child)
        {
            // Get bodies and offsets for the bones.
              var skeleton = skeletonPose.Skeleton;
              var childBody = ragdoll.Bodies[child];
              var childOffset = ragdoll.BodyOffsets[child];
              var parentBody = ragdoll.Bodies[parent];
              var parentOffset = ragdoll.BodyOffsets[parent];

              // Get bind poses of the bones in model space.
              var parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(parent).Inverse;
              var childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(child).Inverse;

              // The child pose relative to the parent bone.
              var bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute;

              // Add BallJoint that connects the two bones. The position of the joint is the
              // origin of the child bone.
              BallJoint joint = new BallJoint
              {
            BodyA = parentBody,
            BodyB = childBody,
            CollisionEnabled = false,
            AnchorPositionALocal = (parentOffset.Inverse * bindPoseRelative).Position,
            AnchorPositionBLocal = childOffset.Inverse.Position,
            ErrorReduction = 0.2f,
            Softness = 0.0001f,
              };
              ragdoll.Joints.Add(joint);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Visualizes the constraints of the ragdoll (for debugging).
        /// </summary>
        /// <param name="ragdoll">The ragdoll.</param>
        /// <param name="graphicsDevice">The graphics device.</param>
        /// <param name="effect">
        /// A BasicEffect. The world, view and projection matrices must be initialized.
        /// </param>
        /// <param name="scale">
        /// A scale factor that determines the size of the drawn elements.
        /// </param>
        /// <remarks>
        /// Currently, only <see cref="TwistSwingLimit"/>s and <see cref="AngularLimit"/>s are
        /// supported. 
        /// </remarks>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="ragdoll"/>, <paramref name="graphicsDevice"/> or <paramref name="effect"/>
        /// is <see langword="null"/>.
        /// </exception>
        public static void DrawConstraints(Ragdoll ragdoll, GraphicsDevice graphicsDevice, 
                                       BasicEffect effect, float scale)
        {
            if (ragdoll == null)
            throw new ArgumentNullException("ragdoll");
              if (graphicsDevice == null)
            throw new ArgumentNullException("graphicsDevice");
              if (effect == null)
            throw new ArgumentNullException("effect");

              _graphicsDevice = graphicsDevice;
              _scale = scale;
              _pointCount = 0;

              Debug.Assert(_points.Length % 2 == 0, "_points array must have an even number of elements.");
              _pointCount = 0;

              // Disable lighting, enable vertex colors.
              bool originalLightingEnabled = effect.LightingEnabled;
              bool originalVertexColorEnabled = effect.VertexColorEnabled;
              effect.LightingEnabled = false;
              effect.VertexColorEnabled = true;

              effect.CurrentTechnique.Passes[0].Apply();

              // Render information for each limit.
              foreach (Constraint limit in ragdoll.Limits)
              {
            // Get the ball joint constraint that connects the two bodies of the limit.
            BallJoint joint = null;
            foreach (Constraint constraint in ragdoll.Joints)
            {
              if (constraint.BodyA == limit.BodyA && constraint.BodyB == limit.BodyB
              || constraint.BodyA == limit.BodyB && constraint.BodyB == limit.BodyA)
              {
            joint = constraint as BallJoint;
            break;
              }
            }

            // Skip this limit if no joint was found.
            if (joint == null)
              continue;

            TwistSwingLimit twistSwingLimit = limit as TwistSwingLimit;
            if (twistSwingLimit != null)
            {
              DrawTwistSwingLimit(joint, twistSwingLimit);
              continue;
            }

            AngularLimit angularLimit = limit as AngularLimit;
            if (angularLimit != null)
            {
              DrawAngularLimit(joint, angularLimit);
              continue;
            }
              }

              // Draw everything that is in the buffer.
              Flush();

              // Restore original effect settings.
              effect.LightingEnabled = originalLightingEnabled;
              effect.VertexColorEnabled = originalVertexColorEnabled;
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Adds an AngularLimit between the specified bones.
        /// </summary>
        /// <param name="skeletonPose">The skeleton pose.</param>
        /// <param name="ragdoll">The ragdoll.</param>
        /// <param name="parent">The parent bone.</param>
        /// <param name="child">The childbone .</param>
        /// <param name="minimum">The minimum limits for each constraint axis (x/y/z).</param>
        /// <param name="maximum">The maximum limits for each constraint axis (x/y/z).</param>
        /// <remarks>
        /// The constraint anchor orientation is the orientation of the child bone.
        /// </remarks>
        private static void AddAngularLimit(SkeletonPose skeletonPose, Ragdoll ragdoll, int parent, int child, Vector3F minimum, Vector3F maximum)
        {
            var skeleton = skeletonPose.Skeleton;
              var childBody = ragdoll.Bodies[child];
              var childOffset = ragdoll.BodyOffsets[child];
              var parentBody = ragdoll.Bodies[parent];
              var parentOffset = ragdoll.BodyOffsets[parent];

              var parentBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(parent).Inverse;
              var childBindPoseAbsolute = (Pose)skeleton.GetBindPoseAbsoluteInverse(child).Inverse;
              var bindPoseRelative = parentBindPoseAbsolute.Inverse * childBindPoseAbsolute;

              var limit = new AngularLimit
              {
            BodyA = parentBody,
            BodyB = childBody,
            AnchorOrientationALocal = parentOffset.Orientation.Transposed * bindPoseRelative.Orientation,
            AnchorOrientationBLocal = childOffset.Orientation.Transposed,
            Minimum = minimum,
            Maximum = maximum,
            ErrorReduction = new Vector3F(0.2f),
            Softness = new Vector3F(0.001f)
              };
              ragdoll.Limits.Add(limit);
        }
Ejemplo n.º 13
0
    public ActiveRagdollSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;

      // Add game objects which allow to shoot balls and grab rigid bodies.
      _ballShooterObject = new BallShooterObject(Services) { Speed = 10 };
      GameObjectService.Objects.Add(_ballShooterObject);
      _grabObject = new GrabObject(Services);
      GameObjectService.Objects.Add(_grabObject);

      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create a copy of the dude's skeleton.
      _targetSkeletonPose = SkeletonPose.Create(_meshNode.Mesh.Skeleton);

      // Animate the _targetSkeletonPose.
      var animations = _meshNode.Mesh.Animations;
      var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_targetSkeletonPose);

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_targetSkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the world space pose of the whole ragdoll. And copy the bone poses of the
      // current skeleton pose.
      _ragdoll.Pose = _meshNode.PoseWorld;
      _ragdoll.UpdateBodiesFromSkeleton(_targetSkeletonPose);

      // In this sample we use an active ragdoll. We need joints because constraint ragdoll
      // motors only affect the body rotations.
      _ragdoll.EnableJoints();

      // We disable limits. If limits are enabled, the ragdoll could get unstable if 
      // the animation tries to move a limb beyond an allowed limit. (This happens if
      // a pose in the animation violates one of our limits.)
      _ragdoll.DisableLimits();

      // Set all motors to constraint motors. Constraint motors are like springs that
      // rotate the limbs to a target position.
      foreach (RagdollMotor motor in _ragdoll.Motors)
      {
        if (motor != null)
        {
          motor.Mode = RagdollMotorMode.Constraint;
          motor.ConstraintDamping = 10000;
          motor.ConstraintSpring = 100000;
        }
      }
      _ragdoll.EnableMotors();

      // Add rigid bodies and the constraints of the ragdoll to the simulation.
      _ragdoll.AddToSimulation(Simulation);

      // Add a rigid body.
      var box = new RigidBody(new BoxShape(0.4f, 0.4f, 0.4f))
      {
        Name = "Box",
        Pose = new Pose(new Vector3F(0, 3, 0)),
      };
      Simulation.RigidBodies.Add(box);
    }
Ejemplo n.º 14
0
        protected override void LoadContent()
        {
            // Add a ground plane to the simulation.
              Simulation.RigidBodies.Add(
            new RigidBody(new PlaneShape(Vector3F.UnitY, 0))
            {
              MotionType = MotionType.Static
            });

              _basicEffect = new BasicEffect(GraphicsDevice);

              _model = Game.Content.Load<Model>("Dude");
              var additionalData = (Dictionary<string, object>)_model.Tag;
              var skeleton = (Skeleton)additionalData["Skeleton"];
              _skeletonPose = SkeletonPose.Create(skeleton);

              // Create a ragdoll for the Dude model.
              _ragdoll = new Ragdoll();
              DudeRagdollCreator.Create(_skeletonPose, _ragdoll, Simulation);

              // Set the world space pose of the whole ragdoll. And copy the bone poses of the
              // current skeleton pose.
              _ragdoll.Pose = _pose;
              _ragdoll.UpdateBodiesFromSkeleton(_skeletonPose);

              // Uncomment to disable dynamic movement (for debugging during ragdoll creation):
              //foreach (var body in _ragdoll.Bodies)
              //  if (body != null)
              //    body.MotionType = MotionType.Kinematic;

              // In this sample we use a passive ragdoll where we need joints to hold the
              // limbs together and limits to restrict angular movement.
              _ragdoll.EnableJoints();
              _ragdoll.EnableLimits();

              // Set all motors to constraint motors that only use damping. This adds a damping
              // effect to all ragdoll limbs.
              foreach (RagdollMotor motor in _ragdoll.Motors)
              {
            if (motor != null)
            {
              motor.Mode = RagdollMotorMode.Constraint;
              motor.ConstraintDamping = 5;
              motor.ConstraintSpring = 0;
            }
              }
              _ragdoll.EnableMotors();

              // Add rigid bodies and the constraints of the ragdoll to the simulation.
              _ragdoll.AddToSimulation(Simulation);

              base.LoadContent();
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Creates a <see cref="Ragdoll"/> for an Xbox LIVE Avatar. (Only available on Xbox 360.)
        /// </summary>
        /// <param name="skeleton">The skeleton of the Xbox LIVE Avatar.</param>
        /// <param name="simulation">The simulation.</param>
        /// <returns>The avatar ragdoll.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="skeleton"/> or <paramref name="simulation"/> is
        /// <see langword="null"/>.
        /// </exception>
        /// <remarks>
        /// This method is available only in the Xbox 360 build of the
        /// DigitalRune.Physics.Specialized.dll.
        /// </remarks>
        public static Ragdoll CreateAvatarRagdoll(Skeleton skeleton, Simulation simulation)
        {
            if (skeleton == null)
            {
                throw new ArgumentNullException("skeleton");
            }
            if (simulation == null)
            {
                throw new ArgumentNullException("simulation");
            }

            var ragdoll = new Ragdoll();

            // The lists ragdoll.Bodies, ragdoll.BodyOffsets and _motors contain one entry per bone - even if there
            // is no RigidBody for this bone. - This wastes memory but simplifies the code.
            for (int i = 0; i < AvatarRenderer.BoneCount; i++)
            {
                ragdoll.Bodies.Add(null);
                ragdoll.BodyOffsets.Add(Pose.Identity);
                ragdoll.Joints.Add(null);
                ragdoll.Limits.Add(null);
                ragdoll.Motors.Add(null);
            }

            // ----- Create bodies.
            // We use the same mass for all bodies. This is not physically correct but it makes the
            // simulation more stable, for several reasons:
            // - It is better to avoid large mass differences. Therefore, all limbs have the same mass.
            // - Capsule shapes have a low inertia value about their height axis. This causes instability
            //   and it is better to use larger inertia values.
            var massFrame = MassFrame.FromShapeAndMass(new SphereShape(0.2f), Vector3F.One, 4, 0.1f, 1);

            // Use standard material.
            var material = new UniformMaterial();

            // Create rigid bodies for the important bones. The shapes have been manually adapted to
            // produce useful results for thin and overweight avatars.
            // Without offset, the bodies are centered at the joint. ragdoll.BodyOffsets stores an offset pose
            // for each body. Instead, we could use TransformedShape but we can easily handle that
            // ourselves.
            // The collar bones are special, they use dummy shapes and are only used to connect the
            // shoulder bones.
            ragdoll.Bodies[(int)AvatarBone.Root]               = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.Root]          = new Pose(new Vector3F(0, -0.08f, -0.01f), QuaternionF.CreateRotationX(-0.0f));
            ragdoll.Bodies[(int)AvatarBone.BackLower]          = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.BackLower]     = new Pose(new Vector3F(0, 0.08f, -0.01f), QuaternionF.CreateRotationX(-0.0f));
            ragdoll.Bodies[(int)AvatarBone.BackUpper]          = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.BackUpper]     = new Pose(new Vector3F(0, 0.08f, -0.01f), QuaternionF.CreateRotationX(-0.1f));
            ragdoll.Bodies[(int)AvatarBone.Neck]               = new RigidBody(new CapsuleShape(0.04f, 0.09f), massFrame, material);
            ragdoll.Bodies[(int)AvatarBone.Head]               = new RigidBody(new SphereShape(0.15f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.Head]          = new Pose(new Vector3F(0, 0.1f, 0));
            ragdoll.Bodies[(int)AvatarBone.CollarLeft]         = new RigidBody(Shape.Empty, massFrame, material);
            ragdoll.Bodies[(int)AvatarBone.CollarRight]        = new RigidBody(Shape.Empty, massFrame, material);
            ragdoll.Bodies[(int)AvatarBone.ShoulderLeft]       = new RigidBody(new CapsuleShape(0.04f, 0.25f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.ShoulderLeft]  = new Pose(new Vector3F(0.08f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
            ragdoll.Bodies[(int)AvatarBone.ShoulderRight]      = new RigidBody(new CapsuleShape(0.04f, 0.25f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.ShoulderRight] = new Pose(new Vector3F(-0.08f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
            ragdoll.Bodies[(int)AvatarBone.ElbowLeft]          = new RigidBody(new CapsuleShape(0.04f, 0.21f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.ElbowLeft]     = new Pose(new Vector3F(0.06f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
            ragdoll.Bodies[(int)AvatarBone.ElbowRight]         = new RigidBody(new CapsuleShape(0.04f, 0.21f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.ElbowRight]    = new Pose(new Vector3F(-0.06f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
            ragdoll.Bodies[(int)AvatarBone.WristLeft]          = new RigidBody(new BoxShape(0.1f, 0.04f, 0.1f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.WristLeft]     = new Pose(new Vector3F(0.06f, -0.02f, -0.01f), QuaternionF.CreateRotationZ(0.0f));
            ragdoll.Bodies[(int)AvatarBone.WristRight]         = new RigidBody(new BoxShape(0.1f, 0.04f, 0.1f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.WristRight]    = new Pose(new Vector3F(-0.06f, -0.02f, -0.01f), QuaternionF.CreateRotationZ(0.0f));
            ragdoll.Bodies[(int)AvatarBone.HipLeft]            = new RigidBody(new CapsuleShape(0.06f, 0.34f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.HipLeft]       = new Pose(new Vector3F(0, -0.14f, -0.02f), QuaternionF.CreateRotationX(0.1f));
            ragdoll.Bodies[(int)AvatarBone.HipRight]           = new RigidBody(new CapsuleShape(0.06f, 0.34f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.HipRight]      = new Pose(new Vector3F(0, -0.14f, -0.02f), QuaternionF.CreateRotationX(0.1f));
            ragdoll.Bodies[(int)AvatarBone.KneeLeft]           = new RigidBody(new CapsuleShape(0.06f, 0.36f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.KneeLeft]      = new Pose(new Vector3F(0, -0.18f, -0.04f), QuaternionF.CreateRotationX(0.1f));
            ragdoll.Bodies[(int)AvatarBone.KneeRight]          = new RigidBody(new CapsuleShape(0.06f, 0.36f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.KneeRight]     = new Pose(new Vector3F(0, -0.18f, -0.04f), QuaternionF.CreateRotationX(0.1f));
            ragdoll.Bodies[(int)AvatarBone.AnkleLeft]          = new RigidBody(new BoxShape(0.1f, 0.06f, 0.22f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.AnkleLeft]     = new Pose(new Vector3F(0, -0.07f, 0.05f), QuaternionF.CreateRotationZ(0));
            ragdoll.Bodies[(int)AvatarBone.AnkleRight]         = new RigidBody(new BoxShape(0.1f, 0.06f, 0.22f), massFrame, material);
            ragdoll.BodyOffsets[(int)AvatarBone.AnkleRight]    = new Pose(new Vector3F(0, -0.07f, 0.05f), QuaternionF.CreateRotationZ(0));

            // ----- Add joint constraints.
            const float jointErrorReduction = 0.2f;
            const float jointSoftness       = 0.0001f;

            AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.BackLower, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.BackLower, AvatarBone.BackUpper, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.Neck, 0.6f, 0.000001f);
            AddJoint(ragdoll, skeleton, AvatarBone.Neck, AvatarBone.Head, 0.6f, 0.000001f);
            AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.CollarRight, AvatarBone.ShoulderRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.ShoulderRight, AvatarBone.ElbowRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.ElbowLeft, AvatarBone.WristLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.ElbowRight, AvatarBone.WristRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.HipLeft, AvatarBone.KneeLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.HipRight, AvatarBone.KneeRight, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.KneeLeft, AvatarBone.AnkleLeft, jointErrorReduction, jointSoftness);
            AddJoint(ragdoll, skeleton, AvatarBone.KneeRight, AvatarBone.AnkleRight, jointErrorReduction, jointSoftness);

            // ----- Add constraint limits.
            // We use TwistSwingLimits to define an allowed twist and swing cone for the joints.
            // Exceptions are the back and knees, where we use AngularLimits to create hinges.
            // (We could also create a hinge with a TwistSwingLimit where the twist axis is the hinge
            // axis and no swing is allowed - but AngularLimits create more stable hinges.)
            // Another exception are the collar bones joint. We use AngularLimits to disallow any
            // rotations.
            AddAngularLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.BackLower,
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackLower).Rotation.Conjugated.ToRotationMatrix33(),
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackLower).Rotation.Conjugated.ToRotationMatrix33(),
                            new Vector3F(-0.3f, 0, 0), new Vector3F(0.3f, 0, 0));

            AddAngularLimit(ragdoll, skeleton, AvatarBone.BackLower, AvatarBone.BackUpper,
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackUpper).Rotation.Conjugated.ToRotationMatrix33(),
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackUpper).Rotation.Conjugated.ToRotationMatrix33(),
                            new Vector3F(-0.3f, 0, 0), new Vector3F(0.4f, 0, 0));

            var rotationZ90Degrees = Matrix33F.CreateRotationZ(ConstantsF.PiOver2);

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.Neck, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.3f, -0.3f), new Vector3F(+0.1f, +0.3f, +0.3f));

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Neck, AvatarBone.Head, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.6f, -0.6f), new Vector3F(+0.1f, +0.6f, +0.6f));

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarLeft,
                               skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarLeft).Rotation.Conjugated.ToRotationMatrix33(),
                               skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarLeft).Rotation.Conjugated.ToRotationMatrix33(),
                               new Vector3F(0), new Vector3F(0));

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarRight,
                               skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarRight).Rotation.Conjugated.ToRotationMatrix33(),
                               skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarRight).Rotation.Conjugated.ToRotationMatrix33(),
                               new Vector3F(0), new Vector3F(0));

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft, Matrix33F.Identity, Matrix33F.CreateRotationY(0.7f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.CollarRight, AvatarBone.ShoulderRight, Matrix33F.Identity, Matrix33F.CreateRotationY(-0.7f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft, Matrix33F.Identity, Matrix33F.CreateRotationY(1.2f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ShoulderRight, AvatarBone.ElbowRight, Matrix33F.Identity, Matrix33F.CreateRotationY(-1.2f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ElbowLeft, AvatarBone.WristLeft, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.7f, -0.7f, -0.7f), new Vector3F(+0.7f, +0.7f, +0.7f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ElbowRight, AvatarBone.WristRight, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.7f, -0.7f, -0.7f), new Vector3F(+0.7f, +0.7f, +0.7f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipLeft, rotationZ90Degrees, Matrix33F.CreateRotationX(-1.2f) * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 + 0.2f), new Vector3F(-0.1f, -1.5f, -0.7f), new Vector3F(+0.1f, +1.5f, +0.7f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipRight, rotationZ90Degrees, Matrix33F.CreateRotationX(-1.2f) * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 - 0.2f), new Vector3F(-0.1f, -1.5f, -0.7f), new Vector3F(+0.1f, +1.5f, +0.7f));

            AddAngularLimit(ragdoll, skeleton, AvatarBone.HipLeft, AvatarBone.KneeLeft,
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeLeft).Rotation.Conjugated.ToRotationMatrix33(),
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeLeft).Rotation.Conjugated.ToRotationMatrix33(),
                            new Vector3F(0, 0, 0), new Vector3F(2.2f, 0, 0));

            AddAngularLimit(ragdoll, skeleton, AvatarBone.HipRight, AvatarBone.KneeRight,
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeRight).Rotation.Conjugated.ToRotationMatrix33(),
                            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeRight).Rotation.Conjugated.ToRotationMatrix33(),
                            new Vector3F(0, 0, 0), new Vector3F(2.2f, 0, 0));

            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.KneeLeft, AvatarBone.AnkleLeft, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.7f, -0.3f), new Vector3F(+0.1f, +0.7f, +0.3f));
            AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.KneeRight, AvatarBone.AnkleRight, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.7f, -0.3f), new Vector3F(+0.1f, +0.7f, +0.3f));

            // ----- Add motors
            // We use QuaternionMotors to create forces that rotate the bones into desired poses.
            // This can be used for damping, spring or animating the ragdoll.
            AddMotor(ragdoll, (AvatarBone)(-1), AvatarBone.Root);
            AddMotor(ragdoll, AvatarBone.Root, AvatarBone.BackLower);
            AddMotor(ragdoll, AvatarBone.BackLower, AvatarBone.BackUpper);
            AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.Neck);
            AddMotor(ragdoll, AvatarBone.Neck, AvatarBone.Head);
            AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.CollarLeft);
            AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.CollarRight);
            AddMotor(ragdoll, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft);
            AddMotor(ragdoll, AvatarBone.CollarRight, AvatarBone.ShoulderRight);
            AddMotor(ragdoll, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft);
            AddMotor(ragdoll, AvatarBone.ShoulderRight, AvatarBone.ElbowRight);
            AddMotor(ragdoll, AvatarBone.ElbowLeft, AvatarBone.WristLeft);
            AddMotor(ragdoll, AvatarBone.ElbowRight, AvatarBone.WristRight);
            AddMotor(ragdoll, AvatarBone.Root, AvatarBone.HipLeft);
            AddMotor(ragdoll, AvatarBone.Root, AvatarBone.HipRight);
            AddMotor(ragdoll, AvatarBone.HipLeft, AvatarBone.KneeLeft);
            AddMotor(ragdoll, AvatarBone.HipRight, AvatarBone.KneeRight);
            AddMotor(ragdoll, AvatarBone.KneeLeft, AvatarBone.AnkleLeft);
            AddMotor(ragdoll, AvatarBone.KneeRight, AvatarBone.AnkleRight);

            // ----- Set collision filters.
            // Collisions between connected bones have been disabled with Constraint.CollisionEnabled
            // = false in the joints. We need to disable a few other collisions.
            // Following bodies do not collide with anything. They are only used to connect other
            // bones.
            ragdoll.Bodies[(int)AvatarBone.Neck].CollisionObject.Enabled        = false;
            ragdoll.Bodies[(int)AvatarBone.CollarLeft].CollisionObject.Enabled  = false;
            ragdoll.Bodies[(int)AvatarBone.CollarRight].CollisionObject.Enabled = false;

            // We disable filters for following body pairs because they are usually penetrating each
            // other, which needs to be ignored.
            var filter = simulation.CollisionDomain.CollisionDetection.CollisionFilter as CollisionFilter;

            if (filter != null)
            {
                filter.Set(ragdoll.Bodies[(int)AvatarBone.BackUpper].CollisionObject, ragdoll.Bodies[(int)AvatarBone.ShoulderLeft].CollisionObject, false);
                filter.Set(ragdoll.Bodies[(int)AvatarBone.BackUpper].CollisionObject, ragdoll.Bodies[(int)AvatarBone.ShoulderRight].CollisionObject, false);
            }

            return(ragdoll);
        }
Ejemplo n.º 16
0
    private void InitializeModelAndRagdoll()
    {
      // Load Dude model.
      var contentManager = Services.GetInstance<ContentManager>();
      var dudeModelNode = contentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = dudeModelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the world space pose of the whole ragdoll. And copy the bone poses of the
      // current skeleton pose.
      _ragdoll.Pose = _meshNode.PoseWorld;
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      // Disable sleeping.
      foreach (var body in _ragdoll.Bodies)
      {
        if (body != null)
        {
          body.CanSleep = false;
          //body.CollisionResponseEnabled = false;
        }
      }

      // The pelvis bone (index 1) is updated directly from the Kinect hip center.
      _ragdoll.Bodies[1].MotionType = MotionType.Kinematic;

      // In this sample we use a passive ragdoll where we need joints to hold the
      // limbs together and limits to restrict angular movement.
      _ragdoll.EnableJoints();
      _ragdoll.EnableLimits();

      // Set all motors to constraint motors that only use damping. This adds a damping
      // effect to all ragdoll limbs.
      foreach (RagdollMotor motor in _ragdoll.Motors)
      {
        if (motor != null)
        {
          motor.Mode = RagdollMotorMode.Constraint;
          motor.ConstraintDamping = 100;
          motor.ConstraintSpring = 0;
        }
      }
      _ragdoll.EnableMotors();

      // Add rigid bodies and the constraints of the ragdoll to the simulation.
      _ragdoll.AddToSimulation(Simulation);
    }
Ejemplo n.º 17
0
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

              if (_avatarPose == null)
              {
            if (_avatarRenderer.State == AvatarRendererState.Ready)
            {
              _avatarPose = new AvatarPose(_avatarRenderer);
              _targetPose = SkeletonPose.Create(_avatarPose.SkeletonPose.Skeleton);

              // Create a ragdoll for the avatar.
              _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation);

              // Set the world space pose of the whole ragdoll. And copy the bone poses
              // of the current skeleton pose.
              _ragdoll.Pose = _pose;
              _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose);

              // To simplify collision checks, we need a simple way to determine whether
              // a rigid body belongs to the ragdoll.
              // --> Set RigidBody.UserData = _ragdoll.
              // (Alternatively we could also set specific names for the rigid bodies,
              // or we could assign the collision objects to a certain collision group.)
              foreach (var body in _ragdoll.Bodies)
            if (body != null)
              body.UserData = _ragdoll;

              // Add rigid bodies and constraints to the simulation.
              _ragdoll.AddToSimulation(Simulation);

              // Start by playing the key frame animation.
              SwitchMode(RagdollMode.Mode1);

              // The facial expression can be applied directly to the _avatarPose.
              _animationController0 = AnimationService.StartAnimation(_expressionAnimation, _avatarPose);

              // The skeletal animation is applied to the _targetPose. The _targetPose
              // is used to drive the ragdoll. (See end of method.)
              _animationController1 = AnimationService.StartAnimation(_skeletonAnimation, (IAnimatableProperty<SkeletonPose>)_targetPose);
            }

            return;
              }

              if (InputService.IsPressed(Buttons.A, false, PlayerIndex.One))
            SwitchMode(RagdollMode.Mode1);
              else if (InputService.IsPressed(Buttons.B, false, PlayerIndex.One))
            SwitchMode(RagdollMode.Mode2);
              else if (InputService.IsPressed(Buttons.X, false, PlayerIndex.One))
            SwitchMode(RagdollMode.Mode3);
              else if (InputService.IsPressed(Buttons.Y, false, PlayerIndex.One))
            SwitchMode(RagdollMode.Mode4);

              if (_mode == RagdollMode.Mode1 || _mode == RagdollMode.Mode2)
              {
            // The ragdoll plays a certain animation. Check whether the character was
            // hit by a ball.
            foreach (var contactConstraint in Simulation.ContactConstraints)
            {
              if (contactConstraint.BodyA.UserData == _ragdoll && contactConstraint.BodyB.Name.StartsWith("Ball")
              || contactConstraint.BodyB.UserData == _ragdoll && contactConstraint.BodyA.Name.StartsWith("Ball"))
              {
            // Switch to the "Passive Ragdoll" mode and let the character collapse.
            SwitchMode(RagdollMode.Mode3);

            // Hint: You can read contactConstraint.LinearConstraintImpulse.Length to
            // determine the strength of the impact.
              }
            }
              }

              switch (_mode)
              {
            case RagdollMode.Mode1:
              // In mode 1 we update the rigid bodies directly.
              _ragdoll.UpdateBodiesFromSkeleton(_targetPose);
              break;
            case RagdollMode.Mode2:
              // In mode 2 velocity motors update the rigid bodies.
              _ragdoll.DriveToPose(_targetPose, gameTime.ElapsedGameTime);
              break;
            case RagdollMode.Mode3:
              // In mode 3 we don't have to update the rigid bodies.
              break;
            case RagdollMode.Mode4:
              // In mode 4 constraint motors control the joints of the ragdoll.
              _ragdoll.DriveToPose(_targetPose, gameTime.ElapsedGameTime);
              break;
              }

              // Copy the skeleton pose. (_avatarPose stores the skeleton pose which is
              // being rendered.)
              _ragdoll.UpdateSkeletonFromBodies(_avatarPose.SkeletonPose);
        }
Ejemplo n.º 18
0
    public KinematicRagdollSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;

      // Add game objects which allow to shoot balls and grab rigid bodies.
      _ballShooterObject = new BallShooterObject(Services) { Speed = 10 };
      GameObjectService.Objects.Add(_ballShooterObject);
      _grabObject = new GrabObject(Services);
      GameObjectService.Objects.Add(_grabObject);

      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(ConstantsF.Pi));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      var animations = _meshNode.Mesh.Animations;
      var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
      {
        LoopBehavior = LoopBehavior.Cycle,
        Duration = TimeSpan.MaxValue,
      };
      var animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_meshNode.SkeletonPose);
      animationController.UpdateAndApply();

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the world space pose of the whole ragdoll. And copy the bone poses of the
      // current skeleton pose.
      _ragdoll.Pose = _meshNode.PoseWorld;
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      // Set all bodies to kinematic -  they should not be affected by forces.
      foreach (var body in _ragdoll.Bodies)
      {
        if (body != null)
        {
          body.MotionType = MotionType.Kinematic;
        }
      }

      // Set all motors to velocity motors. Velocity motors change RigidBody.LinearVelocity
      // RigidBody.AngularVelocity to move the rigid bodies. 
      foreach (RagdollMotor motor in _ragdoll.Motors)
      {
        if (motor != null)
        {
          motor.Mode = RagdollMotorMode.Velocity;
        }
      }
      _ragdoll.EnableMotors();

      // In this sample, we do not need joints or limits.
      _ragdoll.DisableJoints();
      _ragdoll.DisableLimits();

      // Add ragdoll rigid bodies to the simulation.
      _ragdoll.AddToSimulation(Simulation);

      // Add a rigid body.
      var box = new RigidBody(new BoxShape(0.4f, 0.4f, 0.4f))
      {
        Name = "Box",
        Pose = new Pose(new Vector3F(0, 3, 0)),
      };
      Simulation.RigidBodies.Add(box);
    }
Ejemplo n.º 19
0
    private Ragdoll CreateRagdoll(MeshNode meshNode)
    {
      var mesh = meshNode.Mesh;
      var skeleton = mesh.Skeleton;

      // Extract the vertices from the mesh sorted per bone.
      var verticesPerBone = new List<Vector3F>[skeleton.NumberOfBones];
      // Also get the AABB of the model.
      Aabb? aabb = null;
      foreach (var submesh in mesh.Submeshes)
      {
        // Get vertex element info.
        var vertexDeclaration = submesh.VertexBuffer.VertexDeclaration;
        var vertexElements = vertexDeclaration.GetVertexElements();

        // Get the vertex positions.
        var positionElement = vertexElements.First(e => e.VertexElementUsage == VertexElementUsage.Position);
        if (positionElement.VertexElementFormat != VertexElementFormat.Vector3)
          throw new NotSupportedException("For vertex positions only VertexElementFormat.Vector3 is supported.");
        var positions = new Vector3[submesh.VertexCount];
        submesh.VertexBuffer.GetData(
          submesh.StartVertex * vertexDeclaration.VertexStride + positionElement.Offset,
          positions,
          0,
          submesh.VertexCount,
          vertexDeclaration.VertexStride);

        // Get the bone indices.
        var boneIndexElement = vertexElements.First(e => e.VertexElementUsage == VertexElementUsage.BlendIndices);
        if (boneIndexElement.VertexElementFormat != VertexElementFormat.Byte4)
          throw new NotSupportedException();
        var boneIndicesArray = new Byte4[submesh.VertexCount];
        submesh.VertexBuffer.GetData(
          submesh.StartVertex * vertexDeclaration.VertexStride + boneIndexElement.Offset,
          boneIndicesArray,
          0,
          submesh.VertexCount,
          vertexDeclaration.VertexStride);

        // Get the bone weights.
        var boneWeightElement = vertexElements.First(e => e.VertexElementUsage == VertexElementUsage.BlendWeight);
        if (boneWeightElement.VertexElementFormat != VertexElementFormat.Vector4)
          throw new NotSupportedException();
        var boneWeightsArray = new Vector4[submesh.VertexCount];
        submesh.VertexBuffer.GetData(
          submesh.StartVertex * vertexDeclaration.VertexStride + boneWeightElement.Offset,
          boneWeightsArray,
          0,
          submesh.VertexCount,
          vertexDeclaration.VertexStride);

        // Sort the vertices per bone. 
        for (int i = 0; i < submesh.VertexCount; i++)
        {
          var vertex = (Vector3F)positions[i];

          // Here, we only check the first bone index. We could also check the
          // bone weights to add the vertex to all bone vertex lists where the 
          // weight is high...
          Vector4 boneIndices = boneIndicesArray[i].ToVector4();
          //Vector4 boneWeights = boneWeightsArray[i];
          int boneIndex = (int)boneIndices.X;
          if (verticesPerBone[boneIndex] == null)
            verticesPerBone[boneIndex] = new List<Vector3F>();
          verticesPerBone[boneIndex].Add(vertex);

          // Add vertex to AABB.
          if (aabb == null)
            aabb = new Aabb(vertex, vertex);
          else
            aabb.Value.Grow(vertex);
        }
      }

      // We create a body for each bone with vertices.
      int numberOfBodies = verticesPerBone.Count(vertices => vertices != null);

      // We use the same mass properties for all bodies. This is not realistic but more stable 
      // because large mass differences or thin bodies (arms!) are less stable.
      // We use the mass properties of sphere proportional to the size of the model.
      const float totalMass = 80;     // The total mass of the ragdoll.
      var massFrame = MassFrame.FromShapeAndMass(new SphereShape(aabb.Value.Extent.Y / 8), Vector3F.One, totalMass / numberOfBodies, 0.1f, 1);

      var material = new UniformMaterial();

      Ragdoll ragdoll = new Ragdoll();
      for (int boneIndex = 0; boneIndex < skeleton.NumberOfBones; boneIndex++)
      {
        var boneVertices = verticesPerBone[boneIndex];
        if (boneVertices != null)
        {
          var bindPoseInverse = (Pose)skeleton.GetBindPoseAbsoluteInverse(boneIndex);

          // Compute bounding capsule.
          //float radius;
          //float height;
          //Pose pose;
          //GeometryHelper.ComputeBoundingCapsule(boneVertices, out radius, out height, out pose);
          //Shape shape = new TransformedShape(new GeometricObject(new CapsuleShape(radius, height), pose));

          // Compute convex hull.
          var points = GeometryHelper.CreateConvexHull(boneVertices, 32, 0).ToTriangleMesh().Vertices;
          Shape shape = new ConvexHullOfPoints(points.Count > 0 ? points : boneVertices);

          ragdoll.Bodies.Add(new RigidBody(shape, massFrame, material));
          ragdoll.BodyOffsets.Add(bindPoseInverse);
        }
        else
        {
          ragdoll.Bodies.Add(null);
          ragdoll.BodyOffsets.Add(Pose.Identity);
        }
      }

      return ragdoll;
    }
Ejemplo n.º 20
0
    internal static void CorrectWorldSpacePose(MeshNode meshNode, Ragdoll ragdoll)
    {
      // Notes:
      // The Ragdoll class is simply a container for rigid bodies, joints, limits, motors, etc.
      // It has a Ragdoll.Pose property that determines the world space pose of the model.
      // The Ragdoll class does not update this property. It only reads it.
      // Let's say the ragdoll and model are created at the world space origin. Then the user
      // grabs the ragdoll and throws it 100 units away. Then the Ragdoll.Pose (and the root bone)
      // is still at the origin and the first body (the pelvis) is 100 units away. 
      // You can observe this if you comment out this method and look at the debug rendering of 
      // the skeleton.
      // To avoid this we correct the Ragdoll.Pose and make sure that it is always near the 
      // pelvis bone.

      int pelvis = meshNode.SkeletonPose.Skeleton.GetIndex("Pelvis");
      SrtTransform pelvisBindPoseAbsoluteInverse = meshNode.SkeletonPose.Skeleton.GetBindPoseAbsoluteInverse(pelvis);
      ragdoll.Pose = ragdoll.Bodies[pelvis].Pose * ragdoll.BodyOffsets[pelvis].Inverse * (Pose)pelvisBindPoseAbsoluteInverse;
      meshNode.PoseWorld = ragdoll.Pose;
    }
Ejemplo n.º 21
0
        protected override void LoadContent()
        {
            // Add a ground plane to the simulation.
              Simulation.RigidBodies.Add(
            new RigidBody(new PlaneShape(Vector3F.UnitY, 0))
            {
              MotionType = MotionType.Static
            });

              // Load model.
              _model = Game.Content.Load<Model>("Dude");
              var additionalData = (Dictionary<string, object>)_model.Tag;
              var skeleton = (Skeleton)additionalData["Skeleton"];

              // Create the two skeleton poses.
              _targetSkeletonPose = SkeletonPose.Create(skeleton);
              _actualSkeletonPose = SkeletonPose.Create(skeleton);

              // Animate the _targetSkeletonPose.
              var animations = (Dictionary<string, SkeletonKeyFrameAnimation>)additionalData["Animations"];
              var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
              {
            LoopBehavior = LoopBehavior.Cycle,
            Duration = TimeSpan.MaxValue,
              };
              AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_targetSkeletonPose);

              // Create a ragdoll for the Dude model.
              _ragdoll = new Ragdoll();
              DudeRagdollCreator.Create(_targetSkeletonPose, _ragdoll, Simulation);

              // Set the world space pose of the whole ragdoll. And copy the bone poses of the
              // current skeleton pose.
              _ragdoll.Pose = _pose;
              _ragdoll.UpdateBodiesFromSkeleton(_targetSkeletonPose);

              // In this sample we use an active ragdoll. We need joints because constraint ragdoll
              // motors only affect the body rotations.
              _ragdoll.EnableJoints();

              // We disable limits. If limits are enabled, the ragdoll could get unstable if
              // the animation tries to move a limb beyond an allowed limit. (This happens if
              // a pose in the animation violates one of our limits.)
              _ragdoll.DisableLimits();

              // Set all motors to constraint motors. Constraint motors are like springs that
              // rotate the limbs to a target position.
              foreach (RagdollMotor motor in _ragdoll.Motors)
              {
            if (motor != null)
            {
              motor.Mode = RagdollMotorMode.Constraint;
              motor.ConstraintDamping = 10000;
              motor.ConstraintSpring = 100000;
            }
              }
              _ragdoll.EnableMotors();

              // Add rigid bodies and the constraints of the ragdoll to the simulation.
              _ragdoll.AddToSimulation(Simulation);

              base.LoadContent();
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Adds a TwistSwingLimit between the specified bones. 
        /// </summary>
        /// <param name="ragdoll">The ragdoll.</param>
        /// <param name="parent">The parent bone.</param>
        /// <param name="child">The child bone.</param>
        /// <param name="parentAnchorOrientationLocal">The constraint anchor orientation relative to the parent bone.</param>
        /// <param name="childAnchorOrientationLocal">The constraint anchor orientation relative to the child bone.</param>
        /// <param name="minimum">The minimum limits (twist/swing/swing).</param>
        /// <param name="maximum">The maximum limits (twist/swing/swing).</param>
        private static void AddTwistSwingLimit(Ragdoll ragdoll, int parent, int child, Matrix33F parentAnchorOrientationLocal, Matrix33F childAnchorOrientationLocal, Vector3F minimum, Vector3F maximum)
        {
            var childBody = ragdoll.Bodies[child];
              var childOffset = ragdoll.BodyOffsets[child];
              var parentBody = ragdoll.Bodies[parent];
              var parentOffset = ragdoll.BodyOffsets[parent];

              var limit = new TwistSwingLimit
              {
            BodyA = parentBody,
            BodyB = childBody,
            AnchorOrientationALocal = parentOffset.Orientation.Transposed * parentAnchorOrientationLocal,
            AnchorOrientationBLocal = childOffset.Orientation.Transposed * childAnchorOrientationLocal,
            Minimum = minimum,
            Maximum = maximum,
            ErrorReduction = 0.2f,
            Softness = 0.001f
              };
              ragdoll.Limits.Add(limit);
        }
Ejemplo n.º 23
0
    public override void Update(GameTime gameTime)
    {
      if (_avatarPose == null)
      {
        if (_avatarRenderer.State == AvatarRendererState.Ready)
        {
          _avatarPose = new AvatarPose(_avatarRenderer);

          // Create a ragdoll for the avatar.
          _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation);

          // Set the world space pose of the whole ragdoll. And copy the bone poses of the
          // current skeleton pose.
          _ragdoll.Pose = _pose;
          _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose);

          // In this sample we use a passive ragdoll where we need joints to hold the
          // limbs together and limits to control the angular movement.
          _ragdoll.EnableJoints();
          _ragdoll.EnableLimits();

          // Set all motors to constraint motors that only use damping. This adds a damping
          // effect to all ragdoll limbs.
          foreach (RagdollMotor motor in _ragdoll.Motors)
          {
            if (motor != null)
            {
              motor.Mode = RagdollMotorMode.Constraint;
              motor.ConstraintDamping = 5;
              motor.ConstraintSpring = 0;
            }
          }
          _ragdoll.EnableMotors();

          // Add rigid bodies and the constraints of the ragdoll to the simulation.
          _ragdoll.AddToSimulation(Simulation);
        }
      }
      else
      {
        // Copy skeleton pose from ragdoll.
        _ragdoll.UpdateSkeletonFromBodies(_avatarPose.SkeletonPose);
      }

      // Render rigid bodies.
      _debugRenderer.Clear();
      foreach (var body in Simulation.RigidBodies)
        if (!(body.Shape is EmptyShape))  // Do not draw dummy bodies which might be used by the ragdoll.
          _debugRenderer.DrawObject(body, Color.Black, true, false);
    }
        private void InitializeModel()
        {
            // Load dude model including the skeleton.
              _model = Game.Content.Load<Model>("Dude");
              var additionalData = (Dictionary<string, object>)_model.Tag;
              var ragdollSkeleton = (DRSkeleton)additionalData["Skeleton"];
              _skeletonPose = SkeletonPose.Create(ragdollSkeleton);

              // Create a ragdoll for the Dude model.
              _ragdoll = new Ragdoll();
              DudeRagdollCreator.Create(_skeletonPose, _ragdoll, Simulation, 0.57f);

              // Set the world space pose of the whole ragdoll. And copy the bone poses of the
              // current skeleton pose.
              _ragdoll.UpdateBodiesFromSkeleton(_skeletonPose);

              // Disable sleeping.
              foreach (var body in _ragdoll.Bodies)
              {
            if (body != null)
              body.CanSleep = false;
              }

              // The pelvis bone (index 1) is updated directly from the Kinect hip center.
              _ragdoll.Bodies[1].MotionType = MotionType.Kinematic;

              // In this sample we use a passive ragdoll where we need joints to hold the
              // limbs together and limits to restrict angular movement.
              _ragdoll.EnableJoints();
              _ragdoll.EnableLimits();

              // Set all motors to constraint motors that only use damping. This adds a damping
              // effect to all ragdoll limbs.
              foreach (RagdollMotor motor in _ragdoll.Motors)
              {
            if (motor != null)
            {
              motor.Mode = RagdollMotorMode.Constraint;
              motor.ConstraintDamping = 100;
              motor.ConstraintSpring = 0;
            }
              }
              _ragdoll.EnableMotors();

              // Add rigid bodies and the constraints of the ragdoll to the simulation.
              _ragdoll.AddToSimulation(Simulation);
        }
Ejemplo n.º 25
0
        private static void AddTwistSwingLimit(Ragdoll ragdoll, Skeleton skeleton, AvatarBone parentBone, AvatarBone childBone, Matrix33F orientationA, Matrix33F orientationB, Vector3F minimum, Vector3F maximum)
        {
            int parentIndex = (int)parentBone;
              int childIndex = (int)childBone;

              // The difficult part is to define the constraint anchor orientation.
              // Here is how we do it:
              // When we look at the front side of an Avatar in bind pose, the x-axis is parallel
              // to the arms. y points up and z is normal to the those axes.
              //
              // To define orientationA/B:
              // The anchor x-axis is the twist axis. That means, this is already the correct axis
              // for the hands (wrist joints) and orientationA/B are therefore Matrix33F.Identity.
              // For the Head, the twist axis must point up. Therefore orientationA/B must be a 90°
              // rotation about z to rotate the twist axis up.
              // For the shoulder-elbow connection, orientationA is Matrix.Identity. The swing cone must
              // not be parallel to the arm axis (because the elbow cannot bend backwards). Therefore,
              // orientationB defines a rotation that rotates the twist axis (= swing cone center) to the
              // front.
              //
              // To define AnchorOrientationALocal/AnchorOrientationBLocal:
              // AnchorOrientationALocal must be a rotation matrix that transforms a vector from local
              // constraint anchor space to local body space of A.
              // orientationA defines the constraint anchor orientation in model space.
              // With jointPosesAbsolute[boneAIndex].Orientation.Transposed, we convert from model space
              // to joint space. With ragdoll.BodyOffsets[boneAIndex].Orientation.Transposed, we convert from joint
              // space to body space. The combined rotation matrix converts from constraint anchor space
              // to body space.

              var limit = new TwistSwingLimit
              {
            BodyA = ragdoll.Bodies[parentIndex],
            BodyB = ragdoll.Bodies[childIndex],
            AnchorOrientationALocal = ragdoll.BodyOffsets[parentIndex].Orientation.Transposed * skeleton.GetBindPoseAbsoluteInverse(parentIndex).Rotation.ToRotationMatrix33() * orientationA,
            AnchorOrientationBLocal = ragdoll.BodyOffsets[childIndex].Orientation.Transposed * skeleton.GetBindPoseAbsoluteInverse(childIndex).Rotation.ToRotationMatrix33() * orientationB,
            Minimum = minimum,
            Maximum = maximum,
            ErrorReduction = 0.2f,
            Softness = 0.001f
              };
              ragdoll.Limits[childIndex] = limit;
        }
        protected override void LoadContent()
        {
            // Load model and start animation.
              _model = Game.Content.Load<Model>("Dude");
              var additionalData = (Dictionary<string, object>)_model.Tag;
              var skeleton = (Skeleton)additionalData["Skeleton"];
              _skeletonPose = SkeletonPose.Create(skeleton);
              var animations = (Dictionary<string, SkeletonKeyFrameAnimation>)additionalData["Animations"];
              var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
              {
            LoopBehavior = LoopBehavior.Cycle,
            Duration = TimeSpan.MaxValue,
              };
              AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_skeletonPose);

              // Create a ragdoll for the Dude model.
              _ragdoll = new Ragdoll();
              DudeRagdollCreator.Create(_skeletonPose, _ragdoll, Simulation);

              // Set the world space pose of the whole ragdoll.
              _ragdoll.Pose = _pose;
              // And copy the bone poses of the current skeleton pose.
              _ragdoll.UpdateBodiesFromSkeleton(_skeletonPose);

              foreach(var body in _ragdoll.Bodies)
              {
            if (body != null)
            {
              // Set all bodies to kinematic - they should not be affected by forces.
              body.MotionType = MotionType.Kinematic;

              // Disable collision response.
              body.CollisionResponseEnabled = false;
            }
              }

              // In this sample, we do not need joints, limits or motors.
              _ragdoll.DisableJoints();
              _ragdoll.DisableLimits();
              _ragdoll.DisableMotors();

              // Add ragdoll rigid bodies to the simulation.
              _ragdoll.AddToSimulation(Simulation);

              base.LoadContent();
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Creates a <see cref="Ragdoll"/> for an Xbox LIVE Avatar. (Only available on Xbox 360.)
        /// </summary>
        /// <param name="skeleton">The skeleton of the Xbox LIVE Avatar.</param>
        /// <param name="simulation">The simulation.</param>
        /// <returns>The avatar ragdoll.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="skeleton"/> or <paramref name="simulation"/> is 
        /// <see langword="null"/>.
        /// </exception>
        /// <remarks>
        /// This method is available only in the Xbox 360 build of the 
        /// DigitalRune.Physics.Specialized.dll.
        /// </remarks>
        public static Ragdoll CreateAvatarRagdoll(Skeleton skeleton, Simulation simulation)
        {
            if (skeleton == null)
            throw new ArgumentNullException("skeleton");
              if (simulation == null)
            throw new ArgumentNullException("simulation");

              var ragdoll = new Ragdoll();

              // The lists ragdoll.Bodies, ragdoll.BodyOffsets and _motors contain one entry per bone - even if there
              // is no RigidBody for this bone. - This wastes memory but simplifies the code.
              for (int i = 0; i < AvatarRenderer.BoneCount; i++)
              {
            ragdoll.Bodies.Add(null);
            ragdoll.BodyOffsets.Add(Pose.Identity);
            ragdoll.Joints.Add(null);
            ragdoll.Limits.Add(null);
            ragdoll.Motors.Add(null);
              }

              // ----- Create bodies.
              // We use the same mass for all bodies. This is not physically correct but it makes the
              // simulation more stable, for several reasons:
              // - It is better to avoid large mass differences. Therefore, all limbs have the same mass.
              // - Capsule shapes have a low inertia value about their height axis. This causes instability
              //   and it is better to use larger inertia values.
              var massFrame = MassFrame.FromShapeAndMass(new SphereShape(0.2f), Vector3F.One, 4, 0.1f, 1);

              // Use standard material.
              var material = new UniformMaterial();

              // Create rigid bodies for the important bones. The shapes have been manually adapted to
              // produce useful results for thin and overweight avatars.
              // Without offset, the bodies are centered at the joint. ragdoll.BodyOffsets stores an offset pose
              // for each body. Instead, we could use TransformedShape but we can easily handle that
              // ourselves.
              // The collar bones are special, they use dummy shapes and are only used to connect the
              // shoulder bones.
              ragdoll.Bodies[(int)AvatarBone.Root] = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.Root] = new Pose(new Vector3F(0, -0.08f, -0.01f), QuaternionF.CreateRotationX(-0.0f));
              ragdoll.Bodies[(int)AvatarBone.BackLower] = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.BackLower] = new Pose(new Vector3F(0, 0.08f, -0.01f), QuaternionF.CreateRotationX(-0.0f));
              ragdoll.Bodies[(int)AvatarBone.BackUpper] = new RigidBody(new BoxShape(0.22f, 0.16f, 0.16f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.BackUpper] = new Pose(new Vector3F(0, 0.08f, -0.01f), QuaternionF.CreateRotationX(-0.1f));
              ragdoll.Bodies[(int)AvatarBone.Neck] = new RigidBody(new CapsuleShape(0.04f, 0.09f), massFrame, material);
              ragdoll.Bodies[(int)AvatarBone.Head] = new RigidBody(new SphereShape(0.15f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.Head] = new Pose(new Vector3F(0, 0.1f, 0));
              ragdoll.Bodies[(int)AvatarBone.CollarLeft] = new RigidBody(Shape.Empty, massFrame, material);
              ragdoll.Bodies[(int)AvatarBone.CollarRight] = new RigidBody(Shape.Empty, massFrame, material);
              ragdoll.Bodies[(int)AvatarBone.ShoulderLeft] = new RigidBody(new CapsuleShape(0.04f, 0.25f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.ShoulderLeft] = new Pose(new Vector3F(0.08f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
              ragdoll.Bodies[(int)AvatarBone.ShoulderRight] = new RigidBody(new CapsuleShape(0.04f, 0.25f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.ShoulderRight] = new Pose(new Vector3F(-0.08f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
              ragdoll.Bodies[(int)AvatarBone.ElbowLeft] = new RigidBody(new CapsuleShape(0.04f, 0.21f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.ElbowLeft] = new Pose(new Vector3F(0.06f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
              ragdoll.Bodies[(int)AvatarBone.ElbowRight] = new RigidBody(new CapsuleShape(0.04f , 0.21f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.ElbowRight] = new Pose(new Vector3F(-0.06f, 0, -0.02f), QuaternionF.CreateRotationZ(ConstantsF.PiOver2));
              ragdoll.Bodies[(int)AvatarBone.WristLeft] = new RigidBody(new BoxShape(0.1f, 0.04f, 0.1f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.WristLeft] = new Pose(new Vector3F(0.06f, -0.02f, -0.01f), QuaternionF.CreateRotationZ(0.0f));
              ragdoll.Bodies[(int)AvatarBone.WristRight] = new RigidBody(new BoxShape(0.1f, 0.04f, 0.1f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.WristRight] = new Pose(new Vector3F(-0.06f, -0.02f, -0.01f), QuaternionF.CreateRotationZ(0.0f));
              ragdoll.Bodies[(int)AvatarBone.HipLeft] = new RigidBody(new CapsuleShape(0.06f, 0.34f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.HipLeft] = new Pose(new Vector3F(0, -0.14f, -0.02f), QuaternionF.CreateRotationX(0.1f));
              ragdoll.Bodies[(int)AvatarBone.HipRight] = new RigidBody(new CapsuleShape(0.06f, 0.34f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.HipRight] = new Pose(new Vector3F(0, -0.14f, -0.02f), QuaternionF.CreateRotationX(0.1f));
              ragdoll.Bodies[(int)AvatarBone.KneeLeft] = new RigidBody(new CapsuleShape(0.06f, 0.36f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.KneeLeft] = new Pose(new Vector3F(0, -0.18f, -0.04f), QuaternionF.CreateRotationX(0.1f));
              ragdoll.Bodies[(int)AvatarBone.KneeRight] = new RigidBody(new CapsuleShape(0.06f, 0.36f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.KneeRight] = new Pose(new Vector3F(0, -0.18f, -0.04f), QuaternionF.CreateRotationX(0.1f));
              ragdoll.Bodies[(int)AvatarBone.AnkleLeft] = new RigidBody(new BoxShape(0.1f, 0.06f, 0.22f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.AnkleLeft] = new Pose(new Vector3F(0, -0.07f, 0.05f), QuaternionF.CreateRotationZ(0));
              ragdoll.Bodies[(int)AvatarBone.AnkleRight] = new RigidBody(new BoxShape(0.1f, 0.06f, 0.22f), massFrame, material);
              ragdoll.BodyOffsets[(int)AvatarBone.AnkleRight] = new Pose(new Vector3F(0, -0.07f, 0.05f), QuaternionF.CreateRotationZ(0));

              // ----- Add joint constraints.
              const float jointErrorReduction = 0.2f;
              const float jointSoftness = 0.0001f;
              AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.BackLower, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.BackLower, AvatarBone.BackUpper, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.Neck, 0.6f, 0.000001f);
              AddJoint(ragdoll, skeleton, AvatarBone.Neck, AvatarBone.Head, 0.6f, 0.000001f);
              AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarLeft, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarRight, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.CollarRight, AvatarBone.ShoulderRight, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.ShoulderRight, AvatarBone.ElbowRight, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.ElbowLeft, AvatarBone.WristLeft, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.ElbowRight, AvatarBone.WristRight, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipLeft, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipRight, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.HipLeft, AvatarBone.KneeLeft, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.HipRight, AvatarBone.KneeRight, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.KneeLeft, AvatarBone.AnkleLeft, jointErrorReduction, jointSoftness);
              AddJoint(ragdoll, skeleton, AvatarBone.KneeRight, AvatarBone.AnkleRight, jointErrorReduction, jointSoftness);

              // ----- Add constraint limits.
              // We use TwistSwingLimits to define an allowed twist and swing cone for the joints.
              // Exceptions are the back and knees, where we use AngularLimits to create hinges.
              // (We could also create a hinge with a TwistSwingLimit where the twist axis is the hinge
              // axis and no swing is allowed - but AngularLimits create more stable hinges.)
              // Another exception are the collar bones joint. We use AngularLimits to disallow any
              // rotations.
              AddAngularLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.BackLower,
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackLower).Rotation.Conjugated.ToRotationMatrix33(),
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackLower).Rotation.Conjugated.ToRotationMatrix33(),
            new Vector3F(-0.3f, 0, 0), new Vector3F(0.3f, 0, 0));

              AddAngularLimit(ragdoll, skeleton, AvatarBone.BackLower, AvatarBone.BackUpper,
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackUpper).Rotation.Conjugated.ToRotationMatrix33(),
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.BackUpper).Rotation.Conjugated.ToRotationMatrix33(),
            new Vector3F(-0.3f, 0, 0), new Vector3F(0.4f, 0, 0));

              var rotationZ90Degrees = Matrix33F.CreateRotationZ(ConstantsF.PiOver2);
              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.Neck, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.3f, -0.3f), new Vector3F(+0.1f, +0.3f, +0.3f));

              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Neck, AvatarBone.Head, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.6f, -0.6f), new Vector3F(+0.1f, +0.6f, +0.6f));

              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarLeft,
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarLeft).Rotation.Conjugated.ToRotationMatrix33(),
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarLeft).Rotation.Conjugated.ToRotationMatrix33(),
            new Vector3F(0), new Vector3F(0));

              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.BackUpper, AvatarBone.CollarRight,
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarRight).Rotation.Conjugated.ToRotationMatrix33(),
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.CollarRight).Rotation.Conjugated.ToRotationMatrix33(),
            new Vector3F(0), new Vector3F(0));

              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft, Matrix33F.Identity, Matrix33F.CreateRotationY(0.7f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.CollarRight, AvatarBone.ShoulderRight, Matrix33F.Identity, Matrix33F.CreateRotationY(-0.7f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft, Matrix33F.Identity, Matrix33F.CreateRotationY(1.2f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ShoulderRight, AvatarBone.ElbowRight, Matrix33F.Identity, Matrix33F.CreateRotationY(-1.2f), new Vector3F(-0.7f, -1.2f, -1.2f), new Vector3F(+0.7f, +1.2f, +1.2f));
              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ElbowLeft, AvatarBone.WristLeft, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.7f, -0.7f, -0.7f), new Vector3F(+0.7f, +0.7f, +0.7f));
              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.ElbowRight, AvatarBone.WristRight, Matrix33F.Identity, Matrix33F.Identity, new Vector3F(-0.7f, -0.7f, -0.7f), new Vector3F(+0.7f, +0.7f, +0.7f));
              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipLeft, rotationZ90Degrees, Matrix33F.CreateRotationX(-1.2f) * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 + 0.2f), new Vector3F(-0.1f, -1.5f, -0.7f), new Vector3F(+0.1f, +1.5f, +0.7f));
              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.Root, AvatarBone.HipRight, rotationZ90Degrees, Matrix33F.CreateRotationX(-1.2f) * Matrix33F.CreateRotationZ(ConstantsF.PiOver2 - 0.2f), new Vector3F(-0.1f, -1.5f, -0.7f), new Vector3F(+0.1f, +1.5f, +0.7f));

              AddAngularLimit(ragdoll, skeleton, AvatarBone.HipLeft, AvatarBone.KneeLeft,
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeLeft).Rotation.Conjugated.ToRotationMatrix33(),
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeLeft).Rotation.Conjugated.ToRotationMatrix33(),
            new Vector3F(0, 0, 0), new Vector3F(2.2f, 0, 0));

              AddAngularLimit(ragdoll, skeleton, AvatarBone.HipRight, AvatarBone.KneeRight,
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeRight).Rotation.Conjugated.ToRotationMatrix33(),
            skeleton.GetBindPoseAbsoluteInverse((int)AvatarBone.KneeRight).Rotation.Conjugated.ToRotationMatrix33(),
            new Vector3F(0, 0, 0), new Vector3F(2.2f, 0, 0));

              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.KneeLeft, AvatarBone.AnkleLeft, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.7f, -0.3f), new Vector3F(+0.1f, +0.7f, +0.3f));
              AddTwistSwingLimit(ragdoll, skeleton, AvatarBone.KneeRight, AvatarBone.AnkleRight, rotationZ90Degrees, rotationZ90Degrees, new Vector3F(-0.1f, -0.7f, -0.3f), new Vector3F(+0.1f, +0.7f, +0.3f));

              // ----- Add motors
              // We use QuaternionMotors to create forces that rotate the bones into desired poses.
              // This can be used for damping, spring or animating the ragdoll.
              AddMotor(ragdoll, (AvatarBone)(-1), AvatarBone.Root);
              AddMotor(ragdoll, AvatarBone.Root, AvatarBone.BackLower);
              AddMotor(ragdoll, AvatarBone.BackLower, AvatarBone.BackUpper);
              AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.Neck);
              AddMotor(ragdoll, AvatarBone.Neck, AvatarBone.Head);
              AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.CollarLeft);
              AddMotor(ragdoll, AvatarBone.BackUpper, AvatarBone.CollarRight);
              AddMotor(ragdoll, AvatarBone.CollarLeft, AvatarBone.ShoulderLeft);
              AddMotor(ragdoll, AvatarBone.CollarRight, AvatarBone.ShoulderRight);
              AddMotor(ragdoll, AvatarBone.ShoulderLeft, AvatarBone.ElbowLeft);
              AddMotor(ragdoll, AvatarBone.ShoulderRight, AvatarBone.ElbowRight);
              AddMotor(ragdoll, AvatarBone.ElbowLeft, AvatarBone.WristLeft);
              AddMotor(ragdoll, AvatarBone.ElbowRight, AvatarBone.WristRight);
              AddMotor(ragdoll, AvatarBone.Root, AvatarBone.HipLeft);
              AddMotor(ragdoll, AvatarBone.Root, AvatarBone.HipRight);
              AddMotor(ragdoll, AvatarBone.HipLeft, AvatarBone.KneeLeft);
              AddMotor(ragdoll, AvatarBone.HipRight, AvatarBone.KneeRight);
              AddMotor(ragdoll, AvatarBone.KneeLeft, AvatarBone.AnkleLeft);
              AddMotor(ragdoll, AvatarBone.KneeRight, AvatarBone.AnkleRight);

              // ----- Set collision filters.
              // Collisions between connected bones have been disabled with Constraint.CollisionEnabled
              // = false in the joints. We need to disable a few other collisions.
              // Following bodies do not collide with anything. They are only used to connect other
              // bones.
              ragdoll.Bodies[(int)AvatarBone.Neck].CollisionObject.Enabled = false;
              ragdoll.Bodies[(int)AvatarBone.CollarLeft].CollisionObject.Enabled = false;
              ragdoll.Bodies[(int)AvatarBone.CollarRight].CollisionObject.Enabled = false;

              // We disable filters for following body pairs because they are usually penetrating each
              // other, which needs to be ignored.
              var filter = simulation.CollisionDomain.CollisionDetection.CollisionFilter as CollisionFilter;
              if (filter != null)
              {
            filter.Set(ragdoll.Bodies[(int)AvatarBone.BackUpper].CollisionObject, ragdoll.Bodies[(int)AvatarBone.ShoulderLeft].CollisionObject, false);
            filter.Set(ragdoll.Bodies[(int)AvatarBone.BackUpper].CollisionObject, ragdoll.Bodies[(int)AvatarBone.ShoulderRight].CollisionObject, false);
              }

              return ragdoll;
        }
Ejemplo n.º 28
0
        private static void AddAngularLimit(Ragdoll ragdoll, Skeleton skeleton, AvatarBone parentBone, AvatarBone childBone, Matrix33F orientationA, Matrix33F orientationB, Vector3F minimum, Vector3F maximum)
        {
            // Similar to AddTwistSwingLimit

              int parentIndex = (int)parentBone;
              int childIndex = (int)childBone;

              var limit = new AngularLimit
              {
            BodyA = ragdoll.Bodies[parentIndex],
            BodyB = ragdoll.Bodies[childIndex],
            AnchorOrientationALocal = ragdoll.BodyOffsets[parentIndex].Orientation.Transposed * skeleton.GetBindPoseAbsoluteInverse(parentIndex).Rotation.ToRotationMatrix33() * orientationA,
            AnchorOrientationBLocal = ragdoll.BodyOffsets[childIndex].Orientation.Transposed * skeleton.GetBindPoseAbsoluteInverse(childIndex).Rotation.ToRotationMatrix33() * orientationB,
            Minimum = minimum,
            Maximum = maximum,
            ErrorReduction = new Vector3F(0.2f),
            Softness = new Vector3F(0.001f)
              };
              ragdoll.Limits[childIndex] = limit;
        }
Ejemplo n.º 29
0
        protected override void LoadContent()
        {
            // Add a ground plane to the simulation.
              Simulation.RigidBodies.Add(
            new RigidBody(new PlaneShape(Vector3F.UnitY, 0))
            {
              MotionType = MotionType.Static
            });

              // Load model and start animation.
              _model = Game.Content.Load<Model>("Dude");
              var additionalData = (Dictionary<string, object>)_model.Tag;
              var skeleton = (Skeleton)additionalData["Skeleton"];
              _skeletonPose = SkeletonPose.Create(skeleton);
              var animations = (Dictionary<string, SkeletonKeyFrameAnimation>)additionalData["Animations"];
              var loopingAnimation = new AnimationClip<SkeletonPose>(animations.Values.First())
              {
            LoopBehavior = LoopBehavior.Cycle,
            Duration = TimeSpan.MaxValue,
              };
              var animationController = AnimationService.StartAnimation(loopingAnimation, (IAnimatableProperty)_skeletonPose);
              animationController.UpdateAndApply();

              // Create a ragdoll for the Dude model.
              _ragdoll = new Ragdoll();
              DudeRagdollCreator.Create(_skeletonPose, _ragdoll, Simulation);

              // Set the world space pose of the whole ragdoll. And copy the bone poses of the
              // current skeleton pose.
              _ragdoll.Pose = _pose;
              _ragdoll.UpdateBodiesFromSkeleton(_skeletonPose);

              // Set all bodies to kinematic -  they should not be affected by forces.
              foreach (var body in _ragdoll.Bodies)
              {
            if (body != null)
            {
              body.MotionType = MotionType.Kinematic;
            }
              }

              // Set all motors to velocity motors. Velocity motors change RigidBody.LinearVelocity
              // RigidBody.AngularVelocity to move the rigid bodies.
              foreach (RagdollMotor motor in _ragdoll.Motors)
              {
            if (motor != null)
            {
              motor.Mode = RagdollMotorMode.Velocity;
            }
              }
              _ragdoll.EnableMotors();

              // In this sample, we do not need joints or limits.
              _ragdoll.DisableJoints();
              _ragdoll.DisableLimits();

              // Add ragdoll rigid bodies to the simulation.
              _ragdoll.AddToSimulation(Simulation);

              base.LoadContent();
        }
Ejemplo n.º 30
0
        private static void AddJoint(Ragdoll ragdoll, Skeleton skeleton, AvatarBone parentBone, AvatarBone childBone, float errorReduction, float softness)
        {
            int parentIndex = (int)parentBone;
              int childIndex = (int)childBone;

              // To define AnchorPositionALocal/AnchorPositionBLocal:
              // To get the AnchorPositionALocal we apply jointPosesAbsolute[indexA].Inverse to
              // convert the joint pose from model space into the joints space of parentBone. Then we apply
              // ragdoll.BodyOffsets[boneAIndex].Inverse to convert from joint space to body space. The result is
              // the joint position of B in body space of A.
              // To get AnchorPositionBLocal, we only have to apply the inverse offset.

              BallJoint joint = new BallJoint
              {
            BodyA = ragdoll.Bodies[parentIndex],
            BodyB = ragdoll.Bodies[childIndex],
            CollisionEnabled = false,
            AnchorPositionALocal = (ragdoll.BodyOffsets[parentIndex].Inverse * skeleton.GetBindPoseAbsoluteInverse(parentIndex) * skeleton.GetBindPoseAbsoluteInverse(childIndex).Inverse).Translation,
            AnchorPositionBLocal = ragdoll.BodyOffsets[childIndex].Inverse.Position,
            ErrorReduction = errorReduction,
            Softness = softness,
              };
              ragdoll.Joints[childIndex] = joint;
        }
Ejemplo n.º 31
0
        private static void AddMotor(Ragdoll ragdoll, AvatarBone parentBone, AvatarBone childBone)
        {
            // A quaternion motor controls the relative orientation between two bodies. The target
              // orientation is specified with a quaternion. The target orientations are set in
              // SetMotorTargets.

              // We can use the motors to achieve following results:
              // - No motors: The ragdoll joints are not damped and the bones swing a lot (within the
              //   allowed limits).
              // - Damping: If DampingConstant > 0 and SpringConstant == 0, the relative bone rotations
              //   are damped. This simulates joint friction and muscles forces acting against the movement.
              // - Springs: If DampingConstant > 0 and SpringConstant > 0, the motors try to move the
              //   ragdoll limbs to a pose defined by the TargetOrientations of the motors. This could be,
              //   for example, a defensive pose of a character.
              // - Animation: Like "Springs" but the TargetOrientation is changed in each frame. This
              //   way the ragdoll performs a user defined animation while still reacting to impacts.

              int parentIndex = (int)parentBone;
              int childIndex = (int)childBone;

              var motor = new RagdollMotor(childIndex, parentIndex);

              ragdoll.Motors[childIndex] = motor;
        }
Ejemplo n.º 32
0
    public override void Update(GameTime gameTime)
    {
      if (_avatarPose == null)
      {
        if (_avatarRenderer.State == AvatarRendererState.Ready)
        {
          _avatarPose = new AvatarPose(_avatarRenderer);
          _targetPose = SkeletonPose.Create(_avatarPose.SkeletonPose.Skeleton);

          // Create a ragdoll for the avatar.
          _ragdoll = Ragdoll.CreateAvatarRagdoll(_avatarPose, Simulation);

          // Set the world space pose of the whole ragdoll. And copy the bone poses 
          // of the current skeleton pose.
          _ragdoll.Pose = _pose;
          _ragdoll.UpdateBodiesFromSkeleton(_avatarPose.SkeletonPose);

          // To simplify collision checks, we need a simple way to determine whether
          // a rigid body belongs to the ragdoll.
          // --> Set RigidBody.UserData = _ragdoll.
          // (Alternatively we could also set specific names for the rigid bodies,
          // or we could assign the collision objects to a certain collision group.)
          foreach (var body in _ragdoll.Bodies)
            if (body != null)
              body.UserData = _ragdoll;

          // Add rigid bodies and constraints to the simulation.
          _ragdoll.AddToSimulation(Simulation);

          // Start by playing the key frame animation.
          SwitchMode(RagdollMode.Mode1);

          // The facial expression can be applied directly to the _avatarPose.
          _animationController0 = AnimationService.StartAnimation(_expressionAnimation, _avatarPose);

          // The skeletal animation is applied to the _targetPose. The _targetPose
          // is used to drive the ragdoll. (See end of method.)
          _animationController1 = AnimationService.StartAnimation(_skeletonAnimation, (IAnimatableProperty<SkeletonPose>)_targetPose);
        }

        return;
      }

      if (InputService.IsPressed(Buttons.A, false, LogicalPlayerIndex.One))
        SwitchMode(RagdollMode.Mode1);
      else if (InputService.IsPressed(Buttons.B, false, LogicalPlayerIndex.One))
        SwitchMode(RagdollMode.Mode2);
      else if (InputService.IsPressed(Buttons.X, false, LogicalPlayerIndex.One))
        SwitchMode(RagdollMode.Mode3);
      else if (InputService.IsPressed(Buttons.Y, false, LogicalPlayerIndex.One))
        SwitchMode(RagdollMode.Mode4);

      if (_mode == RagdollMode.Mode1 || _mode == RagdollMode.Mode2)
      {
        // The ragdoll plays a certain animation. Check whether the character was 
        // hit by a ball.
        foreach (var contactConstraint in Simulation.ContactConstraints)
        {
          if (contactConstraint.BodyA.UserData == _ragdoll && contactConstraint.BodyB.Name.StartsWith("Ball")
              || contactConstraint.BodyB.UserData == _ragdoll && contactConstraint.BodyA.Name.StartsWith("Ball"))
          {
            // Switch to the "Passive Ragdoll" mode and let the character collapse.
            SwitchMode(RagdollMode.Mode3);

            // Hint: You can read contactConstraint.LinearConstraintImpulse.Length to
            // determine the strength of the impact.
          }
        }
      }

      switch (_mode)
      {
        case RagdollMode.Mode1:
          // In mode 1 we update the rigid bodies directly.
          _ragdoll.UpdateBodiesFromSkeleton(_targetPose);
          break;
        case RagdollMode.Mode2:
          // Compute how much time the simulation will advance in the next Update().
          TimeSpan nextSimulationTimeStep;
          int numberOfSubTimeSteps;
          Simulation.GetNextTimeStep(gameTime.ElapsedGameTime, out nextSimulationTimeStep, out numberOfSubTimeSteps);

          // In mode 2 velocity motors update the rigid bodies.
          _ragdoll.DriveToPose(_targetPose, (float)nextSimulationTimeStep.TotalSeconds);
          break;
        case RagdollMode.Mode3:
          // In mode 3 we don't have to update the rigid bodies.
          break;
        case RagdollMode.Mode4:
          // In mode 4 constraint motors control the joints of the ragdoll.
          // (The second parameter is only required for velocity motors.)
          _ragdoll.DriveToPose(_targetPose, 0);
          break;
      }

      // Copy the skeleton pose. (_avatarPose stores the skeleton pose which is 
      // being rendered.)
      _ragdoll.UpdateSkeletonFromBodies(_avatarPose.SkeletonPose);

      _debugRenderer.Clear();
      _debugRenderer.DrawText("\n");
      _debugRenderer.DrawText(_statusMessage);

      // Render rigid bodies.
      foreach (var body in Simulation.RigidBodies)
        if (!(body.Shape is EmptyShape))  // Do not draw dummy bodies which might be used by the ragdoll.
          _debugRenderer.DrawObject(body, Color.Black, true, false);
    }
Ejemplo n.º 33
0
    public IKPhysicsSample(Microsoft.Xna.Framework.Game game)
      : base(game)
    {
      GraphicsScreen.DrawReticle = true;

      // Add game objects which allows to grab rigid bodies.
      _grabObject = new GrabObject(Services);
      GameObjectService.Objects.Add(_grabObject);

      // Add Dude model.
      var modelNode = ContentManager.Load<ModelNode>("Dude/Dude");
      _meshNode = modelNode.GetSubtree().OfType<MeshNode>().First().Clone();
      _meshNode.PoseLocal = new Pose(new Vector3F(0, 0, 0));
      SampleHelper.EnablePerPixelLighting(_meshNode);
      GraphicsScreen.Scene.Children.Add(_meshNode);

      // Create a ragdoll for the Dude model.
      _ragdoll = new Ragdoll();
      DudeRagdollCreator.Create(_meshNode.SkeletonPose, _ragdoll, Simulation, 0.571f);

      // Set the initial world space pose of the whole ragdoll. And copy the bone poses of the
      // current skeleton pose.
      _ragdoll.Pose = _meshNode.PoseWorld;
      _ragdoll.UpdateBodiesFromSkeleton(_meshNode.SkeletonPose);

      // Enable constraints (joints and limits, no motors)
      _ragdoll.EnableJoints();
      _ragdoll.EnableLimits();
      _ragdoll.DisableMotors();

      foreach (var body in _ragdoll.Bodies)
      {
        if (body != null)
        {
          // Disable rigid body sleeping. (If we leave it enabled, the simulation might
          // disable slow bodies before they reach their IK goal.)
          body.CanSleep = false;

          // Disable collisions response.
          body.CollisionResponseEnabled = false;
        }
      }

      // Add rigid bodies and the constraints of the ragdoll to the simulation.
      _ragdoll.AddToSimulation(Simulation);

      // Disable all force effects (default gravity and damping).
      Simulation.ForceEffects.Clear();

      // Create constraints which hold selected bodies at their current position 
      // relative to the world.
      // To constrain the position + orientation, we use a FixedJoint.
      foreach (var boneName in new[] { "Pelvis" })
      {
        var ragdollBody = _ragdoll.Bodies[_meshNode.SkeletonPose.Skeleton.GetIndex(boneName)];
        var ikJoint = new FixedJoint
        {
          AnchorPoseALocal = ragdollBody.Pose,
          BodyA = Simulation.World,
          AnchorPoseBLocal = Pose.Identity,
          BodyB = ragdollBody,
          CollisionEnabled = false,
          MaxForce = 1000,
        };
        _ikJoints.Add(ikJoint);
        Simulation.Constraints.Add(ikJoint);
      }
      // To constrain only the position, we use a BallJoint.
      foreach(var boneName in new[] { "L_Hand", "R_Hand", "L_Ankle1", "R_Ankle" })
      {
        var ragdollBody = _ragdoll.Bodies[_meshNode.SkeletonPose.Skeleton.GetIndex(boneName)];
        var ikJoint = new BallJoint
        {
          AnchorPositionALocal = ragdollBody.Pose.Position,
          BodyA = Simulation.World,
          AnchorPositionBLocal = Vector3F.Zero,
          BodyB = ragdollBody,
          CollisionEnabled = false,
          MaxForce = 1000,
        };
        _ikJoints.Add(ikJoint);
        Simulation.Constraints.Add(ikJoint);
      }
    }