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