Or, a tutorial on how to use and abuse the tools we have to do strange an wonderful things, coupled with the many ways I broke KnightErrants GOAT toolkit, the things he did to fix it and make it Bwian proof, and the things I discovered it could de that KE had not intended, but I went ahead and did anyway!
This will be a series of posts building up a knowledge base, and outlining what we know, backed up nby some realtime development projects so you can see the steps in action.
Part 1: The Known Universe of Animation.
I want to open this with a look at the basic structure of the MESH / Animation relationship, and how things link together. This is an area that os often not well understood, and ends up with people confusing themselves horribly.
What is where?
First, you need to understand what the structure of the models and animations is and how they are linked. The game uses a skeletal structure that is animated to make the game models walk, fight, die etc. The animation files contain that skeleton, and the data that tells the game how it will move. The MESH file contains the actual model geometry. Each vertex of the model is ‘rigged’ to a bone so that when the bone moves, the surface of the 3D model moves. Each vertex can be influenced by more than one bone, and in varying degrees. This allows the model to move in more natural ways than was possible with RTW, where a vertex could only be moved by a single bone. Important note…
THE MESH FILE DOES NOT CONTAIN THE SKELETON
Don’t forget this. When you create a model in MS3D, you will have seen a skeleton in there, and rigged the vertices to it….so it must be there, I hear you say. No. That is provided by the model importer when the MESH is converted to MS3D format. It is there purely so you CAN rig the model. Bone data is only used to tell the game which bone affects which vertex.
When we begin to modify things, it is important to understand this, since the links between the MESH and the animation CAS file must be right for all to work.
Summary:
MESH – model geometry, skin rigging
CAS – animation file, containing skeletal data and rotation / position data for the bones.
Move a bone in an animation, and the MESH will follow if rigged to it. Rig a vertex to 2 bones and it moves proportionally with either bone movements. Just like a real skin.
A picture of the different parts of the mesh and cas files is shown here:
We trace the way vertex <3> (that’s just an index for it) gets moved. It is paired with a primary bone assignment number of 6 (we’ll ignore its secondary bone assignment for this). Number 6 corresponds to the bone string “bone_head”. That’s the only skeleton information in a .mesh file. That bone string gets paired up with the information in the .cas file. In particular, there is offset to the quaternion rotation data
1824, and another offset to its position data at offset 7448. This is the mechanism the game uses to know how to move a given vertex. The other information needed is shown in green, one has to construct the skeleton using the hierarchy tree and the bone offsets at the bottom of the .cas file. We’ll treat that in a moment when we discuss the .cas file format after it has been converted to a .txt representation.
This is quite technical stuff in places, but it hopefully serves to clarify how the various parts fit together. We need to have a basic understanding of this before we look at the individual parts, or we risk confusion. I know....a sentance with words like Quaternions and Offsets in it is confusin enough...but I am talking about real confusion here!
Part 2: Tools to open Pandora's Box of animations
OK..to do the next bit, you will need to get some tools in your toolbox. You will need to obtain the latest version of KnightErrant’s GOAT toolbox. This contains the means to do all the things we will need to do. Also, you will require a recent version of Milkshape 3D (version 1.8 onwards) with the ‘zero rotations’ plugin present. We will cover what this is and does later on, but suffice to say, if you don’t have it…bad things will happen and frustration is the certain result!
Also required are the stock animations supplied by Caliban and downloadable form TWCenter.net. These provide the building blocks from which we will work.
Checklist:
1) Latest version of GOAT – free download
2) Python framework (pre version 3) – free download
3) Milkshape 3D plus plugin - not free but worth it
4) Notepad (or preferred equivalent) – free download
5) Full set of animations – free download
6) This guide!
CAS Files
In order to look at the data in a CAS file, you first need to convert it into a format that a human can read. More advanced beings like KnightErrant have made this possible, and should be suitably venerated for their skills. Using GOAT, you can turn any of the standard CAS files into a text file, and play around with the contents. These animation files also contain some useful hooks into other things, such as where riders are attached to mounts, and some of the hard coded behaviour for the mount classes. If the game thinks it’s an elephant, it will let it do elephant things. So, let us look at what an animation file is made up of:
The first line should look something like this:
3.210000 38 9 0 2.20000004768 1 0 104 104 104 1 0 104 104 104
The 1st number (red) is the animation version number. Whilst playing about with some of the unused animations, I have found older versions lurking around, but these do not work well with the game. Changes have been made in formats. It is a guide.
The 5th number, (blue) is the animation duration in seconds. The example animation takes 2.2 seconds to run. Standard animations run in 0.05 second frames, which is 20 frames per second. The animation in the example has 45 frames ( 44x0.05 plus start frame) The last part of interest here is the section in green. This is the header part which tells the game what sort of unit the animation is for. Human, Elephant, Horse etc. A matching footer is needed, but by changing this, you can do some quite interesting things!
The next line should look something like this:
30749 0
The number is red is the chunk size of the animation. I am not sure how critical this number is when editing or converting. The number after it is always 0.
The next line should look like this:
24 0 0 1 2 3 4 2 6 7 1 9 10 11 12 9 14 9 16 1 18 19 1 21 22
The number in red is the total number of bones in the model. This is made up of a Scene Root bone, plus, in this case, 23 actual model bones. The limit for model bones has been found to be 25. Problems occur in terms of display if more than 25 model bones are put in a model. The numbers that follow it are the hierarchy tree for the bones. Both the model and scene root bones are always zero. The numbers relate to the bone names below in order. If you cross-check, you will see that value 1 bones attach directly to root, and so on. This controls the order in which rotations are applied, and MUST be correct if your model is to move as intended. When making custom models, the extract skeleton function in GOAT will create a text extract that shows this structure for a custom model.
Let’s do a quick example for the human skeleton just to make this more concrete. If you number all the bones in order with a zero-based index you obtain a list like this:
Bone Bone Name
Index Array
0 Scene Root
1 bone_pelvis
2 bone_RThigh
3 bone_Rlowerleg
4 bone_Rfoot
5 bone_abs
6 bone_torso
7 bone_head
8 bone_jaw
9 bone_eyebrow
10 bone_Rclavical
11 bone_Rupperarm
12 bone_Relbow
13 bone_Rhand
14 bone_Lclavical
15 bone_Lupperarm
16 bone_Lelbow
17 bone_Lhand
18 bone_LThigh
19 bone_Llowerleg
20 bone_Lfoot
Now put the hierarchy tree or array next to it and fill in the corresponding names. Then you get this list:
Bone Bone Name Hierarchy Parent Bone
Index Array Array Name Array
0 Scene Root 0 No parent, by convention a 0 goes here
1 bone_pelvis 0 Scene Root
2 bone_RThigh 1 bone_pelvis
3 bone_Rlowerleg 2 bone_RThigh
4 bone_Rfoot 3 bone_Rlowerleg
5 bone_abs 0 bone_pelvis
6 bone_torso 5 bone_abs
7 bone_head 6 bone_torso
8 bone_jaw 7 bone_head
9 bone_eyebrow 7 bone_head
10 bone_Rclavical 6 bone_torso
11 bone_Rupperarm 10 bone_Rclavical
12 bone_Relbow 11 bone_Rupperarm
13 bone_Rhand 12 bone_Relbow
14 bone_Lclavical 6 bone_torso
15 bone_Lupperarm 14 bone_Lclavical
16 bone_Lelbow 15 bone_Lupperarm
17 bone_Lhand 16 bone_Lelbow
18 bone_LThigh 0 bone_pelvis
19 bone_Llowerleg 18 bone_LThigh
20 bone_Lfoot 19 bone_Llowerleg
And now you can see the child to parent relationship that forms the skeleton. You can do the same exercise with the elephant hierarchy
24 0 0 1 2 3 4 2 6 7 1 9 10 11 12 9 14 9 16 1 18 19 1 21 22
using the elephant bones listed below and find out how they are wired together to form the elephant skeleton.
The next line should look like this. It will be longer than shown, since I trimmed it to fit the page!
45 0.00000 0.05000 0.10000 0.15000 0.20000 0.25000 0.30000 0.35000
The line shows the total number of frames, followed by the ‘time ticks’ at which each frame of animation plays. As we established earlier, there are 45 frames. The start frame is at 0.0000 and they then go up in increments of 0.05 until they reach 2.2 (the total animation runtime) Unless you wish to change the duration of the animations, these do not need altering.. The 0.05 is fixed, but you can reduce the number of frames in an animation to speed it up.
The next block is the part which defines the skeleton:
Scene Root 0 0 0 16560 0 1 0
bone_E_platform 45 45 0 16560 0 1 0
bone_E_back 45 45 720 17100 0 1 0
bone_E_right back thigh 45 45 1440 17640 0 1 0
bone_E_right back lower leg 45 45 2160 18180 0 1 0
bone_E_right back foot 45 45 2880 18720 0 1 0
bone_E_left back thigh 45 45 3600 19260 0 1 0
bone_E_left back lower leg 45 45 4320 19800 0 1 0
This is only a portion of it, but it is enough to show what the thing is made up of. The first column os the actual bone name. If you are editing a model in MS3D and want to add a bone, or change bones name, you must make the corresponding changes in the text file to keep the animation data and model data the same. Though there are no bones in the mesh, it must have correct links to the animation. If I changed the bone_E-platform to bone_saddle in the text file, the game would not be able to make the link between MESH and animation. Be careful if you are changing things here!
The next column is the number of rotation frames for that bone. If there are no rotations, the value is zero. Otherwise, it should equal the number of frames. Each animation should have the same number of frames, or else a zero value. In this case, each is 45 except the root which has 0.
The column after is the positional frames. These are numbered either for the number of positional frames, or zero. In this example, there are positional frames for all the frames except root, so all are 45 except root which is zero. Again, the value should either be the total number of frames or zero.
The next column is a little more complex. This points to where in the animation file the data for that bones rotations are held. The calculation is:
Frames x 4 x 4
In our example, it is 45x4x4 = 720
When you look at the numbers, the root starts at 0, and then goes up by increments. The first increment is zero, since the root bone has a zero value for rotations. The next bone has rotations, so the number is 720, giving the correct offset to point to the Quaternion movements for the rotations of the bone. The last bone value in our elephant_walk example is 15840, which is the start point for the last rotations. The next column starts at 16560 … exactly 720 on from the last block’s start point.
The 4th column is the offsets that tell the animation where the positional data is. It starts after the last chunk of rotations, as detailed above. The increments, however, are NOT the same. Where the 2nd column was zero, the number does not increase. There is no data, so the number does not alter. Where the frames have positional data, the number has gone up by 540, not 720. The value is:
Frames x 4 x 3
In our example, it is 45x4x3 = 540
The positional data has only 3 elements, not 4…hence the reduction. If you are changing the number of frames, or reducing / increasing the number of bones, the offsets for the data have to be re-calculated. The maths isn’t complex, but an error here means that the CAS file will apply wrong rotations, or will fail to convert back to CAS when you have edited it.
The bulk of the rest of the CAS file is made up of the actual rotational and positional data. For rotations, there are 4 columns for the quaternion values. These are the ones the game uses, but they are not logical x/y/z numbers. Thankfully, KnightErrant has also added in the x/y/z numbers that relate to the axes in the MS3D model, with similar orientation.. When the text file is converted back into a CAS file, GOAT ignores the quaternion values in the text files, and recalculates them from the other values. ONLY change the x/y/z euler values, or your changes will be ignored when you convert back to CAS.
The positional values show proper values ONLY for the root bone for the model, bone_E_platform for the elephant. There are no values for scene root as noted earlier. All the other positional values are either zero or very small numbers which are, effectively, zero values. The game is moving the root bone only, and rotating the joints relative to that point to animate the model.
The last piece of data in the animation file is the footer. These, as with the header portion, are specific to the type of unit the animation is for. I do not confess to know what the numbers do or mean, but they can be copied and pasted. Keep them paired with the correct header or problems occur which will prevent correct conversion back!
This leads us on to the creation of whole new skeletons and custom animations to go with them. It’s slightly more involved, but it is easy enough to do once you understand what is going on. I have begun to do a lot of the animation using the basic text files, since you end up with neat absolute rotations. I still do key-framing in a modelling program for brand new stuff, but there is the opportunity to save a lot of time and effort with text editing…as I hope to show in this section!
Edit due to slight change of plan .... Tutorial 1 is now : ADDING A NEW BONE
and continues in my next post