# Vertex skinning, blending matrices problem

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

## Recommended Posts

I'm doing something wrong here with the skeleton animations, using matrices. Most vertices have only 1 bone, but where 2 bones are used it goes wrong. If I use them seperately the result is correct. So, either I initialize the skeleton wrong, or the blending goes wrong. In case 2 bones are used on a vertex, they both have a weight of 0.5 so far. The sum of the weights is always one.
// initialize all vertices via the INVERSE MATRIX of the base pose
for each vertex
m4x4 bone1Matrix	= skeleton.BasePose.InverseMatrix[ vertex.boneIndex1 ];
m4x4 bone2Matrix	= skeleton.BasePose.InverseMatrix[ vertex.boneIndex2 ];

// Multiply matrices with the basepose world vertices
v1	= bone1Matrix * skeleton.Mesh.vertex[i]
v2	= bone2Matrix * skeleton.Mesh.vertex[i]

// result (weights are both 0.5)
// Store into a initial skinned vertexlist
vRes	= v1 * weight1  +  v2 * weight2;
skeleton.BasePose.skinnedVertex[i] = vRes;

Next step would be animating with the base data:
// Transform all vertices
for each vertex
m4x4 bone1Matrix	= skeleton.currentFrame.Matrix[ vertex.boneIndex1 ];
m4x4 bone2Matrix	= skeleton.currentFrame.Matrix[ vertex.boneIndex2 ];

// Multiply current matrices with the skinned vertices
// from the initial stage.
v1	= bone1Matrix * skeleton.BasePose.skinnedVertex[i]
v2	= bone2Matrix * skeleton.BasePose.skinnedVertex[i]

// result (weights are both 0.5)
// Store into result
vRes	= v1 * weight1  +  v2 * weight2;
skeleton.skinnedResult.vertex[i] = vRes;

I think it goes wrong because the initial vertex was made by two matrices. The two seperate transformations in the second step go wrong. I could fix this by storing TWO sets of initial skinned vertices, but maybe it can be fixed alot more easy. I mean, skinning shaders only have 1 set of vertices either so... Rick

##### Share on other sites
You could use 2 arrays of pre-calculated vertices, I suppose. But, for large meshes, those arrays could be pretty big.

Perhaps the most straightforward way would be to just use the inverse matrix to calculate the final vertex positions.

// Transform all verticesfor each vertex	m4x4 bone1Matrix = skeleton.currentFrame.Matrix[ vertex.boneIndex1 ];	m4x4 bone2Matrix = skeleton.currentFrame.Matrix[ vertex.boneIndex2 ];		// Multiply current matrices with the inverse matrix and vert	v1 = bone1Matrix * skeleton.BasePose.InverseMatrix[vertex.boneIndex1] * skeleton.Mesh.vertex[i];	v2 = bone2Matrix * skeleton.BasePose.InverseMatrix[vertex.boneIndex2] * skeleton.Mesh.vertex[i];		// result (weights are both 0.5)	// Store into result	vRes	= v1 * weight1  +  v2 * weight2;	skeleton.skinnedResult.vertex[i] = vRes;

Does that work?

Because several vertices may be influenced by the same bone, you can also calculate an array of
// finalMatrix = array of size(numBones)finalMatrix[boneIndex] = boneMatrix[boneIndex]*inverseMatrix[boneIndex]...Then, in your loop, calculate:v1 = finalMatrix[boneIndex1]*meshVert[i];v2 = finalMatrix[boneIndex2]*meshVert[i];

Quote:
 skinning shaders only have 1 set of vertices either

Not sure what you mean by this. Shaders can be written to use multiple bone indices and matrices. Is that your concern?

A common algorithm to use with a shader is to calculate an array of finalMatrices = boneMatrix * inverseMatrix for each bone, as mentioned above.
...
The vertex position is calculated in the shader, given an array of those finalMatrices:
pos = vector4( 0, 0, 0, 1);v = input_mesh_vertex;numWeights = number_of_weights_for_this_vertex;weight[numWeights] = array_of_weights, usually passed in shader input structure per-vertexboneIndex = array_of_bone_indices, usually passed in shader input per-vertexsumWeights = 0;for( int n=0; n < numWeights-1; n++){   pos += finalMatrix[ boneIndex[n] ] * v * weight[n];   sumWeights += weight[n];}pos += finalMatrix[ boneIndex[numWeights-1]] * v * ( 1 - sumWeights );

This shader code, by the way, may have to have the order of multiplications reversed. I.e., pos += weight[n] * v * finalMatrix[boneIndex[n]], etc.

[Edited by - Buckeye on February 19, 2010 8:39:26 AM]

##### Share on other sites
Thanks for all the info!

What I meant to say was that shaders only make use of 1 set of vertices, and 1 set of matrices. The problem is that I make an initial list of vertices that are multiplied with their inverse bone matrix. But it seems to go wrong when I create an initial vertex that is assigned to 2 bones.

You showed how to make "final matrices", sounds what I need. If I understand it properly, instead of making this "initial mesh" I'll apply the base pose at runtime on the resulting matrices. So I can use the original set of vertices.

I gave it a quick try with just 1 weight. A few times I got "The Thing" as a result, but now he's walking like a charm again :). I'll try it with multiple bones now.

Thanks!
Rick

##### Share on other sites
And with two bones it finally works as well :) Thanks again

##### Share on other sites

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

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628645
• Total Posts
2984015

• 9
• 9
• 10
• 21
• 20