Where to go from here?

Topics: Developer Forum
Jan 28, 2007 at 1:54 AM
We talked about how the runtime data structure should be different, and that it uses too many objects. I agree that it uses a lot of objects, but to set a matrix palette parameter, you have to pass in an entire array and can't split it up. So, this is one thing to look at, but really this change won't take long to implement if we decide to do it.

What we add from here? I believe we've covered most of major features.
Jan 29, 2007 at 7:16 AM
One feature that came to my mind and which I have seen on other animation engines is the possibility to attach other mesh(es) to specific nodes.
That is give an character a sword in his hand bone/frame. That would at least be a feature I could use very well on my program (and I am sure other can use this too).

Otherwise congratulation to all for your wonderful work. I am very glad the animation lib exists.
Jan 30, 2007 at 5:26 AM
I believe that what people want first is more options of animation blending.

Run-time blending of animations is important because of interactive nature of games. You can't predict when a game character would want to switch from standing to running to walking: it is defined by game events. And it is not possible to have pre-calculated transitions from every frame of every motion to every other motion. Therefore, run-time blending of animations is a common approach.

Smooth transition from one animation to another (replacing previous animation) is just one kind of transition.

One more common case is "additive" motion blending. Like, a running "tiny_4anim.x" waves hand on some game event.

In general, motion data in modern game can come from a variety of sources:
- keyframed animation track;
- blending of two or more keyframed animations;
- ragdoll motions calculated by physics engine (please note that this comes as an absolute pose);
- a programmatic "behavior" (like character randomly moving head when speaking, or character swinging sword in some fancy tragectories);
- inverse kinematics solver (common for "look at" behaviours).

For a real-time strategy (RTS) like Total War, it is probably possible to have all animations in a form of pre-calculated absolute pose keyframes, because this would save significant CPU time (no need to calculate absolute pose in run-time), and RTS needs to display hundreds of charactes at ones, at expense of some loss of animation quality.

But other types of games (like first-person shooter or RPG) will need run-time motion blending. And the "additive" motion blending needs to have relative bone poses at run-time, as far as I understand.

Jan 30, 2007 at 6:03 AM
About run-time data structures:

1) This is an implementation detail so this is significantly less critical then API or new features. I've only mentioned it because that was what I was thinking lately - I need very high performance for my own game which is in fact a very special case compared to typical games. Currently, Animation Component Library performance is mostly limited by Vertex Shader performance - that means for people without LOD management it is too early to think about other performance bottlenecks.

2) In the long run, current run-time structures may lead to potential performance bottlenecks.
Current implementation has SortedList<string, BoneKeyframeCollection>, where BoneKeyframeCollection is a List of structs (which is a ref type). Since BoneKeyframe is a struct, a List<BoneKeyframe> (which is implemented as array in .NET 2.0) is stored in memory as an array of structs, that is continuously. But List<BoneKeyframe> is a class, that is a ref type. So SortedList<string, BoneKeyframeCollection> is a SortedList of ref type objects, not value type objects.

For an animation track with 50 channels (bones), we have 50 (plus 1) ref objects. Imagine a game with hundreds of animation tracks. For 100 animation tracks, this would be around 5000 live objects. And XBox's Compact .NET Framework's garbage collector slows down if the number of live objects is over 2000. This is less of a problem on PC since Windows .NET VM has generational garbage collector.

One more potential problem is poor cache locality for a typical inner loop in AnimationController's UpdatePoses(). Pose calculation code goes over all bones' matrices of one frame in UpdatePoses(), but that data are not continuous in memory. This is not a big problem because currently the speed of Draw() is actually limited by Vertex Shader performance, not by CPU.

My idea is to have just one big chunk of binary data (an array of Matrix) in ModelAnimation. This would be 2 objects per ModelAnimation instead of NumChannels+1 objects. This would also increase cache locality for inner loops of UpdatePoses().

I know premature optimization is evil. Could not resist, mate!

Jan 30, 2007 at 6:19 AM
I am actually wrong about 2000 object max, but the number of live objects does affect performance:

Jan 30, 2007 at 10:40 AM
Check my post in the user forum under "Question to users."

I outline a proposed change set that would add animation control and blending at a per bone level, which would allow additive blending.
Jan 30, 2007 at 10:42 AM
I guess we still have a lot of work to do!
Jan 30, 2007 at 11:08 AM

first of all I'd like to thank you for putting together this library. Very nice work :)

Obviously Microsoft decided not to add an mesh animation component to XNA because there are many different needs, and it's impossible to make everyone happy. Like Mnikonov said in a different post, the current animation playback/blending is sufficient for RTS-like requirements as there is no "mixing" involved, either your little soldier/jeep/tank moves forward, turns left/right, shoots or dies - blending between a max. of 2 animations is sufficient for that.

Please do not misunderstand this post, it's not destructive critique. This posts sole purpose is to take a look at how experienced developers do it (and maybe get one or two "Aha!" like I had).

I've been curious and taken a look how FPS games deal with it (in this case Half-Life 1 .smd), unfortunately my attempts to decompile .md5 models failed so cannot post an analysis of that, yet.

Animations for NS Marine Playermodel:

1 skeleton Reference (neutral pose with arms stretched, this was the pose they rigged)
5 death Animations (4 stand, 1 crouch - no ragdolls in HL1 afaik)
4 idle Animations (2 stand, 1 crouch, 1 swim)
1 jump Animation
1 run Animation (forwards)
1 walk Animation (forwards)
1 swim Animation

Also for every weapon the character can hold:
2 "blend" aim References (aiming up, aiming down)
2 "blend" attack Animations (attacking upwards, attacking downwards).
1 reload animation for each weapon (character standing, legs not moving)

The feet were in a pose as if the player was standing. For all of the weapon hold frames the character could play while standing there was a second set for crouching (spine leaned forwards, so you couldn't just switch legs animation).

Reference = 1 single frame
Animation = multiple frames

It appears they used the 2 "blend" (up and down) poses and decided by the vertical viewing direction of the player how much to weight them.

Most notable was the definition of the model in the .qc file, there they declared Animation tags if it was loopable (walk) or not (reload), frames/second, etc. I'll post the whole .qc file if desired, but it's alot of text and I don't want to spam :P

Basically this is a summary of the 5 chapters:
1. Header/Paths/Scaling
2. Attachments for mounting weapons at the hands (number, bone name,1x Vector3 offset)
3. Controllers at the spines, most likely for upper torso animations that override walk/run (number, bone, weighting)
4. Hitboxes (group number, bone name, 2x Vector3 offsets)
5. huge Sequence list assigning .smd animations to asset names, set looping/fps, set blending, set weighting.

Most important i found the fact what level of control they assign to the programmer, and to the artist. The way the implemented it the artists can fine-tune the model without touching any code, and any model that supplies the correct asset names will probably run with the game.

Hope this helps!

Jan 30, 2007 at 12:20 PM
Thanks for the post. All help from the community is appreciated, and at this point I am sort of relying on community suggestions/info to move forward. I believe that adding in the per-bone blending and animation control system will allow for a user to interface with the animation controller to create most of these features. Eventually, I'll have to add the option to blend 3-4 animations together, but that shouldn't be too hard since the algorithm is well documented.

I realize that the purpose of your post was to provide information on another animation system, but I'd like to address the issue of the general utility of an animation library.

I think that it is possible for this library to suit nearly everyone's needs (short of professional games made by medium/large companies) for a few reasons:

1. It is open source, so it allows complete customization and at the least, provides a starting point.
2. Anyone can contribute since it is wiki based. Although there are only two code contributors at the moment, I expect that as we continue to add new features and revise the lib, more people will contribute.
3. XNA provides a high level of class standardization

As for Microsoft not including an animation API, I believe this has more to do with time constraints than anything else.

If the changes discussed in the "Question to users" forum are implemented, as well as an inverse kinematics solver, am I wrong in thinking a more specialized animation library can such as the half life 1 api can be created from the XNA Animation Component Library?
Jan 30, 2007 at 12:23 PM
Whoops, what i meant by "Question to users" forum is the "Question to users" thread in the Users forum.