37 using namespace StrUtils;
38 using namespace FileUtils;
49 case FbxNodeAttribute::eUnknown:
50 return "unidentified";
51 case FbxNodeAttribute::eNull:
53 case FbxNodeAttribute::eMarker:
55 case FbxNodeAttribute::eSkeleton:
57 case FbxNodeAttribute::eMesh:
59 case FbxNodeAttribute::eNurbs:
61 case FbxNodeAttribute::ePatch:
63 case FbxNodeAttribute::eCamera:
65 case FbxNodeAttribute::eCameraStereo:
67 case FbxNodeAttribute::eCameraSwitcher:
68 return "camera switcher";
69 case FbxNodeAttribute::eLight:
71 case FbxNodeAttribute::eOpticalReference:
72 return "optical reference";
73 case FbxNodeAttribute::eOpticalMarker:
75 case FbxNodeAttribute::eNurbsCurve:
77 case FbxNodeAttribute::eTrimNurbsSurface:
78 return "trim nurbs surface";
79 case FbxNodeAttribute::eBoundary:
81 case FbxNodeAttribute::eNurbsSurface:
82 return "nurbs surface";
83 case FbxNodeAttribute::eShape:
85 case FbxNodeAttribute::eLODGroup:
87 case FbxNodeAttribute::eSubDiv:
104 FbxString attrName = pAttribute->GetName();
109 << typeName.Buffer() <<
' ' << attrName.Buffer() << std::endl;
118 const auto nodeName = pNode->GetName();
119 FbxDouble3 translation = pNode->LclTranslation.Get();
120 FbxDouble3 rotation = pNode->LclRotation.Get();
121 FbxDouble3 scaling = pNode->LclScaling.Get();
124 std::cout << nodeName <<
' ' << translation[0] <<
' ' << translation[1] <<
' '
125 << translation[2] <<
' ' << rotation[0] <<
' ' << rotation[1] <<
' '
126 << rotation[2] <<
' ' << scaling[0] <<
' ' << scaling[1] <<
' '
130 for(
int i = 0; i < pNode->GetNodeAttributeCount(); ++i)
134 for(
int i = 0; i < pNode->GetChildCount(); ++i)
137 std::cout << std::endl;
146 FbxNode *root_node = scene.GetRootNode();
149 for(
int i = 0; i < root_node->GetChildCount(); ++i)
169 template<
typename coord_type,
170 typename coordN_type,
171 typename coordT_type,
172 typename coordC_type,
174 typename material_type >
177 std::vector< std::vector< coord_type > > &points_coords,
178 std::vector< std::vector< coordN_type > > &normals_coords,
179 std::vector< std::vector< coordT_type > > &texture_coords,
180 std::vector< std::vector< coordC_type > > & ,
181 std::vector< std::vector< index_type > > &face_indices,
182 std::vector< std::vector< index_type > > &texture_face_indices,
183 std::vector< std::vector< index_type > > &normal_face_indices,
184 std::vector< material_type > &materials,
187 FbxManager *manager = FbxManager::Create();
189 FbxIOSettings *ioSettings = FbxIOSettings::Create(manager, IOSROOT);
190 manager->SetIOSettings(ioSettings);
192 FbxImporter *importer = FbxImporter::Create(manager,
"");
194 if(!importer->Initialize(filePath.c_str(), -1, manager->GetIOSettings()))
195 throw std::invalid_argument(
196 {
"Reader::read_fbx_file -> Error: couldn't load the given FBX file.\n",
197 importer->GetStatus().GetErrorString()});
203 importer->Import(scene);
207 FbxAxisSystem::OpenGL.ConvertScene(scene);
214 for(
int meshIndex = 0; meshIndex < scene->GetGeometryCount(); ++meshIndex)
216 const auto mesh =
static_cast< FbxMesh *
>(scene->GetGeometry(meshIndex));
218 std::cout <<
"[FbxFileReader] --- Mesh no." << meshIndex
219 <<
"'s poly count: " << mesh->GetPolygonCount() << std::endl;
226 std::size_t currentVertIndex = points_coords.size();
227 points_coords.resize(currentVertIndex + mesh->GetControlPointsCount(),
228 std::vector< coord_type >(3));
230 for(
int vertIndex = 0; vertIndex < mesh->GetControlPointsCount();
231 ++vertIndex, ++currentVertIndex)
233 const auto &vertPos = mesh->GetControlPointAt(vertIndex);
235 points_coords[currentVertIndex][0] = vertPos[0];
236 points_coords[currentVertIndex][1] = vertPos[1];
237 points_coords[currentVertIndex][2] = vertPos[2];
241 const auto &meshNormals = mesh->GetElementNormal();
245 std::size_t currentNormIndex = normals_coords.size();
246 normals_coords.resize(currentNormIndex +
247 meshNormals->GetDirectArray().GetCount(),
248 std::vector< coordN_type >(3));
250 for(
int normIndex = 0;
251 normIndex < meshNormals->GetDirectArray().GetCount();
252 ++normIndex, ++currentNormIndex)
254 const auto &normal = meshNormals->GetDirectArray()[normIndex];
256 normals_coords[currentNormIndex][0] = normal[0];
257 normals_coords[currentNormIndex][1] = normal[1];
258 normals_coords[currentNormIndex][2] = normal[2];
263 const auto &meshTexcoords = mesh->GetElementUV();
267 std::size_t currentTexIndex = texture_coords.size();
268 texture_coords.resize(currentTexIndex +
269 meshTexcoords->GetDirectArray().GetCount(),
270 std::vector< coordT_type >(2));
272 for(
int texIndex = 0;
273 texIndex < meshTexcoords->GetDirectArray().GetCount();
274 ++texIndex, ++currentTexIndex)
276 const auto &texcoords = meshTexcoords->GetDirectArray()[texIndex];
278 texture_coords[currentTexIndex][0] =
static_cast<coordT_type
>(texcoords[0]);
279 texture_coords[currentTexIndex][1] =
static_cast<coordT_type
>(texcoords[1]);
294 const std::size_t basePosIndex =
295 points_coords.size() - mesh->GetControlPointsCount();
296 std::size_t currentPosPolyIndex = face_indices.size();
297 face_indices.resize(currentPosPolyIndex + mesh->GetPolygonCount());
299 for(
int polyIndex = 0; polyIndex < mesh->GetPolygonCount();
300 ++polyIndex, ++currentPosPolyIndex)
302 const auto polySize = mesh->GetPolygonSize(polyIndex);
303 face_indices[currentPosPolyIndex].resize(polySize);
305 for(
int polyVertIndex = 0; polyVertIndex < polySize; ++polyVertIndex)
306 face_indices[currentPosPolyIndex][polyVertIndex] =
307 basePosIndex + mesh->GetPolygonVertex(polyIndex, polyVertIndex);
313 if(meshTexcoords->GetMappingMode() ==
314 FbxLayerElement::EMappingMode::eByControlPoint)
317 <<
"[FbxFileReader] Mapping mesh's texcoords by control point."
320 texture_face_indices.resize(texture_face_indices.size() +
321 mesh->GetPolygonCount());
325 for(std::size_t faceIndex =
326 face_indices.size() - mesh->GetPolygonCount();
327 faceIndex < face_indices.size();
330 texture_face_indices[faceIndex].resize(
331 face_indices[faceIndex].size());
333 for(
size_t vertIndex = 0; vertIndex < face_indices[faceIndex].size();
336 index_type texIndex{};
338 if(meshTexcoords->GetReferenceMode() ==
339 FbxGeometryElement::eDirect)
341 texIndex = face_indices[faceIndex][vertIndex];
342 else if(meshTexcoords->GetReferenceMode() ==
343 FbxGeometryElement::eIndexToDirect)
345 texIndex = meshTexcoords->GetIndexArray().GetAt(
346 static_cast< int >(face_indices[faceIndex][vertIndex]));
348 texture_face_indices[faceIndex][vertIndex] = texIndex;
352 else if(meshTexcoords->GetMappingMode() ==
353 FbxLayerElement::EMappingMode::eByPolygonVertex)
356 <<
"[FbxFileReader] Mapping mesh's texcoords by face vertices."
359 const std::size_t baseTexIndex =
360 texture_coords.size() - meshTexcoords->GetDirectArray().GetCount();
361 std::size_t globalTexIndex = texture_face_indices.size();
362 texture_face_indices.resize(globalTexIndex + mesh->GetPolygonCount());
363 int currentTexPolyIndex = 0;
367 for(
int polyIndex = 0; polyIndex < mesh->GetPolygonCount();
368 ++polyIndex, ++globalTexIndex)
370 texture_face_indices[globalTexIndex].resize(
371 mesh->GetPolygonSize(polyIndex));
374 for(
int polyVertIndex = 0;
375 polyVertIndex < mesh->GetPolygonSize(polyIndex);
376 ++polyVertIndex, ++currentTexPolyIndex)
378 index_type texIndex{};
380 if(meshTexcoords->GetReferenceMode() == FbxGeometryElement::eDirect)
381 texIndex = currentTexPolyIndex;
382 else if(meshTexcoords->GetReferenceMode() ==
383 FbxGeometryElement::eIndexToDirect)
385 meshTexcoords->GetIndexArray().GetAt(currentTexPolyIndex);
387 texture_face_indices[globalTexIndex][polyVertIndex] =
388 baseTexIndex + texIndex;
395 <<
"[FbxFileReader] Couldn't handle mesh's texcoords' mapping mode."
402 if(meshNormals->GetMappingMode() ==
403 FbxLayerElement::EMappingMode::eByControlPoint)
405 std::cout <<
"[FbxFileReader] Mapping mesh's normals by control point."
408 normal_face_indices.resize(normal_face_indices.size() +
409 mesh->GetPolygonCount());
413 for(std::size_t faceIndex =
414 face_indices.size() - mesh->GetPolygonCount();
415 faceIndex < face_indices.size();
418 normal_face_indices[faceIndex].resize(face_indices[faceIndex].size());
420 for(
size_t vertIndex = 0; vertIndex < face_indices[faceIndex].size();
423 index_type normIndex{};
425 if(meshNormals->GetReferenceMode() ==
426 FbxGeometryElement::eDirect)
428 normIndex = face_indices[faceIndex][vertIndex];
429 else if(meshNormals->GetReferenceMode() ==
430 FbxGeometryElement::eIndexToDirect)
432 normIndex = meshNormals->GetIndexArray().GetAt(
433 static_cast< int >(face_indices[faceIndex][vertIndex]));
435 normal_face_indices[faceIndex][vertIndex] = normIndex;
439 else if(meshNormals->GetMappingMode() ==
440 FbxLayerElement::EMappingMode::eByPolygonVertex)
442 std::cout <<
"[FbxFileReader] Mapping mesh's normals by face vertices."
445 const std::size_t baseNormIndex =
446 normals_coords.size() - meshNormals->GetDirectArray().GetCount();
447 std::size_t globalNormIndex = normal_face_indices.size();
448 normal_face_indices.resize(globalNormIndex + mesh->GetPolygonCount());
449 int currentNormPolyIndex = 0;
453 for(
int polyIndex = 0; polyIndex < mesh->GetPolygonCount();
454 ++polyIndex, ++globalNormIndex)
456 normal_face_indices[globalNormIndex].resize(
457 mesh->GetPolygonSize(polyIndex));
460 for(
int polyVertIndex = 0;
461 polyVertIndex < mesh->GetPolygonSize(polyIndex);
462 ++polyVertIndex, ++currentNormPolyIndex)
464 index_type normIndex{};
466 if(meshNormals->GetReferenceMode() == FbxGeometryElement::eDirect)
467 normIndex = currentNormPolyIndex;
468 else if(meshNormals->GetReferenceMode() ==
469 FbxGeometryElement::eIndexToDirect)
471 meshNormals->GetIndexArray().GetAt(currentNormPolyIndex);
473 normal_face_indices[globalNormIndex][polyVertIndex] =
474 baseNormIndex + normIndex;
481 <<
"[FbxFileReader] Couldn't handle mesh's normals' mapping mode."
486 const auto &meshMaterial = mesh->GetElementMaterial();
489 if(meshMaterial->GetMappingMode() ==
490 FbxLayerElement::EMappingMode::eByPolygon)
494 for(
int polyIndex = 0; polyIndex < mesh->GetPolygonCount(); ++polyIndex)
495 face_material[polyIndex] = meshMaterial->GetIndexArray()[polyIndex];
497 else if(meshMaterial->GetMappingMode() ==
498 FbxLayerElement::EMappingMode::eAllSame)
502 face_material.resize(prevFaceMatSize + mesh->GetPolygonCount());
509 std::min(meshIndex, scene->GetMaterialCount() - 1));
515 materials.resize(scene->GetMaterialCount());
517 for(
int matIndex = 0; matIndex < scene->GetMaterialCount(); ++matIndex)
519 const FbxSurfaceMaterial *material = scene->GetMaterial(matIndex);
521 materials[matIndex].name = material->GetName();
525 const FbxPropertyT< FbxDouble3 > &ambient =
526 material->FindProperty(FbxSurfaceMaterial::sAmbient);
527 if(ambient.IsValid())
529 materials[matIndex].ambient_red_component = ambient.Get()[0];
530 materials[matIndex].ambient_green_component = ambient.Get()[1];
531 materials[matIndex].ambient_blue_component = ambient.Get()[2];
534 const FbxPropertyT< FbxDouble3 > &diffuse =
535 material->FindProperty(FbxSurfaceMaterial::sDiffuse);
536 if(diffuse.IsValid())
538 materials[matIndex].diffuse_red_component = diffuse.Get()[0];
539 materials[matIndex].diffuse_green_component = diffuse.Get()[1];
540 materials[matIndex].diffuse_blue_component = diffuse.Get()[2];
543 const FbxPropertyT< FbxDouble3 > &specular =
544 material->FindProperty(FbxSurfaceMaterial::sSpecular);
545 if(specular.IsValid())
547 materials[matIndex].specular_red_component = specular.Get()[0];
548 materials[matIndex].specular_green_component = specular.Get()[1];
549 materials[matIndex].specular_blue_component = specular.Get()[2];
552 const FbxPropertyT< FbxDouble3 > &emissive =
553 material->FindProperty(FbxSurfaceMaterial::sEmissive);
554 if(emissive.IsValid())
556 materials[matIndex].emissive_red_component = emissive.Get()[0];
557 materials[matIndex].emissive_green_component = emissive.Get()[1];
558 materials[matIndex].emissive_blue_component = emissive.Get()[2];
561 const FbxPropertyT< FbxDouble > &transparency =
562 material->FindProperty(FbxSurfaceMaterial::sTransparencyFactor);
563 if(transparency.IsValid())
564 materials[matIndex].transparency = transparency.Get();
569 const auto ambientTexture =
static_cast< FbxFileTexture *
>(
570 ambient.GetSrcObject(FbxCriteria::ObjectType(FbxFileTexture::ClassId)));
573 materials[matIndex].ambient_texture_filename =
574 ambientTexture->GetRelativeFileName();
575 materials[matIndex].ambient_texture_filename.insert(
576 0, parent_directory +
"/");
579 const auto diffuseTexture =
static_cast< FbxFileTexture *
>(
580 diffuse.GetSrcObject(FbxCriteria::ObjectType(FbxFileTexture::ClassId)));
583 materials[matIndex].diffuse_texture_filename =
584 diffuseTexture->GetRelativeFileName();
585 materials[matIndex].diffuse_texture_filename.insert(
586 0, parent_directory +
"/");
589 const auto specularTexture =
590 static_cast< FbxFileTexture *
>(specular.GetSrcObject(
591 FbxCriteria::ObjectType(FbxFileTexture::ClassId)));
594 materials[matIndex].specular_texture_filename =
595 specularTexture->GetRelativeFileName();
596 materials[matIndex].specular_texture_filename.insert(
597 0, parent_directory +
"/");
600 const auto emissiveTexture =
601 static_cast< FbxFileTexture *
>(emissive.GetSrcObject(
602 FbxCriteria::ObjectType(FbxFileTexture::ClassId)));
605 materials[matIndex].emissive_texture_filename =
606 emissiveTexture->GetRelativeFileName();
607 materials[matIndex].emissive_texture_filename.insert(
608 0, parent_directory +
"/");
611 const auto normalMapProp =
612 material->FindProperty(FbxSurfaceMaterial::sNormalMap);
613 if(normalMapProp.IsValid())
615 const auto normalMap =
616 static_cast< FbxFileTexture *
>(normalMapProp.GetSrcObject(
617 FbxCriteria::ObjectType(FbxFileTexture::ClassId)));
620 materials[matIndex].normal_map_filename =
621 normalMap->GetRelativeFileName();
622 materials[matIndex].normal_map_filename.insert(0,
623 parent_directory +
"/");
625 materials[matIndex].has_normal_map =
true;
637 #undef isnan // fix issue with std::isnan due to fbxmath.h