BabylonMesh.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  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. auto jinstances = web::json::value::array();
  336. for (auto& instance : _instances) {
  337. jinstances[jinstances.size()] = instance.toJson();
  338. }
  339. jobj[L"instances"] = jinstances;
  340. return jobj;
  341. }
  342. BabylonMesh::BabylonMesh() :
  343. _isEnabled(true),
  344. _isVisible(true),
  345. _billboardMode(0),
  346. _visibility(1),
  347. _skeletonId(-1),
  348. _pickable(true)
  349. {
  350. pivotMatrix.SetIdentity();
  351. }
  352. BabylonMesh::BabylonMesh(BabylonNode* node) :
  353. BabylonAbstractMesh(node),
  354. _isEnabled(true),
  355. _isVisible(true),
  356. _billboardMode(0),
  357. _visibility(1),
  358. _skeletonId(-1),
  359. _pickable(true),
  360. _hasVertexAlpha(false),
  361. _checkCollision(false),
  362. _receiveShadows(false),
  363. _infiniteDistance(false),
  364. _autoAnimate(false),
  365. _autoAnimateFrom(0),
  366. _autoAnimateTo(0),
  367. _autoAnimateLoop(false),
  368. _showBoundingBox(false),
  369. _showSubMeshesBoundingBox(false),
  370. _applyFog(false),
  371. _alphaIndex(0)
  372. {
  373. pivotMatrix.SetIdentity();
  374. auto fbxNode = node->fbxNode();
  375. std::string ansiName = fbxNode->GetName();
  376. name(std::wstring(ansiName.begin(), ansiName.end()));
  377. id(getNodeId(fbxNode));
  378. auto parent = fbxNode->GetParent();
  379. if (parent) {
  380. parentId(getNodeId(parent));
  381. }
  382. pivotMatrix = ConvertToBabylonCoordinateSystem( GetGeometryTransformation(fbxNode));
  383. auto animStack = fbxNode->GetScene()->GetSrcObject<FbxAnimStack>(0);
  384. FbxString animStackName = animStack->GetName();
  385. FbxTakeInfo* takeInfo = fbxNode->GetScene()->GetTakeInfo(animStackName);
  386. auto animTimeMode = GlobalSettings::Current().AnimationsTimeMode;
  387. auto animFrameRate = GlobalSettings::Current().AnimationsFrameRate();
  388. auto startFrame = takeInfo->mLocalTimeSpan.GetStart().GetFrameCount(animTimeMode);
  389. auto endFrame = takeInfo->mLocalTimeSpan.GetStop().GetFrameCount(animTimeMode);
  390. auto animLengthInFrame = endFrame - startFrame + 1;
  391. _visibility = static_cast<float>(node->fbxNode()->Visibility.Get());
  392. 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);
  393. 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);
  394. 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);
  395. 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);
  396. auto mesh = fbxNode->GetMesh();
  397. _isVisible = fbxNode->Show.Get();
  398. auto rotCurveNode = fbxNode->LclRotation.GetCurveNode();
  399. auto translateCurveNode = fbxNode->LclTranslation.GetCurveNode();
  400. auto scalingCurveNode = fbxNode->LclScaling.GetCurveNode();
  401. auto visibilityCurveNode = fbxNode->Visibility.GetCurveNode();
  402. if (rotCurveNode || translateCurveNode || scalingCurveNode) {
  403. for (auto ix = 0; ix < animLengthInFrame; ix++) {
  404. FbxTime currTime;
  405. currTime.SetFrame(startFrame + ix, animTimeMode);
  406. babylon_animation_key<babylon_vector3> poskey;
  407. babylon_animation_key<babylon_vector4> rotkey;
  408. babylon_animation_key<babylon_vector3> scalekey;
  409. poskey.frame = ix;
  410. rotkey.frame = ix;
  411. scalekey.frame = ix;
  412. auto currTransform = node->GetLocal(currTime);
  413. poskey.values = currTransform.translation();
  414. rotkey.values = currTransform.rotationQuaternion();
  415. scalekey.values = currTransform.scaling();
  416. posAnim->appendKey(poskey);
  417. rotAnim->appendKey(rotkey);
  418. scaleAnim->appendKey(scalekey);
  419. }
  420. }
  421. if (visibilityCurveNode) {
  422. for (auto ix = 0; ix < animLengthInFrame; ix++) {
  423. FbxTime currTime;
  424. currTime.SetFrame(startFrame + ix, animTimeMode);
  425. babylon_animation_key<float> visibilityKey;
  426. visibilityKey.frame = ix;
  427. visibilityKey.values = static_cast<float>(node->fbxNode()->Visibility.EvaluateValue(currTime));
  428. visibilityAnim->appendKey(visibilityKey);
  429. }
  430. }
  431. if (!posAnim->isConstant()){
  432. animations.push_back(posAnim);
  433. }
  434. if (!rotAnim->isConstant()){
  435. animations.push_back(rotAnim);
  436. }
  437. if (!scaleAnim->isConstant()){
  438. animations.push_back(scaleAnim);
  439. }
  440. if (!visibilityAnim->isConstant()) {
  441. animations.push_back(visibilityAnim);
  442. }
  443. if (!mesh) {
  444. return;
  445. }
  446. if (mesh->GetPolygonCount() == 0){
  447. return;
  448. }
  449. _receiveShadows = mesh->ReceiveShadow.Get();
  450. FbxGeometryConverter conv(mesh->GetFbxManager());
  451. conv.ComputePolygonSmoothingFromEdgeSmoothing(mesh);
  452. if (!mesh->IsTriangleMesh()) {
  453. mesh = (FbxMesh*) conv.Triangulate(mesh, true);
  454. }
  455. mesh->RemoveBadPolygons();
  456. mesh->GenerateNormals();
  457. FbxStringList uvSetNameList;
  458. mesh->GetUVSetNames(uvSetNameList);
  459. std::vector<std::string> uniqueUVSets;
  460. int uvCount = uvSetNameList.GetCount();
  461. for (int i = 0; i < uvCount; ++i) {
  462. std::string value = uvSetNameList.GetStringAt(i);
  463. if (std::find(uniqueUVSets.begin(), uniqueUVSets.end(), value) == uniqueUVSets.end()) {
  464. uniqueUVSets.push_back(value);
  465. }
  466. }
  467. uvsets = uniqueUVSets;
  468. bool hasUv = uniqueUVSets.size() > 0;
  469. bool hasUv2 = uniqueUVSets.size() > 1;
  470. bool hasUv3 = uniqueUVSets.size() > 2;
  471. bool hasUv4 = uniqueUVSets.size() > 3;
  472. bool hasUv5 = uniqueUVSets.size() > 4;
  473. bool hasUv6 = uniqueUVSets.size() > 5;
  474. std::string uvSetName;
  475. std::string uv2SetName;
  476. std::string uv3SetName;
  477. std::string uv4SetName;
  478. std::string uv5SetName;
  479. std::string uv6SetName;
  480. if (hasUv) {
  481. uvSetName = uniqueUVSets[0];
  482. }
  483. if (hasUv2) {
  484. uv2SetName = uniqueUVSets[1];
  485. }
  486. if (hasUv3) {
  487. uv3SetName = uniqueUVSets[2];
  488. }
  489. if (hasUv4) {
  490. uv4SetName = uniqueUVSets[3];
  491. }
  492. if (hasUv5) {
  493. uv5SetName = uniqueUVSets[4];
  494. }
  495. if (hasUv6) {
  496. uv6SetName = uniqueUVSets[5];
  497. }
  498. auto colors = mesh->GetElementVertexColor();
  499. FbxLayerElement::EMappingMode colorMappingMode;
  500. FbxLayerElement::EReferenceMode colorReferenceMode;
  501. if (colors) {
  502. colorMappingMode = colors->GetMappingMode();
  503. colorReferenceMode = colors->GetReferenceMode();
  504. }
  505. auto normals = mesh->GetElementNormal();
  506. FbxGeometryElementUV* uvs = nullptr;
  507. FbxGeometryElementUV* uvs2 = nullptr;
  508. FbxGeometryElementUV* uvs3 = nullptr;
  509. FbxGeometryElementUV* uvs4 = nullptr;
  510. FbxGeometryElementUV* uvs5 = nullptr;
  511. FbxGeometryElementUV* uvs6 = nullptr;
  512. FbxLayerElement::EMappingMode uvsMappingMode;
  513. FbxLayerElement::EReferenceMode uvsReferenceMode;
  514. FbxLayerElement::EMappingMode uvs2MappingMode;
  515. FbxLayerElement::EReferenceMode uvs2ReferenceMode;
  516. FbxLayerElement::EMappingMode uvs3MappingMode;
  517. FbxLayerElement::EReferenceMode uvs3ReferenceMode;
  518. FbxLayerElement::EMappingMode uvs4MappingMode;
  519. FbxLayerElement::EReferenceMode uvs4ReferenceMode;
  520. FbxLayerElement::EMappingMode uvs5MappingMode;
  521. FbxLayerElement::EReferenceMode uvs5ReferenceMode;
  522. FbxLayerElement::EMappingMode uvs6MappingMode;
  523. FbxLayerElement::EReferenceMode uvs6ReferenceMode;
  524. if (hasUv) {
  525. uvs = mesh->GetElementUV(uvSetName.c_str());
  526. uvsMappingMode = uvs->GetMappingMode();
  527. uvsReferenceMode = uvs->GetReferenceMode();
  528. }
  529. if (hasUv2) {
  530. uvs2 = mesh->GetElementUV(uv2SetName.c_str());
  531. uvs2MappingMode = uvs2->GetMappingMode();
  532. uvs2ReferenceMode = uvs2->GetReferenceMode();
  533. }
  534. if (hasUv3) {
  535. uvs3 = mesh->GetElementUV(uv3SetName.c_str());
  536. uvs3MappingMode = uvs3->GetMappingMode();
  537. uvs3ReferenceMode = uvs3->GetReferenceMode();
  538. }
  539. if (hasUv4) {
  540. uvs4 = mesh->GetElementUV(uv4SetName.c_str());
  541. uvs4MappingMode = uvs4->GetMappingMode();
  542. uvs4ReferenceMode = uvs4->GetReferenceMode();
  543. }
  544. if (hasUv5) {
  545. uvs5 = mesh->GetElementUV(uv5SetName.c_str());
  546. uvs5MappingMode = uvs5->GetMappingMode();
  547. uvs5ReferenceMode = uvs5->GetReferenceMode();
  548. }
  549. if (hasUv6) {
  550. uvs6 = mesh->GetElementUV(uv6SetName.c_str());
  551. uvs6MappingMode = uvs6->GetMappingMode();
  552. uvs6ReferenceMode = uvs6->GetReferenceMode();
  553. }
  554. auto normalMappingMode = normals->GetMappingMode();
  555. auto normalReferenceMode = normals->GetReferenceMode();
  556. std::vector<SubmeshData> submeshes;
  557. auto materialCount = node->fbxNode()->GetMaterialCount();
  558. if (materialCount == 0) {
  559. materialCount = 1;
  560. }
  561. submeshes.resize(materialCount);
  562. auto baseLayer = mesh->GetLayer(0);
  563. auto materials = baseLayer->GetMaterials();
  564. FbxLayerElement::EMappingMode materialMappingMode = materials ?
  565. materials->GetMappingMode() : FbxLayerElement::eByPolygon;
  566. // extract deformers
  567. SkinInfo skinInfo(fbxNode);
  568. if (skinInfo.hasSkin()){
  569. associatedSkeleton = std::make_shared<BabylonSkeleton>();
  570. skinInfo.buildBabylonSkeleton(*associatedSkeleton);
  571. }
  572. auto triangleCount = mesh->GetPolygonCount();
  573. for (int triangleIndex = 0; triangleIndex < triangleCount; ++triangleIndex) {
  574. int materialIndex = 0;
  575. if (materialCount > 0 && materials) {
  576. switch (materialMappingMode) {
  577. case FbxLayerElement::eAllSame:
  578. materialIndex = materials->GetIndexArray().GetAt(0);
  579. break;
  580. case FbxLayerElement::eByPolygon:
  581. materialIndex = materials->GetIndexArray().GetAt(triangleIndex);
  582. }
  583. }
  584. auto& submesh = submeshes[materialIndex];
  585. triangle t;
  586. for (int cornerIndex = 0; cornerIndex < 3; ++cornerIndex) {
  587. auto controlPointIndex = mesh->GetPolygonVertex(triangleIndex, cornerIndex);
  588. auto vertexIndex = triangleIndex * 3 + cornerIndex;
  589. auto position = mesh->GetControlPoints()[controlPointIndex];
  590. position[2] = -position[2];
  591. BabylonVertex v;
  592. v.position = position;
  593. if (normals) {
  594. int normalMapIndex = (normalMappingMode == FbxLayerElement::eByControlPoint) ?
  595. controlPointIndex : vertexIndex;
  596. int normalValueIndex = (normalReferenceMode == FbxLayerElement::eDirect) ?
  597. normalMapIndex : normals->GetIndexArray().GetAt(normalMapIndex);
  598. v.normal = normals->GetDirectArray().GetAt(normalValueIndex);
  599. v.normal.z = -v.normal.z;
  600. }
  601. if (colors) {
  602. int mappingIndex = (colorMappingMode == FbxLayerElement::eByControlPoint) ?
  603. controlPointIndex : vertexIndex;
  604. int valueIndex = (colorReferenceMode == FbxLayerElement::eDirect) ?
  605. mappingIndex : colors->GetIndexArray().GetAt(mappingIndex);
  606. v.color = colors->GetDirectArray().GetAt(valueIndex);
  607. }
  608. if (uvs) {
  609. int mappingIndex = (uvsMappingMode == FbxLayerElement::eByControlPoint) ?
  610. controlPointIndex : vertexIndex;
  611. int valueIndex = (uvsReferenceMode == FbxLayerElement::eDirect) ?
  612. mappingIndex : uvs->GetIndexArray().GetAt(mappingIndex);
  613. v.uv = uvs->GetDirectArray().GetAt(valueIndex);
  614. //v.uv.y = 1 - v.uv.y;
  615. }
  616. if (uvs2) {
  617. int mappingIndex = (uvs2MappingMode == FbxLayerElement::eByControlPoint) ?
  618. controlPointIndex : vertexIndex;
  619. int valueIndex = (uvs2ReferenceMode == FbxLayerElement::eDirect) ?
  620. mappingIndex : uvs2->GetIndexArray().GetAt(mappingIndex);
  621. v.uv2 = uvs2->GetDirectArray().GetAt(valueIndex);
  622. }
  623. if (uvs3) {
  624. int mappingIndex = (uvs3MappingMode == FbxLayerElement::eByControlPoint) ?
  625. controlPointIndex : vertexIndex;
  626. int valueIndex = (uvs3ReferenceMode == FbxLayerElement::eDirect) ?
  627. mappingIndex : uvs3->GetIndexArray().GetAt(mappingIndex);
  628. v.uv3 = uvs3->GetDirectArray().GetAt(valueIndex);
  629. }
  630. if (uvs4) {
  631. int mappingIndex = (uvs4MappingMode == FbxLayerElement::eByControlPoint) ?
  632. controlPointIndex : vertexIndex;
  633. int valueIndex = (uvs4ReferenceMode == FbxLayerElement::eDirect) ?
  634. mappingIndex : uvs4->GetIndexArray().GetAt(mappingIndex);
  635. v.uv4 = uvs4->GetDirectArray().GetAt(valueIndex);
  636. }
  637. if (uvs5) {
  638. int mappingIndex = (uvs5MappingMode == FbxLayerElement::eByControlPoint) ?
  639. controlPointIndex : vertexIndex;
  640. int valueIndex = (uvs5ReferenceMode == FbxLayerElement::eDirect) ?
  641. mappingIndex : uvs5->GetIndexArray().GetAt(mappingIndex);
  642. v.uv5 = uvs5->GetDirectArray().GetAt(valueIndex);
  643. }
  644. if (uvs6) {
  645. int mappingIndex = (uvs6MappingMode == FbxLayerElement::eByControlPoint) ?
  646. controlPointIndex : vertexIndex;
  647. int valueIndex = (uvs6ReferenceMode == FbxLayerElement::eDirect) ?
  648. mappingIndex : uvs6->GetIndexArray().GetAt(mappingIndex);
  649. v.uv6 = uvs6->GetDirectArray().GetAt(valueIndex);
  650. }
  651. if (skinInfo.hasSkin()){
  652. auto& skinData = skinInfo.controlPointBoneIndicesAndWeights(controlPointIndex);
  653. for (auto boneix = 0; boneix < skinData.size()&&boneix<4; ++boneix){
  654. v.boneIndices[boneix] = skinData[boneix].index;
  655. v.boneWeights[boneix] = static_cast<float>(skinData[boneix].weight);
  656. }
  657. for (auto boneix = skinData.size(); boneix < 4; ++boneix){
  658. v.boneIndices[boneix] = skinInfo.bonesCount();
  659. v.boneWeights[boneix] = 0;
  660. }
  661. }
  662. auto foundVertex = submesh.knownVertices.find(v);
  663. if (foundVertex != submesh.knownVertices.end()) {
  664. //submesh.indices.push_back(foundVertex->second);
  665. t.indices[cornerIndex] = foundVertex->second;
  666. }
  667. else {
  668. auto index = static_cast<int>(submesh.vertices.size());
  669. submesh.vertices.push_back(v);
  670. //submesh.indices.push_back(index);
  671. submesh.knownVertices[v] = index;
  672. t.indices[cornerIndex] = index;
  673. }
  674. }
  675. if (submesh.knownTriangles.insert(t).second) {
  676. submesh.indices.push_back(t.indices[0]);
  677. submesh.indices.push_back(t.indices[1]);
  678. submesh.indices.push_back(t.indices[2]);
  679. }
  680. else {
  681. std::cout << "duplicate triangle found (and eliminated) in " << fbxNode->GetName() << std::endl;
  682. }
  683. }
  684. std::uint32_t vertexOffset = 0;
  685. for (auto matIndex = 0u; matIndex < submeshes.size(); ++matIndex) {
  686. auto& submesh = submeshes[matIndex];
  687. BabylonSubmesh babsubmesh;
  688. babsubmesh.indexCount = static_cast<int>(submesh.indices.size());
  689. babsubmesh.indexStart = static_cast<int>(_indices.size());
  690. babsubmesh.materialIndex = matIndex;
  691. babsubmesh.verticesCount = static_cast<int>(submesh.vertices.size());
  692. babsubmesh.verticesStart = static_cast<int>(_positions.size());
  693. for (auto& v : submesh.vertices) {
  694. _positions.push_back(v.position);
  695. if (normals) {
  696. _normals.push_back(v.normal);
  697. }
  698. if (colors) {
  699. _colors.push_back(v.color);
  700. }
  701. if (uvs) {
  702. _uvs.push_back(v.uv);
  703. }
  704. if (uvs2) {
  705. _uvs2.push_back(v.uv2);
  706. }
  707. if (uvs3) {
  708. _uvs3.push_back(v.uv3);
  709. }
  710. if (uvs4) {
  711. _uvs4.push_back(v.uv4);
  712. }
  713. if (uvs5) {
  714. _uvs5.push_back(v.uv5);
  715. }
  716. if (uvs6) {
  717. _uvs6.push_back(v.uv6);
  718. }
  719. if (skinInfo.hasSkin()){
  720. float weight0 = v.boneWeights[0];
  721. float weight1 = v.boneWeights[1];
  722. float weight2 = v.boneWeights[2];
  723. int bone0 = v.boneIndices[0];
  724. int bone1 = v.boneIndices[1];
  725. int bone2 = v.boneIndices[2];
  726. int bone3 = v.boneIndices[3];
  727. _boneWeights.push_back(babylon_vector4( weight0, weight1, weight2, 1.0f - weight0 - weight1 - weight2));
  728. _boneIndices.push_back((bone3 << 24) | (bone2 << 16) | (bone1 << 8) | bone0);
  729. }
  730. }
  731. for (auto i : submesh.indices) {
  732. _indices.push_back(i + vertexOffset);
  733. }
  734. vertexOffset = static_cast<int>(_positions.size());
  735. _submeshes.push_back(babsubmesh);
  736. }
  737. }
  738. BabylonMesh::BabylonMesh(BabylonMesh && moved) :
  739. BabylonAbstractMesh(moved),
  740. _id(std::move(moved._id)),
  741. _parentId(std::move(moved._parentId)),
  742. _materialId(std::move(moved._materialId)),
  743. _isEnabled(std::move(moved._isEnabled)),
  744. _isVisible(std::move(moved._isVisible)),
  745. _pickable(std::move(moved._pickable)),
  746. _positions(std::move(moved._positions)),
  747. _normals(std::move(moved._normals)),
  748. _uvs(std::move(moved._uvs)),
  749. _uvs2(std::move(moved._uvs2)),
  750. _uvs3(std::move(moved._uvs3)),
  751. _uvs4(std::move(moved._uvs4)),
  752. _uvs5(std::move(moved._uvs5)),
  753. _uvs6(std::move(moved._uvs6)),
  754. _colors(std::move(moved._colors)),
  755. _hasVertexAlpha(std::move(moved._hasVertexAlpha)),
  756. _boneIndices(std::move(moved._boneIndices)),
  757. _boneWeights(std::move(moved._boneWeights)),
  758. _indices(std::move(moved._indices)),
  759. _checkCollision(std::move(moved._checkCollision)),
  760. _receiveShadows(std::move(moved._receiveShadows)),
  761. _infiniteDistance(std::move(moved._infiniteDistance)),
  762. _billboardMode(std::move(moved._billboardMode)),
  763. _visibility(std::move(moved._visibility)),
  764. _submeshes(std::move(moved._submeshes)),
  765. _instances(std::move(moved._instances)),
  766. _skeletonId(std::move(moved._skeletonId)),
  767. _autoAnimate(std::move(moved._autoAnimate)),
  768. _autoAnimateFrom(std::move(moved._autoAnimateFrom)),
  769. _autoAnimateTo(std::move(moved._autoAnimateTo)),
  770. _autoAnimateLoop(std::move(moved._autoAnimateLoop)),
  771. _showBoundingBox(std::move(moved._showBoundingBox)),
  772. _showSubMeshesBoundingBox(std::move(moved._showSubMeshesBoundingBox)),
  773. _applyFog(std::move(moved._applyFog)),
  774. _alphaIndex(std::move(moved._alphaIndex)),
  775. uvsets(std::move(moved.uvsets)),
  776. associatedSkeleton(std::move(moved.associatedSkeleton)),
  777. animations(std::move(moved.animations)),
  778. pivotMatrix(std::move(moved.pivotMatrix))
  779. {
  780. }
  781. void BabylonMesh::addInstance(BabylonNode * node)
  782. {
  783. _instances.emplace_back(node);
  784. }
  785. BabylonMesh::~BabylonMesh()
  786. {
  787. }