/// <summary>
        /// Creates a list of bone index values for the given avatar bone
        /// and its children.
        /// </summary>
        /// <param name="avatarBone">The root bone to start search</param>
        /// <param name="parentBones">List of parent bones from the avatar
        /// renderer</param>
        /// <returns></returns>
        List <int> FindInfluencedBones(AvatarBone avatarBone,
                                       ReadOnlyCollection <int> parentBones)
        {
            // New list of bones that will be influenced
            List <int> influencedList = new List <int>();

            // Add the first bone
            influencedList.Add((int)avatarBone);

            // Start searching after the first bone
            int currentBoneID = influencedList[0] + 1;

            // Loop until we are done with all of the bones
            while (currentBoneID < parentBones.Count)
            {
                // Check to see if the current bone is a child of any of the
                // previous bones we have found
                if (influencedList.Contains(parentBones[currentBoneID]))
                {
                    // Add the bone to the influenced list
                    influencedList.Add(currentBoneID);
                }
                // Move to the next bone
                currentBoneID++;
            }

            return(influencedList);
        }
Example #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;
        }
Example #3
0
 public static bool TryGetBone(AvatarBone bone, out Transform transform)
 {
     if (TryGetInstance(out var avatar))
     {
         transform = bone switch {
             AvatarBone.Head => avatar.headBone,
             AvatarBone.Body => avatar.bodyBone,
             AvatarBone.Legs => avatar.legsBone,
             AvatarBone.Broom => avatar.broomBone,
             _ => throw new NotImplementedException(),
         };
         return(transform);
     }
     transform = default;
     return(false);
 }
Example #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;
        }
Example #5
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;
        }
Example #6
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;
        }
Example #7
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;
        }
Example #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;
        }
Example #9
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;
        }
Example #10
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;
        }
Example #11
0
        /// <summary>
        /// Creates a list of bone index values for the given avatar bone 
        /// and its children.
        /// </summary>
        /// <param name="avatarBone">The root bone to start search</param>
        /// <param name="parentBones">List of parent bones from the avatar 
        /// renderer</param>
        /// <returns></returns>
        List<int> FindInfluencedBones(AvatarBone avatarBone, ReadOnlyCollection<int> parentBones)
        {
            // New list of bones that will be influenced
            List<int> influencedList = new List<int>();
            // Add the first bone
            influencedList.Add((int)avatarBone);

            // Start searching after the first bone
            int currentBoneID = influencedList[0] + 1;

            // Loop until we are done with all of the bones
            while (currentBoneID < parentBones.Count)
            {
                // Check to see if the current bone is a child of any of the
                // previous bones we have found
                if (influencedList.Contains(parentBones[currentBoneID]))
                {
                    // Add the bone to the influenced list
                    influencedList.Add(currentBoneID);
                }
                // Move to the next bone
                currentBoneID++;
            }

            return influencedList;
        }
Example #12
0
 public Matrix GetBoneTransform(AvatarBone avatarBone)
 {
     return(this.GetBoneTransform((int)avatarBone));
 }
Example #13
0
 public int GetBone(AvatarBone avatarBone)
 {
     return((int)avatarBone);
 }