Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

TombRaider.cpp 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. /*!
  2. * \file test/TombRaider.cpp
  3. * \brief Loads maps, meshes, textures...
  4. *
  5. * \author Mongoose
  6. */
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <math.h>
  10. #include <string.h>
  11. #include <stdarg.h>
  12. #include <TombRaider.h>
  13. #ifdef __TEST_TR5_DUMP_TGA
  14. #include <utils/tga.h>
  15. #endif
  16. #ifdef DEBUG_MEMORY
  17. #include <memory_test.h>
  18. #endif
  19. void dump_textures(TombRaider *tr, char *mapname)
  20. {
  21. #ifdef __TEST_TR5_DUMP_TGA
  22. int i;
  23. unsigned char *image;
  24. unsigned char *bumpmap;
  25. char buffer[128];
  26. FILE *f;
  27. if (!tr || !mapname)
  28. return;
  29. // Dump textures
  30. printf("\n\t[Texture dumping for '%s']\n", mapname);
  31. for (i = 0; i < tr->NumTextures(); i++)
  32. {
  33. tr->Texture(i, &image, &bumpmap);
  34. if (image)
  35. {
  36. snprintf(buffer, 128, "%s-%03i-texture.tga", mapname, i);
  37. f = fopen(buffer, "wb");
  38. if (f)
  39. {
  40. if (!tga_save(f, image, 256, 256, 4))
  41. printf("\tWrote texture %s\n", buffer);
  42. fclose(f);
  43. }
  44. snprintf(buffer, 128, "%s.lst", mapname);
  45. f = fopen(buffer, "a");
  46. if (f)
  47. {
  48. fprintf(f, "%s-%03i-texture.tga;\n", mapname, i);
  49. fclose(f);
  50. }
  51. delete [] image;
  52. }
  53. if (bumpmap)
  54. {
  55. snprintf(buffer, 64, "%s-%03i-bumpmap.tga", mapname, i);
  56. f = fopen(buffer, "wb");
  57. if (f)
  58. {
  59. if (!tga_save(f, bumpmap, 256, 256, 4))
  60. printf("\tWrote texture %s\n", buffer);
  61. fclose(f);
  62. }
  63. delete [] bumpmap;
  64. }
  65. }
  66. for (i = 0; i < tr->NumSpecialTextures(); i++)
  67. {
  68. image = tr->SpecialTexTile(i);
  69. snprintf(buffer, 128, "%s-%03i-special.tga", mapname, i);
  70. f = fopen(buffer, "wb");
  71. if (f)
  72. {
  73. if (!tga_save(f, image, 256, 256, 4))
  74. printf("\tWrote texture %s\n", buffer);
  75. fclose(f);
  76. }
  77. else
  78. {
  79. printf("\tFailed to write texture %s\n", buffer);
  80. }
  81. delete [] image;
  82. }
  83. #else
  84. printf("Texture dumping not in this build\n");
  85. #endif
  86. }
  87. void dump_mesh(TombRaider *tr, char *mapname, int index)
  88. {
  89. tr2_object_texture_t *object_texture = NULL;
  90. tr2_mesh_t *meshes = NULL;
  91. unsigned int v, check;
  92. int i, triangles, rectangles, t_index;
  93. char buffer[128];
  94. float rgba[4];
  95. float s, t;
  96. char id[8];
  97. FILE *f;
  98. if (!mapname || !tr)
  99. {
  100. return;
  101. }
  102. snprintf(buffer, 128, "%s-%03i.mesh", mapname, index);
  103. object_texture = tr->ObjectTextures();
  104. meshes = tr->Mesh();
  105. f = fopen(buffer, "wb");
  106. if (!f)
  107. {
  108. perror("Failed to write mesh :");
  109. return;
  110. }
  111. // Setup header id and check points
  112. strncpy(id, "TRMESH", 7);
  113. id[7] = 0;
  114. check = 0xcdcdcdcd;
  115. fwrite(id, 8, 1, f);
  116. fwrite(&meshes[index].num_vertices, 2, 1, f);
  117. fwrite(&meshes[index].num_textured_triangles, 2, 1, f);
  118. fwrite(&meshes[index].num_textured_rectangles, 2, 1, f);
  119. fwrite(&meshes[index].num_coloured_triangles, 2, 1, f);
  120. fwrite(&meshes[index].num_coloured_rectangles, 2, 1, f);
  121. fwrite(&meshes[index].collision_size, 4, 1, f);
  122. // Textured triangles ////////////////////////
  123. fwrite(&check, 4, 1, f);
  124. triangles = meshes[index].num_textured_triangles;
  125. for (i = 0; triangles > 0 && i < triangles; i++)
  126. {
  127. t_index = meshes[index].textured_triangles[i].texture;
  128. // Store texture info
  129. fwrite(&object_texture[t_index].tile, 2, 1, f);
  130. fwrite(&object_texture[t_index].transparency_flags, 2, 1, f);
  131. // Store vertices
  132. v = meshes[index].textured_triangles[i].vertices[0];
  133. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  134. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  135. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  136. v = meshes[index].textured_triangles[i].vertices[1];
  137. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  138. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  139. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  140. v = meshes[index].textured_triangles[i].vertices[2];
  141. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  142. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  143. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  144. // Store texels
  145. s = tr->adjustTexel(object_texture[t_index].vertices[0].xpixel,
  146. object_texture[t_index].vertices[0].xcoordinate);
  147. t = tr->adjustTexel(object_texture[t_index].vertices[0].ypixel,
  148. object_texture[t_index].vertices[0].ycoordinate);
  149. fwrite(&s, 4, 1, f);
  150. fwrite(&t, 4, 1, f);
  151. s = tr->adjustTexel(object_texture[t_index].vertices[1].xpixel,
  152. object_texture[t_index].vertices[1].xcoordinate);
  153. t = tr->adjustTexel(object_texture[t_index].vertices[1].ypixel,
  154. object_texture[t_index].vertices[1].ycoordinate);
  155. fwrite(&s, 4, 1, f);
  156. fwrite(&t, 4, 1, f);
  157. s = tr->adjustTexel(object_texture[t_index].vertices[2].xpixel,
  158. object_texture[t_index].vertices[2].xcoordinate);
  159. t = tr->adjustTexel(object_texture[t_index].vertices[2].ypixel,
  160. object_texture[t_index].vertices[2].ycoordinate);
  161. fwrite(&s, 4, 1, f);
  162. fwrite(&t, 4, 1, f);
  163. }
  164. fwrite(&check, 4, 1, f);
  165. // Textured rectangles ////////////////////////
  166. fwrite(&check, 4, 1, f);
  167. rectangles = meshes[index].num_textured_rectangles;
  168. for (i = 0; rectangles > 0 && i < rectangles; i++)
  169. {
  170. t_index = meshes[index].textured_rectangles[i].texture;
  171. // Store texture info
  172. fwrite(&object_texture[t_index].tile, 2, 1, f);
  173. fwrite(&object_texture[t_index].transparency_flags, 2, 1, f);
  174. // Store vertices
  175. v = meshes[index].textured_rectangles[i].vertices[0];
  176. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  177. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  178. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  179. v = meshes[index].textured_rectangles[i].vertices[1];
  180. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  181. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  182. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  183. v = meshes[index].textured_rectangles[i].vertices[2];
  184. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  185. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  186. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  187. v = meshes[index].textured_rectangles[i].vertices[3];
  188. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  189. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  190. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  191. // Store texels
  192. s = tr->adjustTexel(object_texture[t_index].vertices[0].xpixel,
  193. object_texture[t_index].vertices[0].xcoordinate);
  194. t = tr->adjustTexel(object_texture[t_index].vertices[0].ypixel,
  195. object_texture[t_index].vertices[0].ycoordinate);
  196. fwrite(&s, 4, 1, f);
  197. fwrite(&t, 4, 1, f);
  198. s = tr->adjustTexel(object_texture[t_index].vertices[1].xpixel,
  199. object_texture[t_index].vertices[1].xcoordinate);
  200. t = tr->adjustTexel(object_texture[t_index].vertices[1].ypixel,
  201. object_texture[t_index].vertices[1].ycoordinate);
  202. fwrite(&s, 4, 1, f);
  203. fwrite(&t, 4, 1, f);
  204. s = tr->adjustTexel(object_texture[t_index].vertices[2].xpixel,
  205. object_texture[t_index].vertices[2].xcoordinate);
  206. t = tr->adjustTexel(object_texture[t_index].vertices[2].ypixel,
  207. object_texture[t_index].vertices[2].ycoordinate);
  208. fwrite(&s, 4, 1, f);
  209. fwrite(&t, 4, 1, f);
  210. s = tr->adjustTexel(object_texture[t_index].vertices[3].xpixel,
  211. object_texture[t_index].vertices[3].xcoordinate);
  212. t = tr->adjustTexel(object_texture[t_index].vertices[3].ypixel,
  213. object_texture[t_index].vertices[3].ycoordinate);
  214. fwrite(&s, 4, 1, f);
  215. fwrite(&t, 4, 1, f);
  216. }
  217. fwrite(&check, 4, 1, f);
  218. // Coloured triangles ////////////////////////
  219. fwrite(&check, 4, 1, f);
  220. triangles = meshes[index].num_coloured_triangles;
  221. for (i = 0; triangles > 0 && i < triangles; i++)
  222. {
  223. // Store vertices
  224. v = meshes[index].coloured_triangles[i].vertices[0];
  225. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  226. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  227. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  228. v = meshes[index].coloured_triangles[i].vertices[1];
  229. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  230. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  231. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  232. v = meshes[index].coloured_triangles[i].vertices[2];
  233. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  234. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  235. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  236. // Store color
  237. switch (tr->Engine())
  238. {
  239. case TR_VERSION_1:
  240. tr->getColor(meshes[index].coloured_triangles[i].texture
  241. & 0xff, rgba);
  242. break;
  243. case TR_VERSION_UNKNOWN:
  244. case TR_VERSION_2:
  245. case TR_VERSION_3:
  246. case TR_VERSION_4:
  247. case TR_VERSION_5:
  248. tr->getColor((meshes[index].coloured_triangles[i].texture>>8)
  249. & 0xff, rgba);
  250. break;
  251. }
  252. s = rgba[0];
  253. t = rgba[1];
  254. fwrite(&s, 4, 1, f);
  255. fwrite(&t, 4, 1, f);
  256. s = rgba[2];
  257. t = rgba[3];
  258. fwrite(&s, 4, 1, f);
  259. fwrite(&t, 4, 1, f);
  260. }
  261. fwrite(&check, 4, 1, f);
  262. // Coloured rectangles ////////////////////////
  263. fwrite(&check, 4, 1, f);
  264. rectangles = meshes[index].num_coloured_rectangles;
  265. for (i = 0; rectangles > 0 && i < rectangles; i++)
  266. {
  267. // Store vertices
  268. v = meshes[index].coloured_rectangles[i].vertices[0];
  269. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  270. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  271. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  272. v = meshes[index].coloured_rectangles[i].vertices[1];
  273. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  274. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  275. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  276. v = meshes[index].coloured_rectangles[i].vertices[2];
  277. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  278. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  279. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  280. v = meshes[index].coloured_rectangles[i].vertices[3];
  281. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  282. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  283. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  284. // Store color
  285. switch (tr->Engine())
  286. {
  287. case TR_VERSION_1:
  288. tr->getColor(meshes[index].coloured_rectangles[i].texture
  289. & 0xff, rgba);
  290. break;
  291. case TR_VERSION_UNKNOWN:
  292. case TR_VERSION_2:
  293. case TR_VERSION_3:
  294. case TR_VERSION_4:
  295. case TR_VERSION_5:
  296. tr->getColor((meshes[index].coloured_rectangles[i].texture>>8)
  297. & 0xff, rgba);
  298. break;
  299. }
  300. s = rgba[0];
  301. t = rgba[1];
  302. fwrite(&s, 4, 1, f);
  303. fwrite(&t, 4, 1, f);
  304. s = rgba[2];
  305. t = rgba[3];
  306. fwrite(&s, 4, 1, f);
  307. fwrite(&t, 4, 1, f);
  308. }
  309. fwrite(&check, 4, 1, f);
  310. fclose(f);
  311. printf(".");
  312. fflush(stdout);
  313. }
  314. void dump_lara_stuff(char *mapname, TombRaider &tr)
  315. {
  316. unsigned int i, j, k, n;
  317. tr2_moveable_t *moveable = tr.Moveable();
  318. unsigned int numMoveables = tr.NumMoveables();
  319. char filename[64];
  320. unsigned char *riff;
  321. unsigned int riffSz, total = 0;
  322. FILE *f;
  323. snprintf(filename, 63, "%s-lara.nfo", mapname);
  324. f = fopen(filename, "w");
  325. if (!f)
  326. {
  327. perror("Failed to write lara.nfo: ");
  328. return;
  329. }
  330. for (i = 0; i < numMoveables; ++i)
  331. {
  332. j = n = 0;
  333. if (moveable[i].object_id == 0)
  334. {
  335. j = moveable[i].starting_mesh;
  336. n = moveable[i].num_meshes + j;
  337. fprintf(f, "Lara (%u)\n", i);
  338. }
  339. else if (moveable[i].object_id == 30)
  340. {
  341. j = moveable[i].starting_mesh;
  342. n = moveable[i].num_meshes + j;
  343. fprintf(f, "Lara ponytail\n");
  344. }
  345. else if (tr.Engine() == TR_VERSION_4)
  346. {
  347. switch (moveable[i].object_id)
  348. {
  349. case 8: // Joints, ( interconnecting skin/ploys )
  350. case 9:
  351. fprintf(f, "TR4 lara joints (%u)\n", i);
  352. j = moveable[i].starting_mesh;
  353. n = moveable[i].num_meshes + j;
  354. }
  355. }
  356. for (k = j; j < n; ++j)
  357. {
  358. fprintf(f, "\tMesh[%i] = %u\n", (j - k), j);
  359. }
  360. }
  361. fclose(f);
  362. printf("\nDumping %u audio samples: ", tr.getSoundSamplesCount());
  363. for (i = 0, j = 0; i < tr.getSoundSamplesCount(); ++i)
  364. {
  365. tr.getSoundSample(i, &riffSz, &riff);
  366. total += riffSz;
  367. snprintf(filename, 63, "%s-%03i.wav", mapname, j++);
  368. f = fopen(filename, "wb");
  369. if (!f)
  370. {
  371. perror("Failed to write riff.wav: ");
  372. continue;
  373. }
  374. fwrite(riff, 1, riffSz, f);
  375. fclose(f);
  376. delete [] riff;
  377. printf(".");
  378. fflush(stdout);
  379. }
  380. printf("\n");
  381. if (total)
  382. {
  383. printf("Dumped %ubytes (%.2f MB) of audio samples\n",
  384. total, (float)total/1024000.0);
  385. }
  386. }
  387. void percent_callback(int p)
  388. {
  389. printf("Level %i%% loaded\n", p);
  390. }
  391. int test_main(int argc, char *argv[])
  392. {
  393. TombRaider tr;
  394. char mapname[128];
  395. int len, i, j;
  396. printf("[TombRaider class test]\n");
  397. tr.setDebug(true);
  398. if (argc > 2)
  399. {
  400. // Strip for mapname //////////////////////////////
  401. len = strlen(argv[2]);
  402. for (i = len, j = 0; i > 0; i--, j++)
  403. if (argv[2][i] == '/' || argv[2][i] == '\\')
  404. break;
  405. j--;
  406. memset(mapname, 0, 128);
  407. for (i = 0; i < len - j && i < 30; i++)
  408. mapname[i] = argv[2][i + len - j];
  409. ////////////////////////////////////////////////////
  410. if (strncmp(argv[1], "load", 4) == 0)
  411. {
  412. if (!tr.Load(argv[2], percent_callback))
  413. {
  414. printf("\nmain: Load reports success.\n");
  415. }
  416. }
  417. else if (strncmp(argv[1], "dump", 4) == 0)
  418. {
  419. if (!tr.Load(argv[2], percent_callback))
  420. {
  421. printf("\nmain: Load reports success.\n");
  422. dump_textures(&tr, mapname);
  423. printf("Mesh dumping: ");
  424. for (i = 0; i < tr.getMeshCount(); i++)
  425. {
  426. dump_mesh(&tr, mapname, i);
  427. }
  428. if (argc > 3)
  429. {
  430. printf("\nLoading external sound SFX.\n");
  431. tr.loadSFX(argv[3]);
  432. }
  433. dump_lara_stuff(mapname, tr);
  434. printf("\n");
  435. }
  436. else
  437. {
  438. printf("\nmain: Load failed.\n");
  439. }
  440. }
  441. else
  442. printf("\n\n%s [ load | dump ] filename [sound.sfx]\n", argv[0]);
  443. }
  444. else
  445. {
  446. printf("\n\n%s [ load | dump ] filename [sound.sfx]\n", argv[0]);
  447. }
  448. return 0;
  449. }
  450. int main(int argc, char *argv[])
  451. {
  452. test_main(argc, argv);
  453. #ifdef DEBUG_MEMORY
  454. dump_memory_report();
  455. #endif
  456. return 0;
  457. }