Open Source Tomb Raider Engine
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

World.cpp 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. /*!
  2. * \file src/World.cpp
  3. * \brief The game world (model)
  4. *
  5. * \author Mongoose
  6. */
  7. #include <cstdio>
  8. #include <math.h>
  9. #include <assert.h>
  10. #include "World.h"
  11. World::~World() {
  12. destroy();
  13. }
  14. // Temp methods for rendering use until more refactoring is done
  15. model_mesh_t *World::getMesh(int index)
  16. {
  17. return mMeshes[index];
  18. }
  19. void World::addMesh(model_mesh_t *mesh)
  20. {
  21. if (mesh)
  22. mMeshes.push_back(mesh);
  23. }
  24. void World::moveEntity(entity_t *e, char movement)
  25. {
  26. const float moved = 180.0f;
  27. const float testd = 220.0f;
  28. const float camHeight = 8.0f;
  29. float x, y, z, pitch, h, floor, ceiling;
  30. int room, sector;
  31. bool wall;
  32. unsigned int roomFlags;
  33. if (!e)
  34. {
  35. return;
  36. }
  37. switch (e->moveType)
  38. {
  39. case worldMoveType_walkNoSwim:
  40. case worldMoveType_walk:
  41. pitch = 0.0f; // in the future pitch could control jump up blocks here
  42. break;
  43. case worldMoveType_noClipping:
  44. case worldMoveType_fly:
  45. case worldMoveType_swim:
  46. pitch = e->angles[2];
  47. break;
  48. }
  49. switch (movement)
  50. {
  51. case 'f':
  52. x = e->pos[0] + (testd * sinf(e->angles[1]));
  53. y = e->pos[1] + (testd * sinf(pitch));
  54. z = e->pos[2] + (testd * cosf(e->angles[1]));
  55. break;
  56. case 'b':
  57. x = e->pos[0] - (testd * sinf(e->angles[1]));
  58. y = e->pos[1] - (testd * sinf(pitch));
  59. z = e->pos[2] - (testd * cosf(e->angles[1]));
  60. break;
  61. case 'l':
  62. x = e->pos[0] - (testd * sinf(e->angles[1] + 90.0f));
  63. y = e->pos[1];
  64. z = e->pos[2] - (testd * cosf(e->angles[1] + 90.0f));
  65. break;
  66. case 'r':
  67. x = e->pos[0] + (testd * sinf(e->angles[1] + 90.0f));
  68. y = e->pos[1];
  69. z = e->pos[2] + (testd * cosf(e->angles[1] + 90.0f));
  70. break;
  71. default:
  72. return;
  73. }
  74. //room = getRoomByLocation(x, y, z);
  75. room = getRoomByLocation(e->room, x, y, z);
  76. if (room == -1) // Will we hit a portal?
  77. {
  78. room = getAdjoiningRoom(e->room,
  79. e->pos[0], e->pos[1], e->pos[2],
  80. x, y, z);
  81. if (room > -1)
  82. {
  83. printf("Crossing from room %i to %i\n", e->room, room);
  84. } else {
  85. //! \fixme mRooms, sectors, ... are now std::vector, but often upper bound checks are missing
  86. return;
  87. }
  88. }
  89. roomFlags = getRoomInfo(room);
  90. sector = getSector(room, x, z, &floor, &ceiling);
  91. wall = isWall(room, sector);
  92. // If you're underwater you may want to swim =)
  93. // ...if you're worldMoveType_walkNoSwim, you better hope it's shallow
  94. if (roomFlags & RoomFlagUnderWater && e->moveType == worldMoveType_walk)
  95. e->moveType = worldMoveType_swim;
  96. // Don't swim on land
  97. if (!(roomFlags & RoomFlagUnderWater) && e->moveType == worldMoveType_swim)
  98. e->moveType = worldMoveType_walk;
  99. // Mongoose 2002.09.02, Add check for room -> room transition
  100. // ( Only allow by movement between rooms by using portals )
  101. if (((e->moveType == worldMoveType_noClipping) ||
  102. (e->moveType == worldMoveType_fly) ||
  103. (e->moveType == worldMoveType_swim)) ||
  104. ((room > -1) && (!wall)))
  105. {
  106. e->room = room;
  107. switch (movement)
  108. {
  109. case 'f':
  110. x = e->pos[0] + (moved * sinf(e->angles[1]));
  111. y = e->pos[1] + (moved * sinf(pitch));
  112. z = e->pos[2] + (moved * cosf(e->angles[1]));
  113. break;
  114. case 'b':
  115. x = e->pos[0] - (moved * sinf(e->angles[1]));
  116. y = e->pos[1] - (moved * sinf(pitch));
  117. z = e->pos[2] - (moved * cosf(e->angles[1]));
  118. break;
  119. case 'l':
  120. x = e->pos[0] - (moved * sinf(e->angles[1] + 90.0f));
  121. z = e->pos[2] - (moved * cosf(e->angles[1] + 90.0f));
  122. break;
  123. case 'r':
  124. x = e->pos[0] + (moved * sinf(e->angles[1] + 90.0f));
  125. z = e->pos[2] + (moved * cosf(e->angles[1] + 90.0f));
  126. break;
  127. }
  128. /*! \fixme Test for vector (move vector) / plane (portal) collision here
  129. * to see if we need to switch rooms... man...
  130. */
  131. h = y;
  132. getHeightAtPosition(room, x, &h, z);
  133. switch (e->moveType)
  134. {
  135. case worldMoveType_fly:
  136. case worldMoveType_swim:
  137. // Don't fall out of world, avoid a movement that does
  138. if (h > y - camHeight)
  139. {
  140. e->pos[0] = x;
  141. e->pos[1] = y;
  142. e->pos[2] = z;
  143. }
  144. break;
  145. case worldMoveType_walk:
  146. case worldMoveType_walkNoSwim:
  147. y = e->pos[1]; // Override vector movement walking ( er, not pretty )
  148. // Now fake gravity
  149. // Mongoose 2002.08.14, Remember TR is upside down ( you fall 'up' )
  150. //ddist = h - e->pos[1];
  151. // This is to force false gravity, by making camera stay on ground
  152. e->pos[1] = h; //roomFloor->bbox_min[1];
  153. // Check for camera below terrian and correct
  154. if (e->pos[1] < h - camHeight)
  155. {
  156. e->pos[1] = h - camHeight;
  157. }
  158. e->pos[0] = x;
  159. e->pos[2] = z;
  160. break;
  161. case worldMoveType_noClipping:
  162. e->pos[0] = x;
  163. e->pos[1] = y;
  164. e->pos[2] = z;
  165. }
  166. }
  167. else
  168. {
  169. return;
  170. }
  171. e->room = room;
  172. }
  173. void World::addRoom(Room &room) {
  174. mRooms.push_back(&room);
  175. }
  176. unsigned int World::sizeRoom() {
  177. return mRooms.size();
  178. }
  179. Room &World::getRoom(unsigned int index) {
  180. assert(index < mRooms.size());
  181. return *mRooms.at(index);
  182. }
  183. void World::addSprite(SpriteSequence &sprite) {
  184. mSprites.push_back(&sprite);
  185. }
  186. unsigned int World::sizeSprite() {
  187. return mSprites.size();
  188. }
  189. SpriteSequence &World::getSprite(unsigned int index) {
  190. assert(index < mSprites.size());
  191. return *mSprites.at(index);
  192. }
  193. void World::addEntity(Entity &entity) {
  194. //e->moveType = worldMoveType_walk; // Walk
  195. //e->room = getRoomByLocation(e->pos[0], e->pos[1], e->pos[2]);
  196. mEntities.push_back(&entity);
  197. }
  198. unsigned int World::sizeEntity() {
  199. return mEntities.size();
  200. }
  201. Entity &World::getEntity(unsigned int index) {
  202. assert(index < mEntities.size());
  203. return *mEntities.at(index);
  204. }
  205. void World::addSkeletalModel(SkeletalModel &model) {
  206. mModels.push_back(&model);
  207. }
  208. unsigned int World::sizeSkeletalModel() {
  209. return mModels.size();
  210. }
  211. SkeletalModel &World::getSkeletalModel(unsigned int index) {
  212. assert(index < mModels.size());
  213. return *mModels.at(index);
  214. }
  215. int World::getRoomByLocation(int index, float x, float y, float z)
  216. {
  217. assert(index >= 0);
  218. assert(index < (int)mRooms.size());
  219. Room &room = *mRooms.at(index);
  220. if (room.getBoundingBox().inBox(x, y, z))
  221. return index;
  222. else
  223. return getRoomByLocation(x, y, z);
  224. }
  225. int World::getRoomByLocation(float x, float y, float z) {
  226. int hop = -1;
  227. for (unsigned int i = 0; i < mRooms.size(); i++) {
  228. if (mRooms.at(i)->getBoundingBox().inBoxPlane(x, z)) {
  229. if (mRooms.at(i)->getBoundingBox().inBox(x, y, z))
  230. return i;
  231. else
  232. hop = i; // This room is above or below current position
  233. }
  234. }
  235. return hop;
  236. }
  237. int World::getAdjoiningRoom(int index,
  238. float x, float y, float z,
  239. float x2, float y2, float z2) {
  240. assert(index >= 0);
  241. assert(index < (int)mRooms.size());
  242. Room &room = *mRooms.at(index);
  243. vec3_t intersect, p1, p2;
  244. vec3_t vertices[4];
  245. p1[0] = x; p1[1] = y; p1[2] = z;
  246. p2[0] = x2; p2[1] = y2; p2[2] = z2;
  247. for (unsigned int i = 0; i < room.sizePortals(); i++) {
  248. room.getPortal(i).getVertices(vertices);
  249. if (intersectionLinePolygon(intersect, p1, p2, //4,
  250. vertices))
  251. return room.getPortal(i).getAdjoiningRoom();
  252. }
  253. return -1;
  254. }
  255. int World::getSector(int room, float x, float z, float *floor, float *ceiling) {
  256. assert(room >= 0);
  257. assert(room < (int)mRooms.size());
  258. assert(floor != NULL);
  259. assert(ceiling != NULL);
  260. int sector = getSector(room, x, z);
  261. if ((sector >= 0) && (sector < (int)mRooms.at(room)->sizeSectors())) {
  262. *floor = mRooms.at(room)->getSector(sector).getFloor();
  263. *ceiling = mRooms.at(room)->getSector(sector).getCeiling();
  264. }
  265. return sector;
  266. }
  267. int World::getSector(int room, float x, float z) {
  268. assert(room >= 0);
  269. assert(room < (int)mRooms.size());
  270. vec3_t pos;
  271. mRooms.at(room)->getPos(pos);
  272. int sector = (((((int)x - (int)pos[0]) / 1024) *
  273. mRooms.at(room)->getNumZSectors()) + (((int)z - (int)pos[2]) / 1024));
  274. if (sector < 0)
  275. return -1;
  276. return sector;
  277. }
  278. unsigned int World::getRoomInfo(int room) {
  279. assert(room >= 0);
  280. assert(room < (int)mRooms.size());
  281. return mRooms.at(room)->getFlags();
  282. }
  283. bool World::isWall(int room, int sector) {
  284. assert(room >= 0);
  285. assert(room < (int)mRooms.size());
  286. assert(sector >= 0);
  287. assert(sector < (int)mRooms.at(room)->sizeSectors());
  288. //! \fixme is (sector > 0) correct??
  289. return ((sector > 0) && mRooms.at(room)->getSector(sector).isWall());
  290. }
  291. void World::getHeightAtPosition(int index, float x, float *y, float z) {
  292. assert(index >= 0);
  293. assert(index < (int)mRooms.size());
  294. int sector = getSector(index, x, z);
  295. if ((sector >= 0) && (sector < (int)mRooms.at(index)->sizeSectors()))
  296. *y = mRooms.at(index)->getSector(sector).getFloor();
  297. }
  298. void World::destroy() {
  299. for (unsigned int i = 0; i != mRooms.size(); i++)
  300. delete mRooms[i];
  301. mRooms.clear();
  302. for (unsigned int i = 0; i != mSprites.size(); i++)
  303. delete mSprites[i];
  304. mSprites.clear();
  305. for (unsigned int i = 0; i != mEntities.size(); i++)
  306. delete mEntities[i];
  307. mEntities.clear();
  308. for (unsigned int i = 0; i != mModels.size(); i++)
  309. delete mModels[i];
  310. mModels.clear();
  311. for (std::vector<int>::size_type i = 0; i != mMeshes.size(); i++) {
  312. model_mesh_t *mesh = mMeshes[i];
  313. if (!mesh)
  314. continue;
  315. for (std::vector<int>::size_type j = 0; j != mesh->texturedTriangles.size(); j++) {
  316. if (mesh->texturedTriangles[j])
  317. delete mesh->texturedTriangles[j];
  318. }
  319. for (std::vector<int>::size_type j = 0; j != mesh->coloredTriangles.size(); j++) {
  320. if (mesh->coloredTriangles[j])
  321. delete mesh->coloredTriangles[j];
  322. }
  323. for (std::vector<int>::size_type j = 0; j != mesh->texturedRectangles.size(); j++) {
  324. if (mesh->texturedRectangles[j])
  325. delete mesh->texturedRectangles[j];
  326. }
  327. for (std::vector<int>::size_type j = 0; j != mesh->coloredRectangles.size(); j++) {
  328. if (mesh->coloredRectangles[j])
  329. delete mesh->coloredRectangles[j];
  330. }
  331. if (mesh->vertices)
  332. delete [] mesh->vertices;
  333. if (mesh->colors)
  334. delete [] mesh->colors;
  335. if (mesh->normals)
  336. delete [] mesh->normals;
  337. delete mesh;
  338. }
  339. mMeshes.clear();
  340. }