Getting proper bone transformation for a vertex


photo

Recommended Posts

Hi,

I am currently working on extracting final bone transformations for a skinned mesh for an animation and re-create them for later use. This shouldn't be a problem on first hand I thought because UNIGINE provides all necessary functions for it.

My idea was to implement the following steps:

1. Load a proper skinned mesh including necessary bones and apply an animation for it.

2. Iterate: For each animation frame

    2.1 Set the animation frame (via setFrame()) and update the bone transformation (calling updateSkinned())

    2.2 For each bone

        2.2.1 get the current bone transform via getBoneTransform() and store it for later use.

 

However, when I load a new skinned mesh with the exact skinned mesh (and bones), apply for each animation frame the bone transform for each vertex, respecting their bone weight, I got wrong results.

So I try to debug a little bit and try to calculate the vertex positions for and fresh created mesh manually to see if I get something wrong. For a new skinned mesh with (currently now animation applied, no layers) I do the following:

Spoiler

for (int i = 0; i < tcindices.size(); ++i)
{
  vec3 position = instancedMesh->getVertex(tcindices[i], 0);

  ivec4 bones = instancedMesh->getWeightBones(tcindices[i], 0);
  vec4 weights = instancedMesh->getWeightWeights(tcindices[i], 0);

  mat4 finalMatrix = instancedMesh->getBoneTransform(bones.x) * weights.x;
  finalMatrix += instancedMesh->getBoneTransform(bones.y) * weights.y;
  finalMatrix += instancedMesh->getBoneTransform(bones.z) * weights.z;
  finalMatrix += instancedMesh->getBoneTransform(bones.w) * weights.w;

  Vec3 vertexPosition = Vec3( position * finalMatrix);
  Visualizer::renderPoint3D(Vec3(vertexPosition.x, vertexPosition.y, vertexPosition.z), 0.01f, vec4_one);

}		

 

Calculating the vertex position respecting the bone transform and weights was just the standard approach that is used in many other engine implementations. But still for this case the results are not correct. I know, that the getVertex()-function will return the already transformed result for an animated frame. But when I use a standard t-bose I thought the results would be equal to no animation applied to it.

So the question is how do I get the proper bone transformation matrix for each animation frame that (by multiplying with the vertex coordinates by a standard t-pose) will result in proper vertex transformation, like getVertex() will do after updating the animation frame via the API?

 

Thanks in advance

Christian

Link to post

Hi Christian,

Can you send us the model itself and results in screenshots / video?

Maybe there is some troubles with local transforms relative the parent bones, try to use getBoneWorldTransform instead: https://developer.unigine.com/en/docs/future/api/library/objects/class.objectmeshskinned?rlang=cpp#getBoneWorldTransform_int_Mat4

How to submit a good bug report
---
FTP server for test scenes and user uploads:

Link to post

Hi @karpych11;

awesome, you are a time saver for me! inverse bone transform does indeed solved the problem for me.

Many thanks to you!

 

Link to post