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>
16 using namespace Core::Utils;
17 using namespace Core::Asset;
20 AssimpHandleDataLoader::AssimpHandleDataLoader(
const bool VERBOSE_MODE ) :
21 DataLoader<HandleData>( VERBOSE_MODE ) {}
24 AssimpHandleDataLoader::~AssimpHandleDataLoader() =
default;
28 void AssimpHandleDataLoader::loadData(
const aiScene* scene,
29 std::vector<std::unique_ptr<HandleData>>& data ) {
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"; }
51 aiNode* 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; }
64 void initMarks(
const aiNode* node, std::map<std::string, bool>& flags,
bool flag =
false ) {
65 flags[assimpToCore( node->mName )] = flag;
66 for ( uint i = 0; i < node->mNumChildren; ++i ) {
67 initMarks( node->mChildren[i], flags, flag );
71 void markParents( aiNode* node,
73 const std::vector<aiNode*>& meshParents,
74 std::map<std::string, bool>& flag ) {
75 const std::string nodeName = assimpToCore( node->mName );
76 if ( flag[nodeName] ) {
80 flag[nodeName] =
true;
82 auto it = std::find_if(
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 ); }
95 void AssimpHandleDataLoader::loadHandleData(
97 std::vector<std::unique_ptr<HandleData>>& data )
const {
99 std::set<std::string> meshNames;
102 std::map<std::string, bool> needNode;
103 initMarks( scene->mRootNode, needNode );
105 std::vector<std::vector<aiNode*>> meshParents( scene->mNumMeshes );
108 std::map<std::string, HandleComponentData> mapBone2Data;
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() ) {
114 meshName.append(
"_" );
116 meshNames.insert( meshName );
119 if ( !mesh->HasBones() ) {
continue; }
122 aiNode* meshNode = findMeshNode( scene->mRootNode, scene, mesh->mName );
123 while ( meshNode !=
nullptr ) {
124 meshParents[n].push_back( meshNode );
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; }
161 std::find_if( meshParents.begin(), meshParents.end(), [node](
const auto& nodes ) {
162 return std::find_if( nodes.begin(), nodes.end(), [node]( const auto& n ) {
166 if ( res != meshParents.end() ) {
continue; }
168 initMarks( node, needNode,
true );
172 std::vector<std::pair<std::string, std::string>> edgeList;
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 );
196 std::set<std::string> roots;
197 for (
const auto& node : needNode ) {
198 if ( node.second ) { roots.insert( node.first ); }
200 std::set<std::string> leaves = roots;
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 );
221 std::map<std::string, uint> nameTable;
222 fillHandleData( root, edgeList, mapBone2Data, nameTable, handle );
223 handle->setNameTable( nameTable );
226 bool needEndBone =
false;
227 for (
const std::string& leaf : leaves ) {
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(); }
253 void 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;
265 void AssimpHandleDataLoader::loadHandleComponentDataWeights(
const aiBone* bone,
266 const std::string& meshName,
267 HandleComponentData& data )
const {
269 for ( uint j = 0; j < bone->mNumWeights; ++j ) {
270 std::pair<uint, Scalar> weight( bone->mWeights[j].mVertexId, bone->mWeights[j].mWeight );
271 data.m_weights[meshName].push_back( weight );
273 data.m_bindMatrices[meshName] = assimpToCore( bone->mOffsetMatrix );
276 void AssimpHandleDataLoader::fillHandleData(
277 const std::string& node,
278 const std::vector<std::pair<std::string, std::string>>& edgeList,
279 const std::map<std::string, HandleComponentData>& mapBone2Data,
280 std::map<std::string, uint>& nameTable,
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 ) } );