/// <summary> /// Constructs a new animation player. /// </summary> public AnimationPlayer(SkinningData skinningData) { if (skinningData == null) { throw new ArgumentNullException("skinningData"); } skinningDataValue = skinningData; boneTransforms = new Matrix[skinningData.BindPose.Count]; worldTransforms = new Matrix[skinningData.BindPose.Count]; skinTransforms = new Matrix[skinningData.BindPose.Count]; bindPose = new Matrix[skinningData.BindPose.Count]; }
/// <summary> /// Embeds animation data into ModelContent /// </summary> /// <param name="input"></param> /// <param name="context"></param> /// <returns></returns> public override ModelContent Process(NodeContent input, ContentProcessorContext context) { ValidateMesh(input, null); // find the skeletion BoneContent skeleton = MeshHelper.FindSkeleton(input); if (skeleton == null) { throw new InvalidContentException("Input skeleton not found"); } // We don't want to have to worry about different parts of the model being in different // coordinate systems, so let's just bake everything FlattenTransforms(input, skeleton); // Read the bind pose and skeleton hierarchy data IList <BoneContent> bones = MeshHelper.FlattenSkeleton(skeleton); if (bones.Count > SkinnedEffect.MaxBones) { throw new InvalidContentException(string.Format( "Skeleton has {0} bones, but the maximum supported is {1}.", bones.Count, SkinnedEffect.MaxBones )); } List <Matrix> bindPose = new List <Matrix>(); List <Matrix> inverseBindPose = new List <Matrix>(); List <int> skeletonHierarchy = new List <int>(); Dictionary <string, int> assignement = new Dictionary <string, int>(); int ctr = 0; foreach (BoneContent bone in bones) { assignement.Add(bone.Name, ctr); bindPose.Add(bone.Transform); inverseBindPose.Add(Matrix.Invert(bone.AbsoluteTransform)); skeletonHierarchy.Add(bones.IndexOf(bone.Parent as BoneContent)); ++ctr; } // Convert animation data to our runtime format Dictionary <string, AnimationClip> animationClips; animationClips = ProcessAnimations(skeleton.Animations, bones); // Chain to teh base ModelProcessor class so it can convert the model data ModelContent model = base.Process(input, context); // Store our custon animation data in the Tag property of the model object[] intoTag; try { intoTag = (object[])model.Tag; } catch (InvalidCastException e) { Console.Out.WriteLine(e.Message); model.Tag = null; return(model); } intoTag[0] = new SkinningData(animationClips, bindPose, inverseBindPose, skeletonHierarchy, assignement); model.Tag = intoTag; return(model); }