XNA comes with a great foundation for importing FBX files. There's also a fantastic sample from the Creators Website that runs through the process of an Animated FBX. However, there's a problem when exporting an animated Model from Maya. When Maya exports an FBX file, it will export the animation all in one track. This causes a problem of animating the model in your XNA games.
So, after crawling through Google and the forums, the best solution I could find, was to create a document with the individual keys and it's animation, so that the Skinned Model Processor could load the animation clips itself.
So, for example, Key 1 - 20 could be the Walk Cycle, and Key 21 - 40 could be the Jump Cycle, etc. etc.
So, the text file would look something like this :
"walk" 1 20
"jump" 21 40
"leftpunch" 41 45
"rightpunch" 46 50
To accomplish this we need to add code to the SkinnedModelProcessor.cs file in the SkinnedModel Sample from the XNA Creators Website.
Dictionary<string, AnimationClip> SplitAnimations(AnimationClip rootAnimation, string animationDefs)
{
Dictionary<string, AnimationClip> splitAnimations = new Dictionary<string, AnimationClip>();
StreamReader fileReader = new StreamReader(animationDefs);
while (!fileReader.EndOfStream)
{
string line = fileReader.ReadLine();
string[] parts = line.Split(' ');
string animName = parts[0].Trim('"');
int startFrame = int.Parse(parts[1]);
int endFrame = int.Parse(parts[2]);
splitAnimations[animName] = ExtractAnimation(rootAnimation, startFrame, endFrame);
}
fileReader.Close();
return splitAnimations;
}
AnimationClip ExtractAnimation(AnimationClip rootAnimation, int startFrame, int endFrame)
{
TimeSpan startTime = ConvertFrameNumberToTimeSpan(startFrame);
TimeSpan endTime = ConvertFrameNumberToTimeSpan(endFrame);
List<Keyframe> keyframes = new List<Keyframe>();
foreach (Keyframe keyframe in rootAnimation.Keyframes)
{
if (keyframe.Time >= startTime && keyframe.Time <= endTime)
{
Keyframe newKeyframe = new Keyframe(keyframe.Bone, keyframe.Time - startTime, keyframe.Transform);
keyframes.Add(newKeyframe);
}
}
return new AnimationClip(endTime - startTime, keyframes);
}
Next, in the Process function we need to change the following line :
// Convert animation data to our runtime format.
Dictionary<string, AnimationClip> animationClips;
animationClips = ProcessAnimations(skeleton.Animations, bones);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
To :
// Convert animation data to our runtime format.
Dictionary<string, AnimationClip> animationClips;
animationClips = SplitAnimations(ProcessAnimations(skeleton.Animations, bones)[0].animClip, "definitions.txt");
Now that you have that, you need to include your definitions.txt file in your Content folder. Now you can start your animation clips by calling the animation clip name as follows :
AnimationClip clip = skinningData.AnimationClips["walk"];
animationPlayer.StartClip(clip);
Sources :
http://forums.xna.com/forums/t/1415.aspx?PageIndex=2
http://creators.xna.com/en-US/sample/skinnedmodel
7809aaf6-81a6-4fd5-bd79-0736ba78dac8|1|5.0