예제 #1
0
        public override void Update(GameTime gameTime)
        {
            _debugRenderer.Clear();

            if (_avatarPose == null)
            {
                // Must wait till renderer is ready. Before that we do not get skeleton info.
                if (_avatarRenderer.State == AvatarRendererState.Ready)
                {
                    // Create AvatarPose.
                    _avatarPose = new AvatarPose(_avatarRenderer);

                    // A 'bone transform' is the transformation of a bone relative to its bind pose.
                    // Bone transforms define the pose of a skeleton.

                    // Rotate arm of avatar.
                    SkeletonPose skeletonPose  = _avatarPose.SkeletonPose;
                    int          shoulderIndex = skeletonPose.Skeleton.GetIndex("ShoulderLeft");
                    skeletonPose.SetBoneTransform(shoulderIndex, new SrtTransform(QuaternionF.CreateRotationZ(-0.9f)));

                    // The class SkeletonHelper provides some useful extension methods.
                    // One is SetBoneRotationAbsolute() which sets the orientation of a bone relative
                    // to model space.
                    // Rotate elbow to make the lower arm point forward.
                    int elbowIndex = skeletonPose.Skeleton.GetIndex("ElbowLeft");
                    SkeletonHelper.SetBoneRotationAbsolute(skeletonPose, elbowIndex, QuaternionF.CreateRotationY(ConstantsF.PiOver2));

                    // Draw avatar skeleton for debugging.
                    _debugRenderer.DrawSkeleton(skeletonPose, _pose, Vector3F.One, 0.02f, Color.Orange, true);
                }
            }
        }
예제 #2
0
        public void Update(float deltaTime, Matrix world)
        {
            if (deltaTime <= 0)
            {
                return;
            }

            // Reset bone transform.
            SkeletonPose.SetBoneTransform(BoneIndex, SrtTransform.Identity);

            // Get new fixed point position in world space.
            var bonePoseAbsolute   = SkeletonPose.GetBonePoseAbsolute(BoneIndex);
            var bonePoseWorld      = world * bonePoseAbsolute;
            var fixedPointPosition = bonePoseWorld.TransformPosition(Offset);

            // If we haven't set the fixed point position before, then store the position
            // and we are done.
            if (_fixedPointPosition.IsNaN)
            {
                _fixedPointPosition = fixedPointPosition;
                return;
            }

            // New position and velocity of fixed point.
            _fixedPointVelocity = (fixedPointPosition - _fixedPointPosition) / deltaTime;
            _fixedPointPosition = fixedPointPosition;

            // If the particle position was not set before, then we only store the current values.
            // The real work starts in the next frame.
            if (_particlePosition.IsNaN)
            {
                _particlePosition = _fixedPointPosition;
                _particleVelocity = _fixedPointVelocity;
                return;
            }

            // Compute the spring force between the particle and the fixed point.
            var force = Spring * (_fixedPointPosition - _particlePosition) + Damping * (_fixedPointVelocity - _particleVelocity);

            // Update velocity and position of the particle using symplectic Euler.
            _particleVelocity = _particleVelocity + force * deltaTime;
            _particlePosition = _particlePosition + _particleVelocity * deltaTime;

            // Convert particle position back to bone space.
            var particleLocal = bonePoseWorld.Inverse.TransformPosition(_particlePosition);

            // Create rotation between the fixed point vector and the particle vector.
            var boneTransform = new SrtTransform(Quaternion.CreateFromRotationMatrix(Offset, particleLocal));

            SkeletonPose.SetBoneTransform(BoneIndex, boneTransform);
        }
예제 #3
0
        // Initializes the bone rotations using the quaternions of the specified array.
        private void ArrayToSkeletonPose(float[] values)
        {
            var numberOfBones = SkeletonPose.Skeleton.NumberOfBones;

            for (int i = 0; i < numberOfBones; i++)
            {
                QuaternionF quaternion = new QuaternionF(
                    values[i * 4 + 0],
                    values[i * 4 + 1],
                    values[i * 4 + 2],
                    values[i * 4 + 3]);

                // The quaternions were filtered using component-wise linear interpolation. This
                // is only an approximation which denormalizes the quaternions.
                // --> Renormalize the quaternions.
                quaternion.TryNormalize();

                // Exchange the rotation in the bone transform.
                var boneTransform = SkeletonPose.GetBoneTransform(i);
                boneTransform.Rotation = quaternion;
                SkeletonPose.SetBoneTransform(i, boneTransform);
            }
        }
예제 #4
0
        /// <summary>
        /// Perform mapping in local bone space.
        /// </summary>
        private static void MapLocal(bool mapTranslations, SkeletonPose skeletonA, int boneIndexA, SkeletonPose skeletonB, int boneIndexB, float scaleAToB, QuaternionF rotationBToA, QuaternionF rotationAToB)
        {
            var boneTransform = skeletonA.GetBoneTransform(boneIndexA);

              // Remove any scaling.
              boneTransform.Scale = Vector3F.One;

              // Rotation: Using similarity transformation: (Read from right to left.)
              // Rotate from bone B space to bone A space.
              // Apply the bone transform rotation in bone A space
              // Rotate back from bone A space to bone B space.
              boneTransform.Rotation = rotationAToB * boneTransform.Rotation * rotationBToA;

              // If we should map translations, then we scale the translation and rotate it from
              // bone A space to bone B space.
              if (mapTranslations)
            boneTransform.Translation = rotationAToB.Rotate(boneTransform.Translation * scaleAToB);
              else
            boneTransform.Translation = Vector3F.Zero;

              // Apply new bone transform to B.
              skeletonB.SetBoneTransform(boneIndexB, boneTransform);
        }