WorldInstaller.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  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 <tinyxml.h>
  18. #include <OgreRoot.h>
  19. #include <OgreMesh.h>
  20. #include <OgreMeshSerializer.h>
  21. #include <boost/filesystem.hpp>
  22. #include "WorldInstaller.h"
  23. #include "TexFile.h"
  24. #include "common/Lzs.h"
  25. #include "common/FinalFantasy7/FF7NameLookup.h"
  26. #include "common/VGearsStringUtil.h"
  27. #include "data/VGearsLGPArchive.h"
  28. #include "data/WorldMapWalkmesh.h"
  29. #include "data/VGearsHRCFileManager.h"
  30. #include "data/FF7Data.h"
  31. std::string WorldInstaller::ELEMENT_MODELS_DIR("models/world/element");
  32. std::string WorldInstaller::TERRAIN_MODELS_DIR("models/world/terrain");
  33. WorldInstaller::WorldInstaller(
  34. const DiskImage& disk_image, const std::string output_dir,
  35. const bool keep_originals, Ogre::ResourceGroupManager* res_mgr
  36. ): disk_image_(disk_image), output_dir_(output_dir), keep_originals_(keep_originals), res_mgr_(res_mgr) {}
  37. WorldInstaller::~WorldInstaller(){}
  38. unsigned int WorldInstaller::Initialize(){
  39. if (wm_map_.size() > 0) wm_map_.clear();
  40. processed_maps_ = 0;
  41. wm_map_.push_back(File(*disk_image_.filePath("data/wm/WM0.MAP")));
  42. wm_map_.push_back(File(*disk_image_.filePath("data/wm/WM2.MAP")));
  43. wm_map_.push_back(File(*disk_image_.filePath("data/wm/WM3.MAP")));
  44. return wm_map_.size();
  45. }
  46. void WorldInstaller::GenerateMaterials(){
  47. // First, populate the texture list with static data.
  48. texture_.push_back({0, "pond", 32, 32, 0, 352});
  49. texture_.push_back({1, "riv_m2", 32, 32, 128, 64});
  50. texture_.push_back({2, "was_gs", 64, 64, 64, 192});
  51. texture_.push_back({3, "wpcltr", 32, 128, 0, 256});
  52. texture_.push_back({4, "wpcltr2", 32, 32, 160, 64});
  53. texture_.push_back({5, "bzdun", 64, 64, 192, 192});
  54. texture_.push_back({6, "bone", 32, 32, 224, 384});
  55. texture_.push_back({7, "bone2", 32, 32, 224, 416});
  56. texture_.push_back({8, "bornwd", 64, 64, 160, 320});
  57. texture_.push_back({9, "bridge", 32, 64, 192, 0});
  58. texture_.push_back({10, "bridge2", 32, 32, 224, 0});
  59. texture_.push_back({11, "cave", 32, 32, 224, 448});
  60. texture_.push_back({12, "cave2", 32, 32, 224, 320});
  61. texture_.push_back({13, "cave_s", 32, 32, 160, 224});
  62. texture_.push_back({14, "cdl_cl2", 64, 32, 96, 96});
  63. texture_.push_back({15, "cf01", 64, 32, 192, 288});
  64. texture_.push_back({16, "clf_bgs", 64, 32, 192, 384});
  65. texture_.push_back({17, "clf_ggl", 64, 64, 128, 256});
  66. texture_.push_back({18, "clf_ggs", 64, 32, 192, 352});
  67. texture_.push_back({19, "clf_l", 64, 64, 0, 0});
  68. texture_.push_back({20, "clf_ld", 64, 64, 64, 0});
  69. texture_.push_back({21, "clf_lf", 64, 64, 128, 0});
  70. texture_.push_back({22, "clf_lg", 32, 64, 0, 96});
  71. texture_.push_back({23, "clf_lr", 32, 64, 128, 0});
  72. texture_.push_back({24, "clf_lsg", 32, 64, 64, 64});
  73. texture_.push_back({25, "clf_r", 32, 32, 0, 96});
  74. texture_.push_back({26, "clf_s", 64, 32, 192, 0});
  75. texture_.push_back({27, "clf_sd", 64, 32, 192, 32});
  76. texture_.push_back({28, "clf_sf", 64, 32, 0, 64});
  77. texture_.push_back({29, "clf_sg", 32, 32, 32, 96});
  78. texture_.push_back({30, "clf_sg2", 32, 32, 0, 160});
  79. texture_.push_back({31, "clf_sr", 32, 32, 32, 96});
  80. texture_.push_back({32, "clf_ss", 32, 32, 32, 128});
  81. texture_.push_back({33, "clf_ssd", 32, 32, 0, 224});
  82. texture_.push_back({34, "clf_ssw", 32, 32, 224, 32});
  83. texture_.push_back({35, "clf_sw", 32, 32, 192, 32});
  84. texture_.push_back({36, "clf_w02", 64, 64, 128, 64});
  85. texture_.push_back({37, "clf_w03", 64, 64, 192, 64});
  86. texture_.push_back({38, "clf_was", 64, 32, 64, 64});
  87. texture_.push_back({39, "clfeg", 32, 32, 192, 320});
  88. texture_.push_back({40, "clfegd", 32, 32, 0, 320});
  89. texture_.push_back({41, "clftop", 64, 32, 192, 64});
  90. texture_.push_back({42, "clftop2", 32, 32, 128, 64});
  91. texture_.push_back({43, "cndl_cl", 64, 32, 96, 128});
  92. texture_.push_back({44, "cndlf", 64, 64, 160, 64});
  93. texture_.push_back({45, "cndlf02", 64, 64, 208, 64});
  94. texture_.push_back({46, "comtr", 16, 32, 144, 96});
  95. texture_.push_back({47, "cosinn", 32, 32, 224, 416});
  96. texture_.push_back({48, "cosinn2", 32, 32, 192, 448});
  97. texture_.push_back({49, "csmk", 32, 32, 64, 64});
  98. texture_.push_back({50, "csmk2", 32, 32, 96, 64});
  99. texture_.push_back({51, "cstds01", 32, 32, 224, 160});
  100. texture_.push_back({52, "cstds02", 64, 64, 0, 448});
  101. texture_.push_back({53, "des01", 32, 32, 160, 320});
  102. texture_.push_back({54, "desert", 64, 64, 128, 128});
  103. texture_.push_back({55, "desor", 64, 32, 160, 64});
  104. texture_.push_back({56, "ds1", 32, 32, 0, 256});
  105. texture_.push_back({57, "ds_s1", 32, 32, 192, 288});
  106. texture_.push_back({58, "dsee1", 32, 32, 96, 288});
  107. texture_.push_back({59, "dsrt_d", 32, 32, 224, 0});
  108. texture_.push_back({60, "dsrt_e", 64, 128, 64, 128});
  109. texture_.push_back({61, "edes01", 32, 32, 224, 320});
  110. texture_.push_back({62, "elm01", 32, 32, 160, 0});
  111. texture_.push_back({63, "elm02", 32, 32, 64, 96});
  112. texture_.push_back({64, "elm_gro", 64, 64, 0, 96});
  113. texture_.push_back({65, "elm_r", 32, 32, 192, 0});
  114. texture_.push_back({66, "elm_r2", 32, 32, 224, 0});
  115. texture_.push_back({67, "fall1", 32, 32, 128, 256});
  116. texture_.push_back({68, "farm01", 32, 32, 160, 32});
  117. texture_.push_back({69, "farm02", 32, 32, 192, 32});
  118. texture_.push_back({70, "farm_g", 32, 32, 128, 64});
  119. texture_.push_back({71, "farm_r", 32, 16, 128, 48});
  120. texture_.push_back({72, "fld", 64, 64, 64, 96});
  121. texture_.push_back({73, "fld_02", 64, 64, 0, 64});
  122. texture_.push_back({74, "fld_s", 64, 64, 0, 160});
  123. texture_.push_back({75, "fld_s2", 32, 32, 224, 256});
  124. texture_.push_back({76, "fld_sw", 64, 64, 128, 192});
  125. texture_.push_back({77, "fld_v", 128, 128, 0, 128});
  126. texture_.push_back({78, "fld_vd", 32, 64, 96, 128});
  127. texture_.push_back({79, "fld_vd2", 32, 64, 192, 416});
  128. texture_.push_back({80, "fvedge", 32, 64, 0, 0});
  129. texture_.push_back({81, "gclf_d", 128, 64, 128, 128});
  130. texture_.push_back({82, "gclf_g", 32, 64, 224, 128});
  131. texture_.push_back({83, "gclfwa", 128, 64, 64, 320});
  132. texture_.push_back({84, "gclfwa2", 32, 64, 160, 320});
  133. texture_.push_back({85, "gclfwag", 32, 64, 32, 320});
  134. texture_.push_back({86, "gg_gro", 64, 64, 64, 448});
  135. texture_.push_back({87, "gg_mts", 64, 128, 0, 128});
  136. texture_.push_back({88, "ggmk", 64, 64, 128, 448});
  137. texture_.push_back({89, "ggmt", 128, 128, 0, 0});
  138. texture_.push_back({90, "ggmt_e", 128, 32, 0, 96});
  139. texture_.push_back({91, "ggmt_ed", 128, 32, 128, 96});
  140. texture_.push_back({92, "ggmt_eg", 32, 32, 96, 224});
  141. texture_.push_back({93, "ggmtd", 128, 128, 128, 0});
  142. texture_.push_back({94, "ggs_g", 32, 32, 32, 64});
  143. texture_.push_back({95, "ggshr", 32, 32, 192, 96});
  144. texture_.push_back({96, "ggshrg", 32, 32, 224, 96});
  145. texture_.push_back({97, "gia", 64, 32, 64, 224});
  146. texture_.push_back({98, "gia2", 64, 32, 0, 224});
  147. texture_.push_back({99, "gia_d", 64, 32, 128, 224});
  148. texture_.push_back({100, "gia_d2", 64, 32, 64, 224});
  149. texture_.push_back({101, "gia_g", 32, 32, 192, 224});
  150. texture_.push_back({102, "gia_g2", 32, 32, 128, 224});
  151. texture_.push_back({103, "gmt_eda", 32, 32, 0, 352});
  152. texture_.push_back({104, "gonclf", 128, 64, 96, 64});
  153. texture_.push_back({105, "gredge", 32, 32, 192, 192});
  154. texture_.push_back({106, "hyouga", 64, 64, 192, 64});
  155. texture_.push_back({107, "iceclf", 64, 32, 64, 96});
  156. texture_.push_back({108, "iceclfd", 64, 32, 128, 96});
  157. texture_.push_back({109, "iceclfg", 32, 32, 32, 224});
  158. texture_.push_back({110, "jun", 64, 64, 192, 192});
  159. texture_.push_back({111, "jun_d", 64, 64, 128, 192});
  160. texture_.push_back({112, "jun_e", 64, 16, 0, 240});
  161. texture_.push_back({113, "jun_gro", 64, 64, 0, 64});
  162. texture_.push_back({114, "junmk", 32, 32, 0, 96});
  163. texture_.push_back({115, "junn01", 32, 32, 160, 112});
  164. texture_.push_back({116, "junn02", 32, 32, 192, 112});
  165. texture_.push_back({117, "junn03", 32, 32, 224, 112});
  166. texture_.push_back({118, "junn04", 32, 32, 64, 128});
  167. texture_.push_back({119, "jutmpl01", 64, 64, 128, 192});
  168. texture_.push_back({120, "lake-e", 32, 32, 96, 192});
  169. texture_.push_back({121, "lake_ef", 32, 32, 128, 224});
  170. texture_.push_back({122, "lake_fl", 128, 32, 160, 224});
  171. texture_.push_back({123, "lostclf", 32, 64, 128, 384});
  172. texture_.push_back({124, "lostmt", 128, 32, 128, 448});
  173. texture_.push_back({125, "lostmtd", 128, 32, 128, 480});
  174. texture_.push_back({126, "lostmts", 64, 32, 160, 384});
  175. texture_.push_back({127, "lostwd_e", 32, 32, 64, 480});
  176. texture_.push_back({128, "lostwod", 64, 64, 0, 448});
  177. texture_.push_back({129, "lst1", 32, 32, 192, 256});
  178. texture_.push_back({130, "lstwd_e2", 32, 32, 96, 480});
  179. texture_.push_back({131, "mzes", 32, 32, 224, 128});
  180. texture_.push_back({132, "mzmt_e", 128, 64, 128, 64});
  181. texture_.push_back({133, "mzmt_ed", 128, 32, 128, 128});
  182. texture_.push_back({134, "mzmt_edw", 128, 32, 128, 160});
  183. texture_.push_back({135, "mzmt_ew", 128, 32, 0, 128});
  184. texture_.push_back({136, "mzmt_o", 128, 32, 64, 416});
  185. texture_.push_back({137, "mzmt_od", 128, 32, 64, 448});
  186. texture_.push_back({138, "mzmt_s", 128, 32, 0, 192});
  187. texture_.push_back({139, "mzmt_sd", 128, 32, 0, 160});
  188. texture_.push_back({140, "md01", 32, 32, 96, 16});
  189. texture_.push_back({141, "md02", 128, 128, 0, 0});
  190. texture_.push_back({142, "md03", 16, 16, 112, 64});
  191. texture_.push_back({143, "md04", 32, 32, 128, 16});
  192. texture_.push_back({144, "md05", 64, 16, 96, 0});
  193. texture_.push_back({145, "md06", 16, 32, 96, 48});
  194. texture_.push_back({146, "md07", 16, 16, 112, 48});
  195. texture_.push_back({147, "md_mt", 128, 128, 128, 0});
  196. texture_.push_back({148, "md_mtd", 128, 128, 0, 0});
  197. texture_.push_back({149, "md_mts", 64, 128, 64, 160});
  198. texture_.push_back({150, "md_snow", 128, 32, 128, 0});
  199. texture_.push_back({151, "md_snw2", 128, 32, 128, 32});
  200. texture_.push_back({152, "md_snwd", 128, 64, 0, 128});
  201. texture_.push_back({153, "md_snwe", 64, 64, 96, 320});
  202. texture_.push_back({154, "md_snws", 64, 64, 128, 128});
  203. texture_.push_back({155, "md_snwt", 128, 32, 0, 192});
  204. texture_.push_back({156, "md_snww", 32, 32, 224, 224});
  205. texture_.push_back({157, "md_sw_s", 128, 128, 0, 0});
  206. texture_.push_back({158, "md_swd2", 32, 32, 192, 256});
  207. texture_.push_back({159, "md_swnp", 128, 128, 0, 96});
  208. texture_.push_back({160, "mdsrt_e", 128, 32, 128, 192});
  209. texture_.push_back({161, "mdsrt_ed", 128, 32, 128, 224});
  210. texture_.push_back({162, "mdsrt_eg", 32, 32, 64, 224});
  211. texture_.push_back({163, "midil", 32, 32, 32, 192});
  212. texture_.push_back({164, "midild", 32, 32, 224, 192});
  213. texture_.push_back({165, "mt_ewg", 32, 32, 64, 96});
  214. texture_.push_back({166, "mt_road", 64, 64, 192, 128});
  215. texture_.push_back({167, "mt_se", 32, 32, 160, 416});
  216. texture_.push_back({168, "mt_se2", 64, 64, 128, 256});
  217. texture_.push_back({169, "mt_sg01", 32, 32, 0, 224});
  218. texture_.push_back({170, "mt_sg02", 32, 32, 32, 224});
  219. texture_.push_back({171, "mt_sg03", 32, 32, 0, 192});
  220. texture_.push_back({172, "mt_sg04", 32, 32, 160, 384});
  221. texture_.push_back({173, "mtcoin", 64, 64, 0, 256});
  222. texture_.push_back({174, "mtwas_e", 128, 32, 0, 224});
  223. texture_.push_back({175, "mtwas_ed", 128, 32, 0, 224});
  224. texture_.push_back({176, "ncol_gro", 64, 64, 64, 384});
  225. texture_.push_back({177, "ncole01", 32, 32, 224, 384});
  226. texture_.push_back({178, "ncole02", 32, 32, 192, 416});
  227. texture_.push_back({179, "nivl_gro", 64, 64, 128, 384});
  228. texture_.push_back({180, "nivl_mt", 128, 64, 0, 0});
  229. texture_.push_back({181, "nivl_top", 32, 32, 0, 64});
  230. texture_.push_back({182, "nivlr", 32, 32, 192, 384});
  231. texture_.push_back({183, "port", 32, 32, 96, 224});
  232. texture_.push_back({184, "port_d", 32, 32, 160, 0});
  233. texture_.push_back({185, "rzclf02", 64, 64, 128, 128});
  234. texture_.push_back({186, "rct_gro", 64, 128, 0, 416});
  235. texture_.push_back({187, "riv_cls", 64, 64, 64, 0});
  236. texture_.push_back({188, "riv_l1", 32, 32, 96, 320});
  237. texture_.push_back({189, "riv_m", 32, 32, 0, 224});
  238. texture_.push_back({190, "rivr", 32, 32, 64, 224});
  239. texture_.push_back({191, "rivrclf", 64, 64, 128, 192});
  240. texture_.push_back({192, "rivs1", 32, 32, 128, 320});
  241. texture_.push_back({193, "rivshr", 64, 64, 192, 192});
  242. texture_.push_back({194, "rivssr", 64, 32, 192, 224});
  243. texture_.push_back({195, "rivstrt", 32, 32, 192, 160});
  244. texture_.push_back({196, "rm1", 32, 32, 32, 288});
  245. texture_.push_back({197, "rocet", 32, 32, 128, 160});
  246. texture_.push_back({198, "rs_ss", 32, 32, 96, 224});
  247. texture_.push_back({199, "sango", 32, 32, 224, 320});
  248. texture_.push_back({200, "sango2", 32, 32, 224, 352});
  249. texture_.push_back({201, "sango3", 32, 32, 128, 384});
  250. texture_.push_back({202, "sango4", 64, 64, 0, 384});
  251. texture_.push_back({203, "sdun", 64, 64, 0, 160});
  252. texture_.push_back({204, "sdun02", 64, 64, 64, 160});
  253. texture_.push_back({205, "sh1", 32, 32, 32, 256});
  254. texture_.push_back({206, "sh_s1", 32, 32, 224, 288});
  255. texture_.push_back({207, "shedge", 32, 64, 160, 160});
  256. texture_.push_back({208, "shlm_1", 32, 32, 192, 320});
  257. texture_.push_back({209, "shol", 128, 128, 128, 96});
  258. texture_.push_back({210, "shol_s", 64, 64, 192, 192});
  259. texture_.push_back({211, "shor", 128, 128, 0, 0});
  260. texture_.push_back({212, "shor_s", 64, 64, 128, 192});
  261. texture_.push_back({213, "shor_s2", 32, 32, 224, 416});
  262. texture_.push_back({214, "shor_v", 32, 32, 192, 0});
  263. texture_.push_back({215, "silo", 32, 32, 224, 32});
  264. texture_.push_back({216, "slope", 128, 32, 0, 384});
  265. texture_.push_back({217, "snow_es", 32, 32, 192, 480});
  266. texture_.push_back({218, "snow_es2", 32, 32, 224, 480});
  267. texture_.push_back({219, "snow_es3", 32, 32, 224, 448});
  268. texture_.push_back({220, "snw_mt", 128, 128, 0, 0});
  269. texture_.push_back({221, "snw_mtd", 128, 128, 128, 0});
  270. texture_.push_back({222, "snw_mte", 64, 32, 0, 96});
  271. texture_.push_back({223, "snw_mted", 64, 32, 64, 96});
  272. texture_.push_back({224, "snw_mts", 64, 128, 64, 0});
  273. texture_.push_back({225, "snw_mts2", 64, 32, 128, 192});
  274. texture_.push_back({226, "snwfld", 64, 64, 0, 64});
  275. texture_.push_back({227, "snwfld_s", 64, 32, 128, 128});
  276. texture_.push_back({228, "snwgra", 64, 64, 192, 192});
  277. texture_.push_back({229, "snwhm01", 32, 32, 32, 0});
  278. texture_.push_back({230, "snwhm02", 32, 32, 32, 32});
  279. texture_.push_back({231, "snwods", 32, 32, 224, 192});
  280. texture_.push_back({232, "snwood", 64, 64, 192, 128});
  281. texture_.push_back({233, "snwtrk", 32, 64, 96, 256});
  282. texture_.push_back({234, "sse_s1", 32, 32, 32, 320});
  283. texture_.push_back({235, "ssee1", 32, 32, 64, 288});
  284. texture_.push_back({236, "sst1", 32, 32, 224, 256});
  285. texture_.push_back({237, "stown_r", 32, 32, 192, 256});
  286. texture_.push_back({238, "stw_gro", 64, 64, 0, 384});
  287. texture_.push_back({239, "subrg2", 32, 32, 224, 160});
  288. texture_.push_back({240, "susbrg", 64, 64, 192, 96});
  289. texture_.push_back({241, "sw_se", 64, 64, 0, 0});
  290. texture_.push_back({242, "swclf_l", 64, 64, 64, 128});
  291. texture_.push_back({243, "swclf_ld", 64, 64, 192, 128});
  292. texture_.push_back({244, "swclf_lg", 32, 64, 0, 192});
  293. texture_.push_back({245, "swclf_s", 64, 32, 128, 96});
  294. texture_.push_back({246, "swclf_sd", 64, 32, 192, 96});
  295. texture_.push_back({247, "swclf_sg", 32, 32, 32, 192});
  296. texture_.push_back({248, "swclf_wg", 32, 32, 192, 192});
  297. texture_.push_back({249, "swfld_s2", 64, 32, 128, 160});
  298. texture_.push_back({250, "swfld_s3", 32, 32, 160, 192});
  299. texture_.push_back({251, "swmd_cg", 32, 32, 128, 192});
  300. texture_.push_back({252, "swmd_clf", 64, 32, 64, 192});
  301. texture_.push_back({253, "swp1", 32, 32, 0, 288});
  302. texture_.push_back({254, "trk", 64, 64, 128, 0});
  303. texture_.push_back({255, "tyo_f", 128, 128, 128, 128});
  304. texture_.push_back({256, "tyosnw", 64, 128, 64, 384});
  305. texture_.push_back({257, "uf1", 32, 32, 160, 256});
  306. texture_.push_back({258, "utai01", 32, 32, 32, 96});
  307. texture_.push_back({259, "utai02", 32, 32, 224, 64});
  308. texture_.push_back({260, "utai_gro", 64, 64, 128, 96});
  309. texture_.push_back({261, "utaimt", 32, 32, 0, 128});
  310. texture_.push_back({262, "utaimtd", 32, 32, 96, 96});
  311. texture_.push_back({263, "utaimtg", 32, 32, 96, 128});
  312. texture_.push_back({264, "wa1", 32, 32, 192, 320});
  313. texture_.push_back({265, "wzs1", 32, 32, 128, 288});
  314. texture_.push_back({266, "wzshr", 32, 32, 160, 32});
  315. texture_.push_back({267, "wzshr2", 32, 32, 32, 128});
  316. texture_.push_back({268, "wzshrs", 32, 32, 32, 160});
  317. texture_.push_back({269, "was", 128, 128, 0, 96});
  318. texture_.push_back({270, "was_d", 64, 32, 0, 224});
  319. texture_.push_back({271, "was_g", 64, 64, 0, 192});
  320. texture_.push_back({272, "was_s", 128, 128, 128, 0});
  321. texture_.push_back({273, "wasfld", 64, 64, 64, 256});
  322. texture_.push_back({274, "wdedge", 64, 64, 64, 160});
  323. texture_.push_back({275, "we1", 32, 32, 96, 256});
  324. texture_.push_back({276, "we_s1", 32, 32, 160, 288});
  325. texture_.push_back({277, "wedged", 32, 64, 128, 160});
  326. texture_.push_back({278, "wod-e2", 32, 32, 64, 224});
  327. texture_.push_back({279, "wood", 64, 64, 192, 0});
  328. texture_.push_back({280, "wood_d", 64, 64, 192, 160});
  329. texture_.push_back({281, "wtrk", 32, 64, 64, 96});
  330. Ogre::MaterialSerializer mSer;
  331. for (Texture t : texture_){
  332. Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().create(t.name, "General", true);
  333. Ogre::Technique* tech = mat->getTechnique(0);
  334. Ogre::Pass* pass = tech->getPass(0);
  335. pass->setDiffuse(0.7, 0.7, 0.7, 0.7);
  336. mSer.exportMaterial(mat, output_dir_ + "models/world/" + t.name + ".material");
  337. }
  338. }
  339. void WorldInstaller::ProcessModels(){
  340. // Open world_us.lgp
  341. File world_file(*disk_image_.filePath("data/wm/world_us.lgp"));
  342. boost::filesystem::create_directories(output_dir_ + "temp/world_models/");
  343. boost::filesystem::create_directories(output_dir_ + "data/models/world/");
  344. VGears::LGPArchive world_lgp(*disk_image_.filePath("data/wm/world_us.lgp"), "LGP");
  345. world_lgp.open(*disk_image_.filePath("data/wm/world_us.lgp"), true);
  346. world_lgp.load();
  347. VGears::LGPArchive::FileList file_list = world_lgp.GetFiles();
  348. std::vector<std::string> hrc_file_names;
  349. // First pass: extract all files so HRC sidecar dependencies (.rsd, .p, .tex) exist.
  350. for (int i = 0; i < file_list.size(); i ++){
  351. VGears::LGPArchive::FileEntry f = file_list.at(i);
  352. if (f.data_offset + f.data_size <= world_file.GetFileSize()){
  353. File w_lgp_file(&world_file, f.data_offset, f.data_size);
  354. std::string file_name = f.file_name;
  355. VGears::StringUtil::toLowerCase(file_name);
  356. w_lgp_file.WriteFile(output_dir_ + "temp/world_models/" + file_name);
  357. if (file_name.size() >= 7 && file_name.substr(4, 3) == "hrc") hrc_file_names.push_back(file_name);
  358. }
  359. }
  360. // Second pass: convert HRC models once all dependencies are available on disk.
  361. for (int i = 0; i < hrc_file_names.size(); i ++){
  362. const std::string& file_name = hrc_file_names.at(i);
  363. // TODO: Can this be done with declare resource?
  364. // TODO: If not, do aloop to save all the hrc files, then call this once, then
  365. // another loop to process them.
  366. res_mgr_->declareResource(output_dir_ + "temp/world_models/" + file_name, "Skeleton", "FFVII");
  367. res_mgr_->removeResourceLocation(output_dir_ + "temp/world_models/", "FFVII");
  368. res_mgr_->addResourceLocation(output_dir_ + "temp/world_models/", "FileSystem", "FFVII", true, true);
  369. // TODO: This needs work to assemble all the pieces. Similar to field models.
  370. Ogre::ResourcePtr hrc = VGears::HRCFileManager::GetSingleton().load(file_name, "FFVII");
  371. Ogre::String hrc_base_name;
  372. VGears::StringUtil::splitBase(file_name, hrc_base_name);
  373. auto mesh_name = VGears::NameLookup::model(hrc_base_name) + ".mesh";
  374. Ogre::MeshPtr mesh(Ogre::MeshManager::getSingleton().load(mesh_name, "FFVII"));
  375. Ogre::SkeletonPtr skeleton(mesh->getSkeleton());
  376. // TODO: a files??
  377. /*for (std::string anim : model.a){
  378. VGears::AFileManager &afl_mgr(VGears::AFileManager::GetSingleton());
  379. Ogre::String a_base_name;
  380. VGears::StringUtil::splitBase(anim, a_base_name);
  381. VGears::AFilePtr a
  382. = afl_mgr.load(a_base_name + ".a", "FFVII").staticCast<VGears::AFile>();
  383. // Convert the FF7 name to a more readable name set in the meta data.
  384. VGears::StringUtil::splitBase(anim, base_name);
  385. a->AddTo(skeleton, VGears::NameLookup::Animation(base_name));
  386. }*/
  387. ExportMesh(output_dir_ + "data/models/world/", mesh);
  388. }
  389. }
  390. bool WorldInstaller::ProcessMap(){
  391. if (processed_maps_ >= wm_map_.size()) return true;
  392. // Initialize the xml file.
  393. TiXmlDocument doc;
  394. std::unique_ptr<TiXmlElement> xml(new TiXmlElement("world_map"));
  395. // Script.
  396. std::unique_ptr<TiXmlElement> xml_script_element(new TiXmlElement("script"));
  397. xml_script_element->SetAttribute("file_name", std::to_string(processed_maps_) + "/script.lua");
  398. xml->LinkEndChild(xml_script_element.release());
  399. // Background.
  400. std::unique_ptr<TiXmlElement> xml_background_2d(new TiXmlElement("background2d"));
  401. xml_background_2d->SetAttribute("file_name", std::to_string(processed_maps_) + "/bg.xml");
  402. xml->LinkEndChild(xml_background_2d.release());
  403. // Texts.
  404. std::unique_ptr<TiXmlElement> xml_texts(new TiXmlElement("texts"));
  405. xml_texts->SetAttribute("file_name", std::to_string(processed_maps_) + "/text.xml");
  406. xml->LinkEndChild(xml_texts.release());
  407. // Walkmesh.
  408. std::unique_ptr<TiXmlElement> xml_walkmesh(new TiXmlElement("walkmesh"));
  409. xml_walkmesh->SetAttribute("file_name", std::to_string(processed_maps_) + "/wm.xml");
  410. xml->LinkEndChild(xml_walkmesh.release());
  411. // Terrain (don't close yet).
  412. std::unique_ptr<TiXmlElement> xml_terrain(new TiXmlElement("terrain"));
  413. // Initialize the walkmesh data.
  414. WorldMapWalkmesh walkmesh(processed_maps_, processed_maps_ == 0 ? true : false);
  415. // Read WM*.MAP file.
  416. Map map;
  417. Ogre::MeshSerializer mesh_serializer;
  418. boost::filesystem::path p(wm_map_[processed_maps_].GetFileName());
  419. std::string map_name = p.stem().native(); // w/o path or extension.
  420. for (int b = 0; b < wm_map_[processed_maps_].GetFileSize() / 0xB800; b ++){
  421. // Calculate offsets for walkmesh.
  422. // WM0 is 9x7 blocks, WM2 probably is too, WM3 no idea?
  423. int wm_offset_x = 32 * (b % 9);
  424. int wm_offset_y = 32 * (b / 9);
  425. Block block;
  426. for (int m = 0; m < 16; m ++){
  427. // Extract lzss compressed mesh to file.
  428. std::vector<unsigned char> lzss;
  429. wm_map_[processed_maps_].SetOffset(0xB800 * b + m * 4);
  430. u32 mesh_offset = 0xB800 * b + wm_map_[processed_maps_].readU32LE();
  431. wm_map_[processed_maps_].SetOffset(mesh_offset);
  432. u32 mesh_size = wm_map_[processed_maps_].readU32LE();
  433. // Add size to lzss
  434. wm_map_[processed_maps_].SetOffset(mesh_offset);
  435. for (int d = 0; d < 4; d ++) lzss.push_back(wm_map_[processed_maps_].readU8());
  436. for (int d = 0; d < mesh_size ; d ++) lzss.push_back(wm_map_[processed_maps_].readU8());
  437. // Extract the lzss file.
  438. std::vector<unsigned char> data = Lzs::Decompress(lzss);
  439. if (data.size() == 0) continue;
  440. std::string dat_name = output_dir_ + "temp/wm/" + map_name + "_"
  441. + std::to_string(b) + "_" + std::to_string(m) + ".dat";
  442. std::ofstream dat(dat_name, std::ios::out | std::ios::binary);
  443. if (!dat){
  444. std::cerr << "Cannot create temporary world map file " << dat_name << std::endl;
  445. processed_maps_ ++;
  446. if (processed_maps_ >= wm_map_.size()) return true;
  447. else return false;
  448. }
  449. for (int d = 0; d < data.size(); d ++) dat.write((char *) &data[d], sizeof(unsigned char));
  450. dat.close();
  451. // Open and read the decompressed file.
  452. File mesh_data(dat_name);
  453. block.mesh[m].triangle_count = mesh_data.readU16LE();
  454. block.mesh[m].vertex_count = mesh_data.readU16LE();
  455. for (int tri = 0; tri < block.mesh[m].triangle_count; tri ++){
  456. Triangle t;
  457. t.vertex_index[0] = mesh_data.readU8();
  458. t.vertex_index[1] = mesh_data.readU8();
  459. t.vertex_index[2] = mesh_data.readU8();
  460. u8 walkability_function = mesh_data.readU8();
  461. //t.walkability = walkability_function >> 5; // 5 bits
  462. //t.function_id = walkability_function & 0x7; // 3 bits
  463. t.walkability = walkability_function & 0x1F; // Lowest 5 bits
  464. t.function_id = walkability_function >> 3; // 3 bits
  465. // FIXME: I think function_id is wrong. It must be 3 bits
  466. t.vertex_coord[0].u = mesh_data.readU8();
  467. t.vertex_coord[0].v = mesh_data.readU8();
  468. t.vertex_coord[1].u = mesh_data.readU8();
  469. t.vertex_coord[1].v = mesh_data.readU8();
  470. t.vertex_coord[2].u = mesh_data.readU8();
  471. t.vertex_coord[2].v = mesh_data.readU8();
  472. u16 texture_location = mesh_data.readU16LE();
  473. t.texture = texture_location >> 9; // 9 bytes
  474. t.location = texture_location & ((1 << 7) - 1); // 7 bytes.
  475. block.mesh[m].triangles.push_back(t);
  476. }
  477. for (int ver = 0; ver < block.mesh[m].vertex_count; ver ++){
  478. Vertex v;
  479. v.x = mesh_data.readU16LE();
  480. v.z = mesh_data.readU16LE();
  481. v.y = mesh_data.readU16LE();
  482. v.unknown = mesh_data.readU16LE();
  483. block.mesh[m].vertices.push_back(v);
  484. }
  485. for (int nor = 0; nor < block.mesh[m].vertex_count; nor ++){
  486. Vertex v;
  487. v.x = mesh_data.readU16LE();
  488. v.z = mesh_data.readU16LE();
  489. v.y = mesh_data.readU16LE();
  490. v.unknown = mesh_data.readU16LE();
  491. block.mesh[m].normals.push_back(v);
  492. }
  493. // Add data to the walkmesh
  494. for (int tri = 0; tri < block.mesh[m].triangle_count; tri ++){
  495. Triangle t = block.mesh[m].triangles.at(tri);
  496. walkmesh.addTriangle(
  497. Ogre::Vector3(
  498. block.mesh[m].vertices.at(t.vertex_index[0]).x + wm_offset_x,
  499. block.mesh[m].vertices.at(t.vertex_index[0]).y + wm_offset_y,
  500. block.mesh[m].vertices.at(t.vertex_index[0]).z
  501. ), // a
  502. Ogre::Vector3(
  503. block.mesh[m].vertices.at(t.vertex_index[1]).x + wm_offset_x,
  504. block.mesh[m].vertices.at(t.vertex_index[1]).y + wm_offset_y,
  505. block.mesh[m].vertices.at(t.vertex_index[1]).z
  506. ), // b
  507. Ogre::Vector3(
  508. block.mesh[m].vertices.at(t.vertex_index[2]).x + wm_offset_x,
  509. block.mesh[m].vertices.at(t.vertex_index[2]).y + wm_offset_y,
  510. block.mesh[m].vertices.at(t.vertex_index[2]).z
  511. ), // c
  512. t.walkability,
  513. t.function_id
  514. );
  515. }
  516. }
  517. map.blocks.push_back(block);
  518. }
  519. // TODO: Generate material.
  520. // Generate manual meshes.
  521. for (int b = 0; b < map.blocks.size(); b ++){
  522. int wm_offset_x = 32 * (b % 9);
  523. int wm_offset_y = 32 * (b / 9);
  524. //std::cout << "[MAN] Block " << b << "/" << map.blocks.size() << std::endl;
  525. std::string name = map_name + "_" + std::to_string(b);
  526. std::string mat_name = texture_.at(0).name;
  527. Ogre::ManualObject man = Ogre::ManualObject(name);
  528. //man.setBoundingBox(Ogre::AxisAlignedBox({-100,-100,0}, {100,100,0})); //TODO;
  529. //= Ogre::Root::getSingleton().getSceneManager("Scene")->createManualObject(name);
  530. man.begin(mat_name, Ogre::RenderOperation::OT_TRIANGLE_LIST);
  531. for (int m = 0; m < 16; m ++){
  532. //std::cout << "[MAN] Mesh " << m << " triangles: "
  533. // << map.blocks[b].mesh[m].triangle_count << "\n";
  534. // Add vertices.
  535. for (int v = 0; v < map.blocks[b].mesh[m].vertex_count; v ++){
  536. man.position(
  537. map.blocks[b].mesh[m].vertices[v].x, map.blocks[b].mesh[m].vertices[v].y,
  538. map.blocks[b].mesh[m].vertices[v].z
  539. );
  540. man.normal(
  541. map.blocks[b].mesh[m].normals[v].x, map.blocks[b].mesh[m].normals[v].y,
  542. map.blocks[b].mesh[m].normals[v].z
  543. );
  544. // TODO: How to add texture coordinates at this point?
  545. //man->textureCoord(0, 0);
  546. }
  547. // Conform faces from vertices
  548. for (int t = 0; t < map.blocks[b].mesh[m].triangle_count; t ++){
  549. //std::cout << "Triangle " << t << " vertizes: "
  550. // << (int) map.blocks[b].mesh[m].triangles[t].vertex_index[0] << ", "
  551. // << (int) map.blocks[b].mesh[m].triangles[t].vertex_index[1] << ", "
  552. // << (int) map.blocks[b].mesh[m].triangles[t].vertex_index[2] << std::endl;
  553. // TODO: El index deberia incrementar por triangulo por cada material
  554. man.setMaterialName(0, texture_.at(map.blocks[b].mesh[m].triangles[t].texture).name);
  555. man.triangle(
  556. map.blocks[b].mesh[m].triangles[t].vertex_index[0],
  557. map.blocks[b].mesh[m].triangles[t].vertex_index[1],
  558. map.blocks[b].mesh[m].triangles[t].vertex_index[2]
  559. );
  560. }
  561. }
  562. // Export the mesh.
  563. man.end();
  564. Ogre::MeshPtr mesh = man.convertToMesh(name);
  565. //std::cout << "[WI] Export mesh " << (output_dir_ + "wm/" + mesh->getName() + ".mesh")
  566. // << std::endl;
  567. mesh_serializer.exportMesh(
  568. mesh.getPointer(),
  569. output_dir_ + TERRAIN_MODELS_DIR + "/" + std::to_string(processed_maps_) + "/" + mesh->getName() + ".mesh"
  570. );
  571. // WM0 is te main worldmap, its shape changes according to the history progress, it has
  572. // 68 blocks but only 63 are used at a time
  573. if (processed_maps_ > 0 || b < 63){
  574. std::unique_ptr<TiXmlElement> xml_block(new TiXmlElement("block"));
  575. xml_block->SetAttribute("index", std::to_string(b));
  576. xml_block->SetAttribute(
  577. "file_name", "terrain/" + std::to_string(processed_maps_) + "/" + mesh->getName() + ".mesh"
  578. );
  579. xml_block->SetAttribute("position", std::to_string(wm_offset_x) + " " + std::to_string(wm_offset_y) + " 0");
  580. if (processed_maps_ == 0){
  581. // TODO: Correct history points for each block.
  582. switch (b){
  583. case 50: // Block 50 replaced by block 63
  584. xml_block->SetAttribute("alt_file_name", "terrain/0/WM0_63.mesh");
  585. xml_block->SetAttribute("alt_story_change", "1000");
  586. break;
  587. case 41: // Block 41 replaced by block 64
  588. xml_block->SetAttribute("alt_file_name", "terrain/0/WM0_64.mesh");
  589. xml_block->SetAttribute("alt_story_change", "1000");
  590. break;
  591. case 42: // Block 42 replaced by block 65
  592. xml_block->SetAttribute("alt_file_name", "terrain/0/WM0_65.mesh");
  593. xml_block->SetAttribute("alt_story_change", "1000");
  594. break;
  595. case 60: // Block 60 replaced by block 66
  596. xml_block->SetAttribute("alt_file_name", "terrain/0/WM0_66.mesh");
  597. xml_block->SetAttribute("alt_story_change", "1000");
  598. break;
  599. case 47: // Block 50 replaced by block 67
  600. xml_block->SetAttribute("alt_file_name", "terrain/0/WM0_67.mesh");
  601. xml_block->SetAttribute("alt_story_change", "1000");
  602. break;
  603. case 48: // Block 50 replaced by block 68
  604. xml_block->SetAttribute("alt_file_name", "terrain/0/WM0_68.mesh");
  605. xml_block->SetAttribute("alt_story_change", "1000");
  606. break;
  607. }
  608. }
  609. xml_terrain->LinkEndChild(xml_block.release());
  610. }
  611. }
  612. // Add other data to the XML file.
  613. // Close and save XML file,
  614. xml->LinkEndChild(xml_terrain.release());
  615. doc.LinkEndChild(xml.release());
  616. // TODO: Add models, entities...
  617. doc.SaveFile(
  618. output_dir_ + "/world/" + std::to_string(processed_maps_) + "/world" + std::to_string(processed_maps_) + ".xml"
  619. );
  620. // Generate the walkmesh xml file
  621. walkmesh.generate(output_dir_ + "/world/" + std::to_string(processed_maps_) + "/wm.xml");
  622. // TODO: Generate other files: background, script, texts...
  623. // Ready for next map or next step.
  624. processed_maps_ ++;
  625. if (processed_maps_ >= wm_map_.size()) return true;
  626. else return false;
  627. }
  628. void WorldInstaller::ExportMesh(const std::string outdir, const Ogre::MeshPtr &mesh){
  629. if (mesh.isNull()){
  630. std::cerr << "[ERROR] ExportMesh called with null mesh." << std::endl;
  631. return;
  632. }
  633. boost::filesystem::create_directories(outdir);
  634. // TODO: Share function with pc model exporter
  635. VGears::String base_mesh_name;
  636. VGears::StringUtil::splitFull(mesh->getName(), base_mesh_name);
  637. Ogre::MeshSerializer mesh_serializer;
  638. Ogre::SkeletonPtr skeleton(mesh->getSkeleton());
  639. if (!skeleton.isNull()){
  640. Ogre::SkeletonSerializer skeleton_serializer;
  641. skeleton_serializer.exportSkeleton(skeleton.getPointer(), outdir + base_mesh_name + ".skeleton");
  642. mesh->setSkeletonName(base_mesh_name + ".skeleton");
  643. }
  644. mesh_serializer.exportMesh(mesh.getPointer(), outdir + mesh->getName());
  645. Ogre::Mesh::SubMeshIterator it(mesh->getSubMeshIterator());
  646. Ogre::MaterialSerializer mat_ser;
  647. size_t i(0);
  648. std::set<std::string> textures;
  649. std::set<std::string> queued_materials;
  650. bool has_queued_materials = false;
  651. while (it.hasMoreElements()){
  652. Ogre::SubMesh *sub_mesh(it.getNext());
  653. Ogre::MaterialPtr mat(Ogre::MaterialManager::getSingleton().getByName(sub_mesh->getMaterialName()));
  654. if (mat != nullptr){
  655. for (size_t techs = 0; techs < mat->getNumTechniques(); techs ++){
  656. Ogre::Technique* tech = mat->getTechnique(techs);
  657. if (tech){
  658. for (size_t pass_num = 0; pass_num < tech->getNumPasses(); pass_num ++){
  659. Ogre::Pass* pass = tech->getPass(pass_num);
  660. if (pass){
  661. for (
  662. size_t texture_unit_num = 0;
  663. texture_unit_num < pass->getNumTextureUnitStates();
  664. texture_unit_num ++
  665. ){
  666. Ogre::TextureUnitState* unit = pass->getTextureUnitState(texture_unit_num);
  667. if (unit && unit->getTextureName().empty() == false){
  668. try{
  669. // Convert the texture from .tex to .png.
  670. TexFile tex(output_dir_ + "temp/world_models/" + unit->getTextureName());
  671. // Ensure the output material script references png files
  672. // rather than tex files.
  673. Ogre::String base_name;
  674. VGears::StringUtil::splitBase(unit->getTextureName(), base_name);
  675. unit->setTextureName(base_mesh_name + "_" + base_name + ".png");
  676. const auto plain_png = outdir + base_name + ".png";
  677. const auto model_png = outdir + base_mesh_name + "_" + base_name + ".png";
  678. tex.SavePng(plain_png, 0);
  679. boost::filesystem::copy_file(
  680. plain_png, model_png, boost::filesystem::copy_options::overwrite_existing
  681. );
  682. textures.insert(unit->getTextureName());
  683. }
  684. catch (const std::exception& ex){
  685. std::cerr << "[ERROR] Texture export failed for "
  686. << unit->getTextureName() << ": " << ex.what() << std::endl;
  687. }
  688. }
  689. }
  690. }
  691. }
  692. }
  693. }
  694. // Queue each material once. Exporting with an empty queue throws in Ogre.
  695. if (queued_materials.insert(sub_mesh->getMaterialName()).second){
  696. mat_ser.queueForExport(mat);
  697. has_queued_materials = true;
  698. }
  699. }
  700. ++ i;
  701. }
  702. if (has_queued_materials) mat_ser.exportQueued(outdir + base_mesh_name + VGears::EXT_MATERIAL);
  703. for (auto& texture_name : textures){
  704. std::string tex_name = texture_name.c_str();
  705. try{
  706. Ogre::TexturePtr texture_ptr = Ogre::TextureManager::getSingleton().load(tex_name, "FFVIITextures");
  707. //Ogre::TexturePtr texture_ptr = Ogre::TextureManager::getSingleton().load(tex_name, "FFVII");
  708. Ogre::Image image;
  709. texture_ptr->convertToImage(image);
  710. Ogre::String base_name;
  711. VGears::StringUtil::splitBase(texture_name, base_name);
  712. image.save(outdir + base_mesh_name + "_" + base_name + ".png");
  713. }
  714. catch (std::exception const& ex){
  715. std::cerr << "[ERROR] Exception: " << ex.what() << std::endl;
  716. }
  717. }
  718. }