WorldInstaller.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Copyright (C) 2022 The V-Gears Team
  3. *
  4. * This file is part of V-Gears
  5. *
  6. * V-Gears is free software: you can redistribute it and/or modify it under
  7. * terms of the GNU General Public License as published by the Free Software
  8. * Foundation, version 3.0 (GPLv3) of the License.
  9. *
  10. * V-Gears is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include <iostream>
  16. #include <fstream>
  17. #include <OgreRoot.h>
  18. #include <OgreMesh.h>
  19. #include <OgreMeshSerializer.h>
  20. #include <boost/filesystem.hpp>
  21. #include "WorldInstaller.h"
  22. #include "common/Lzs.h"
  23. WorldInstaller::WorldInstaller(
  24. std::string input_dir, std::string output_dir, const bool keep_originals
  25. ):
  26. input_dir_(input_dir), output_dir_(output_dir), keep_originals_(keep_originals)
  27. {}
  28. WorldInstaller::~WorldInstaller(){}
  29. unsigned int WorldInstaller::Initialize(){
  30. if (wm_map_.size() > 0) wm_map_.clear();
  31. processed_maps_ = 0;
  32. wm_map_.push_back(File(input_dir_ + "/data/wm/WM0.MAP"));
  33. wm_map_.push_back(File(input_dir_ + "/data/wm/WM2.MAP"));
  34. wm_map_.push_back(File(input_dir_ + "/data/wm/WM3.MAP"));
  35. return wm_map_.size();
  36. }
  37. bool WorldInstaller::ProcessMap(){
  38. //std::cout << "[WI] Processing map " << processed_maps_ << "/" << wm_map_.size() << std::endl;
  39. if (processed_maps_ >= wm_map_.size()) return true;
  40. // Read WM*.MAP file.
  41. Map map;
  42. Ogre::MeshSerializer mesh_serializer;
  43. boost::filesystem::path p(wm_map_[processed_maps_].GetFileName());
  44. std::string map_name = p.stem().native(); // w/o path or extension.
  45. for (int b = 0; b < wm_map_[processed_maps_].GetFileSize() / 0xB800; b ++){
  46. //std::cout << "[WI] Block " << b << std::endl;
  47. Block block;
  48. for (int m = 0; m < 16; m ++){
  49. // Extract lzss compressed mesh to file.
  50. std::vector<unsigned char> lzss;
  51. wm_map_[processed_maps_].SetOffset(0xB800 * b + m * 4);
  52. u32 mesh_offset = 0xB800 * b + wm_map_[processed_maps_].readU32LE();
  53. wm_map_[processed_maps_].SetOffset(mesh_offset);
  54. u32 mesh_size = wm_map_[processed_maps_].readU32LE();
  55. // Add size to lzss
  56. wm_map_[processed_maps_].SetOffset(mesh_offset);
  57. for (int d = 0; d < 4; d ++)
  58. lzss.push_back(wm_map_[processed_maps_].readU8());
  59. //std::cout << "[WI] Mesh " << m << " Size: " << mesh_size
  60. // << " Offset: " << mesh_offset << " - 0x";
  61. //std::cout << std::hex << mesh_offset;
  62. //std::cout << std::dec << std::endl;
  63. for (int d = 0; d < mesh_size ; d ++) lzss.push_back(wm_map_[processed_maps_].readU8());
  64. //std::cout << " LZSS size: " << lzss.size() << std::endl;
  65. // Extract the lzss file.
  66. std::vector<unsigned char> data = Lzs::Decompress(lzss);
  67. if (data.size() == 0) continue;
  68. std::string dat_name = output_dir_ + "temp/wm/" + map_name + "_"
  69. + std::to_string(b) + "_" + std::to_string(m) + ".dat";
  70. std::ofstream dat(dat_name, std::ios::out | std::ios::binary);
  71. if (!dat){
  72. std::cerr << "Cannot create temporary world map file " << dat_name << std::endl;
  73. processed_maps_ ++;
  74. if (processed_maps_ >= wm_map_.size()) return true;
  75. else return false;
  76. }
  77. for (int d = 0; d <= data.size(); d ++)
  78. dat.write((char *) &data[d], sizeof(unsigned char));
  79. dat.close();
  80. // Open and read the decompressed file.
  81. File mesh_data(dat_name);
  82. block.mesh[m].triangle_count = mesh_data.readU16LE();
  83. block.mesh[m].vertex_count = mesh_data.readU16LE();
  84. for (int tri = 0; tri < block.mesh[m].triangle_count; tri ++){
  85. Triangle t;
  86. t.vertex_index[0] = mesh_data.readU8();
  87. t.vertex_index[1] = mesh_data.readU8();
  88. t.vertex_index[2] = mesh_data.readU8();
  89. u8 walkability_function = mesh_data.readU8();
  90. t.walkability = walkability_function >> 5; // 5 bits
  91. t.function_id = walkability_function & 0x7; // 3 bits
  92. t.vertex_coord[0].u = mesh_data.readU8();
  93. t.vertex_coord[0].v = mesh_data.readU8();
  94. t.vertex_coord[1].u = mesh_data.readU8();
  95. t.vertex_coord[1].v = mesh_data.readU8();
  96. t.vertex_coord[2].u = mesh_data.readU8();
  97. t.vertex_coord[2].v = mesh_data.readU8();
  98. u16 texture_location = mesh_data.readU16LE();
  99. t.texture_info = texture_location >> 9; // 9 bytes
  100. t.location = texture_location & ((1 << 7) - 1); // 7 bytes.
  101. block.mesh[m].triangles.push_back(t);
  102. }
  103. for (int ver = 0; ver < block.mesh[m].vertex_count; ver ++){
  104. Vertex v;
  105. v.x = mesh_data.readU16LE();
  106. v.y = mesh_data.readU16LE();
  107. v.z = mesh_data.readU16LE();
  108. v.unknown = mesh_data.readU16LE();
  109. block.mesh[m].vertices.push_back(v);
  110. }
  111. for (int nor = 0; nor < block.mesh[m].vertex_count; nor ++){
  112. Vertex v;
  113. v.x = mesh_data.readU16LE();
  114. v.y = mesh_data.readU16LE();
  115. v.z = mesh_data.readU16LE();
  116. v.unknown = mesh_data.readU16LE();
  117. block.mesh[m].normals.push_back(v);
  118. }
  119. }
  120. map.blocks.push_back(block);
  121. }
  122. // TODO: Generate material.
  123. // Generate manual meshes.
  124. for (int b = 0; b < map.blocks.size(); b ++){
  125. //std::cout << "[MAN] Block " << b << "/" << map.blocks.size() << std::endl;
  126. std::string name = map_name + "_" + std::to_string(b);
  127. Ogre::ManualObject man = Ogre::ManualObject(name);
  128. //man.setBoundingBox(Ogre::AxisAlignedBox({-100,-100,0}, {100,100,0})); //TODO;
  129. //= Ogre::Root::getSingleton().getSceneManager("Scene")->createManualObject(name);
  130. man.begin(name, Ogre::RenderOperation::OT_TRIANGLE_LIST);
  131. for (int m = 0; m < 16; m ++){
  132. //std::cout << "[MAN] Mesh " << m << " triangles: "
  133. // << map.blocks[b].mesh[m].triangle_count << "\n";
  134. // Add vertices.
  135. for (int v = 0; v < map.blocks[b].mesh[m].vertex_count; v ++){
  136. man.position(
  137. map.blocks[b].mesh[m].vertices[v].x, map.blocks[b].mesh[m].vertices[v].y,
  138. map.blocks[b].mesh[m].vertices[v].z
  139. );
  140. man.normal(
  141. map.blocks[b].mesh[m].normals[v].x, map.blocks[b].mesh[m].normals[v].y,
  142. map.blocks[b].mesh[m].normals[v].z
  143. );
  144. // TODO: How to add texture coordinates at this point?
  145. //man->textureCoord(0, 0);
  146. }
  147. // Conform faces from vertices
  148. for (int t = 0; t < map.blocks[b].mesh[m].triangle_count; t ++){
  149. //std::cout << "Triangle " << t << " vertizes: "
  150. // << (int) map.blocks[b].mesh[m].triangles[t].vertex_index[0] << ", "
  151. // << (int) map.blocks[b].mesh[m].triangles[t].vertex_index[1] << ", "
  152. // << (int) map.blocks[b].mesh[m].triangles[t].vertex_index[2] << std::endl;
  153. man.triangle(
  154. map.blocks[b].mesh[m].triangles[t].vertex_index[0],
  155. map.blocks[b].mesh[m].triangles[t].vertex_index[1],
  156. map.blocks[b].mesh[m].triangles[t].vertex_index[2]
  157. );
  158. }
  159. }
  160. // Export the mesh.
  161. man.end();
  162. Ogre::MeshPtr mesh = man.convertToMesh(name);
  163. //std::cout << "[WI] Export mesh " << (output_dir_ + "wm/" + mesh->getName() + ".mesh")
  164. // << std::endl;
  165. mesh_serializer.exportMesh(
  166. mesh.getPointer(), output_dir_ + "wm/" + mesh->getName() + ".mesh"
  167. );
  168. }
  169. // Export mesh file.
  170. processed_maps_ ++;
  171. if (processed_maps_ >= wm_map_.size()) return true;
  172. else return false;
  173. }