BsFBXImporter.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311
  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. Matrix4 FBXToNativeType(const FbxAMatrix& value)
  18. {
  19. Matrix4 native;
  20. for (UINT32 row = 0; row < 4; row++)
  21. for (UINT32 col = 0; col < 4; col++)
  22. native[row][col] = (float)value[col][row];
  23. return native;
  24. }
  25. Vector4 FBXToNativeType(const FbxVector4& value)
  26. {
  27. Vector4 native;
  28. native.x = (float)value[0];
  29. native.y = (float)value[1];
  30. native.z = (float)value[2];
  31. native.w = (float)value[3];
  32. return native;
  33. }
  34. Vector3 FBXToNativeType(const FbxDouble3& value)
  35. {
  36. Vector3 native;
  37. native.x = (float)value[0];
  38. native.y = (float)value[1];
  39. native.z = (float)value[2];
  40. return native;
  41. }
  42. Vector2 FBXToNativeType(const FbxVector2& value)
  43. {
  44. Vector2 native;
  45. native.x = (float)value[0];
  46. native.y = (float)value[1];
  47. return native;
  48. }
  49. RGBA FBXToNativeType(const FbxColor& value)
  50. {
  51. Color native;
  52. native.r = (float)value[0];
  53. native.g = (float)value[1];
  54. native.b = (float)value[2];
  55. native.a = (float)value[3];
  56. return native.getAsRGBA();
  57. }
  58. FbxSurfaceMaterial* FBXToNativeType(FbxSurfaceMaterial* const& value)
  59. {
  60. return value;
  61. }
  62. int FBXToNativeType(const int & value)
  63. {
  64. return value;
  65. }
  66. FBXImporter::FBXImporter()
  67. :SpecificImporter(), mFBXManager(nullptr)
  68. {
  69. mExtensions.push_back(L"fbx");
  70. }
  71. FBXImporter::~FBXImporter()
  72. {
  73. }
  74. bool FBXImporter::isExtensionSupported(const WString& ext) const
  75. {
  76. WString lowerCaseExt = ext;
  77. StringUtil::toLowerCase(lowerCaseExt);
  78. return find(mExtensions.begin(), mExtensions.end(), lowerCaseExt) != mExtensions.end();
  79. }
  80. bool FBXImporter::isMagicNumberSupported(const UINT8* magicNumPtr, UINT32 numBytes) const
  81. {
  82. return true; // FBX files can be plain-text so I don't even check for magic number
  83. }
  84. ImportOptionsPtr FBXImporter::createImportOptions() const
  85. {
  86. return bs_shared_ptr<MeshImportOptions, PoolAlloc>();
  87. }
  88. ResourcePtr FBXImporter::import(const Path& filePath, ConstImportOptionsPtr importOptions)
  89. {
  90. FbxScene* fbxScene = nullptr;
  91. if (!startUpSdk(fbxScene))
  92. return nullptr;
  93. if (!loadFBXFile(fbxScene, filePath))
  94. return nullptr;
  95. const MeshImportOptions* meshImportOptions = static_cast<const MeshImportOptions*>(importOptions.get());
  96. FBXImportOptions fbxImportOptions;
  97. fbxImportOptions.importNormals = meshImportOptions->getImportNormals();
  98. fbxImportOptions.importTangents = meshImportOptions->getImportTangents();
  99. fbxImportOptions.importAnimation = meshImportOptions->getImportAnimation();
  100. fbxImportOptions.importBlendShapes = meshImportOptions->getImportBlendShapes();
  101. fbxImportOptions.importSkin = meshImportOptions->getImportSkin();
  102. fbxImportOptions.importScale = meshImportOptions->getImportScale();
  103. FBXImportScene importedScene;
  104. parseScene(fbxScene, fbxImportOptions, importedScene);
  105. if (fbxImportOptions.importBlendShapes)
  106. importBlendShapes(importedScene, fbxImportOptions);
  107. if (fbxImportOptions.importSkin)
  108. importSkin(importedScene);
  109. if (fbxImportOptions.importAnimation)
  110. importAnimations(fbxScene, fbxImportOptions, importedScene);
  111. splitMeshVertices(importedScene);
  112. Vector<SubMesh> subMeshes;
  113. MeshDataPtr meshData = generateMeshData(importedScene, fbxImportOptions, subMeshes);
  114. // TODO - Later: Optimize mesh: Remove bad and degenerate polygons, optimize for vertex cache
  115. shutDownSdk();
  116. INT32 usage = MU_STATIC;
  117. if (meshImportOptions->getCPUReadable())
  118. usage |= MU_CPUCACHED;
  119. MeshPtr mesh = Mesh::_createPtr(meshData, subMeshes, usage);
  120. WString fileName = filePath.getWFilename(false);
  121. mesh->setName(fileName);
  122. return mesh;
  123. }
  124. bool FBXImporter::startUpSdk(FbxScene*& scene)
  125. {
  126. mFBXManager = FbxManager::Create();
  127. if (mFBXManager == nullptr)
  128. {
  129. LOGERR("FBX import failed: FBX SDK failed to initialize. FbxManager::Create() failed.");
  130. return false;
  131. }
  132. FbxIOSettings* ios = FbxIOSettings::Create(mFBXManager, IOSROOT);
  133. mFBXManager->SetIOSettings(ios);
  134. scene = FbxScene::Create(mFBXManager, "Import Scene");
  135. if (scene == nullptr)
  136. {
  137. LOGWRN("FBX import failed: Failed to create FBX scene.");
  138. return false;
  139. }
  140. return true;
  141. }
  142. void FBXImporter::shutDownSdk()
  143. {
  144. mFBXManager->Destroy();
  145. mFBXManager = nullptr;
  146. }
  147. bool FBXImporter::loadFBXFile(FbxScene* scene, const Path& filePath)
  148. {
  149. int lFileMajor, lFileMinor, lFileRevision;
  150. int lSDKMajor, lSDKMinor, lSDKRevision;
  151. FbxManager::GetFileFormatVersion(lSDKMajor, lSDKMinor, lSDKRevision);
  152. FbxImporter* importer = FbxImporter::Create(mFBXManager, "");
  153. bool importStatus = importer->Initialize(filePath.toString().c_str(), -1, mFBXManager->GetIOSettings());
  154. importer->GetFileVersion(lFileMajor, lFileMinor, lFileRevision);
  155. if(!importStatus)
  156. {
  157. LOGERR("FBX import failed: Call to FbxImporter::Initialize() failed.\n" +
  158. String("Error returned: %s\n\n") + String(importer->GetStatus().GetErrorString()));
  159. return false;
  160. }
  161. mFBXManager->GetIOSettings()->SetBoolProp(IMP_FBX_TEXTURE, false);
  162. mFBXManager->GetIOSettings()->SetBoolProp(IMP_FBX_GOBO, false);
  163. importStatus = importer->Import(scene);
  164. if(!importStatus)
  165. {
  166. importer->Destroy();
  167. LOGERR("FBX import failed: Call to FbxImporter::Initialize() failed.\n" +
  168. String("Error returned: %s\n\n") + String(importer->GetStatus().GetErrorString()));
  169. return false;
  170. }
  171. FbxAxisSystem fileCoordSystem = scene->GetGlobalSettings().GetAxisSystem();
  172. FbxAxisSystem bsCoordSystem(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eRightHanded);
  173. if (fileCoordSystem != bsCoordSystem)
  174. bsCoordSystem.ConvertScene(scene);
  175. importer->Destroy();
  176. return true;
  177. }
  178. void FBXImporter::parseScene(FbxScene* scene, const FBXImportOptions& options, FBXImportScene& outputScene)
  179. {
  180. outputScene.rootNode = createImportNode(outputScene, scene->GetRootNode(), nullptr);
  181. Stack<FbxNode*> todo;
  182. todo.push(scene->GetRootNode());
  183. while(!todo.empty())
  184. {
  185. FbxNode* curNode = todo.top();
  186. FBXImportNode* curImportNode = outputScene.nodeMap[curNode];
  187. todo.pop();
  188. const char* name = curNode->GetName();
  189. FbxNodeAttribute* attrib = curNode->GetNodeAttribute();
  190. if(attrib != nullptr)
  191. {
  192. FbxNodeAttribute::EType attribType = attrib->GetAttributeType();
  193. switch(attribType)
  194. {
  195. case FbxNodeAttribute::eNurbs:
  196. case FbxNodeAttribute::eNurbsSurface:
  197. case FbxNodeAttribute::ePatch:
  198. {
  199. FbxGeometryConverter geomConverter(mFBXManager);
  200. attrib = geomConverter.Triangulate(attrib, true);
  201. if (attrib->GetAttributeType() == FbxNodeAttribute::eMesh)
  202. {
  203. FbxMesh* mesh = static_cast<FbxMesh*>(attrib);
  204. mesh->RemoveBadPolygons();
  205. parseMesh(mesh, curImportNode, options, outputScene);
  206. }
  207. }
  208. break;
  209. case FbxNodeAttribute::eMesh:
  210. {
  211. FbxMesh* mesh = static_cast<FbxMesh*>(attrib);
  212. mesh->RemoveBadPolygons();
  213. if(!mesh->IsTriangleMesh())
  214. {
  215. FbxGeometryConverter geomConverter(mFBXManager);
  216. geomConverter.Triangulate(mesh, true);
  217. attrib = curNode->GetNodeAttribute();
  218. mesh = static_cast<FbxMesh*>(attrib);
  219. }
  220. parseMesh(mesh, curImportNode, options, outputScene);
  221. }
  222. break;
  223. }
  224. }
  225. for (int i = 0; i < curNode->GetChildCount(); i++)
  226. {
  227. FbxNode* childNode = curNode->GetChild(i);
  228. createImportNode(outputScene, childNode, curImportNode);
  229. todo.push(childNode);
  230. }
  231. }
  232. }
  233. FBXImportNode* FBXImporter::createImportNode(FBXImportScene& scene, FbxNode* fbxNode, FBXImportNode* parent)
  234. {
  235. FBXImportNode* node = bs_new<FBXImportNode>();
  236. Vector3 translation = FBXToNativeType(fbxNode->LclTranslation.Get());
  237. Vector3 rotationEuler = FBXToNativeType(fbxNode->LclRotation.Get());
  238. Vector3 scale = FBXToNativeType(fbxNode->LclScaling.Get());
  239. Quaternion rotation((Radian)rotationEuler.x, (Radian)rotationEuler.y, (Radian)rotationEuler.z);
  240. node->localTransform.setTRS(translation, rotation, scale);
  241. node->fbxNode = fbxNode;
  242. if (parent != nullptr)
  243. {
  244. node->worldTransform = node->localTransform * parent->worldTransform;
  245. parent->children.push_back(node);
  246. }
  247. else
  248. node->worldTransform = node->localTransform;
  249. scene.nodeMap.insert(std::make_pair(fbxNode, node));
  250. return node;
  251. }
  252. void FBXImporter::splitMeshVertices(FBXImportScene& scene)
  253. {
  254. Vector<FBXImportMesh*> splitMeshes;
  255. for (auto& mesh : scene.meshes)
  256. {
  257. FBXImportMesh* splitMesh = bs_new<FBXImportMesh>();
  258. splitMesh->fbxMesh = mesh->fbxMesh;
  259. splitMesh->referencedBy = mesh->referencedBy;
  260. splitMesh->bones = mesh->bones;
  261. FBXUtility::splitVertices(*mesh, *splitMesh);
  262. FBXUtility::flipWindingOrder(*splitMesh);
  263. splitMeshes.push_back(splitMesh);
  264. bs_delete(mesh);
  265. }
  266. scene.meshes = splitMeshes;
  267. }
  268. MeshDataPtr FBXImporter::generateMeshData(const FBXImportScene& scene, const FBXImportOptions& options, Vector<SubMesh>& outputSubMeshes)
  269. {
  270. Matrix4 importScale = Matrix4::scaling(options.importScale);
  271. Vector<MeshDataPtr> allMeshData;
  272. Vector<Vector<SubMesh>> allSubMeshes;
  273. for (auto& mesh : scene.meshes)
  274. {
  275. Vector<Vector<UINT32>> indicesPerMaterial;
  276. for (UINT32 i = 0; i < (UINT32)mesh->indices.size(); i++)
  277. {
  278. while (mesh->materials[i] >= indicesPerMaterial.size())
  279. indicesPerMaterial.push_back(Vector<UINT32>());
  280. indicesPerMaterial[mesh->materials[i]].push_back(mesh->indices[i]);
  281. }
  282. UINT32* orderedIndices = (UINT32*)bs_alloc((UINT32)mesh->indices.size() * sizeof(UINT32));
  283. Vector<SubMesh> subMeshes;
  284. UINT32 currentIndex = 0;
  285. for (auto& subMeshIndices : indicesPerMaterial)
  286. {
  287. UINT32 indexCount = (UINT32)subMeshIndices.size();
  288. UINT32* dest = orderedIndices + currentIndex;
  289. memcpy(dest, subMeshIndices.data(), indexCount * sizeof(UINT32));
  290. subMeshes.push_back(SubMesh(currentIndex, indexCount, DOT_TRIANGLE_LIST));
  291. currentIndex += indexCount;
  292. }
  293. VertexDataDescPtr vertexDesc = bs_shared_ptr<VertexDataDesc>();
  294. vertexDesc->addVertElem(VET_FLOAT3, VES_POSITION);
  295. size_t numVertices = mesh->positions.size();
  296. bool hasColors = mesh->colors.size() == numVertices;
  297. bool hasNormals = mesh->normals.size() == numVertices;
  298. if (hasColors)
  299. vertexDesc->addVertElem(VET_COLOR, VES_COLOR);
  300. bool hasTangents = false;
  301. if (hasNormals)
  302. {
  303. vertexDesc->addVertElem(VET_FLOAT3, VES_NORMAL);
  304. if (mesh->tangents.size() == numVertices &&
  305. mesh->bitangents.size() == numVertices)
  306. {
  307. vertexDesc->addVertElem(VET_FLOAT4, VES_TANGENT);
  308. hasTangents = true;
  309. }
  310. }
  311. int UVIdx = 0;
  312. for (UINT32 i = 0; i < FBX_IMPORT_MAX_UV_LAYERS; i++)
  313. {
  314. if (mesh->UV[i].size() == numVertices)
  315. {
  316. vertexDesc->addVertElem(VET_FLOAT2, VES_TEXCOORD, UVIdx++);
  317. }
  318. }
  319. UINT32 numIndices = (UINT32)mesh->indices.size();
  320. for (auto& node : mesh->referencedBy)
  321. {
  322. Matrix4 worldTransform = node->worldTransform * importScale;
  323. Matrix4 worldTransformIT = worldTransform.transpose();
  324. worldTransformIT = worldTransformIT.inverse();
  325. MeshDataPtr meshData = bs_shared_ptr<MeshData>((UINT32)numVertices, numIndices, vertexDesc);
  326. // Copy indices
  327. UINT32* indices = meshData->getIndices32();
  328. memcpy(indices, mesh->indices.data(), numIndices * sizeof(UINT32));
  329. // Copy & transform positions
  330. auto posIter = meshData->getVec3DataIter(VES_POSITION, 0);
  331. for (auto& position : mesh->positions)
  332. {
  333. Vector3 tfrmdValue = worldTransform.multiplyAffine((Vector3)position);
  334. posIter.addValue(tfrmdValue);
  335. }
  336. // Copy & transform normals
  337. if (hasNormals)
  338. {
  339. auto normalIter = meshData->getVec3DataIter(VES_NORMAL, 0);
  340. // Copy, convert & transform tangents & bitangents
  341. if (hasTangents)
  342. {
  343. auto tangentIter = meshData->getVec4DataIter(VES_TANGENT, 0);
  344. for (UINT32 i = 0; i < (UINT32)numVertices; i++)
  345. {
  346. Vector3 normal = (Vector3)mesh->normals[i];
  347. normal = worldTransformIT.multiplyAffine(normal);
  348. normalIter.addValue(normal);
  349. Vector3 tangent = (Vector3)mesh->tangents[i];
  350. tangent = worldTransformIT.multiplyAffine(tangent);
  351. Vector3 bitangent = (Vector3)mesh->bitangents[i];
  352. bitangent = worldTransformIT.multiplyAffine(bitangent);
  353. Vector3 engineBitangent = Vector3::cross(normal, tangent);
  354. float sign = Vector3::dot(engineBitangent, bitangent);
  355. Vector4 combinedTangent(tangent.x, tangent.y, tangent.z, sign > 0 ? 1.0f : -1.0f);
  356. tangentIter.addValue(combinedTangent);
  357. }
  358. }
  359. else // Just normals
  360. {
  361. for (auto& normal : mesh->normals)
  362. {
  363. Vector3 tfrmdValue = worldTransformIT.multiplyAffine((Vector3)normal);
  364. normalIter.addValue(tfrmdValue);
  365. }
  366. }
  367. }
  368. // Copy colors
  369. if (hasColors)
  370. {
  371. auto colorIter = meshData->getDWORDDataIter(VES_COLOR, 0);
  372. for (auto& color : mesh->colors)
  373. colorIter.addValue(color);
  374. }
  375. // Copy UV
  376. int writeUVIDx = 0;
  377. for (auto& uvLayer : mesh->UV)
  378. {
  379. if (uvLayer.size() == numVertices)
  380. {
  381. auto uvIter = meshData->getVec2DataIter(VES_TEXCOORD, writeUVIDx);
  382. for (auto& uv : uvLayer)
  383. {
  384. uv.y = 1.0f - uv.y;
  385. uvIter.addValue(uv);
  386. }
  387. writeUVIDx++;
  388. }
  389. }
  390. allMeshData.push_back(meshData);
  391. allSubMeshes.push_back(subMeshes);
  392. }
  393. }
  394. if (allMeshData.size() > 1)
  395. {
  396. return MeshData::combine(allMeshData, allSubMeshes, outputSubMeshes);
  397. }
  398. else if (allMeshData.size() == 1)
  399. {
  400. outputSubMeshes = allSubMeshes[0];
  401. return allMeshData[0];
  402. }
  403. return nullptr;
  404. }
  405. template<class TFBX, class TNative>
  406. class FBXDirectIndexer
  407. {
  408. public:
  409. FBXDirectIndexer(const FbxLayerElementTemplate<TFBX>& layer)
  410. :mElementArray(layer.GetDirectArray()),
  411. mElementCount(mElementArray.GetCount())
  412. {}
  413. bool get(int index, TNative& output) const
  414. {
  415. if (index < 0 || index >= mElementCount)
  416. return false;
  417. output = FBXToNativeType(mElementArray.GetAt(index));
  418. return true;
  419. }
  420. bool isEmpty() const
  421. {
  422. return mElementCount == 0;
  423. }
  424. private:
  425. const FbxLayerElementArrayTemplate<TFBX>& mElementArray;
  426. int mElementCount;
  427. };
  428. template<class TFBX, class TNative>
  429. class FBXIndexIndexer
  430. {
  431. public:
  432. FBXIndexIndexer(const FbxLayerElementTemplate<TFBX>& layer)
  433. :mElementArray(layer.GetDirectArray()),
  434. mIndexArray(layer.GetIndexArray()),
  435. mElementCount(mElementArray.GetCount()),
  436. mIndexCount(mIndexArray.GetCount())
  437. {}
  438. bool get(int index, TNative& output) const
  439. {
  440. if (index < 0 || index >= mIndexCount)
  441. return false;
  442. int actualIndex = mIndexArray.GetAt(index);
  443. if (actualIndex < 0 || actualIndex >= mElementCount)
  444. return false;
  445. output = FBXToNativeType(mElementArray.GetAt(actualIndex));
  446. return true;
  447. }
  448. bool isEmpty() const
  449. {
  450. return mElementCount == 0 || mIndexCount == 0;
  451. }
  452. private:
  453. const FbxLayerElementArrayTemplate<TFBX>& mElementArray;
  454. const FbxLayerElementArrayTemplate<int>& mIndexArray;
  455. int mElementCount;
  456. int mIndexCount;
  457. };
  458. template<class TFBX, class TNative, class TIndexer>
  459. void readLayerData(FbxLayerElementTemplate<TFBX>& layer, Vector<TNative>& output, const Vector<int>& indices)
  460. {
  461. TIndexer indexer(layer);
  462. if (indexer.isEmpty())
  463. return;
  464. output.resize(indices.size());
  465. FbxLayerElement::EMappingMode mappingMode = layer.GetMappingMode();
  466. UINT32 indexCount = (UINT32)indices.size();
  467. switch (mappingMode)
  468. {
  469. case FbxLayerElement::eByControlPoint:
  470. for (UINT32 i = 0; i < indexCount; i++)
  471. {
  472. int index = indices[i];
  473. indexer.get(index, output[i]);
  474. }
  475. break;
  476. case FbxLayerElement::eByPolygonVertex:
  477. for (UINT32 i = 0; i < indexCount; i++)
  478. indexer.get(i, output[i]);
  479. break;
  480. case FbxLayerElement::eByPolygon:
  481. // We expect mesh to be triangulated here
  482. {
  483. UINT32 polygonCount = indexCount / 3;
  484. UINT32 index = 0;
  485. for (UINT32 i = 0; i < polygonCount; i++)
  486. {
  487. TNative value;
  488. indexer.get(i, value);
  489. output[index++] = value;
  490. output[index++] = value;
  491. output[index++] = value;
  492. }
  493. }
  494. break;
  495. case FbxLayerElement::eAllSame:
  496. {
  497. TNative value;
  498. indexer.get(0, value);
  499. for (UINT32 i = 0; i < indexCount; i++)
  500. output[i] = value;
  501. }
  502. break;
  503. default:
  504. LOGWRN("FBX Import: Unsupported layer mapping mode.");
  505. break;
  506. }
  507. }
  508. template<class TFBX, class TNative>
  509. void readLayerData(FbxLayerElementTemplate<TFBX>& layer, Vector<TNative>& output, const Vector<int>& indices)
  510. {
  511. FbxLayerElement::EReferenceMode refMode = layer.GetReferenceMode();
  512. if (refMode == FbxLayerElement::eDirect)
  513. readLayerData<TFBX, TNative, FBXDirectIndexer<TFBX, TNative> >(layer, output, indices);
  514. else if (refMode == FbxLayerElement::eIndexToDirect)
  515. readLayerData<TFBX, TNative, FBXIndexIndexer<TFBX, TNative> >(layer, output, indices);
  516. else
  517. LOGWRN("FBX Import: Unsupported layer reference mode.");
  518. }
  519. void FBXImporter::parseMesh(FbxMesh* mesh, FBXImportNode* parentNode, const FBXImportOptions& options, FBXImportScene& outputScene)
  520. {
  521. // Check if valid
  522. if (!mesh->IsTriangleMesh())
  523. return;
  524. UINT32 vertexCount = mesh->GetControlPointsCount();
  525. UINT32 triangleCount = mesh->GetPolygonCount();
  526. if (vertexCount == 0 || triangleCount == 0)
  527. return;
  528. // Register in global mesh array
  529. FBXImportMesh* importMesh = nullptr;
  530. auto iterFindMesh = outputScene.meshMap.find(mesh);
  531. if (iterFindMesh != outputScene.meshMap.end())
  532. {
  533. UINT32 meshIdx = iterFindMesh->second;
  534. outputScene.meshes[meshIdx]->referencedBy.push_back(parentNode);
  535. return;
  536. }
  537. else
  538. {
  539. importMesh = bs_new<FBXImportMesh>();
  540. outputScene.meshes.push_back(importMesh);
  541. importMesh->referencedBy.push_back(parentNode);
  542. importMesh->fbxMesh = mesh;
  543. outputScene.meshMap[mesh] = (UINT32)outputScene.meshes.size() - 1;
  544. }
  545. // Import vertices
  546. importMesh->positions.resize(vertexCount);
  547. FbxVector4* controlPoints = mesh->GetControlPoints();
  548. for (UINT32 i = 0; i < vertexCount; i++)
  549. importMesh->positions[i] = FBXToNativeType(controlPoints[i]);
  550. // Import triangles
  551. UINT32 indexCount = triangleCount * 3;
  552. importMesh->indices.resize(indexCount);
  553. int* fbxIndices = mesh->GetPolygonVertices();
  554. importMesh->indices.assign(fbxIndices, fbxIndices + indexCount);
  555. // Import UVs
  556. Vector<FbxLayerElementUV*> fbxUVLayers;
  557. //// Search the diffuse layers first
  558. for (UINT32 i = 0; i < FBX_IMPORT_MAX_UV_LAYERS; i++)
  559. {
  560. FbxLayer* layer = mesh->GetLayer(i, FbxLayerElement::eUV);
  561. if (layer == nullptr)
  562. continue;
  563. for (int j = FbxLayerElement::eTextureDiffuse; j < FbxLayerElement::eTypeCount; j++)
  564. {
  565. FbxLayerElementUV* uvLayer = layer->GetUVs((FbxLayerElement::EType)j);
  566. if (uvLayer == nullptr)
  567. continue;
  568. fbxUVLayers.push_back(uvLayer);
  569. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  570. break;
  571. }
  572. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  573. break;
  574. }
  575. //// If there's room, search all others too
  576. if (fbxUVLayers.size() < FBX_IMPORT_MAX_UV_LAYERS)
  577. {
  578. UINT32 numLayers = mesh->GetLayerCount();
  579. for (UINT32 i = 0; i < numLayers; i++)
  580. {
  581. FbxLayer* layer = mesh->GetLayer(i);
  582. if (layer == nullptr)
  583. continue;
  584. for (int j = FbxLayerElement::eTextureDiffuse; j < FbxLayerElement::eTypeCount; j++)
  585. {
  586. FbxLayerElementUV* uvLayer = layer->GetUVs((FbxLayerElement::EType)j);
  587. if (uvLayer == nullptr)
  588. continue;
  589. auto iterFind = std::find(fbxUVLayers.begin(), fbxUVLayers.end(), uvLayer);
  590. if (iterFind != fbxUVLayers.end())
  591. continue;
  592. fbxUVLayers.push_back(uvLayer);
  593. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  594. break;
  595. }
  596. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  597. break;
  598. }
  599. }
  600. for (size_t i = 0; i < fbxUVLayers.size(); i++)
  601. readLayerData(*fbxUVLayers[i], importMesh->UV[i], importMesh->indices);
  602. FbxLayer* mainLayer = mesh->GetLayer(0);
  603. if (mainLayer != nullptr)
  604. {
  605. // Import colors
  606. if (mainLayer->GetVertexColors() != nullptr)
  607. readLayerData(*mainLayer->GetVertexColors(), importMesh->colors, importMesh->indices);
  608. // Import normals
  609. if (options.importNormals)
  610. {
  611. bool hasNormals = mainLayer->GetNormals() != nullptr;
  612. if (!hasNormals)
  613. {
  614. if (mainLayer->GetSmoothing() != nullptr)
  615. {
  616. FbxLayerElementSmoothing* smoothing = mainLayer->GetSmoothing();
  617. if (smoothing->GetMappingMode() == FbxLayerElement::eByEdge)
  618. {
  619. FbxGeometryConverter converter(mFBXManager);
  620. converter.ComputePolygonSmoothingFromEdgeSmoothing(mesh, 0);
  621. }
  622. readLayerData(*smoothing, importMesh->smoothingGroups, importMesh->indices);
  623. if (!importMesh->smoothingGroups.empty())
  624. {
  625. FBXUtility::normalsFromSmoothing(importMesh->positions, importMesh->indices,
  626. importMesh->smoothingGroups, importMesh->normals);
  627. hasNormals = true;
  628. }
  629. }
  630. if (!hasNormals)
  631. {
  632. // TODO - Calculate normals
  633. }
  634. }
  635. else
  636. readLayerData(*mainLayer->GetNormals(), importMesh->normals, importMesh->indices);
  637. }
  638. // Import tangents
  639. if (options.importTangents)
  640. {
  641. bool hasTangents = mainLayer->GetTangents() != nullptr && mainLayer->GetBinormals() != nullptr;
  642. if (!hasTangents)
  643. {
  644. if (fbxUVLayers.size() > 0)
  645. hasTangents = mesh->GenerateTangentsData(0, false);
  646. }
  647. if (hasTangents)
  648. {
  649. readLayerData(*mainLayer->GetTangents(), importMesh->tangents, importMesh->indices);
  650. readLayerData(*mainLayer->GetBinormals(), importMesh->bitangents, importMesh->indices);
  651. }
  652. else
  653. {
  654. // TODO - Calculate tangent frame
  655. }
  656. }
  657. // Import material indexes
  658. if (mainLayer->GetMaterials() != nullptr)
  659. {
  660. Vector<FbxSurfaceMaterial*> fbxMaterials;
  661. readLayerData(*mainLayer->GetMaterials(), fbxMaterials, importMesh->indices);
  662. UnorderedMap<FbxSurfaceMaterial*, int> materialLookup;
  663. int nextMaterialIdx = 0;
  664. for (UINT32 i = 0; i < (UINT32)fbxMaterials.size(); i++)
  665. {
  666. auto iterFind = materialLookup.find(fbxMaterials[i]);
  667. int materialIdx = 0;
  668. if (iterFind != materialLookup.end())
  669. materialIdx = iterFind->second;
  670. else
  671. {
  672. materialIdx = nextMaterialIdx++;
  673. materialLookup[fbxMaterials[i]] = materialIdx;
  674. }
  675. importMesh->materials.push_back(materialIdx);
  676. }
  677. }
  678. }
  679. }
  680. void FBXImporter::importBlendShapes(FBXImportScene& scene, const FBXImportOptions& options)
  681. {
  682. for (auto& mesh : scene.meshes)
  683. {
  684. FbxMesh* fbxMesh = mesh->fbxMesh;
  685. UINT32 deformerCount = (UINT32)fbxMesh->GetDeformerCount(FbxDeformer::eBlendShape);
  686. for (UINT32 i = 0; i < deformerCount; i++)
  687. {
  688. FbxBlendShape* deformer = static_cast<FbxBlendShape*>(fbxMesh->GetDeformer(i, FbxDeformer::eBlendShape));
  689. UINT32 blendShapeChannelCount = (UINT32)deformer->GetBlendShapeChannelCount();
  690. for (UINT32 j = 0; j < blendShapeChannelCount; ++j)
  691. {
  692. FbxBlendShapeChannel* channel = deformer->GetBlendShapeChannel(j);
  693. double* weights = channel->GetTargetShapeFullWeights();
  694. UINT32 frameCount = channel->GetTargetShapeCount();
  695. if (frameCount == 0)
  696. continue;
  697. mesh->blendShapes.push_back(FBXBlendShape());
  698. FBXBlendShape& blendShape = mesh->blendShapes.back();
  699. blendShape.name = channel->GetName();
  700. blendShape.frames.resize(frameCount);
  701. for (UINT32 k = 0; k < frameCount; k++)
  702. {
  703. FbxShape* fbxShape = channel->GetTargetShape(k);
  704. FBXBlendShapeFrame& frame = blendShape.frames[k];
  705. frame.weight = (float)weights[k];
  706. importBlendShapeFrame(fbxShape, *mesh, options, frame);
  707. }
  708. }
  709. }
  710. }
  711. }
  712. void FBXImporter::importBlendShapeFrame(FbxShape* shape, const FBXImportMesh& mesh, const FBXImportOptions& options, FBXBlendShapeFrame& outFrame)
  713. {
  714. UINT32 vertexCount = (UINT32)shape->GetControlPointsCount();
  715. outFrame.positions.resize(vertexCount);
  716. FbxVector4* controlPoints = shape->GetControlPoints();
  717. for (UINT32 i = 0; i < vertexCount; i++)
  718. outFrame.positions[i] = FBXToNativeType(controlPoints[i]);
  719. FbxLayer* mainLayer = shape->GetLayer(0);
  720. if (options.importNormals)
  721. {
  722. bool hasNormals = mainLayer->GetNormals() != nullptr;
  723. if (!hasNormals)
  724. {
  725. if (!mesh.smoothingGroups.empty())
  726. {
  727. FBXUtility::normalsFromSmoothing(outFrame.positions, mesh.indices,
  728. mesh.smoothingGroups, outFrame.normals);
  729. }
  730. else
  731. {
  732. // TODO - Calculate normals
  733. }
  734. }
  735. else
  736. readLayerData(*mainLayer->GetNormals(), outFrame.normals, mesh.indices);
  737. }
  738. if (options.importTangents)
  739. {
  740. bool hasTangents = mainLayer->GetTangents() != nullptr && mainLayer->GetBinormals() != nullptr;
  741. if (hasTangents)
  742. {
  743. readLayerData(*mainLayer->GetTangents(), outFrame.tangents, mesh.indices);
  744. readLayerData(*mainLayer->GetBinormals(), outFrame.bitangents, mesh.indices);
  745. }
  746. else
  747. {
  748. // TODO - Calculate tangent frame
  749. }
  750. }
  751. }
  752. void FBXImporter::importSkin(FBXImportScene& scene)
  753. {
  754. for (auto& mesh : scene.meshes)
  755. {
  756. FbxMesh* fbxMesh = mesh->fbxMesh;
  757. UINT32 deformerCount = (UINT32)fbxMesh->GetDeformerCount(FbxDeformer::eSkin);
  758. if (deformerCount > 0)
  759. {
  760. // We ignore other deformers if there's more than one
  761. FbxSkin* deformer = static_cast<FbxSkin*>(fbxMesh->GetDeformer(0, FbxDeformer::eSkin));
  762. UINT32 boneCount = (UINT32)deformer->GetClusterCount();
  763. if (boneCount == 0)
  764. continue;
  765. // If only one bone and it links to itself, ignore the bone
  766. if (boneCount == 1)
  767. {
  768. FbxCluster* cluster = deformer->GetCluster(0);
  769. if (mesh->referencedBy.size() == 1 && mesh->referencedBy[0]->fbxNode == cluster->GetLink())
  770. continue;
  771. }
  772. importSkin(scene, deformer, *mesh);
  773. }
  774. }
  775. }
  776. void FBXImporter::importSkin(FBXImportScene& scene, FbxSkin* skin, FBXImportMesh& mesh)
  777. {
  778. Vector<FBXBoneInfluence>& influences = mesh.boneInfluences;
  779. influences.resize(mesh.positions.size());
  780. UnorderedSet<FbxNode*> existingBones;
  781. UINT32 boneCount = (UINT32)skin->GetClusterCount();
  782. for (UINT32 i = 0; i < boneCount; i++)
  783. {
  784. FbxCluster* cluster = skin->GetCluster(i);
  785. FbxNode* link = cluster->GetLink();
  786. // The bone node doesn't exist, skip it
  787. auto iterFind = scene.nodeMap.find(link);
  788. if (iterFind == scene.nodeMap.end())
  789. continue;
  790. mesh.bones.push_back(FBXBone());
  791. FBXBone& bone = mesh.bones.back();
  792. bone.node = iterFind->second;
  793. FbxAMatrix clusterTransform;
  794. cluster->GetTransformMatrix(clusterTransform);
  795. FbxAMatrix linkTransform;
  796. cluster->GetTransformLinkMatrix(linkTransform);
  797. FbxAMatrix bindPose = linkTransform.Inverse() * clusterTransform;
  798. bone.bindPose = FBXToNativeType(bindPose);
  799. bool isDuplicate = existingBones.insert(link).second;
  800. bool isAdditive = cluster->GetLinkMode() == FbxCluster::eAdditive;
  801. // We avoid importing weights twice for duplicate bones and we don't
  802. // support additive link mode.
  803. bool importWeights = !isDuplicate && !isAdditive;
  804. if (!importWeights)
  805. continue;
  806. double* weights = cluster->GetControlPointWeights();
  807. INT32* indices = cluster->GetControlPointIndices();
  808. UINT32 numIndices = (UINT32)cluster->GetControlPointIndicesCount();
  809. INT32 numVertices = (INT32)influences.size();
  810. // Add new weights while keeping them in order and removing the smallest ones
  811. // if number of influences exceeds the set maximum value
  812. for (UINT32 j = 0; j < numIndices; j++)
  813. {
  814. INT32 vertexIndex = indices[j];
  815. float weight = (float)weights[j];
  816. for (UINT32 k = 0; k < FBX_IMPORT_MAX_BONE_INFLUENCES; k++)
  817. {
  818. if (vertexIndex < 0 || vertexIndex >= numVertices)
  819. continue;
  820. if (weight >= influences[vertexIndex].weights[k])
  821. {
  822. for (UINT32 l = FBX_IMPORT_MAX_BONE_INFLUENCES - 2; l >= k; l--)
  823. {
  824. influences[vertexIndex].weights[l + 1] = influences[vertexIndex].weights[l];
  825. influences[vertexIndex].indices[l + 1] = influences[vertexIndex].indices[l];
  826. }
  827. influences[vertexIndex].weights[k] = weight;
  828. influences[vertexIndex].indices[k] = i;
  829. break;
  830. }
  831. }
  832. }
  833. }
  834. if (mesh.bones.empty())
  835. mesh.boneInfluences.clear();
  836. // Normalize weights
  837. UINT32 numInfluences = (UINT32)mesh.boneInfluences.size();
  838. for (UINT32 i = 0; i < numInfluences; i++)
  839. {
  840. float sum = 0.0f;
  841. for (UINT32 j = 0; j < FBX_IMPORT_MAX_BONE_INFLUENCES; j++)
  842. sum += influences[i].weights[j];
  843. float invSum = 1.0f / sum;
  844. for (UINT32 j = 0; j < FBX_IMPORT_MAX_BONE_INFLUENCES; j++)
  845. influences[i].weights[j] *= invSum;
  846. }
  847. }
  848. void FBXImporter::importAnimations(FbxScene* scene, FBXImportOptions& importOptions, FBXImportScene& importScene)
  849. {
  850. FbxNode* root = scene->GetRootNode();
  851. UINT32 numAnimStacks = (UINT32)scene->GetSrcObjectCount<FbxAnimStack>();
  852. for (UINT32 i = 0; i < numAnimStacks; i++)
  853. {
  854. FbxAnimStack* animStack = scene->GetSrcObject<FbxAnimStack>(i);
  855. importScene.clips.push_back(FBXAnimationClip());
  856. FBXAnimationClip& clip = importScene.clips.back();
  857. clip.name = animStack->GetName();
  858. FbxTimeSpan timeSpan = animStack->GetLocalTimeSpan();
  859. clip.start = (float)timeSpan.GetStart().GetSecondDouble();
  860. clip.end = (float)timeSpan.GetStop().GetSecondDouble();
  861. UINT32 layerCount = animStack->GetMemberCount<FbxAnimLayer>();
  862. if (layerCount > 1)
  863. {
  864. FbxAnimEvaluator* evaluator = scene->GetAnimationEvaluator();
  865. FbxTime startTime;
  866. startTime.SetSecondDouble(clip.start);
  867. FbxTime endTime;
  868. endTime.SetSecondDouble(clip.end);
  869. FbxTime sampleRate;
  870. if (importOptions.animResample)
  871. sampleRate.SetSecondDouble(importOptions.animSampleRate);
  872. else
  873. {
  874. FbxTime::EMode timeMode = scene->GetGlobalSettings().GetTimeMode();
  875. sampleRate.SetSecondDouble(1.0f / FbxTime::GetFrameRate(timeMode));
  876. }
  877. if (!animStack->BakeLayers(evaluator, startTime, endTime, sampleRate))
  878. continue;
  879. layerCount = animStack->GetMemberCount<FbxAnimLayer>();
  880. }
  881. if (layerCount == 1)
  882. {
  883. FbxAnimLayer* animLayer = animStack->GetMember<FbxAnimLayer>(0);
  884. importAnimations(animLayer, root, importOptions, clip, importScene);
  885. }
  886. }
  887. }
  888. void FBXImporter::importAnimations(FbxAnimLayer* layer, FbxNode* node, FBXImportOptions& importOptions,
  889. FBXAnimationClip& clip, FBXImportScene& importScene)
  890. {
  891. FbxAnimCurve* translation[3];
  892. translation[0] = node->LclTranslation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_X);
  893. translation[1] = node->LclTranslation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Y);
  894. translation[2] = node->LclTranslation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Z);
  895. FbxAnimCurve* rotation[3];
  896. rotation[0] = node->LclRotation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_X);
  897. rotation[1] = node->LclRotation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Y);
  898. rotation[2] = node->LclRotation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Z);
  899. FbxAnimCurve* scale[3];
  900. scale[0] = node->LclScaling.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_X);
  901. scale[1] = node->LclScaling.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Y);
  902. scale[2] = node->LclScaling.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Z);
  903. auto hasCurveValues = [](FbxAnimCurve* curves[3])
  904. {
  905. for (UINT32 i = 0; i < 3; i++)
  906. {
  907. if (curves[i] != nullptr && curves[i]->KeyGetCount() > 0)
  908. return true;
  909. }
  910. return false;
  911. };
  912. bool hasBoneAnimation = hasCurveValues(translation) || hasCurveValues(rotation) || hasCurveValues(scale);
  913. if (hasBoneAnimation)
  914. {
  915. clip.boneAnimations.push_back(FBXBoneAnimation());
  916. FBXBoneAnimation& boneAnim = clip.boneAnimations.back();
  917. boneAnim.node = importScene.nodeMap[node];
  918. importCurve(translation[0], importOptions, boneAnim.translation[0], clip.start, clip.end);
  919. importCurve(translation[1], importOptions, boneAnim.translation[1], clip.start, clip.end);
  920. importCurve(translation[2], importOptions, boneAnim.translation[2], clip.start, clip.end);
  921. importCurve(scale[0], importOptions, boneAnim.scale[0], clip.start, clip.end);
  922. importCurve(scale[1], importOptions, boneAnim.scale[1], clip.start, clip.end);
  923. importCurve(scale[2], importOptions, boneAnim.scale[2], clip.start, clip.end);
  924. FBXAnimationCurve tempCurveRotation[3];
  925. importCurve(rotation[0], importOptions, tempCurveRotation[0], clip.start, clip.end);
  926. importCurve(rotation[1], importOptions, tempCurveRotation[1], clip.start, clip.end);
  927. importCurve(rotation[2], importOptions, tempCurveRotation[2], clip.start, clip.end);
  928. eulerToQuaternionCurves(tempCurveRotation, boneAnim.rotation);
  929. }
  930. if (importOptions.importBlendShapes)
  931. {
  932. FbxMesh* fbxMesh = node->GetMesh();
  933. if (fbxMesh != nullptr)
  934. {
  935. INT32 deformerCount = fbxMesh->GetDeformerCount(FbxDeformer::eBlendShape);
  936. for (INT32 i = 0; i < deformerCount; i++)
  937. {
  938. FbxBlendShape* deformer = static_cast<FbxBlendShape*>(fbxMesh->GetDeformer(i, FbxDeformer::eBlendShape));
  939. INT32 channelCount = deformer->GetBlendShapeChannelCount();
  940. for (INT32 j = 0; j < channelCount; j++)
  941. {
  942. FbxBlendShapeChannel* channel = deformer->GetBlendShapeChannel(j);
  943. FbxAnimCurve* curve = fbxMesh->GetShapeChannel(i, j, layer);
  944. if (curve != nullptr && curve->KeyGetCount() > 0)
  945. {
  946. clip.blendShapeAnimations.push_back(FBXBlendShapeAnimation());
  947. FBXBlendShapeAnimation& blendShapeAnim = clip.blendShapeAnimations.back();
  948. blendShapeAnim.blendShape = channel->GetName();
  949. importCurve(curve, importOptions, blendShapeAnim.curve, clip.start, clip.end);
  950. }
  951. }
  952. }
  953. }
  954. }
  955. UINT32 childCount = (UINT32)node->GetChildCount();
  956. for (UINT32 i = 0; i < childCount; i++)
  957. {
  958. FbxNode* child = node->GetChild(i);
  959. importAnimations(layer, child, importOptions, clip, importScene);
  960. }
  961. }
  962. void FBXImporter::eulerToQuaternionCurves(FBXAnimationCurve(&eulerCurves)[3], FBXAnimationCurve(&quatCurves)[4])
  963. {
  964. INT32 numKeys = (INT32)eulerCurves[0].keyframes.size();
  965. if (numKeys != (INT32)eulerCurves[1].keyframes.size() || numKeys != (INT32)eulerCurves[2].keyframes.size())
  966. return;
  967. Quaternion lastQuat;
  968. for (INT32 i = 0; i < numKeys; i++)
  969. {
  970. float time = eulerCurves[0].keyframes[i].time;
  971. Degree x = (Degree)eulerCurves[0].keyframes[i].value;
  972. Degree y = (Degree)eulerCurves[1].keyframes[i].value;
  973. Degree z = (Degree)eulerCurves[2].keyframes[i].value;
  974. Quaternion quat(x, y, z);
  975. // Flip quaternion in case rotation is over 180 degrees
  976. if (i > 0)
  977. {
  978. float dot = quat.dot(lastQuat);
  979. if (dot < 0.0f)
  980. quat = Quaternion(-quat.x, -quat.y, -quat.z, -quat.w);
  981. }
  982. // TODO - If animation is looping I should also compare last and first for continuity
  983. for (INT32 j = 0; j < 4; j++)
  984. {
  985. quatCurves[j].keyframes.push_back(FBXKeyFrame());
  986. FBXKeyFrame& keyFrame = quatCurves[j].keyframes.back();
  987. keyFrame.time = time;
  988. keyFrame.value = quat[j];
  989. // TODO - Recalculate tangents(make sure not to ignore original ones)
  990. // - Pay attention to deal with non-equally spaced keyframes
  991. // TODO - Tangent recalculation assumes all curves are cubic, which might not be the case
  992. keyFrame.inTangent = 0;
  993. keyFrame.outTangent = 0;
  994. }
  995. lastQuat = quat;
  996. }
  997. }
  998. void FBXImporter::importCurve(FbxAnimCurve* fbxCurve, FBXImportOptions& importOptions, FBXAnimationCurve& curve, float start, float end)
  999. {
  1000. if (fbxCurve == nullptr)
  1001. return;
  1002. INT32 keyCount = fbxCurve->KeyGetCount();
  1003. if (importOptions.animResample)
  1004. {
  1005. float curveStart = std::numeric_limits<float>::infinity();
  1006. float curveEnd = -std::numeric_limits<float>::infinity();
  1007. for (INT32 i = 0; i < keyCount; i++)
  1008. {
  1009. FbxTime fbxTime = fbxCurve->KeyGetTime(i);
  1010. float time = (float)fbxTime.GetSecondDouble();
  1011. curveStart = std::min(time, curveStart);
  1012. curveEnd = std::max(time, curveEnd);
  1013. }
  1014. curveStart = Math::clamp(curveStart, start, end);
  1015. curveEnd = Math::clamp(curveEnd, start, end);
  1016. float curveLength = curveEnd - curveStart;
  1017. INT32 numSamples = Math::ceilToInt(curveLength / importOptions.animSampleRate);
  1018. // We don't use the exact provided sample rate but instead modify it slightly so it
  1019. // completely covers the curve range including start/end points while maintaining
  1020. // constant time step between keyframes.
  1021. float dt = curveLength / (float)numSamples;
  1022. INT32 lastKeyframe = 0;
  1023. INT32 lastLeftTangent = 0;
  1024. INT32 lastRightTangent = 0;
  1025. for (INT32 i = 0; i < numSamples; i++)
  1026. {
  1027. float sampleTime = std::min(curveStart + i * dt, curveEnd);
  1028. FbxTime fbxSampleTime;
  1029. fbxSampleTime.SetSecondDouble(sampleTime);
  1030. curve.keyframes.push_back(FBXKeyFrame());
  1031. FBXKeyFrame& keyFrame = curve.keyframes.back();
  1032. keyFrame.time = sampleTime;
  1033. keyFrame.value = fbxCurve->Evaluate(fbxSampleTime, &lastKeyframe);
  1034. keyFrame.inTangent = fbxCurve->EvaluateLeftDerivative(fbxSampleTime, &lastLeftTangent);
  1035. keyFrame.outTangent = fbxCurve->EvaluateRightDerivative(fbxSampleTime, &lastRightTangent);
  1036. }
  1037. }
  1038. else
  1039. {
  1040. for (int i = 0; i < keyCount; i++)
  1041. {
  1042. FbxTime fbxTime = fbxCurve->KeyGetTime(i);
  1043. float time = (float)fbxTime.GetSecondDouble();
  1044. if (time < start || time > end)
  1045. continue;
  1046. curve.keyframes.push_back(FBXKeyFrame());
  1047. FBXKeyFrame& keyFrame = curve.keyframes.back();
  1048. keyFrame.time = time;
  1049. keyFrame.value = fbxCurve->KeyGetValue(i);
  1050. keyFrame.inTangent = fbxCurve->KeyGetLeftDerivative(i);
  1051. keyFrame.outTangent = fbxCurve->KeyGetRightDerivative(i);
  1052. }
  1053. }
  1054. }
  1055. }