Sorry for the OT posting here, but I'm trying to write a skeletal animation system in OpenGL and am running into some issues.

The system uses quats at each key for each bone to dictate how the bone should rotate. Each time I update the skeleton, I interpolate between the appropriate keys and multiply the quat by it's parent (if one exists) for the final rotation quat, which I can then convert into a matrix. The system relies on quat rotations that are relative to it's parent (obviously) and I think this is where I am going wrong. I am getting my data from a 3DSMax script. Basically the call boils down to:

(in coordsys parent MObject.Rotation)

Seems simple enough, however I wonder if Max is getting me in trouble because it is using a diffrent coord system than OpenGL is (y and z are swapped).

Anybody have any real-world experience in this area that could help me out? (Hopefully even some of you know a little bit of maxScript).

Again, sorry for this being OT, but I don't know of another body of graphics programers which are so easily accessible.

Edit: I should note that this approach has worked very well for my test cases of varying complexity, however as soon as the code is applied to a humanoid skeleton it breaks.

[This message has been edited by rgreene (edited 03-17-2003).]

jwatte

03-18-2003, 07:44 PM

The most important skill of all: debugging!

1) Export a skeleton with as few bones as possible, all in the identity pose. If you're using Character Studio, then create a simple skeleton, and concentrate only on the left leg; leave the other bones alone. Make sure you export node positions for each node.

2) Export an animation which first bends only the knee, then moves it back, then bends only the hip, then moves it back, then bends both.

3) Render your skeleton in LINES mode, based on the position of the bone and its orientation (as applied by the parent). Start with the identity (frame 0) -- this should look okay. If not, look at the data (rotate it around, or whatever) and figure out what's wrong. You might want to give each bone a distinctive color.

4) Now, slowly mutate the data; start by moving one step forward in the animation, and see what happens. Compare to what should happen. Inspect all data in the debugger (ideally, trace through all the code as it happens).

You should be going in no time.

I'm assuming that the calculation of point/orientation of sub-limbs already works right; i e you have to offset the position of the next bone by its delta to the previous bone, rotated by that previous bone's orientation. Since you're saying things work OK in testing, I'm assuming you have three-bone chains already working that way, and that's not the problem, but worth a check.

rgreene

03-19-2003, 12:40 AM

Actually, the code was working on 100% of the test cases. I found the problem today, and it was due to the asset (despite what the art dept. says, I knew it was their fault http://www.opengl.org/discussion_boards/ubb/smile.gif). All of my test cases that I built had the root bone's rotation at (0 0 0 1) (none), but the assets I was using gave them some rotation. Since I assume that all rotations are relative in object-space I assumed that this is what they wanted to have, when actually it was a world-space rotation. Thanks for the reply.

rgreene

03-19-2003, 12:41 AM

Oh yea, and another neat thing that I figured out (in case you didn't know, but you probably did) you can directly swap the y/z component of your input quaternion to convert the model from max's wacky-z-is-up space to a normal y-is-up space.

grisha

03-19-2003, 10:35 AM

Originally posted by rgreene:
Oh yea, and another neat thing that I figured out (in case you didn't know, but you probably did) you can directly swap the y/z component of your input quaternion to convert the model from max's wacky-z-is-up space to a normal y-is-up space.

Max space is exactly what you get in OpenGL. GL did't define wich axis is "up" - you can choose it just be assuming where camera is looking with identity matrix.
With Z - up identity camera positioned at origin and looking in -Z direction. In this case you don't need any coordinate swapping.