1#include <IO/AssimpLoader/AssimpHandleDataLoader.hpp>
3#include <assimp/mesh.h>
4#include <assimp/scene.h>
8#include <Core/Asset/HandleData.hpp>
9#include <Core/Utils/Log.hpp>
11#include <IO/AssimpLoader/AssimpWrapper.hpp>
16using namespace Core::Utils;
17using namespace Core::Asset;
20AssimpHandleDataLoader::AssimpHandleDataLoader(
const bool VERBOSE_MODE ) :
21 DataLoader<HandleData>( VERBOSE_MODE ) {}
24AssimpHandleDataLoader::~AssimpHandleDataLoader() =
default;
28void AssimpHandleDataLoader::loadData(
const aiScene* scene,
32 if ( scene ==
nullptr ) {
33 LOG( logDEBUG ) <<
"AssimpHandleDataLoader : scene is nullptr.";
38 LOG( logDEBUG ) <<
"File contains handle.";
39 LOG( logDEBUG ) <<
"Handle Loading begin...";
42 loadHandleData( scene, data );
44 if ( m_verbose ) { LOG( logDEBUG ) <<
"Handle Loading end.\n"; }
51aiNode* findMeshNode( aiNode* node,
const aiScene* scene,
const aiString& meshName ) {
53 for ( uint i = 0; i < node->mNumMeshes; ++i ) {
54 if ( scene->mMeshes[node->mMeshes[i]]->mName == meshName ) {
return node; }
57 for ( uint i = 0; i < node->mNumChildren; ++i ) {
58 aiNode* n = findMeshNode( node->mChildren[i], scene, meshName );
59 if ( n !=
nullptr ) {
return n; }
65 flags[assimpToCore( node->mName )] = flag;
66 for ( uint i = 0; i < node->mNumChildren; ++i ) {
67 initMarks( node->mChildren[i], flags, flag );
71void markParents( aiNode* node,
75 const std::string nodeName = assimpToCore( node->mName );
76 if ( flag[nodeName] ) {
80 flag[nodeName] =
true;
83 meshParents.
begin(), meshParents.
end(), [node](
const auto& n ) { return n == node; } );
84 if ( it != meshParents.
end() ) {
85 flag[nodeName] =
false;
89 if ( node->mParent !=
nullptr ) { markParents( node->mParent, scene, meshParents, flag ); }
95void AssimpHandleDataLoader::loadHandleData(
103 initMarks( scene->mRootNode, needNode );
109 for ( uint n = 0; n < scene->mNumMeshes; ++n ) {
110 const aiMesh* mesh = scene->mMeshes[n];
112 std::string meshName = assimpToCore( mesh->mName );
113 while ( meshNames.
find( meshName ) != meshNames.
end() ) {
116 meshNames.
insert( meshName );
119 if ( !mesh->HasBones() ) {
continue; }
122 aiNode* meshNode = findMeshNode( scene->mRootNode, scene, mesh->mName );
123 while ( meshNode !=
nullptr ) {
125 meshNode = meshNode->mParent;
129 for ( uint j = 0; j < mesh->mNumBones; ++j ) {
130 const aiBone* bone = mesh->mBones[j];
132 const std::string boneName = assimpToCore( bone->mName );
134 mapBone2Data[boneName].m_name = boneName;
136 loadHandleComponentDataWeights( bone, meshName, mapBone2Data[boneName] );
138 aiNode* node = scene->mRootNode->FindNode( bone->mName );
139 if ( node ==
nullptr ) {
continue; }
141 markParents( node, scene, meshParents[n], needNode );
143 if ( node->mNumChildren == 1 ) {
144 const aiNode* child = node->mChildren[0];
145 const std::string childName = assimpToCore( child->mName );
147 needNode[childName] =
true;
149 mapBone2Data[childName].m_name = childName;
155 auto rootNode = scene->mRootNode;
156 for ( uint i = 0; i < rootNode->mNumChildren; ++i ) {
157 auto node = rootNode->mChildren[i];
158 if ( needNode[assimpToCore( node->mName )] ) {
continue; }
162 return std::find_if( nodes.begin(), nodes.end(), [node]( const auto& n ) {
166 if ( res != meshParents.
end() ) {
continue; }
168 initMarks( node, needNode,
true );
173 for (
const auto& n : needNode ) {
174 if ( !n.second ) {
continue; }
176 mapBone2Data[n.first].m_name = n.first;
178 const aiNode* node = scene->mRootNode->FindNode( aiString( n.first ) );
179 for ( uint j = 0; j < node->mNumChildren; ++j ) {
180 const std::string childName = assimpToCore( node->mChildren[j]->mName );
181 if ( needNode.at( childName ) ) {
183 mapBone2Data[childName].m_name = childName;
185 edgeList.
push_back( { n.first, childName } );
191 for (
auto& bone : mapBone2Data ) {
192 loadHandleComponentDataFrame( scene, aiString( bone.first ), bone.second );
197 for (
const auto& node : needNode ) {
198 if ( node.second ) { roots.
insert( node.first ); }
201 for (
auto edge : edgeList ) {
202 roots.
erase( edge.second );
203 leaves.
erase( edge.first );
207 for (
auto root : roots ) {
208 HandleData* handle =
new HandleData();
209 handle->setType( HandleData::SKELETON );
210 handle->setName( root );
212 Ra::Core::Transform frame = Ra::Core::Transform::Identity();
213 aiNode* node = scene->mRootNode->FindNode( aiString( root ) );
214 while ( node->mParent !=
nullptr ) {
215 node = node->mParent;
216 frame = assimpToCore( node->mTransformation ) * frame;
218 handle->setFrame( frame );
222 fillHandleData( root, edgeList, mapBone2Data, nameTable, handle );
223 handle->setNameTable( nameTable );
226 bool needEndBone =
false;
228 if ( nameTable.
find( leaf ) != nameTable.
end() ) {
229 const auto& handleComponentData = mapBone2Data[leaf];
230 for (
const auto& mesh : handleComponentData.m_weights ) {
231 if ( mesh.second.size() != 0 ) {
236 if ( needEndBone ) {
break; }
239 handle->needEndNodes( needEndBone );
241 if ( handle->isSkeleton() && !handle->hasEdges() ) {
247 data.emplace_back( handle );
248 if ( m_verbose ) { handle->displayInfo(); }
253void AssimpHandleDataLoader::loadHandleComponentDataFrame(
const aiScene* scene,
254 const aiString& boneName,
255 HandleComponentData& data )
const {
257 data.m_frame.setIdentity();
258 aiNode* node = scene->mRootNode->FindNode( boneName );
259 while ( node !=
nullptr ) {
260 data.m_frame = assimpToCore( node->mTransformation ) * data.m_frame;
261 node = node->mParent;
265void AssimpHandleDataLoader::loadHandleComponentDataWeights(
const aiBone* bone,
267 HandleComponentData& data )
const {
269 for ( uint j = 0; j < bone->mNumWeights; ++j ) {
271 data.m_weights[meshName].push_back( weight );
273 data.m_bindMatrices[meshName] = assimpToCore( bone->mOffsetMatrix );
276void AssimpHandleDataLoader::fillHandleData(
281 HandleData* data )
const {
283 nameTable[node] = uint( data->getComponentData().size() );
284 data->getComponentData().push_back( mapBone2Data.
at( node ) );
286 for (
const auto& mesh : mapBone2Data.
at( node ).m_weights ) {
287 data->addBindMesh( mesh.first );
290 for (
const auto& edge : edgeList ) {
291 if ( edge.first == node ) {
292 fillHandleData( edge.second, edgeList, mapBone2Data, nameTable, data );
293 data->getEdgeData().push_back(
294 { nameTable.
at( edge.first ), nameTable.
at( edge.second ) } );
hepler function to manage enum as underlying types in VariableSet