Given the tools/art pipeline side of things doesn't get always get a lot of focus, we'll be starting this journey in Maya-land, which is where my objects are being modelled and animated. Here's my test tileset sitting happily in Maya - it's the spinning fan in the middle we're interested in today:
In order to get things into my game, the exporter first works out which sets of Maya surfaces should be grouped together to create a game entity (e.g. a character, a ground tile, a doorway). Then for each game entity, it works out which game objects it needs to create based on what it's found in Maya (e.g. was there a skeleton, did I find animation, what kind of shader is applied, have the objects been tagged with special game attributes, etc). Our fan object is pretty simple: a static frame mesh, and a blade mesh which has some rotation animation frames to make it spin around.
So what does matrix animation look like in Maya? The shot below shows Maya's hypergraph window, which lets you see the scene nodes and connections Maya uses to represent things. Understanding how this data is represented makes our job of exporting it much easier.
You can see there's a single animation curve driving the rotation of the fan's matrix. This is good - because sometimes the data we're dealing with can be a little more complex. Just for a giggle, here's Maya's data representation of smooth skinning that I had to sort out to get skinning/skeletons working. This example shows a trivial 3 bone skeleton with 3 different animations (walk, jump, and crouch) and a single IK handle - you can imagine how much data you need to work with for a full character!
Anyway - back to our fan. Now that we know how to pull the data out of Maya, the next step is working out how this should be represented in Milkshake-land. The first option I considered (and swiftly discarded) was just using the character skinning I already had. Doing this is more hassle on the art side, and a whole bunch more work in the engine. This left two serious options - and being an idiot, I decided to implement them both just to keep my options open.
The first (useful) option I came up with was to add support for generic animation curves on any object property in the game. Not only would this allow me to directly animate the vector and quaternion describing an object's transformation matrix, but I could use exactly the same animation code to animate material properties (colour, specularity, translucency, etc), physical properties (gravity, weight, bounciness, friction), lighting, script parameters ... pretty powerful if I do say so myself. It was only after I'd gotten it all working that I realised it wouldn't actually help to rotate my fan. Still - I'm sure I'll find loads of uses for this elsewhere.
The problem I hit was that there currently is no matrix for the individual shapes inside an object - just for the object itself. So while I could easily use my new animation system to rotate the whole object (including the frame), there was no way to rotate just the fan blade. This is one aspect of the scene graph I go backwards and forwards on all the time - adding in a layer of transforms between the object and the shapes is obviously flexible - but it forces you to deal with the whole local vs world space matrix issue, and adds an extra matrix multiple into nearly everything you do, from rendering, to collision detection to picking. So for now, I haven't found enough reason to pay the performance price.
So, off I went to option 2: add support for rigid binding into my skeletal animation system. In this solution, the exporter builds a dead-simple one bone skeleton to represent the transform of the fan, and attaches the fan to the bone (rather than skinning the verts across the skeleton itself). The beauty of doing this inside the existing skeletal animation system is that you can mix and match skinned and rigid binding: so a character's body can be skinned to the skeleton, but his ray-gun can be rigidly attached to his hand. I already had most of the code I needed for this kicking around (as I was using it to attach the character's head already) - but I did need to make it a little more generic. In the end, the toughest thing was actually getting the fan blades to show up correctly in the editor palette - so pay particular attention to how splendidly the blades show up in the editor palette in the shot below! Here's the end result: behold a static screenshot of the finished fan blades in the game itself (you'll just have to trust me - both the fan and the shadows are now spinning =)