BsFBXImporter.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  1. #include "BsFBXImporter.h"
  2. #include "BsResource.h"
  3. #include "BsCoreApplication.h"
  4. #include "BsDebug.h"
  5. #include "BsDataStream.h"
  6. #include "BsMeshData.h"
  7. #include "BsMesh.h"
  8. #include "BsVector2.h"
  9. #include "BsVector3.h"
  10. #include "BsVector4.h"
  11. #include "BsQuaternion.h"
  12. #include "BsVertexDataDesc.h"
  13. #include "BsFBXUtility.h"
  14. #include <BsMeshImportOptions.h>
  15. namespace BansheeEngine
  16. {
  17. Vector4 FBXToNativeType(const FbxVector4& value)
  18. {
  19. Vector4 native;
  20. native.x = (float)value[0];
  21. native.y = (float)value[1];
  22. native.z = (float)value[2];
  23. native.w = (float)value[3];
  24. return native;
  25. }
  26. Vector3 FBXToNativeType(const FbxDouble3& value)
  27. {
  28. Vector3 native;
  29. native.x = (float)value[0];
  30. native.y = (float)value[1];
  31. native.z = (float)value[2];
  32. return native;
  33. }
  34. Vector2 FBXToNativeType(const FbxVector2& value)
  35. {
  36. Vector2 native;
  37. native.x = (float)value[0];
  38. native.y = (float)value[1];
  39. return native;
  40. }
  41. RGBA FBXToNativeType(const FbxColor& value)
  42. {
  43. Color native;
  44. native.r = (float)value[0];
  45. native.g = (float)value[1];
  46. native.b = (float)value[2];
  47. native.a = (float)value[3];
  48. return native.getAsRGBA();
  49. }
  50. FbxSurfaceMaterial* FBXToNativeType(FbxSurfaceMaterial* const& value)
  51. {
  52. return value;
  53. }
  54. int FBXToNativeType(const int & value)
  55. {
  56. return value;
  57. }
  58. FBXImporter::FBXImporter()
  59. :SpecificImporter(), mFBXManager(nullptr)
  60. {
  61. mExtensions.push_back(L"fbx");
  62. }
  63. FBXImporter::~FBXImporter()
  64. {
  65. }
  66. bool FBXImporter::isExtensionSupported(const WString& ext) const
  67. {
  68. WString lowerCaseExt = ext;
  69. StringUtil::toLowerCase(lowerCaseExt);
  70. return find(mExtensions.begin(), mExtensions.end(), lowerCaseExt) != mExtensions.end();
  71. }
  72. bool FBXImporter::isMagicNumberSupported(const UINT8* magicNumPtr, UINT32 numBytes) const
  73. {
  74. return true; // FBX files can be plain-text so I don't even check for magic number
  75. }
  76. ImportOptionsPtr FBXImporter::createImportOptions() const
  77. {
  78. return bs_shared_ptr<MeshImportOptions, PoolAlloc>();
  79. }
  80. ResourcePtr FBXImporter::import(const Path& filePath, ConstImportOptionsPtr importOptions)
  81. {
  82. FbxScene* fbxScene = nullptr;
  83. if (!startUpSdk(fbxScene))
  84. return nullptr;
  85. if (!loadFBXFile(fbxScene, filePath))
  86. return nullptr;
  87. const MeshImportOptions* meshImportOptions = static_cast<const MeshImportOptions*>(importOptions.get());
  88. FBXImportOptions fbxImportOptions;
  89. fbxImportOptions.importNormals = meshImportOptions->getImportNormals();
  90. fbxImportOptions.importTangents = meshImportOptions->getImportTangents();
  91. fbxImportOptions.importAnimation = meshImportOptions->getImportAnimation();
  92. fbxImportOptions.importBlendShapes = meshImportOptions->getImportBlendShapes();
  93. fbxImportOptions.importSkin = meshImportOptions->getImportSkin();
  94. fbxImportOptions.importScale = meshImportOptions->getImportScale();
  95. FBXImportScene importedScene;
  96. parseScene(fbxScene, fbxImportOptions, importedScene);
  97. splitMeshVertices(importedScene);
  98. Vector<SubMesh> subMeshes;
  99. MeshDataPtr meshData = generateMeshData(importedScene, fbxImportOptions, subMeshes);
  100. // TODO - Later: Optimize mesh: Remove bad and degenerate polygons, optimize for vertex cache
  101. shutDownSdk();
  102. INT32 usage = MU_STATIC;
  103. if (meshImportOptions->getCPUReadable())
  104. usage |= MU_CPUCACHED;
  105. MeshPtr mesh = Mesh::_createPtr(meshData, subMeshes, usage);
  106. WString fileName = filePath.getWFilename(false);
  107. mesh->setName(fileName);
  108. return mesh;
  109. }
  110. bool FBXImporter::startUpSdk(FbxScene*& scene)
  111. {
  112. mFBXManager = FbxManager::Create();
  113. if (mFBXManager == nullptr)
  114. {
  115. LOGERR("FBX import failed: FBX SDK failed to initialize. FbxManager::Create() failed.");
  116. return false;
  117. }
  118. FbxIOSettings* ios = FbxIOSettings::Create(mFBXManager, IOSROOT);
  119. mFBXManager->SetIOSettings(ios);
  120. scene = FbxScene::Create(mFBXManager, "Import Scene");
  121. if (scene == nullptr)
  122. {
  123. LOGWRN("FBX import failed: Failed to create FBX scene.");
  124. return false;
  125. }
  126. return true;
  127. }
  128. void FBXImporter::shutDownSdk()
  129. {
  130. mFBXManager->Destroy();
  131. mFBXManager = nullptr;
  132. }
  133. bool FBXImporter::loadFBXFile(FbxScene* scene, const Path& filePath)
  134. {
  135. int lFileMajor, lFileMinor, lFileRevision;
  136. int lSDKMajor, lSDKMinor, lSDKRevision;
  137. FbxManager::GetFileFormatVersion(lSDKMajor, lSDKMinor, lSDKRevision);
  138. FbxImporter* importer = FbxImporter::Create(mFBXManager, "");
  139. bool importStatus = importer->Initialize(filePath.toString().c_str(), -1, mFBXManager->GetIOSettings());
  140. importer->GetFileVersion(lFileMajor, lFileMinor, lFileRevision);
  141. if(!importStatus)
  142. {
  143. LOGERR("FBX import failed: Call to FbxImporter::Initialize() failed.\n" +
  144. String("Error returned: %s\n\n") + String(importer->GetStatus().GetErrorString()));
  145. return false;
  146. }
  147. mFBXManager->GetIOSettings()->SetBoolProp(IMP_FBX_TEXTURE, false);
  148. mFBXManager->GetIOSettings()->SetBoolProp(IMP_FBX_GOBO, false);
  149. importStatus = importer->Import(scene);
  150. if(!importStatus)
  151. {
  152. importer->Destroy();
  153. LOGERR("FBX import failed: Call to FbxImporter::Initialize() failed.\n" +
  154. String("Error returned: %s\n\n") + String(importer->GetStatus().GetErrorString()));
  155. return false;
  156. }
  157. FbxAxisSystem fileCoordSystem = scene->GetGlobalSettings().GetAxisSystem();
  158. FbxAxisSystem bsCoordSystem(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eRightHanded);
  159. if (fileCoordSystem != bsCoordSystem)
  160. bsCoordSystem.ConvertScene(scene);
  161. importer->Destroy();
  162. return true;
  163. }
  164. void FBXImporter::parseScene(FbxScene* scene, const FBXImportOptions& options, FBXImportScene& outputScene)
  165. {
  166. outputScene.rootNode = createImportNode(outputScene, scene->GetRootNode(), nullptr);
  167. Stack<FbxNode*> todo;
  168. todo.push(scene->GetRootNode());
  169. while(!todo.empty())
  170. {
  171. FbxNode* curNode = todo.top();
  172. FBXImportNode* curImportNode = outputScene.nodeMap[curNode];
  173. todo.pop();
  174. const char* name = curNode->GetName();
  175. FbxNodeAttribute* attrib = curNode->GetNodeAttribute();
  176. if(attrib != nullptr)
  177. {
  178. FbxNodeAttribute::EType attribType = attrib->GetAttributeType();
  179. switch(attribType)
  180. {
  181. case FbxNodeAttribute::eNurbs:
  182. case FbxNodeAttribute::eNurbsSurface:
  183. case FbxNodeAttribute::ePatch:
  184. {
  185. FbxGeometryConverter geomConverter(mFBXManager);
  186. attrib = geomConverter.Triangulate(attrib, true);
  187. if (attrib->GetAttributeType() == FbxNodeAttribute::eMesh)
  188. {
  189. FbxMesh* mesh = static_cast<FbxMesh*>(attrib);
  190. mesh->RemoveBadPolygons();
  191. parseMesh(mesh, curImportNode, options, outputScene);
  192. }
  193. }
  194. break;
  195. case FbxNodeAttribute::eMesh:
  196. {
  197. FbxMesh* mesh = static_cast<FbxMesh*>(attrib);
  198. mesh->RemoveBadPolygons();
  199. if(!mesh->IsTriangleMesh())
  200. {
  201. FbxGeometryConverter geomConverter(mFBXManager);
  202. geomConverter.Triangulate(mesh, true);
  203. attrib = curNode->GetNodeAttribute();
  204. mesh = static_cast<FbxMesh*>(attrib);
  205. }
  206. parseMesh(mesh, curImportNode, options, outputScene);
  207. }
  208. break;
  209. }
  210. }
  211. for (int i = 0; i < curNode->GetChildCount(); i++)
  212. {
  213. FbxNode* childNode = curNode->GetChild(i);
  214. createImportNode(outputScene, childNode, curImportNode);
  215. todo.push(childNode);
  216. }
  217. }
  218. // TODO - Parse skin
  219. // TODO - Parse animation
  220. // TODO - Parse blend shapes
  221. }
  222. FBXImportNode* FBXImporter::createImportNode(FBXImportScene& scene, FbxNode* fbxNode, FBXImportNode* parent)
  223. {
  224. FBXImportNode* node = bs_new<FBXImportNode>();
  225. Vector3 translation = FBXToNativeType(fbxNode->LclTranslation.Get());
  226. Vector3 rotationEuler = FBXToNativeType(fbxNode->LclRotation.Get());
  227. Vector3 scale = FBXToNativeType(fbxNode->LclScaling.Get());
  228. Quaternion rotation((Radian)rotationEuler.x, (Radian)rotationEuler.y, (Radian)rotationEuler.z);
  229. node->localTransform.setTRS(translation, rotation, scale);
  230. if (parent != nullptr)
  231. {
  232. node->worldTransform = node->localTransform * parent->worldTransform;
  233. parent->children.push_back(node);
  234. }
  235. else
  236. node->worldTransform = node->localTransform;
  237. scene.nodeMap.insert(std::make_pair(fbxNode, node));
  238. return node;
  239. }
  240. void FBXImporter::splitMeshVertices(FBXImportScene& scene)
  241. {
  242. Vector<FBXImportMesh*> splitMeshes;
  243. for (auto& mesh : scene.meshes)
  244. {
  245. FBXImportMesh* splitMesh = bs_new<FBXImportMesh>();
  246. FBXUtility::splitVertices(*mesh, *splitMesh);
  247. FBXUtility::flipWindingOrder(*splitMesh);
  248. splitMeshes.push_back(splitMesh);
  249. bs_delete(mesh);
  250. }
  251. scene.meshes = splitMeshes;
  252. }
  253. MeshDataPtr FBXImporter::generateMeshData(const FBXImportScene& scene, const FBXImportOptions& options, Vector<SubMesh>& outputSubMeshes)
  254. {
  255. Matrix4 importScale = Matrix4::scaling(options.importScale);
  256. Vector<MeshDataPtr> allMeshData;
  257. Vector<Vector<SubMesh>> allSubMeshes;
  258. for (auto& mesh : scene.meshes)
  259. {
  260. Vector<Vector<UINT32>> indicesPerMaterial;
  261. for (UINT32 i = 0; i < (UINT32)mesh->indices.size(); i++)
  262. {
  263. while (mesh->materials[i] >= indicesPerMaterial.size())
  264. indicesPerMaterial.push_back(Vector<UINT32>());
  265. indicesPerMaterial[mesh->materials[i]].push_back(mesh->indices[i]);
  266. }
  267. UINT32* orderedIndices = (UINT32*)bs_alloc((UINT32)mesh->indices.size() * sizeof(UINT32));
  268. Vector<SubMesh> subMeshes;
  269. UINT32 currentIndex = 0;
  270. for (auto& subMeshIndices : indicesPerMaterial)
  271. {
  272. UINT32 indexCount = (UINT32)subMeshIndices.size();
  273. UINT32* dest = orderedIndices + currentIndex;
  274. memcpy(dest, subMeshIndices.data(), indexCount * sizeof(UINT32));
  275. subMeshes.push_back(SubMesh(currentIndex, indexCount, DOT_TRIANGLE_LIST));
  276. currentIndex += indexCount;
  277. }
  278. VertexDataDescPtr vertexDesc = bs_shared_ptr<VertexDataDesc>();
  279. vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
  280. size_t numVertices = mesh->positions.size();
  281. bool hasColors = mesh->colors.size() == numVertices;
  282. bool hasNormals = mesh->normals.size() == numVertices;
  283. if (hasColors)
  284. vertexDesc->addVertElem(VET_COLOR, VES_COLOR);
  285. bool hasTangents = false;
  286. if (hasNormals)
  287. {
  288. vertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
  289. if (mesh->tangents.size() == numVertices &&
  290. mesh->bitangents.size() == numVertices)
  291. {
  292. vertexDesc->addVertElem(VET_FLOAT4, VES_TANGENT);
  293. hasTangents = true;
  294. }
  295. }
  296. int UVIdx = 0;
  297. for (UINT32 i = 0; i < FBX_IMPORT_MAX_UV_LAYERS; i++)
  298. {
  299. if (mesh->UV[i].size() == numVertices)
  300. {
  301. vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD, UVIdx++);
  302. }
  303. }
  304. UINT32 numIndices = (UINT32)mesh->indices.size();
  305. for (auto& node : mesh->referencedBy)
  306. {
  307. Matrix4 worldTransform = node->worldTransform * importScale;
  308. Matrix4 worldTransformIT = worldTransform.transpose();
  309. worldTransformIT = worldTransformIT.inverse();
  310. MeshDataPtr meshData = bs_shared_ptr<MeshData>((UINT32)numVertices, numIndices, vertexDesc);
  311. // Copy indices
  312. UINT32* indices = meshData->getIndices32();
  313. memcpy(indices, mesh->indices.data(), numIndices * sizeof(UINT32));
  314. // Copy & transform positions
  315. auto posIter = meshData->getVec3DataIter(VES_POSITION, 0);
  316. for (auto& position : mesh->positions)
  317. {
  318. Vector3 tfrmdValue = worldTransform.multiplyAffine((Vector3)position);
  319. posIter.addValue(tfrmdValue);
  320. }
  321. // Copy & transform normals
  322. if (hasNormals)
  323. {
  324. auto normalIter = meshData->getVec3DataIter(VES_NORMAL, 0);
  325. // Copy, convert & transform tangents & bitangents
  326. if (hasTangents)
  327. {
  328. auto tangentIter = meshData->getVec4DataIter(VES_TANGENT, 0);
  329. for (UINT32 i = 0; i < (UINT32)numVertices; i++)
  330. {
  331. Vector3 normal = (Vector3)mesh->normals[i];
  332. normal = worldTransformIT.multiplyAffine(normal);
  333. normalIter.addValue(normal);
  334. Vector3 tangent = (Vector3)mesh->tangents[i];
  335. tangent = worldTransformIT.multiplyAffine(tangent);
  336. Vector3 bitangent = (Vector3)mesh->bitangents[i];
  337. bitangent = worldTransformIT.multiplyAffine(bitangent);
  338. Vector3 engineBitangent = Vector3::cross(normal, tangent);
  339. float sign = Vector3::dot(engineBitangent, bitangent);
  340. Vector4 combinedTangent(tangent.x, tangent.y, tangent.z, sign > 0 ? 1.0f : -1.0f);
  341. tangentIter.addValue(combinedTangent);
  342. }
  343. }
  344. else // Just normals
  345. {
  346. for (auto& normal : mesh->normals)
  347. {
  348. Vector3 tfrmdValue = worldTransformIT.multiplyAffine((Vector3)normal);
  349. normalIter.addValue(tfrmdValue);
  350. }
  351. }
  352. }
  353. // Copy colors
  354. if (hasColors)
  355. {
  356. auto colorIter = meshData->getDWORDDataIter(VES_COLOR, 0);
  357. for (auto& color : mesh->colors)
  358. colorIter.addValue(color);
  359. }
  360. // Copy UV
  361. int writeUVIDx = 0;
  362. for (auto& uvLayer : mesh->UV)
  363. {
  364. if (uvLayer.size() == numVertices)
  365. {
  366. auto uvIter = meshData->getVec2DataIter(VES_TEXCOORD, writeUVIDx);
  367. for (auto& uv : uvLayer)
  368. {
  369. uv.y = 1.0f - uv.y;
  370. uvIter.addValue(uv);
  371. }
  372. writeUVIDx++;
  373. }
  374. }
  375. allMeshData.push_back(meshData);
  376. allSubMeshes.push_back(subMeshes);
  377. }
  378. }
  379. if (allMeshData.size() > 1)
  380. {
  381. return MeshData::combine(allMeshData, allSubMeshes, outputSubMeshes);
  382. }
  383. else if (allMeshData.size() == 1)
  384. {
  385. outputSubMeshes = allSubMeshes[0];
  386. return allMeshData[0];
  387. }
  388. return nullptr;
  389. }
  390. template<class TFBX, class TNative>
  391. class FBXDirectIndexer
  392. {
  393. public:
  394. FBXDirectIndexer(const FbxLayerElementTemplate<TFBX>& layer)
  395. :mElementArray(layer.GetDirectArray()),
  396. mElementCount(mElementArray.GetCount())
  397. {}
  398. bool get(int index, TNative& output) const
  399. {
  400. if (index < 0 || index >= mElementCount)
  401. return false;
  402. output = FBXToNativeType(mElementArray.GetAt(index));
  403. return true;
  404. }
  405. bool isEmpty() const
  406. {
  407. return mElementCount == 0;
  408. }
  409. private:
  410. const FbxLayerElementArrayTemplate<TFBX>& mElementArray;
  411. int mElementCount;
  412. };
  413. template<class TFBX, class TNative>
  414. class FBXIndexIndexer
  415. {
  416. public:
  417. FBXIndexIndexer(const FbxLayerElementTemplate<TFBX>& layer)
  418. :mElementArray(layer.GetDirectArray()),
  419. mIndexArray(layer.GetIndexArray()),
  420. mElementCount(mElementArray.GetCount()),
  421. mIndexCount(mIndexArray.GetCount())
  422. {}
  423. bool get(int index, TNative& output) const
  424. {
  425. if (index < 0 || index >= mIndexCount)
  426. return false;
  427. int actualIndex = mIndexArray.GetAt(index);
  428. if (actualIndex < 0 || actualIndex >= mElementCount)
  429. return false;
  430. output = FBXToNativeType(mElementArray.GetAt(actualIndex));
  431. return true;
  432. }
  433. bool isEmpty() const
  434. {
  435. return mElementCount == 0 || mIndexCount == 0;
  436. }
  437. private:
  438. const FbxLayerElementArrayTemplate<TFBX>& mElementArray;
  439. const FbxLayerElementArrayTemplate<int>& mIndexArray;
  440. int mElementCount;
  441. int mIndexCount;
  442. };
  443. template<class TFBX, class TNative, class TIndexer>
  444. void readLayerData(FbxLayerElementTemplate<TFBX>& layer, Vector<TNative>& output, const Vector<int>& indices)
  445. {
  446. TIndexer indexer(layer);
  447. if (indexer.isEmpty())
  448. return;
  449. output.resize(indices.size());
  450. FbxLayerElement::EMappingMode mappingMode = layer.GetMappingMode();
  451. UINT32 indexCount = (UINT32)indices.size();
  452. switch (mappingMode)
  453. {
  454. case FbxLayerElement::eByControlPoint:
  455. for (UINT32 i = 0; i < indexCount; i++)
  456. {
  457. int index = indices[i];
  458. indexer.get(index, output[i]);
  459. }
  460. break;
  461. case FbxLayerElement::eByPolygonVertex:
  462. for (UINT32 i = 0; i < indexCount; i++)
  463. indexer.get(i, output[i]);
  464. break;
  465. case FbxLayerElement::eByPolygon:
  466. // We expect mesh to be triangulated here
  467. {
  468. UINT32 polygonCount = indexCount / 3;
  469. UINT32 index = 0;
  470. for (UINT32 i = 0; i < polygonCount; i++)
  471. {
  472. TNative value;
  473. indexer.get(i, value);
  474. output[index++] = value;
  475. output[index++] = value;
  476. output[index++] = value;
  477. }
  478. }
  479. break;
  480. case FbxLayerElement::eAllSame:
  481. {
  482. TNative value;
  483. indexer.get(0, value);
  484. for (UINT32 i = 0; i < indexCount; i++)
  485. output[i] = value;
  486. }
  487. break;
  488. default:
  489. LOGWRN("FBX Import: Unsupported layer mapping mode.");
  490. break;
  491. }
  492. }
  493. template<class TFBX, class TNative>
  494. void readLayerData(FbxLayerElementTemplate<TFBX>& layer, Vector<TNative>& output, const Vector<int>& indices)
  495. {
  496. FbxLayerElement::EReferenceMode refMode = layer.GetReferenceMode();
  497. if (refMode == FbxLayerElement::eDirect)
  498. readLayerData<TFBX, TNative, FBXDirectIndexer<TFBX, TNative> >(layer, output, indices);
  499. else if (refMode == FbxLayerElement::eIndexToDirect)
  500. readLayerData<TFBX, TNative, FBXIndexIndexer<TFBX, TNative> >(layer, output, indices);
  501. else
  502. LOGWRN("FBX Import: Unsupported layer reference mode.");
  503. }
  504. void FBXImporter::parseMesh(FbxMesh* mesh, FBXImportNode* parentNode, const FBXImportOptions& options, FBXImportScene& outputScene)
  505. {
  506. // Check if valid
  507. if (!mesh->IsTriangleMesh())
  508. return;
  509. UINT32 vertexCount = mesh->GetControlPointsCount();
  510. UINT32 triangleCount = mesh->GetPolygonCount();
  511. if (vertexCount == 0 || triangleCount == 0)
  512. return;
  513. // Register in global mesh array
  514. FBXImportMesh* importMesh = nullptr;
  515. auto iterFindMesh = outputScene.meshMap.find(mesh);
  516. if (iterFindMesh != outputScene.meshMap.end())
  517. {
  518. UINT32 meshIdx = iterFindMesh->second;
  519. outputScene.meshes[meshIdx]->referencedBy.push_back(parentNode);
  520. return;
  521. }
  522. else
  523. {
  524. importMesh = bs_new<FBXImportMesh>();
  525. outputScene.meshes.push_back(importMesh);
  526. importMesh->referencedBy.push_back(parentNode);
  527. outputScene.meshMap[mesh] = (UINT32)outputScene.meshes.size() - 1;
  528. }
  529. // Import vertices
  530. importMesh->positions.resize(vertexCount);
  531. FbxVector4* controlPoints = mesh->GetControlPoints();
  532. for (UINT32 i = 0; i < vertexCount; i++)
  533. importMesh->positions[i] = FBXToNativeType(controlPoints[i]);
  534. // Import triangles
  535. UINT32 indexCount = triangleCount * 3;
  536. importMesh->indices.resize(indexCount);
  537. int* fbxIndices = mesh->GetPolygonVertices();
  538. importMesh->indices.assign(fbxIndices, fbxIndices + indexCount);
  539. // Import UVs
  540. Vector<FbxLayerElementUV*> fbxUVLayers;
  541. //// Search the diffuse layers first
  542. for (UINT32 i = 0; i < FBX_IMPORT_MAX_UV_LAYERS; i++)
  543. {
  544. FbxLayer* layer = mesh->GetLayer(i, FbxLayerElement::eUV);
  545. if (layer == nullptr)
  546. continue;
  547. for (int j = FbxLayerElement::eTextureDiffuse; j < FbxLayerElement::eTypeCount; j++)
  548. {
  549. FbxLayerElementUV* uvLayer = layer->GetUVs((FbxLayerElement::EType)j);
  550. if (uvLayer == nullptr)
  551. continue;
  552. fbxUVLayers.push_back(uvLayer);
  553. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  554. break;
  555. }
  556. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  557. break;
  558. }
  559. //// If there's room, search all others too
  560. if (fbxUVLayers.size() < FBX_IMPORT_MAX_UV_LAYERS)
  561. {
  562. UINT32 numLayers = mesh->GetLayerCount();
  563. for (UINT32 i = 0; i < numLayers; i++)
  564. {
  565. FbxLayer* layer = mesh->GetLayer(i);
  566. if (layer == nullptr)
  567. continue;
  568. for (int j = FbxLayerElement::eTextureDiffuse; j < FbxLayerElement::eTypeCount; j++)
  569. {
  570. FbxLayerElementUV* uvLayer = layer->GetUVs((FbxLayerElement::EType)j);
  571. if (uvLayer == nullptr)
  572. continue;
  573. auto iterFind = std::find(fbxUVLayers.begin(), fbxUVLayers.end(), uvLayer);
  574. if (iterFind != fbxUVLayers.end())
  575. continue;
  576. fbxUVLayers.push_back(uvLayer);
  577. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  578. break;
  579. }
  580. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  581. break;
  582. }
  583. }
  584. for (size_t i = 0; i < fbxUVLayers.size(); i++)
  585. readLayerData(*fbxUVLayers[i], importMesh->UV[i], importMesh->indices);
  586. FbxLayer* mainLayer = mesh->GetLayer(0);
  587. if (mainLayer != nullptr)
  588. {
  589. // Import colors
  590. if (mainLayer->GetVertexColors() != nullptr)
  591. readLayerData(*mainLayer->GetVertexColors(), importMesh->colors, importMesh->indices);
  592. // Import normals
  593. if (options.importNormals)
  594. {
  595. bool hasNormals = mainLayer->GetNormals() != nullptr;
  596. if (!hasNormals)
  597. {
  598. if (mainLayer->GetSmoothing() != nullptr)
  599. {
  600. FbxLayerElementSmoothing* smoothing = mainLayer->GetSmoothing();
  601. if (smoothing->GetMappingMode() == FbxLayerElement::eByEdge)
  602. {
  603. FbxGeometryConverter converter(mFBXManager);
  604. converter.ComputePolygonSmoothingFromEdgeSmoothing(mesh, 0);
  605. }
  606. Vector<int> smoothingGroups;
  607. readLayerData(*smoothing, smoothingGroups, importMesh->indices);
  608. if (!smoothingGroups.empty())
  609. {
  610. FBXUtility::normalsFromSmoothing(importMesh->positions, importMesh->indices, smoothingGroups, importMesh->normals);
  611. hasNormals = true;
  612. }
  613. }
  614. }
  615. if (hasNormals)
  616. readLayerData(*mainLayer->GetNormals(), importMesh->normals, importMesh->indices);
  617. }
  618. // Import tangents
  619. if (options.importTangents)
  620. {
  621. bool hasTangents = mainLayer->GetTangents() != nullptr && mainLayer->GetBinormals() != nullptr;
  622. if (!hasTangents)
  623. {
  624. if (fbxUVLayers.size() > 0)
  625. hasTangents = mesh->GenerateTangentsData(0, false);
  626. }
  627. if (hasTangents)
  628. {
  629. readLayerData(*mainLayer->GetTangents(), importMesh->tangents, importMesh->indices);
  630. readLayerData(*mainLayer->GetBinormals(), importMesh->bitangents, importMesh->indices);
  631. }
  632. }
  633. // Import material indexes
  634. if (mainLayer->GetMaterials() != nullptr)
  635. {
  636. Vector<FbxSurfaceMaterial*> fbxMaterials;
  637. readLayerData(*mainLayer->GetMaterials(), fbxMaterials, importMesh->indices);
  638. UnorderedMap<FbxSurfaceMaterial*, int> materialLookup;
  639. int nextMaterialIdx = 0;
  640. for (UINT32 i = 0; i < (UINT32)fbxMaterials.size(); i++)
  641. {
  642. auto iterFind = materialLookup.find(fbxMaterials[i]);
  643. int materialIdx = 0;
  644. if (iterFind != materialLookup.end())
  645. materialIdx = iterFind->second;
  646. else
  647. {
  648. materialIdx = nextMaterialIdx++;
  649. materialLookup[fbxMaterials[i]] = materialIdx;
  650. }
  651. importMesh->materials.push_back(materialIdx);
  652. }
  653. }
  654. }
  655. }
  656. }