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.

Room.cpp 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /*!
  2. * \file src/Room.cpp
  3. * \brief World Room Mesh
  4. *
  5. * \author xythobuz
  6. */
  7. #ifdef __APPLE__
  8. #include <OpenGL/gl.h>
  9. #include <OpenGL/glu.h>
  10. #else
  11. #include <GL/gl.h>
  12. #include <GL/glu.h>
  13. #endif
  14. #include <algorithm>
  15. #include <assert.h>
  16. #include "main.h"
  17. #include "Room.h"
  18. Room::Room(TombRaider &tr, unsigned int index) {
  19. vec3_t box[2];
  20. Matrix transform;
  21. if (!tr.isRoomValid(index)) {
  22. getConsole().print("WARNING: Handling invalid vertex array in room");
  23. //printf("x");
  24. //fflush(stdout);
  25. return;
  26. }
  27. tr.getRoomInfo(index, &flags, pos, box[0], box[1]);
  28. // Adjust positioning for OR world coordinate translation
  29. box[0][0] += pos[0];
  30. box[1][0] += pos[0];
  31. box[0][2] += pos[2];
  32. box[1][2] += pos[2];
  33. bbox.setBoundingBox(box[0], box[1]);
  34. // Mongoose 2002.04.03, Setup 3D transform
  35. transform.setIdentity();
  36. transform.translate(pos);
  37. // Current room is always first
  38. adjacentRooms.push_back(index);
  39. // Setup portals
  40. unsigned int count = tr.getRoomPortalCount(index);
  41. for (unsigned int i = 0; i < count; i++) {
  42. portals.push_back(new Portal(tr, index, i, transform));
  43. adjacentRooms.push_back(portals.back()->getAdjoiningRoom());
  44. }
  45. //! \fixme Use more of sector structure, boxes, and floordata
  46. // List of sectors in this room
  47. count = tr.getRoomSectorCount(index, &numZSectors, &numXSectors);
  48. for (unsigned int i = 0; i < count; i++)
  49. sectors.push_back(new Sector(tr, index, i));
  50. // Setup collision boxes
  51. //! fixme Should use sectors, but this is a test
  52. count = tr.getRoomBoxCount(index);
  53. for (unsigned int i = 0; i < count; i++)
  54. boxes.push_back(new Box(tr, index, i));
  55. // Setup room lights
  56. count = tr.getRoomLightCount(index);
  57. for (unsigned int i = 0; i < count; i++)
  58. lights.push_back(new Light(tr, index, i));
  59. // Room models
  60. count = tr.getRoomModelCount(index);
  61. for (unsigned int i = 0; i < count; i++)
  62. models.push_back(new StaticModel(tr, index, i));
  63. // Room sprites
  64. count = tr.getRoomSpriteCount(index);
  65. for (unsigned int i = 0; i < count; i++)
  66. sprites.push_back(new Sprite(tr, index, i));
  67. //#define EXPERIMENTAL_UNIFIED_ROOM_GEOMETERY
  68. #ifdef EXPERIMENTAL_UNIFIED_ROOM_GEOMETERY
  69. unsigned int vertexCount, normalCount, colorCount, triCount;
  70. vec_t *vertexArray;
  71. vec_t *normalArray;
  72. vec_t *colorArray;
  73. unsigned int *indices, *fflags;
  74. float *texCoords;
  75. int *textures;
  76. tr.getRoomVertexArrays(index,
  77. &vertexCount, &vertexArray,
  78. &normalCount, &normalArray,
  79. &colorCount, &colorArray);
  80. mesh.bufferVertexArray(vertexCount, vertexArray);
  81. mesh.bufferNormalArray(normalCount, normalArray);
  82. mesh.bufferColorArray(vertexCount, colorArray);
  83. tr.getRoomTriangles(index, getGame().getTextureStart(),
  84. &triCount, &indices, &texCoords, &textures,
  85. &fflags);
  86. mesh.bufferTriangles(triCount, indices, texCoords, textures, fflags);
  87. #else
  88. const unsigned int TextureLimit = 24;
  89. float rgba[4];
  90. float xyz[3];
  91. count = tr.getRoomVertexCount(index);
  92. mesh.allocateVertices(count);
  93. mesh.allocateNormals(0); // count
  94. mesh.allocateColors(count);
  95. for (unsigned int i = 0; i < count; ++i)
  96. {
  97. tr.getRoomVertex(index, i, xyz, rgba);
  98. mesh.setVertex(i, xyz[0], xyz[1], xyz[2]);
  99. mesh.setColor(i, rgba);
  100. }
  101. // Mongoose 2002.06.09, Setup allocation of meshes and polygons
  102. // Counters ( Textured polygon lists are allocated per texture)
  103. // ( Textures are mapped to these meshes )
  104. int triangle_counter[TextureLimit];
  105. int triangle_counter_alpha[TextureLimit];
  106. int rectangle_counter[TextureLimit];
  107. int rectangle_counter_alpha[TextureLimit];
  108. int tris_mesh_map[TextureLimit];
  109. int rect_mesh_map[TextureLimit];
  110. for (unsigned int i = 0; i < TextureLimit; ++i)
  111. {
  112. triangle_counter[i] = 0;
  113. triangle_counter_alpha[i] = 0;
  114. rectangle_counter[i] = 0;
  115. rectangle_counter_alpha[i] = 0;
  116. tris_mesh_map[i] = -1;
  117. rect_mesh_map[i] = -1;
  118. }
  119. unsigned int numTris = 0;
  120. unsigned int numQuads = 0;
  121. int texture;
  122. unsigned int r, t, q, v;
  123. unsigned int indices[4];
  124. float texCoords[8];
  125. count = tr.getRoomTriangleCount(index);
  126. // Mongoose 2002.08.15, Presort by alpha and texture and setup mapping
  127. for (t = 0; t < count; ++t)
  128. {
  129. tr.getRoomTriangle(index, t,
  130. indices, texCoords, &texture, &flags);
  131. texture += getGame().getTextureStart();
  132. if (texture > (int)TextureLimit)
  133. {
  134. getConsole().print("Handling bad room[%i].tris[%i].texture = %i",
  135. index, t, texture);
  136. texture = TextureLimit - 1;
  137. }
  138. // Counters set up polygon allocation
  139. if (flags & tombraiderFace_Alpha ||
  140. flags & tombraiderFace_PartialAlpha)
  141. {
  142. triangle_counter_alpha[texture] += 1;
  143. }
  144. else
  145. {
  146. triangle_counter[texture] += 1;
  147. }
  148. // Counter sets up texture id to mesh id mapping
  149. if (tris_mesh_map[texture] == -1)
  150. {
  151. tris_mesh_map[texture] = ++numTris;
  152. }
  153. }
  154. count = tr.getRoomRectangleCount(index);
  155. for (r = 0; r < count; ++r)
  156. {
  157. tr.getRoomRectangle(index, r,
  158. indices, texCoords, &texture, &flags);
  159. texture += getGame().getTextureStart();
  160. if (texture > (int)TextureLimit)
  161. {
  162. getConsole().print("Handling bad room[%i].quad[%i].texture = %i",
  163. index, r, texture);
  164. texture = TextureLimit - 1;
  165. }
  166. if (flags & tombraiderFace_Alpha ||
  167. flags & tombraiderFace_PartialAlpha)
  168. {
  169. rectangle_counter_alpha[texture] += 1;
  170. }
  171. else
  172. {
  173. rectangle_counter[texture] += 1;
  174. }
  175. if (rect_mesh_map[texture] == -1)
  176. {
  177. rect_mesh_map[texture] = ++numQuads;
  178. }
  179. }
  180. // Allocate indexed polygon meshes
  181. mesh.allocateTriangles(numTris);
  182. mesh.allocateRectangles(numQuads);
  183. for (unsigned int i = 0, j = 0; i < TextureLimit; ++i)
  184. {
  185. if (tris_mesh_map[i] > 0)
  186. {
  187. j = tris_mesh_map[i] - 1;
  188. t = triangle_counter[i];
  189. mesh.mTris[j].texture = i;
  190. #ifdef MULTITEXTURE
  191. mesh.mTris[j].bumpmap = gMapTex2Bump[i];
  192. #endif
  193. mesh.mTris[j].cnum_triangles = 0;
  194. mesh.mTris[j].num_triangles = 0;
  195. mesh.mTris[j].cnum_alpha_triangles = 0;
  196. mesh.mTris[j].num_alpha_triangles = 0;
  197. mesh.mTris[j].triangles = 0x0;
  198. mesh.mTris[j].alpha_triangles = 0x0;
  199. mesh.mTris[j].texcoors = 0x0;
  200. mesh.mTris[j].texcoors2 = 0x0;
  201. if (t > 0)
  202. {
  203. mesh.mTris[j].num_triangles = t;
  204. mesh.mTris[j].triangles = new unsigned int[t*3];
  205. mesh.mTris[j].num_texcoors = t * 3;
  206. mesh.mTris[j].texcoors = new vec2_t[t * 3];
  207. }
  208. t = triangle_counter_alpha[i];
  209. if (t > 0)
  210. {
  211. mesh.mTris[j].num_alpha_triangles = t;
  212. mesh.mTris[j].alpha_triangles = new unsigned int[t*3];
  213. mesh.mTris[j].num_texcoors2 = t * 3;
  214. mesh.mTris[j].texcoors2 = new vec2_t[t * 3];
  215. }
  216. }
  217. ///////////////////////////////////////////
  218. if (rect_mesh_map[i] > 0)
  219. {
  220. j = rect_mesh_map[i] - 1;
  221. r = rectangle_counter[i];
  222. mesh.mQuads[j].texture = i;
  223. #ifdef MULTITEXTURE
  224. mesh.mQuads[j].bumpmap = gMapTex2Bump[i];
  225. #endif
  226. mesh.mQuads[j].cnum_quads = 0;
  227. mesh.mQuads[j].num_quads = 0;
  228. mesh.mQuads[j].cnum_alpha_quads = 0;
  229. mesh.mQuads[j].num_alpha_quads = 0;
  230. mesh.mQuads[j].quads = 0x0;
  231. mesh.mQuads[j].alpha_quads = 0x0;
  232. mesh.mQuads[j].texcoors = 0x0;
  233. mesh.mQuads[j].texcoors2 = 0x0;
  234. if (r > 0)
  235. {
  236. mesh.mQuads[j].num_quads = r;
  237. mesh.mQuads[j].quads = new unsigned int[r*4];
  238. mesh.mQuads[j].num_texcoors = r * 4;
  239. mesh.mQuads[j].texcoors = new vec2_t[r * 4];
  240. }
  241. r = rectangle_counter_alpha[i];
  242. if (r > 0)
  243. {
  244. mesh.mQuads[j].num_alpha_quads = r;
  245. mesh.mQuads[j].alpha_quads = new unsigned int[r*4];
  246. mesh.mQuads[j].num_texcoors2 = r * 4;
  247. mesh.mQuads[j].texcoors2 = new vec2_t[r * 4];
  248. }
  249. }
  250. }
  251. // Generate textured triangles
  252. count = tr.getRoomTriangleCount(index);
  253. for (t = 0; t < count; ++t)
  254. {
  255. tr.getRoomTriangle(index, t,
  256. indices, texCoords, &texture, &flags);
  257. // Adjust texture id using getGame().getTextureStart() to map into
  258. // correct textures
  259. texture += getGame().getTextureStart();
  260. unsigned int j = tris_mesh_map[texture] - 1;
  261. // Setup per vertex
  262. for (unsigned int i = 0; i < 3; ++i)
  263. {
  264. // Get vertex index {(0, a), (1, b), (2, c)}
  265. v = indices[i];
  266. if ((flags & tombraiderFace_Alpha ||
  267. flags & tombraiderFace_PartialAlpha) &&
  268. mesh.mTris[j].num_alpha_triangles > 0)
  269. {
  270. q = mesh.mTris[j].cnum_alpha_triangles*3+i;
  271. mesh.mTris[j].alpha_triangles[q] = v;
  272. mesh.mTris[j].texcoors2[q][0] = texCoords[i*2];
  273. mesh.mTris[j].texcoors2[q][1] = texCoords[i*2+1];
  274. }
  275. else if (mesh.mTris[j].num_triangles > 0)
  276. {
  277. q = mesh.mTris[j].cnum_triangles*3+i;
  278. mesh.mTris[j].triangles[q] = v;
  279. mesh.mTris[j].texcoors[q][0] = texCoords[i*2];
  280. mesh.mTris[j].texcoors[q][1] = texCoords[i*2+1];
  281. }
  282. // Partial alpha hack
  283. if (flags & tombraiderFace_PartialAlpha)
  284. {
  285. //mesh.colors[v].rgba[3] = 0.45;
  286. }
  287. }
  288. if (flags & tombraiderFace_Alpha ||
  289. flags & tombraiderFace_PartialAlpha)
  290. {
  291. mesh.mTris[j].cnum_alpha_triangles++;
  292. }
  293. else
  294. {
  295. mesh.mTris[j].cnum_triangles++;
  296. }
  297. }
  298. // Generate textured quads
  299. count = tr.getRoomRectangleCount(index);
  300. for (r = 0; r < count; ++r)
  301. {
  302. tr.getRoomRectangle(index, r,
  303. indices, texCoords, &texture, &flags);
  304. // Adjust texture id using getGame().getTextureStart() to map into
  305. // correct textures
  306. texture += getGame().getTextureStart();
  307. if (texture > (int)TextureLimit)
  308. {
  309. texture = TextureLimit - 1;
  310. }
  311. unsigned int j = rect_mesh_map[texture] - 1;
  312. if (mesh.mQuads[j].num_quads <= 0 &&
  313. mesh.mQuads[j].num_alpha_quads <= 0)
  314. continue;
  315. // Setup per vertex
  316. for (unsigned int i = 0; i < 4; ++i)
  317. {
  318. // Get vertex index {(0, a), (1, b), (2, c), (3, d)}
  319. v = indices[i];
  320. if ((flags & tombraiderFace_Alpha ||
  321. flags & tombraiderFace_PartialAlpha) &&
  322. mesh.mQuads[j].num_alpha_quads > 0)
  323. {
  324. q = mesh.mQuads[j].cnum_alpha_quads*4+i;
  325. mesh.mQuads[j].alpha_quads[q] = v;
  326. mesh.mQuads[j].texcoors2[q][0] = texCoords[i*2];
  327. mesh.mQuads[j].texcoors2[q][1] = texCoords[i*2+1];
  328. }
  329. else if (mesh.mQuads[j].num_quads > 0)
  330. {
  331. q = mesh.mQuads[j].cnum_quads*4+i;
  332. mesh.mQuads[j].quads[q] = v;
  333. mesh.mQuads[j].texcoors[q][0] = texCoords[i*2];
  334. mesh.mQuads[j].texcoors[q][1] = texCoords[i*2+1];
  335. }
  336. // Partial alpha hack
  337. if (flags & tombraiderFace_PartialAlpha)
  338. {
  339. //rRoom->mesh.colors[v].rgba[3] = 0.45;
  340. }
  341. }
  342. if (flags & tombraiderFace_Alpha ||
  343. flags & tombraiderFace_PartialAlpha)
  344. {
  345. mesh.mQuads[j].cnum_alpha_quads++;
  346. }
  347. else
  348. {
  349. mesh.mQuads[j].cnum_quads++;
  350. }
  351. }
  352. #endif
  353. }
  354. #define EMPTY_VECTOR(x) \
  355. while (!x.empty()) { \
  356. delete x[x.size() - 1]; \
  357. x.pop_back(); \
  358. }
  359. Room::~Room() {
  360. EMPTY_VECTOR(sprites);
  361. EMPTY_VECTOR(models);
  362. EMPTY_VECTOR(portals);
  363. EMPTY_VECTOR(boxes);
  364. EMPTY_VECTOR(sectors);
  365. EMPTY_VECTOR(lights);
  366. }
  367. void Room::display(bool alpha) {
  368. glPushMatrix();
  369. //LightingSetup();
  370. getRender().mTexture.bindTextureId(0); // WHITE texture
  371. if ((!alpha) && getRender().getMode() == Render::modeWireframe) {
  372. glLineWidth(2.0);
  373. glColor3fv(RED);
  374. for (unsigned int i = 0; i < sizePortals(); i++) {
  375. Portal &portal = getPortal(i);
  376. vec3_t vertices[4];
  377. portal.getVertices(vertices);
  378. glBegin(GL_LINE_LOOP);
  379. glVertex3fv(vertices[0]);
  380. glVertex3fv(vertices[1]);
  381. glVertex3fv(vertices[2]);
  382. glVertex3fv(vertices[3]);
  383. glEnd();
  384. }
  385. glLineWidth(1.0);
  386. }
  387. if (getRender().getMode() == Render::modeWireframe && (!alpha)) {
  388. bbox.display(true, RED, GREEN);
  389. }
  390. glTranslated(pos[0], pos[1], pos[2]);
  391. // Reset since GL_MODULATE used, reset to WHITE
  392. glColor3fv(WHITE);
  393. switch (getRender().getMode())
  394. {
  395. case Render::modeWireframe:
  396. getMesh().mMode = Mesh::MeshModeWireframe;
  397. break;
  398. case Render::modeSolid:
  399. getMesh().mMode = Mesh::MeshModeSolid;
  400. break;
  401. default:
  402. getMesh().mMode = Mesh::MeshModeTexture;
  403. break;
  404. }
  405. if (alpha)
  406. getMesh().drawAlpha();
  407. else
  408. getMesh().drawSolid();
  409. glPopMatrix();
  410. //getRender().mTexture.bindTextureId(0);
  411. // Draw other room meshes and sprites
  412. if (alpha || (getRender().getMode() == Render::modeWireframe)
  413. || (getRender().getMode() == Render::modeSolid)) {
  414. sortModels();
  415. for (unsigned int i = 0; i < sizeModels(); i++)
  416. getModel(i).display();
  417. for (unsigned int i = 0; i < sizeSprites(); i++)
  418. getSprite(i).display();
  419. }
  420. }
  421. unsigned int Room::getFlags() {
  422. return flags;
  423. }
  424. unsigned int Room::getNumXSectors() {
  425. return numXSectors;
  426. }
  427. unsigned int Room::getNumZSectors() {
  428. return numZSectors;
  429. }
  430. void Room::getPos(vec3_t p) {
  431. for (unsigned int i = 0; i < 3; i++)
  432. p[i] = pos[i];
  433. }
  434. unsigned int Room::sizeAdjacentRooms() {
  435. return adjacentRooms.size();
  436. }
  437. int Room::getAdjacentRoom(unsigned int index) {
  438. assert(index < adjacentRooms.size());
  439. return adjacentRooms.at(index);
  440. }
  441. unsigned int Room::sizePortals() {
  442. return portals.size();
  443. }
  444. Portal &Room::getPortal(unsigned int index) {
  445. assert(index < portals.size());
  446. return *portals.at(index);
  447. }
  448. unsigned int Room::sizeSectors() {
  449. return sectors.size();
  450. }
  451. Sector &Room::getSector(unsigned int index) {
  452. assert(index < sectors.size());
  453. return *sectors.at(index);
  454. }
  455. unsigned int Room::sizeBox() {
  456. return boxes.size();
  457. }
  458. Box &Room::getBox(unsigned int index) {
  459. assert(index < boxes.size());
  460. return *boxes.at(index);
  461. }
  462. unsigned int Room::sizeModels() {
  463. return models.size();
  464. }
  465. StaticModel &Room::getModel(unsigned int index) {
  466. assert(index < models.size());
  467. return *models.at(index);
  468. }
  469. void Room::sortModels() {
  470. std::sort(models.begin(), models.end());
  471. }
  472. unsigned int Room::sizeLights() {
  473. return lights.size();
  474. }
  475. Light &Room::getLight(unsigned int index) {
  476. assert(index < lights.size());
  477. return *lights.at(index);
  478. }
  479. unsigned int Room::sizeSprites() {
  480. return sprites.size();
  481. }
  482. Sprite &Room::getSprite(unsigned int index) {
  483. assert(index < sprites.size());
  484. return *sprites.at(index);
  485. }
  486. BoundingBox &Room::getBoundingBox() {
  487. return bbox;
  488. }
  489. Mesh &Room::getMesh() {
  490. return mesh;
  491. }