BabylonMesh.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. #include "stdafx.h"
  2. #include "BabylonMesh.h"
  3. #include <map>
  4. #include <vector>
  5. #include <iostream>
  6. #include <sstream>
  7. #include "NodeHelpers.h"
  8. #include "GlobalSettings.h"
  9. struct BabylonVertex {
  10. babylon_vector3 position;
  11. babylon_vector3 normal;
  12. babylon_vector2 uv;
  13. babylon_vector2 uv2;
  14. babylon_vector2 uv3;
  15. babylon_vector2 uv4;
  16. babylon_vector2 uv5;
  17. babylon_vector2 uv6;
  18. babylon_color color;
  19. std::uint32_t boneIndices[4];
  20. float boneWeights[4];
  21. BabylonVertex() {
  22. boneIndices[0] = 0;
  23. boneIndices[1] = 0;
  24. boneIndices[2] = 0;
  25. boneIndices[3] = 0;
  26. boneWeights[0] = 0;
  27. boneWeights[1] = 0;
  28. boneWeights[2] = 0;
  29. boneWeights[3] = 0;
  30. }
  31. };
  32. struct triangle {
  33. std::uint32_t indices[3];
  34. };
  35. inline bool operator <(const triangle& lhs, const triangle& rhs) {
  36. if (lhs.indices[0] < rhs.indices[0]) {
  37. return true;
  38. }
  39. else if (rhs.indices[0] < lhs.indices[0]) {
  40. return false;
  41. }
  42. if (lhs.indices[1] < rhs.indices[1]) {
  43. return true;
  44. }
  45. else if (rhs.indices[1] < lhs.indices[1]) {
  46. return false;
  47. }
  48. return lhs.indices[2] < rhs.indices[2];
  49. }
  50. inline bool operator <(const BabylonVertex& lhs, const BabylonVertex& rhs) {
  51. if (lhs.position < rhs.position) {
  52. return true;
  53. }
  54. else if (rhs.position < lhs.position) {
  55. return false;
  56. }
  57. if (lhs.normal < rhs.normal) {
  58. return true;
  59. }
  60. else if (rhs.normal < lhs.normal) {
  61. return false;
  62. }
  63. if (lhs.uv < rhs.uv) {
  64. return true;
  65. }
  66. else if (rhs.uv < lhs.uv) {
  67. return false;
  68. }
  69. if (lhs.uv2 < rhs.uv2) {
  70. return true;
  71. }
  72. else if (rhs.uv2 < lhs.uv2) {
  73. return false;
  74. }
  75. if (lhs.uv3 < rhs.uv3) {
  76. return true;
  77. }
  78. else if (rhs.uv3 < lhs.uv3) {
  79. return false;
  80. }
  81. if (lhs.uv4 < rhs.uv4) {
  82. return true;
  83. }
  84. else if (rhs.uv4 < lhs.uv4) {
  85. return false;
  86. }
  87. if (lhs.uv5 < rhs.uv5) {
  88. return true;
  89. }
  90. else if (rhs.uv5 < lhs.uv5) {
  91. return false;
  92. }
  93. if (lhs.uv6 < rhs.uv6) {
  94. return true;
  95. }
  96. else if (rhs.uv6 < lhs.uv6) {
  97. return false;
  98. }
  99. if (lhs.color < rhs.color) {
  100. return true;
  101. }
  102. else if (rhs.color < lhs.color) {
  103. return false;
  104. }
  105. if (lhs.boneIndices[0] < rhs.boneIndices[0]) {
  106. return true;
  107. }
  108. else if (rhs.boneIndices[0] < lhs.boneIndices[0]) {
  109. return false;
  110. }
  111. if (lhs.boneIndices[1] < rhs.boneIndices[1]) {
  112. return true;
  113. }
  114. else if (rhs.boneIndices[1] < lhs.boneIndices[1]) {
  115. return false;
  116. }
  117. if (lhs.boneIndices[2] < rhs.boneIndices[2]) {
  118. return true;
  119. }
  120. else if (rhs.boneIndices[2] < lhs.boneIndices[2]) {
  121. return false;
  122. }
  123. if (lhs.boneIndices[3] < rhs.boneIndices[3]) {
  124. return true;
  125. }
  126. else if (rhs.boneIndices[3] < lhs.boneIndices[3]) {
  127. return false;
  128. }
  129. if (lhs.boneWeights[0] < rhs.boneWeights[0]) {
  130. return true;
  131. }
  132. else if (rhs.boneWeights[0] < lhs.boneWeights[0]) {
  133. return false;
  134. }
  135. if (lhs.boneWeights[1] < rhs.boneWeights[1]) {
  136. return true;
  137. }
  138. else if (rhs.boneWeights[1] < lhs.boneWeights[1]) {
  139. return false;
  140. }
  141. if (lhs.boneWeights[2] < rhs.boneWeights[2]) {
  142. return true;
  143. }
  144. else if (rhs.boneWeights[2] < lhs.boneWeights[2]) {
  145. return false;
  146. }
  147. if (lhs.boneWeights[3] < rhs.boneWeights[3]) {
  148. return true;
  149. }
  150. else if (rhs.boneWeights[3] < lhs.boneWeights[3]) {
  151. return false;
  152. }
  153. return false;
  154. }
  155. struct SubmeshData {
  156. std::map<BabylonVertex, std::uint32_t> knownVertices;
  157. std::set<triangle> knownTriangles;
  158. std::vector<BabylonVertex> vertices;
  159. std::vector<std::uint32_t> indices;
  160. };
  161. web::json::value convertToJson(const std::vector<babylon_vector3>& v) {
  162. auto result = web::json::value::array();
  163. for (auto ix = 0u;ix < v.size();++ix) {
  164. result[ix * 3] = web::json::value::number(v[ix].x);
  165. result[ix * 3 + 1] = web::json::value::number(v[ix].y);
  166. result[ix * 3 + 2] = web::json::value::number(v[ix].z);
  167. }
  168. return result;
  169. }
  170. web::json::value convertToJson(const std::vector<babylon_vector2>& v) {
  171. auto result = web::json::value::array();
  172. for (auto ix = 0u;ix < v.size();++ix) {
  173. result[ix * 2] = web::json::value::number(v[ix].x);
  174. result[ix * 2 + 1] = web::json::value::number(v[ix].y);
  175. }
  176. return result;
  177. }
  178. web::json::value convertToJson(const std::vector<babylon_color>& v) {
  179. auto result = web::json::value::array();
  180. for (auto ix = 0u;ix < v.size();++ix) {
  181. result[ix * 4] = web::json::value::number(v[ix].r);
  182. result[ix * 4 + 1] = web::json::value::number(v[ix].g);
  183. result[ix * 4 + 2] = web::json::value::number(v[ix].b);
  184. result[ix * 4 + 3] = web::json::value::number(v[ix].a);
  185. }
  186. return result;
  187. }
  188. web::json::value convertToJson(const std::vector<babylon_vector4>& v) {
  189. auto result = web::json::value::array();
  190. for (auto ix = 0u; ix < v.size(); ++ix) {
  191. result[ix * 4] = web::json::value::number(v[ix].x);
  192. result[ix * 4 + 1] = web::json::value::number(v[ix].y);
  193. result[ix * 4 + 2] = web::json::value::number(v[ix].z);
  194. result[ix * 4 + 3] = web::json::value::number(v[ix].w);
  195. }
  196. return result;
  197. }
  198. web::json::value convertToJson(const std::vector<std::uint32_t>& v){
  199. auto result = web::json::value::array();
  200. for (auto ix = 0u; ix < v.size() ; ++ix) {
  201. result[ix ] = web::json::value::number(v[ix ]);
  202. }
  203. return result;
  204. }
  205. web::json::value convertToJson(const std::vector<std::uint32_t>& v, bool changeVertexOrder) {
  206. if (changeVertexOrder) {
  207. auto result = web::json::value::array();
  208. for (auto ix = 0u;ix < v.size() / 3;++ix) {
  209. result[ix * 3] = web::json::value::number(v[ix * 3]);
  210. result[ix * 3 + 1] = web::json::value::number(v[ix * 3 + 2]);
  211. result[ix * 3 + 2] = web::json::value::number(v[ix * 3 + 1]);
  212. }
  213. return result;
  214. }
  215. else {
  216. auto result = web::json::value::array();
  217. for (auto ix = 0u;ix < v.size() / 3;++ix) {
  218. result[ix * 3] = web::json::value::number(v[ix * 3]);
  219. result[ix * 3 + 1] = web::json::value::number(v[ix * 3 + 1]);
  220. result[ix * 3 + 2] = web::json::value::number(v[ix * 3 + 2]);
  221. }
  222. return result;
  223. }
  224. }
  225. web::json::value convertToJson(const std::vector<BabylonSubmesh>& v) {
  226. auto result = web::json::value::array();
  227. for (auto ix = 0u;ix < v.size();++ix) {
  228. auto jsubmesh = web::json::value::object();
  229. jsubmesh[L"materialIndex"] = web::json::value::number(v[ix].materialIndex);
  230. jsubmesh[L"verticesStart"] = web::json::value::number(v[ix].verticesStart);
  231. jsubmesh[L"verticesCount"] = web::json::value::number(v[ix].verticesCount);
  232. jsubmesh[L"indexStart"] = web::json::value::number(v[ix].indexStart);
  233. jsubmesh[L"indexCount"] = web::json::value::number(v[ix].indexCount);
  234. result[result.size()] = jsubmesh;
  235. }
  236. return result;
  237. }
  238. web::json::value BabylonSubmesh::toJson(){
  239. auto jobj = web::json::value::object();
  240. jobj[L"materialIndex"] = web::json::value::number(materialIndex);
  241. jobj[L"verticesStart"] = web::json::value::number(verticesStart);
  242. jobj[L"verticesCount"] = web::json::value::number(verticesCount);
  243. jobj[L"indexStart"] = web::json::value::number(indexStart);
  244. jobj[L"indexCount"] = web::json::value::number(indexCount);
  245. return jobj;
  246. }
  247. web::json::value BabylonMesh::toJson()
  248. {
  249. auto jobj = BabylonAbstractMesh::toJson();
  250. jobj[L"id"] = web::json::value::string(_id);
  251. jobj[L"name"] = web::json::value::string(_id);
  252. if (_parentId.size() > 0)
  253. jobj[L"parentId"] = web::json::value::string(_parentId);
  254. if (_materialId.size() > 0)
  255. jobj[L"materialId"] = web::json::value::string(_materialId);
  256. jobj[L"isEnabled"] = web::json::value::boolean(_isEnabled);
  257. jobj[L"isVisible"] = web::json::value::boolean(_isVisible);
  258. jobj[L"pickable"] = web::json::value::boolean(_pickable);
  259. jobj[L"hasVertexAlpha"] = web::json::value::boolean(_hasVertexAlpha);
  260. jobj[L"checkCollision"] = web::json::value::boolean(_checkCollision);
  261. jobj[L"receiveShadows"] = web::json::value::boolean(_receiveShadows);
  262. jobj[L"infiniteDistance"] = web::json::value::boolean(_infiniteDistance);
  263. jobj[L"billboardMode"] = web::json::value::number(_billboardMode);
  264. jobj[L"visibility"] = web::json::value::number(_visibility);
  265. jobj[L"skeletonId"] = web::json::value::number(_skeletonId);
  266. auto submeshesArray = web::json::value::array();
  267. for (auto ix = 0u; ix < submeshes().size(); ++ix){
  268. submeshesArray[ix] = submeshes()[ix].toJson();
  269. }
  270. jobj[L"subMeshes"] = submeshesArray;
  271. jobj[L"showBoundingBox"] = web::json::value::boolean(_showBoundingBox);
  272. jobj[L"showSubMeshesBoundingBox"] = web::json::value::boolean(_showSubMeshesBoundingBox);
  273. jobj[L"applyFog"] = web::json::value::boolean(_applyFog);
  274. jobj[L"alphaIndex"] = web::json::value::number(_alphaIndex);
  275. if (_positions.size() > 0)
  276. jobj[L"positions"] = convertToJson(_positions);
  277. if (_normals.size() > 0)
  278. jobj[L"normals"] = convertToJson(_normals);
  279. if (_uvs.size() > 0)
  280. jobj[L"uvs"] = convertToJson(_uvs);
  281. if (_uvs2.size() > 0)
  282. jobj[L"uvs2"] = convertToJson(_uvs2);
  283. if (_uvs3.size() > 0)
  284. jobj[L"uvs3"] = convertToJson(_uvs3);
  285. if (_uvs4.size() > 0)
  286. jobj[L"uvs4"] = convertToJson(_uvs4);
  287. if (_uvs5.size() > 0)
  288. jobj[L"uvs5"] = convertToJson(_uvs5);
  289. if (_uvs6.size() > 0)
  290. jobj[L"uvs6"] = convertToJson(_uvs6);
  291. if (_colors.size() > 0)
  292. jobj[L"colors"] = convertToJson(_colors);
  293. if (_indices.size() > 0)
  294. jobj[L"indices"] = convertToJson(_indices, false);
  295. if (_boneIndices.size() > 0){
  296. jobj[L"matricesIndices"] = convertToJson(_boneIndices);
  297. }
  298. if (_boneWeights.size() > 0){
  299. jobj[L"matricesWeights"] = convertToJson(_boneWeights);
  300. }
  301. if (animations.size() == 0 && !associatedSkeleton){
  302. jobj[L"autoAnimate"] = web::json::value::boolean(false);
  303. jobj[L"autoAnimateLoop"] = web::json::value::boolean(false);
  304. jobj[L"autoAnimateFrom"] = web::json::value::number(0);
  305. jobj[L"autoAnimateTo"] = web::json::value::number(0);
  306. }
  307. else if (animations.size()>0){
  308. jobj[L"autoAnimate"] = web::json::value::boolean(animations[0]->autoAnimate);
  309. jobj[L"autoAnimateLoop"] = web::json::value::boolean(animations[0]->autoAnimateLoop);
  310. jobj[L"autoAnimateFrom"] = web::json::value::number(animations[0]->autoAnimateFrom);
  311. jobj[L"autoAnimateTo"] = web::json::value::number(animations[0]->autoAnimateTo);
  312. }
  313. else{
  314. jobj[L"autoAnimate"] = web::json::value::boolean(associatedSkeleton->bones[0].animation->autoAnimate);
  315. jobj[L"autoAnimateLoop"] = web::json::value::boolean(associatedSkeleton->bones[0].animation->autoAnimateLoop);
  316. jobj[L"autoAnimateFrom"] = web::json::value::number(associatedSkeleton->bones[0].animation->autoAnimateFrom);
  317. jobj[L"autoAnimateTo"] = web::json::value::number(associatedSkeleton->bones[0].animation->autoAnimateTo);
  318. }
  319. auto janimations = web::json::value::array();
  320. for (const auto& anim : animations){
  321. janimations[janimations.size()] = anim->toJson();
  322. }
  323. jobj[L"animations"] = janimations;
  324. FbxMatrix identity;
  325. identity.SetIdentity();
  326. if (pivotMatrix != identity){
  327. auto jpivot = web::json::value::array();
  328. for (auto x = 0; x < 4; ++x){
  329. for (auto y = 0; y < 4; ++y){
  330. jpivot[x * 4 + y] = web::json::value::number( pivotMatrix[x][y]);
  331. }
  332. }
  333. jobj[L"pivotMatrix"] = jpivot;
  334. }
  335. return jobj;
  336. }
  337. BabylonMesh::BabylonMesh() :
  338. _isEnabled(true),
  339. _isVisible(true),
  340. _billboardMode(0),
  341. _visibility(1),
  342. _skeletonId(-1),
  343. _pickable(true)
  344. {
  345. pivotMatrix.SetIdentity();
  346. }
  347. BabylonMesh::BabylonMesh(BabylonNode* node) :
  348. BabylonAbstractMesh(node),
  349. _isEnabled(true),
  350. _isVisible(true),
  351. _billboardMode(0),
  352. _visibility(1),
  353. _skeletonId(-1),
  354. _pickable(true),
  355. _hasVertexAlpha(false),
  356. _checkCollision(false),
  357. _receiveShadows(false),
  358. _infiniteDistance(false),
  359. _autoAnimate(false),
  360. _autoAnimateFrom(0),
  361. _autoAnimateTo(0),
  362. _autoAnimateLoop(false),
  363. _showBoundingBox(false),
  364. _showSubMeshesBoundingBox(false),
  365. _applyFog(false),
  366. _alphaIndex(0)
  367. {
  368. pivotMatrix.SetIdentity();
  369. auto fbxNode = node->fbxNode();
  370. std::string ansiName = fbxNode->GetName();
  371. name(std::wstring(ansiName.begin(), ansiName.end()));
  372. id(getNodeId(fbxNode));
  373. auto parent = fbxNode->GetParent();
  374. if (parent) {
  375. parentId(getNodeId(parent));
  376. }
  377. pivotMatrix = ConvertToBabylonCoordinateSystem( GetGeometryTransformation(fbxNode));
  378. auto animStack = fbxNode->GetScene()->GetSrcObject<FbxAnimStack>(0);
  379. FbxString animStackName = animStack->GetName();
  380. FbxTakeInfo* takeInfo = fbxNode->GetScene()->GetTakeInfo(animStackName);
  381. auto animTimeMode = GlobalSettings::Current().AnimationsTimeMode;
  382. auto animFrameRate = GlobalSettings::Current().AnimationsFrameRate();
  383. auto startFrame = takeInfo->mLocalTimeSpan.GetStart().GetFrameCount(animTimeMode);
  384. auto endFrame = takeInfo->mLocalTimeSpan.GetStop().GetFrameCount(animTimeMode);
  385. auto animLengthInFrame = endFrame - startFrame + 1;
  386. _visibility = static_cast<float>(node->fbxNode()->Visibility.Get());
  387. auto posAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"position", L"position", true, 0, static_cast<int>(animLengthInFrame), true);
  388. auto rotAnim = std::make_shared<BabylonAnimation<babylon_vector4>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"rotationQuaternion", L"rotationQuaternion", true, 0, static_cast<int>(animLengthInFrame), true);
  389. auto scaleAnim = std::make_shared<BabylonAnimation<babylon_vector3>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"scaling", L"scaling", true, 0, static_cast<int>(animLengthInFrame), true);
  390. auto visibilityAnim = std::make_shared<BabylonAnimation<float>>(BabylonAnimationBase::loopBehavior_Cycle, static_cast<int>(animFrameRate), L"visibility", L"visibility", true, 0, static_cast<int>(animLengthInFrame), true);
  391. auto mesh = fbxNode->GetMesh();
  392. _isVisible = fbxNode->Show.Get();
  393. auto rotCurveNode = fbxNode->LclRotation.GetCurveNode();
  394. auto translateCurveNode = fbxNode->LclTranslation.GetCurveNode();
  395. auto scalingCurveNode = fbxNode->LclScaling.GetCurveNode();
  396. auto visibilityCurveNode = fbxNode->Visibility.GetCurveNode();
  397. if (rotCurveNode || translateCurveNode || scalingCurveNode) {
  398. for (auto ix = 0; ix < animLengthInFrame; ix++) {
  399. FbxTime currTime;
  400. currTime.SetFrame(startFrame + ix, animTimeMode);
  401. babylon_animation_key<babylon_vector3> poskey;
  402. babylon_animation_key<babylon_vector4> rotkey;
  403. babylon_animation_key<babylon_vector3> scalekey;
  404. poskey.frame = ix;
  405. rotkey.frame = ix;
  406. scalekey.frame = ix;
  407. auto currTransform = node->GetLocal(currTime);
  408. poskey.values = currTransform.translation();
  409. rotkey.values = currTransform.rotationQuaternion();
  410. scalekey.values = currTransform.scaling();
  411. posAnim->appendKey(poskey);
  412. rotAnim->appendKey(rotkey);
  413. scaleAnim->appendKey(scalekey);
  414. }
  415. }
  416. if (visibilityCurveNode) {
  417. for (auto ix = 0; ix < animLengthInFrame; ix++) {
  418. FbxTime currTime;
  419. currTime.SetFrame(startFrame + ix, animTimeMode);
  420. babylon_animation_key<float> visibilityKey;
  421. visibilityKey.frame = ix;
  422. visibilityKey.values = static_cast<float>(node->fbxNode()->Visibility.EvaluateValue(currTime));
  423. visibilityAnim->appendKey(visibilityKey);
  424. }
  425. }
  426. if (!posAnim->isConstant()){
  427. animations.push_back(posAnim);
  428. }
  429. if (!rotAnim->isConstant()){
  430. animations.push_back(rotAnim);
  431. }
  432. if (!scaleAnim->isConstant()){
  433. animations.push_back(scaleAnim);
  434. }
  435. if (!visibilityAnim->isConstant()) {
  436. animations.push_back(visibilityAnim);
  437. }
  438. if (!mesh) {
  439. return;
  440. }
  441. if (mesh->GetPolygonCount() == 0){
  442. return;
  443. }
  444. _receiveShadows = mesh->ReceiveShadow.Get();
  445. FbxGeometryConverter conv(mesh->GetFbxManager());
  446. conv.ComputePolygonSmoothingFromEdgeSmoothing(mesh);
  447. if (!mesh->IsTriangleMesh()) {
  448. mesh = (FbxMesh*) conv.Triangulate(mesh, true);
  449. }
  450. mesh->RemoveBadPolygons();
  451. mesh->GenerateNormals();
  452. FbxStringList uvSetNameList;
  453. mesh->GetUVSetNames(uvSetNameList);
  454. std::vector<std::string> uniqueUVSets;
  455. int uvCount = uvSetNameList.GetCount();
  456. for (int i = 0; i < uvCount; ++i) {
  457. std::string value = uvSetNameList.GetStringAt(i);
  458. if (std::find(uniqueUVSets.begin(), uniqueUVSets.end(), value) == uniqueUVSets.end()) {
  459. uniqueUVSets.push_back(value);
  460. }
  461. }
  462. uvsets = uniqueUVSets;
  463. bool hasUv = uniqueUVSets.size() > 0;
  464. bool hasUv2 = uniqueUVSets.size() > 1;
  465. bool hasUv3 = uniqueUVSets.size() > 2;
  466. bool hasUv4 = uniqueUVSets.size() > 3;
  467. bool hasUv5 = uniqueUVSets.size() > 4;
  468. bool hasUv6 = uniqueUVSets.size() > 5;
  469. std::string uvSetName;
  470. std::string uv2SetName;
  471. std::string uv3SetName;
  472. std::string uv4SetName;
  473. std::string uv5SetName;
  474. std::string uv6SetName;
  475. if (hasUv) {
  476. uvSetName = uniqueUVSets[0];
  477. }
  478. if (hasUv2) {
  479. uv2SetName = uniqueUVSets[1];
  480. }
  481. if (hasUv3) {
  482. uv3SetName = uniqueUVSets[2];
  483. }
  484. if (hasUv4) {
  485. uv4SetName = uniqueUVSets[3];
  486. }
  487. if (hasUv5) {
  488. uv5SetName = uniqueUVSets[4];
  489. }
  490. if (hasUv6) {
  491. uv6SetName = uniqueUVSets[5];
  492. }
  493. auto colors = mesh->GetElementVertexColor();
  494. FbxLayerElement::EMappingMode colorMappingMode;
  495. FbxLayerElement::EReferenceMode colorReferenceMode;
  496. if (colors) {
  497. colorMappingMode = colors->GetMappingMode();
  498. colorReferenceMode = colors->GetReferenceMode();
  499. }
  500. auto normals = mesh->GetElementNormal();
  501. FbxGeometryElementUV* uvs = nullptr;
  502. FbxGeometryElementUV* uvs2 = nullptr;
  503. FbxGeometryElementUV* uvs3 = nullptr;
  504. FbxGeometryElementUV* uvs4 = nullptr;
  505. FbxGeometryElementUV* uvs5 = nullptr;
  506. FbxGeometryElementUV* uvs6 = nullptr;
  507. FbxLayerElement::EMappingMode uvsMappingMode;
  508. FbxLayerElement::EReferenceMode uvsReferenceMode;
  509. FbxLayerElement::EMappingMode uvs2MappingMode;
  510. FbxLayerElement::EReferenceMode uvs2ReferenceMode;
  511. FbxLayerElement::EMappingMode uvs3MappingMode;
  512. FbxLayerElement::EReferenceMode uvs3ReferenceMode;
  513. FbxLayerElement::EMappingMode uvs4MappingMode;
  514. FbxLayerElement::EReferenceMode uvs4ReferenceMode;
  515. FbxLayerElement::EMappingMode uvs5MappingMode;
  516. FbxLayerElement::EReferenceMode uvs5ReferenceMode;
  517. FbxLayerElement::EMappingMode uvs6MappingMode;
  518. FbxLayerElement::EReferenceMode uvs6ReferenceMode;
  519. if (hasUv) {
  520. uvs = mesh->GetElementUV(uvSetName.c_str());
  521. uvsMappingMode = uvs->GetMappingMode();
  522. uvsReferenceMode = uvs->GetReferenceMode();
  523. }
  524. if (hasUv2) {
  525. uvs2 = mesh->GetElementUV(uv2SetName.c_str());
  526. uvs2MappingMode = uvs2->GetMappingMode();
  527. uvs2ReferenceMode = uvs2->GetReferenceMode();
  528. }
  529. if (hasUv3) {
  530. uvs3 = mesh->GetElementUV(uv3SetName.c_str());
  531. uvs3MappingMode = uvs3->GetMappingMode();
  532. uvs3ReferenceMode = uvs3->GetReferenceMode();
  533. }
  534. if (hasUv4) {
  535. uvs4 = mesh->GetElementUV(uv4SetName.c_str());
  536. uvs4MappingMode = uvs4->GetMappingMode();
  537. uvs4ReferenceMode = uvs4->GetReferenceMode();
  538. }
  539. if (hasUv5) {
  540. uvs5 = mesh->GetElementUV(uv5SetName.c_str());
  541. uvs5MappingMode = uvs5->GetMappingMode();
  542. uvs5ReferenceMode = uvs5->GetReferenceMode();
  543. }
  544. if (hasUv6) {
  545. uvs6 = mesh->GetElementUV(uv6SetName.c_str());
  546. uvs6MappingMode = uvs6->GetMappingMode();
  547. uvs6ReferenceMode = uvs6->GetReferenceMode();
  548. }
  549. auto normalMappingMode = normals->GetMappingMode();
  550. auto normalReferenceMode = normals->GetReferenceMode();
  551. std::vector<SubmeshData> submeshes;
  552. auto materialCount = node->fbxNode()->GetMaterialCount();
  553. if (materialCount == 0) {
  554. materialCount = 1;
  555. }
  556. submeshes.resize(materialCount);
  557. auto baseLayer = mesh->GetLayer(0);
  558. auto materials = baseLayer->GetMaterials();
  559. FbxLayerElement::EMappingMode materialMappingMode = materials ?
  560. materials->GetMappingMode() : FbxLayerElement::eByPolygon;
  561. // extract deformers
  562. SkinInfo skinInfo(fbxNode);
  563. if (skinInfo.hasSkin()){
  564. associatedSkeleton = std::make_shared<BabylonSkeleton>();
  565. skinInfo.buildBabylonSkeleton(*associatedSkeleton);
  566. }
  567. auto triangleCount = mesh->GetPolygonCount();
  568. for (int triangleIndex = 0; triangleIndex < triangleCount; ++triangleIndex) {
  569. int materialIndex = 0;
  570. if (materialCount > 0 && materials) {
  571. switch (materialMappingMode) {
  572. case FbxLayerElement::eAllSame:
  573. materialIndex = materials->GetIndexArray().GetAt(0);
  574. break;
  575. case FbxLayerElement::eByPolygon:
  576. materialIndex = materials->GetIndexArray().GetAt(triangleIndex);
  577. }
  578. }
  579. auto& submesh = submeshes[materialIndex];
  580. triangle t;
  581. for (int cornerIndex = 0; cornerIndex < 3; ++cornerIndex) {
  582. auto controlPointIndex = mesh->GetPolygonVertex(triangleIndex, cornerIndex);
  583. auto vertexIndex = triangleIndex * 3 + cornerIndex;
  584. auto position = mesh->GetControlPoints()[controlPointIndex];
  585. position[2] = -position[2];
  586. BabylonVertex v;
  587. v.position = position;
  588. if (normals) {
  589. int normalMapIndex = (normalMappingMode == FbxLayerElement::eByControlPoint) ?
  590. controlPointIndex : vertexIndex;
  591. int normalValueIndex = (normalReferenceMode == FbxLayerElement::eDirect) ?
  592. normalMapIndex : normals->GetIndexArray().GetAt(normalMapIndex);
  593. v.normal = normals->GetDirectArray().GetAt(normalValueIndex);
  594. v.normal.z = -v.normal.z;
  595. }
  596. if (colors) {
  597. int mappingIndex = (colorMappingMode == FbxLayerElement::eByControlPoint) ?
  598. controlPointIndex : vertexIndex;
  599. int valueIndex = (colorReferenceMode == FbxLayerElement::eDirect) ?
  600. mappingIndex : colors->GetIndexArray().GetAt(mappingIndex);
  601. v.color = colors->GetDirectArray().GetAt(valueIndex);
  602. }
  603. if (uvs) {
  604. int mappingIndex = (uvsMappingMode == FbxLayerElement::eByControlPoint) ?
  605. controlPointIndex : vertexIndex;
  606. int valueIndex = (uvsReferenceMode == FbxLayerElement::eDirect) ?
  607. mappingIndex : uvs->GetIndexArray().GetAt(mappingIndex);
  608. v.uv = uvs->GetDirectArray().GetAt(valueIndex);
  609. //v.uv.y = 1 - v.uv.y;
  610. }
  611. if (uvs2) {
  612. int mappingIndex = (uvs2MappingMode == FbxLayerElement::eByControlPoint) ?
  613. controlPointIndex : vertexIndex;
  614. int valueIndex = (uvs2ReferenceMode == FbxLayerElement::eDirect) ?
  615. mappingIndex : uvs2->GetIndexArray().GetAt(mappingIndex);
  616. v.uv2 = uvs2->GetDirectArray().GetAt(valueIndex);
  617. }
  618. if (uvs3) {
  619. int mappingIndex = (uvs3MappingMode == FbxLayerElement::eByControlPoint) ?
  620. controlPointIndex : vertexIndex;
  621. int valueIndex = (uvs3ReferenceMode == FbxLayerElement::eDirect) ?
  622. mappingIndex : uvs3->GetIndexArray().GetAt(mappingIndex);
  623. v.uv3 = uvs3->GetDirectArray().GetAt(valueIndex);
  624. }
  625. if (uvs4) {
  626. int mappingIndex = (uvs4MappingMode == FbxLayerElement::eByControlPoint) ?
  627. controlPointIndex : vertexIndex;
  628. int valueIndex = (uvs4ReferenceMode == FbxLayerElement::eDirect) ?
  629. mappingIndex : uvs4->GetIndexArray().GetAt(mappingIndex);
  630. v.uv4 = uvs4->GetDirectArray().GetAt(valueIndex);
  631. }
  632. if (uvs5) {
  633. int mappingIndex = (uvs5MappingMode == FbxLayerElement::eByControlPoint) ?
  634. controlPointIndex : vertexIndex;
  635. int valueIndex = (uvs5ReferenceMode == FbxLayerElement::eDirect) ?
  636. mappingIndex : uvs5->GetIndexArray().GetAt(mappingIndex);
  637. v.uv5 = uvs5->GetDirectArray().GetAt(valueIndex);
  638. }
  639. if (uvs6) {
  640. int mappingIndex = (uvs6MappingMode == FbxLayerElement::eByControlPoint) ?
  641. controlPointIndex : vertexIndex;
  642. int valueIndex = (uvs6ReferenceMode == FbxLayerElement::eDirect) ?
  643. mappingIndex : uvs6->GetIndexArray().GetAt(mappingIndex);
  644. v.uv6 = uvs6->GetDirectArray().GetAt(valueIndex);
  645. }
  646. if (skinInfo.hasSkin()){
  647. auto& skinData = skinInfo.controlPointBoneIndicesAndWeights(controlPointIndex);
  648. for (auto boneix = 0; boneix < skinData.size()&&boneix<4; ++boneix){
  649. v.boneIndices[boneix] = skinData[boneix].index;
  650. v.boneWeights[boneix] = static_cast<float>(skinData[boneix].weight);
  651. }
  652. for (auto boneix = skinData.size(); boneix < 4; ++boneix){
  653. v.boneIndices[boneix] = skinInfo.bonesCount();
  654. v.boneWeights[boneix] = 0;
  655. }
  656. }
  657. auto foundVertex = submesh.knownVertices.find(v);
  658. if (foundVertex != submesh.knownVertices.end()) {
  659. //submesh.indices.push_back(foundVertex->second);
  660. t.indices[cornerIndex] = foundVertex->second;
  661. }
  662. else {
  663. auto index = static_cast<int>(submesh.vertices.size());
  664. submesh.vertices.push_back(v);
  665. //submesh.indices.push_back(index);
  666. submesh.knownVertices[v] = index;
  667. t.indices[cornerIndex] = index;
  668. }
  669. }
  670. if (submesh.knownTriangles.insert(t).second) {
  671. submesh.indices.push_back(t.indices[0]);
  672. submesh.indices.push_back(t.indices[1]);
  673. submesh.indices.push_back(t.indices[2]);
  674. }
  675. else {
  676. std::cout << "duplicate triangle found" << std::endl;
  677. }
  678. }
  679. std::uint32_t vertexOffset = 0;
  680. for (auto matIndex = 0u; matIndex < submeshes.size(); ++matIndex) {
  681. auto& submesh = submeshes[matIndex];
  682. BabylonSubmesh babsubmesh;
  683. babsubmesh.indexCount = static_cast<int>(submesh.indices.size());
  684. babsubmesh.indexStart = static_cast<int>(_indices.size());
  685. babsubmesh.materialIndex = matIndex;
  686. babsubmesh.verticesCount = static_cast<int>(submesh.vertices.size());
  687. babsubmesh.verticesStart = static_cast<int>(_positions.size());
  688. for (auto& v : submesh.vertices) {
  689. _positions.push_back(v.position);
  690. if (normals) {
  691. _normals.push_back(v.normal);
  692. }
  693. if (colors) {
  694. _colors.push_back(v.color);
  695. }
  696. if (uvs) {
  697. _uvs.push_back(v.uv);
  698. }
  699. if (uvs2) {
  700. _uvs2.push_back(v.uv2);
  701. }
  702. if (uvs3) {
  703. _uvs3.push_back(v.uv3);
  704. }
  705. if (uvs4) {
  706. _uvs4.push_back(v.uv4);
  707. }
  708. if (uvs5) {
  709. _uvs5.push_back(v.uv5);
  710. }
  711. if (uvs6) {
  712. _uvs6.push_back(v.uv6);
  713. }
  714. if (skinInfo.hasSkin()){
  715. float weight0 = v.boneWeights[0];
  716. float weight1 = v.boneWeights[1];
  717. float weight2 = v.boneWeights[2];
  718. int bone0 = v.boneIndices[0];
  719. int bone1 = v.boneIndices[1];
  720. int bone2 = v.boneIndices[2];
  721. int bone3 = v.boneIndices[3];
  722. _boneWeights.push_back(babylon_vector4( weight0, weight1, weight2, 1.0f - weight0 - weight1 - weight2));
  723. _boneIndices.push_back((bone3 << 24) | (bone2 << 16) | (bone1 << 8) | bone0);
  724. }
  725. }
  726. for (auto i : submesh.indices) {
  727. _indices.push_back(i + vertexOffset);
  728. }
  729. vertexOffset = static_cast<int>(_positions.size());
  730. _submeshes.push_back(babsubmesh);
  731. }
  732. }
  733. BabylonMesh::~BabylonMesh()
  734. {
  735. }