Added ArmaturePopulate scale process for all formats

This commit is contained in:
RevoluPowered
2019-10-26 18:47:48 +01:00
parent 93efe4197a
commit 46cdd81d75
5 changed files with 372 additions and 194 deletions

View File

@@ -121,39 +121,6 @@ namespace Assimp {
ConvertGlobalSettings();
TransferDataToScene();
// Now convert all bone positions to the correct mOffsetMatrix
std::vector<aiBone*> bones;
std::vector<aiNode*> nodes;
std::map<aiBone*, aiNode*> bone_stack;
BuildBoneList(out->mRootNode, out->mRootNode, out, bones);
BuildNodeList(out->mRootNode, nodes );
BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes);
std::cout << "Bone stack size: " << bone_stack.size() << std::endl;
for( std::pair<aiBone*, aiNode*> kvp : bone_stack )
{
aiBone *bone = kvp.first;
aiNode *bone_node = kvp.second;
std::cout << "active node lookup: " << bone->mName.C_Str() << std::endl;
// lcl transform grab - done in generate_nodes :)
//bone->mOffsetMatrix = bone_node->mTransformation;
aiNode * armature = GetArmatureRoot(bone_node, bones);
ai_assert(armature);
// set up bone armature id
bone->mArmature = armature;
// set this bone node to be referenced properly
ai_assert(bone_node);
bone->mNode = bone_node;
}
// if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE
// to make sure the scene passes assimp's validation. FBX files
// need not contain geometry (i.e. camera animations, raw armatures).
@@ -172,167 +139,6 @@ namespace Assimp {
std::for_each(textures.begin(), textures.end(), Util::delete_fun<aiTexture>());
}
/* Returns the armature root node */
/* This is required to be detected for a bone initially, it will recurse up until it cannot find another
* bone and return the node
* No known failure points. (yet)
*/
aiNode * FBXConverter::GetArmatureRoot(aiNode *bone_node, std::vector<aiBone*> &bone_list)
{
while(bone_node)
{
if(!IsBoneNode(bone_node->mName, bone_list))
{
std::cout << "Found valid armature: " << bone_node->mName.C_Str() << std::endl;
return bone_node;
}
bone_node = bone_node->mParent;
}
std::cout << "can't find armature! node: " << bone_node << std::endl;
return NULL;
}
/* Simple IsBoneNode check if this could be a bone */
bool FBXConverter::IsBoneNode(const aiString &bone_name, std::vector<aiBone*>& bones )
{
for( aiBone *bone : bones)
{
if(bone->mName == bone_name)
{
return true;
}
}
return false;
}
/* Pop this node by name from the stack if found */
/* Used in multiple armature situations with duplicate node / bone names */
/* Known flaw: cannot have nodes with bone names, will be fixed in later release */
/* (serious to be fixed) Known flaw: nodes which have more than one bone could be prematurely dropped from stack */
aiNode* FBXConverter::GetNodeFromStack(const aiString &node_name, std::vector<aiNode*> &nodes)
{
std::vector<aiNode*>::iterator iter;
aiNode *found = NULL;
for( iter = nodes.begin(); iter < nodes.end(); ++iter )
{
aiNode *element = *iter;
ai_assert(element);
// node valid and node name matches
if(element->mName == node_name)
{
found = element;
break;
}
}
if(found != NULL) {
// now pop the element from the node list
nodes.erase(iter);
return found;
}
return NULL;
}
/* Prepare flat node list which can be used for non recursive lookups later */
void FBXConverter::BuildNodeList(aiNode *current_node, std::vector<aiNode *> &nodes)
{
ai_assert(current_node);
for( unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId)
{
aiNode *child = current_node->mChildren[nodeId];
ai_assert(child);
nodes.push_back(child);
BuildNodeList(child, nodes);
}
}
/* Reprocess all nodes to calculate bone transforms properly based on the REAL mOffsetMatrix not the local. */
/* Before this would use mesh transforms which is wrong for bone transforms */
/* Before this would work for simple character skeletons but not complex meshes with multiple origins */
/* Source: sketch fab log cutter fbx */
void FBXConverter::BuildBoneList(aiNode *current_node, const aiNode * root_node, const aiScene *scene, std::vector<aiBone*> &bones )
{
ai_assert(scene);
for( unsigned int nodeId = 0; nodeId < current_node->mNumChildren; ++nodeId)
{
aiNode *child = current_node->mChildren[nodeId];
ai_assert(child);
// check for bones
for( unsigned int meshId = 0; meshId < child->mNumMeshes; ++meshId)
{
ai_assert(child->mMeshes);
unsigned int mesh_index = child->mMeshes[meshId];
aiMesh *mesh = scene->mMeshes[ mesh_index ];
ai_assert(mesh);
for( unsigned int boneId = 0; boneId < mesh->mNumBones; ++boneId)
{
aiBone *bone = mesh->mBones[boneId];
ai_assert(bone);
// duplicate meshes exist with the same bones sometimes :)
// so this must be detected
if( std::find(bones.begin(), bones.end(), bone) == bones.end() )
{
// add the element once
bones.push_back(bone);
}
}
// find mesh and get bones
// then do recursive lookup for bones in root node hierarchy
}
BuildBoneList(child, root_node, scene, bones);
}
}
/* A bone stack allows us to have multiple armatures, with the same bone names
* A bone stack allows us also to retrieve bones true transform even with duplicate names :)
*/
void FBXConverter::BuildBoneStack(aiNode *current_node, const aiNode *root_node, const aiScene *scene,
const std::vector<aiBone *> &bones,
std::map<aiBone *, aiNode *> &bone_stack,
std::vector<aiNode*> &node_stack )
{
ai_assert(scene);
ai_assert(root_node);
ai_assert(!node_stack.empty());
for( aiBone * bone : bones)
{
ai_assert(bone);
aiNode* node = GetNodeFromStack(bone->mName, node_stack);
if(node == NULL)
{
node_stack.clear();
BuildNodeList(out->mRootNode, node_stack );
std::cout << "Resetting bone stack: null element " << bone->mName.C_Str() << std::endl;
node = GetNodeFromStack(bone->mName, node_stack);
if(!node) {
std::cout << "serious import issue armature failed to be detected?" << std::endl;
continue;
}
}
std::cout << "Successfully added bone to stack and have valid armature: " << bone->mName.C_Str() << std::endl;
bone_stack.insert(std::pair<aiBone*, aiNode*>(bone, node));
}
}
void FBXConverter::ConvertRootNode() {
out->mRootNode = new aiNode();
std::string unique_name;