#region File Description //----------------------------------------------------------------------------- // SkinnedAnimationPlayer.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion using System; using System.Collections.Generic; using Microsoft.Xna.Framework; namespace CustomModelAnimation { /// /// The animation player manipulates a skinned model /// public class SkinnedAnimationPlayer : ModelAnimationPlayerBase { // Current animation transform matrices. Matrix[] boneTransforms; Matrix[] worldTransforms; Matrix[] skinTransforms; List bindPose; List inverseBindPose; List skeletonHierarchy; /// /// Constructs a new animation player. /// public SkinnedAnimationPlayer(List bindPose, List inverseBindPose, List skeletonHierarchy) { if (bindPose == null || bindPose.Count == 0) throw new Exception("Bad arguments to model animation player"); boneTransforms = new Matrix[bindPose.Count]; worldTransforms = new Matrix[bindPose.Count]; skinTransforms = new Matrix[bindPose.Count]; this.bindPose = bindPose; this.inverseBindPose = inverseBindPose; this.skeletonHierarchy = skeletonHierarchy; } /// /// Initializes the animation clip /// protected override void InitClip() { bindPose.CopyTo(boneTransforms); } /// /// Sets the key frame for the passed in frame /// /// protected override void SetKeyframe(ModelKeyframe keyframe) { boneTransforms[keyframe.Bone] = keyframe.Transform; } /// /// Updates the transformations ultimately needed for rendering /// protected override void OnUpdate() { if (CurrentClip != null) { // Root bone. worldTransforms[0] = boneTransforms[0]; skinTransforms[0] = inverseBindPose[0] * worldTransforms[0]; // Child bones. for (int bone = 1; bone < worldTransforms.Length; bone++) { int parentBone = skeletonHierarchy[bone]; worldTransforms[bone] = boneTransforms[bone] * worldTransforms[parentBone]; skinTransforms[bone] = inverseBindPose[bone] * worldTransforms[bone]; } } } /// /// Gets the current bone transform matrices, relative to their parent bones. /// private Matrix[] GetBoneTransforms() { return boneTransforms; } /// /// Gets the current bone transform matrices, in absolute format. /// private Matrix[] GetWorldTransforms() { return worldTransforms; } /// /// Gets the current bone transform matrices, relative to the skinning bind pose. /// public Matrix[] GetSkinTransforms() { return skinTransforms; } } }