Public Group

# Skinned Animation Problems

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

## 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 animationfor(unsigned int i = 0; i < mNumChannels; ++i) //each channel affects a single bone{	chan = &mChannels;	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 functionvoid 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, 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 130in 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 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 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 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 codefinal = orient * trans; //rotation followed by translation

// in your shadergl_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 on other sites
So speaketh the master. How you read all that code and picked that out I'll never know Buck. Amazing.

##### Share on other sites
Quote:
 Original post by BuckeyeI'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 codefinal = orient * trans; //rotation followed by translation// in your shadergl_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]

1. 1
2. 2
3. 3
Rutin
22
4. 4
JoeJ
16
5. 5

• 14
• 29
• 13
• 11
• 11
• ### Forum Statistics

• Total Topics
631775
• Total Posts
3002286
×