BabylonMesh.cpp 28 KB

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