MD5 reader and new model animation system


I’ve written an MD5 mesh/anim reader for jME - although currently it doesn’t work like the usual model converters, so I still need to do some work on it. It only supports diffuse textures, so it won’t look as nice as the game yet.

For a quick example: EDIT: Changed site

It’s a simple animation of a Doom 3 sergeant using the left hand pointing animation. You need to select your Doom3 .pk4 file, I’m using the demo so for me it’s C:Program FilesDoom 3 Demodemodemo00.pk4. I assume it’d work fine if you use the main Doom3 game pack file instead, but I haven’t got the game so haven’t tried it.

I’m still in the process of finishing it off, I’ll post the source code for it all next week. The big problem I came across was that JointController doesn’t seem to handle vertices being affected by multiple bones.

I’ve ended up writing a completely new skeletal animation system. This separates the model definition from the model instances, to prevent duplication of data when using multiple instances of the same model. It also supports animations as entities in their own right, so animations can be swapped around at will. When I’ve finished it, it’ll support interpolation between animations and separate ‘action’ animations that override certain bones (to allow running-while-firing and other such situations).

Take a look, and feel free to ask questions. As I said, I’m away for the weekend so I’ll post source code next week.

Looks great! (FYI: works on the real game files for me by using pak002.pk4.)

Let us know how we can help. I’m looking forward to seeing your custom animation code.

JointController wasn’t really optimized for multiple bones affecting the same vertex. I was planning on writting a new one for MD5. Very glad you got to it first. If you get it polished up and commented, I should be able to convert it to jME usable rather easily. If you want to do it yourself, just check out how models are written. You basicly just add an “instance of” catch for your mesh and controller, and write the fields in a HashMap. If you need help following the code, let me know.

OK, animation stuff still not ready to post :// but going to get it sorted out hopefully today or tomorrow… although I probably need to do some more documentation to explain it sometime.

Current demos are on (EDIT: Changed site) - two .jnlp files, one just shows a marine and is standalone, the other is a full model viewer for Doom3 - it works fine on the demo (although some models are obviously missing) but I haven’t tried it on the full game (which I don’t have).

Looking good!

OK, there’s no documentation, but if you go to that url again, there’s an animation.jar (which contains source and classes) and uml.png (which is a vague, probably not proper UML diagram of the main classes in the animation package).

A bit tired, but I’ll try to explain the code so far as coherently as I can:

The classes Model, Mesh and Skeleton describe the definition of a model. Unless you’re writing an importer, you only need to worry about Model. Currently MD5MeshReader returns a Model (it’s not a proper jME importer yet).

Each viewable model instance is a ModelInstance. Currently ModelInstance has a getNode() method to get a spatial to add to the scene graph, but in a later version it’ll extend Node.

Animations are controlled by an Animator object. This extends Controller, and is added to the Modelnstance’s node in the constructor of Animator (hence you don’t need to do addController()). Currently the Animator only handles a single animation, animation blending will be for later.

You can set the current animation playing on an Animator using the setAnimation and resetAnimation methods. The difference is that setAnimation sets the current time position to be the same distance through the animation, whereas resetAnimation goes back to the start. If the animation is null, the model’s bind frame is used.

Note that currently if you don’t set and an Animator on a ModelInstance you won’t even see the bind frame - I need to fix this :slight_smile:

Animations contain an array of KeyFrame objects, which are self explanatory really. MD5AnimLoader loads Animation objects.

That’s the general overview… Feel free to ask me questions :slight_smile:

Still TODO:

Comment the code :slight_smile:

Add animation blending

Make ModelInstance extend Node

Show the bind frame by default without an Animator

Convert the MD5MeshReader and MD5AnimReader to be proper jME importers

Allow the animation objects to be persisted in a .jme binary file (and the XML file)

Convert JointController/JointMesh to be a different type of Mesh, and abstract out Mesh so different types are available

Rewrite all existing character model importers (e.g. MD3) to create Model objects rather than Nodes.

Write a new Controller that uses the physics code to do ragdolls :slight_smile:

Implement IK :slight_smile:

That’s enough to be going on with for now :slight_smile:

Write a new Controller that uses the physics code to do ragdolls

If you mean to integrate it into the jME Physics System, you should know that we're planning on some classes to ease up/formalize creation of ragdolls. More to come soon.

If you'd like to help us out with this, let us know :)

I’d like to help with ragdolls - but currently I don’t have the time! Sorry.

All I’d need to be able to do to integrate ragdolls would be to get the calculated positions/rotations for each joint and copy them over to the animation controller each frame, which shouldn’t be too hard to do. I haven’t had enough time to look into the physics stuff yet, wish I did!

OK, I’ve not had as much time to work on this as I’d like recently - real world stuff (selling my house) has been getting in the way.

I’ve got the simple stuff done (ModelInstance now extends Node, and the bind frame is show by default), and I’ve recoded some of it to work better for animation blending and animation events when I do them. I’ve also realised that this model stuff is more general than I originally thought.

Currently, the only supported mesh definition is a skeletally-animated one, with each vertex affected by one or more joints. But using different mesh types, I’m going to do vertices affected by only a single joint, plus each ‘joint’ being a separate vertex (basically, non-skeletal keyframe animation). Hope that makes sense. Anyway, what this means is that models that are used multiple times can share vertex or skeleton data, depending on the type of model, but have separate skins. This would cut down memory usage and allow new instances of an object to be created quite simply by just creating a new ModelInstance based on a loaded Model.

Hope you got all that… Basically, abstract out the model definition data from the instances of that object.

Anyway, currently the jME binary format loader wouldn’t support this kind of setup as it can only read in Node objects, not my new Model class. I’d need to either create a separate reader for loading Models in (possibly .jmem, for jME Model?) or modify the JME binary format and reader/writer, which would be a bit presumptuous of me considering how new I am to the project :slight_smile:

When I’ve got the code commented better and some other features done, I’ll try to write a small tutorial for this animation system, to make it clearer what it does.

Currently todo before I do that:

Animation blending

Comment the code

Hope this is reasonably understandable, I’m not very awake today. Sorry!

I forgot to mention before: The animation stuff I’ve done so far has moved to, with an outdated UML diagram. I’ll put my tutorial up there when I write it.

The rotation/position thing is simple enough with the new design, should be a treat once its finished!


OK, latest update:

Due to being full of flu for a week, I’ve only just got the animation blending stuff I did working. Seems to work fine, if you go to the usual URL and look at the Doom 3 model viewer, it blends between animations when you change between them. I’ve also refactored and repackaged a large chunk of the code. All still available from:

Sorry it’s taken so long, a combination of real life and illness has kept me from coding as much as I wanted to recently :frowning:

I’ve put up the source code as source.jar if anyone wants to have a look, still embarassingly undocumented and half in my personal coding style, so needs reformatting. Feel free to have a browse, I’ll post again when I have another version with half-decent documentation. I’ll be documenting the code I have, put that up for people to look at and then write a tutorial on how to use the animation system, and another on how it all fits together internally. Unless anyone would prefer some kind of tutorial first? The demo programs should be simple enough to understand though.

Any comments on the source code or the design very welcome, I could do with some feedback from someone else. I’ve looked at the Cal3d suite recently, and it discovered that my design is very similar to theirs in a lot of ways, which has reinforced my belief that it’s a good design. Any thoughts?

The current code partially supports non-skeletal animation, once I’ve done the rest of the above I’ll get onto writing converters for the other model types already implemented and get normal keyframe animation working, so I can test that properly. Also I don’t support partial animations or animation sequences very well at the moment, which could be awkward for the MD2 importing.

Oh, and for the ragdoll system, once DP and Per have got the physics side working, it can be implemented as a simple Animator which sets up the translations and rotations of each limb accordingly, so it should be a piece of cake to plug in. The documentation on the source code should be enough to go by on.

Another update to come when I’ve got the documentation sorted out a bit and a small tutorial written.

Anyway, off to bed now, I have a long weekend of real life stuff coming up, so no more documentation 'til sometime next week :slight_smile:

GREAT! :smiley:

I download the source but it doesn’t compile unless I comment out these lines can’t remember the errors exactly but its choking on “signum” complaining that it is undefined if the code is active will post full error soon setting up new pc at the moment, remembered at the office this morning

if ( current.jointRotation != null ) {
                    rotDiff.slerp( last.jointRotation[ j ], next.jointRotation[ j ], delta );
                    Quaternion cur = current.jointRotation[ j ];
                    if ( Math.signum( rotDiff.x ) == Math.signum( cur.x ) ||
                         Math.signum( rotDiff.y ) == Math.signum( cur.y ) ||
                         Math.signum( rotDiff.z ) == Math.signum( cur.z ) )
                    rotDiff.addLocal( cur );
                    if ( rotDiff.x + rotDiff.y + rotDiff.z + rotDiff.w > error )
                        continue main;

Doh! My fault, I’m using a 1.5-specific method. I’ve modified it and uploaded a new version of the source and runtime code.

I’ve also fixed the movement direction bug, where animations were moving sideways (walking etc.) in the Doom 3 model viewer.

thanks does your animation stuff have its own translation control methods because I find it easier to animate the in models in place mode handle actually forward etc. motion in the engine, that seems simpler timing wise

it would also be good to know if I can manipulate md5 animation speeds aswell e.g slow motion

Which requirements for your MD5 importer and your new skeletal animation system?

  • jME 0.8 or jME CVS?
  • LWJGL 0.9.4 or other release?
  • Java SDK 1.4.:? or 1.5?

    Thaks, chaosdeathfish! :smiley:

    Bye, bye

thanks does your animation stuff have its own translation control methods because I find it easier to animate the in models in place mode handle actually forward etc. motion in the engine, that seems simpler timing wise

it would also be good to know if I can manipulate md5 animation speeds aswell e.g slow motion

You can manage the positioning manually, but it would probably involve resetting the position of joint 0 to 0,0,0 each frame, and adding the difference since the last frame (before you reset it) to the local translation. You may have to do this by creating a new Animator subclass, and adding that to your AnimationManager as the last animator.

Currently the animation stuff fires off an event when an animation wraps round - in my own code I just add the difference between position of joint 0 in the first and last frame (multiplied by the weight) to the local translation of the ModelInstance - doing this automatically per frame or per update could be added later, but I've got lots of other things to do at the moment, sorry! :(

Animation speed can easily be modified - the Animator class has a setSpeed method, which should work the same as that in the Controller class - ie. 1.0 is normal speed, 0.5 is half speed, 2 is double speed etc.

Which requirements for your MD5 importer and your new skeletal animation system?

- jME 0.8 or jME CVS?
- LWJGL 0.9.4 or other release?
- Java SDK 1.4.Question or 1.5?

The current binary version requires jME 0.8, but the source requires the CVS version. The only difference currently is the TextureManager.loadTexture calls, which need an extra parameter under the 0.8 release (just pass false), so easy enough to change.

The LWJGL version needed is whichever is required by the jME release you're using - 0.9.4 (iirc) for the 0.8 release, 0.9.6 for the latest CVS version.

JDK1.4 and 1.5 should both be supported - I've tried to keep all my code 1.4-compatible, let me know if anything doesn't work properly under 1.4!

Hope that helps, let me know if there're any more problems. I'm still working on documentation, and some API changes are inevitable, especially the Animator stuff, but I'll try to let you know about anything like that.

Just to let everyone know - I’ve not had time to work on this recently due to Real Life Stuff getting in the way, but I’ve still got every intention of getting back to work on it, just as soon as I have the time. So it’s not dead, just on hold for a couple more weeks.

That is all :slight_smile:

Good to hear :slight_smile:


I have finally tested your loader using

  • your source code (source.jar)
  • the marine mesh found in to the d3anim.jar
  • LWJGL 0.96a
  • jME cvs
  • Java SDK 1.4.2_04!
  • Pentium III 600 MHz, 192MB RAM
  • Windows 98 SE
  • Nvidia RIVA TNT2 16MB

    I have loaded the sources into Eclipse, correctly setted classpath and native path, and everithing worked great!

    I’m really happy to see that animation, textures and mesh loaded greatly!

    Thanks, thanks, thanks, thanks :wink: :smiley:

    Bye, bye