FBXSceneEncoder.cpp 49 KB

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