JSONSceneProcess.cpp 28 KB

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