christian.wolf2 Posted June 4, 2021 Share Posted June 4, 2021 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 comment
silent Posted June 4, 2021 Share Posted June 4, 2021 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: ftp://files.unigine.com user: upload password: 6xYkd6vLYWjpW6SN Link to comment
karpych11 Posted June 5, 2021 Share Posted June 5, 2021 Hello, You can use inverse bone transform to change position of vertex relative to bones. The attachment contains a model and sample code. AppWorldLogic.hAppWorldLogic.cppwalk.fbx 2 Link to comment
christian.wolf2 Posted June 7, 2021 Author Share Posted June 7, 2021 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 comment
Recommended Posts