Sign in to follow this  

Transformation Matrix

This topic is 4836 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I think all of the SkinMesh experts have accended to some other plane of existence. I'm gonna keep this question very simple, in hopes of getting at least one reply. You know the TID_D3DRMFrameTransformMatrix type templates that always follow a TID_D3DRMFrame in the X-File format? What the hell are these for? If I read in the transform matrix following each bone in the X-File, what happens if I apply those matrices to my bones and render it? Will the model be in it's pose that existed in the X File? If not, what do I need to do to these matrices to make them put the model in it's default pose? Please ignore the rest of this if you can answer that question. All of my animation matrices are screwed up. In your standard walk-animation, the model's thighs are bent so that the feet are kicking it in the head. The transform matrices included after each bone give me the same results when applied DIRECTLY to the mesh hierarchy. Please tell me if I'm doing something wrong here.
#1- Set all bone states (I set these DIRECTLY from the file)
#2- For each bone in hierarchy..
     #2a- Set Final-Matrix of this bone to Offset-Matrix
     #2b- Multiply that with the state of the bone (from #1)
     #2c- Multiply that with the Inverse-Offset-Matrix (inversed #2a)
     #2d- Multiply that with our parent's Final Matrix (see #2e)
     #2e- Pass our Final Matrix to each child bone
#3- Throw Final Matrices into the shader and render
Here is the hierarchy part in real code..
VOID CBone::ComputeHierarchy(MATRIX *States, MATRIX *Finals, MATRIX &Derive) // Cycles the states through the heirarchy
{
    Finals[Index] = Offset * States[Index] * InverseOffset * Derive;

    // Compute Children
    CBone *b = FirstChildBone;
    while(b)
    {
        b->ComputeHierarchy(States,Finals,Finals[Index]);
        b = b->Next;
    }
}


See any problems with this? Because it doesn't work. The only problem I can see is the matrices in animations of the X file. Any help is appreciated. [disturbed] [Edited by - Jiia on September 13, 2004 6:44:59 PM]

Share this post


Link to post
Share on other sites
I cannot see how you exit the while loop; once in, the recursion will never exit because the b is always initialized with FirstChildBone so if b!=NULL it will never exit.

Share this post


Link to post
Share on other sites
FirstChildBone is the first node in a linked list of child bones for each bone. But I know my problem is not within the hierarchy. I can simply pass identity matrices through the hierarchy until I reach the left thigh, compute it, and it's still kicking the head.

EDIT: See what the animated model looks like here.

Share this post


Link to post
Share on other sites
the frame transform matrices have the local object coordinates. Typically the root node is an identity matrix and the children indicate offsets to their parent. I think you do process the frame info in your bones states as you said. So the problem I believe is with the matrix transforms before rendering somewhere. Can you post the code of the matrix operations you do from the .x file frames before rendering? I am not clear which one is the offset-matrix, parent final matrix etc and also the matrix order in the multiply operations.

Share this post


Link to post
Share on other sites
Well, there is no code. I'm trying to use the matrices from the animation keys directly. I set those as the state. Then I pass it through the hierarchy, which applies the offsets and such. If there is any code that would modify the animation matrix keys before ever using them, then that is what I NEED, badly.

The CBone::Offset matrix is what I got from ID3DXSkinInfo::GetBoneOffsetMatrix(). The CBone::InverseOffset matrix is just the inverted version of the CBone::Offset matrix.

The matrix multiplies go from left to right. Like this:

Finals[Index] = Offset;
Finals[Index] *= States[Index];
Finals[Index] *= InverseOffset;
Finals[Index] *= Derive;



The parent final matrix is exactly what is computed above. It is passed to each child as "Derive" parameter.

Also note that I am not using the AnimationController provided with D3DX. I'm assuming it is doing exactly what I need to do, which is probably why very few people know the answer to this.

With my current code, if I set each bone state to identity, I get a perfect default pose. If I rotate a bone's state manually, it does exactly what it should. If I rotate the shoulder, the forearm and hand behave perfectly. If I set any bone state to a matrix from an animation key, it goes whacky. The animation keys are plain screwed up. I'm assuming there must be a way to modify them to make them relative to the identity matrix. In other words. States[LeftThighIndex] = Animation.Keys[0]; makes the left leg kick the head, when it should be barely rotated, as in the animation while in the modeler. It's not just with my mesh, though. Tiny does the same thing.

Share this post


Link to post
Share on other sites
Ok I see. I was looking the skinnedmesh demo in the SDK (uses the animation controller as you said to derive the paths) but the updateframematrices function in it takes into account frame siblings not just the children in a separate operation so the parent matrix is multiplied with the current for each sibling.

Also you do an inverse on the offset while you already multiplied the offset itself (before states why?).

Share this post


Link to post
Share on other sites
I'm not sure what you mean about siblings. The sibling of the left shoulder would be the right shoulder. Why would the left shoulder have any affect on the right, or vice versa?

Each child bone computes all of it's children. That means the hip computes both the left thigh, and the right thigh. The entire left leg would be computed, then the entire right leg. If I computed siblings as you mention, it would mean the left and right thigh are computed, then the left and right shins. So in a different order. But the result should be the same, right? The parent of each bone remains the same, and the bone's only use their parent as a guid to modify their own orientation. Let me know if I'm missing out on something.

Quote:
Also you do an inverse on the offset while you already multiplied the offset itself (before states why?).

The "Offset" matrix that I get from ID3DXSkinInfo::GetBoneOffsetMatrix() tells each bone how to move itself so that it's rotational origin is 0,0,0 in 3D space. So the Offset matrix for the hand moves the wrist joint to the 0,0,0 point. The state of each bone is supposed to (as far as I know) tell the bone how to rotate. If I tried to rotate a bone before moving it to the center point, it would rotate around the model's origin rather than it's own origin.

So Final = Offset * State would move the bone to the origin, then rotate it, but then it remains at the origin. If I render after this, the hand would appear stretched from the forearm to the center point of the model. It would be rotated correctly, however. The InverseOffset matrix moves the hand's wrist back to where it was before. So it is put back onto the forearm. So ToCenterPoint,Rotate,BackToLocation. I guess the Animation Controller also takes care of these things?

Again, let me know if I'm totolly blotching something.

Share this post


Link to post
Share on other sites
I may not be too helpful here, as I am using DX8 and created my own skeleton and skinned mesh objects.
But in my experience, the offset matrices should not be taken into account until you are building your mesh object (ie. applying the transformations).
All of the bone (or frame as .x files call them) matrix transformations are in BONE-local space. From what I have played with, I have discovered that the offset matrices seem to apply these bone matrices into MODEL space.
So when animating :
1) Set your bones with the .x file BONE local transformation matrices.
2) Traverse your skeleton hierachy, multiplying children by the parent matrices.
3) Extract these multiplied-through matrices in the order which they came in the .x file (the bone name buffer from D3DXLoadSkinMeshFromXof) to build up your final array of matrices to apply to the skinned mesh.
I use something like :

D3DXMatrixMultiply(&(amtxBones[dwCurBone]), // output
mtxOff, // offset matrix
mtxCur); // multiplied through bone matrix


and plug that into

smSkin->UpdateSkinnedMesh(amtxBones, NULL, mshPose);


Hope this helps you out - even if it is based on DX8.
Steele.

Share this post


Link to post
Share on other sites
Quote:
Original post by Crow-knee
But in my experience, the offset matrices should not be taken into account until you are building your mesh object (ie. applying the transformations).

Right. That's the only time I use them.

Quote:
Original post by Crow-knee
All of the bone (or frame as .x files call them) matrix transformations are in BONE-local space. From what I have played with, I have discovered that the offset matrices seem to apply these bone matrices into MODEL space.

That would be groovy, but it's not that simple. Do me a favor. Open Tiny.X in notepad, press Ctrl+F, type Bip01_L_Toe0, and press enter. Keep pressing enter until there are a crap load of numbers above the bone name. Now scroll up and look at the very first frame. I think we can all agree that Tiny's left toes move very little in her animations, right? Lets take a look at this first keyframe matrix..

0.000000, 1.000000, 0.000000, 0.000000,
-1.000000, 0.000000, -0.000000, 0.000000,
-0.000000, 0.000000, 1.000000, 0.000000,
27.423233, 34.577133, 0.000000, 1.000000

// Keep in mind that an identity matrix looks like..

1.000000, 0.000000, 0.000000, 0.000000
0.000000, 1.000000, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000



Notice how the first row has the 1.0 and 0.0 swapped (compared to the identity matrix) on the first two entries? That's telling me to rotate the toes so that it's X is facing it's Y. In other words, Your toes are twisted so that your big toe is closest to the ground, and your pinky toe is closest to your upper body. Doesn't sound too comfortable. In reality, or at least my reality, Tiny's toe matrix should be really, really close to an identity matrix, because they are barely rotating. They may not even be rotating at all.

Does anyone have a clue why this is like this?
Does anyone have a clue how to fix it? [disturbed]

Share this post


Link to post
Share on other sites
The skinnedmesh sample takes into account the SkinWeights template (these are not the frame/frametransformatrix templates in the .x file) it is the bone that influences the vertices of the mesh. This need to be multiplied with the FrameTransformMatrix of the associated part. This matrix is the last field in this template.

Share this post


Link to post
Share on other sites
Smooth skinning (previous post on blending based on bone weights) would factor into the equation after the final transformation matrices have been calculated. It may be an element of your problem, and you should be blending these transforms using the 'SkinWeights' values if they exist in the X File. Export your model using rigid skinning if you don't want to write the blend code right now.

However, I believe that your order of operations is incorrect when building your final transforms, and you're not properly calculating InverseOffset.

The transforms in the X file are relative to the parent frame. The geometry in the X file is for the model at the bind pose, which is why you get the correct model when removing all transforms. I view this as a two-step process, keeping in mind that order of transforms matter and that in the end you're acting on the geometry.

1) Transform the points to bone space to 'remove' the bind pose
2) Transform the points forward from bone space into model space.

The transform for step 1, you're calling InverseOffset. But InverseOffset should actually be the inverse of the heirarchy transform. e.g. Inverse(Offset * Derive). This takes the geometry all the way back to the origin, through the heirarchy. Simply inversing the relative transform (Offset) doesn't get you much, and it certainly doesn't get you back to the origin.

The transform for step 2 you already know. The offset, modified by the current state, multiplied by the parent matrix.

I use the following equations:
BindPoseTransform = (Offset * Derive).Inverse(); (InverseOffset)
ModelTransform = Offset * States[index] * Derive;
Finals[index] = BindPoseTransform * ModelTransform;


If you remove States[index] in your head (i.e. no animation), you should see that all of these transforms cancel out... putting your model right back at the bind pose.

I hope this helps! It can be rough to get it working at first, but once you spend enough time on it, I think it will start making sense.

EDIT:
I want to point out two more things, these may stem from my lack of exact knowledge of ::GetBoneOffsetMatrix()
1) Offset contains the bone transform relative to the parent's transform, and NOT the transform to go from origin to bind pose or anything else.
2) The Derive matrix contains the value of the variable ModelTransform for the current bone's parent.

[Edited by - Cauthon on September 14, 2004 12:14:57 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Cauthon
Smooth skinning (previous post on blending based on bone weights) would factor into the equation after the final transformation matrices have been calculated. It may be an element of your problem, and you should be blending these transforms using the 'SkinWeights' values if they exist in the X File. Export your model using rigid skinning if you don't want to write the blend code right now.

Skin weights have nothing to do with my problems. The model bends and rotates perfectly. Each bone bends and sends it's children into the exact correct rotations. It's not until I get into trying to use an x-file animation keyframe that everything turns crap.

Quote:
Original post by Cauthon
However, I believe that your order of operations is incorrect when building your final transforms, and you're not properly calculating InverseOffset.

There's no calculating to it. Inverse offset is the inversed Offset. The Offset matrix moves the bone's joint to space-0,0,0. This process is totally unrelative to the parent. The matrix simply moves "space" so that it's bone's joint is located at the model's local origin. This allows any rotations to rotate the bone at it's joint. So next, the states are applied. After this, "space" must be moved back so that the vertices of that bone are not stuck at the origin when rendered. So the inversed offset is thrown in. Now the bone is back where it was, but rotated correctly. All of this happens without any effect of the parent bone. The only thing the parent bone is needed for is yet another rotation, but around it's origin. The parent bone's final contains the rotation around it's origin. So the child simply multiplies that at the end, and all is well.

You wanna rotate the left shin 45 degrees? It moves perfectly. So does it's children. Everything works exactly like it should, except the keyframes in X-Files. They do not behave as should be expected. How is that? They should show rotations in local space for each bone. That's it. If they did that, Tiny's left toe would be an identity matrix. Not some crazy x=y inverted mess.

Quote:
Original post by Cauthon
The transforms in the X file are relative to the parent frame.

Again, if Tiny's toe was relative to her foot, which was relative to her calf, which.. etc. Then her toe would be an identity matrix, because it is not animating in the animation. The foot is moving it around, but it is not moving locally. Yet looking at that matrix above, something is wrong. You don't agree? Those keyframe matrices contain something more than just a local rotation. What else is in there?? How can I remove it?

Quote:
Original post by Cauthon
1) Transform the points to bone space to 'remove' the bind pose
2) Transform the points forward from bone space into model space.

I'm not sure I understand this. What points are you referring to? Are you telling me that every animation keyframe is in model space, rather than local space? How do I perform step 1? If step 2 moves the points to model space, what space were they in before step 1?

Quote:
Original post by Cauthon
The transform for step 1, you're calling InverseOffset.

My InverseOffset does not move points to bone space. They move them back to model space. My "Offset" moves the points to bone space. That is, unless I have the terms "model space" and "bone space" confused with each other. My idea of moving to bone space is when the bone is at the origin of rotations. If you moved all of the model's vertices to one bone's space, the whole model would rotate around that bone's joint. Is that right? Or do I have them backwards?

Quote:
Original post by Cauthon
But InverseOffset should actually be the inverse of the heirarchy transform. e.g. Inverse(Offset * Derive). This takes the geometry all the way back to the origin, through the heirarchy. Simply inversing the relative transform (Offset) doesn't get you much, and it certainly doesn't get you back to the origin.

I'm lossed. What is the relative transform? The GetBoneOffsetMatrix function gives you the orientation of the bone. It moves the bone's joint to the zero point. The parent has nothing to do with it.

Quote:
Original post by Cauthon
The transform for step 2 you already know. The offset, modified by the current state, multiplied by the parent matrix.

I'm almost positive that we have mixed up the offsets or something. If you applied the Offset matrix of the hand to every vertex in the entire mesh, then render, it would be rendered where the wrist is the model's new center point. Now imagine applying a world transform rotation. The whole model would rotate around the wrist center point. Now if you applied the inverse, it would put the model's center point back where it was, but the rotation is still there. It's still rotated like it's wrist was nailed to something.

I really appreciate your efforts to help me. If you understand the keyframe matrices, can you instead help me understand how to convert those to local bone space? Whatever calculations are needed, it should move that above toe matrix so that it is an identity matrix. I don't understand what else, besides a local rotation, is going on.

Thanks again.

[Edited by - Jiia on September 14, 2004 2:18:15 PM]

Share this post


Link to post
Share on other sites
Ok, I might be able to see the difference in the matrices we're working with.

Your 'Offset' is my 'BindPoseTransform'. It's the combined transformation matrix that moves model geometry to the origin. I have a feeling that your animation keyframes work the same way. (When I say 'your' I really mean the X File's) They're the combined transforms that take model geometry from bone space to model space. They're not 'relative' to any parent, which is why they're not the identity matrix, despite not having any local rotation.

If the keyframes are combined transforms, this would make your final transform simply:
Final[index] = Offset * States[Index];


I'm not getting how the parent factors in to the equation if you're not using relative transforms. By relative transform, I mean the transformation that takes points from the parent's bone space into the child's bone space. But I'll keep re-reading your reply and I'll see if I can approach the problem from your viewpoint. I'll also try to disect the transforms in tiny.x and see if I can help relate them to you.


I have to admit here, that I'm familiar with the D3DX animation functions, but don't use them myself. I used the X file format while learning the basics of character animation, but my system uses quaternion keyframes for interpolation.

Share this post


Link to post
Share on other sites
Mine uses quaternions as well. The keyframes are converted when loaded in. That's why I can't directly test your algo for the hierarchy computations. My keyframes are now quaternions, so they do not contain the translation vector anymore.

Dude, if you can show me how to convert the matrix keys in Tiny to local bone rotations, I will be forever in your dept. For example, if the left thigh is bent forward 45 degrees in the animation key, relative to the default pose, then applying that matrix to a stick which started in a simular rotation as the thigh, the stick would rotate exactly 45 degrees and be in the same location as the thigh.

It only makes sense that if something didn't rotate at it's own joint, that it should be an identity matrix.

So each keyframe should tell the bone how much to rotate. My problem is that I just don't understand what is actually in those keyframes, other than a local rotation.

EDIT:

That's not it, is it? I've been assuming all along that keyframe rotations were relative to the model's default pose. As in it's pose without any transformations applied. Is that true? If not, what are they relative to?

EDIT again:

Actually, if you could just help me understand what each keyframe actually represents, that would be just as good. I want mine to be a local transformation to a bone. If the bone was located so that it rotated around it's joint, then applying the keyframe should rotate it so that it's new orientation is where it was in the animation. I cannot apply that toe matrix, as it just twists and bends it out of control. Any idea why?

[Edited by - Jiia on September 14, 2004 3:53:51 PM]

Share this post


Link to post
Share on other sites
I just finished my DX80 SDK download yet for tiny.x, but if it is correct that each bone's keyframe is a combined transform to go from bone space to model space at a specific point in time. That's the same as saying that each keyframe is the same as the local transform multiplied by the parent's combined transform.

KeyFrame[index] = LocalTransform * ParentKeyFrame[index]

You would like to find LocalTransform, so try reversing this process:
LocalTransform = KeyFrame[index] * ParentKeyFrame[index].Inverse();

If you test this on non-rotating joints ... you should get your identity matrices as a result. uhhhh, yeah :)

[Edited by - Cauthon on September 14, 2004 4:15:23 PM]

Share this post


Link to post
Share on other sites
Ehh? Are you serious? That's it? Each keyframe is already multiplied with it's parent's keyframe?

I'm off to try this. By the way, I think there were two versions of Tiny in DX8. They may have changed her again for 9c (which I'm using). I've uploaded it for you if you need it (if you can download from GeoCities). About 350kb.

EDIT: Do I need to take the scene into account as well? Or just bones?

Also, if I export an animation where the character is not moving at all, then everything is still messed up. Most bones do not contain an identity matrix. Doesn't that mean that LocalTransform = KeyFrame[index] * ParentKeyFrame[index].Inverse() wouldn't work? I'm gonna try anways. Just wanted to mention that.

Share this post


Link to post
Share on other sites
I'm afraid I've gotten you horribly sidetracked. Now that I can see the contents of tiny.x, the transforms in the AnimationKey segments look very similar to the transforms in the Frame's TransformationMatrix sections. Both of those transforms are local transforms for that bone, that move points from the parent Frame's coordinate space to the current Frame's coordinate space.

So:

// Offset is the reverse transform (model>>bone)
ModelTransform = State[i] * Derive; // This is forward (bone>>model)
Final[i] = Offset * ModelTransform; // This is the total transform


Then, in ComputeHeirarchy, send ModelTransform into the children, because you want to concatenate onto the forward transform, not the total transform. I think this will work.

Share this post


Link to post
Share on other sites
EDIT note: this reply is in response to the Key = Key * ParentKey.Invert

Unfortunately, it doesn't work. I backed up each matrix which was used in the key frames as I loaded the animations. I set each keyframe to it's backed up matrix (original from file) multiplied with it's parent's backed up matrix.

I also tried executing this in hierarchy order, where the backed up matrices change once it's keyframe changes.

Something still doesn't make sense. If the whole model is in it's default pose in the animation, how could anything cause the keyframes to not be identity? It must be something about orientation. But the matrices to move from bone space -> model space and vice versa do not even look simular to these keyframes. So what are these keyframes supposed to do?

Nothing I've tried so far looks as close as simply using the keyframes like local transformations. Most of the model looks good, except the thighs, toes, and shoulders. Everything I've tried so far just makes it worse.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jiia
Something still doesn't make sense. If the whole model is in it's default pose in the animation, how could anything cause the keyframes to not be identity? It must be something about orientation. But the matrices to move from bone space -> model space and vice versa do not even look simular to these keyframes. So what are these keyframes supposed to do?


I think that your expectation for Identity keyframes is wrong. I picture the local transform as the transform required to move from parent joint to child joint. If we draw a basic skeleton as:
O----->O

The local transform is the transform that moves the geometry between the O's (joints), along the arrow (bone). This would only be the Identity matrix if the joints were in the same locaation. If you're expecting no animation, then what you're expecting is that the keyframe doesn't change. Or that the keyframe DIFFERENCE is the Identity matrix. e.g. the bone is staying in the same place relative to its parent's location. (Eureka? Any help?)

Quote:
Everything I've tried so far just makes it worse.

That happens to me a lot -- it's probably just my influence on you.

Share this post


Link to post
Share on other sites
Quote:
Original post by Cauthon
I think that your expectation for Identity keyframes is wrong. I picture the local transform as the transform required to move from parent joint to child joint. If we draw a basic skeleton as:
O----->O


So you're saying the keyframes for each bone are the difference between itself and the parent's keyframe? Including translation offsets? Including orientation rotation?

If I set each bone state to it's GetBoneOffsetMatrix, every bone of my character would be neatly stacked in the center. Every bone would also be perfectly aligned with a world axis. That's what I'm referring to by orientation. The rotation part of GetBoneOffsetMatrix, excluding the translation part to move the joint to the zero point. Is that also included in the keyframes?

If each keyframe is just the difference between itself and it's parent, then simply multiplying each bone keyframe with it's parent's keyframe, then using the results to render would put the model into the correct pose. Wouldn't it? If so, why is any kind of offset matrix needed at all? It sounds like the keyframes include the offset matrix.

I'm not afraid to admit I'm getting more and more confused. The matrix can hold the bone's rotation, it's orientation, it's offset, and even an inverse offset. I'm having trouble identifying what is where.

Quote:
Original post by Cauthon
The local transform is the transform that moves the geometry between the O's (joints), along the arrow (bone). This would only be the Identity matrix if the joints were in the same locaation.

Ahh, so then they must contain the offset matrices. In any case, my above statement about simply rendering the multipled keys through the hierarchy would still work. I think. And for some reason, multiplying each keyframe with it's parent's inversed keyframe didn't work. Why? If each bone is the difference between itself and it's parent, multiplying each with the inversed parent should result in the simple, local, rotation. Did I do something wrong? Do I need to do it backwards through the hierarchy? [disturbed]

Quote:
Original post by Cauthon
If you're expecting no animation, then what you're expecting is that the keyframe doesn't change. Or that the keyframe DIFFERENCE is the Identity matrix. e.g. the bone is staying in the same place relative to its parent's location. (Eureka? Any help?)

But I thought you said the keyframe was the difference? Now you're saying that the difference will be the identity matrix? Or do you mean the difference between differences? [disturbed] If keyframe = difference = identity, then something is still wrong, as there are no identity matrices for the default pose animation. Or at least very few.

EDIT: I think I see what you're saying here. If the bone doesn't rotate, then it's keyframes will all be the same through the animation. So the differences between each of it's keys, not it and it's parent's keys. I'm still not understanding how to remove the difference between the bone and it's parent, to force it to be identity.

Do you totally understand all of this? Am I just not getting it? My confusion is outweighing my comprehension.

EDIT again:

If the entire model is in it's default pose, is this true?
LeftToeKey == LeftShinBone->GetOffsetMatrix() - LeftToeKey->GetOffsetMatrix() ?
I'm using '-' meaning difference. In other words, the left toe's keyframe is the difference between the left toe's bone space and the left shin's bone space?

[Edited by - Jiia on September 14, 2004 6:54:39 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Jiia
So you're saying the keyframes for each bone are the difference between itself and the parent's keyframe? Including translation offsets? Including orientation rotation?

Yes. The keyframe is the difference between the parent and the child transformation.

Quote:
Original post by Jiia
If I set each bone state to it's GetBoneOffsetMatrix, every bone of my character would be neatly stacked in the center. Every bone would also be perfectly aligned with a world axis. That's what I'm referring to by orientation. The rotation part of GetBoneOffsetMatrix, excluding the translation part to move the joint to the zero point. Is that also included in the keyframes?

The Offset matrix, which D3DX is neatly giving you, is the inverse of the combined matrix when the model is at the bind pose. The combined matrix is the sum of the keyframes from root bone to end bone. Each keyframe is a portion of the combined matrix, the portion that goes from parent to child. To build the combined matrix:
B0 * B1 * B2 . . . Bn-1 * Bn
So you have the bones of your model sitting out in Model space, specifically at the bind pose. You need to get them from the bind pose to the origin, so you multiply them by the Offset matrix.

Then you need to put them back into model space by using the keyframes. Once at the origin, you transform them to the root bone B0, from the root you transform the root's child B1... all the way until you reach your bone's local transform.

To do that in a single matrix, you do

ModelTransform = KeyFrame[index] * ParentCombinedTransform;
Final[index] = OffsetMatrix * ModelTransform;

Where ModelTransform moves a bone from the origin to its animated position through by following the skeleton heirarchy.

Quote:

But I thought you said the keyframe was the difference?

Hahaha. The keyframes are the difference between the parent bone and the child bone. Animation is the difference between the location of the child bone at time 0 and the child bone at time x. If we're not moving, then we expect the keyframe matrices to remain constant. If you look at the keyframes for tiny's toe ... you'll see it's not changing much. And you'll know that relative to the parent (foot), it's not rotating or translating and that the difference between the two bones is remaining constant.

Quote:
Do you totally understand all of this? Am I just not
getting it? My confusion is outweighing my comprehension

My understanding of what's in the X File and what the D3DX functions give you has changed as we've worked through this, but I understand the transforms and what's necessary to maintain the animation. It's difficult to explain though.

EDIT:
Quote:

If the entire model is in it's default pose, is this true?
LeftToeKey == LeftShinBone->GetOffsetMatrix() - LeftToeKey->GetOffsetMatrix() ?
I'm using '-' meaning difference. In other words, the left toe's keyframe is the difference between the left toe's bone space and the left shin's bone space?


Man ... that's a tough question to figure out in your head. But, I think the answer is yes.
LeftToeKey = LeftToeBone->GetOffsetMatrix() * LeftShinBone->GetOffsetMatrix().Inverse()

(the Inverse and multiplication are just the way to calculate matrix difference)

Share this post


Link to post
Share on other sites
I'm gonna mail ya $50 bucks.

In the default pose, this is true:

LeftToeKey == LeftToeBone->GetOffset().Inverse() * LeftFootBone->GetOffset()

I had to switch em around a bit, manually comparing printed out matrices, but this is definitely true. What exactly does this mean? Bone.offset.inverse() * parent.offset(). Is this not taking the parent bone's offset and removing the child's offset from it? If so, what is the result? Or rather, what can I call the result? What does it represent?

The overjoy is not helping my overworked brain.

The fact that I can invert this thing and apply it to the keyframes is all I need. In fact, I just tried it and it works perfectly. My model is totally animating, no flaws. Maybe this will all make sense once I recover from this 4-day-straight, torturous event.

I seriously doubt I would have ever found the solution without your help. I'd give ya a hella rating boost, but that's impossible. Let me know if I can make it up.

Ahhh 4 days, and it's finally over.

Share this post


Link to post
Share on other sites

This topic is 4836 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this