Sign in to follow this  
mosweg

Don't understand .X Animation

Recommended Posts

Looking at an .x file i can't figure out how to apply the animation in C++
I have 1 triangle of 3 vertices whit 1 bone, to keep is simple

[code] SkinWeights {
"Bone001";
3;
0,
1,
2;
1.000000,
1.000000,
1.000000;
0.753317,0.000000,-0.657658,0.000000,-0.000000,1.000000,0.000000,0.000000,0.657658,0.000000,0.753317,0.000000,30.545536,0.000001,-2.056927,1.000000;;
}
[/code]
I understand that there are 3 vertices connected to Bone001 (0,1,2), they all weight the same so the amount the vertices change is equel for the 3
But as soon as the 4x4 matrix comes in I'm lost.
I think the 4x4 matrix somehow tells where the bone is inside the mesh

Below the SkinWeights there is this.
[code] Frame Bone001 {


FrameTransformMatrix {
0.753317,0.657658,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,-0.657658,0.753317,0.000000,0.000000,2.254292,-21.498741,0.000001,1.000000;;
}
}[/code]
What is that 4x4 matrix for? I thought the position of the bone was already in SkinWeights

Below that there is:
[code]
AnimationSet Anim-1 {


Animation Anim-Plane001 {

{ Plane001 }

AnimationKey {
4;
2;
0;16;1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,26.617512,-2.959750,0.000000,1.000000;;,
1600;16;1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,26.617512,-2.959750,0.000000,1.000000;;;
}
}

Animation Anim-Bone001 {

{ Bone001 }

AnimationKey {
4;
2;
0;16;
0.753317,0.657658,0.000000,0.000000,
0.000000,0.000000,-1.000000,0.000000,
-0.657658,0.753317,0.000000,0.000000,
2.254292,-21.498741,0.000001,1.000000;;,

1600;16;
0.985874,-0.167490,0.000000,0.000000,
0.000000,-0.000000,-1.000000,0.000000,
0.167490,0.985874,-0.000000,0.000000,
2.254292,-21.498741,0.000001,1.000000;;;
}
}
}
[/code]
I see there are 2 animations, one for the triangle(Animation Anim-Plane001) and one for the bone(Animation Anim-Bone001).
Why are there 2 as it seems that there only needs one?

[code]
Animation Anim-Bone001 {

{ Bone001 }

AnimationKey {
4;
2;
0;16;
0.753317,0.657658,0.000000,0.000000,
0.000000,0.000000,-1.000000,0.000000,
-0.657658,0.753317,0.000000,0.000000,
2.254292,-21.498741,0.000001,1.000000;;,
[/code]

To change the vertices correctly I assume { Bone001 } points to the bone position.
4 means there is a matrix coming
2 means there are 2 keys, so 2 times a 4x4 matrix
0 means the frame time
16 means that there are 16 variables

So I think I understand some parts of the animation.
[b]But how do I apply the 4x4 matrix to the vertices in C++?[/b]

Share this post


Link to post
Share on other sites
According to the [url="http://msdn.microsoft.com/en-us/library/bb172982%28v=vs.85%29.aspx"]X File Reference[/url], the 4x4 matrix in SkinWeights is used to transform the mesh vertices into the bone's local object space. The FrameTransformMatrix is the transform matrix for that bone. It kinda looks like you could ignore the animation for Plane001 since it doesn't change. For Bone001, it's first frame has the same matrix as that given in the bone's FrameTransformMatrix, so It looks like thats its initial position.

I'm guessing a bit here, but I'd say to determine a given vertex's position, multiply the bone's current transform matrix by the transform in the SkinWeights and transform the vertex by the resulting transform matrix. I hope that makes sense.

Share this post


Link to post
Share on other sites
For the first time the triangle does something thanks to discovering the [size="2"][color="#030003"][size="2"][color="#030003"]D3DXMatrixDecompose function
I've tried some combinations but it doesn't do the correct animation
In the DirectX viewer the triangle rotates on the y axis and stays in one place.
But whit my code it rotates around the x axis and it doesn't stays on the same place

[code]
D3DXVECTOR3 newpos;
D3DXQUATERNION newrot;
D3DXVECTOR3 newsca;

D3DXMATRIX offset(0.753317,0.000000,-0.657658,0.000000,-0.000000,1.000000,0.000000,0.000000,0.657658,0.000000,0.753317,0.000000,30.545536,0.000001,-2.056927,1.000000);
D3DXMATRIX matrix4x4(0.985874,-0.167490,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,0.167490,0.985874,-0.000000,0.000000,2.254292,-21.498741,0.000001,1.000000);
D3DXMATRIX pos;
D3DXMATRIX rot;
D3DXMATRIX final;
D3DXMATRIX final2;
for(int i=0;i<3;i++)
{
D3DXMatrixMultiply(&final,&matrix4x4,&offset);
D3DXMatrixTranslation(&pos,skeleton[i].X,skeleton[i].Y,skeleton[i].Z);
D3DXMatrixDecompose(&newsca,&newrot,&newpos,&final);
D3DXMatrixRotationX(&rot,newrot.x);
D3DXMatrixRotationY(&rot,newrot.y);
D3DXMatrixRotationZ(&rot,newrot.z);
D3DXMatrixMultiply(&final2,&pos,&rot);
D3DXMatrixDecompose(&newsca,&newrot,&newpos,&final2);
skeleton[i].X = newpos.x;
skeleton[i].Y = newpos.y;
skeleton[i].Z = newpos.z;
}
[/code][/color][/size][/color][/size]
The offset is the 4x4 matrix in SkinWeights
The matrix4x4 is the second 4x4 matrix in the bone animation

Does someone know how to apply it correctly so the triangle shows the animation?

Share this post


Link to post
Share on other sites
[quote name='mosweg' timestamp='1313428859' post='4849457'][size="2"][color="#030003"][size="2"][color="#030003"]
[code]
D3DXVECTOR3 newpos;
D3DXQUATERNION newrot;
D3DXVECTOR3 newsca;

D3DXMATRIX offset(0.753317,0.000000,-0.657658,0.000000,-0.000000,1.000000,0.000000,0.000000,0.657658,0.000000,0.753317,0.000000,30.545536,0.000001,-2.056927,1.000000);
D3DXMATRIX matrix4x4(0.985874,-0.167490,0.000000,0.000000,0.000000,-0.000000,-1.000000,0.000000,0.167490,0.985874,-0.000000,0.000000,2.254292,-21.498741,0.000001,1.000000);
D3DXMATRIX pos;
D3DXMATRIX rot;
D3DXMATRIX final;
D3DXMATRIX final2;
for(int i=0;i<3;i++)
{
D3DXMatrixMultiply(&final,&matrix4x4,&offset);
[/code]
I'll say again, I'm not familiar with this, but it seems to me that you ought to be able to use [b][font="Lucida Console"]D3DXVec3Transform()[/font][/b] at this point, transforming each vertex's position by [b][font="Lucida Console"]final[/font][/b]. You may have to extract the rotation matrix and transform by that instead, but everything following that [i]shouldn't[/i] be necessary, by my reasoning.
[code]
D3DXMatrixRotationX(&rot,newrot.x);
D3DXMatrixRotationY(&rot,newrot.y);
D3DXMatrixRotationZ(&rot,newrot.z);
[/code]
[/color][/size][/color][/size][size="2"][color="#030003"][size="2"][color="#030003"]You're not doing what you think here. [/color][/size][/color][/size][size="2"][color="#030003"][size="2"][color="#030003"]Each D3DXMatrixRotation* call is overwriting the previous call's rotation matrix with a completely new one. The X-Axis and Y-Axis rotations are being lost.
[/color][/size][/color][/size]

Share this post


Link to post
Share on other sites
Because bone animation seems a bit hard i tried to make it easier.
Just one triangle 3 vertices and just an simple rotation, no bones
But now it seems that the numbers just don't add up
Its an animation rotating on the y-axis only the y-axis
But whit getting the data whit [size="2"][color="#030003"][size="2"][color="#030003"]D3DXMatrixDecompose I see why I had so much trouble whit the animation

There are now 3 4x4 matrixes
[code]
FrameTransformMatrix {
1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,26.617512,-2.959750,0.000000,1.000000;;
}
AnimationSet Anim-1 {

Animation Anim-Plane001 {

{ Plane001 }

AnimationKey {
4;
2;
0;16;1.000000,0.000000,0.000000,0.000000,0.000000,0.000000,-1.000000,0.000000,0.000000,1.000000,0.000000,0.000000,26.617512,-2.959750,0.000000,1.000000;;,
1600;16;0.889221,-0.457477,0.000000,0.000000,-0.000000,-0.000000,-1.000000,0.000000,0.457477,0.889221,-0.000000,0.000000,26.617512,-2.959750,0.000000,1.000000;;;
}
}
}
[/code]
[/color][/size][/color][/size]2 of the 3 are the same so that means only 2 different 4x4 matrixes, assuming the starting position (1) and the end position (2)
When getting the data out of the matrixes this is what i get:
1e:
newsca = {x=1.0000000 y=1.0000000 z=1.0000000 }
newrot = {x=-0.70710671 y=0.00000000 z=0.00000000 ...}
newpos = {x=26.617512 y=-2.9597499 z=0.00000000 }

2e:
newsca = {x=0.99999958 y=1.0000000 z=0.99999958 }
newrot = {x=-0.68724471 y=0.16641712 z=-0.16641712 ...}
newpos = {x=26.617512 y=-2.9597499 z=0.00000000 }

Multiply(1,2):
newsca = {x=0.99999958 y=0.99999958 z=1.0000000 }
newrot = {x=0.97191083 y=-0.23534934 z=0.00000000 ...}
newpos = {x=50.286362 y=-15.136650 z=2.9597499 }

Multiply(2,1):
newsca = {x=0.99999958 y=1.0000000 z=0.99999958 }
newrot = {x=0.97191077 y=0.00000000 z=0.23534934 ...}
newpos = {x=53.235023 y=-2.9597499 z=2.9597499 }

It appears its rotating on 2 axises.
But I've created the animation to go only the y-axis and that is what is shows on the DirectX viewer...
I don't get it anymore.
How is it possible to get a one axis rotation from these numbers?

Share this post


Link to post
Share on other sites
Yeah, that's odd. Also, I'm not sure why the position would be changing if it's only supposed to be doing rotation.

Are you sure you're supposed to multiply the matrices instead of interpolate between them? If you draw the triangle using just the 2nd matrix, is it in its correct final orientation?

Share this post


Link to post
Share on other sites
[color="#000000"]I've tried switching between the 2 matrices and it seems that its doing something correct, I'ts in a different camera angle than DirectX viewer so I don't know of its exactly the correct final orientation but it seems like its doing an rotation on the y axis.
But now I'm not applying the changes on each vertex but on the whole object.
For bone animation that won't work.
I will try to see if I can apply it to each vertex.

[i]Current code, applying the 2 matrices to whole object at mouse click:
[/i][code]
if (GetAsyncKeyState(VK_LBUTTON)&0x8000)
{
D3DXMatrixDecompose(&newsca,&newrot,&newpos,&matrix4x4_2);
D3DXMatrixTranslation(&matTranslateA, newpos.x, newpos.y, newpos.z);
D3DXMatrixRotationX(&matRotateX, newrot.x);
D3DXMatrixRotationY(&matRotateY, newrot.y);
D3DXMatrixRotationZ(&matRotateZ, newrot.z);
D3DXMatrixScaling(&matScale,newsca.x,newsca.y,newsca.z);
d3ddev->SetTransform(D3DTS_WORLD, &(matTranslateA*matRotateX*matRotateY*matRotateZ*matScale));
d3ddev->DrawPrimitive(D3DPT_POINTLIST, 0, 53);
d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 53);
}
else
{
D3DXMatrixDecompose(&newsca,&newrot,&newpos,&matrix4x4_1);
D3DXMatrixTranslation(&matTranslateA, newpos.x, newpos.y, newpos.z);
D3DXMatrixRotationX(&matRotateX, newrot.x);
D3DXMatrixRotationY(&matRotateY, newrot.y);
D3DXMatrixRotationZ(&matRotateZ, newrot.z);
D3DXMatrixScaling(&matScale,newsca.x,newsca.y,newsca.z);
d3ddev->SetTransform(D3DTS_WORLD, &(matTranslateA*matRotateX*matRotateY*matRotateZ*matScale));
d3ddev->DrawPrimitive(D3DPT_POINTLIST, 0, 53);
d3ddev->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 53);
}
[/code][/color]

Share this post


Link to post
Share on other sites
Things seem to go a little bit better,
I already use 2 triangles and 2 bones
The animation is in big line correct but after debugging the numbers I noticed a problem
If vertex.x position is 0 and the x rotation is -0.64196301
Then the new .x position is 0
A quick example of different positions before and after RotationX -0.64196301

old = 0
new = 0
difference = 0

old = 1
new = 0,91466111
difference = 0,08533889

old = 2
new = 1,8293222
difference = 0,1706778

So when rotating vertexes there not affected equally because of the difference in positions
How can I rotate the vertex position equally whit the rest.
I think that's supposed to be happening for the correct animation

Current code I'm using to apply the animation rotation to each vertex:
[code]
for(int b=0;b<2;b++)
{
for(int i=0;i<Bone[b].Max_Vertices;i++)
{
D3DXVECTOR3 oldpos(skeleton[Bone[b].Bone_vertices[i].id].X, skeleton[Bone[b].Bone_vertices[i].id].Y, skeleton[Bone[b].Bone_vertices[i].id].Z);
D3DXMatrixRotationX(&rotx, Bone[b].Anim[1].rotx - Bone[b].Anim[0].rotx);
D3DXMatrixRotationY(&roty, Bone[b].Anim[1].roty - Bone[b].Anim[0].roty);
D3DXMatrixRotationZ(&rotz, Bone[b].Anim[1].rotz - Bone[b].Anim[0].rotz);
D3DXVec3Transform(&newpos,&oldpos,&(rotx*roty*rotz));
skeleton[Bone[b].Bone_vertices[i].id].X = newpos.x;
skeleton[Bone[b].Bone_vertices[i].id].Y = newpos.y;
skeleton[Bone[b].Bone_vertices[i].id].Z = newpos.z;
}
}[/code]

Share this post


Link to post
Share on other sites
[quote name='mosweg' timestamp='1313773379' post='4851282']
If vertex.x position is 0 and the x rotation is -0.64196301
Then the new .x position is 0
A quick example of different positions before and after RotationX -0.64196301

old = 0
new = 0
difference = 0

old = 1
new = 0,91466111
difference = 0,08533889

old = 2
new = 1,8293222
difference = 0,1706778
[/quote]
Actually, this looks correct to me. A point at X=0 will not move in the X direction when rotated about the X-axis, and a point at X=2 will move twice as far in the X direction as one at X=1 when rotated about the X-axis.

Share this post


Link to post
Share on other sites
After doing some combinations it seems that the new position isn't the correct one.
I've exported the frame 1 object and the frame 2 object as different .x file so i could compare the positions of the vertices.
Here are the results on one vertex:

Frame 1.x:
Vertex before animation: 20.261631;0.000000;16.652271;;
Frame 2.x:
Vertex after animation: 26.864090;-0.000002;1.800200;;

Now the results with different D3DXMatrixRotationX
Anim[0] is the rotation of the first frame and Anim[1] is the rotation of the second frame

Bone[1].Anim[1].rotx
Before: {x=20.261631 y=0.00000000 z=16.652271 }
After: {x=25.590113 y=0.00000000 z=5.7426424 ...}


Bone[1].Anim[1].rotx - Bone[1].Anim[0].rotx
Before: {x=20.261631 y=0.00000000 z=16.652271 }
After: {x=24.023504 y=0.00000000 z=10.521553 ...}


Bone[1].Anim[1].rotx + Bone[1].Anim[0].rotx
Before: {x=20.261631 y=0.00000000 z=16.652271 }
After: {x=26.215748 y=0.00000000 z=0.75257111 ...}


Bone[1].Anim[1].rotx * Bone[1].Anim[0].rotx
Before: {x=20.261631 y=0.00000000 z=16.652271 }
After: {x=21.672215 y=0.00000000 z=14.769795 ...}

As you see none of those new positions are 26.864090;-0.000002;1.800200
What did I forgot to add so the new position is the correct one?

Share this post


Link to post
Share on other sites

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