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 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
  2. /*================================================================
  3. *
  4. * Project : OpenRaider
  5. * Author : Mongoose
  6. * Website : http://www.westga.edu/~stu7440/
  7. * Email : stu7440@westga.edu
  8. * Object : OpenRaider
  9. * License : No use w/o permission (C) 2001 Mongoose
  10. * Comments: Loads TR 1, 2, 3, and 4 maps, meshes, and textures
  11. *
  12. * This file was generated using Mongoose's C++
  13. * template generator script. <stu7440@westga.edu>
  14. *
  15. *-- History ------------------------------------------------
  16. *
  17. * 2003.05.13:
  18. * Mongoose - New API, maintance cost was becoming so high
  19. * it was needed to sort out methods in groups
  20. * like my newer source code -- of course some
  21. * methods were altered or removed ( clean up )
  22. *
  23. * 2001.06.19:
  24. * Mongoose - New texture API for the new TR4/TR5 bump map
  25. * support, also purged textile exposure
  26. *
  27. * 2001.05.21:
  28. * Mongoose - Added to project OpenRaider, more documentation
  29. * than Freyja version I wrote ( 3d modeler )
  30. *
  31. *
  32. * 2000-05-13:
  33. * Mongoose - Added gcc and VC++ pragmas for packing
  34. *
  35. * id style typedefs for structs
  36. *
  37. * Heavy clean up and ported to C++
  38. *
  39. * I saved yuri's notes as best I could and
  40. * reformatted and corected as needed
  41. *
  42. * Mongoose - Created, based on:
  43. * tr_view's tr2io.c by Yuri Zhivago, PhD,
  44. * TR Rosetta Stone ( TombRaider pak format specs )
  45. ================================================================*/
  46. #include <stdlib.h>
  47. #include <stdio.h>
  48. #include <math.h>
  49. #include <string.h>
  50. #include <stdarg.h>
  51. #include <TombRaider.h>
  52. #ifdef __TEST_TR5_DUMP_TGA
  53. #include <utils/tga.h>
  54. #endif
  55. #ifdef DEBUG_MEMORY
  56. #include <memory_test.h>
  57. #endif
  58. void dump_textures(TombRaider *tr, char *mapname)
  59. {
  60. #ifdef __TEST_TR5_DUMP_TGA
  61. int i;
  62. unsigned char *image;
  63. unsigned char *bumpmap;
  64. char buffer[128];
  65. FILE *f;
  66. if (!tr || !mapname)
  67. return;
  68. // Dump textures
  69. printf("\n\t[Texture dumping for '%s']\n", mapname);
  70. for (i = 0; i < tr->NumTextures(); i++)
  71. {
  72. tr->Texture(i, &image, &bumpmap);
  73. if (image)
  74. {
  75. snprintf(buffer, 128, "%s-%03i-texture.tga", mapname, i);
  76. f = fopen(buffer, "wb");
  77. if (f)
  78. {
  79. if (!tga_save(f, image, 256, 256, 4))
  80. printf("\tWrote texture %s\n", buffer);
  81. fclose(f);
  82. }
  83. snprintf(buffer, 128, "%s.lst", mapname);
  84. f = fopen(buffer, "a");
  85. if (f)
  86. {
  87. fprintf(f, "%s-%03i-texture.tga;\n", mapname, i);
  88. fclose(f);
  89. }
  90. delete [] image;
  91. }
  92. if (bumpmap)
  93. {
  94. snprintf(buffer, 64, "%s-%03i-bumpmap.tga", mapname, i);
  95. f = fopen(buffer, "wb");
  96. if (f)
  97. {
  98. if (!tga_save(f, bumpmap, 256, 256, 4))
  99. printf("\tWrote texture %s\n", buffer);
  100. fclose(f);
  101. }
  102. delete [] bumpmap;
  103. }
  104. }
  105. for (i = 0; i < tr->NumSpecialTextures(); i++)
  106. {
  107. image = tr->SpecialTexTile(i);
  108. snprintf(buffer, 128, "%s-%03i-special.tga", mapname, i);
  109. f = fopen(buffer, "wb");
  110. if (f)
  111. {
  112. if (!tga_save(f, image, 256, 256, 4))
  113. printf("\tWrote texture %s\n", buffer);
  114. fclose(f);
  115. }
  116. else
  117. {
  118. printf("\tFailed to write texture %s\n", buffer);
  119. }
  120. delete [] image;
  121. }
  122. #else
  123. printf("Texture dumping not in this build\n");
  124. #endif
  125. }
  126. void dump_mesh(TombRaider *tr, char *mapname, int index)
  127. {
  128. tr2_object_texture_t *object_texture = NULL;
  129. tr2_mesh_t *meshes = NULL;
  130. unsigned int v, check;
  131. int i, triangles, rectangles, t_index;
  132. char buffer[128];
  133. float rgba[4];
  134. float s, t;
  135. char id[8];
  136. FILE *f;
  137. if (!mapname || !tr)
  138. {
  139. return;
  140. }
  141. snprintf(buffer, 128, "%s-%03i.mesh", mapname, index);
  142. object_texture = tr->ObjectTextures();
  143. meshes = tr->Mesh();
  144. f = fopen(buffer, "wb");
  145. if (!f)
  146. {
  147. perror("Failed to write mesh :");
  148. return;
  149. }
  150. // Setup header id and check points
  151. strncpy(id, "TRMESH", 7);
  152. id[7] = 0;
  153. check = 0xcdcdcdcd;
  154. fwrite(id, 8, 1, f);
  155. fwrite(&meshes[index].num_vertices, 2, 1, f);
  156. fwrite(&meshes[index].num_textured_triangles, 2, 1, f);
  157. fwrite(&meshes[index].num_textured_rectangles, 2, 1, f);
  158. fwrite(&meshes[index].num_coloured_triangles, 2, 1, f);
  159. fwrite(&meshes[index].num_coloured_rectangles, 2, 1, f);
  160. fwrite(&meshes[index].collision_size, 4, 1, f);
  161. // Textured triangles ////////////////////////
  162. fwrite(&check, 4, 1, f);
  163. triangles = meshes[index].num_textured_triangles;
  164. for (i = 0; triangles > 0 && i < triangles; i++)
  165. {
  166. t_index = meshes[index].textured_triangles[i].texture;
  167. // Store texture info
  168. fwrite(&object_texture[t_index].tile, 2, 1, f);
  169. fwrite(&object_texture[t_index].transparency_flags, 2, 1, f);
  170. // Store vertices
  171. v = meshes[index].textured_triangles[i].vertices[0];
  172. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  173. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  174. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  175. v = meshes[index].textured_triangles[i].vertices[1];
  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_triangles[i].vertices[2];
  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. // Store texels
  184. s = tr->adjustTexel(object_texture[t_index].vertices[0].xpixel,
  185. object_texture[t_index].vertices[0].xcoordinate);
  186. t = tr->adjustTexel(object_texture[t_index].vertices[0].ypixel,
  187. object_texture[t_index].vertices[0].ycoordinate);
  188. fwrite(&s, 4, 1, f);
  189. fwrite(&t, 4, 1, f);
  190. s = tr->adjustTexel(object_texture[t_index].vertices[1].xpixel,
  191. object_texture[t_index].vertices[1].xcoordinate);
  192. t = tr->adjustTexel(object_texture[t_index].vertices[1].ypixel,
  193. object_texture[t_index].vertices[1].ycoordinate);
  194. fwrite(&s, 4, 1, f);
  195. fwrite(&t, 4, 1, f);
  196. s = tr->adjustTexel(object_texture[t_index].vertices[2].xpixel,
  197. object_texture[t_index].vertices[2].xcoordinate);
  198. t = tr->adjustTexel(object_texture[t_index].vertices[2].ypixel,
  199. object_texture[t_index].vertices[2].ycoordinate);
  200. fwrite(&s, 4, 1, f);
  201. fwrite(&t, 4, 1, f);
  202. }
  203. fwrite(&check, 4, 1, f);
  204. // Textured rectangles ////////////////////////
  205. fwrite(&check, 4, 1, f);
  206. rectangles = meshes[index].num_textured_rectangles;
  207. for (i = 0; rectangles > 0 && i < rectangles; i++)
  208. {
  209. t_index = meshes[index].textured_rectangles[i].texture;
  210. // Store texture info
  211. fwrite(&object_texture[t_index].tile, 2, 1, f);
  212. fwrite(&object_texture[t_index].transparency_flags, 2, 1, f);
  213. // Store vertices
  214. v = meshes[index].textured_rectangles[i].vertices[0];
  215. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  216. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  217. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  218. v = meshes[index].textured_rectangles[i].vertices[1];
  219. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  220. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  221. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  222. v = meshes[index].textured_rectangles[i].vertices[2];
  223. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  224. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  225. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  226. v = meshes[index].textured_rectangles[i].vertices[3];
  227. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  228. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  229. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  230. // Store texels
  231. s = tr->adjustTexel(object_texture[t_index].vertices[0].xpixel,
  232. object_texture[t_index].vertices[0].xcoordinate);
  233. t = tr->adjustTexel(object_texture[t_index].vertices[0].ypixel,
  234. object_texture[t_index].vertices[0].ycoordinate);
  235. fwrite(&s, 4, 1, f);
  236. fwrite(&t, 4, 1, f);
  237. s = tr->adjustTexel(object_texture[t_index].vertices[1].xpixel,
  238. object_texture[t_index].vertices[1].xcoordinate);
  239. t = tr->adjustTexel(object_texture[t_index].vertices[1].ypixel,
  240. object_texture[t_index].vertices[1].ycoordinate);
  241. fwrite(&s, 4, 1, f);
  242. fwrite(&t, 4, 1, f);
  243. s = tr->adjustTexel(object_texture[t_index].vertices[2].xpixel,
  244. object_texture[t_index].vertices[2].xcoordinate);
  245. t = tr->adjustTexel(object_texture[t_index].vertices[2].ypixel,
  246. object_texture[t_index].vertices[2].ycoordinate);
  247. fwrite(&s, 4, 1, f);
  248. fwrite(&t, 4, 1, f);
  249. s = tr->adjustTexel(object_texture[t_index].vertices[3].xpixel,
  250. object_texture[t_index].vertices[3].xcoordinate);
  251. t = tr->adjustTexel(object_texture[t_index].vertices[3].ypixel,
  252. object_texture[t_index].vertices[3].ycoordinate);
  253. fwrite(&s, 4, 1, f);
  254. fwrite(&t, 4, 1, f);
  255. }
  256. fwrite(&check, 4, 1, f);
  257. // Coloured triangles ////////////////////////
  258. fwrite(&check, 4, 1, f);
  259. triangles = meshes[index].num_coloured_triangles;
  260. for (i = 0; triangles > 0 && i < triangles; i++)
  261. {
  262. // Store vertices
  263. v = meshes[index].coloured_triangles[i].vertices[0];
  264. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  265. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  266. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  267. v = meshes[index].coloured_triangles[i].vertices[1];
  268. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  269. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  270. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  271. v = meshes[index].coloured_triangles[i].vertices[2];
  272. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  273. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  274. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  275. // Store color
  276. switch (tr->Engine())
  277. {
  278. case TR_VERSION_1:
  279. tr->getColor(meshes[index].coloured_triangles[i].texture
  280. & 0xff, rgba);
  281. break;
  282. case TR_VERSION_UNKNOWN:
  283. case TR_VERSION_2:
  284. case TR_VERSION_3:
  285. case TR_VERSION_4:
  286. case TR_VERSION_5:
  287. tr->getColor((meshes[index].coloured_triangles[i].texture>>8)
  288. & 0xff, rgba);
  289. break;
  290. }
  291. s = rgba[0];
  292. t = rgba[1];
  293. fwrite(&s, 4, 1, f);
  294. fwrite(&t, 4, 1, f);
  295. s = rgba[2];
  296. t = rgba[3];
  297. fwrite(&s, 4, 1, f);
  298. fwrite(&t, 4, 1, f);
  299. }
  300. fwrite(&check, 4, 1, f);
  301. // Coloured rectangles ////////////////////////
  302. fwrite(&check, 4, 1, f);
  303. rectangles = meshes[index].num_coloured_rectangles;
  304. for (i = 0; rectangles > 0 && i < rectangles; i++)
  305. {
  306. // Store vertices
  307. v = meshes[index].coloured_rectangles[i].vertices[0];
  308. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  309. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  310. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  311. v = meshes[index].coloured_rectangles[i].vertices[1];
  312. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  313. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  314. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  315. v = meshes[index].coloured_rectangles[i].vertices[2];
  316. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  317. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  318. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  319. v = meshes[index].coloured_rectangles[i].vertices[3];
  320. fwrite(&meshes[index].vertices[v].x, 2, 1, f);
  321. fwrite(&meshes[index].vertices[v].y, 2, 1, f);
  322. fwrite(&meshes[index].vertices[v].z, 2, 1, f);
  323. // Store color
  324. switch (tr->Engine())
  325. {
  326. case TR_VERSION_1:
  327. tr->getColor(meshes[index].coloured_rectangles[i].texture
  328. & 0xff, rgba);
  329. break;
  330. case TR_VERSION_UNKNOWN:
  331. case TR_VERSION_2:
  332. case TR_VERSION_3:
  333. case TR_VERSION_4:
  334. case TR_VERSION_5:
  335. tr->getColor((meshes[index].coloured_rectangles[i].texture>>8)
  336. & 0xff, rgba);
  337. break;
  338. }
  339. s = rgba[0];
  340. t = rgba[1];
  341. fwrite(&s, 4, 1, f);
  342. fwrite(&t, 4, 1, f);
  343. s = rgba[2];
  344. t = rgba[3];
  345. fwrite(&s, 4, 1, f);
  346. fwrite(&t, 4, 1, f);
  347. }
  348. fwrite(&check, 4, 1, f);
  349. fclose(f);
  350. printf(".");
  351. fflush(stdout);
  352. }
  353. void dump_lara_stuff(char *mapname, TombRaider &tr)
  354. {
  355. unsigned int i, j, k, n;
  356. tr2_moveable_t *moveable = tr.Moveable();
  357. unsigned int numMoveables = tr.NumMoveables();
  358. char filename[64];
  359. unsigned char *riff;
  360. unsigned int riffSz, total = 0;
  361. FILE *f;
  362. snprintf(filename, 63, "%s-lara.nfo", mapname);
  363. f = fopen(filename, "w");
  364. if (!f)
  365. {
  366. perror("Failed to write lara.nfo: ");
  367. return;
  368. }
  369. for (i = 0; i < numMoveables; ++i)
  370. {
  371. j = n = 0;
  372. if (moveable[i].object_id == 0)
  373. {
  374. j = moveable[i].starting_mesh;
  375. n = moveable[i].num_meshes + j;
  376. fprintf(f, "Lara (%u)\n", i);
  377. }
  378. else if (moveable[i].object_id == 30)
  379. {
  380. j = moveable[i].starting_mesh;
  381. n = moveable[i].num_meshes + j;
  382. fprintf(f, "Lara ponytail\n");
  383. }
  384. else if (tr.Engine() == TR_VERSION_4)
  385. {
  386. switch (moveable[i].object_id)
  387. {
  388. case 8: // Joints, ( interconnecting skin/ploys )
  389. case 9:
  390. fprintf(f, "TR4 lara joints (%u)\n", i);
  391. j = moveable[i].starting_mesh;
  392. n = moveable[i].num_meshes + j;
  393. }
  394. }
  395. for (k = j; j < n; ++j)
  396. {
  397. fprintf(f, "\tMesh[%i] = %u\n", (j - k), j);
  398. }
  399. }
  400. fclose(f);
  401. printf("\nDumping %u audio samples: ", tr.getSoundSamplesCount());
  402. for (i = 0, j = 0; i < tr.getSoundSamplesCount(); ++i)
  403. {
  404. tr.getSoundSample(i, &riffSz, &riff);
  405. total += riffSz;
  406. snprintf(filename, 63, "%s-%03i.wav", mapname, j++);
  407. f = fopen(filename, "wb");
  408. if (!f)
  409. {
  410. perror("Failed to write riff.wav: ");
  411. continue;
  412. }
  413. fwrite(riff, 1, riffSz, f);
  414. fclose(f);
  415. delete [] riff;
  416. printf(".");
  417. fflush(stdout);
  418. }
  419. printf("\n");
  420. if (total)
  421. {
  422. printf("Dumped %ubytes (%.2f MB) of audio samples\n",
  423. total, (float)total/1024000.0);
  424. }
  425. }
  426. void percent_callback(int p)
  427. {
  428. printf("Level %i%% loaded\n", p);
  429. }
  430. int test_main(int argc, char *argv[])
  431. {
  432. TombRaider tr;
  433. char mapname[128];
  434. int len, i, j;
  435. printf("[TombRaider class test]\n");
  436. tr.setDebug(true);
  437. if (argc > 2)
  438. {
  439. // Strip for mapname //////////////////////////////
  440. len = strlen(argv[2]);
  441. for (i = len, j = 0; i > 0; i--, j++)
  442. if (argv[2][i] == '/' || argv[2][i] == '\\')
  443. break;
  444. j--;
  445. memset(mapname, 0, 128);
  446. for (i = 0; i < len - j && i < 30; i++)
  447. mapname[i] = argv[2][i + len - j];
  448. ////////////////////////////////////////////////////
  449. if (strncmp(argv[1], "load", 4) == 0)
  450. {
  451. if (!tr.Load(argv[2], percent_callback))
  452. {
  453. printf("\nmain: Load reports success.\n");
  454. }
  455. }
  456. else if (strncmp(argv[1], "dump", 4) == 0)
  457. {
  458. if (!tr.Load(argv[2], percent_callback))
  459. {
  460. printf("\nmain: Load reports success.\n");
  461. dump_textures(&tr, mapname);
  462. printf("Mesh dumping: ");
  463. for (i = 0; i < tr.getMeshCount(); i++)
  464. {
  465. dump_mesh(&tr, mapname, i);
  466. }
  467. if (argc > 3)
  468. {
  469. printf("\nLoading external sound SFX.\n");
  470. tr.loadSFX(argv[3]);
  471. }
  472. dump_lara_stuff(mapname, tr);
  473. printf("\n");
  474. }
  475. else
  476. {
  477. printf("\nmain: Load failed.\n");
  478. }
  479. }
  480. else
  481. printf("\n\n%s [ load | dump ] filename [sound.sfx]\n", argv[0]);
  482. }
  483. else
  484. {
  485. printf("\n\n%s [ load | dump ] filename [sound.sfx]\n", argv[0]);
  486. }
  487. return 0;
  488. }
  489. int main(int argc, char *argv[])
  490. {
  491. test_main(argc, argv);
  492. #ifdef DEBUG_MEMORY
  493. dump_memory_report();
  494. #endif
  495. return 0;
  496. }