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); } } }
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); }
// 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); } }
/// <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); }