BabylonScene.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #include "stdafx.h"
  2. #include "BabylonScene.h"
  3. web::json::value BabylonScene::toJson()
  4. {
  5. auto jobj = web::json::value::object();
  6. jobj[L"autoClear"] = web::json::value::boolean(_autoClear);
  7. writeVector3(jobj, L"clearColor", _clearColor);
  8. writeVector3(jobj, L"ambientColor", _ambientColor);
  9. jobj[L"fogMode"] = web::json::value::number(_fogMode);
  10. writeVector3(jobj, L"fogColor", _fogColor);
  11. jobj[L"fogStart"] = web::json::value::number(_fogStart);
  12. jobj[L"fogEnd"] = web::json::value::number(_fogEnd);
  13. jobj[L"fogDensity"] = web::json::value::number(_fogDensity);
  14. writeVector3(jobj, L"gravity", _gravity);
  15. jobj[L"activeCameraID"] = web::json::value::string(_activeCameraID);
  16. auto jcameras = web::json::value::array();
  17. for (auto& cam : _cameras) {
  18. jcameras[jcameras.size()] = cam.toJson();
  19. }
  20. jobj[L"cameras"] = jcameras;
  21. auto jmeshes = web::json::value::array();
  22. for (auto& mesh : _meshes) {
  23. jmeshes[jmeshes.size()] = mesh.toJson();
  24. }
  25. jobj[L"meshes"] = jmeshes;
  26. auto jmats = web::json::value::array();
  27. for (auto& mat : _materials) {
  28. jmats[jmats.size()] = mat.toJson();
  29. }
  30. jobj[L"materials"] = jmats;
  31. auto jmulmats = web::json::value::array();
  32. for (auto& mat : _multiMaterials) {
  33. jmulmats[jmulmats.size()] = mat.toJson();
  34. }
  35. jobj[L"multiMaterials"] = jmulmats;
  36. auto jlights = web::json::value::array();
  37. for (auto& light : _lights) {
  38. jlights[jlights.size()] = light.toJson();
  39. }
  40. jobj[L"lights"] = jlights;
  41. auto jskeletons = web::json::value::array();
  42. for (auto& skel : _skeletons){
  43. jskeletons[jskeletons.size()] = skel->toJson();
  44. }
  45. jobj[L"skeletons"] = jskeletons;
  46. auto jshadowGenerators = web::json::value::array();
  47. for (auto& sg : _shadowGenerators) {
  48. jshadowGenerators[jshadowGenerators.size()] = sg->toJson();
  49. }
  50. jobj[L"shadowGenerators"] = jshadowGenerators;
  51. return jobj;
  52. }
  53. BabylonScene::BabylonScene() :
  54. _autoClear(true),
  55. _clearColor(.2f, .2f, .3f),
  56. _ambientColor(0,0,0),
  57. _gravity(0,0,-.9f)
  58. {
  59. }
  60. BabylonScene::BabylonScene(BabylonNode & rootNode, bool skipEmptyNodes) :
  61. _autoClear(true),
  62. _clearColor(.2f, .2f, .3f),
  63. _ambientColor(0, 0, 0),
  64. _gravity(0, 0, -.9f)
  65. {
  66. std::map<FbxMesh*, size_t> meshInstanceMap;
  67. exploreNodes(rootNode, skipEmptyNodes, meshInstanceMap);
  68. if (_cameras.size() == 0) {
  69. babylon_boundingbox bbox(rootNode.fbxNode()->GetScene());
  70. auto cam = buildCameraFromBoundingBox(bbox);
  71. _activeCameraID = cam.id;
  72. _cameras.push_back(std::move(cam));
  73. }
  74. if (_lights.size() == 0) {
  75. BabylonLight light;
  76. light.diffuse = babylon_vector3(1, 1, 1);
  77. light.specular = babylon_vector3(1, 1, 1);
  78. light.position = babylon_vector3(0, 0, 0);
  79. light.parentId = _activeCameraID;
  80. light.type = 0;
  81. light.id = L"default_light";
  82. light.name = L"default_light";
  83. light.intensity = 1;
  84. _lights.push_back(std::move(light));
  85. }
  86. }
  87. BabylonScene::BabylonScene(BabylonScene && moved) :
  88. _autoClear(std::move(moved._autoClear)),
  89. _clearColor(std::move(moved._clearColor)),
  90. _ambientColor(std::move(moved._ambientColor)),
  91. _fogMode(std::move(moved._fogMode)),
  92. _fogColor(std::move(moved._fogColor)),
  93. _fogStart(std::move(moved._fogStart)),
  94. _fogEnd(std::move(moved._fogEnd)),
  95. _fogDensity(std::move(moved._fogDensity)),
  96. _gravity(std::move(moved._gravity)),
  97. _cameras(std::move(moved._cameras)),
  98. _activeCameraID(std::move(moved._activeCameraID)),
  99. _meshes(std::move(moved._meshes)),
  100. _materials(std::move(moved._materials)),
  101. _multiMaterials(std::move(moved._multiMaterials)),
  102. _lights(std::move(moved._lights)),
  103. _shadowGenerators(std::move(moved._shadowGenerators)),
  104. _skeletons(std::move(moved._skeletons))
  105. {
  106. }
  107. BabylonScene::~BabylonScene()
  108. {
  109. }
  110. void fixupTextureCoordinateIndices(BabylonMaterial& mat, BabylonMesh& mesh) {
  111. std::vector<std::shared_ptr<BabylonTexture>> textures;
  112. if (mat.ambientTexture) {
  113. textures.push_back(mat.ambientTexture);
  114. }
  115. if (mat.diffuseTexture) {
  116. textures.push_back(mat.diffuseTexture);
  117. }
  118. if (mat.specularTexture) {
  119. textures.push_back(mat.specularTexture);
  120. }
  121. if (mat.emissiveTexture) {
  122. textures.push_back(mat.emissiveTexture);
  123. }
  124. if (mat.reflectionTexture) {
  125. textures.push_back(mat.reflectionTexture);
  126. }
  127. if (mat.bumpTexture) {
  128. textures.push_back(mat.bumpTexture);
  129. }
  130. for (auto& tex : textures) {
  131. auto found = std::find(mesh.uvsets.begin(), mesh.uvsets.end(), tex->uvset);
  132. if (found != mesh.uvsets.end()) {
  133. tex->coordinatesIndex = static_cast<int>(found - mesh.uvsets.begin());
  134. }
  135. }
  136. }
  137. bool isAlreadyInstanciatedMesh(FbxNode* node, std::map<FbxMesh*, size_t>& meshInstanceMap, size_t* oIndex) {
  138. auto mesh = node->GetMesh();
  139. if (!mesh) {
  140. return false;
  141. }
  142. auto found = meshInstanceMap.find(mesh);
  143. if (found == meshInstanceMap.end()) {
  144. return false;
  145. }
  146. *oIndex = found->second;
  147. return true;
  148. }
  149. void BabylonScene::exploreNodes(BabylonNode & node, bool skipEmptyNodes, std::map<FbxMesh*, size_t>& meshInstanceMap)
  150. {
  151. if (node.nodeType() == BabylonNodeType::Skeleton && node.hasOnlySkeletonDescendants()) {
  152. return;
  153. }
  154. if (skipEmptyNodes && node.isEmptySkeletonOrEmptyMeshRecursive()) {
  155. return;
  156. }
  157. // append mesh
  158. switch (node.nodeType())
  159. {
  160. case BabylonNodeType::Empty:
  161. case BabylonNodeType::Mesh:
  162. case BabylonNodeType::Skeleton:
  163. {
  164. size_t instanceOwnerIndex;
  165. if (isAlreadyInstanciatedMesh(node.fbxNode(), meshInstanceMap, &instanceOwnerIndex)) {
  166. _meshes[instanceOwnerIndex].addInstance(&node);
  167. }
  168. else {
  169. BabylonMesh mesh(&node);
  170. auto matCount = node.fbxNode()->GetMaterialCount();
  171. BabylonMultiMaterial multiMat;
  172. for (auto i = 0; i < matCount; ++i) {
  173. auto mat = node.fbxNode()->GetMaterial(i);
  174. if (mat) {
  175. auto id = getMaterialId(mat);
  176. auto existing = std::find_if(_materials.begin(), _materials.end(), [id](const BabylonMaterial& e) {
  177. return e.id == id;
  178. });
  179. if (existing == _materials.end()) {
  180. auto babMat = BabylonMaterial(mat);
  181. fixupTextureCoordinateIndices(babMat, mesh);
  182. _materials.push_back(std::move(babMat));
  183. }
  184. multiMat.materials.push_back(id);
  185. }
  186. }
  187. if (mesh.associatedSkeleton) {
  188. mesh.associatedSkeleton->id = static_cast<int>(_skeletons.size() + 1);
  189. mesh.skeletonId(static_cast<int>(_skeletons.size() + 1));
  190. _skeletons.push_back(mesh.associatedSkeleton);
  191. }
  192. if (multiMat.materials.size() > 0) {
  193. multiMat.id = mesh.id();
  194. multiMat.name = mesh.name();
  195. mesh.materialId(multiMat.id);
  196. _multiMaterials.push_back(std::move(multiMat));
  197. }
  198. auto fbxMesh = node.fbxNode()->GetMesh();
  199. if (fbxMesh) {
  200. meshInstanceMap[fbxMesh] = _meshes.size();
  201. }
  202. _meshes.push_back(std::move(mesh));
  203. }
  204. }
  205. break;
  206. case BabylonNodeType::Camera:
  207. {
  208. _cameras.emplace_back(node);
  209. if (_cameras.size() == 1) {
  210. activeCameraID(_cameras[0].id);
  211. }
  212. }
  213. break;
  214. case BabylonNodeType::Light:
  215. {
  216. _lights.emplace_back(node);
  217. auto& l = _lights[_lights.size() - 1];
  218. if (l.shadowGenerator) {
  219. _shadowGenerators.push_back(l.shadowGenerator);
  220. }
  221. }
  222. break;
  223. default:
  224. break;
  225. }
  226. for (auto& child : node.children()) {
  227. exploreNodes(child, skipEmptyNodes, meshInstanceMap);
  228. }
  229. }