Example #1
0
        protected override AnimationClip Read(ContentReader input, AnimationClip existingInstance)
        {
            AnimationClip clip = new AnimationClip();

            clip.Name     = input.ReadString();
            clip.Duration = input.ReadDouble();

            int boneCnt = input.ReadInt32();

            for (int i = 0; i < boneCnt; i++)
            {
                AnimationClip.Bone bone = new AnimationClip.Bone();
                clip.Bones.Add(bone);

                bone.Name = input.ReadString();

                int cnt = input.ReadInt32();

                for (int j = 0; j < cnt; j++)
                {
                    AnimationClip.Keyframe keyframe = new AnimationClip.Keyframe();
                    keyframe.Time        = input.ReadDouble();
                    keyframe.Rotation    = input.ReadQuaternion();
                    keyframe.Translation = input.ReadVector3();

                    bone.Keyframes.Add(keyframe);
                }
            }

            return(clip);
        }
        /// <summary>
        /// Recursive function that processes the entire scene graph, collecting up
        /// all of the animation data.
        /// </summary>
        private void ProcessAnimationsRecursive(NodeContent input)
        {
            // Look up the bone for this input channel
            int inputBoneIndex;
            if (bones.TryGetValue(input.Name, out inputBoneIndex))
            {
                // Save the transform
                boneTransforms[inputBoneIndex] = input.Transform;
            }

            foreach (KeyValuePair<string, AnimationContent> animation in input.Animations)
            {
                // Do we have this animation before?
                AnimationClip clip;
                string clipName = animation.Key;

                if (!clips.TryGetValue(clipName, out clip))
                {
                    // Never seen before clip
                    clip = new AnimationClip();
                    modelExtra.Clips.Add(clipName,clip);

                    // Retain by name
                    clips[clipName] = clip;

                    clip.Name = clipName;
                    foreach (ModelBoneContent bone in model.Bones)
                    {
                        AnimationClip.Bone clipBone = new AnimationClip.Bone();
                        clipBone.Name = bone.Name;

                        clip.Bones.Add(clipBone);
                    }
                }

                // Ensure the duration is always set
                if (animation.Value.Duration.TotalSeconds > clip.Duration)
                    clip.Duration = animation.Value.Duration.TotalSeconds;

                //
                // For each channel, determine the bone and then process all of the
                // keyframes for that bone.
                //

                foreach (KeyValuePair<string, AnimationChannel> channel in animation.Value.Channels)
                {
                    // What is the bone index?
                    int boneIndex;
                    if (!bones.TryGetValue(channel.Key, out boneIndex))
                        continue;           // Ignore if not a named bone

                    // An animation is useless if it is for a bone not assigned to any meshes at all
                    if (UselessAnimationTest(boneIndex))
                        continue;

                    // I'm collecting up in a linked list so we can process the data
                    // and remove redundant keyframes
                    LinkedList<AnimationClip.Keyframe> keyframes = new LinkedList<AnimationClip.Keyframe>();
                    foreach (AnimationKeyframe keyframe in channel.Value)
                    {
                        Matrix transform = keyframe.Transform;      // Keyframe transformation

                        AnimationClip.Keyframe newKeyframe = new AnimationClip.Keyframe();
                        newKeyframe.Time = keyframe.Time.TotalSeconds;
                        newKeyframe.Transform = transform;

                        keyframes.AddLast(newKeyframe);
                    }

                   // LinearKeyframeReduction(keyframes);
                    foreach (AnimationClip.Keyframe keyframe in keyframes)
                    {
                        clip.Bones[boneIndex].Keyframes.Add(keyframe);
                    }

                }

            }

            foreach (NodeContent child in input.Children)
            {
                ProcessAnimationsRecursive(child);
            }
        }
        /// <summary>
        /// Entry point for animation processing. 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="input"></param>
        /// <param name="context"></param>
        private void ProcessAnimations(ModelContent model, NodeContent input, ContentProcessorContext context)
        {
            // First build a lookup table so we can determine the
            // index into the list of bones from a bone name.
            for (int i = 0; i < model.Bones.Count; i++)
            {
                bones[model.Bones[i].Name] = i;
            }

            // For saving the bone transforms
            boneTransforms = new Matrix[model.Bones.Count];

            //
            // Collect up all of the animation data
            //

            ProcessAnimationsRecursive(input);

            // Ensure there is always a clip, even if none is included in the FBX
            // That way we can create poses using FBX files as one-frame
            // animation clips
            if (modelExtra.Clips.Count == 0)
            {
                AnimationClip clip = new AnimationClip();
                modelExtra.Clips.Add(clip);

                string clipName = "Take 001";

                // Retain by name
                clips[clipName] = clip;

                clip.Name = clipName;
                foreach (ModelBoneContent bone in model.Bones)
                {
                    AnimationClip.Bone clipBone = new AnimationClip.Bone();
                    clipBone.Name = bone.Name;

                    clip.Bones.Add(clipBone);
                }
            }

            // Ensure all animations have a first key frame for every bone
            foreach (AnimationClip clip in modelExtra.Clips)
            {
                for (int b = 0; b < bones.Count; b++)
                {
                    List<AnimationClip.Keyframe> keyframes = clip.Bones[b].Keyframes;
                    if (keyframes.Count == 0 || keyframes[0].Time > 0)
                    {
                        AnimationClip.Keyframe keyframe = new AnimationClip.Keyframe();
                        keyframe.Time = 0;
                        keyframe.Transform = boneTransforms[b];
                        keyframes.Insert(0, keyframe);
                    }
                }
            }
        }
        /// <summary>
        /// Entry point for animation processing. 
        /// </summary>
        /// <param name="model"></param>
        /// <param name="input"></param>
        /// <param name="context"></param>
        private void ProcessAnimations(ModelContent model, NodeContent input, ContentProcessorContext context, ContentIdentity sourceIdentity)
        {
            // First build a lookup table so we can determine the
            // index into the list of bones from a bone name.
            for (int i = 0; i < model.Bones.Count; i++)
            {
                bones[model.Bones[i].Name] = i;
            }

            // For saving the bone transforms
            boneTransforms = new Matrix[model.Bones.Count];

            //
            // Collect up all of the animation data
            //

            ProcessAnimationsRecursive(input);

            // Check to see if there's an animation clip definition
            // Here, we're checking for a file with the _Anims suffix.
            // So, if your model is named dude.fbx, we'd add dude_Anims.xml in the same folder
            // and the pipeline will see the file and use it to override the animations in the
            // original model file.
            string SourceModelFile = sourceIdentity.SourceFilename;
            string SourcePath = Path.GetDirectoryName(SourceModelFile);
            string AnimFilename = Path.GetFileNameWithoutExtension(SourceModelFile);
            AnimFilename += "_Anims.xml";
            string AnimPath = Path.Combine(SourcePath, AnimFilename);
            if (File.Exists(AnimPath))
            {
                // Add the filename as a dependency, so if it changes, the model is rebuilt
                context.AddDependency(AnimPath);

                // Load the animation definition from the XML file
                AnimationDefinition AnimDef = context.BuildAndLoadAsset<XmlImporter, AnimationDefinition>(new ExternalReference<XmlImporter>(AnimPath), null);

                if (modelExtra.Clips.Count > 0) //if there are some animations in our model
                {
                    foreach (AnimationDefinition.ClipPart Part in AnimDef.ClipParts)
                    {
                        // Grab the main clip that we are using and copy to MainClip

                        AnimationClip MainClip = new AnimationClip();

                        float StartTime = GetTimeSpanForFrame(Part.StartFrame, AnimDef.OriginalFrameCount, modelExtra.Clips[AnimDef.OriginalClipName].Duration);
                        float EndTime = GetTimeSpanForFrame(Part.EndFrame, AnimDef.OriginalFrameCount, modelExtra.Clips[AnimDef.OriginalClipName].Duration);

                        MainClip.Duration = EndTime-StartTime;
                        MainClip.Name = modelExtra.Clips[AnimDef.OriginalClipName].Name;

                        for (int i = 0; i < modelExtra.Clips[AnimDef.OriginalClipName].Bones.Count; i++)
                        {
                            AnimationClip.Bone clipBone = new AnimationClip.Bone();
                            clipBone.Name = modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Name;

                            if (modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes.Count != 0)
                            {

                                for (int j = 0; j < modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes.Count; j++)
                                {
                                    if ((modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes[j].Time >= StartTime) && (modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes[j].Time <= EndTime))
                                    {
                                        AnimationClip.Keyframe frame = new AnimationClip.Keyframe();
                                        frame.Rotation = modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes[j].Rotation;
                                        frame.Time = modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes[j].Time - StartTime;
                                        frame.Translation = modelExtra.Clips[AnimDef.OriginalClipName].Bones[i].Keyframes[j].Translation;
                                        clipBone.Keyframes.Add(frame);
                                    }

                                }
                            }
                            MainClip.Bones.Add(clipBone);

                        }

                        modelExtra.Clips.Add(Part.ClipName, MainClip);

                    }

                    // Process each of our new animation clip parts
                    //foreach (AnimationDefinition.ClipPart Part in AnimDef.ClipParts)
                    //{
                    //    // Calculate the frame times
                    //    float StartTime = GetTimeSpanForFrame(Part.StartFrame, AnimDef.OriginalFrameCount, MainClip.Duration);
                    //    float EndTime = GetTimeSpanForFrame(Part.EndFrame, AnimDef.OriginalFrameCount, MainClip.Duration);

                    //    //prepare new animation
                    //    LinkedList<AnimationClip.Keyframe> keyframes = new LinkedList<AnimationClip.Keyframe>();
                    //    AnimationClip.Bone NewBone = new AnimationClip.Bone();
                    //    NewBone.Keyframes = new List<AnimationClip.Keyframe>();

                    //    AnimationClip clip = new AnimationClip();
                    //    modelExtra.Clips.Add(Part.ClipName, clip);
                    //    modelExtra.Clips[Part.ClipName].Duration = (Part.EndFrame - Part.StartFrame + 1) * MainClip.Duration / AnimDef.OriginalFrameCount;

                    //    string clipName = Part.ClipName;

                    //    // Retain by name
                    //    clips[clipName] = clip;
                    //    modelExtra.Clips[Part.ClipName].Name = clipName;

                    //    foreach (AnimationClip.Bone bone in MainClip.Bones)
                    //    {
                    //        if (bone.Keyframes.Count != 0)
                    //        {
                    //            int ilosc = Part.EndFrame - Part.StartFrame + 1;
                    //            NewBone.Keyframes = bone.Keyframes.GetRange(Part.StartFrame, ilosc);
                    //            NewBone.Name = bone.Name;
                    //            modelExtra.Clips[Part.ClipName].Bones.Add(NewBone);
                    //        }
                    //        else
                    //        {
                    //            AnimationClip.Bone clipBone = new AnimationClip.Bone();
                    //            clipBone.Name = bone.Name;
                    //            modelExtra.Clips[Part.ClipName].Bones.Add(clipBone);
                    //        }
                    //    }
                    //}
                }
            }

            // Ensure there is always a clip, even if none is included in the FBX
            // That way we can create poses using FBX files as one-frame
            // animation clips
            if (modelExtra.Clips.Count == 0)
            {
                AnimationClip clip = new AnimationClip();
                modelExtra.Clips.Add("Take 001",clip);

                string clipName = "Take 001";

                // Retain by name
                clips[clipName] = clip;

                clip.Name = clipName;
                foreach (ModelBoneContent bone in model.Bones)
                {
                    AnimationClip.Bone clipBone = new AnimationClip.Bone();
                    clipBone.Name = bone.Name;

                    clip.Bones.Add(clipBone);
                }
            }

            //Ensure all animations have a first key frame for every bone
            foreach (KeyValuePair<string,AnimationClip> clip in modelExtra.Clips)
            {
                for (int b = 0; b < bones.Count; b++)
                {
                    List<AnimationClip.Keyframe> keyframes = clip.Value.Bones[b].Keyframes;
                    if (keyframes.Count == 0 || keyframes[0].Time > 0)
                    {
                        AnimationClip.Keyframe keyframe = new AnimationClip.Keyframe();
                        keyframe.Time = 0;
                        keyframe.Transform = boneTransforms[b];
                        keyframes.Insert(0, keyframe);
                    }
                }
            }
        }
Example #5
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="bone"></param>
 public BoneInfo(AnimationClip.Bone bone)
 {
     this.ClipBone = bone;
     SetKeyframes();
     SetPosition(0);
 }