First, I must give a special thanks to Latch for all his examples, explanations, and help with the quaternion mathematics. None of this would have been possible without him.
The Problem
As Latch and I discovered when working on our respective animator programs, DB 1.20 is incapable of rotating any limb in the region 90..180 degrees. If the limb is supposed to move from 90 to 180, it will do so by moving the long way round and rotating from 90..0..270..180.
It is possible to force the limb into this 'forbidden region' by setting keyframes with angles up to 119 degrees. However, as soon as the limb strikes this value it will reverse direction and move the long way round.
The Simple Solution
DBC 1.20 is incorrectly interpreting the limb rotations which make up the animation. Recalculating these rotations will make the animation play correctly, and the "Animation Converter.dba" code snippet in the attached Zip file will do just that.
The code makes use of my new QuatMath dll (included in the Zip). The full Delphi source code for the dll is also included (it's the .dpr file, for those of you who don't know Delphi)
The Complex Solution
Limb rotations are stored in .x files as quaternion keyframes (a quaternion is a four float number - one float (w) defines how far to move around an axis defined by the next three floats (x,y,z)). These rotations were calculated from ordinary 0..360 degree angles (Euler angles) but DirectX assumes them to have been wrapped around into the range 180..-180 (so 270 is defined as -90).
This wrapping is important, because different quaternions are generated in each case, and this controls which direction the limb moves in. For example, a quaternion for the rotation 0,0,270 would move the limb +270, but a quaternion for the rotation 0,0,-90 would move the limb -90.
In most (and I think probably all) other programs, there's a built in failsafe used when animating to ensure that the limbs always move the shortest distance - it's called quaternion slerping. This mathematical algorithm starts by comparing two quaternion keyframes and finding Cos(Theta), where theta is the angle bewteen the two. It Cos(Theta)<0, then Theta is greater than 180 degrees and so the limb will be moving the long way round. This gets corrected by inverting the second quaternion (same destination, but reached by moving in the other direction) and using that in the calculation.
DBC 1.20 is unusual in that it does not perform this check for Cos(Theta) being negative. As a result, limbs can be made to move in
any direction by simply placing the angles in the range -360..360 instead of -180..180.
To get existing animation to run correctly, I've written a .dba animation converter, along with a QuatMath dll (all enclosed in the attached Zip). The converter takes any ASCII .x file and passes each quaternion keyframe to the dll, where it gets converted to Euler and back to quaternion. The dll also looks at the previous keyframe and checks to ensure that Cos(Theta) between these two keyframes is positive so that the limb will always move the short route. The corrected quaternion keys get written to a copy of the input .x file.
As far as I can tell, the output .x file plays exactly the same in DBC 1.20 as it did in DBC 1.13. Unfortunately, 3ds files can only be corrected if they are first converted to .x files using the 3ds2x command, and .x Binary files can't be corrected at all.
"I wish I was a spaceman, the fastest guy alive. I'd fly you round the universe, in Fireball XL5..."