Sign in to follow this  
Inukai

wrong(?) bone matrices in animation

Recommended Posts

hi guys.
I'm new to 3d-programming and need help with my game.

I exported a fbx model into my own file format and want to load it in my game.
I managed to load all the data from my file and load it into my model class.

I also checked the skinning10 example and managed to create an effect file:
effect.fx:
[CODE]

Texture2D colorMap_ : register( t0 );
SamplerState colorSampler_ : register( s0 );

cbuffer cbChangesEveryFrame : register( b0 )
{
matrix worldMatrix;
};
cbuffer cbNeverChanges : register( b1 )
{
matrix viewMatrix;
};
cbuffer cbChangeOnResize : register( b2 )
{
matrix projMatrix;
};
cbuffer cbBoneMatrix : register( b3 )
{
Matrix boneMat[100];
};
struct VS_Input
{
float4 pos : POSITION;
float2 tex0 : TEXCOORD0;
uint4 bones : BONES;
float4 weights : WEIGHTS;
};
struct PS_Input
{
float4 pos : SV_POSITION;
float2 tex0 : TEXCOORD0;
};

PS_Input VS_Main( VS_Input vertex )
{
PS_Input vsOut = ( PS_Input )0;

float4 vertexPos = 0;

int boneId = vertex.bones[0];
if(vertex.weights[0] > 0) vertexPos += vertex.weights[0] * mul(boneMat[boneId],vertex.pos);
boneId = vertex.bones[1];
if(vertex.weights[1] > 0) vertexPos += vertex.weights[1] * mul(boneMat[boneId],vertex.pos);
boneId = vertex.bones[2];
if(vertex.weights[2] > 0) vertexPos += vertex.weights[2] * mul(boneMat[boneId],vertex.pos);
boneId = vertex.bones[3];
if(vertex.weights[3] > 0) vertexPos += vertex.weights[3] * mul(boneMat[boneId],vertex.pos);


vsOut.pos = mul( vertexPos, viewMatrix );
vsOut.pos = mul( vsOut.pos, projMatrix );
vsOut.tex0 = vertex.tex0;
return vsOut;
}

float4 PS_Main( PS_Input frag ) : SV_TARGET
{
return colorMap_.Sample( colorSampler_, frag.tex0 );
}
[/CODE]

method to play the animation and create the bone matrices
[CODE]
bool Model::PlayAnimation(std::string aniName)
{
aniName = _animations[0].getName(); //fixed for testing
static int cnt = 0; //counter for the keyframes
for(int i = 0; i<_numberOfAnimations; i++)
{
if(_animations[i].getName() == aniName)
_currentAni = i;
}

int boneId = 0;
XMFLOAT4X4 matrix;
XMFLOAT3 rot;
XMFLOAT3 transl;
XMFLOAT3 scal;

//set the world matrix (put it into the root bone)
XMStoreFloat4x4(&matrix, XMMatrixRotationRollPitchYaw(90*PI/180, 0*PI/180, 0*PI/180));
_bones[0].setWorldMatrix(matrix);

//root bone is at i = 0 and bones are sorted so that the parents are called before their childs alwaya
for(int i= 0; i<_numberOfBones; i++)
{
//get the information from the animation class, I controlled the values, they are right.
boneId = _animations[_currentAni].getKeyFrames()[i].getBoneId();
rot = XMFLOAT3(_animations[_currentAni].getKeyFrames()[i].getRotation()[cnt][0], _animations[_currentAni].getKeyFrames()[i].getRotation()[cnt][1], _animations[_currentAni].getKeyFrames()[i].getRotation()[cnt][2]);
transl = XMFLOAT3(_animations[_currentAni].getKeyFrames()[i].getTranslation()[cnt][0], _animations[_currentAni].getKeyFrames()[i].getTranslation()[cnt][1], _animations[_currentAni].getKeyFrames()[i].getTranslation()[cnt][2]);
scal = XMFLOAT3(_animations[_currentAni].getKeyFrames()[i].getScaling()[cnt][0], _animations[_currentAni].getKeyFrames()[i].getScaling()[cnt][1], _animations[_currentAni].getKeyFrames()[i].getScaling()[cnt][2]);

//multiply the matrices into the matrix variable
XMStoreFloat4x4(&matrix, XMMatrixTranslation(transl.x, transl.y, transl.z));
XMStoreFloat4x4(&matrix, XMLoadFloat4x4(&matrix)*XMMatrixRotationRollPitchYaw(rot.x*PI/180, rot.y*PI/180, rot.z*PI/180));
XMStoreFloat4x4(&matrix, XMLoadFloat4x4(&matrix)* XMMatrixScaling(scal.x, scal.y, scal.z));
_bones[i].setBoneMatrix(matrix, _bones);
XMStoreFloat4x4(&_boneMatrix[boneId], _bones[i].getPoseMatrix());
}
cnt++;
if(cnt>=20)
{
cnt = 0;
}
return true;
}
[/CODE]

And here are the 3 methods in my bone class:
[CODE]

void setWorldMatrix(XMFLOAT4X4 mat)
{
_worldMatrix = mat;
}

//get calculated values from the playAnimation method and put it as world matrix for the children
void setBoneMatrix(XMFLOAT4X4 mat, Bone* children)
{
XMStoreFloat4x4(&_boneMatrix, (XMLoadFloat4x4(&mat)));


for(int i = 0; i<_numberOfChildren; i++)
{
children[_children[i]].setWorldMatrix(mat);
};
return;
};

//will be stored in the bonebuffer for the hlsl file
XMMATRIX getPoseMatrix() { return (XMLoadFloat4x4(&_boneMatrix)* XMLoadFloat4x4(&_worldMatrix)); };
[/CODE]


My Problem is, that one of my models got strange graphic artifacs (he looks like he is exploded) (human-like with 40 bones, he is moving...kinda)
And the other model(snake like with 2 bones) isn't even moving. (well, the root bone is probably right, but the tail isn't moving(it shoulld move up and down))
Both models are rendered correct when i set the boneMatrices for the hlsl file only on Matrix.Identity(). The hirachy should be right aswell, because I can change the worldMatrix for the root bone and all vertices are moving.

I'm kinda new to 3d programming and I guess I failed with the matrix calculations.
I'll attach the screens of the models. I count on you guy ;)

[img]http://s7.directupload.net/images/120610/8xpy45en.png[/img] Edited by Inukai

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