FBXSceneEncoder.cpp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550
  1. #ifdef USE_FBX
  2. #include <algorithm>
  3. #include <string>
  4. #include "FBXSceneEncoder.h"
  5. #include "EncoderArguments.h"
  6. using namespace gameplay;
  7. /**
  8. * Returns the aspect ratio from the given camera.
  9. *
  10. * @param fbxCamera The FBX camera to get the aspect ratio from.
  11. *
  12. * @return The aspect ratio from the camera.
  13. */
  14. static float getAspectRatio(FbxCamera* fbxCamera);
  15. /**
  16. * Returns the field of view Y from the given camera.
  17. *
  18. * @param fbxCamera The camera to get the fiew of view from.
  19. *
  20. * @return The field of view Y.
  21. */
  22. static float getFieldOfView(FbxCamera* fbxCamera);
  23. /**
  24. * Loads the texture coordinates from given mesh's polygon part into the vertex.
  25. *
  26. * @param fbxMesh The mesh to get the polygon from.
  27. * @param polyIndex The index of the polygon.
  28. * @param posInPoly The position in the polygon.
  29. * @param vertex The vertex to copy the texture coordinates to.
  30. */
  31. static void loadTextureCoords(FbxMesh* fbxMesh, int polyIndex, int posInPoly, Vertex* vertex);
  32. /**
  33. * Loads the normal from the mesh and adds it to the given vertex.
  34. *
  35. * @param fbxMesh The mesh to get the polygon from.
  36. * @param vertexIndex The vertex index in the mesh.
  37. * @param controlPointIndex The control point index.
  38. * @param vertex The vertex to copy to.
  39. */
  40. static void loadNormal(FbxMesh* fbxMesh, int vertexIndex, int controlPointIndex, Vertex* vertex);
  41. /**
  42. * Loads the tangent from the mesh and adds it to the given vertex.
  43. *
  44. * @param fbxMesh The mesh to load from.
  45. * @param vertexIndex The index of the vertex within fbxMesh.
  46. * @param vertex The vertex to copy to.
  47. */
  48. static void loadTangent(FbxMesh* fbxMesh, int vertexIndex, Vertex* vertex);
  49. /**
  50. * Loads the binormal from the mesh and adds it to the given vertex.
  51. *
  52. * @param fbxMesh The mesh to load from.
  53. * @param vertexIndex The index of the vertex within fbxMesh.
  54. * @param vertex The vertex to copy to.
  55. */
  56. static void loadBinormal(FbxMesh* fbxMesh, int vertexIndex, Vertex* vertex);
  57. /**
  58. * Loads the vertex diffuse color from the mesh and adds it to the given vertex.
  59. *
  60. * @param fbxMesh The mesh to load from.
  61. * @param vertexIndex The index of the vertex within fbxMesh.
  62. * @param vertex The vertex to copy to.
  63. */
  64. static void loadVertexColor(FbxMesh* fbxMesh, int vertexIndex, Vertex* vertex);
  65. /**
  66. * Loads the blend weight and blend indices data into the vertex.
  67. *
  68. * @param vertexWeights List of vertex weights. The x member contains the blendIndices. The y member contains the blendWeights.
  69. * @param vertex The vertex to copy the blend data to.
  70. */
  71. static void loadBlendData(const std::vector<Vector2>& vertexWeights, Vertex* vertex);
  72. /**
  73. * Loads the blend weights and blend indices from the given mesh.
  74. *
  75. * Each element of weights is a list of Vector2s where "x" is the blend index and "y" is the blend weight.
  76. *
  77. * @param fbxMesh The mesh to load from.
  78. * @param weights List of blend weights and blend indices for each vertex.
  79. *
  80. * @return True if this mesh has a mesh skin, false otherwise.
  81. */
  82. static bool loadBlendWeights(FbxMesh* fbxMesh, std::vector<std::vector<Vector2> >& weights);
  83. /**
  84. * Copies from an FBX matrix to a float[16] array.
  85. */
  86. static void copyMatrix(const FbxMatrix& fbxMatrix, float* matrix);
  87. /**
  88. * Copies from an FBX matrix to a gameplay matrix.
  89. */
  90. static void copyMatrix(const FbxMatrix& fbxMatrix, Matrix& matrix);
  91. /**
  92. * Finds the min and max start time and stop time of the given animation curve.
  93. *
  94. * startTime is updated if the animation curve contains a start time that is less than startTime.
  95. * stopTime is updated if the animation curve contains a stop time that is greater than stopTime.
  96. * frameRate is updated if the animation curve contains a frame rate that is greater than frameRate.
  97. *
  98. * @param animCurve The animation curve to read from.
  99. * @param startTime The min start time. (in/out)
  100. * @param stopTime The max stop time. (in/out)
  101. * @param frameRate The frame rate. (in/out)
  102. */
  103. static void findMinMaxTime(FbxAnimCurve* animCurve, float* startTime, float* stopTime, float* frameRate);
  104. /**
  105. * Appends a key frame of the given node's transform at the given time.
  106. *
  107. * @param fbxNode The node to get the matrix transform from.
  108. * @param time The key time to add and the time to get the transform from.
  109. * @param keyTimes The list of key times to append to.
  110. * @param keyValues The list of key values to append to.
  111. */
  112. static void appendKeyFrame(FbxNode* fbxNode, float time, std::vector<float>* keyTimes, std::vector<float>* keyValues);
  113. /**
  114. * Decomposes the given node's matrix transform at the given time and copies to scale, rotation and translation.
  115. *
  116. * @param fbxNode The node to get the matrix transform from.
  117. * @param time The time to get the matrix transform from.
  118. * @param scale The scale to copy to.
  119. * @param rotation The rotation to copy to.
  120. * @param translation The translation to copy to.
  121. */
  122. static void decompose(FbxNode* fbxNode, float time, Vector3* scale, Quaternion* rotation, Vector3* translation);
  123. /**
  124. * Creates an animation channel that targets the given node and target attribute using the given key times and key values.
  125. *
  126. * @param fbxNode The node to target.
  127. * @param targetAttrib The attribute type to target.
  128. * @param keyTimes The key times for the animation channel.
  129. * @param keyValues The key values for the animation channel.
  130. *
  131. * @return The newly created animation channel.
  132. */
  133. static AnimationChannel* createAnimationChannel(FbxNode* fbxNode, unsigned int targetAttrib, const std::vector<float>& keyTimes, const std::vector<float>& keyValues);
  134. void addScaleChannel(Animation* animation, FbxNode* fbxNode, float startTime, float stopTime);
  135. void addTranslateChannel(Animation* animation, FbxNode* fbxNode, float startTime, float stopTime);
  136. /**
  137. * Determines if it is possible to automatically group animations for mesh skins.
  138. *
  139. * @param fbxScene The FBX scene to search.
  140. *
  141. * @return True if there is at least one mesh skin that has animations that can be grouped.
  142. */
  143. bool isGroupAnimationPossible(FbxScene* fbxScene);
  144. bool isGroupAnimationPossible(FbxNode* fbxNode);
  145. bool isGroupAnimationPossible(FbxMesh* fbxMesh);
  146. FbxAnimCurve* getCurve(FbxPropertyT<FbxDouble3>& prop, FbxAnimLayer* animLayer, const char* pChannel)
  147. {
  148. #if FBXSDK_VERSION_MAJOR == 2013 && FBXSDK_VERSION_MINOR == 1
  149. return prop.GetCurve<FbxAnimCurve>(animLayer, pChannel);
  150. #else
  151. return prop.GetCurve(animLayer, pChannel);
  152. #endif
  153. }
  154. ////////////////////////////////////
  155. // Member Functions
  156. ////////////////////////////////////
  157. FBXSceneEncoder::FBXSceneEncoder()
  158. : _groupAnimation(NULL), _autoGroupAnimations(false)
  159. {
  160. }
  161. FBXSceneEncoder::~FBXSceneEncoder()
  162. {
  163. }
  164. void FBXSceneEncoder::write(const std::string& filepath, const EncoderArguments& arguments)
  165. {
  166. FbxManager* sdkManager = FbxManager::Create();
  167. FbxIOSettings *ios = FbxIOSettings::Create(sdkManager, IOSROOT);
  168. sdkManager->SetIOSettings(ios);
  169. FbxImporter* importer = FbxImporter::Create(sdkManager,"");
  170. if (!importer->Initialize(filepath.c_str(), -1, sdkManager->GetIOSettings()))
  171. {
  172. printf("Call to FbxImporter::Initialize() failed.\n");
  173. printf("Error returned: %s\n\n", importer->GetLastErrorString());
  174. exit(-1);
  175. }
  176. FbxScene* fbxScene = FbxScene::Create(sdkManager,"__FBX_SCENE__");
  177. print("Loading FBX file.");
  178. importer->Import(fbxScene);
  179. importer->Destroy();
  180. // Determine if animations should be grouped.
  181. if (arguments.getGroupAnimationAnimationId().empty() && isGroupAnimationPossible(fbxScene))
  182. {
  183. if (promptUserGroupAnimations())
  184. {
  185. _autoGroupAnimations = true;
  186. }
  187. }
  188. print("Loading Scene.");
  189. loadScene(fbxScene);
  190. print("Loading animations.");
  191. loadAnimations(fbxScene, arguments);
  192. sdkManager->Destroy();
  193. print("Optimizing GamePlay Binary.");
  194. _gamePlayFile.adjust();
  195. if (_autoGroupAnimations)
  196. {
  197. _gamePlayFile.groupMeshSkinAnimations();
  198. }
  199. std::string outputFilePath = arguments.getOutputFilePath();
  200. if (arguments.textOutputEnabled())
  201. {
  202. int pos = outputFilePath.find_last_of('.');
  203. if (pos > 2)
  204. {
  205. std::string path = outputFilePath.substr(0, pos);
  206. path.append(".xml");
  207. fprintf(stderr, "Saving debug file: %s\n", path.c_str());
  208. if (!_gamePlayFile.saveText(path))
  209. {
  210. fprintf(stderr,"Error writing text file: %s\n", path.c_str());
  211. }
  212. }
  213. }
  214. else
  215. {
  216. fprintf(stderr, "Saving binary file: %s\n", outputFilePath.c_str());
  217. if (!_gamePlayFile.saveBinary(outputFilePath))
  218. {
  219. fprintf(stderr,"Error writing binary file: %s\n", outputFilePath.c_str());
  220. }
  221. }
  222. }
  223. void FBXSceneEncoder::loadScene(FbxScene* fbxScene)
  224. {
  225. Scene* scene = new Scene();
  226. scene->setId(fbxScene->GetName());
  227. if (scene->getId().length() == 0)
  228. {
  229. scene->setId("__SCENE__");
  230. }
  231. // Load all of the nodes and their contents.
  232. FbxNode* rootNode = fbxScene->GetRootNode();
  233. if (rootNode)
  234. {
  235. print("Triangulate.");
  236. triangulateRecursive(rootNode);
  237. print("Load nodes.");
  238. // Don't include the FBX root node in the GPB.
  239. const int childCount = rootNode->GetChildCount();
  240. for (int i = 0; i < childCount; ++i)
  241. {
  242. Node* node = loadNode(rootNode->GetChild(i));
  243. if (node)
  244. {
  245. scene->add(node);
  246. }
  247. }
  248. }
  249. // Load the MeshSkin information from the scene's poses.
  250. loadBindShapes(fbxScene);
  251. // Find the ambient light of the scene
  252. FbxColor ambientColor = fbxScene->GetGlobalSettings().GetAmbientColor();
  253. scene->setAmbientColor((float)ambientColor.mRed, (float)ambientColor.mGreen, (float)ambientColor.mBlue);
  254. // Assign the first camera node (if there is one) in the scene as the active camera
  255. // This ensures that if there's a camera in the scene that it is assigned as the
  256. // active camera.
  257. // TODO: add logic to find the "active" camera node in the fbxScene
  258. scene->setActiveCameraNode(scene->getFirstCameraNode());
  259. _gamePlayFile.addScene(scene);
  260. }
  261. void FBXSceneEncoder::loadAnimationChannels(FbxAnimLayer* animLayer, FbxNode* fbxNode, Animation* animation)
  262. {
  263. const std::string* targetId = NULL;
  264. const char* name = fbxNode->GetName();
  265. Node* node = _gamePlayFile.getNode(name);
  266. if (node)
  267. {
  268. targetId = &node->getId();
  269. }
  270. // Determine which properties are animated on this node
  271. // Find the transform at each key frame
  272. // TODO: Ignore properties that are not animated (scale, rotation, translation)
  273. // This should result in only one animation channel per animated node.
  274. float startTime = FLT_MAX, stopTime = -1.0f, frameRate = -FLT_MAX;
  275. bool tx = false, ty = false, tz = false, rx = false, ry = false, rz = false, sx = false, sy = false, sz = false;
  276. FbxAnimCurve* animCurve = NULL;
  277. animCurve = getCurve(fbxNode->LclTranslation, animLayer, FBXSDK_CURVENODE_COMPONENT_X);
  278. if (animCurve)
  279. {
  280. tx = true;
  281. findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
  282. }
  283. animCurve = getCurve(fbxNode->LclTranslation, animLayer, FBXSDK_CURVENODE_COMPONENT_Y);
  284. if (animCurve)
  285. {
  286. ty = true;
  287. findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
  288. }
  289. animCurve = getCurve(fbxNode->LclTranslation, animLayer, FBXSDK_CURVENODE_COMPONENT_Z);
  290. if (animCurve)
  291. {
  292. tz = true;
  293. findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
  294. }
  295. animCurve = getCurve(fbxNode->LclRotation, animLayer, FBXSDK_CURVENODE_COMPONENT_X);
  296. if (animCurve)
  297. {
  298. rx = true;
  299. findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
  300. }
  301. animCurve = getCurve(fbxNode->LclRotation, animLayer, FBXSDK_CURVENODE_COMPONENT_Y);
  302. if (animCurve)
  303. {
  304. ry = true;
  305. findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
  306. }
  307. animCurve = getCurve(fbxNode->LclRotation, animLayer, FBXSDK_CURVENODE_COMPONENT_Z);
  308. if (animCurve)
  309. {
  310. rz = true;
  311. findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
  312. }
  313. animCurve = getCurve(fbxNode->LclScaling, animLayer, FBXSDK_CURVENODE_COMPONENT_X);
  314. if (animCurve)
  315. {
  316. sx = true;
  317. findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
  318. }
  319. animCurve = getCurve(fbxNode->LclScaling, animLayer, FBXSDK_CURVENODE_COMPONENT_Y);
  320. if (animCurve)
  321. {
  322. sy = true;
  323. findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
  324. }
  325. animCurve = getCurve(fbxNode->LclScaling, animLayer, FBXSDK_CURVENODE_COMPONENT_Z);
  326. if (animCurve)
  327. {
  328. sz = true;
  329. findMinMaxTime(animCurve, &startTime, &stopTime, &frameRate);
  330. }
  331. bool translate = tx | ty | tz;
  332. bool scale = sx | sy | sz;
  333. bool rotate = rx | ry | rz;
  334. if (translate || rotate || scale)
  335. {
  336. assert(startTime != FLT_MAX);
  337. assert(stopTime >= 0.0f);
  338. AnimationChannel* channel = new AnimationChannel();
  339. channel->setTargetId(name);
  340. channel->setTargetAttribute(Transform::ANIMATE_SCALE_ROTATE_TRANSLATE);
  341. float increment = 1000.0f / frameRate;
  342. std::vector<float> keyTimes;
  343. std::vector<float> keyValues;
  344. for (float time = startTime; time < stopTime; time += increment)
  345. {
  346. appendKeyFrame(fbxNode, time, &keyTimes, &keyValues);
  347. }
  348. // Add the last key frame at exactly stopTime
  349. appendKeyFrame(fbxNode, stopTime, &keyTimes, &keyValues);
  350. channel->setKeyTimes(keyTimes);
  351. /*
  352. std::vector<float> newKeyValues;
  353. for (size_t i = 0, size = keyValues.size(); i < size; i += 10)
  354. {
  355. if (translate)
  356. {
  357. newKeyValues.push_back(keyValues[i+0]);
  358. newKeyValues.push_back(keyValues[i+1]);
  359. newKeyValues.push_back(keyValues[i+2]);
  360. }
  361. if (rotate)
  362. {
  363. newKeyValues.push_back(keyValues[i+3]);
  364. newKeyValues.push_back(keyValues[i+4]);
  365. newKeyValues.push_back(keyValues[i+5]);
  366. newKeyValues.push_back(keyValues[i+6]);
  367. }
  368. if (scale)
  369. {
  370. newKeyValues.push_back(keyValues[i+7]);
  371. newKeyValues.push_back(keyValues[i+8]);
  372. newKeyValues.push_back(keyValues[i+9]);
  373. }
  374. }
  375. channel->setKeyValues(newKeyValues);
  376. */
  377. channel->setKeyValues(keyValues);
  378. channel->setInterpolation(AnimationChannel::LINEAR);
  379. animation->add(channel);
  380. /*
  381. if (!translate)
  382. {
  383. addTranslateChannel(animation, fbxNode, startTime, stopTime);
  384. }
  385. if (!rotate)
  386. {
  387. printf("rotate?\n"); // TODO
  388. }
  389. if (!scale)
  390. {
  391. addScaleChannel(animation, fbxNode, startTime, stopTime);
  392. }
  393. */
  394. if (_groupAnimation != animation)
  395. {
  396. // TODO explains
  397. _gamePlayFile.addAnimation(animation);
  398. }
  399. }
  400. }
  401. void FBXSceneEncoder::loadAnimationLayer(FbxAnimLayer* fbxAnimLayer, FbxNode* fbxNode, const EncoderArguments& arguments)
  402. {
  403. bool animationGroupId = false;
  404. const char* name = fbxNode->GetName();
  405. // Check if this node's animations are supposed to be grouped
  406. if (name)
  407. {
  408. std::string str = name;
  409. if (arguments.containsGroupNodeId(str))
  410. {
  411. animationGroupId = true;
  412. _groupAnimation = new Animation();
  413. _groupAnimation->setId(arguments.getAnimationId(str));
  414. }
  415. }
  416. Animation* animation = _groupAnimation;
  417. if (!_groupAnimation)
  418. {
  419. animation = new Animation();
  420. animation->setId(name);
  421. }
  422. loadAnimationChannels(fbxAnimLayer, fbxNode, animation);
  423. const int childCount = fbxNode->GetChildCount();
  424. for (int modelCount = 0; modelCount < childCount; ++modelCount)
  425. {
  426. loadAnimationLayer(fbxAnimLayer, fbxNode->GetChild(modelCount), arguments);
  427. }
  428. if (animationGroupId)
  429. {
  430. _gamePlayFile.addAnimation(_groupAnimation);
  431. _groupAnimation = NULL;
  432. }
  433. }
  434. void FBXSceneEncoder::loadAnimations(FbxScene* fbxScene, const EncoderArguments& arguments)
  435. {
  436. FbxAnimEvaluator* evaluator = fbxScene->GetEvaluator();
  437. if (!evaluator)
  438. return;
  439. FbxAnimStack* animStack = evaluator->GetContext();
  440. if (!animStack)
  441. return;
  442. for (int i = 0; i < fbxScene->GetSrcObjectCount(FBX_TYPE(FbxAnimStack)); ++i)
  443. {
  444. FbxAnimStack* animStack = FbxCast<FbxAnimStack>(fbxScene->GetSrcObject(FBX_TYPE(FbxAnimStack), i));
  445. int nbAnimLayers = animStack->GetMemberCount(FBX_TYPE(FbxAnimLayer));
  446. for (int l = 0; l < nbAnimLayers; ++l)
  447. {
  448. FbxAnimLayer* animLayer = animStack->GetMember(FBX_TYPE(FbxAnimLayer), l);
  449. loadAnimationLayer(animLayer, fbxScene->GetRootNode(), arguments);
  450. }
  451. }
  452. }
  453. Node* FBXSceneEncoder::loadNode(FbxNode* fbxNode)
  454. {
  455. Node* node = NULL;
  456. // Check if this node has already been loaded
  457. const char* id = fbxNode->GetName();
  458. if (id && strlen(id) > 0)
  459. {
  460. node = _gamePlayFile.getNode(fbxNode->GetName());
  461. if (node)
  462. {
  463. return node;
  464. }
  465. }
  466. node = new Node();
  467. if (id)
  468. {
  469. node->setId(id);
  470. }
  471. _gamePlayFile.addNode(node);
  472. transformNode(fbxNode, node);
  473. loadCamera(fbxNode, node);
  474. loadLight(fbxNode, node);
  475. loadModel(fbxNode, node);
  476. if (fbxNode->GetSkeleton())
  477. {
  478. // Indicate that this is a joint node for the purpose of debugging.
  479. // The XML debug output will print that this node is a joint.
  480. node->setIsJoint(true);
  481. }
  482. // Load child nodes
  483. const int childCount = fbxNode->GetChildCount();
  484. for (int i = 0; i < childCount; ++i)
  485. {
  486. Node* child = loadNode(fbxNode->GetChild(i));
  487. if (child)
  488. {
  489. node->addChild(child);
  490. }
  491. }
  492. return node;
  493. }
  494. Mesh* FBXSceneEncoder::getMesh(FbxUInt64 meshId)
  495. {
  496. // Check if this mesh was already loaded.
  497. std::map<FbxUInt64, Mesh*>::iterator it = _meshes.find(meshId);
  498. if (it != _meshes.end())
  499. {
  500. return it->second;
  501. }
  502. return NULL;
  503. }
  504. void FBXSceneEncoder::saveMesh(FbxUInt64 meshId, Mesh* mesh)
  505. {
  506. assert(mesh);
  507. if (!getMesh(meshId))
  508. {
  509. _meshes[meshId] = mesh;
  510. }
  511. }
  512. void FBXSceneEncoder::print(const char* str)
  513. {
  514. fprintf(stderr,"%s\n", str);
  515. }
  516. void FBXSceneEncoder::transformNode(FbxNode* fbxNode, Node* node)
  517. {
  518. FbxAMatrix matrix;
  519. if (fbxNode->GetCamera() || fbxNode->GetLight())
  520. {
  521. // TODO: Why is this necessary for Camera and Light?
  522. matrix.SetTRS(fbxNode->LclTranslation.Get(), fbxNode->LclRotation.Get(), fbxNode->LclScaling.Get());
  523. }
  524. else
  525. {
  526. matrix = fbxNode->EvaluateLocalTransform();
  527. }
  528. float m[16];
  529. copyMatrix(matrix, m);
  530. node->setTransformMatrix(m);
  531. }
  532. void FBXSceneEncoder::loadBindShapes(FbxScene* fbxScene)
  533. {
  534. float m[16];
  535. const int poseCount = fbxScene->GetPoseCount();
  536. for (int i = 0; i < poseCount; ++i)
  537. {
  538. FbxPose* pose = fbxScene->GetPose(i);
  539. assert(pose);
  540. if (pose->IsBindPose() && pose->GetCount() > 0)
  541. {
  542. FbxNode* fbxNode = pose->GetNode(0);
  543. if (fbxNode->GetMesh() != NULL)
  544. {
  545. Node* node = _gamePlayFile.getNode(fbxNode->GetName());
  546. assert(node && node->getModel());
  547. Model* model = node->getModel();
  548. if (model && model->getSkin())
  549. {
  550. MeshSkin* skin = model->getSkin();
  551. copyMatrix(pose->GetMatrix(0), m);
  552. skin->setBindShape(m);
  553. }
  554. }
  555. }
  556. }
  557. }
  558. void FBXSceneEncoder::loadCamera(FbxNode* fbxNode, Node* node)
  559. {
  560. FbxCamera* fbxCamera = fbxNode->GetCamera();
  561. if (!fbxCamera)
  562. {
  563. return;
  564. }
  565. Camera* camera = new Camera();
  566. const char* name = fbxNode->GetName();
  567. if (name)
  568. {
  569. std::string id(name);
  570. id.append("_Camera");
  571. camera->setId(id);
  572. }
  573. camera->setAspectRatio(getAspectRatio(fbxCamera));
  574. camera->setNearPlane((float)fbxCamera->NearPlane.Get());
  575. camera->setFarPlane((float)fbxCamera->FarPlane.Get());
  576. if (fbxCamera->ProjectionType.Get() == FbxCamera::eOrthogonal)
  577. {
  578. camera->setOrthographic();
  579. camera->setViewportWidth((float)fbxCamera->GetApertureWidth());
  580. camera->setViewportWidth((float)fbxCamera->GetApertureHeight());
  581. // xmag in FBX can be calculated from: OrthoZoom * 30.0 / 2.0
  582. camera->setViewportWidth((float)fbxCamera->OrthoZoom.Get() * 15.0f);
  583. }
  584. else if (fbxCamera->ProjectionType.Get() == FbxCamera::ePerspective)
  585. {
  586. camera->setPerspective();
  587. camera->setFieldOfView(getFieldOfView(fbxCamera));
  588. }
  589. else
  590. {
  591. warning("Unknown camera type in node");
  592. return;
  593. }
  594. _gamePlayFile.addCamera(camera);
  595. node->setCamera(camera);
  596. }
  597. void FBXSceneEncoder::loadLight(FbxNode* fbxNode, Node* node)
  598. {
  599. FbxLight* fbxLight = fbxNode->GetLight();
  600. if (!fbxLight)
  601. {
  602. return;
  603. }
  604. Light* light = new Light();
  605. const char* name = fbxNode->GetName();
  606. if (name)
  607. {
  608. std::string id(name);
  609. id.append("_Light");
  610. light->setId(id);
  611. }
  612. FbxDouble3 color = fbxLight->Color.Get();
  613. light->setColor((float)color[0], (float)color[1], (float)color[2]);
  614. switch (fbxLight->LightType.Get())
  615. {
  616. case FbxLight::ePoint:
  617. {
  618. FbxLight::EDecayType decayType = fbxLight->DecayType.Get();
  619. switch (decayType)
  620. {
  621. case FbxLight::eNone:
  622. // No decay. Can assume we have an ambient light, because ambient lights in the scene are
  623. // converted to point lights with no decay when exporting to FBX.
  624. light->setAmbientLight();
  625. break;
  626. case FbxLight::eLinear:
  627. light->setPointLight();
  628. light->setLinearAttenuation((float)fbxLight->DecayStart.Get());
  629. break;
  630. case FbxLight::eQuadratic:
  631. light->setPointLight();
  632. light->setQuadraticAttenuation((float)fbxLight->DecayStart.Get());
  633. break;
  634. case FbxLight::eCubic:
  635. default:
  636. // Not supported..
  637. break;
  638. }
  639. break;
  640. }
  641. case FbxLight::eDirectional:
  642. {
  643. light->setDirectionalLight();
  644. break;
  645. }
  646. case FbxLight::eSpot:
  647. {
  648. light->setSpotLight();
  649. FbxLight::EDecayType decayType = fbxLight->DecayType.Get();
  650. switch (decayType)
  651. {
  652. case FbxLight::eNone:
  653. // No decay.
  654. break;
  655. case FbxLight::eLinear:
  656. light->setLinearAttenuation((float)fbxLight->DecayStart.Get());
  657. break;
  658. case FbxLight::eQuadratic:
  659. light->setQuadraticAttenuation((float)fbxLight->DecayStart.Get());
  660. break;
  661. case FbxLight::eCubic:
  662. // Not supported..
  663. break;
  664. }
  665. light->setFalloffAngle(MATH_DEG_TO_RAD((float)fbxLight->OuterAngle.Get())); // fall off angle
  666. break;
  667. }
  668. default:
  669. {
  670. warning("Unknown light type in node.");
  671. return;
  672. }
  673. }
  674. _gamePlayFile.addLight(light);
  675. node->setLight(light);
  676. }
  677. void FBXSceneEncoder::loadModel(FbxNode* fbxNode, Node* node)
  678. {
  679. FbxMesh* fbxMesh = fbxNode->GetMesh();
  680. if (!fbxMesh)
  681. {
  682. return;
  683. }
  684. if (fbxMesh->IsTriangleMesh())
  685. {
  686. Mesh* mesh = loadMesh(fbxMesh);
  687. Model* model = new Model();
  688. model->setMesh(mesh);
  689. node->setModel(model);
  690. loadSkin(fbxMesh, model);
  691. if (model->getSkin())
  692. {
  693. // TODO: explain
  694. node->resetTransformMatrix();
  695. }
  696. }
  697. }
  698. void FBXSceneEncoder::loadSkin(FbxMesh* fbxMesh, Model* model)
  699. {
  700. const int deformerCount = fbxMesh->GetDeformerCount();
  701. for (int i = 0; i < deformerCount; ++i)
  702. {
  703. FbxDeformer* deformer = fbxMesh->GetDeformer(i);
  704. if (deformer->GetDeformerType() == FbxDeformer::eSkin)
  705. {
  706. FbxSkin* fbxSkin = static_cast<FbxSkin*>(deformer);
  707. MeshSkin* skin = new MeshSkin();
  708. std::vector<std::string> jointNames;
  709. std::vector<Node*> joints;
  710. std::vector<Matrix> bindPoses;
  711. const int clusterCount = fbxSkin->GetClusterCount();
  712. for (int j = 0; j < clusterCount; ++j)
  713. {
  714. FbxCluster* cluster = fbxSkin->GetCluster(j);
  715. assert(cluster);
  716. FbxNode* linkedNode = cluster->GetLink();
  717. assert(linkedNode);
  718. if (linkedNode->GetSkeleton())
  719. {
  720. const char* jointName = linkedNode->GetName();
  721. assert(jointName);
  722. jointNames.push_back(jointName);
  723. Node* joint = loadNode(linkedNode);
  724. assert(joint);
  725. joints.push_back(joint);
  726. FbxAMatrix matrix;
  727. cluster->GetTransformLinkMatrix(matrix);
  728. Matrix m;
  729. copyMatrix(matrix.Inverse(), m);
  730. bindPoses.push_back(m);
  731. }
  732. }
  733. skin->setJointNames(jointNames);
  734. skin->setJoints(joints);
  735. skin->setBindPoses(bindPoses);
  736. model->setSkin(skin);
  737. break;
  738. }
  739. }
  740. }
  741. Mesh* FBXSceneEncoder::loadMesh(FbxMesh* fbxMesh)
  742. {
  743. // Check if this mesh has already been loaded.
  744. Mesh* mesh = getMesh(fbxMesh->GetUniqueID());
  745. if (mesh)
  746. {
  747. return mesh;
  748. }
  749. mesh = new Mesh();
  750. // GamePlay requires that a mesh have a unique ID but FbxMesh doesn't have a string ID.
  751. const char* name = fbxMesh->GetNode()->GetName();
  752. if (name)
  753. {
  754. std::string id(name);
  755. id.append("_Mesh");
  756. mesh->setId(id);
  757. }
  758. // The number of mesh parts is equal to the number of materials that affect this mesh.
  759. // There is always at least one mesh part.
  760. std::vector<MeshPart*> meshParts;
  761. const int materialCount = fbxMesh->GetNode()->GetMaterialCount();
  762. int meshPartSize = (materialCount > 0) ? materialCount : 1;
  763. for (int i = 0; i < meshPartSize; ++i)
  764. {
  765. meshParts.push_back(new MeshPart());
  766. }
  767. // Find the blend weights and blend indices if this mesh is skinned.
  768. std::vector<std::vector<Vector2> > weights;
  769. bool hasSkin = loadBlendWeights(fbxMesh, weights);
  770. int vertexIndex = 0;
  771. FbxVector4* controlPoints = fbxMesh->GetControlPoints();
  772. const int polygonCount = fbxMesh->GetPolygonCount();
  773. for (int polyIndex = 0; polyIndex < polygonCount; ++polyIndex)
  774. {
  775. const int polygonSize = fbxMesh->GetPolygonSize(polyIndex);
  776. for (int posInPoly = 0; posInPoly < polygonSize; ++posInPoly)
  777. {
  778. int controlPointIndex = fbxMesh->GetPolygonVertex(polyIndex, posInPoly);
  779. Vertex vertex;
  780. FbxVector4& position = controlPoints[controlPointIndex];
  781. vertex.position.x = (float)position[0];
  782. vertex.position.y = (float)position[1];
  783. vertex.position.z = (float)position[2];
  784. loadTextureCoords(fbxMesh, polyIndex, posInPoly, &vertex);
  785. loadNormal(fbxMesh, vertexIndex, controlPointIndex, &vertex);
  786. loadTangent(fbxMesh, vertexIndex, &vertex);
  787. loadBinormal(fbxMesh, vertexIndex, &vertex);
  788. loadVertexColor(fbxMesh, vertexIndex, &vertex);
  789. if (hasSkin)
  790. {
  791. loadBlendData(weights[controlPointIndex], &vertex);
  792. }
  793. // Determine which mesh part this vertex index should be added to based on the material that affects it.
  794. int meshPartIndex = 0;
  795. const int elementMatrialCount = fbxMesh->GetElementMaterialCount();
  796. for (int k = 0; k < elementMatrialCount; ++k)
  797. {
  798. FbxGeometryElementMaterial* elementMaterial = fbxMesh->GetElementMaterial(k);
  799. meshPartIndex = elementMaterial->GetIndexArray().GetAt(polyIndex);
  800. }
  801. // Add the vertex to the mesh if it hasn't already been added and find the vertex index.
  802. unsigned int index;
  803. if (mesh->contains(vertex))
  804. {
  805. index = mesh->getVertexIndex(vertex);
  806. }
  807. else
  808. {
  809. index = mesh->addVertex(vertex);
  810. }
  811. meshParts[meshPartIndex]->addIndex(index);
  812. vertexIndex++;
  813. }
  814. }
  815. const size_t meshpartsSize = meshParts.size();
  816. for (size_t i = 0; i < meshpartsSize; ++i)
  817. {
  818. mesh->addMeshPart(meshParts[i]);
  819. }
  820. // The order that the vertex elements are add to the list matters.
  821. // It should be the same order as how the Vertex data is written.
  822. // Position
  823. mesh->addVetexAttribute(POSITION, Vertex::POSITION_COUNT);
  824. const Vertex& vertex = mesh->vertices[0];
  825. // Normals
  826. if (vertex.hasNormal)
  827. {
  828. mesh->addVetexAttribute(NORMAL, Vertex::NORMAL_COUNT);
  829. }
  830. // Tangents
  831. if (vertex.hasTangent)
  832. {
  833. mesh->addVetexAttribute(TANGENT, Vertex::TANGENT_COUNT);
  834. }
  835. // Binormals
  836. if (vertex.hasBinormal)
  837. {
  838. mesh->addVetexAttribute(BINORMAL, Vertex::BINORMAL_COUNT);
  839. }
  840. // Texture Coordinates
  841. if (vertex.hasTexCoord)
  842. {
  843. mesh->addVetexAttribute(TEXCOORD0, Vertex::TEXCOORD_COUNT);
  844. }
  845. // Diffuse Color
  846. if (vertex.hasDiffuse)
  847. {
  848. mesh->addVetexAttribute(COLOR, Vertex::DIFFUSE_COUNT);
  849. }
  850. // Skinning BlendWeights BlendIndices
  851. if (vertex.hasWeights)
  852. {
  853. mesh->addVetexAttribute(BLENDWEIGHTS, Vertex::BLEND_WEIGHTS_COUNT);
  854. mesh->addVetexAttribute(BLENDINDICES, Vertex::BLEND_INDICES_COUNT);
  855. }
  856. _gamePlayFile.addMesh(mesh);
  857. saveMesh(fbxMesh->GetUniqueID(), mesh);
  858. return mesh;
  859. }
  860. void FBXSceneEncoder::triangulateRecursive(FbxNode* fbxNode)
  861. {
  862. // Triangulate all NURBS, patch and mesh under this node recursively.
  863. FbxNodeAttribute* nodeAttribute = fbxNode->GetNodeAttribute();
  864. if (nodeAttribute)
  865. {
  866. if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh ||
  867. nodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbs ||
  868. nodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbsSurface ||
  869. nodeAttribute->GetAttributeType() == FbxNodeAttribute::ePatch)
  870. {
  871. FbxGeometryConverter converter(fbxNode->GetFbxManager());
  872. converter.TriangulateInPlace(fbxNode);
  873. }
  874. }
  875. const int childCount = fbxNode->GetChildCount();
  876. for (int childIndex = 0; childIndex < childCount; ++childIndex)
  877. {
  878. triangulateRecursive(fbxNode->GetChild(childIndex));
  879. }
  880. }
  881. void FBXSceneEncoder::warning(const std::string& message)
  882. {
  883. printf("Warning: %s\n", message.c_str());
  884. }
  885. void FBXSceneEncoder::warning(const char* message)
  886. {
  887. printf("Warning: %s\n", message);
  888. }
  889. ////////////////////////////////////
  890. // Functions
  891. ////////////////////////////////////
  892. float getAspectRatio(FbxCamera* fbxCamera)
  893. {
  894. return (float)fbxCamera->FilmAspectRatio.Get();
  895. /*
  896. FbxCamera::ECameraAspectRatioMode camAspectRatioMode = fbxCamera->GetAspectRatioMode();
  897. double aspectX = fbxCamera->AspectWidth.Get();
  898. double aspectY = fbxCamera->AspectHeight.Get();
  899. double aspectRatio = 1.333333;
  900. switch ( camAspectRatioMode)
  901. {
  902. case FbxCamera::eWINDOW_SIZE:
  903. aspectRatio = aspectX / aspectY;
  904. break;
  905. case FbxCamera::eFIXED_RATIO:
  906. aspectRatio = aspectX;
  907. break;
  908. case FbxCamera::eFIXED_RESOLUTION:
  909. aspectRatio = aspectX / aspectY * fbxCamera->GetPixelRatio();
  910. break;
  911. case FbxCamera::eFIXED_WIDTH:
  912. aspectRatio = fbxCamera->GetPixelRatio() / aspectY;
  913. break;
  914. case FbxCamera::eFIXED_HEIGHT:
  915. aspectRatio = fbxCamera->GetPixelRatio() * aspectX;
  916. break;
  917. default:
  918. break;
  919. }
  920. return (float)aspectRatio;
  921. */
  922. }
  923. inline double vfov(double hfov, double aspect)
  924. {
  925. static const double MATH_PI_180 = 0.01745329251994329576923690768489;
  926. static const double MATH_180_PI = 57.295779513082320876798154814105;
  927. return (2.0 * atan((aspect) * tan( (hfov * MATH_PI_180) * 0.5)) * MATH_180_PI);
  928. }
  929. float getFieldOfView(FbxCamera* fbxCamera)
  930. {
  931. double fieldOfViewX = 0.0;
  932. double fieldOfViewY = 0.0;
  933. double filmHeight = fbxCamera->GetApertureHeight();
  934. double filmWidth = fbxCamera->GetApertureWidth() * fbxCamera->GetSqueezeRatio();
  935. double apertureRatio = filmHeight / filmWidth;
  936. if ( fbxCamera->GetApertureMode() == FbxCamera::eVertical)
  937. {
  938. fieldOfViewY = fbxCamera->FieldOfView.Get();
  939. }
  940. else if (fbxCamera->GetApertureMode() == FbxCamera::eHorizontal)
  941. {
  942. fieldOfViewX = fbxCamera->FieldOfView.Get();
  943. fieldOfViewY = vfov( fieldOfViewX, apertureRatio);
  944. }
  945. else if (fbxCamera->GetApertureMode() == FbxCamera::eFocalLength)
  946. {
  947. fieldOfViewX = fbxCamera->ComputeFieldOfView(fbxCamera->FocalLength.Get());
  948. fieldOfViewY = vfov( fieldOfViewX, apertureRatio);
  949. }
  950. else if (fbxCamera->GetApertureMode() == FbxCamera::eHorizAndVert)
  951. {
  952. fieldOfViewY = fbxCamera->FieldOfViewY.Get();
  953. }
  954. else
  955. {
  956. fieldOfViewY = 45.0;
  957. }
  958. return (float)fieldOfViewY;
  959. }
  960. void loadTextureCoords(FbxMesh* fbxMesh, int polyIndex, int posInPoly, Vertex* vertex)
  961. {
  962. assert(fbxMesh && polyIndex >=0 && posInPoly >= 0);
  963. if (fbxMesh->GetElementUVCount() > 0)
  964. {
  965. // Get only the first UV coordinates.
  966. FbxGeometryElementUV* uv = fbxMesh->GetElementUV(0);
  967. switch (uv->GetMappingMode())
  968. {
  969. case FbxGeometryElement::eByControlPoint:
  970. switch (uv->GetReferenceMode())
  971. {
  972. case FbxGeometryElement::eDirect:
  973. vertex->hasTexCoord = true;
  974. vertex->texCoord.x = (float)uv->GetDirectArray().GetAt(polyIndex)[0];
  975. vertex->texCoord.y = (float)uv->GetDirectArray().GetAt(polyIndex)[1];
  976. break;
  977. case FbxGeometryElement::eIndexToDirect:
  978. {
  979. int id = uv->GetIndexArray().GetAt(polyIndex);
  980. vertex->hasTexCoord = true;
  981. vertex->texCoord.x = (float)uv->GetDirectArray().GetAt(id)[0];
  982. vertex->texCoord.y = (float)uv->GetDirectArray().GetAt(id)[1];
  983. }
  984. break;
  985. default:
  986. break;
  987. }
  988. break;
  989. case FbxGeometryElement::eByPolygonVertex:
  990. {
  991. int lTextureUVIndex = fbxMesh->GetTextureUVIndex(polyIndex, posInPoly);
  992. switch (uv->GetReferenceMode())
  993. {
  994. case FbxGeometryElement::eDirect:
  995. case FbxGeometryElement::eIndexToDirect:
  996. vertex->hasTexCoord = true;
  997. vertex->texCoord.x = (float)uv->GetDirectArray().GetAt(lTextureUVIndex)[0];
  998. vertex->texCoord.y = (float)uv->GetDirectArray().GetAt(lTextureUVIndex)[1];
  999. break;
  1000. default:
  1001. break;
  1002. }
  1003. }
  1004. break;
  1005. default:
  1006. break;
  1007. }
  1008. }
  1009. }
  1010. void loadNormal(FbxMesh* fbxMesh, int vertexIndex, int controlPointIndex, Vertex* vertex)
  1011. {
  1012. if (fbxMesh->GetElementNormalCount() > 0)
  1013. {
  1014. // Get only the first
  1015. FbxGeometryElementNormal* normal = fbxMesh->GetElementNormal(0);
  1016. FbxGeometryElement::EMappingMode mappingMode = normal->GetMappingMode();
  1017. if (mappingMode == FbxGeometryElement::eByControlPoint)
  1018. {
  1019. switch (normal->GetReferenceMode())
  1020. {
  1021. case FbxGeometryElement::eDirect:
  1022. {
  1023. FbxVector4 vec4 = normal->GetDirectArray().GetAt(controlPointIndex);
  1024. vertex->hasNormal = true;
  1025. vertex->normal.x = (float)vec4[0];
  1026. vertex->normal.y = (float)vec4[1];
  1027. vertex->normal.z = (float)vec4[2];
  1028. }
  1029. break;
  1030. case FbxGeometryElement::eIndexToDirect:
  1031. {
  1032. int id = normal->GetIndexArray().GetAt(controlPointIndex);
  1033. FbxVector4 vec4 = normal->GetDirectArray().GetAt(id);
  1034. vertex->hasNormal = true;
  1035. vertex->normal.x = (float)vec4[0];
  1036. vertex->normal.y = (float)vec4[1];
  1037. vertex->normal.z = (float)vec4[2];
  1038. }
  1039. break;
  1040. default:
  1041. break;
  1042. }
  1043. }
  1044. else if (mappingMode == FbxGeometryElement::eByPolygonVertex)
  1045. {
  1046. switch (normal->GetReferenceMode())
  1047. {
  1048. case FbxGeometryElement::eDirect:
  1049. {
  1050. FbxVector4 vec4 = normal->GetDirectArray().GetAt(vertexIndex);
  1051. vertex->hasNormal = true;
  1052. vertex->normal.x = (float)vec4[0];
  1053. vertex->normal.y = (float)vec4[1];
  1054. vertex->normal.z = (float)vec4[2];
  1055. }
  1056. break;
  1057. case FbxGeometryElement::eIndexToDirect:
  1058. {
  1059. int id = normal->GetIndexArray().GetAt(vertexIndex);
  1060. FbxVector4 vec4 = normal->GetDirectArray().GetAt(id);
  1061. vertex->hasNormal = true;
  1062. vertex->normal.x = (float)vec4[0];
  1063. vertex->normal.y = (float)vec4[1];
  1064. vertex->normal.z = (float)vec4[2];
  1065. }
  1066. break;
  1067. default:
  1068. break;
  1069. }
  1070. }
  1071. }
  1072. }
  1073. void loadTangent(FbxMesh* fbxMesh, int vertexIndex, Vertex* vertex)
  1074. {
  1075. if (fbxMesh->GetElementTangentCount() > 0)
  1076. {
  1077. // Get only the first tangent
  1078. FbxGeometryElementTangent* tangent = fbxMesh->GetElementTangent(0);
  1079. if (tangent->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
  1080. {
  1081. switch (tangent->GetReferenceMode())
  1082. {
  1083. case FbxGeometryElement::eDirect:
  1084. {
  1085. FbxVector4 vec4 = tangent->GetDirectArray().GetAt(vertexIndex);
  1086. vertex->hasTangent = true;
  1087. vertex->tangent.x = (float)vec4[0];
  1088. vertex->tangent.y = (float)vec4[1];
  1089. vertex->tangent.z = (float)vec4[2];
  1090. }
  1091. break;
  1092. case FbxGeometryElement::eIndexToDirect:
  1093. {
  1094. int id = tangent->GetIndexArray().GetAt(vertexIndex);
  1095. FbxVector4 vec4 = tangent->GetDirectArray().GetAt(id);
  1096. vertex->hasTangent = true;
  1097. vertex->tangent.x = (float)vec4[0];
  1098. vertex->tangent.y = (float)vec4[1];
  1099. vertex->tangent.z = (float)vec4[2];
  1100. }
  1101. break;
  1102. default:
  1103. break;
  1104. }
  1105. }
  1106. }
  1107. }
  1108. void loadBinormal(FbxMesh* fbxMesh, int vertexIndex, Vertex* vertex)
  1109. {
  1110. if (fbxMesh->GetElementBinormalCount() > 0)
  1111. {
  1112. // Get only the first binormal.
  1113. FbxGeometryElementBinormal* binormal = fbxMesh->GetElementBinormal(0);
  1114. if (binormal->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
  1115. {
  1116. switch (binormal->GetReferenceMode())
  1117. {
  1118. case FbxGeometryElement::eDirect:
  1119. {
  1120. FbxVector4 vec4 = binormal->GetDirectArray().GetAt(vertexIndex);
  1121. vertex->hasBinormal = true;
  1122. vertex->binormal.x = (float)vec4[0];
  1123. vertex->binormal.y = (float)vec4[1];
  1124. vertex->binormal.z = (float)vec4[2];
  1125. }
  1126. break;
  1127. case FbxGeometryElement::eIndexToDirect:
  1128. {
  1129. int id = binormal->GetIndexArray().GetAt(vertexIndex);
  1130. FbxVector4 vec4 = binormal->GetDirectArray().GetAt(id);
  1131. vertex->hasBinormal = true;
  1132. vertex->binormal.x = (float)vec4[0];
  1133. vertex->binormal.y = (float)vec4[1];
  1134. vertex->binormal.z = (float)vec4[2];
  1135. }
  1136. break;
  1137. default:
  1138. break;
  1139. }
  1140. }
  1141. }
  1142. }
  1143. void loadVertexColor(FbxMesh* fbxMesh, int vertexIndex, Vertex* vertex)
  1144. {
  1145. if (fbxMesh->GetElementVertexColorCount() > 0)
  1146. {
  1147. // Get only the first vertex color.
  1148. FbxGeometryElementVertexColor* vertexColor = fbxMesh->GetElementVertexColor(0);
  1149. if (vertexColor->GetMappingMode() == FbxGeometryElement::eByPolygonVertex)
  1150. {
  1151. switch (vertexColor->GetReferenceMode())
  1152. {
  1153. case FbxGeometryElement::eDirect:
  1154. {
  1155. FbxColor color = vertexColor->GetDirectArray().GetAt(vertexIndex);
  1156. vertex->hasDiffuse = true;
  1157. vertex->diffuse.x = (float)color.mRed;
  1158. vertex->diffuse.y = (float)color.mGreen;
  1159. vertex->diffuse.z = (float)color.mBlue;
  1160. vertex->diffuse.w = (float)color.mAlpha;
  1161. }
  1162. break;
  1163. case FbxGeometryElement::eIndexToDirect:
  1164. {
  1165. int id = vertexColor->GetIndexArray().GetAt(vertexIndex);
  1166. FbxColor color = vertexColor->GetDirectArray().GetAt(id);
  1167. vertex->hasDiffuse = true;
  1168. vertex->diffuse.x = (float)color.mRed;
  1169. vertex->diffuse.y = (float)color.mGreen;
  1170. vertex->diffuse.z = (float)color.mBlue;
  1171. vertex->diffuse.w = (float)color.mAlpha;
  1172. }
  1173. break;
  1174. default:
  1175. break;
  1176. }
  1177. }
  1178. }
  1179. }
  1180. void loadBlendData(const std::vector<Vector2>& vertexWeights, Vertex* vertex)
  1181. {
  1182. size_t size = vertexWeights.size();
  1183. if (size >= 1)
  1184. {
  1185. vertex->hasWeights= true;
  1186. vertex->blendIndices.x = vertexWeights[0].x;
  1187. vertex->blendWeights.x = vertexWeights[0].y;
  1188. }
  1189. if (size >= 2)
  1190. {
  1191. vertex->blendIndices.y = vertexWeights[1].x;
  1192. vertex->blendWeights.y = vertexWeights[1].y;
  1193. }
  1194. if (size >= 3)
  1195. {
  1196. vertex->blendIndices.z = vertexWeights[2].x;
  1197. vertex->blendWeights.z = vertexWeights[2].y;
  1198. }
  1199. if (size >= 4)
  1200. {
  1201. vertex->blendIndices.w = vertexWeights[3].x;
  1202. vertex->blendWeights.w = vertexWeights[3].y;
  1203. }
  1204. //vertex->normalizeBlendWeight();
  1205. }
  1206. bool loadBlendWeights(FbxMesh* fbxMesh, std::vector<std::vector<Vector2> >& weights)
  1207. {
  1208. assert(fbxMesh);
  1209. const int vertexCount = fbxMesh->GetControlPointsCount();
  1210. FbxSkin* fbxSkin = NULL;
  1211. const int deformerCount = fbxMesh->GetDeformerCount();
  1212. for (int i = 0; i < deformerCount; ++i)
  1213. {
  1214. FbxDeformer* deformer = fbxMesh->GetDeformer(i);
  1215. if (deformer->GetDeformerType() == FbxDeformer::eSkin)
  1216. {
  1217. fbxSkin = static_cast<FbxSkin*>(deformer);
  1218. weights.resize(vertexCount);
  1219. const int clusterCount = fbxSkin->GetClusterCount();
  1220. for (int j = 0; j < clusterCount; ++j)
  1221. {
  1222. FbxCluster* cluster = fbxSkin->GetCluster(j);
  1223. assert(cluster);
  1224. FbxNode* linkedNode = cluster->GetLink();
  1225. assert(linkedNode);
  1226. const int vertexIndexCount = cluster->GetControlPointIndicesCount();
  1227. for (int k = 0; k < vertexIndexCount; ++k)
  1228. {
  1229. int index = cluster->GetControlPointIndices()[k];
  1230. if (index >= vertexCount)
  1231. {
  1232. continue;
  1233. }
  1234. double weight = cluster->GetControlPointWeights()[k];
  1235. if (weight == 0.0)
  1236. {
  1237. continue;
  1238. }
  1239. weights[index].push_back(Vector2((float)j, (float)weight));
  1240. }
  1241. }
  1242. // Only the first skin deformer will be loaded.
  1243. // There probably won't be more than one.
  1244. break;
  1245. }
  1246. }
  1247. return fbxSkin != NULL;
  1248. }
  1249. void findMinMaxTime(FbxAnimCurve* animCurve, float* startTime, float* stopTime, float* frameRate)
  1250. {
  1251. FbxTime start, stop;
  1252. FbxTimeSpan timeSpan;
  1253. animCurve->GetTimeInterval(timeSpan);
  1254. start = timeSpan.GetStart();
  1255. stop = timeSpan.GetStop();
  1256. *startTime = std::min(*startTime, (float)start.GetMilliSeconds());
  1257. *stopTime = std::max(*stopTime, (float)stop.GetMilliSeconds());
  1258. *frameRate = std::max(*frameRate, (float)stop.GetFrameRate(FbxTime::eDefaultMode));
  1259. }
  1260. void appendKeyFrame(FbxNode* fbxNode, float time, std::vector<float>* keyTimes, std::vector<float>* keyValues)
  1261. {
  1262. FbxAMatrix fbxMatrix;
  1263. Matrix matrix;
  1264. FbxTime kTime;
  1265. kTime.SetMilliSeconds((FbxLongLong)time);
  1266. fbxMatrix = fbxNode->EvaluateLocalTransform(kTime);
  1267. copyMatrix(fbxMatrix, matrix);
  1268. Vector3 scale;
  1269. Quaternion rotation;
  1270. Vector3 translation;
  1271. matrix.decompose(&scale, &rotation, &translation);
  1272. rotation.normalize();
  1273. keyTimes->push_back(time);
  1274. keyValues->push_back(scale.x);
  1275. keyValues->push_back(scale.y);
  1276. keyValues->push_back(scale.z);
  1277. keyValues->push_back(rotation.x);
  1278. keyValues->push_back(rotation.y);
  1279. keyValues->push_back(rotation.z);
  1280. keyValues->push_back(rotation.w);
  1281. keyValues->push_back(translation.x);
  1282. keyValues->push_back(translation.y);
  1283. keyValues->push_back(translation.z);
  1284. }
  1285. void decompose(FbxNode* fbxNode, float time, Vector3* scale, Quaternion* rotation, Vector3* translation)
  1286. {
  1287. FbxAMatrix fbxMatrix;
  1288. Matrix matrix;
  1289. FbxTime kTime;
  1290. kTime.SetMilliSeconds((FbxLongLong)time);
  1291. fbxMatrix = fbxNode->EvaluateLocalTransform(kTime);
  1292. copyMatrix(fbxMatrix, matrix);
  1293. matrix.decompose(scale, rotation, translation);
  1294. }
  1295. AnimationChannel* createAnimationChannel(FbxNode* fbxNode, unsigned int targetAttrib, const std::vector<float>& keyTimes, const std::vector<float>& keyValues)
  1296. {
  1297. AnimationChannel* channel = new AnimationChannel();
  1298. channel->setTargetId(fbxNode->GetName());
  1299. channel->setKeyTimes(keyTimes);
  1300. channel->setKeyValues(keyValues);
  1301. channel->setInterpolation(AnimationChannel::LINEAR);
  1302. channel->setTargetAttribute(targetAttrib);
  1303. return channel;
  1304. }
  1305. void addScaleChannel(Animation* animation, FbxNode* fbxNode, float startTime, float stopTime)
  1306. {
  1307. std::vector<float> keyTimes;
  1308. std::vector<float> keyValues;
  1309. Vector3 scale;
  1310. Quaternion rotation;
  1311. Vector3 translation;
  1312. decompose(fbxNode, startTime, &scale, &rotation, &translation);
  1313. keyTimes.push_back(startTime);
  1314. keyValues.push_back(scale.x);
  1315. keyValues.push_back(scale.y);
  1316. keyValues.push_back(scale.z);
  1317. decompose(fbxNode, stopTime, &scale, &rotation, &translation);
  1318. keyTimes.push_back(stopTime);
  1319. keyValues.push_back(scale.x);
  1320. keyValues.push_back(scale.y);
  1321. keyValues.push_back(scale.z);
  1322. AnimationChannel* channel = createAnimationChannel(fbxNode, Transform::ANIMATE_SCALE, keyTimes, keyValues);
  1323. animation->add(channel);
  1324. }
  1325. void addTranslateChannel(Animation* animation, FbxNode* fbxNode, float startTime, float stopTime)
  1326. {
  1327. std::vector<float> keyTimes;
  1328. std::vector<float> keyValues;
  1329. Vector3 scale;
  1330. Quaternion rotation;
  1331. Vector3 translation;
  1332. decompose(fbxNode, startTime, &scale, &rotation, &translation);
  1333. keyTimes.push_back(startTime);
  1334. keyValues.push_back(translation.x);
  1335. keyValues.push_back(translation.y);
  1336. keyValues.push_back(translation.z);
  1337. decompose(fbxNode, stopTime, &scale, &rotation, &translation);
  1338. keyTimes.push_back(stopTime);
  1339. keyValues.push_back(translation.x);
  1340. keyValues.push_back(translation.y);
  1341. keyValues.push_back(translation.z);
  1342. AnimationChannel* channel = createAnimationChannel(fbxNode, Transform::ANIMATE_TRANSLATE, keyTimes, keyValues);
  1343. animation->add(channel);
  1344. }
  1345. void copyMatrix(const FbxMatrix& fbxMatrix, float* matrix)
  1346. {
  1347. int i = 0;
  1348. for (int row = 0; row < 4; ++row)
  1349. {
  1350. for (int col = 0; col < 4; ++col)
  1351. {
  1352. matrix[i++] = (float)fbxMatrix.Get(row, col);
  1353. }
  1354. }
  1355. }
  1356. void copyMatrix(const FbxMatrix& fbxMatrix, Matrix& matrix)
  1357. {
  1358. int i = 0;
  1359. for (int row = 0; row < 4; ++row)
  1360. {
  1361. for (int col = 0; col < 4; ++col)
  1362. {
  1363. matrix.m[i++] = (float)fbxMatrix.Get(row, col);
  1364. }
  1365. }
  1366. }
  1367. bool isGroupAnimationPossible(FbxScene* fbxScene)
  1368. {
  1369. FbxNode* rootNode = fbxScene->GetRootNode();
  1370. if (rootNode)
  1371. {
  1372. if (isGroupAnimationPossible(rootNode))
  1373. return true;
  1374. }
  1375. return false;
  1376. }
  1377. bool isGroupAnimationPossible(FbxNode* fbxNode)
  1378. {
  1379. if (fbxNode)
  1380. {
  1381. FbxMesh* fbxMesh = fbxNode->GetMesh();
  1382. if (isGroupAnimationPossible(fbxMesh))
  1383. return true;
  1384. const int childCount = fbxNode->GetChildCount();
  1385. for (int i = 0; i < childCount; ++i)
  1386. {
  1387. if (isGroupAnimationPossible(fbxNode->GetChild(i)))
  1388. return true;
  1389. }
  1390. }
  1391. return false;
  1392. }
  1393. bool isGroupAnimationPossible(FbxMesh* fbxMesh)
  1394. {
  1395. if (fbxMesh)
  1396. {
  1397. const int deformerCount = fbxMesh->GetDeformerCount();
  1398. for (int i = 0; i < deformerCount; ++i)
  1399. {
  1400. FbxDeformer* deformer = fbxMesh->GetDeformer(i);
  1401. if (deformer->GetDeformerType() == FbxDeformer::eSkin)
  1402. {
  1403. FbxSkin* fbxSkin = static_cast<FbxSkin*>(deformer);
  1404. if (fbxSkin)
  1405. {
  1406. return true;
  1407. }
  1408. }
  1409. }
  1410. }
  1411. return false;
  1412. }
  1413. #endif