Bug on the skinned meshes
Posted: Mon Sep 17, 2012 10:47 pm
I have found an inconsistency between the EJUOR_READ and the EJUOR_CONTROL modes of the skinned meshes.
Tracing all the process, the skinning works properly, but the update of the bone nodes doesn't happen correctly on the EJUOR_CONTROL skinned meshes. Taking a peek to the code of the getMeshForCurrentFrame() method of the CAnimatedMeshSceneNode class, in the file CAnimatedMeshSceneNode.cpp, in the source directory, there is a conditional that is executed when the mode is EJUOR_READ:
There is a "slow" comment on it making it to note that the updating of that scene node is slow when that happens. The next code is another conditional that triggers when the mesh is controlled using EJUOR_CONTROL mode.
Taking a peek to the "animateMesh()" method, there is no place where the jointChildNodes are ever updated. This results in that the child nodes aren't updated properly, and thus, they have to wait for the scene tree to progress until it reaches them, causing them a small delay because of an improper update of its transformations.
Adding that same code to the EJUOR_CONTROL conditional solves this, and, although it is marked as slow and temporary, it is also convenient, The function updateAbsolutePositionOfAllChildren() doesn't diference nodes, and thus the childs (bones or not) are updated correctly, and their rendering happens on the expected place, instead of the place that they had been the previous frame.
While in the search of a better option, this modification solves this problem.
For the Skinned meshes, maybe their children nodes should be rendered BEFORE the skinned node because this would force the nodes to update, and maybe the scene traverse wouldn't suffer much, because this can be done locally in the skinned mesh node scope, and when the regular flow of the scene traverse wouldn't be affected too much.
Tracing all the process, the skinning works properly, but the update of the bone nodes doesn't happen correctly on the EJUOR_CONTROL skinned meshes. Taking a peek to the code of the getMeshForCurrentFrame() method of the CAnimatedMeshSceneNode class, in the file CAnimatedMeshSceneNode.cpp, in the source directory, there is a conditional that is executed when the mode is EJUOR_READ:
Code: Select all
if (JointMode == EJUOR_READ)//read from mesh
{
skinnedMesh->recoverJointsFromMesh(JointChildSceneNodes);
//---slow---
for (u32 n=0;n<JointChildSceneNodes.size();++n)
if (JointChildSceneNodes[n]->getParent()==this)
{
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
}
}
Code: Select all
if(JointMode == EJUOR_CONTROL)
{
// For meshes other than EJUOR_CONTROL, this is done by calling animateMesh()
skinnedMesh->updateBoundingBox();
}
Adding that same code to the EJUOR_CONTROL conditional solves this, and, although it is marked as slow and temporary, it is also convenient, The function updateAbsolutePositionOfAllChildren() doesn't diference nodes, and thus the childs (bones or not) are updated correctly, and their rendering happens on the expected place, instead of the place that they had been the previous frame.
Code: Select all
if(JointMode == EJUOR_CONTROL)
{
// For meshes other than EJUOR_CONTROL, this is done by calling animateMesh()
//---slow---
for (u32 n=0;n<JointChildSceneNodes.size();++n)
if (JointChildSceneNodes[n]->getParent()==this)
{
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
}
skinnedMesh->updateBoundingBox();
}
For the Skinned meshes, maybe their children nodes should be rendered BEFORE the skinned node because this would force the nodes to update, and maybe the scene traverse wouldn't suffer much, because this can be done locally in the skinned mesh node scope, and when the regular flow of the scene traverse wouldn't be affected too much.