Пример #1
0
        private void InitializeSkeletonPoses()
        {
            // Create a list of the bone/joint names of a Kinect skeleton.
            int numberOfJoints = Enum.GetNames(typeof(JointType)).Length;
            var boneNames      = new string[numberOfJoints];

            for (int i = 0; i < numberOfJoints; i++)
            {
                boneNames[i] = ((JointType)i).ToString();
            }

            // Create list with one entry per bone. Each entry is the index of the parent bone.
            var boneParents = new[]
            {
                -1,
                (int)JointType.HipCenter,
                (int)JointType.Spine,
                (int)JointType.ShoulderCenter,
                (int)JointType.ShoulderCenter,
                (int)JointType.ShoulderLeft,
                (int)JointType.ElbowLeft,
                (int)JointType.WristLeft,
                (int)JointType.ShoulderCenter,
                (int)JointType.ShoulderRight,
                (int)JointType.ElbowRight,
                (int)JointType.WristRight,
                (int)JointType.HipCenter,
                (int)JointType.HipLeft,
                (int)JointType.KneeLeft,
                (int)JointType.AnkleLeft,
                (int)JointType.HipCenter,
                (int)JointType.HipRight,
                (int)JointType.KneeRight,
                (int)JointType.AnkleRight,
            };

            // Create a list of the bind pose transformations of all bones. Since we do not
            // get such information from Kinect, we position all bones in the local origin.
            var boneBindPoses = new SrtTransform[numberOfJoints];

            for (int i = 0; i < numberOfJoints; i++)
            {
                boneBindPoses[i] = SrtTransform.Identity;
            }

            // Create a skeleton that defines the bone hierarchy and rest pose.
            var skeleton = new DRSkeleton(boneParents, boneNames, boneBindPoses);

            // Create a SkeletonPose for each player.
            SkeletonPoseA = SkeletonPose.Create(skeleton);
            SkeletonPoseB = SkeletonPose.Create(skeleton);
        }
Пример #2
0
        private static OutlineItem CreateOutlineItem(Skeleton skeleton, int boneIndex)
        {
            var item = new OutlineItem
            {
                Text = $"Bone {boneIndex} \"{skeleton.GetName(boneIndex)}\"",
                Icon = MultiColorGlyphs.Bone,
                Children = new OutlineItemCollection(),
                UserData = boneIndex,
            };

            for (int bone = 0; bone < skeleton.NumberOfBones; bone++)
                if (skeleton.GetParent(bone) == boneIndex)
                    item.Children.Add(CreateOutlineItem(skeleton, bone));

            return item;
        }
Пример #3
0
        private static OutlineItem CreateOutlineItem(Skeleton skeleton)
        {
            var item = new OutlineItem
            {
                Text = $"Skeleton \"{skeleton.Name}\"",
                Icon = MultiColorGlyphs.Skeleton,
                IsExpanded = false,
                Children = new OutlineItemCollection(),
                UserData = skeleton,
            };

            for (int bone = 0; bone < skeleton.NumberOfBones; bone++)
                if (skeleton.GetParent(bone) == -1)
                    item.Children.Add(CreateOutlineItem(skeleton, bone));

            return item;
        }
        /// <summary>
        /// Extracts all animations and stores them in a dictionary of timelines.
        /// </summary>
        private Dictionary<string, SkeletonKeyFrameAnimation> ProcessAnimations(AnimationContentDictionary animationContentDictionary, Skeleton skeleton, ContentProcessorContext context)
        {
            var animations = new Dictionary<string, SkeletonKeyFrameAnimation>();
              foreach (var item in animationContentDictionary)
              {
            string animationName = item.Key;
            AnimationContent animationContent = item.Value;

            // Convert the AnimationContent to a SkeletonKeyFrameAnimation.
            SkeletonKeyFrameAnimation skeletonAnimation = ProcessAnimation(animationContent, skeleton, context);
            animations.Add(animationName, skeletonAnimation);
              }

              if (animations.Count == 0)
            context.Logger.LogWarning(null, null, "Skinned model does not contain any animations.");

              return animations;
        }
        /// <summary>
        /// Converts an AnimationContent to a SkeletonKeyFrameAnimation.
        /// </summary>
        private SkeletonKeyFrameAnimation ProcessAnimation(AnimationContent animationContent, Skeleton skeleton, ContentProcessorContext context)
        {
            var animation = new SkeletonKeyFrameAnimation { EnableInterpolation = true };

              // Process all animation channels (each channel animates a bone).
              int numberOfKeyFrames = 0;
              foreach (var item in animationContent.Channels)
              {
            string channelName = item.Key;
            AnimationChannel channel = item.Value;

            int boneIndex = skeleton.GetIndex(channelName);
            if (boneIndex == -1)
            {
              var message = string.Format("Found animation for bone '{0}', which is not part of the skeleton.", channelName);
              throw new InvalidContentException(message, animationContent.Identity);
            }

            var bindPoseRelativeInverse = skeleton.GetBindPoseRelative(boneIndex).Inverse;
            foreach (AnimationKeyframe keyframe in channel)
            {
              TimeSpan time = keyframe.Time;
              SrtTransform transform = SrtTransform.FromMatrix(keyframe.Transform);

              // The matrix in the key frame is the transformation in the coordinate space of the
              // parent bone. --> Convert it to a transformation relative to the animated bone.
              transform = bindPoseRelativeInverse * transform;

              // To start with minimal numerical errors, we normalize the rotation quaternion.
              transform.Rotation.Normalize();

              animation.AddKeyFrame(boneIndex, time, transform);
              numberOfKeyFrames++;
            }
              }

              if (numberOfKeyFrames == 0)
            throw new InvalidContentException("Animation has no keyframes.", animationContent.Identity);

             // Compress animation to safe memory.
              float removedKeyFrames = animation.Compress(
            CompressionScaleThreshold,
            CompressionRotationThreshold,
            CompressionTranslationThreshold);

              if (removedKeyFrames > 0)
            context.Logger.LogImportantMessage("{0}: Compression removed {1:P} of all key frames.",
                                           animationContent.Name,
                                           removedKeyFrames);

              // Finalize the animation. (Optimizes the animation data for fast runtime access.)
              animation.Freeze();

              return animation;
        }
Пример #6
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;
        }
Пример #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;
        }
Пример #8
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;
        }
Пример #9
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;
        }
Пример #10
0
        private void InitializeSkeletonPoses()
        {
            // Create a list of the bone/joint names of a Kinect skeleton.
              int numberOfJoints = Enum.GetNames(typeof(JointType)).Length;
              var boneNames = new string[numberOfJoints];
              for (int i = 0; i < numberOfJoints; i++)
            boneNames[i] = ((JointType)i).ToString();

              // Create list with one entry per bone. Each entry is the index of the parent bone.
              var boneParents = new[]
              {
            -1,
            (int)JointType.HipCenter,
            (int)JointType.Spine,
            (int)JointType.ShoulderCenter,
            (int)JointType.ShoulderCenter,
            (int)JointType.ShoulderLeft,
            (int)JointType.ElbowLeft,
            (int)JointType.WristLeft,
            (int)JointType.ShoulderCenter,
            (int)JointType.ShoulderRight,
            (int)JointType.ElbowRight,
            (int)JointType.WristRight,
            (int)JointType.HipCenter,
            (int)JointType.HipLeft,
            (int)JointType.KneeLeft,
            (int)JointType.AnkleLeft,
            (int)JointType.HipCenter,
            (int)JointType.HipRight,
            (int)JointType.KneeRight,
            (int)JointType.AnkleRight,
              };

              // Create a list of the bind pose transformations of all bones. Since we do not
              // get such information from Kinect, we position all bones in the local origin.
              var boneBindPoses = new SrtTransform[numberOfJoints];
              for (int i = 0; i < numberOfJoints; i++)
            boneBindPoses[i] = SrtTransform.Identity;

              // Create a skeleton that defines the bone hierarchy and rest pose.
              var skeleton = new DRSkeleton(boneParents, boneNames, boneBindPoses);

              // Create a SkeletonPose for each player.
              SkeletonPoseA = SkeletonPose.Create(skeleton);
              SkeletonPoseB = SkeletonPose.Create(skeleton);
        }
        private void BuildSkeleton()
        {
            // Get an array of all bones in depth-first order.
              // (Same as MeshHelper.FlattenSkeleton(root).)
              var bones = TreeHelper.GetSubtree(_rootBone, n => n.Children.OfType<BoneContent>(), true)
                            .ToList();

              // Create list of parent indices, bind pose transformations and bone names.
              var boneParents = new List<int>();
              var bindTransforms = new List<SrtTransform>();
              var boneNames = new List<string>();
              int numberOfWarnings = 0;
              foreach (var bone in bones)
              {
            int parentIndex = bones.IndexOf(bone.Parent as BoneContent);
            boneParents.Add(parentIndex);

            // Log warning for invalid transform matrices - but not too many warnings.
            if (numberOfWarnings < 2)
            {
              if (!SrtTransform.IsValid((Matrix44F)bone.Transform))
              {
            if (numberOfWarnings < 1)
              _context.Logger.LogWarning(null, _input.Identity, "Bone transform is not supported. Bone transform matrices may only contain scaling, rotation and translation.");
            else
              _context.Logger.LogWarning(null, _input.Identity, "More unsupported bone transform found.");

            numberOfWarnings++;
              }
            }

            bindTransforms.Add(SrtTransform.FromMatrix(bone.Transform));

            if (boneNames.Contains(bone.Name))
            {
              string message = String.Format(CultureInfo.InvariantCulture, "Duplicate bone name (\"{0}\") found.", bone.Name);
              throw new InvalidContentException(message, _input.Identity);
            }

            boneNames.Add(bone.Name);
              }

              // Create and return a new skeleton instance.
              _skeleton = new Skeleton(boneParents, boneNames, bindTransforms);
        }