BsFBXImporter.cpp 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsFBXImporter.h"
  4. #include "BsResource.h"
  5. #include "BsCoreApplication.h"
  6. #include "BsDebug.h"
  7. #include "BsDataStream.h"
  8. #include "BsMeshData.h"
  9. #include "BsMesh.h"
  10. #include "BsVector2.h"
  11. #include "BsVector3.h"
  12. #include "BsVector4.h"
  13. #include "BsQuaternion.h"
  14. #include "BsVertexDataDesc.h"
  15. #include "BsFBXUtility.h"
  16. #include "BsMeshUtility.h"
  17. #include "BsRendererMeshData.h"
  18. #include "BsMeshImportOptions.h"
  19. #include "BsPhysicsMesh.h"
  20. #include "BsAnimationCurve.h"
  21. #include "BsAnimationClip.h"
  22. #include "BsSkeleton.h"
  23. #include "BsPhysics.h"
  24. namespace BansheeEngine
  25. {
  26. Matrix4 FBXToNativeType(const FbxAMatrix& value)
  27. {
  28. Matrix4 native;
  29. for (UINT32 row = 0; row < 4; row++)
  30. for (UINT32 col = 0; col < 4; col++)
  31. native[row][col] = (float)value[col][row];
  32. return native;
  33. }
  34. Vector3 FBXToNativeType(const FbxVector4& 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. Vector3 FBXToNativeType(const FbxDouble3& value)
  43. {
  44. Vector3 native;
  45. native.x = (float)value[0];
  46. native.y = (float)value[1];
  47. native.z = (float)value[2];
  48. return native;
  49. }
  50. Vector2 FBXToNativeType(const FbxVector2& value)
  51. {
  52. Vector2 native;
  53. native.x = (float)value[0];
  54. native.y = (float)value[1];
  55. return native;
  56. }
  57. RGBA FBXToNativeType(const FbxColor& value)
  58. {
  59. Color native;
  60. native.r = (float)value[0];
  61. native.g = (float)value[1];
  62. native.b = (float)value[2];
  63. native.a = (float)value[3];
  64. return native.getAsRGBA();
  65. }
  66. FbxSurfaceMaterial* FBXToNativeType(FbxSurfaceMaterial* const& value)
  67. {
  68. return value;
  69. }
  70. int FBXToNativeType(const int & value)
  71. {
  72. return value;
  73. }
  74. FBXImporter::FBXImporter()
  75. :SpecificImporter(), mFBXManager(nullptr)
  76. {
  77. mExtensions.push_back(L"fbx");
  78. }
  79. FBXImporter::~FBXImporter()
  80. {
  81. }
  82. bool FBXImporter::isExtensionSupported(const WString& ext) const
  83. {
  84. WString lowerCaseExt = ext;
  85. StringUtil::toLowerCase(lowerCaseExt);
  86. return find(mExtensions.begin(), mExtensions.end(), lowerCaseExt) != mExtensions.end();
  87. }
  88. bool FBXImporter::isMagicNumberSupported(const UINT8* magicNumPtr, UINT32 numBytes) const
  89. {
  90. return true; // FBX files can be plain-text so I don't even check for magic number
  91. }
  92. SPtr<ImportOptions> FBXImporter::createImportOptions() const
  93. {
  94. return bs_shared_ptr_new<MeshImportOptions>();
  95. }
  96. SPtr<Resource> FBXImporter::import(const Path& filePath, SPtr<const ImportOptions> importOptions)
  97. {
  98. Vector<SubMesh> subMeshes;
  99. UnorderedMap<String, SPtr<AnimationCurves>> dummy;
  100. SPtr<Skeleton> skeleton;
  101. SPtr<RendererMeshData> rendererMeshData = importMeshData(filePath, importOptions, subMeshes, dummy, skeleton);
  102. const MeshImportOptions* meshImportOptions = static_cast<const MeshImportOptions*>(importOptions.get());
  103. INT32 usage = MU_STATIC;
  104. if (meshImportOptions->getCPUReadable())
  105. usage |= MU_CPUCACHED;
  106. SPtr<Mesh> mesh = Mesh::_createPtr(rendererMeshData->getData(), subMeshes, usage, skeleton);
  107. WString fileName = filePath.getWFilename(false);
  108. mesh->setName(fileName);
  109. return mesh;
  110. }
  111. Vector<SubResourceRaw> FBXImporter::importAll(const Path& filePath, SPtr<const ImportOptions> importOptions)
  112. {
  113. Vector<SubMesh> subMeshes;
  114. UnorderedMap<String, SPtr<AnimationCurves>> animationClips;
  115. SPtr<Skeleton> skeleton;
  116. SPtr<RendererMeshData> rendererMeshData = importMeshData(filePath, importOptions, subMeshes, animationClips, skeleton);
  117. const MeshImportOptions* meshImportOptions = static_cast<const MeshImportOptions*>(importOptions.get());
  118. INT32 usage = MU_STATIC;
  119. if (meshImportOptions->getCPUReadable())
  120. usage |= MU_CPUCACHED;
  121. SPtr<Mesh> mesh = Mesh::_createPtr(rendererMeshData->getData(), subMeshes, usage, skeleton);
  122. WString fileName = filePath.getWFilename(false);
  123. mesh->setName(fileName);
  124. Vector<SubResourceRaw> output;
  125. if(mesh != nullptr)
  126. {
  127. output.push_back({ L"primary", mesh });
  128. CollisionMeshType collisionMeshType = meshImportOptions->getCollisionMeshType();
  129. if(collisionMeshType != CollisionMeshType::None)
  130. {
  131. if(Physics::isStarted())
  132. {
  133. PhysicsMeshType type = collisionMeshType == CollisionMeshType::Convex ?
  134. PhysicsMeshType::Convex : PhysicsMeshType::Triangle;
  135. SPtr<PhysicsMesh> physicsMesh = PhysicsMesh::_createPtr(rendererMeshData->getData(), type);
  136. output.push_back({ L"collision", physicsMesh });
  137. }
  138. else
  139. {
  140. LOGWRN("Cannot generate a collision mesh as the physics module was not started.");
  141. }
  142. }
  143. for(auto& entry : animationClips)
  144. {
  145. SPtr<AnimationClip> clip = AnimationClip::_createPtr(entry.second);
  146. output.push_back({ toWString(entry.first), clip });
  147. }
  148. }
  149. return output;
  150. }
  151. SPtr<RendererMeshData> FBXImporter::importMeshData(const Path& filePath, SPtr<const ImportOptions> importOptions,
  152. Vector<SubMesh>& subMeshes, UnorderedMap<String, SPtr<AnimationCurves>>& animation, SPtr<Skeleton>& skeleton)
  153. {
  154. FbxScene* fbxScene = nullptr;
  155. if (!startUpSdk(fbxScene))
  156. return nullptr;
  157. if (!loadFBXFile(fbxScene, filePath))
  158. return nullptr;
  159. const MeshImportOptions* meshImportOptions = static_cast<const MeshImportOptions*>(importOptions.get());
  160. FBXImportOptions fbxImportOptions;
  161. fbxImportOptions.importNormals = meshImportOptions->getImportNormals();
  162. fbxImportOptions.importTangents = meshImportOptions->getImportTangents();
  163. fbxImportOptions.importAnimation = meshImportOptions->getImportAnimation();
  164. fbxImportOptions.importBlendShapes = meshImportOptions->getImportBlendShapes();
  165. fbxImportOptions.importSkin = meshImportOptions->getImportSkin();
  166. fbxImportOptions.importScale = meshImportOptions->getImportScale();
  167. FBXImportScene importedScene;
  168. parseScene(fbxScene, fbxImportOptions, importedScene);
  169. if (fbxImportOptions.importBlendShapes)
  170. importBlendShapes(importedScene, fbxImportOptions);
  171. if (fbxImportOptions.importSkin)
  172. importSkin(importedScene);
  173. if (fbxImportOptions.importAnimation)
  174. importAnimations(fbxScene, fbxImportOptions, importedScene);
  175. splitMeshVertices(importedScene);
  176. generateMissingTangentSpace(importedScene, fbxImportOptions);
  177. SPtr<RendererMeshData> rendererMeshData = generateMeshData(importedScene, fbxImportOptions, subMeshes, skeleton);
  178. // Import animation clips
  179. if (!importedScene.clips.empty())
  180. {
  181. Vector<AnimationSplitInfo> splits = meshImportOptions->getAnimationClipSplits();
  182. convertAnimations(importedScene.clips, splits, animation);
  183. }
  184. // TODO - Later: Optimize mesh: Remove bad and degenerate polygons, weld nearby vertices, optimize for vertex cache
  185. shutDownSdk();
  186. return rendererMeshData;
  187. }
  188. bool FBXImporter::startUpSdk(FbxScene*& scene)
  189. {
  190. mFBXManager = FbxManager::Create();
  191. if (mFBXManager == nullptr)
  192. {
  193. LOGERR("FBX import failed: FBX SDK failed to initialize. FbxManager::Create() failed.");
  194. return false;
  195. }
  196. FbxIOSettings* ios = FbxIOSettings::Create(mFBXManager, IOSROOT);
  197. mFBXManager->SetIOSettings(ios);
  198. scene = FbxScene::Create(mFBXManager, "Import Scene");
  199. if (scene == nullptr)
  200. {
  201. LOGWRN("FBX import failed: Failed to create FBX scene.");
  202. return false;
  203. }
  204. return true;
  205. }
  206. void FBXImporter::shutDownSdk()
  207. {
  208. mFBXManager->Destroy();
  209. mFBXManager = nullptr;
  210. }
  211. bool FBXImporter::loadFBXFile(FbxScene* scene, const Path& filePath)
  212. {
  213. int lFileMajor, lFileMinor, lFileRevision;
  214. int lSDKMajor, lSDKMinor, lSDKRevision;
  215. FbxManager::GetFileFormatVersion(lSDKMajor, lSDKMinor, lSDKRevision);
  216. FbxImporter* importer = FbxImporter::Create(mFBXManager, "");
  217. bool importStatus = importer->Initialize(filePath.toString().c_str(), -1, mFBXManager->GetIOSettings());
  218. importer->GetFileVersion(lFileMajor, lFileMinor, lFileRevision);
  219. if(!importStatus)
  220. {
  221. LOGERR("FBX import failed: Call to FbxImporter::Initialize() failed.\n" +
  222. String("Error returned: %s\n\n") + String(importer->GetStatus().GetErrorString()));
  223. return false;
  224. }
  225. mFBXManager->GetIOSettings()->SetBoolProp(IMP_FBX_TEXTURE, false);
  226. mFBXManager->GetIOSettings()->SetBoolProp(IMP_FBX_GOBO, false);
  227. importStatus = importer->Import(scene);
  228. if(!importStatus)
  229. {
  230. importer->Destroy();
  231. LOGERR("FBX import failed: Call to FbxImporter::Import() failed.\n" +
  232. String("Error returned: %s\n\n") + String(importer->GetStatus().GetErrorString()));
  233. return false;
  234. }
  235. FbxAxisSystem fileCoordSystem = scene->GetGlobalSettings().GetAxisSystem();
  236. FbxAxisSystem bsCoordSystem(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eRightHanded);
  237. if (fileCoordSystem != bsCoordSystem)
  238. bsCoordSystem.ConvertScene(scene);
  239. importer->Destroy();
  240. return true;
  241. }
  242. void FBXImporter::parseScene(FbxScene* scene, const FBXImportOptions& options, FBXImportScene& outputScene)
  243. {
  244. outputScene.rootNode = createImportNode(outputScene, scene->GetRootNode(), nullptr);
  245. Stack<FbxNode*> todo;
  246. todo.push(scene->GetRootNode());
  247. while(!todo.empty())
  248. {
  249. FbxNode* curNode = todo.top();
  250. FBXImportNode* curImportNode = outputScene.nodeMap[curNode];
  251. todo.pop();
  252. FbxNodeAttribute* attrib = curNode->GetNodeAttribute();
  253. if(attrib != nullptr)
  254. {
  255. FbxNodeAttribute::EType attribType = attrib->GetAttributeType();
  256. switch(attribType)
  257. {
  258. case FbxNodeAttribute::eNurbs:
  259. case FbxNodeAttribute::eNurbsSurface:
  260. case FbxNodeAttribute::ePatch:
  261. {
  262. FbxGeometryConverter geomConverter(mFBXManager);
  263. attrib = geomConverter.Triangulate(attrib, true);
  264. if (attrib->GetAttributeType() == FbxNodeAttribute::eMesh)
  265. {
  266. FbxMesh* mesh = static_cast<FbxMesh*>(attrib);
  267. mesh->RemoveBadPolygons();
  268. parseMesh(mesh, curImportNode, options, outputScene);
  269. }
  270. }
  271. break;
  272. case FbxNodeAttribute::eMesh:
  273. {
  274. FbxMesh* mesh = static_cast<FbxMesh*>(attrib);
  275. mesh->RemoveBadPolygons();
  276. if(!mesh->IsTriangleMesh())
  277. {
  278. FbxGeometryConverter geomConverter(mFBXManager);
  279. geomConverter.Triangulate(mesh, true);
  280. attrib = curNode->GetNodeAttribute();
  281. mesh = static_cast<FbxMesh*>(attrib);
  282. }
  283. parseMesh(mesh, curImportNode, options, outputScene);
  284. }
  285. break;
  286. default:
  287. break;
  288. }
  289. }
  290. for (int i = 0; i < curNode->GetChildCount(); i++)
  291. {
  292. FbxNode* childNode = curNode->GetChild(i);
  293. createImportNode(outputScene, childNode, curImportNode);
  294. todo.push(childNode);
  295. }
  296. }
  297. }
  298. FBXImportNode* FBXImporter::createImportNode(FBXImportScene& scene, FbxNode* fbxNode, FBXImportNode* parent)
  299. {
  300. FBXImportNode* node = bs_new<FBXImportNode>();
  301. Vector3 translation = FBXToNativeType(fbxNode->LclTranslation.Get());
  302. Vector3 rotationEuler = FBXToNativeType(fbxNode->LclRotation.Get());
  303. Vector3 scale = FBXToNativeType(fbxNode->LclScaling.Get());
  304. Quaternion rotation((Radian)rotationEuler.x, (Radian)rotationEuler.y, (Radian)rotationEuler.z);
  305. node->localTransform.setTRS(translation, rotation, scale);
  306. node->name = fbxNode->GetNameWithoutNameSpacePrefix().Buffer();
  307. node->fbxNode = fbxNode;
  308. if (parent != nullptr)
  309. {
  310. node->worldTransform = node->localTransform * parent->worldTransform;
  311. parent->children.push_back(node);
  312. }
  313. else
  314. node->worldTransform = node->localTransform;
  315. scene.nodeMap.insert(std::make_pair(fbxNode, node));
  316. return node;
  317. }
  318. void FBXImporter::splitMeshVertices(FBXImportScene& scene)
  319. {
  320. Vector<FBXImportMesh*> splitMeshes;
  321. for (auto& mesh : scene.meshes)
  322. {
  323. FBXImportMesh* splitMesh = bs_new<FBXImportMesh>();
  324. splitMesh->fbxMesh = mesh->fbxMesh;
  325. splitMesh->referencedBy = mesh->referencedBy;
  326. splitMesh->bones = mesh->bones;
  327. FBXUtility::splitVertices(*mesh, *splitMesh);
  328. FBXUtility::flipWindingOrder(*splitMesh);
  329. splitMeshes.push_back(splitMesh);
  330. bs_delete(mesh);
  331. }
  332. scene.meshes = splitMeshes;
  333. }
  334. void FBXImporter::convertAnimations(const Vector<FBXAnimationClip>& clips, const Vector<AnimationSplitInfo>& splits,
  335. UnorderedMap<String, SPtr<AnimationCurves>>& output)
  336. {
  337. bool isFirstClip = true;
  338. for (auto& clip : clips)
  339. {
  340. SPtr<AnimationCurves> curves = bs_shared_ptr_new<AnimationCurves>();
  341. for (auto& bone : clip.boneAnimations)
  342. {
  343. // Translation curves
  344. {
  345. assert((bone.translation[0].keyframes.size() == bone.translation[1].keyframes.size()) &&
  346. (bone.translation[0].keyframes.size() == bone.translation[2].keyframes.size()));
  347. UINT32 numKeyframes = (UINT32)bone.translation[0].keyframes.size();
  348. Vector <TKeyframe<Vector3>> keyFrames(numKeyframes);
  349. for (UINT32 i = 0; i < numKeyframes; i++)
  350. {
  351. const FBXKeyFrame& keyFrameX = bone.translation[0].keyframes[i];
  352. const FBXKeyFrame& keyFrameY = bone.translation[1].keyframes[i];
  353. const FBXKeyFrame& keyFrameZ = bone.translation[2].keyframes[i];
  354. keyFrames[i].value = Vector3(keyFrameX.value, keyFrameY.value, keyFrameZ.value);
  355. assert((keyFrameX.time == keyFrameY.time) && (keyFrameX.time == keyFrameZ.time));
  356. keyFrames[i].time = keyFrameX.time;
  357. keyFrames[i].inTangent = Vector3(keyFrameX.inTangent, keyFrameY.inTangent, keyFrameZ.inTangent);
  358. keyFrames[i].outTangent = Vector3(keyFrameX.outTangent, keyFrameY.outTangent, keyFrameZ.outTangent);
  359. }
  360. curves->position.push_back({ bone.node->name, keyFrames });
  361. }
  362. // Rotation curves
  363. {
  364. assert((bone.rotation[0].keyframes.size() == bone.rotation[1].keyframes.size()) &&
  365. (bone.rotation[0].keyframes.size() == bone.rotation[2].keyframes.size()) &&
  366. (bone.rotation[0].keyframes.size() == bone.rotation[3].keyframes.size()));
  367. UINT32 numKeyframes = (UINT32)bone.rotation[0].keyframes.size();
  368. Vector <TKeyframe<Quaternion>> keyFrames(numKeyframes);
  369. for (UINT32 i = 0; i < numKeyframes; i++)
  370. {
  371. const FBXKeyFrame& keyFrameW = bone.rotation[0].keyframes[i];
  372. const FBXKeyFrame& keyFrameX = bone.rotation[1].keyframes[i];
  373. const FBXKeyFrame& keyFrameY = bone.rotation[2].keyframes[i];
  374. const FBXKeyFrame& keyFrameZ = bone.rotation[3].keyframes[i];
  375. keyFrames[i].value = Quaternion(keyFrameW.value, keyFrameX.value, keyFrameY.value, keyFrameZ.value);
  376. assert((keyFrameX.time == keyFrameY.time) && (keyFrameX.time == keyFrameZ.time) && (keyFrameX.time == keyFrameW.time));
  377. keyFrames[i].time = keyFrameX.time;
  378. keyFrames[i].inTangent = Quaternion(keyFrameW.inTangent, keyFrameX.inTangent, keyFrameY.inTangent, keyFrameZ.inTangent);
  379. keyFrames[i].outTangent = Quaternion(keyFrameW.outTangent, keyFrameX.outTangent, keyFrameY.outTangent, keyFrameZ.outTangent);
  380. }
  381. curves->rotation.push_back({ bone.node->name, keyFrames });
  382. }
  383. // Scale curves
  384. {
  385. assert((bone.scale[0].keyframes.size() == bone.scale[1].keyframes.size()) &&
  386. (bone.scale[0].keyframes.size() == bone.scale[2].keyframes.size()));
  387. UINT32 numKeyframes = (UINT32)bone.scale[0].keyframes.size();
  388. Vector <TKeyframe<Vector3>> keyFrames(numKeyframes);
  389. for (UINT32 i = 0; i < numKeyframes; i++)
  390. {
  391. const FBXKeyFrame& keyFrameX = bone.scale[0].keyframes[i];
  392. const FBXKeyFrame& keyFrameY = bone.scale[1].keyframes[i];
  393. const FBXKeyFrame& keyFrameZ = bone.scale[2].keyframes[i];
  394. keyFrames[i].value = Vector3(keyFrameX.value, keyFrameY.value, keyFrameZ.value);
  395. assert((keyFrameX.time == keyFrameY.time) && (keyFrameX.time == keyFrameZ.time));
  396. keyFrames[i].time = keyFrameX.time;
  397. keyFrames[i].inTangent = Vector3(keyFrameX.inTangent, keyFrameY.inTangent, keyFrameZ.inTangent);
  398. keyFrames[i].outTangent = Vector3(keyFrameX.outTangent, keyFrameY.outTangent, keyFrameZ.outTangent);
  399. }
  400. curves->scale.push_back({ bone.node->name, keyFrames });
  401. }
  402. }
  403. // See if any splits are required. We only split the first clip as it is assumed if FBX has multiple clips the
  404. // user has the ability to split them externally.
  405. if(isFirstClip && !splits.empty())
  406. {
  407. for(auto& split : splits)
  408. {
  409. SPtr<AnimationCurves> splitClipCurve = bs_shared_ptr_new<AnimationCurves>();
  410. auto splitCurves = [&](auto& inCurves, auto& outCurves)
  411. {
  412. UINT32 numCurves = inCurves.size();
  413. outCurves.resize(numCurves);
  414. for (UINT32 i = 0; i < numCurves; i++)
  415. {
  416. TAnimationCurve<Vector3>& animCurve = inCurves[i].curve;
  417. outCurves[i].name = inCurves[i].name;
  418. UINT32 numFrames = animCurve.getNumKeyFrames();
  419. if (numFrames == 0)
  420. continue;
  421. UINT32 lastFrame = numFrames - 1;
  422. float startTime = animCurve.getKeyFrame(std::min(split.startFrame, lastFrame)).time;
  423. float endTime = animCurve.getKeyFrame(std::min(split.endFrame, lastFrame)).time;
  424. outCurves[i].curve = inCurves->position[i].curve.split(startTime, endTime);
  425. if (split.isAdditive)
  426. outCurves[i].curve->makeAdditive();
  427. }
  428. };
  429. splitCurves(curves->position, splitClipCurve->position);
  430. splitCurves(curves->rotation, splitClipCurve->rotation);
  431. splitCurves(curves->scale, splitClipCurve->scale);
  432. splitCurves(curves->generic, splitClipCurve->generic);
  433. // Search for a unique name
  434. String name = split.name;
  435. UINT32 attemptIdx = 0;
  436. while (output.find(name) != output.end())
  437. {
  438. name = clip.name + "_" + toString(attemptIdx);
  439. attemptIdx++;
  440. }
  441. output.insert(std::make_pair(name, splitClipCurve));
  442. }
  443. }
  444. else
  445. {
  446. // Search for a unique name
  447. String name = clip.name;
  448. UINT32 attemptIdx = 0;
  449. while(output.find(name) != output.end())
  450. {
  451. name = clip.name + "_" + toString(attemptIdx);
  452. attemptIdx++;
  453. }
  454. output.insert(std::make_pair(name, curves));
  455. }
  456. isFirstClip = false;
  457. }
  458. }
  459. SPtr<RendererMeshData> FBXImporter::generateMeshData(const FBXImportScene& scene, const FBXImportOptions& options,
  460. Vector<SubMesh>& outputSubMeshes, SPtr<Skeleton>& outputSkeleton)
  461. {
  462. Matrix4 importScale = Matrix4::scaling(options.importScale);
  463. Vector<SPtr<MeshData>> allMeshData;
  464. Vector<Vector<SubMesh>> allSubMeshes;
  465. Vector<BONE_DESC> allBones;
  466. UnorderedMap<FBXImportNode*, UINT32> boneMap;
  467. UINT32 boneIndexOffset = 0;
  468. for (auto& mesh : scene.meshes)
  469. {
  470. Vector<Vector<UINT32>> indicesPerMaterial;
  471. for (UINT32 i = 0; i < (UINT32)mesh->indices.size(); i++)
  472. {
  473. while ((UINT32)mesh->materials[i] >= (UINT32)indicesPerMaterial.size())
  474. indicesPerMaterial.push_back(Vector<UINT32>());
  475. indicesPerMaterial[mesh->materials[i]].push_back(mesh->indices[i]);
  476. }
  477. UINT32* orderedIndices = (UINT32*)bs_alloc((UINT32)mesh->indices.size() * sizeof(UINT32));
  478. Vector<SubMesh> subMeshes;
  479. UINT32 currentIndex = 0;
  480. for (auto& subMeshIndices : indicesPerMaterial)
  481. {
  482. UINT32 indexCount = (UINT32)subMeshIndices.size();
  483. UINT32* dest = orderedIndices + currentIndex;
  484. memcpy(dest, subMeshIndices.data(), indexCount * sizeof(UINT32));
  485. subMeshes.push_back(SubMesh(currentIndex, indexCount, DOT_TRIANGLE_LIST));
  486. currentIndex += indexCount;
  487. }
  488. UINT32 vertexLayout = (UINT32)VertexLayout::Position;
  489. size_t numVertices = mesh->positions.size();
  490. bool hasColors = mesh->colors.size() == numVertices;
  491. bool hasNormals = mesh->normals.size() == numVertices;
  492. bool hasBoneInfluences = mesh->boneInfluences.size() == numVertices;
  493. if (hasColors)
  494. vertexLayout |= (UINT32)VertexLayout::Color;
  495. bool hasTangents = false;
  496. if (hasNormals)
  497. {
  498. vertexLayout |= (UINT32)VertexLayout::Normal;
  499. if (mesh->tangents.size() == numVertices &&
  500. mesh->bitangents.size() == numVertices)
  501. {
  502. vertexLayout |= (UINT32)VertexLayout::Tangent;
  503. hasTangents = true;
  504. }
  505. }
  506. if (hasBoneInfluences)
  507. vertexLayout |= (UINT32)VertexLayout::BoneWeights;
  508. for (UINT32 i = 0; i < FBX_IMPORT_MAX_UV_LAYERS; i++)
  509. {
  510. if (mesh->UV[i].size() == numVertices)
  511. {
  512. if (i == 0)
  513. vertexLayout |= (UINT32)VertexLayout::UV0;
  514. else if (i == 1)
  515. vertexLayout |= (UINT32)VertexLayout::UV1;
  516. }
  517. }
  518. UINT32 numIndices = (UINT32)mesh->indices.size();
  519. for (auto& node : mesh->referencedBy)
  520. {
  521. Matrix4 worldTransform = node->worldTransform * importScale;
  522. Matrix4 worldTransformIT = worldTransform.transpose();
  523. worldTransformIT = worldTransformIT.inverse();
  524. SPtr<RendererMeshData> meshData = RendererMeshData::create((UINT32)numVertices, numIndices, (VertexLayout)vertexLayout);
  525. // Copy indices
  526. meshData->setIndices((UINT32*)mesh->indices.data(), numIndices * sizeof(UINT32));
  527. // Copy & transform positions
  528. UINT32 positionsSize = sizeof(Vector3) * (UINT32)numVertices;
  529. Vector3* transformedPositions = (Vector3*)bs_stack_alloc(positionsSize);
  530. for (UINT32 i = 0; i < (UINT32)numVertices; i++)
  531. transformedPositions[i] = worldTransform.multiplyAffine((Vector3)mesh->positions[i]);
  532. meshData->setPositions(transformedPositions, positionsSize);
  533. bs_stack_free(transformedPositions);
  534. // Copy & transform normals
  535. if (hasNormals)
  536. {
  537. UINT32 normalsSize = sizeof(Vector3) * (UINT32)numVertices;
  538. Vector3* transformedNormals = (Vector3*)bs_stack_alloc(normalsSize);
  539. // Copy, convert & transform tangents & bitangents
  540. if (hasTangents)
  541. {
  542. UINT32 tangentsSize = sizeof(Vector4) * (UINT32)numVertices;
  543. Vector4* transformedTangents = (Vector4*)bs_stack_alloc(tangentsSize);
  544. for (UINT32 i = 0; i < (UINT32)numVertices; i++)
  545. {
  546. Vector3 normal = (Vector3)mesh->normals[i];
  547. normal = worldTransformIT.multiplyDirection(normal);
  548. transformedNormals[i] = Vector3::normalize(normal);
  549. Vector3 tangent = (Vector3)mesh->tangents[i];
  550. tangent = Vector3::normalize(worldTransformIT.multiplyDirection(tangent));
  551. Vector3 bitangent = (Vector3)mesh->bitangents[i];
  552. bitangent = worldTransformIT.multiplyDirection(bitangent);
  553. Vector3 engineBitangent = Vector3::cross(normal, tangent);
  554. float sign = Vector3::dot(engineBitangent, bitangent);
  555. transformedTangents[i] = Vector4(tangent.x, tangent.y, tangent.z, sign > 0 ? 1.0f : -1.0f);
  556. }
  557. meshData->setTangents(transformedTangents, tangentsSize);
  558. bs_stack_free(transformedTangents);
  559. }
  560. else // Just normals
  561. {
  562. for (UINT32 i = 0; i < (UINT32)numVertices; i++)
  563. transformedNormals[i] = Vector3::normalize(worldTransformIT.multiplyDirection((Vector3)mesh->normals[i]));
  564. }
  565. meshData->setNormals(transformedNormals, normalsSize);
  566. bs_stack_free(transformedNormals);
  567. }
  568. // Copy colors
  569. if (hasColors)
  570. {
  571. meshData->setColors(mesh->colors.data(), sizeof(UINT32) * (UINT32)numVertices);
  572. }
  573. // Copy UV
  574. int writeUVIDx = 0;
  575. for (auto& uvLayer : mesh->UV)
  576. {
  577. if (uvLayer.size() == numVertices)
  578. {
  579. UINT32 size = sizeof(Vector2) * (UINT32)numVertices;
  580. Vector2* transformedUV = (Vector2*)bs_stack_alloc(size);
  581. UINT32 i = 0;
  582. for (auto& uv : uvLayer)
  583. {
  584. transformedUV[i] = uv;
  585. transformedUV[i].y = 1.0f - uv.y;
  586. i++;
  587. }
  588. if (writeUVIDx == 0)
  589. meshData->setUV0(transformedUV, size);
  590. else if (writeUVIDx == 1)
  591. meshData->setUV1(transformedUV, size);
  592. bs_stack_free(transformedUV);
  593. writeUVIDx++;
  594. }
  595. }
  596. // Copy bone influences
  597. if(hasBoneInfluences)
  598. {
  599. UINT32 bufferSize = sizeof(BoneWeight) * (UINT32)numVertices;
  600. BoneWeight* weights = (BoneWeight*)bs_stack_alloc(bufferSize);
  601. for(UINT32 i = 0; i < (UINT32)numVertices; i++)
  602. {
  603. weights[i].index0 = mesh->boneInfluences[i].indices[0] + boneIndexOffset;
  604. weights[i].index1 = mesh->boneInfluences[i].indices[1] + boneIndexOffset;
  605. weights[i].index2 = mesh->boneInfluences[i].indices[2] + boneIndexOffset;
  606. weights[i].index3 = mesh->boneInfluences[i].indices[3] + boneIndexOffset;
  607. weights[i].weight0 = mesh->boneInfluences[i].weights[0];
  608. weights[i].weight1 = mesh->boneInfluences[i].weights[1];
  609. weights[i].weight2 = mesh->boneInfluences[i].weights[2];
  610. weights[i].weight3 = mesh->boneInfluences[i].weights[3];
  611. }
  612. meshData->setBoneWeights(weights, bufferSize);
  613. bs_stack_free(weights);
  614. }
  615. // TODO - Transform blend shapes?
  616. allMeshData.push_back(meshData->getData());
  617. allSubMeshes.push_back(subMeshes);
  618. }
  619. // Create bones
  620. UINT32 numBones = (UINT32)mesh->bones.size();
  621. for(auto& fbxBone : mesh->bones)
  622. {
  623. UINT32 boneIdx = (UINT32)allBones.size();
  624. boneMap[fbxBone.node] = boneIdx;
  625. allBones.push_back(BONE_DESC());
  626. BONE_DESC& bone = allBones.back();
  627. bone.name = fbxBone.node->name;
  628. bone.invBindPose = fbxBone.bindPose;
  629. }
  630. boneIndexOffset += numBones;
  631. }
  632. // Generate skeleton
  633. if (allBones.size() > 0)
  634. {
  635. // Find bone parents
  636. UINT32 numProcessedBones = 0;
  637. // Generate common root bone for all meshes
  638. UINT32 rootBoneIdx = (UINT32)-1;
  639. if(allMeshData.size() > 1)
  640. {
  641. rootBoneIdx = (UINT32)allBones.size();
  642. allBones.push_back(BONE_DESC());
  643. BONE_DESC& bone = allBones.back();
  644. bone.name = "MultiMeshRoot";
  645. bone.invBindPose = Matrix4::IDENTITY;
  646. bone.parent = (UINT32)-1;
  647. numProcessedBones++;
  648. }
  649. Stack<std::pair<FBXImportNode*, UINT32>> todo;
  650. todo.push({ scene.rootNode, rootBoneIdx });
  651. while(!todo.empty())
  652. {
  653. auto entry = todo.top();
  654. todo.pop();
  655. FBXImportNode* node = entry.first;
  656. UINT32 parentBoneIdx = entry.second;
  657. auto boneIter = boneMap.find(node);
  658. if (boneIter != boneMap.end())
  659. {
  660. UINT32 boneIdx = boneIter->second;
  661. allBones[boneIdx].parent = parentBoneIdx;
  662. numProcessedBones++;
  663. parentBoneIdx = boneIdx;
  664. }
  665. for (auto& child : node->children)
  666. todo.push({ child, parentBoneIdx });
  667. }
  668. UINT32 numAllBones = (UINT32)allBones.size();
  669. if (numProcessedBones == numAllBones)
  670. outputSkeleton = Skeleton::create(allBones.data(), numAllBones);
  671. else
  672. LOGERR("Not all bones were found in the node hierarchy. Skeleton invalid.");
  673. }
  674. if (allMeshData.size() > 1)
  675. {
  676. return RendererMeshData::create(MeshData::combine(allMeshData, allSubMeshes, outputSubMeshes));
  677. }
  678. else if (allMeshData.size() == 1)
  679. {
  680. outputSubMeshes = allSubMeshes[0];
  681. return RendererMeshData::create(allMeshData[0]);
  682. }
  683. return nullptr;
  684. }
  685. template<class TFBX, class TNative>
  686. class FBXDirectIndexer
  687. {
  688. public:
  689. FBXDirectIndexer(const FbxLayerElementTemplate<TFBX>& layer)
  690. :mElementArray(layer.GetDirectArray()),
  691. mElementCount(mElementArray.GetCount())
  692. {}
  693. bool get(int index, TNative& output) const
  694. {
  695. if (index < 0 || index >= mElementCount)
  696. return false;
  697. output = FBXToNativeType(mElementArray.GetAt(index));
  698. return true;
  699. }
  700. bool isEmpty() const
  701. {
  702. return mElementCount == 0;
  703. }
  704. private:
  705. const FbxLayerElementArrayTemplate<TFBX>& mElementArray;
  706. int mElementCount;
  707. };
  708. template<class TFBX, class TNative>
  709. class FBXIndexIndexer
  710. {
  711. public:
  712. FBXIndexIndexer(const FbxLayerElementTemplate<TFBX>& layer)
  713. :mElementArray(layer.GetDirectArray()),
  714. mIndexArray(layer.GetIndexArray()),
  715. mElementCount(mElementArray.GetCount()),
  716. mIndexCount(mIndexArray.GetCount())
  717. {}
  718. bool get(int index, TNative& output) const
  719. {
  720. if (index < 0 || index >= mIndexCount)
  721. return false;
  722. int actualIndex = mIndexArray.GetAt(index);
  723. if (actualIndex < 0 || actualIndex >= mElementCount)
  724. return false;
  725. output = FBXToNativeType(mElementArray.GetAt(actualIndex));
  726. return true;
  727. }
  728. bool isEmpty() const
  729. {
  730. return mElementCount == 0 || mIndexCount == 0;
  731. }
  732. private:
  733. const FbxLayerElementArrayTemplate<TFBX>& mElementArray;
  734. const FbxLayerElementArrayTemplate<int>& mIndexArray;
  735. int mElementCount;
  736. int mIndexCount;
  737. };
  738. template<class TFBX, class TNative, class TIndexer>
  739. void readLayerData(FbxLayerElementTemplate<TFBX>& layer, Vector<TNative>& output, const Vector<int>& indices)
  740. {
  741. TIndexer indexer(layer);
  742. if (indexer.isEmpty())
  743. return;
  744. output.resize(indices.size());
  745. FbxLayerElement::EMappingMode mappingMode = layer.GetMappingMode();
  746. UINT32 indexCount = (UINT32)indices.size();
  747. switch (mappingMode)
  748. {
  749. case FbxLayerElement::eByControlPoint:
  750. for (UINT32 i = 0; i < indexCount; i++)
  751. {
  752. int index = indices[i];
  753. indexer.get(index, output[i]);
  754. }
  755. break;
  756. case FbxLayerElement::eByPolygonVertex:
  757. for (UINT32 i = 0; i < indexCount; i++)
  758. indexer.get(i, output[i]);
  759. break;
  760. case FbxLayerElement::eByPolygon:
  761. // We expect mesh to be triangulated here
  762. {
  763. UINT32 polygonCount = indexCount / 3;
  764. UINT32 index = 0;
  765. for (UINT32 i = 0; i < polygonCount; i++)
  766. {
  767. TNative value;
  768. indexer.get(i, value);
  769. output[index++] = value;
  770. output[index++] = value;
  771. output[index++] = value;
  772. }
  773. }
  774. break;
  775. case FbxLayerElement::eAllSame:
  776. {
  777. TNative value;
  778. indexer.get(0, value);
  779. for (UINT32 i = 0; i < indexCount; i++)
  780. output[i] = value;
  781. }
  782. break;
  783. default:
  784. LOGWRN("FBX Import: Unsupported layer mapping mode.");
  785. break;
  786. }
  787. }
  788. template<class TFBX, class TNative>
  789. void readLayerData(FbxLayerElementTemplate<TFBX>& layer, Vector<TNative>& output, const Vector<int>& indices)
  790. {
  791. FbxLayerElement::EReferenceMode refMode = layer.GetReferenceMode();
  792. if (refMode == FbxLayerElement::eDirect)
  793. readLayerData<TFBX, TNative, FBXDirectIndexer<TFBX, TNative> >(layer, output, indices);
  794. else if (refMode == FbxLayerElement::eIndexToDirect)
  795. readLayerData<TFBX, TNative, FBXIndexIndexer<TFBX, TNative> >(layer, output, indices);
  796. else
  797. LOGWRN("FBX Import: Unsupported layer reference mode.");
  798. }
  799. void FBXImporter::parseMesh(FbxMesh* mesh, FBXImportNode* parentNode, const FBXImportOptions& options, FBXImportScene& outputScene)
  800. {
  801. // Check if valid
  802. if (!mesh->IsTriangleMesh())
  803. return;
  804. UINT32 vertexCount = mesh->GetControlPointsCount();
  805. UINT32 triangleCount = mesh->GetPolygonCount();
  806. if (vertexCount == 0 || triangleCount == 0)
  807. return;
  808. // Register in global mesh array
  809. FBXImportMesh* importMesh = nullptr;
  810. auto iterFindMesh = outputScene.meshMap.find(mesh);
  811. if (iterFindMesh != outputScene.meshMap.end())
  812. {
  813. UINT32 meshIdx = iterFindMesh->second;
  814. outputScene.meshes[meshIdx]->referencedBy.push_back(parentNode);
  815. return;
  816. }
  817. else
  818. {
  819. importMesh = bs_new<FBXImportMesh>();
  820. outputScene.meshes.push_back(importMesh);
  821. importMesh->referencedBy.push_back(parentNode);
  822. importMesh->fbxMesh = mesh;
  823. outputScene.meshMap[mesh] = (UINT32)outputScene.meshes.size() - 1;
  824. }
  825. // Import vertices
  826. importMesh->positions.resize(vertexCount);
  827. FbxVector4* controlPoints = mesh->GetControlPoints();
  828. for (UINT32 i = 0; i < vertexCount; i++)
  829. importMesh->positions[i] = FBXToNativeType(controlPoints[i]);
  830. // Import triangles
  831. UINT32 indexCount = triangleCount * 3;
  832. importMesh->indices.resize(indexCount);
  833. int* fbxIndices = mesh->GetPolygonVertices();
  834. importMesh->indices.assign(fbxIndices, fbxIndices + indexCount);
  835. // Import UVs
  836. Vector<FbxLayerElementUV*> fbxUVLayers;
  837. //// Search the diffuse layers first
  838. for (UINT32 i = 0; i < FBX_IMPORT_MAX_UV_LAYERS; i++)
  839. {
  840. FbxLayer* layer = mesh->GetLayer(i, FbxLayerElement::eUV);
  841. if (layer == nullptr)
  842. continue;
  843. for (int j = FbxLayerElement::eTextureDiffuse; j < FbxLayerElement::eTypeCount; j++)
  844. {
  845. FbxLayerElementUV* uvLayer = layer->GetUVs((FbxLayerElement::EType)j);
  846. if (uvLayer == nullptr)
  847. continue;
  848. fbxUVLayers.push_back(uvLayer);
  849. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  850. break;
  851. }
  852. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  853. break;
  854. }
  855. //// If there's room, search all others too
  856. if (fbxUVLayers.size() < FBX_IMPORT_MAX_UV_LAYERS)
  857. {
  858. UINT32 numLayers = mesh->GetLayerCount();
  859. for (UINT32 i = 0; i < numLayers; i++)
  860. {
  861. FbxLayer* layer = mesh->GetLayer(i);
  862. if (layer == nullptr)
  863. continue;
  864. for (int j = FbxLayerElement::eTextureDiffuse; j < FbxLayerElement::eTypeCount; j++)
  865. {
  866. FbxLayerElementUV* uvLayer = layer->GetUVs((FbxLayerElement::EType)j);
  867. if (uvLayer == nullptr)
  868. continue;
  869. auto iterFind = std::find(fbxUVLayers.begin(), fbxUVLayers.end(), uvLayer);
  870. if (iterFind != fbxUVLayers.end())
  871. continue;
  872. fbxUVLayers.push_back(uvLayer);
  873. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  874. break;
  875. }
  876. if (fbxUVLayers.size() == FBX_IMPORT_MAX_UV_LAYERS)
  877. break;
  878. }
  879. }
  880. for (size_t i = 0; i < fbxUVLayers.size(); i++)
  881. readLayerData(*fbxUVLayers[i], importMesh->UV[i], importMesh->indices);
  882. FbxLayer* mainLayer = mesh->GetLayer(0);
  883. if (mainLayer != nullptr)
  884. {
  885. // Import colors
  886. if (mainLayer->GetVertexColors() != nullptr)
  887. readLayerData(*mainLayer->GetVertexColors(), importMesh->colors, importMesh->indices);
  888. // Import normals
  889. if (options.importNormals)
  890. {
  891. bool hasNormals = mainLayer->GetNormals() != nullptr;
  892. if (!hasNormals)
  893. {
  894. if (mainLayer->GetSmoothing() != nullptr)
  895. {
  896. FbxLayerElementSmoothing* smoothing = mainLayer->GetSmoothing();
  897. if (smoothing->GetMappingMode() == FbxLayerElement::eByEdge)
  898. {
  899. FbxGeometryConverter converter(mFBXManager);
  900. converter.ComputePolygonSmoothingFromEdgeSmoothing(mesh, 0);
  901. }
  902. readLayerData(*smoothing, importMesh->smoothingGroups, importMesh->indices);
  903. if (!importMesh->smoothingGroups.empty())
  904. {
  905. FBXUtility::normalsFromSmoothing(importMesh->positions, importMesh->indices,
  906. importMesh->smoothingGroups, importMesh->normals);
  907. }
  908. }
  909. }
  910. else
  911. readLayerData(*mainLayer->GetNormals(), importMesh->normals, importMesh->indices);
  912. }
  913. // Import tangents
  914. if (options.importTangents)
  915. {
  916. bool hasTangents = mainLayer->GetTangents() != nullptr && mainLayer->GetBinormals() != nullptr;
  917. if (!hasTangents)
  918. {
  919. if (fbxUVLayers.size() > 0)
  920. hasTangents = mesh->GenerateTangentsData(0, false);
  921. }
  922. if (hasTangents)
  923. {
  924. readLayerData(*mainLayer->GetTangents(), importMesh->tangents, importMesh->indices);
  925. readLayerData(*mainLayer->GetBinormals(), importMesh->bitangents, importMesh->indices);
  926. }
  927. }
  928. // Import material indexes
  929. if (mainLayer->GetMaterials() != nullptr)
  930. {
  931. Vector<FbxSurfaceMaterial*> fbxMaterials;
  932. readLayerData(*mainLayer->GetMaterials(), fbxMaterials, importMesh->indices);
  933. UnorderedMap<FbxSurfaceMaterial*, int> materialLookup;
  934. int nextMaterialIdx = 0;
  935. for (UINT32 i = 0; i < (UINT32)fbxMaterials.size(); i++)
  936. {
  937. auto iterFind = materialLookup.find(fbxMaterials[i]);
  938. int materialIdx = 0;
  939. if (iterFind != materialLookup.end())
  940. materialIdx = iterFind->second;
  941. else
  942. {
  943. materialIdx = nextMaterialIdx++;
  944. materialLookup[fbxMaterials[i]] = materialIdx;
  945. }
  946. importMesh->materials.push_back(materialIdx);
  947. }
  948. }
  949. }
  950. }
  951. void FBXImporter::importBlendShapes(FBXImportScene& scene, const FBXImportOptions& options)
  952. {
  953. for (auto& mesh : scene.meshes)
  954. {
  955. FbxMesh* fbxMesh = mesh->fbxMesh;
  956. UINT32 deformerCount = (UINT32)fbxMesh->GetDeformerCount(FbxDeformer::eBlendShape);
  957. for (UINT32 i = 0; i < deformerCount; i++)
  958. {
  959. FbxBlendShape* deformer = static_cast<FbxBlendShape*>(fbxMesh->GetDeformer(i, FbxDeformer::eBlendShape));
  960. UINT32 blendShapeChannelCount = (UINT32)deformer->GetBlendShapeChannelCount();
  961. for (UINT32 j = 0; j < blendShapeChannelCount; ++j)
  962. {
  963. FbxBlendShapeChannel* channel = deformer->GetBlendShapeChannel(j);
  964. double* weights = channel->GetTargetShapeFullWeights();
  965. UINT32 frameCount = channel->GetTargetShapeCount();
  966. if (frameCount == 0)
  967. continue;
  968. mesh->blendShapes.push_back(FBXBlendShape());
  969. FBXBlendShape& blendShape = mesh->blendShapes.back();
  970. blendShape.name = channel->GetName();
  971. blendShape.frames.resize(frameCount);
  972. for (UINT32 k = 0; k < frameCount; k++)
  973. {
  974. FbxShape* fbxShape = channel->GetTargetShape(k);
  975. FBXBlendShapeFrame& frame = blendShape.frames[k];
  976. frame.weight = (float)weights[k];
  977. importBlendShapeFrame(fbxShape, *mesh, options, frame);
  978. }
  979. }
  980. }
  981. }
  982. }
  983. void FBXImporter::importBlendShapeFrame(FbxShape* shape, const FBXImportMesh& mesh, const FBXImportOptions& options, FBXBlendShapeFrame& outFrame)
  984. {
  985. UINT32 vertexCount = (UINT32)shape->GetControlPointsCount();
  986. outFrame.positions.resize(vertexCount);
  987. FbxVector4* controlPoints = shape->GetControlPoints();
  988. for (UINT32 i = 0; i < vertexCount; i++)
  989. outFrame.positions[i] = FBXToNativeType(controlPoints[i]);
  990. FbxLayer* mainLayer = shape->GetLayer(0);
  991. if (options.importNormals)
  992. {
  993. bool hasNormals = mainLayer->GetNormals() != nullptr;
  994. if (!hasNormals)
  995. {
  996. if (!mesh.smoothingGroups.empty())
  997. {
  998. FBXUtility::normalsFromSmoothing(outFrame.positions, mesh.indices,
  999. mesh.smoothingGroups, outFrame.normals);
  1000. }
  1001. }
  1002. else
  1003. readLayerData(*mainLayer->GetNormals(), outFrame.normals, mesh.indices);
  1004. }
  1005. if (options.importTangents)
  1006. {
  1007. bool hasTangents = mainLayer->GetTangents() != nullptr && mainLayer->GetBinormals() != nullptr;
  1008. if (hasTangents)
  1009. {
  1010. readLayerData(*mainLayer->GetTangents(), outFrame.tangents, mesh.indices);
  1011. readLayerData(*mainLayer->GetBinormals(), outFrame.bitangents, mesh.indices);
  1012. }
  1013. }
  1014. }
  1015. void FBXImporter::importSkin(FBXImportScene& scene)
  1016. {
  1017. for (auto& mesh : scene.meshes)
  1018. {
  1019. FbxMesh* fbxMesh = mesh->fbxMesh;
  1020. UINT32 deformerCount = (UINT32)fbxMesh->GetDeformerCount(FbxDeformer::eSkin);
  1021. if (deformerCount > 0)
  1022. {
  1023. // We ignore other deformers if there's more than one
  1024. FbxSkin* deformer = static_cast<FbxSkin*>(fbxMesh->GetDeformer(0, FbxDeformer::eSkin));
  1025. UINT32 boneCount = (UINT32)deformer->GetClusterCount();
  1026. if (boneCount == 0)
  1027. continue;
  1028. // If only one bone and it links to itself, ignore the bone
  1029. if (boneCount == 1)
  1030. {
  1031. FbxCluster* cluster = deformer->GetCluster(0);
  1032. if (mesh->referencedBy.size() == 1 && mesh->referencedBy[0]->fbxNode == cluster->GetLink())
  1033. continue;
  1034. }
  1035. importSkin(scene, deformer, *mesh);
  1036. }
  1037. }
  1038. }
  1039. void FBXImporter::importSkin(FBXImportScene& scene, FbxSkin* skin, FBXImportMesh& mesh)
  1040. {
  1041. Vector<FBXBoneInfluence>& influences = mesh.boneInfluences;
  1042. influences.resize(mesh.positions.size());
  1043. UnorderedSet<FbxNode*> existingBones;
  1044. UINT32 boneCount = (UINT32)skin->GetClusterCount();
  1045. for (UINT32 i = 0; i < boneCount; i++)
  1046. {
  1047. FbxCluster* cluster = skin->GetCluster(i);
  1048. FbxNode* link = cluster->GetLink();
  1049. // The bone node doesn't exist, skip it
  1050. auto iterFind = scene.nodeMap.find(link);
  1051. if (iterFind == scene.nodeMap.end())
  1052. continue;
  1053. mesh.bones.push_back(FBXBone());
  1054. FBXBone& bone = mesh.bones.back();
  1055. bone.node = iterFind->second;
  1056. FbxAMatrix clusterTransform;
  1057. cluster->GetTransformMatrix(clusterTransform);
  1058. FbxAMatrix linkTransform;
  1059. cluster->GetTransformLinkMatrix(linkTransform);
  1060. FbxAMatrix bindPose = linkTransform.Inverse() * clusterTransform;
  1061. bone.bindPose = FBXToNativeType(bindPose);
  1062. bool isDuplicate = !existingBones.insert(link).second;
  1063. bool isAdditive = cluster->GetLinkMode() == FbxCluster::eAdditive;
  1064. // We avoid importing weights twice for duplicate bones and we don't
  1065. // support additive link mode.
  1066. bool importWeights = !isDuplicate && !isAdditive;
  1067. if (!importWeights)
  1068. continue;
  1069. double* weights = cluster->GetControlPointWeights();
  1070. INT32* indices = cluster->GetControlPointIndices();
  1071. UINT32 numIndices = (UINT32)cluster->GetControlPointIndicesCount();
  1072. INT32 numVertices = (INT32)influences.size();
  1073. // Add new weights while keeping them in order and removing the smallest ones
  1074. // if number of influences exceeds the set maximum value
  1075. for (UINT32 j = 0; j < numIndices; j++)
  1076. {
  1077. INT32 vertexIndex = indices[j];
  1078. float weight = (float)weights[j];
  1079. for (INT32 k = 0; k < FBX_IMPORT_MAX_BONE_INFLUENCES; k++)
  1080. {
  1081. if (vertexIndex < 0 || vertexIndex >= numVertices)
  1082. continue;
  1083. if (weight >= influences[vertexIndex].weights[k])
  1084. {
  1085. for (INT32 l = FBX_IMPORT_MAX_BONE_INFLUENCES - 2; l >= k; l--)
  1086. {
  1087. influences[vertexIndex].weights[l + 1] = influences[vertexIndex].weights[l];
  1088. influences[vertexIndex].indices[l + 1] = influences[vertexIndex].indices[l];
  1089. }
  1090. influences[vertexIndex].weights[k] = weight;
  1091. influences[vertexIndex].indices[k] = i;
  1092. break;
  1093. }
  1094. }
  1095. }
  1096. }
  1097. if (mesh.bones.empty())
  1098. mesh.boneInfluences.clear();
  1099. UINT32 numBones = (UINT32)mesh.bones.size();
  1100. if (numBones > 256)
  1101. LOGWRN("A maximum of 256 bones per skeleton are supported. Imported skeleton has " + toString(numBones) + " bones");
  1102. // Normalize weights
  1103. UINT32 numInfluences = (UINT32)mesh.boneInfluences.size();
  1104. for (UINT32 i = 0; i < numInfluences; i++)
  1105. {
  1106. float sum = 0.0f;
  1107. for (UINT32 j = 0; j < FBX_IMPORT_MAX_BONE_INFLUENCES; j++)
  1108. sum += influences[i].weights[j];
  1109. float invSum = 1.0f / sum;
  1110. for (UINT32 j = 0; j < FBX_IMPORT_MAX_BONE_INFLUENCES; j++)
  1111. influences[i].weights[j] *= invSum;
  1112. }
  1113. }
  1114. void FBXImporter::generateMissingTangentSpace(FBXImportScene& scene, const FBXImportOptions& options)
  1115. {
  1116. for (auto& mesh : scene.meshes)
  1117. {
  1118. UINT32 numVertices = (UINT32)mesh->positions.size();
  1119. UINT32 numIndices = (UINT32)mesh->indices.size();
  1120. if ((options.importNormals || options.importTangents) && mesh->normals.empty())
  1121. {
  1122. mesh->normals.resize(numVertices);
  1123. MeshUtility::calculateNormals(mesh->positions.data(), (UINT8*)mesh->indices.data(), numVertices, numIndices, mesh->normals.data());
  1124. }
  1125. if (options.importTangents && !mesh->UV[0].empty() && (mesh->tangents.empty() || mesh->bitangents.empty()))
  1126. {
  1127. mesh->tangents.resize(numVertices);
  1128. mesh->bitangents.resize(numVertices);
  1129. MeshUtility::calculateTangents(mesh->positions.data(), mesh->normals.data(), mesh->UV[0].data(), (UINT8*)mesh->indices.data(),
  1130. numVertices, numIndices, mesh->tangents.data(), mesh->bitangents.data());
  1131. }
  1132. for (auto& shape : mesh->blendShapes)
  1133. {
  1134. for (auto& frame : shape.frames)
  1135. {
  1136. if ((options.importNormals || options.importTangents) && frame.normals.empty())
  1137. {
  1138. frame.normals.resize(numVertices);
  1139. MeshUtility::calculateNormals(mesh->positions.data(), (UINT8*)mesh->indices.data(), numVertices, numIndices, frame.normals.data());
  1140. }
  1141. if (options.importTangents && !mesh->UV[0].empty() && (frame.tangents.empty() || frame.bitangents.empty()))
  1142. {
  1143. mesh->tangents.resize(numVertices);
  1144. mesh->bitangents.resize(numVertices);
  1145. MeshUtility::calculateTangents(mesh->positions.data(), frame.normals.data(), mesh->UV[0].data(), (UINT8*)mesh->indices.data(),
  1146. numVertices, numIndices, frame.tangents.data(), frame.bitangents.data());
  1147. }
  1148. }
  1149. }
  1150. }
  1151. }
  1152. void FBXImporter::importAnimations(FbxScene* scene, FBXImportOptions& importOptions, FBXImportScene& importScene)
  1153. {
  1154. FbxNode* root = scene->GetRootNode();
  1155. UINT32 numAnimStacks = (UINT32)scene->GetSrcObjectCount<FbxAnimStack>();
  1156. for (UINT32 i = 0; i < numAnimStacks; i++)
  1157. {
  1158. FbxAnimStack* animStack = scene->GetSrcObject<FbxAnimStack>(i);
  1159. importScene.clips.push_back(FBXAnimationClip());
  1160. FBXAnimationClip& clip = importScene.clips.back();
  1161. clip.name = animStack->GetName();
  1162. FbxTimeSpan timeSpan = animStack->GetLocalTimeSpan();
  1163. clip.start = (float)timeSpan.GetStart().GetSecondDouble();
  1164. clip.end = (float)timeSpan.GetStop().GetSecondDouble();
  1165. UINT32 layerCount = animStack->GetMemberCount<FbxAnimLayer>();
  1166. if (layerCount > 1)
  1167. {
  1168. FbxAnimEvaluator* evaluator = scene->GetAnimationEvaluator();
  1169. FbxTime startTime;
  1170. startTime.SetSecondDouble(clip.start);
  1171. FbxTime endTime;
  1172. endTime.SetSecondDouble(clip.end);
  1173. FbxTime sampleRate;
  1174. if (importOptions.animResample)
  1175. sampleRate.SetSecondDouble(importOptions.animSampleRate);
  1176. else
  1177. {
  1178. FbxTime::EMode timeMode = scene->GetGlobalSettings().GetTimeMode();
  1179. sampleRate.SetSecondDouble(1.0f / FbxTime::GetFrameRate(timeMode));
  1180. }
  1181. if (!animStack->BakeLayers(evaluator, startTime, endTime, sampleRate))
  1182. continue;
  1183. layerCount = animStack->GetMemberCount<FbxAnimLayer>();
  1184. }
  1185. if (layerCount == 1)
  1186. {
  1187. FbxAnimLayer* animLayer = animStack->GetMember<FbxAnimLayer>(0);
  1188. importAnimations(animLayer, root, importOptions, clip, importScene);
  1189. }
  1190. }
  1191. }
  1192. void FBXImporter::importAnimations(FbxAnimLayer* layer, FbxNode* node, FBXImportOptions& importOptions,
  1193. FBXAnimationClip& clip, FBXImportScene& importScene)
  1194. {
  1195. FbxAnimCurve* translation[3];
  1196. translation[0] = node->LclTranslation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_X);
  1197. translation[1] = node->LclTranslation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Y);
  1198. translation[2] = node->LclTranslation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Z);
  1199. FbxAnimCurve* rotation[3];
  1200. rotation[0] = node->LclRotation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_X);
  1201. rotation[1] = node->LclRotation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Y);
  1202. rotation[2] = node->LclRotation.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Z);
  1203. FbxAnimCurve* scale[3];
  1204. scale[0] = node->LclScaling.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_X);
  1205. scale[1] = node->LclScaling.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Y);
  1206. scale[2] = node->LclScaling.GetCurve(layer, FBXSDK_CURVENODE_COMPONENT_Z);
  1207. auto hasCurveValues = [](FbxAnimCurve* curves[3])
  1208. {
  1209. for (UINT32 i = 0; i < 3; i++)
  1210. {
  1211. if (curves[i] != nullptr && curves[i]->KeyGetCount() > 0)
  1212. return true;
  1213. }
  1214. return false;
  1215. };
  1216. bool hasBoneAnimation = hasCurveValues(translation) || hasCurveValues(rotation) || hasCurveValues(scale);
  1217. if (hasBoneAnimation)
  1218. {
  1219. clip.boneAnimations.push_back(FBXBoneAnimation());
  1220. FBXBoneAnimation& boneAnim = clip.boneAnimations.back();
  1221. boneAnim.node = importScene.nodeMap[node];
  1222. importCurve(translation[0], importOptions, boneAnim.translation[0], clip.start, clip.end);
  1223. importCurve(translation[1], importOptions, boneAnim.translation[1], clip.start, clip.end);
  1224. importCurve(translation[2], importOptions, boneAnim.translation[2], clip.start, clip.end);
  1225. importCurve(scale[0], importOptions, boneAnim.scale[0], clip.start, clip.end);
  1226. importCurve(scale[1], importOptions, boneAnim.scale[1], clip.start, clip.end);
  1227. importCurve(scale[2], importOptions, boneAnim.scale[2], clip.start, clip.end);
  1228. FBXAnimationCurve tempCurveRotation[3];
  1229. importCurve(rotation[0], importOptions, tempCurveRotation[0], clip.start, clip.end);
  1230. importCurve(rotation[1], importOptions, tempCurveRotation[1], clip.start, clip.end);
  1231. importCurve(rotation[2], importOptions, tempCurveRotation[2], clip.start, clip.end);
  1232. eulerToQuaternionCurves(tempCurveRotation, boneAnim.rotation);
  1233. }
  1234. if (importOptions.importBlendShapes)
  1235. {
  1236. FbxMesh* fbxMesh = node->GetMesh();
  1237. if (fbxMesh != nullptr)
  1238. {
  1239. INT32 deformerCount = fbxMesh->GetDeformerCount(FbxDeformer::eBlendShape);
  1240. for (INT32 i = 0; i < deformerCount; i++)
  1241. {
  1242. FbxBlendShape* deformer = static_cast<FbxBlendShape*>(fbxMesh->GetDeformer(i, FbxDeformer::eBlendShape));
  1243. INT32 channelCount = deformer->GetBlendShapeChannelCount();
  1244. for (INT32 j = 0; j < channelCount; j++)
  1245. {
  1246. FbxBlendShapeChannel* channel = deformer->GetBlendShapeChannel(j);
  1247. FbxAnimCurve* curve = fbxMesh->GetShapeChannel(i, j, layer);
  1248. if (curve != nullptr && curve->KeyGetCount() > 0)
  1249. {
  1250. clip.blendShapeAnimations.push_back(FBXBlendShapeAnimation());
  1251. FBXBlendShapeAnimation& blendShapeAnim = clip.blendShapeAnimations.back();
  1252. blendShapeAnim.blendShape = channel->GetName();
  1253. importCurve(curve, importOptions, blendShapeAnim.curve, clip.start, clip.end);
  1254. }
  1255. }
  1256. }
  1257. }
  1258. }
  1259. UINT32 childCount = (UINT32)node->GetChildCount();
  1260. for (UINT32 i = 0; i < childCount; i++)
  1261. {
  1262. FbxNode* child = node->GetChild(i);
  1263. importAnimations(layer, child, importOptions, clip, importScene);
  1264. }
  1265. }
  1266. void FBXImporter::eulerToQuaternionCurves(FBXAnimationCurve(&eulerCurves)[3], FBXAnimationCurve(&quatCurves)[4])
  1267. {
  1268. const float FIT_TIME = 0.33f;
  1269. INT32 numKeys = (INT32)eulerCurves[0].keyframes.size();
  1270. if (numKeys != (INT32)eulerCurves[1].keyframes.size() || numKeys != (INT32)eulerCurves[2].keyframes.size())
  1271. return;
  1272. auto eulerToQuaternion = [&](INT32 keyIdx, float time, const Quaternion& lastQuat)
  1273. {
  1274. Degree x = (Degree)eulerCurves[0].evaluate(time);
  1275. Degree y = (Degree)eulerCurves[1].evaluate(time);
  1276. Degree z = (Degree)eulerCurves[2].evaluate(time);
  1277. Quaternion quat(x, y, z);
  1278. // Flip quaternion in case rotation is over 180 degrees
  1279. if (keyIdx > 0)
  1280. {
  1281. float dot = quat.dot(lastQuat);
  1282. if (dot < 0.0f)
  1283. quat = Quaternion(-quat.x, -quat.y, -quat.z, -quat.w);
  1284. }
  1285. return quat;
  1286. };
  1287. struct FitKeyframe
  1288. {
  1289. float time;
  1290. Quaternion value;
  1291. };
  1292. Vector<FitKeyframe> fitQuaternions(numKeys * 2);
  1293. Quaternion lastQuat;
  1294. for (INT32 i = 0; i < numKeys; i++)
  1295. {
  1296. float time = eulerCurves[0].keyframes[i].time;
  1297. Quaternion quat = eulerToQuaternion(i, time, lastQuat);
  1298. // Calculate extra values between keys so we can better approximate tangents
  1299. if ((i + 1) < numKeys)
  1300. {
  1301. float nextTime = eulerCurves[0].keyframes[i + 1].time;
  1302. float dt = nextTime - time;
  1303. FitKeyframe& fitStart = fitQuaternions[i * 2 + 0];
  1304. FitKeyframe& fitEnd = fitQuaternions[i * 2 + 1];
  1305. fitStart.time = time + dt * FIT_TIME;
  1306. fitEnd.time = time + dt * (1.0f - FIT_TIME);
  1307. fitStart.value = eulerToQuaternion(i, fitStart.time, quat);
  1308. fitEnd.value = eulerToQuaternion(i, fitEnd.time, fitStart.value);
  1309. lastQuat = fitStart.value;
  1310. }
  1311. // TODO - If animation is looping I should also compare last and first for continuity
  1312. for (INT32 j = 0; j < 4; j++)
  1313. {
  1314. quatCurves[j].keyframes.push_back(FBXKeyFrame());
  1315. FBXKeyFrame& keyFrame = quatCurves[j].keyframes.back();
  1316. keyFrame.time = time;
  1317. keyFrame.value = quat[j];
  1318. keyFrame.inTangent = 0;
  1319. keyFrame.outTangent = 0;
  1320. }
  1321. }
  1322. // Recalculate tangents for quaternion curves
  1323. // TODO - There must be an analytical way to convert euler angle tangents
  1324. // to quaternion tangents, but I don't want to bother figuring it out
  1325. // until I have a test-bed for animation.
  1326. if (numKeys > 1)
  1327. {
  1328. // TODO - I could check per-key curve interpolation originally assigned in FBX
  1329. // and use that to generate linear/constant slopes. Currently I assume
  1330. // its all cubic.
  1331. // First key
  1332. {
  1333. const FitKeyframe& fitKeyFrame = fitQuaternions[0];
  1334. for (INT32 j = 0; j < 4; j++)
  1335. {
  1336. FBXKeyFrame& keyFrame = quatCurves[j].keyframes[0];
  1337. float dt = fitKeyFrame.time - keyFrame.time;
  1338. keyFrame.inTangent = (fitKeyFrame.value[j] - keyFrame.value) / dt;
  1339. keyFrame.outTangent = keyFrame.inTangent;
  1340. }
  1341. }
  1342. // In-between keys
  1343. {
  1344. for (INT32 i = 1; i < (numKeys - 1); i++)
  1345. {
  1346. const FitKeyframe& fitPointStart = fitQuaternions[i * 2 - 1];
  1347. const FitKeyframe& fitPointEnd = fitQuaternions[i * 2 + 0];
  1348. for (INT32 j = 0; j < 4; j++)
  1349. {
  1350. FBXKeyFrame& keyFrame = quatCurves[j].keyframes[i];
  1351. float dt0 = fitPointEnd.time - keyFrame.time;
  1352. float dt1 = keyFrame.time - fitPointStart.time;
  1353. float t0 = fitPointEnd.value[j] - keyFrame.value;
  1354. float t1 = keyFrame.value - fitPointStart.value[j];
  1355. keyFrame.inTangent = t0 / (0.5f * dt0) + t1 / (0.5f * dt1);
  1356. keyFrame.outTangent = keyFrame.inTangent;
  1357. }
  1358. }
  1359. }
  1360. // Last key
  1361. {
  1362. const FitKeyframe& fitKeyFrame = fitQuaternions[(numKeys - 2) * 2];
  1363. for (INT32 j = 0; j < 4; j++)
  1364. {
  1365. FBXKeyFrame& keyFrame = quatCurves[j].keyframes[numKeys - 2];
  1366. float dt = keyFrame.time - fitKeyFrame.time;
  1367. keyFrame.inTangent = (keyFrame.value - fitKeyFrame.value[j]) / dt;
  1368. keyFrame.outTangent = keyFrame.inTangent;
  1369. }
  1370. }
  1371. }
  1372. }
  1373. void FBXImporter::importCurve(FbxAnimCurve* fbxCurve, FBXImportOptions& importOptions, FBXAnimationCurve& curve, float start, float end)
  1374. {
  1375. if (fbxCurve == nullptr)
  1376. return;
  1377. INT32 keyCount = fbxCurve->KeyGetCount();
  1378. if (importOptions.animResample)
  1379. {
  1380. float curveStart = std::numeric_limits<float>::infinity();
  1381. float curveEnd = -std::numeric_limits<float>::infinity();
  1382. for (INT32 i = 0; i < keyCount; i++)
  1383. {
  1384. FbxTime fbxTime = fbxCurve->KeyGetTime(i);
  1385. float time = (float)fbxTime.GetSecondDouble();
  1386. curveStart = std::min(time, curveStart);
  1387. curveEnd = std::max(time, curveEnd);
  1388. }
  1389. curveStart = Math::clamp(curveStart, start, end);
  1390. curveEnd = Math::clamp(curveEnd, start, end);
  1391. float curveLength = curveEnd - curveStart;
  1392. INT32 numSamples = Math::ceilToInt(curveLength / importOptions.animSampleRate);
  1393. // We don't use the exact provided sample rate but instead modify it slightly so it
  1394. // completely covers the curve range including start/end points while maintaining
  1395. // constant time step between keyframes.
  1396. float dt = curveLength / (float)numSamples;
  1397. INT32 lastKeyframe = 0;
  1398. INT32 lastLeftTangent = 0;
  1399. INT32 lastRightTangent = 0;
  1400. for (INT32 i = 0; i < numSamples; i++)
  1401. {
  1402. float sampleTime = std::min(curveStart + i * dt, curveEnd);
  1403. FbxTime fbxSampleTime;
  1404. fbxSampleTime.SetSecondDouble(sampleTime);
  1405. curve.keyframes.push_back(FBXKeyFrame());
  1406. FBXKeyFrame& keyFrame = curve.keyframes.back();
  1407. keyFrame.time = sampleTime;
  1408. keyFrame.value = fbxCurve->Evaluate(fbxSampleTime, &lastKeyframe);
  1409. keyFrame.inTangent = fbxCurve->EvaluateLeftDerivative(fbxSampleTime, &lastLeftTangent);
  1410. keyFrame.outTangent = fbxCurve->EvaluateRightDerivative(fbxSampleTime, &lastRightTangent);
  1411. }
  1412. }
  1413. else
  1414. {
  1415. for (int i = 0; i < keyCount; i++)
  1416. {
  1417. FbxTime fbxTime = fbxCurve->KeyGetTime(i);
  1418. float time = (float)fbxTime.GetSecondDouble();
  1419. if (time < start || time > end)
  1420. continue;
  1421. curve.keyframes.push_back(FBXKeyFrame());
  1422. FBXKeyFrame& keyFrame = curve.keyframes.back();
  1423. keyFrame.time = time;
  1424. keyFrame.value = fbxCurve->KeyGetValue(i);
  1425. keyFrame.inTangent = fbxCurve->KeyGetLeftDerivative(i);
  1426. keyFrame.outTangent = fbxCurve->KeyGetRightDerivative(i);
  1427. }
  1428. }
  1429. }
  1430. }