Sign in to follow this  

Skinned Animation Problems

This topic is 2666 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'm currently trying to animate my mesh with skinned animation, but the results are very off. With no animation transformations preformed on the bones, the model is displayed properly, however when it is animated, the whole model becomes erratic. I think my skeleton is correct, so I think there's something wrong with the way I'm animating and transforming the bones.
I've looked through a lot of tutorials and many books but I've really been struggeling with this for a while now. I believe all the data is being loaded correctly and I'm just not using the transformations correctly, but I haven't been able to pinpoint exactly what the problem.
What happens to the model is that I can see vertices moving around and rotating, but the mesh is skewed and not translated properly.
I'm using the data provided by Assimp for the animations, so there might be something I'm not aware of. Here is some of the relevant code.


//code in animation

for(unsigned int i = 0; i < mNumChannels; ++i) //each channel affects a single bone
{
chan = &mChannels[i];
math::Vec3<float> * posVec = &chan->mPositionKeys[0].mVec;
math::Quaternion * quat = &chan->mRotationKeys[0].mQuat;
float scale = chan->mScaleKeys[0].mVec.x; //turn into uniform scaling...
unsigned int j;
for(j = 0; j < chan->mNumPositionKeys; ++j)
{
if(chan->mPositionKeys[j].mTime >= delta){
posVec = &chan->mPositionKeys[j].mVec;
break;
}
}
for(j = 0; j < chan->mNumRotationKeys; ++j)
{
if(chan->mRotationKeys[j].mTime >= delta){
quat = &chan->mRotationKeys[j].mQuat;
break;
}
}
for(j = 0; j < chan->mNumScaleKeys; ++j)
{
if(chan->mScaleKeys[j].mTime >= delta){
scale = chan->mScaleKeys[j].mVec.x;
break;
}
}
SkeletonNode* node = mSkeleton->findNode(chan->mName);

//order of transformation is scaling, rotation, translation.
math::Matrix4x4 trans; //identity matrix
trans.mMatrix[3] = posVec->x;
trans.mMatrix[7] = posVec->y;
trans.mMatrix[11] = posVec->z;

math::Matrix4x4 matscle; //identity matrix
matscle.mMatrix[0] = scale;
matscle.mMatrix[5] = scale;
matscle.mMatrix[10] = scale;

math::Matrix4x4 orient;
quat->toMatrix4x4(orient);

math::Matrix4x4 final;

final = orient * trans; //not using scale for testing
node->updateTransform(final);
}
mSkeleton->updateBones()







void SkeletonNode::updateTransform(math::Matrix4x4& transform)
{
mLocalTransform = transform;
return;
}





//update bone helper function

void Skeleton::updateBonesH(SkeletonNode *node, math::Matrix4x4 transform)
{
if(!node) return;
node->mGlobalTransform = transform * node->mLocalTransform;
for(unsigned int i = 0; i < node->mNumChildren; ++i)
{
updateBonesH(&node->mChildren[i], node->mGlobalTransform);

}
if(node->mBone){

math::Matrix4x4 b = node->mBone->mOffsetMatrix; //inverse bind pos
math::Matrix4x4 c = node->mGlobalTransform; //current pose

math::Matrix4x4 f = b * c;
node->mBone->mFinalMatrix = f;
}
}




And here is my vertex shader...


#version 130

in vec4 position;

in vec4 boneWeightValue;
in vec4 boneWeightIndex;

uniform mat4 boneMatrices[32];

uniform mat4 perspectiveModelViewMatrix;
uniform mat4 modelViewMatrix;

void main()
{

vec4 pos1 = boneWeightValue.x * (boneMatrices[int(boneWeightIndex.x)] * position);
vec4 pos2 = boneWeightValue.y * (boneMatrices[int(boneWeightIndex.y)] * position);
vec4 pos3 = boneWeightValue.z * (boneMatrices[int(boneWeightIndex.z)] * position);
vec4 pos4 = boneWeightValue.w * (boneMatrices[int(boneWeightIndex.w)] * position);

vec4 pos = pos1 + pos2 + pos3 + pos4;
gl_Position = perspectiveModelViewMatrix * pos;
}




The bone matrices seem to be transferred correctly to the shader, since the initial pose, without any animation, is perfectly fine.
I would really appreciate it if anyone has any experience working with Assimp animations, or can help me in understand what I'm doing wrong.

[Edited by - lmffs on August 30, 2010 3:29:15 PM]

Share this post


Link to post
Share on other sites
Just an idea but I've had similar problems when the joint offsets where not properly aligned. Very weird animation resulted indeed. I can't read your code I'm not a good enough programmer but I would recommend just animating ONE bone and see if altering its offset matrix brings it under control. Assimp may use different axes to your API.

Are you animating in DirectX remember it uses left hand co-ords and the y axis is up - not into the screen.

I'll *try* and read your code and see if there's an issue. I've also got my own format to animate so I am not a total n00b with graphics programming but still very new ;o)

Hope that helps maybe? Out of curiousity does your skin translate in funny ways rather than just static rotation about a specific point (i.e. the joint position)?

**Edit**

I assume you know the procedure for rotation about an arbitrary axis?

Share this post


Link to post
Share on other sites
Thanks for the reply. I'm using Open GL for rendering, and I'm pretty sure my transformations are using the same axis as Assimp. And yes, parts of my skin rotates and moves very strangely, like the global transformation I'm building for that bone is getting corrupted along the way.

I'll follow your advice and try playing around with the bones directly and see what I can learn.

Share this post


Link to post
Share on other sites
I'm not sure how your math library works for matrices, and this could be totally incorrect, but it appears you're multiplying matrices in one order in some places and a different order in the shader.

// in your code
final = orient * trans; //rotation followed by translation


// in your shader
gl_Position = perspectiveModelViewMatrix * pos;

You might try reversing the order of matrix multiplication in one or the other of those instances.

As I remember, OpenGL functions multiply matrices in TRS order (translate, rotate, scale) and expects matrices in column-major order (rather than row-major).

Share this post


Link to post
Share on other sites
Quote:
Original post by Buckeye
I'm not sure how your math library works for matrices, and this could be totally incorrect, but it appears you're multiplying matrices in one order in some places and a different order in the shader.

// in your code
final = orient * trans; //rotation followed by translation


// in your shader
gl_Position = perspectiveModelViewMatrix * pos;

You might try reversing the order of matrix multiplication in one or the other of those instances.

As I remember, OpenGL functions multiply matrices in TRS order (translate, rotate, scale) and expects matrices in column-major order (rather than row-major).


I did try switching the order of the transformations many times before to see if I was messing up the order or something but none of them really gave me too much luck.

I completely got the the layout of the matrices wrong.
Quote:

All matrices in the library are row-major. That means that the matrices are stored row by row in memory, which is similar to the OpenGL matrix layout.

Should have double checked this, thank you for pointing this out Buckeye.

My animations are behaving a lot better now, however it seems as if not all the bones are being transformed or the offsets seem to be off a little bit. I wonder if there's something wrong with my skeleton layout or node transformations. I'll do an extensive check on this in a bit.

Thank you for all the help so far.



EDIT:

Okay, I got it all working now. I just had to transpose the rotation matrix, and fix some of the other matrix-layout problems. Thank you for the help guys.

[Edited by - lmffs on August 30, 2010 9:44:44 PM]

Share this post


Link to post
Share on other sites

This topic is 2666 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