PlayLoopingAnimation is only playing the first animation

Dec 13, 2008 at 4:38 AM
Edited Dec 13, 2008 at 4:28 PM
First let me say, I'm fairly certain that my problem is in my model file, but have failed to diagnose the problem.  I purchased a model from 3DRT that comes in a variety of formats.  The .X file file only comes with 1 master animation "Anim-1".  In the file is something like 55 separate animations for running, walking, jumping, etc... So, I opened the 3dmax file and reexported the .X file with all the animations.  Now when I load the model in the tutorial and I call 'PlayLoopingAnimation', it will not animate the model.  After fudging around getting nowhere, I pulled up the Xen tutorial code and dropped my model into the content.  Then I went to Tutorial 11 and changed the tutorial to use my model.  It works perfectly, as long as I'm 'playing' the first animation.  If I use any of the other valid 54 animations, it doesn't show anything on screen.

With the .FBX file, I get very strange bone deformations when playing back in Xen, e.g., the models fingers will become longer than the model is tall during segments of the animation.  I've tried reexporting FBX files, but get the same problems regardless.  XNAnimation library does the exact same thing.

Anyone give me some ideas? 

I had previously gotten all the animation logic in my game working using XNAnimation library, but took a couple days this week integrating Xen and switched all the animation, update and draw logic over to Xen.  Switched because Xen seems much much better and more comprehensive and it's the first library code I've ever downloaded for XNA that built 1st time for both PC and XBox.  Well done!

UPDATE:  I was able to export a model that will play all animations in Tutorials.  But, it still does not animate in my project.  I've simplified my animation code to the point that it looks identical to Tutorial 11, but the model does not animate.  It executes all the animation logic synchronously inside the 'model.draw' call, but no animation frames render.

The 'export trick' to get the model to animate properly in the tutorial was removing the all encompassing 'Anim-1' animation that encompassed all 4000 frames of animation.  If an animation overlaps other animations, it doesn't appear to play the smaller clips.


Robert
Dec 13, 2008 at 4:59 PM
Alright, I've discovered the problem.  I'm using the MaterialShader to change the texture, which seems to work perfectly.  To accomplish this, I implemented a very simple ModelInstanceShaderProvider class that returns 'false' for ProviderModifiesWorldMatrixInBeginDraw and 'true' for BeginGeometryShaderOverride.  When I comment out the 'model.SetShaderOverride' call, animation works perfectly, but obviously, I only get the default skin.

So, I have animation, but need to be able to change the textures.  Why would setting a 'MaterialShader' cause animation to not run?  And why do I have to set a MaterialShader just to change the texture?

Robert

Coordinator
Dec 15, 2008 at 6:02 AM
Edited Dec 15, 2008 at 8:04 AM

Hi Robert.

I'm pretty sure there is a nice and easy solution here.

In ModelData, there is a array of MeshData classes, which each have an array of GeometryData classes (very similar to XNA's model classes). However, each GeometryData also contains a MaterialData structure. MaterialData stores info about the material for that piece of geometry (The 'GetMaterial' method in GeometryData will return this). However, to make things easier, GeometryData will also create a MaterialShader based on that material data (the 'MaterialShader' property will return this shader).

When drawing a model without a shader override, these MaterialShaders will be used (The shaders stored in the GeometryData). You can feel free to change the texture in these shaders, just before you draw the model (doing this will add very little overhead). This would be the easiest way to change the texture on a model at runtime. The downside is that you have to change the texture in every MaterialShader, in every GeometryData, in every MeshData in your model... But in an ideal world there will only be one of each anyway :-)

The intent of ModelInstanceShaderProvider, is that you use it when you want to draw a model with your own custom .fx shaders. It's obvious the documentation doesn't make this clear enough, which is my fault, so it's something I'll need to clean up (A few others have had problems with this class - which is understandable).

For clarification, the reason you are not seeing animation is that the shader you are using (your own MaterialShader),  is because it does not have any bone transforms set. The 'BeginDraw' method of the shader provider passes in an array of bone transforms (when animating). The shader then has to implement correct skinning logic to show the animation (or in the case of MaterialShader, the 'AnimationTransforms' property needs to be set to a valid instance of MaterialAnimationTransformHierarchy*).

* I know, the names can get quite long :-)

Thank you though, your feedback is really appreciated! And I hope this helps

- I wonder, do you think the original model (that you had trouble with) would also have problems in 'normal' XNA, or other animation libraries?

Coordinator
Dec 15, 2008 at 8:06 AM

Hi. Quick question.

It says you wrote your original message on Saturday, is this the case, or is codeplex screwing up?

I ask, because I got both the notification emails just 2 hours ago (when I wrote my original reply). It'd be nice to know which is unreliable :-)