View more

View more

View more

### Image of the Day Submit

IOTD | Top Screenshots

### The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

# How to debug an fx file

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

26 replies to this topic

### #21Buckeye  GDNet+

Posted 21 March 2014 - 08:07 AM

In my article, take a look at the section A Slight Diversion from the Initialization Process.

Each bone's animation transform (I think they're the NodeTransformation in the article you referenced) orients the bone LOCALLY. "Locally" means (e.g.) a hand bone rotates about it's own Y-axis a little during an animation. That rotation about the bone's Y-axis is to take place wherever the bone is in the world. Maybe the arm is raised into the air or off to one side. The hand bone moves with the arm, but the rotation is still to take place about the bone's Y-axis, not the world Y-axis.

So, if the vertices around the character's hand are to be rotated about the hand bone's Y-axis, that rotation needs to take place relative to the hand bone, not the world Y-axis. See the illustration in the section of the article I linked. The vertex positions in the mesh around the hand are in world(*) space. The offset matrix transforms the vertex from world space to bone space. The animation (scale-rotate-translate) then takes place in bone space. Then the combined animation transforms move the vertex back to world space for rendering.

(*) that's really root-node space. I'm calling it "world" to give you a better visualization.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Posted 21 March 2014 - 12:36 PM

In my article, take a look at the section A Slight Diversion from the Initialization Process.

Buck, from what I read from the article. Here is what I learned. Correct me if I am wrong....

1. I am given the offset matrix by Assimp [which you calculated]

2. And the transformation matrix is given by Assimp's aiNode structure's mTransformation.(Assimp's documentation : "The transformation relative to the node's parent.")

3. Now all I have to do is recursively calculate the transformation matrix for each bone by multiplying it with it's parent transformation.

4. And to render it I have to multiply the offset matrix with each bone's transformation matrix...

I just want to create the bind pose first.

### #23Buckeye  GDNet+

Posted 21 March 2014 - 01:42 PM

As mentioned previously, I'm not familiar with Assimp and how they implement the node hierarchy. The best I can do is say "It sounds like it."

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Posted 22 March 2014 - 02:35 PM

Buck,

I wrote this function to calculate the transformation matrices. It is similar to the tutorial of the blog. And also I did some research in Assimp. It seems mTransformation "is local in relation to its parent node" . So I am guessing it transforms mesh space to bone space. I have to multiply it with each of its children. And the offset matrices are pre calculated. Here is the function:

void Bones::UpdateNode(const aiNode *pNode, const XMFLOAT4X4 parentMatrix) //Bone Index, Parent Matrix (Transformation)
{
const char *name = pNode->mName.C_Str();
XMFLOAT4X4 temp;
AItoXM(pNode->mTransformation, temp);

XMMATRIX finalTransform = NodeTransformation * XMLoadFloat4x4(&parentMatrix);

if (mBoneInfoMap.find(name) != mBoneInfoMap.end())
{
int boneID = mBoneInfoMap[name];
XMStoreFloat4x4(&mBoneInfo[boneID].Transform, temp2);
}

XMFLOAT4X4 temp3;
XMStoreFloat4x4(&temp3, finalTransform);

for (int i = 0; i < pNode->mNumChildren; i++)
{
UpdateNode(pNode->mChildren[i], temp3);
}
}



The author of the tutorial passed the scene's RootNode and an identity matrix . But if I do that the mesh is distorted. Do I have to pass the RootNode of the scene ?

Edited by Saad Manzur, 23 March 2014 - 02:24 AM.

### #25Buckeye  GDNet+

Posted 22 March 2014 - 03:57 PM

Do I have to pass the RootNode of the scene ?

Did you try that?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Posted 23 March 2014 - 02:24 AM

Yes I tried that still getting massively distorted mesh. I tried Icebreaker's method. It should have worked. Is there any specific ordering to multiply this matrices. I tried multiplying the opposite order still no good.

Assimp says : mOffsetMatrix = the matrix transforming from mesh space to bone space, also called inverse bind pose transform

mTransform = a node's transformation matrix in relation to it's parent node

So, this information and does my code match ?

### #27Buckeye  GDNet+

Posted 23 March 2014 - 07:02 AM

So, this information and does my code match ?

I can't tell you. It sounds like you're just trying this, that and the other, hoping to stumble on something that works. With hundreds of lines of code and complex data, that's probably not going to be a good approach.

At some point, you need to understand what each line of code should do, and, more importantly, determine whether it does what it's supposed to do.

The approach I personally prefer is to follow the data. Pick a point in your code and look at the data. Verify that it's correct. If it's not, pick a point earlier in the process. Keep moving earlier in the process until you find correct data.

Then move on to the next step. Pick a line of code in the process where you think everything preceding it is correct, likely the point where you just found good values. If that line of code looks right, then you have to check the data that's coming into that line, to see if the data is correct. If the data is correct, then verify the data gets manipulated by the code the way it should by checking that the data that comes out of the manipulation is correct.

Most programmers know the code better than the data. They can write a line such as: MatrixInverse( Matrix invMat, Matrix inputMat ). But, to know that it's the correct code, someone in the project has to know what a matrix is, what the inverse of a matrix is, and whether (at that point in the code) the inverse of a matrix is needed. If the code is correct, but the results are not correct, someone in the project has to look at the actual inputMat and determine if the data is correct.

If that "someone in the project" is you, you have to be able to do those things.

Edited by Buckeye, 23 March 2014 - 07:03 AM.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.