JSONSceneProcess.cpp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000
  1. //
  2. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  3. // LICENSE: Atomic Game Engine Editor and Tools EULA
  4. // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
  5. // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
  6. //
  7. #include <stdint.h>
  8. #include <Atomic/Core/ProcessUtils.h>
  9. #include <Atomic/IO/Log.h>
  10. #include <Atomic/IO/FileSystem.h>
  11. #include <Atomic/Resource/Image.h>
  12. #include <Atomic/Graphics/IndexBuffer.h>
  13. #include <Atomic/Graphics/VertexBuffer.h>
  14. #include <Atomic/Graphics/Geometry.h>
  15. #include <Atomic/Graphics/Octree.h>
  16. #include <Atomic/Graphics/Zone.h>
  17. #include <Atomic/Atomic3D/AnimatedModel.h>
  18. #include <Atomic/Atomic3D/StaticModel.h>
  19. #include <Atomic/Atomic3D/LMStaticModel.h>
  20. #include <Atomic/Atomic3D/Terrain.h>
  21. #include <Atomic/Atomic3D/Animation.h>
  22. #include <Atomic/Graphics/DebugRenderer.h>
  23. #include <Atomic/Physics/CollisionShape.h>
  24. #include <Atomic/Physics/RigidBody.h>
  25. #include <Atomic/Physics/PhysicsWorld.h>
  26. #include <Atomic/Environment/TimeOfDay.h>
  27. #include "JSONSceneProcess.h"
  28. #include "JSONSceneImporter.h"
  29. namespace ToolCore
  30. {
  31. bool JSONSceneProcess::ProcessTextures()
  32. {
  33. const PODVector<JSONTexture*>& textures = importer_->GetTextures();
  34. for (unsigned i = 0; i < textures.Size(); i++)
  35. {
  36. const JSONTexture* jtexture = textures.At(i);
  37. unsigned length;
  38. const unsigned char* pixels = jtexture->GetPNGPixels(length);
  39. String filename = resourcePath_ + "Textures/" + jtexture->GetName() + ".png";
  40. SharedPtr<File> file (new File(context_, filename, FILE_WRITE));
  41. file->Write(pixels, length);
  42. file->Close();
  43. }
  44. return true;
  45. }
  46. bool JSONSceneProcess::ProcessLightmaps()
  47. {
  48. const PODVector<JSONLightmap*>& lightmaps = importer_->GetLightmaps();
  49. for (unsigned i = 0; i < lightmaps.Size(); i++)
  50. {
  51. const JSONLightmap* jlightmap = lightmaps.At(i);
  52. unsigned length;
  53. const unsigned char* pixels = jlightmap->GetPNGPixels(length);
  54. String filename = resourcePath_ + "Textures/" + jlightmap->GetName() + ".png";
  55. SharedPtr<File> file (new File(context_, filename, FILE_WRITE));
  56. file->Write(pixels, length);
  57. file->Close();
  58. }
  59. return true;
  60. }
  61. bool JSONSceneProcess::ProcessMaterials()
  62. {
  63. const PODVector<JSONMaterial*>& materials = importer_->GetMaterials();
  64. ResourceCache* cache = GetSubsystem<ResourceCache>();
  65. for (unsigned i = 0; i < materials.Size(); i++)
  66. {
  67. const JSONMaterial* jmaterial = materials.At(i);
  68. const String& shader = jmaterial->GetShader();
  69. //LOGINFOF("Shader: %s", shader.CString());
  70. // TODO: factor in lightmaps
  71. bool lightmap = false;
  72. String technique("Diff.xml");
  73. if (!lightmap)
  74. {
  75. if (shader == "Transparent/Diffuse")
  76. technique = "DiffAlpha.xml";
  77. else if (shader == "Transparent/Cutout/Diffuse")
  78. technique = "DiffAlphaMask.xml";
  79. else if (shader == "Transparent/Cutout/Specular")
  80. technique = "DiffAlphaMask.xml";
  81. else if (shader == "Transparent/Specular")
  82. technique = "DiffAlpha.xml";
  83. else if (shader == "Hidden/Nature/Tree Creator Leaves Fast Optimized")
  84. technique = "DiffAlphaMask.xml";
  85. }
  86. else
  87. {
  88. technique = "DiffLightMap.xml";
  89. if (shader == "Transparent/Diffuse")
  90. technique = "DiffLightMapAlpha.xml";
  91. else if (shader == "Transparent/Cutout/Diffuse")
  92. technique = "DiffLightMapAlpha.xml";
  93. else if (shader == "Transparent/Cutout/Specular")
  94. technique = "DiffLightMapAlpha.xml";
  95. else if (shader == "Transparent/Specular")
  96. technique = "DiffLightMapAlpha.xml";
  97. }
  98. SharedPtr<Material> material;
  99. material = new Material(context_);
  100. material->SetName("Materials/" + jmaterial->GetName() + ".material");
  101. Technique* _technique = cache->GetResource<Technique>("Techniques/" + technique);
  102. assert(_technique);
  103. material->SetTechnique(0, _technique);
  104. const String& mainTexture = jmaterial->GetMainTexture();
  105. if (mainTexture.Length())
  106. {
  107. Texture2D* texture = cache->GetResource<Texture2D>("Textures/" + mainTexture + ".png");
  108. material->SetTexture(TU_DIFFUSE, texture);
  109. }
  110. materials_[jmaterial->GetName()] = material;
  111. }
  112. return true;
  113. }
  114. bool JSONSceneProcess::WriteMaterials()
  115. {
  116. String materialFolder("Materials");
  117. HashMap<String, SharedPtr<Material> >::Iterator itr = materials_.Begin();
  118. while (itr != materials_.End())
  119. {
  120. Material* material = itr->second_;
  121. SharedPtr<File> file;
  122. file = new File(context_, resourcePath_ + material->GetName(), FILE_WRITE);
  123. material->Save(*file);
  124. itr++;
  125. }
  126. return true;
  127. }
  128. bool JSONSceneProcess::WriteModels()
  129. {
  130. HashMap<String, SharedPtr<Model> >::Iterator itr = models_.Begin();
  131. while (itr != models_.End())
  132. {
  133. Model* model = itr->second_;
  134. SharedPtr<File> file;
  135. file = new File(context_, resourcePath_ + model->GetName(), FILE_WRITE);
  136. model->Save(*file);
  137. itr++;
  138. }
  139. return true;
  140. }
  141. bool JSONSceneProcess::WriteHierarchy(Scene* scene)
  142. {
  143. List<SharedPtr<Node> >::Iterator itr = hierarchy_.Begin();
  144. while (itr != hierarchy_.End())
  145. {
  146. scene->AddChild(*itr);
  147. itr++;
  148. }
  149. File file(context_);
  150. bool useXML = true;
  151. String filename;
  152. filename.AppendWithFormat("%s", importer_->GetSceneName().CString());
  153. //if (!useXML)
  154. filename += ".scene";
  155. //else
  156. //filename += ".xml";
  157. filename = resourcePath_ + "Scenes/" + filename;
  158. if (!file.Open(filename, FILE_WRITE))
  159. ErrorExit("Could not open output file: Scenes/Test.bin");
  160. if (useXML)
  161. scene->SaveXML(file);
  162. else
  163. scene->Save(file);
  164. file.Close();
  165. return true;
  166. }
  167. bool JSONSceneProcess::ProcessModels()
  168. {
  169. PODVector<JSONMesh*>& meshes = importer_->GetMeshes();
  170. ResourceCache* cache = GetSubsystem<ResourceCache>();
  171. for (unsigned i = 0; i < meshes.Size(); i++)
  172. {
  173. JSONMesh* jmesh = meshes.At(i);
  174. SharedPtr<Model> model(new Model(context_));
  175. model->SetName("Models/" + jmesh->GetName() + ".mdl");
  176. unsigned vertexElementMask = MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1;// | MASK_COLOR;
  177. if (jmesh->GetNumUVSets() == 2)
  178. vertexElementMask |= MASK_TEXCOORD2;
  179. PODVector<JSONMesh::BoneWeight>& boneWeights = jmesh->GetBoneWeights();
  180. if (boneWeights.Size())
  181. vertexElementMask |= (MASK_BLENDWEIGHTS | MASK_BLENDINDICES);
  182. // the model has to have 65535 or less indices to avoid 32 bit indices, check this
  183. SharedPtr<IndexBuffer> ib (new IndexBuffer(context_));
  184. SharedPtr<VertexBuffer> vb (new VertexBuffer(context_));
  185. // even though shadowing, need to "SetData()" on these below
  186. // could we SetData with the shadowed data?
  187. ib->SetShadowed(true);
  188. vb->SetShadowed(true);
  189. // Setup Vertex Data
  190. unsigned vertexCount = jmesh->GetVertexCount();
  191. vb->SetSize(vertexCount, vertexElementMask);
  192. BoundingBox bbox;
  193. PODVector<Vector3>& vpos = jmesh->GetVertexPositions();
  194. PODVector<Vector3>& vnorm = jmesh->GetVertexNormals();
  195. PODVector<Vector4>& vtan = jmesh->GetVertexTangents();
  196. PODVector<Vector2>& uv0 = jmesh->GetUVSet(0);
  197. PODVector<Vector2>& uv1 = jmesh->GetUVSet(1);
  198. PODVector<float> vdata;
  199. unsigned vertexSize = 8;
  200. if (vertexElementMask & MASK_TEXCOORD2)
  201. vertexSize += 2;
  202. if (vertexElementMask & MASK_BLENDWEIGHTS)
  203. vertexSize += 5;
  204. vdata.Resize(vertexCount * vertexSize);
  205. // TODO: we should be identifying unique vertices
  206. float* v = &vdata[0];
  207. for (unsigned j = 0; j < vertexCount; j++)
  208. {
  209. if (j < vpos.Size())
  210. {
  211. *v = vpos[j].x_; v++;
  212. *v = vpos[j].y_; v++;
  213. *v = vpos[j].z_; v++;
  214. }
  215. else
  216. {
  217. *v = 0; v++;
  218. *v = 0; v++;
  219. *v = 0; v++;
  220. }
  221. if (j < vnorm.Size())
  222. {
  223. *v = vnorm[j].x_; v++;
  224. *v = vnorm[j].y_; v++;
  225. *v = vnorm[j].z_; v++;
  226. }
  227. else
  228. {
  229. *v = 0; v++;
  230. *v = 0; v++;
  231. *v = 0; v++;
  232. }
  233. if (j < uv0.Size())
  234. {
  235. *v = uv0[j].x_; v++;
  236. *v = -uv0[j].y_; v++;
  237. }
  238. else
  239. {
  240. *v = 0; v++;
  241. *v = 0; v++;
  242. }
  243. if (vertexElementMask & MASK_TEXCOORD2)
  244. {
  245. if (j < uv1.Size())
  246. {
  247. *v = uv1[j].x_; v++;
  248. *v = -uv1[j].y_; v++;
  249. }
  250. else
  251. {
  252. *v = 0; v++;
  253. *v = 0; v++;
  254. }
  255. }
  256. if (vertexElementMask & MASK_BLENDWEIGHTS)
  257. {
  258. JSONMesh::BoneWeight& boneWeight = boneWeights[j];
  259. for (unsigned k = 0; k < 4; ++k)
  260. {
  261. *v = boneWeight.weights_[k]; v++;
  262. }
  263. }
  264. if (vertexElementMask & MASK_BLENDINDICES)
  265. {
  266. JSONMesh::BoneWeight& boneWeight = boneWeights[j];
  267. unsigned char* destBytes = (unsigned char*)v;
  268. ++v;
  269. for (unsigned k = 0; k < 4; ++k)
  270. {
  271. *destBytes++ = (unsigned char) boneWeight.indexes_[k];
  272. }
  273. }
  274. bbox.Merge(vpos[j]);
  275. }
  276. vb->SetData(&vdata[0]);
  277. unsigned numIndices = 0;
  278. PODVector<uint16_t> allIndices;
  279. unsigned numGeom = jmesh->GetSubMeshCount();
  280. for (unsigned j = 0; j < numGeom; j++)
  281. {
  282. PODVector<int>& submesh = jmesh->GetSubMesh(j);
  283. numIndices += submesh.Size();
  284. for (unsigned k = 0; k < submesh.Size(); k++)
  285. {
  286. allIndices.Push((uint16_t) submesh[k]);
  287. }
  288. }
  289. ib->SetSize(numIndices, false);
  290. ib->SetData(&allIndices[0]);
  291. Vector<SharedPtr<Geometry> > geometry;
  292. uint16_t start = 0;
  293. for (unsigned j = 0; j < numGeom; j++)
  294. {
  295. PODVector<int>& submesh = jmesh->GetSubMesh(j);
  296. SharedPtr<Geometry> geom(new Geometry(context_));
  297. geometry.Push(geom);
  298. geom->SetIndexBuffer(ib);
  299. geom->SetVertexBuffer(0, vb, vertexElementMask);
  300. geom->SetDrawRange(TRIANGLE_LIST, start, submesh.Size(), false);
  301. start += submesh.Size();
  302. }
  303. model->SetNumGeometries(geometry.Size());
  304. Vector<SharedPtr<VertexBuffer> > vbVector;
  305. Vector<SharedPtr<IndexBuffer> > ibVector;
  306. vbVector.Push(vb);
  307. ibVector.Push(ib);
  308. PODVector<unsigned> emptyMorphRange;
  309. model->SetVertexBuffers(vbVector, emptyMorphRange, emptyMorphRange);
  310. model->SetIndexBuffers(ibVector);
  311. Vector<JSONMesh::Bone>& jbones = jmesh->GetBones();
  312. // FIXME: we need to get the bounds or calculate propoer
  313. if (jbones.Size())
  314. {
  315. bbox.min_ *= 2;
  316. bbox.max_ *= 2;
  317. }
  318. // see fixme's for skeletal geo center/bounds
  319. for (unsigned j = 0; j < geometry.Size(); j++)
  320. {
  321. model->SetNumGeometryLodLevels(j, 1);
  322. model->SetGeometry(j, 0, geometry[j]);
  323. // this could be finer grained
  324. // also, fix this for skeletal
  325. model->SetGeometryCenter(j, jbones.Size() ? Vector3::ZERO : bbox.Center());//Vector3::ZERO);
  326. }
  327. // FIXME: skeletal bounds is off
  328. if (!jbones.Size())
  329. model->SetBoundingBox(bbox);
  330. else
  331. model->SetBoundingBox(BoundingBox(-1024, 1024));
  332. // Build skeleton if necessary
  333. if (jbones.Size())
  334. {
  335. Skeleton skeleton;
  336. Vector<Bone>& bones = skeleton.GetModifiableBones();
  337. unsigned rootindex = 0;
  338. const String& rootBoneName = jmesh->GetRootBone();
  339. for (unsigned j = 0; j < jbones.Size(); ++j)
  340. {
  341. JSONMesh::Bone& jbone = jbones[j];
  342. if (jbone.name_ == rootBoneName)
  343. {
  344. rootindex = j;
  345. break;
  346. }
  347. }
  348. for (unsigned j = 0; j < jbones.Size(); ++j)
  349. {
  350. JSONMesh::Bone& jbone = jbones[j];
  351. String boneName(jbone.name_);
  352. Bone newBone;
  353. newBone.name_ = boneName;
  354. newBone.initialPosition_ = jbone.pos_;
  355. newBone.initialRotation_ = jbone.rot_;
  356. newBone.initialScale_ = jbone.scale_;
  357. // Get offset information if exists
  358. newBone.offsetMatrix_ = Matrix3x4(jmesh->GetBindPoses()[j]);
  359. //newBone.radius_ = model.boneRadii_[i];
  360. //newBone.boundingBox_ = model.boneHitboxes_[i];
  361. //newBone.collisionMask_ = BONECOLLISION_SPHERE | BONECOLLISION_BOX;
  362. newBone.parentIndex_ = j;
  363. bones.Push(newBone);
  364. }
  365. // Set the bone hierarchy
  366. for (unsigned j = 0; j < jbones.Size(); ++j)
  367. {
  368. JSONMesh::Bone& jbone = jbones[j];
  369. String parentName = jbone.parentName_;
  370. if (!parentName.Length())
  371. {
  372. bones[j].parentIndex_ = j;
  373. }
  374. else
  375. {
  376. for (unsigned k = 0; k < bones.Size(); ++k)
  377. {
  378. if (bones[k].name_ == parentName)
  379. {
  380. bones[j].parentIndex_ = k;
  381. break;
  382. }
  383. }
  384. }
  385. }
  386. skeleton.SetRootBoneIndex(rootindex);
  387. model->SetSkeleton(skeleton);
  388. }
  389. models_[jmesh->GetName()] = model;
  390. }
  391. return true;
  392. }
  393. bool JSONSceneProcess::ProcessComponent(Node* node, const JSONTransform* jtransform)
  394. {
  395. node->SetPosition(jtransform->GetLocalPosition());
  396. node->SetRotation(jtransform->GetLocalRotation());
  397. node->SetScale(jtransform->GetLocalScale());
  398. return true;
  399. }
  400. bool JSONSceneProcess::ProcessComponent(Node* node, const JSONTimeOfDay* jtime )
  401. {
  402. TimeOfDay* timeofday = node->CreateComponent<TimeOfDay>();
  403. timeofday->SetTimeOn(jtime->GetTimeOn());
  404. timeofday->SetTimeOff(jtime->GetTimeOff());
  405. return true;
  406. }
  407. bool JSONSceneProcess::ProcessComponent(Node* node, const JSONLight* jlight )
  408. {
  409. if (!jlight->GetRealtime() || jlight->GetLightType() != "Point")
  410. return true;
  411. Light* light = node->CreateComponent<Light>();
  412. light->SetRange(jlight->GetRange());
  413. light->SetCastShadows(jlight->GetCastsShadows());
  414. light->SetColor(jlight->GetColor());
  415. light->SetLightType(LIGHT_POINT);
  416. return true;
  417. }
  418. bool JSONSceneProcess::ProcessComponent(Node* node, const JSONBoxCollider* jbox )
  419. {
  420. CollisionShape* shape = node->CreateComponent<CollisionShape>();
  421. shape->SetBox(jbox->GetSize(), jbox->GetCenter());
  422. return true;
  423. }
  424. bool JSONSceneProcess::ProcessComponent(Node* node, const JSONMeshCollider* jmesh )
  425. {
  426. // JSONMeshCollider should store the mesh, as this may not be on node
  427. CollisionShape* shape = node->CreateComponent<CollisionShape>();
  428. StaticModel* model = node->GetComponent<StaticModel>();
  429. if (!model || !model->GetModel())
  430. {
  431. LOGWARNING("Missing model for MeshCollier");
  432. return true;
  433. }
  434. assert(model && model->GetModel());
  435. if (model)
  436. shape->SetTriangleMesh(model->GetModel());
  437. return true;
  438. }
  439. bool JSONSceneProcess::ProcessComponent(Node* node, const JSONRigidBody* jbody )
  440. {
  441. RigidBody* body = node->CreateComponent<RigidBody>();
  442. body->SetMass(jbody->GetMass());
  443. return true;
  444. }
  445. bool JSONSceneProcess::ProcessComponent(Node* node, const JSONTerrain* jterrain)
  446. {
  447. int heightmapHeight = jterrain->GetHeightMapHeight();
  448. int heightmapWidth = jterrain->GetHeightMapWidth();
  449. unsigned length;
  450. const float* heightmap = jterrain->GetHeightMap(length);
  451. const Vector3 heightmapScale = jterrain->GetHeightMapScale();
  452. const Vector3 heightmapSize = jterrain->GetHeightMapSize();
  453. PODVector<uint8_t> bytes;
  454. bytes.Resize(heightmapHeight * heightmapWidth * 4);
  455. uint8_t* out = &bytes[0];
  456. for (int y = 0; y < heightmapHeight; y++)
  457. {
  458. for (int x = 0; x < heightmapWidth; x++)
  459. {
  460. float h = heightmap[y * heightmapWidth + x];
  461. uint8_t hbyte = uint8_t(255.0 * h);
  462. *out++ = hbyte;
  463. *out++ = hbyte;
  464. *out++ = hbyte;
  465. *out++ = 255;
  466. }
  467. }
  468. SharedPtr<Image> image(new Image(context_));
  469. image->SetSize(heightmapWidth, heightmapHeight, 4);
  470. image->SetData(&bytes[0]);
  471. String heightMapPath = resourcePath_ + "Textures/TerrainHeightMap.png";
  472. image->SavePNG(heightMapPath);
  473. int alphamapWidth = jterrain->GetAlphaMapHeight();
  474. int alphamapHeight = jterrain->GetAlphaMapWidth();
  475. int alphamapLayers = jterrain->GetAlphaMapLayers();
  476. if (alphamapLayers > 3)
  477. alphamapLayers = 3;
  478. const float* alphamap = jterrain->GetAlphaMap(length);
  479. bytes.Resize( alphamapWidth * alphamapWidth * 4);
  480. memset (&bytes[0], 255, alphamapWidth * alphamapWidth * 4);
  481. for (int i = 0; i < alphamapLayers; i++)
  482. {
  483. uint8_t* out = &bytes[i];
  484. for (int y = 0; y < alphamapHeight; y++)
  485. {
  486. for (int x = 0; x < alphamapWidth; x++)
  487. {
  488. float w = alphamap[(i * (alphamapWidth * alphamapHeight)) + y * alphamapWidth + x ];
  489. uint8_t wbyte = uint8_t(255.0 * w);
  490. *out = wbyte;
  491. out += 4;
  492. }
  493. }
  494. }
  495. SharedPtr<Image> alphaWeights(new Image(context_));
  496. alphaWeights->SetSize(alphamapWidth, alphamapHeight, 4);
  497. alphaWeights->SetData(&bytes[0]);
  498. String alphaWeightsPath = resourcePath_ + "Textures/TerrainWeights.png";
  499. alphaWeights->SavePNG(alphaWeightsPath);
  500. ResourceCache* cache = GetSubsystem<ResourceCache>();
  501. Image* heightMap = cache->GetResource<Image>(heightMapPath);
  502. Material* material = cache->GetResource<Material>("Materials/DemoTerrain.material");
  503. Terrain* terrain = node->CreateComponent<Terrain>();
  504. terrain->SetHeightMap(heightMap);
  505. terrain->SetMaterial(material);
  506. terrain->SetSmoothing(true);
  507. //terrain->SetPatchSize(64);
  508. //terrain->SetSpacing(Vector3(2.0f, 0.5f, 2.0f)); // Spacing between vertices and vertical resolution of the height map
  509. //terrain->SetSmoothing(true);
  510. Vector3 spacing = heightmapScale;
  511. spacing.y_ = heightmapScale.y_ / 250.0f;
  512. terrain->SetSpacing(spacing);
  513. Vector3 pos = node->GetPosition();
  514. pos.x_ += heightmapSize.x_/2.0f;
  515. pos.y_ += .1f;
  516. pos.z_ += heightmapSize.z_/2.0f;
  517. node->SetPosition(pos);
  518. Quaternion rotation;
  519. rotation = node->GetRotation();
  520. rotation.FromEulerAngles(0, -90, 0);
  521. node->SetRotation(rotation);
  522. RigidBody* body = node->CreateComponent<RigidBody>();
  523. // use layer 2 for static
  524. body->SetCollisionLayer(2);
  525. body->SetFriction(1.0f);
  526. CollisionShape* shape = node->CreateComponent<CollisionShape>();
  527. shape->SetTerrain();
  528. return true;
  529. }
  530. bool JSONSceneProcess::ProcessComponent(Node* node, const JSONAnimation* janim )
  531. {
  532. const Vector<JSONAnimation::AnimationClip*>& clips = janim->GetClips();
  533. for (unsigned i = 0; i < clips.Size(); i++)
  534. {
  535. const JSONAnimation::AnimationClip* clip = clips[i];
  536. SharedPtr<Animation> outAnim(new Animation(context_));
  537. outAnim->SetAnimationName(clip->name_);
  538. outAnim->SetLength(clip->GetDuration());
  539. Vector<AnimationTrack> tracks;
  540. for (unsigned j = 0; j < clip->nodes_.Size(); ++j)
  541. {
  542. const JSONAnimation::AnimationNode* node = clip->nodes_[j];
  543. String channelName = node->name_;
  544. if (channelName.Contains('/'))
  545. {
  546. channelName = channelName.Split('/').Back();
  547. }
  548. AnimationTrack track;
  549. track.name_ = channelName;
  550. track.nameHash_ = channelName;
  551. // TODO: optimize channels
  552. track.channelMask_ |= (CHANNEL_POSITION | CHANNEL_ROTATION | CHANNEL_SCALE);
  553. //assert(node->keyframes_.Size());
  554. for (unsigned k = 0; k < node->keyframes_.Size(); k++)
  555. {
  556. const JSONAnimation::Keyframe* keyframe = node->keyframes_[k];
  557. AnimationKeyFrame key;
  558. key.time_ = keyframe->time_;
  559. key.position_ = keyframe->pos_;
  560. key.rotation_ = keyframe->rot_;
  561. key.scale_ = keyframe->scale_;
  562. track.keyFrames_.Push(key);
  563. }
  564. tracks.Push(track);
  565. }
  566. outAnim->SetTracks(tracks);
  567. String filename = resourcePath_;
  568. filename.AppendWithFormat("Models/FIXME_ANIMATION_PROCESSNAME_%s.ani", clip->name_.CString());
  569. File outFile(context_);
  570. if (!outFile.Open(filename, FILE_WRITE))
  571. ErrorExit("Could not open output file for animation");
  572. outAnim->Save(outFile);
  573. }
  574. return true;
  575. }
  576. bool JSONSceneProcess::ProcessComponent(Node* node, const JSONMeshRenderer* jmeshrenderer )
  577. {
  578. ResourceCache* cache = GetSubsystem<ResourceCache>();
  579. StaticModel* staticModel = NULL;
  580. int lightmapIndex = jmeshrenderer->GetLightmapIndex();
  581. if (lightmapIndex >= 0)
  582. {
  583. LMStaticModel* lmstatic = node->CreateComponent<LMStaticModel>();
  584. staticModel = lmstatic;
  585. const Vector4& tilingOffset = jmeshrenderer->GetLightmapTilingOffset();
  586. lmstatic->lightmapTilingOffset_ = tilingOffset;
  587. lmstatic->lightmapTilingOffset_.w_ = -lmstatic->lightmapTilingOffset_.w_;
  588. String lightmapName;
  589. lightmapName.AppendWithFormat("Textures/%s_Lightmap_%i.png", importer_->GetSceneName().CString(), lightmapIndex);
  590. Texture2D* texture = cache->GetResource<Texture2D>(lightmapName);
  591. assert(texture);
  592. lmstatic->SetLightmapTexure(texture);
  593. }
  594. else
  595. staticModel = node->CreateComponent<StaticModel>();
  596. const JSONMesh* mesh = jmeshrenderer->GetMesh();
  597. assert(models_.Contains(mesh->GetName()));
  598. Model* model = models_[mesh->GetName()];
  599. staticModel->SetModel(model);
  600. for (unsigned i = 0; i < jmeshrenderer->GetNumMaterials(); i++)
  601. {
  602. const JSONMaterial* jmat = jmeshrenderer->GetMaterial(i);
  603. assert(materials_.Contains(jmat->GetName()));
  604. staticModel->SetMaterial(i, materials_[jmat->GetName()]);
  605. }
  606. staticModel->SetCastShadows(jmeshrenderer->GetCastShadows());
  607. /*
  608. CollisionShape* shape = node->CreateComponent<CollisionShape>();
  609. shape->SetTriangleMesh(model, 0);
  610. node->CreateComponent<RigidBody>();
  611. */
  612. BoundingBox bbox = model->GetBoundingBox();
  613. bbox.Transform(node->GetWorldTransform());
  614. Vector3 size = bbox.Size();
  615. //staticModel->SetDrawDistance(size.Length() * 30.0f);
  616. //staticModel->SetShadowDistance(size.Length() * 10.0f);
  617. return true;
  618. }
  619. bool JSONSceneProcess::ProcessComponent(Node* node, const JSONSkinnedMeshRenderer* jmeshrenderer )
  620. {
  621. ResourceCache* cache = GetSubsystem<ResourceCache>();
  622. AnimatedModel* animatedModel = node->CreateComponent<AnimatedModel>();
  623. const JSONMesh* mesh = jmeshrenderer->GetMesh();
  624. assert(models_.Contains(mesh->GetName()));
  625. Model* model = models_[mesh->GetName()];
  626. animatedModel->SetModel(model);
  627. for (unsigned i = 0; i < jmeshrenderer->GetNumMaterials(); i++)
  628. {
  629. const JSONMaterial* jmat = jmeshrenderer->GetMaterial(i);
  630. assert(materials_.Contains(jmat->GetName()));
  631. animatedModel->SetMaterial(i, materials_[jmat->GetName()]);
  632. }
  633. animatedModel->SetCastShadows(jmeshrenderer->GetCastShadows());
  634. return true;
  635. }
  636. Node* JSONSceneProcess::ProcessNode(const JSONNode* jnode, Node* parent)
  637. {
  638. Node* node = parent->CreateChild(jnode->GetName());
  639. const PODVector<JSONComponent*>& components = jnode->GetComponents();
  640. for (unsigned i = 0; i < components.Size(); i++)
  641. {
  642. const JSONComponent* c = components.At(i);
  643. if (c->GetType() == "Transform")
  644. {
  645. ProcessComponent(node, (const JSONTransform*) c);
  646. }
  647. else if (c->GetType() == "MeshRenderer")
  648. {
  649. ProcessComponent(node, (const JSONMeshRenderer*) c);
  650. }
  651. else if (c->GetType() == "SkinnedMeshRenderer")
  652. {
  653. ProcessComponent(node, (const JSONSkinnedMeshRenderer*) c);
  654. }
  655. else if (c->GetType() == "Terrain")
  656. {
  657. ProcessComponent(node, (const JSONTerrain*) c);
  658. }
  659. else if (c->GetType() == "Animation")
  660. {
  661. ProcessComponent(node, (const JSONAnimation*) c);
  662. }
  663. else if (c->GetType() == "BoxCollider")
  664. {
  665. ProcessComponent(node, (const JSONBoxCollider*) c);
  666. }
  667. else if (c->GetType() == "MeshCollider")
  668. {
  669. ProcessComponent(node, (const JSONMeshCollider*) c);
  670. }
  671. else if (c->GetType() == "RigidBody")
  672. {
  673. ProcessComponent(node, (const JSONRigidBody*) c);
  674. }
  675. else if (c->GetType() == "Light")
  676. {
  677. ProcessComponent(node, (const JSONLight*) c);
  678. }
  679. else if (c->GetType() == "TimeOfDay")
  680. {
  681. ProcessComponent(node, (const JSONTimeOfDay*) c);
  682. }
  683. }
  684. if (node->GetComponent<CollisionShape>() && !node->GetComponent<RigidBody>())
  685. {
  686. RigidBody* body = node->CreateComponent<RigidBody>();
  687. body->SetCollisionLayer(2);
  688. }
  689. const PODVector<JSONNode*>& children = jnode->GetChildren();
  690. for (unsigned i = 0; i < children.Size(); i++)
  691. {
  692. node->AddChild(ProcessNode(children.At(i), node));
  693. }
  694. return node;
  695. }
  696. bool JSONSceneProcess::ProcessHierarchy(Scene* scene)
  697. {
  698. const PODVector<JSONNode*>& hierarchy = importer_->GetHierarchy();
  699. for (unsigned i = 0; i < hierarchy.Size(); i++)
  700. {
  701. hierarchy_.Push(SharedPtr<Node>(ProcessNode(hierarchy[i], scene)));
  702. }
  703. return true;
  704. }
  705. bool JSONSceneProcess::Process(const String &resourcePath)
  706. {
  707. resourcePath_ = resourcePath;
  708. ResourceCache* cache = GetSubsystem<ResourceCache>();
  709. cache->AddResourceDir(resourcePath_);
  710. scene_ = new Scene(context_);
  711. scene_->CreateComponent<PhysicsWorld>();
  712. scene_->CreateComponent<Octree>();
  713. scene_->CreateComponent<DebugRenderer>();
  714. Node* zoneNode = scene_->CreateChild("Zone");
  715. Zone* zone = zoneNode->CreateComponent<Zone>();
  716. zone->SetBoundingBox(BoundingBox(-10000.0f, 10000.f));
  717. zone->SetAmbientColor(Color(.4f, .4f, .4f));
  718. ProcessTextures();
  719. ProcessLightmaps();
  720. ProcessMaterials();
  721. ProcessModels();
  722. ProcessHierarchy(scene_);
  723. return true;
  724. }
  725. bool JSONSceneProcess::Write()
  726. {
  727. FileSystem* fs = GetSubsystem<FileSystem>();
  728. if (!fs->DirExists(resourcePath_ + "Scenes"))
  729. fs->CreateDir(resourcePath_ + "Scenes");
  730. if (!fs->DirExists(resourcePath_ + "Models"))
  731. fs->CreateDir(resourcePath_ + "Models");
  732. if (!fs->DirExists(resourcePath_ + "Materials"))
  733. fs->CreateDir(resourcePath_ + "Materials");
  734. if (!fs->DirExists(resourcePath_ + "Textures"))
  735. fs->CreateDir(resourcePath_ + "Textures");
  736. WriteMaterials();
  737. WriteModels();
  738. WriteHierarchy(scene_);
  739. return true;
  740. }
  741. }