JSONSceneProcess.cpp 29 KB

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