Questions and comments to hal {at} artofmagic.co.uk

2.4 Local and Global Transforms

2.3 Models and Entities -> Local and Global Transforms -> 2.5 Cameras

The "Model" built into the XNA framework is essentially a view of the content. However, it is also designed to be rendered and has a number of functions (that we've already seen and used) to render models on screen. The issue is that we don't want to "load" an entire model for every instance of a Machine - the ModelMesh data should be shared amongst them.

The simple solution seems to be to copy a set of transforms for each actual model and replace the transforms used in rendering with the per instance transforms.

There are lots of implications with this somewhat naive approach but it will suffice to get us up and running. We may have to revisit the hierarchy later on and whether or not our entity class represents an entire Model (as it does now) or a slightly more primitive object (something with a local transform, children and one or more meshes).

Entity class now has:

private Matrix transform_;
Model model_;
Matrix[] boneTransforms_;

We initialise during the constructor and use in the rendering function like this:

public void render(Vector3 cameraPosition, float aspectRatio, float time)
{
    // Create an array of Transforms which will hold the global (world) transforms of each bone.
    Matrix[] transforms = new Matrix[model_.Bones.Count];
    // Update the entities bones with any transform plans.
    applyTransformPlans(boneTransforms_, time);
    // copy this array of local transforms to the model
    model_.CopyBoneTransformsFrom(boneTransforms_);
    // The model "knows" the heirarchy and so can convert back to global (world) transforms for rendering.
    model_.CopyAbsoluteBoneTransformsTo(transforms);
    ...

At this point I think it is worthwhile talking about global and local transforms.

The model is made out of bits - these have an offset (transform) from the bit before and a mesh and some materials.

The relationship between head and hip is expressed as a local offset. That is "relative" to hip the head link has a location in space. This is all fine and dandy and that's the data we'll find in the art content files. The issue of course comes from the fact that the shader wants a "world" or global transform. The only transform we have for head is relative to hip. That means, for example, that if the hip has been spun around we would expect the head, the shoulder and the guns to have been spun around as well.

To transform down a hierarchy like this you get the parent transform to transform the offset, and that then transforms the next offset and so on.

It's not particularly complicated and all other engines I've worked with have cached versions of the local and global transforms so that you don't have to recompute them when required. You may be wondering why you would bother with a local transform at all. After all - you only need the global one for rendering right?

The local one is actually extremely useful for certain things as well. For example I want to spin the gun left and right, but that means left and right relative to the shoulder, not to the world. i.e. the frame of reference is important. If I had to compute global transform plans for this kind of thing I would have to work out angles of tilt and transform the angles accordingly. In effect you've just done a global to local transform (that is done in a similar fashion to the local to global transforms but uses the inverse matrix).

For now, I'm going to use the built in helper function  model_.CopyAbsoluteBoneTransformsTo(transforms) this function knows about hierarchies and applies and the parent transforms in order to give you a resultant set of world transforms.

This is is why it is a relatively "naive" engine.

  1. It doesn't trim out excess transforms (the hierarchy in the x file has twice as many transforms as required because of how the model was built).
  2. It copies and transforms LOTS of matricies on the fly. They are relatively expensive operations.
  3. The effect object tweaked (i.e. lots of changing state) for every mesh render.
  4. The model is built in an expensive fashion.

But having said that, we are now at the point (having added the transform plan concept as well) where we can render lots of models.

I have 20 models loaded in this scene. The 1st one has the same control keys bound to it and spins it's head in a crazy way.

Here's our current zip file.

RTSTest1_2.4.zip


Next: 2.5 Cameras

(c) Hal Angseesing 2007 All Rights Reserved.