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.

World.cpp 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: t; c-basic-offset: 3 -*- */
  2. /*================================================================
  3. *
  4. * Project : OpenRaider
  5. * Author : Terry 'Mongoose' Hendrix II
  6. * Website : http://www.westga.edu/~stu7440/
  7. * Email : stu7440@westga.edu
  8. * Object : World
  9. * License : No use w/o permission (C) 2002 Mongoose
  10. * Comments: The game world ( model )
  11. *
  12. *
  13. * This file was generated using Mongoose's C++
  14. * template generator script. <stu7440@westga.edu>
  15. *
  16. *-- History -------------------------------------------------
  17. *
  18. * 2002.12.16:
  19. * Mongoose - Created
  20. =================================================================*/
  21. #ifdef DEBUG_MEMORY
  22. #include <memory_test.h>
  23. #endif
  24. #include <math.h>
  25. #include <World.h>
  26. ////////////////////////////////////////////////////////////
  27. // Constructors
  28. ////////////////////////////////////////////////////////////
  29. World::World()
  30. {
  31. mClearLock = false;
  32. mFlags = 0;
  33. mEntities.setError(0x0);
  34. mRooms.setError(0x0);
  35. mMeshes.setError(0x0);
  36. mSprites.setError(0x0);
  37. mModels.setError(0x0);
  38. }
  39. World::~World()
  40. {
  41. destroy();
  42. }
  43. ////////////////////////////////////////////////////////////
  44. // Public Accessors
  45. ////////////////////////////////////////////////////////////
  46. int World::getRoomByLocation(int index, float x, float y, float z)
  47. {
  48. room_mesh_t *room = mRooms[index];
  49. if (room)
  50. {
  51. if (x > room->bbox_min[0] && x < room->bbox_max[0] &&
  52. z > room->bbox_min[2] && z < room->bbox_max[2])
  53. {
  54. if (y > room->bbox_min[1] && y < room->bbox_max[1])
  55. return index;
  56. }
  57. }
  58. return getRoomByLocation(x, y, z);
  59. }
  60. int World::getRoomByLocation(float x, float y, float z)
  61. {
  62. room_mesh_t *room;
  63. int hop = -1;
  64. for (mRooms.start(); mRooms.forward(); mRooms.next())
  65. {
  66. room = mRooms.current();
  67. if (!room)
  68. continue;
  69. if (x > room->bbox_min[0] && x < room->bbox_max[0] &&
  70. z > room->bbox_min[2] && z < room->bbox_max[2])
  71. {
  72. // This room contains current position
  73. if (y > room->bbox_min[1] && y < room->bbox_max[1])
  74. return mRooms.getCurrentIndex();
  75. // This room is above or below current position
  76. hop = mRooms.getCurrentIndex();
  77. }
  78. }
  79. // Room is -1? Must be in void, try to hop to room with same X,Z
  80. if (mFlags & fEnableHopping)
  81. return hop;
  82. return -1;
  83. }
  84. int World::getAdjoiningRoom(int index,
  85. float x, float y, float z,
  86. float x2, float y2, float z2)
  87. {
  88. room_mesh_t *room = mRooms[index];
  89. portal_t * portal;
  90. vec3_t intersect, p1, p2;
  91. p1[0] = x; p1[1] = y; p1[2] = z;
  92. p2[0] = x2; p2[1] = y2; p2[2] = z2;
  93. if (room)
  94. {
  95. for (room->portals.start(); room->portals.forward();
  96. room->portals.next())
  97. {
  98. portal = room->portals.current();
  99. if (!portal)
  100. continue;
  101. if (helIntersectionLineAndPolygon(intersect, p1, p2, // 4,
  102. portal->vertices))
  103. {
  104. return portal->adjoining_room;
  105. }
  106. }
  107. }
  108. return -1;
  109. }
  110. int World::getSector(int room, float x, float z, float *floor, float *ceiling)
  111. {
  112. room_mesh_t *r;
  113. sector_t * s;
  114. int sector;
  115. r = mRooms[room];
  116. if (!r)
  117. return -1;
  118. sector = (((((int)x - (int)r->pos[0]) / 1024) * r->numZSectors) +
  119. (((int)z - (int)r->pos[2]) / 1024));
  120. if (sector > -1)
  121. {
  122. s = r->sectors[sector];
  123. if (!s)
  124. return -1;
  125. *floor = s->floor;
  126. *ceiling = s->ceiling;
  127. }
  128. return sector;
  129. }
  130. int World::getSector(int room, float x, float z)
  131. {
  132. int sector;
  133. room_mesh_t *r;
  134. r = mRooms[room];
  135. if (!r)
  136. {
  137. return -1;
  138. }
  139. sector = (((((int)x - (int)r->pos[0]) / 1024) * r->numZSectors) +
  140. (((int)z - (int)r->pos[2]) / 1024));
  141. if (sector < 0)
  142. {
  143. return -1;
  144. }
  145. return sector;
  146. }
  147. unsigned int World::getRoomInfo(int room)
  148. {
  149. room_mesh_t *r;
  150. r = mRooms[room];
  151. if (!r)
  152. {
  153. return 0;
  154. }
  155. return r->flags;
  156. }
  157. bool World::isWall(int room, int sector)
  158. {
  159. room_mesh_t *r;
  160. sector_t *sect;
  161. r = mRooms[room];
  162. if (!r)
  163. {
  164. return true;
  165. }
  166. sect = r->sectors[sector];
  167. if (!sect)
  168. {
  169. return true;
  170. }
  171. return (sector > 0 && sect->wall);
  172. }
  173. bool World::getHeightAtPosition(int index, float x, float *y, float z)
  174. {
  175. room_mesh_t *room = mRooms[index];
  176. #ifdef OBSOLETE_USING_BOXES
  177. unsigned int i;
  178. float zmax, xmax, zmin, xmin;
  179. if (!room)
  180. {
  181. return false;
  182. }
  183. // Mongoose 2002.08.14, It's 0302 - give me a fucking break --
  184. // this works albeit poorly =)
  185. for (i = 0; (int)i < room->num_boxes; ++i)
  186. {
  187. xmax = room->boxes[i].c.pos[0];
  188. xmin = room->boxes[i].a.pos[0];
  189. zmax = room->boxes[i].c.pos[2];
  190. zmin = room->boxes[i].a.pos[2];
  191. if (x < xmax && x > xmin && z < zmax && z > zmin)
  192. {
  193. //printf("%f %f %f %f\n", xmax, xmin, zmax, zmin);
  194. *y = room->boxes[i].a.pos[1]; // hhmm...room->pos[1] +
  195. return true;
  196. }
  197. }
  198. return false;
  199. #else
  200. int sector;
  201. sector_t *sect;
  202. if (!room)
  203. {
  204. return false;
  205. }
  206. // Mongoose 2002.08.14, Remember sector_z is width of sector array
  207. sector = getSector(index, x, z);
  208. sect = room->sectors[sector];
  209. if (!sect)
  210. {
  211. return true;
  212. }
  213. *y = sect->floor;
  214. return true;
  215. #endif
  216. }
  217. // Temp methods for rendering use until more refactoring is done
  218. #ifdef BAD_BLOOD
  219. model_mesh_t *World::getMesh(int index)
  220. {
  221. return mMeshes[index];
  222. }
  223. skeletal_model_t *World::getModel(int index)
  224. {
  225. return mModels[index];
  226. }
  227. room_mesh_t *World::getRoom(int index)
  228. {
  229. return mRooms[index];
  230. }
  231. Vector<entity_t *> *World::getEntities()
  232. {
  233. return &mEntities;
  234. }
  235. Vector<sprite_seq_t *> *World::getSprites()
  236. {
  237. return &mSprites;
  238. }
  239. Vector<room_mesh_t *> *World::getRooms()
  240. {
  241. return &mRooms;
  242. }
  243. #endif
  244. ////////////////////////////////////////////////////////////
  245. // Public Mutators
  246. ////////////////////////////////////////////////////////////
  247. void World::setFlag(WorldFlag flag)
  248. {
  249. mFlags |= flag;
  250. }
  251. void World::clearFlag(WorldFlag flag)
  252. {
  253. mFlags |= flag;
  254. mFlags ^= flag;
  255. }
  256. void World::destroy()
  257. {
  258. // Add some locking to check use state first
  259. if (!mClearLock)
  260. {
  261. clear();
  262. }
  263. }
  264. void World::addRoom(room_mesh_t *room)
  265. {
  266. mClearLock = false;
  267. mRooms.pushBack(room);
  268. }
  269. void World::addMesh(model_mesh_t *mesh)
  270. {
  271. if (mesh)
  272. {
  273. mClearLock = false;
  274. mMeshes.pushBack(mesh);
  275. }
  276. }
  277. void World::addEntity(entity_t *e)
  278. {
  279. if (e)
  280. {
  281. mClearLock = false;
  282. e->master = 0x0;
  283. e->moveType = worldMoveType_walk; // Walk
  284. e->room = getRoomByLocation(e->pos[0], e->pos[1], e->pos[2]);
  285. mEntities.pushBack(e);
  286. }
  287. }
  288. int World::addModel(skeletal_model_t *model)
  289. {
  290. if (model)
  291. {
  292. mClearLock = false;
  293. mModels.pushBack(model);
  294. return mModels.end();
  295. }
  296. return -1;
  297. }
  298. void World::addSprite(sprite_seq_t *sprite)
  299. {
  300. if (sprite)
  301. {
  302. mClearLock = false;
  303. mSprites.pushBack(sprite);
  304. }
  305. }
  306. void World::moveEntity(entity_t *e, char movement)
  307. {
  308. const float moved = 180.0f;
  309. const float testd = 220.0f;
  310. const float camHeight = 8.0f;
  311. float x, y, z, pitch, h, floor, ceiling;
  312. int room, sector;
  313. bool wall;
  314. unsigned int roomFlags;
  315. if (!e)
  316. {
  317. return;
  318. }
  319. switch (e->moveType)
  320. {
  321. case worldMoveType_walkNoSwim:
  322. case worldMoveType_walk:
  323. pitch = 0.0f; // in the future pitch could control jump up blocks here
  324. break;
  325. case worldMoveType_noClipping:
  326. case worldMoveType_fly:
  327. case worldMoveType_swim:
  328. default:
  329. pitch = e->angles[2];
  330. break;
  331. }
  332. switch (movement)
  333. {
  334. case 'f':
  335. x = e->pos[0] + (testd * sinf(e->angles[1]));
  336. y = e->pos[1] + (testd * sinf(pitch));
  337. z = e->pos[2] + (testd * cosf(e->angles[1]));
  338. break;
  339. case 'b':
  340. x = e->pos[0] - (testd * sinf(e->angles[1]));
  341. y = e->pos[1] - (testd * sinf(pitch));
  342. z = e->pos[2] - (testd * cosf(e->angles[1]));
  343. break;
  344. case 'l':
  345. x = e->pos[0] - (testd * sinf(e->angles[1] + 90.0f));
  346. y = e->pos[1];
  347. z = e->pos[2] - (testd * cosf(e->angles[1] + 90.0f));
  348. break;
  349. case 'r':
  350. x = e->pos[0] + (testd * sinf(e->angles[1] + 90.0f));
  351. y = e->pos[1];
  352. z = e->pos[2] + (testd * cosf(e->angles[1] + 90.0f));
  353. break;
  354. default:
  355. return;
  356. }
  357. //room = getRoomByLocation(x, y, z);
  358. room = getRoomByLocation(e->room, x, y, z);
  359. if (room == -1) // Will we hit a portal?
  360. {
  361. #define ADJ_ROOM_CHECK
  362. #ifdef ADJ_ROOM_CHECK
  363. room = getAdjoiningRoom(e->room,
  364. e->pos[0], e->pos[1], e->pos[2],
  365. x, y, z);
  366. #else
  367. if (!mFlags & fEnableHopping)
  368. {
  369. mFlags |= fEnableHopping;
  370. room = getRoomByLocation(e->room, x, y, z);
  371. printf("Hopped\n");
  372. mFlags ^= fEnableHopping;
  373. }
  374. //room = getRoomByLocation(x, y, z);
  375. #endif
  376. if (room > -1)
  377. {
  378. printf("Crossing from room %i to %i\n", e->room, room);
  379. }
  380. }
  381. roomFlags = getRoomInfo(room);
  382. sector = getSector(room, x, z, &floor, &ceiling);
  383. wall = isWall(room, sector);
  384. // If you're underwater you may want to swim =)
  385. // ...if you're worldMoveType_walkNoSwim, you better hope it's shallow
  386. if (roomFlags & roomFlag_underWater && e->moveType == worldMoveType_walk)
  387. {
  388. e->moveType = worldMoveType_swim;
  389. }
  390. // Don't swim on land
  391. if (!(roomFlags & roomFlag_underWater) && e->moveType == worldMoveType_swim)
  392. {
  393. e->moveType = worldMoveType_walk;
  394. }
  395. // Mongoose 2002.09.02, Add check for room -> room transition
  396. // ( Only allow by movement between rooms by using portals )
  397. if (((e->moveType == worldMoveType_noClipping) ||
  398. (e->moveType == worldMoveType_fly) ||
  399. (e->moveType == worldMoveType_swim)) ||
  400. ((room > -1) && (!wall)))
  401. {
  402. e->room = room;
  403. switch (movement)
  404. {
  405. case 'f':
  406. x = e->pos[0] + (moved * sinf(e->angles[1]));
  407. y = e->pos[1] + (moved * sinf(pitch));
  408. z = e->pos[2] + (moved * cosf(e->angles[1]));
  409. break;
  410. case 'b':
  411. x = e->pos[0] - (moved * sinf(e->angles[1]));
  412. y = e->pos[1] - (moved * sinf(pitch));
  413. z = e->pos[2] - (moved * cosf(e->angles[1]));
  414. break;
  415. case 'l':
  416. x = e->pos[0] - (moved * sinf(e->angles[1] + 90.0f));
  417. z = e->pos[2] - (moved * cosf(e->angles[1] + 90.0f));
  418. break;
  419. case 'r':
  420. x = e->pos[0] + (moved * sinf(e->angles[1] + 90.0f));
  421. z = e->pos[2] + (moved * cosf(e->angles[1] + 90.0f));
  422. break;
  423. }
  424. /*! \fixme Test for vector (move vector) / plane (portal) collision here
  425. * to see if we need to switch rooms... man...
  426. */
  427. h = y;
  428. getHeightAtPosition(room, x, &h, z);
  429. switch (e->moveType)
  430. {
  431. case worldMoveType_fly:
  432. case worldMoveType_swim:
  433. #ifdef DIVE_GAP
  434. // Clips to top of water, waiting for DIVE event
  435. if (h < floor)
  436. e->pos[1] = floor;
  437. else if (h > ceiling)
  438. e->pos[1] = ceiling;
  439. else
  440. e->pos[1] = y;
  441. #endif
  442. // Don't fall out of world, avoid a movement that does
  443. if (h > y - camHeight)
  444. {
  445. e->pos[0] = x;
  446. e->pos[1] = y;
  447. e->pos[2] = z;
  448. }
  449. break;
  450. case worldMoveType_walk:
  451. case worldMoveType_walkNoSwim:
  452. y = e->pos[1]; // Override vector movement walking ( er, not pretty )
  453. // Now fake gravity
  454. // Mongoose 2002.08.14, Remember TR is upside down ( you fall 'up' )
  455. //ddist = h - e->pos[1];
  456. // This is to force false gravity, by making camera stay on ground
  457. e->pos[1] = h; //roomFloor->bbox_min[1];
  458. // Check for camera below terrian and correct
  459. if (e->pos[1] < h - camHeight)
  460. {
  461. e->pos[1] = h - camHeight;
  462. }
  463. e->pos[0] = x;
  464. e->pos[2] = z;
  465. break;
  466. case worldMoveType_noClipping:
  467. e->pos[0] = x;
  468. e->pos[1] = y;
  469. e->pos[2] = z;
  470. }
  471. #ifdef OBSOLETE
  472. m_text->SetString(1,"Room %2i Sector %2i %sPos %.0f %.0f %.0f Yaw %.0f",
  473. room, sector,
  474. wall ? " Wall " : " ",
  475. e->pos[0], e->pos[1], e->pos[2], e->angles[1]);
  476. #endif
  477. }
  478. else
  479. {
  480. e->moving = false;
  481. return;
  482. }
  483. e->room = room;
  484. e->moving = true;
  485. }
  486. ////////////////////////////////////////////////////////////
  487. // Private Accessors
  488. ////////////////////////////////////////////////////////////
  489. ////////////////////////////////////////////////////////////
  490. // Private Mutators
  491. ////////////////////////////////////////////////////////////
  492. void World::clear()
  493. {
  494. room_mesh_t *room;
  495. model_mesh_t *mesh;
  496. sprite_seq_t *sprite;
  497. skeletal_model_t *model;
  498. bone_frame_t *boneframe;
  499. bone_tag_t *tag;
  500. animation_frame_t *animation;
  501. List<skeletal_model_t *> cache;
  502. mClearLock = true;
  503. mEntities.erase();
  504. for (mRooms.start(); mRooms.forward(); mRooms.next())
  505. {
  506. room = mRooms.current();
  507. if (room)
  508. {
  509. room->portals.erase();
  510. room->models.erase();
  511. room->sprites.erase();
  512. room->sectors.erase();
  513. room->boxes.erase();
  514. }
  515. }
  516. mRooms.erase();
  517. for (mMeshes.start(); mMeshes.forward(); mMeshes.next())
  518. {
  519. mesh = mMeshes.current();
  520. if (!mesh)
  521. continue;
  522. for (mesh->texturedTriangles.start();
  523. mesh->texturedTriangles.forward();
  524. mesh->texturedTriangles.next())
  525. {
  526. if (mesh->texturedTriangles.current())
  527. delete mesh->texturedTriangles.current();
  528. }
  529. for (mesh->coloredTriangles.start(); mesh->coloredTriangles.forward();
  530. mesh->coloredTriangles.next())
  531. {
  532. if (mesh->coloredTriangles.current())
  533. delete mesh->coloredTriangles.current();
  534. }
  535. for (mesh->texturedRectangles.start();
  536. mesh->texturedRectangles.forward();
  537. mesh->texturedRectangles.next())
  538. {
  539. if (mesh->texturedRectangles.current())
  540. delete mesh->texturedRectangles.current();
  541. }
  542. for (mesh->coloredRectangles.start(); mesh->coloredRectangles.forward();
  543. mesh->coloredRectangles.next())
  544. {
  545. if (mesh->coloredRectangles.current())
  546. delete mesh->coloredRectangles.current();
  547. }
  548. if (mesh->vertices)
  549. delete [] mesh->vertices;
  550. if (mesh->colors)
  551. delete [] mesh->colors;
  552. if (mesh->normals)
  553. delete [] mesh->normals;
  554. delete mesh;
  555. }
  556. mMeshes.clear();
  557. for (mSprites.start(); mSprites.forward(); mSprites.next())
  558. {
  559. sprite = mSprites.current();
  560. if (!sprite)
  561. continue;
  562. if (sprite->sprite)
  563. delete [] sprite->sprite;
  564. delete sprite;
  565. }
  566. mSprites.clear();
  567. for (mModels.start(); mModels.forward(); mModels.next())
  568. {
  569. model = mModels.current();
  570. if (!model)
  571. continue;
  572. // No smart pointers, so skip if deleted once =)
  573. if (!cache.SearchKey(model))
  574. {
  575. cache.Add(model);
  576. }
  577. else
  578. {
  579. continue;
  580. }
  581. for (model->animation.start(); model->animation.forward();
  582. model->animation.next())
  583. {
  584. animation = model->animation.current();
  585. if (!animation)
  586. continue;
  587. for (animation->frame.start(); animation->frame.forward();
  588. animation->frame.next())
  589. {
  590. boneframe = animation->frame.current();
  591. if (!boneframe)
  592. continue;
  593. for (boneframe->tag.start(); boneframe->tag.forward();
  594. boneframe->tag.next())
  595. {
  596. tag = boneframe->tag.current();
  597. if (!tag)
  598. continue;
  599. delete tag;
  600. }
  601. delete boneframe;
  602. }
  603. delete animation;
  604. }
  605. delete model;
  606. }
  607. mModels.clear();
  608. }