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.

Render.cpp 37KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461
  1. /*!
  2. * \file src/Render.cpp
  3. * \brief OpenRaider Renderer class
  4. *
  5. * \author Mongoose
  6. * \author xythobuz
  7. */
  8. #include <algorithm>
  9. #ifdef __APPLE__
  10. #include <OpenGL/gl.h>
  11. #else
  12. #include <GL/gl.h>
  13. #endif
  14. #include <stdlib.h>
  15. #include <math.h>
  16. #include <string.h>
  17. #include "global.h"
  18. #include "main.h"
  19. #include "Game.h"
  20. #include "OpenRaider.h"
  21. #include "Render.h"
  22. bool compareEntites(const void *voidA, const void *voidB)
  23. {
  24. entity_t *a = (entity_t *)voidA, *b = (entity_t *)voidB;
  25. vec_t distA, distB;
  26. if (!a || !b)
  27. return false; // error really
  28. distA = getRender().mViewVolume.getDistToSphereFromNear(a->pos[0],
  29. a->pos[1],
  30. a->pos[2],
  31. 1.0f);
  32. distB = getRender().mViewVolume.getDistToSphereFromNear(b->pos[0],
  33. b->pos[1],
  34. b->pos[2],
  35. 1.0f);
  36. return (distA < distB);
  37. }
  38. ////////////////////////////////////////////////////////////
  39. // Constructors
  40. ////////////////////////////////////////////////////////////
  41. Render::Render()
  42. {
  43. mSkyMesh = -1;
  44. mSkyMeshRotation = false;
  45. mMode = Render::modeDisabled;
  46. mLock = 0;
  47. mFlags = (fRoomAlpha | fViewModel | fSprites |
  48. fRoomModels | fEntityModels | fRenderPonytail |
  49. fUsePortals | fUpdateRoomListPerFrame);
  50. }
  51. Render::~Render()
  52. {
  53. ClearWorld();
  54. }
  55. ////////////////////////////////////////////////////////////
  56. // Public Accessors
  57. ////////////////////////////////////////////////////////////
  58. void Render::screenShot(char *filenameBase)
  59. {
  60. mTexture.glScreenShot(filenameBase, getWindow().mWidth, getWindow().mHeight);
  61. }
  62. unsigned int Render::getFlags() {
  63. return mFlags;
  64. }
  65. ////////////////////////////////////////////////////////////
  66. // Public Mutators
  67. ////////////////////////////////////////////////////////////
  68. void Render::loadTexture(unsigned char *image,
  69. unsigned int width, unsigned int height,
  70. unsigned int id)
  71. {
  72. glColor3fv(WHITE);
  73. mTexture.loadBufferSlot(image, width, height, Texture::RGBA, 32, id);
  74. }
  75. int Render::initTextures(char *textureDir) {
  76. char filename[128];
  77. unsigned int numTextures = 0;
  78. unsigned char color[4];
  79. mTexture.reset();
  80. mTexture.setMaxTextureCount(128); /* TR never needs more than 32 iirc
  81. However, color texturegen is a lot */
  82. mTexture.setFlag(Texture::fUseMipmaps);
  83. color[0] = 0xff;
  84. color[1] = 0xff;
  85. color[2] = 0xff;
  86. color[3] = 0xff;
  87. if (mTexture.loadColorTexture(color, 32, 32) > -1)
  88. numTextures++;
  89. //! \fixme Error Checking. Return negative error code, check in calling place too
  90. snprintf(filename, 126, "%s/%s", textureDir, "splash.tga");
  91. filename[127] = 0;
  92. if (mTexture.loadTGA(filename) > -1)
  93. numTextures++;
  94. return numTextures;
  95. }
  96. void Render::ClearWorld() {
  97. mRoomRenderList.clear();
  98. for (unsigned int i = 0; i < mModels.size(); i++) {
  99. if (mModels[i])
  100. delete mModels[i];
  101. }
  102. mModels.clear();
  103. }
  104. // Texture must be set to WHITE solid color texture
  105. void renderTrace(int color, vec3_t start, vec3_t end)
  106. {
  107. const float widthStart = 10.0f; //5.0f;
  108. const float widthEnd = 10.0f;
  109. float delta = randomNum(0.01f, 0.16f); // for flicker fx
  110. // Draw two long quads that skrink and fade the they go further out
  111. glBegin(GL_QUADS);
  112. switch (color)
  113. {
  114. case 0:
  115. glColor3f(0.9f - delta, 0.2f, 0.2f);
  116. break;
  117. case 1:
  118. glColor3f(0.2f, 0.9f - delta, 0.2f);
  119. break;
  120. case 2:
  121. default:
  122. glColor3f(0.2f, 0.2f, 0.9f - delta);
  123. }
  124. glVertex3f(start[0], start[1], start[2]);
  125. glVertex3f(start[0], start[1] + widthStart, start[2] + widthStart);
  126. glVertex3f(end[0], end[1] + widthEnd, end[2] + widthEnd);
  127. glVertex3f(end[0], end[1], end[2]);
  128. glVertex3f(start[0], start[1], start[2]);
  129. glVertex3f(start[0], start[1] + widthStart, start[2] - widthStart);
  130. glVertex3f(end[0], end[1] + widthEnd, end[2] - widthEnd);
  131. glVertex3f(end[0], end[1], end[2]);
  132. glVertex3f(start[0], start[1] + widthStart, start[2] + widthStart);
  133. glVertex3f(start[0], start[1] + widthStart, start[2] - widthStart);
  134. glVertex3f(end[0], end[1] + widthEnd, end[2] - widthEnd);
  135. glVertex3f(end[0], end[1] + widthEnd, end[2] + widthEnd);
  136. glEnd();
  137. }
  138. void setLighting(bool on)
  139. {
  140. if (on)
  141. {
  142. glEnable(GL_LIGHTING);
  143. glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
  144. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, WHITE);
  145. glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, WHITE);
  146. glLightModelfv(GL_LIGHT_MODEL_AMBIENT, DIM_WHITE);
  147. }
  148. else
  149. {
  150. glDisable(GL_LIGHTING);
  151. }
  152. }
  153. void lightRoom(Room &room)
  154. {
  155. for (unsigned int i = 0; i < room.sizeLights(); ++i)
  156. {
  157. Light &light = room.getLight(i);
  158. vec4_t pos, color;
  159. vec3_t dir;
  160. light.getPos(pos);
  161. light.getColor(color);
  162. light.getDir(dir);
  163. glEnable(GL_LIGHT0 + i);
  164. switch (light.getType())
  165. {
  166. case Light::typeSpot:
  167. glLightf(GL_LIGHT0 + i, GL_SPOT_CUTOFF, light.getCutoff());
  168. glLightfv(GL_LIGHT0 + i, GL_POSITION, pos);
  169. glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, dir);
  170. glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, color);
  171. break;
  172. case Light::typePoint:
  173. case Light::typeDirectional:
  174. glLightf(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, 1.0); // 1.0
  175. // GL_QUADRATIC_ATTENUATION
  176. // GL_LINEAR_ATTENUATION
  177. glLightf(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, light.getAtt());
  178. glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, color); // GL_DIFFUSE
  179. glLightfv(GL_LIGHT0 + i, GL_POSITION, pos);
  180. break;
  181. }
  182. }
  183. }
  184. void Render::clearFlags(unsigned int flags)
  185. {
  186. // _defaults |= flags; // Force removal if it wasn't set
  187. mFlags ^= flags;
  188. if (flags & Render::fFog)
  189. {
  190. if (glIsEnabled(GL_FOG))
  191. {
  192. glDisable(GL_FOG);
  193. }
  194. }
  195. if (flags & Render::fGL_Lights)
  196. {
  197. setLighting(false);
  198. }
  199. }
  200. void Render::setFlags(unsigned int flags)
  201. {
  202. mFlags |= flags;
  203. if (flags & Render::fFog)
  204. {
  205. glEnable(GL_FOG);
  206. glFogf(GL_FOG_MODE, GL_EXP2);
  207. glFogf(GL_FOG_DENSITY, 0.00008f);
  208. glFogf(GL_FOG_START, 30000.0f);
  209. glFogf(GL_FOG_END, 50000.0f);
  210. glFogfv(GL_FOG_COLOR, BLACK);
  211. }
  212. if (flags & Render::fGL_Lights)
  213. {
  214. setLighting(true);
  215. }
  216. }
  217. int Render::getMode()
  218. {
  219. return mMode;
  220. }
  221. void Render::setMode(int n)
  222. {
  223. mMode = n;
  224. switch (mMode)
  225. {
  226. case Render::modeDisabled:
  227. break;
  228. case Render::modeSolid:
  229. case Render::modeWireframe:
  230. glClearColor(NEXT_PURPLE[0], NEXT_PURPLE[1],
  231. NEXT_PURPLE[2], NEXT_PURPLE[3]);
  232. glDisable(GL_TEXTURE_2D);
  233. break;
  234. default:
  235. if (mMode == Render::modeLoadScreen)
  236. {
  237. glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  238. }
  239. else
  240. {
  241. glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  242. }
  243. glClearColor(BLACK[0], BLACK[1], BLACK[2], BLACK[3]);
  244. glEnable(GL_TEXTURE_2D);
  245. }
  246. }
  247. // Replaced the deprecated gluLookAt with slightly modified code from here:
  248. // http://www.khronos.org/message_boards/showthread.php/4991
  249. void gluLookAt(float eyeX, float eyeY, float eyeZ,
  250. float lookAtX, float lookAtY, float lookAtZ,
  251. float upX, float upY, float upZ) {
  252. float f[3];
  253. // calculating the viewing vector
  254. f[0] = lookAtX - eyeX;
  255. f[1] = lookAtY - eyeY;
  256. f[2] = lookAtZ - eyeZ;
  257. float fMag, upMag;
  258. fMag = sqrtf(f[0] * f[0] + f[1] * f[1] + f[2] * f[2]);
  259. upMag = sqrtf(upX * upX + upY * upY + upZ * upZ);
  260. // normalizing the viewing vector
  261. f[0] = f[0] / fMag;
  262. f[1] = f[1] / fMag;
  263. f[2] = f[2] / fMag;
  264. float s[3] = {
  265. f[1] * upZ - upY * f[2],
  266. upX * f[2] - f[0] * upZ,
  267. f[0] * upY - upX * f[1]
  268. };
  269. float u[3] = {
  270. s[1] * f[2] - f[1] * s[2],
  271. f[0] * s[2] - s[0] * f[2],
  272. s[0] * f[1] - f[0] * s[1]
  273. };
  274. float m[16] = {
  275. s[0], u[0], -f[0], 0,
  276. s[1], u[1], -f[1], 0,
  277. s[2], u[2], -f[2], 0,
  278. 0, 0, 0, 1
  279. };
  280. glMultMatrixf(m);
  281. glTranslatef(-eyeX, -eyeY, -eyeZ);
  282. }
  283. void Render::display()
  284. {
  285. vec3_t curPos;
  286. vec3_t camPos;
  287. vec3_t atPos;
  288. int index;
  289. switch (mMode)
  290. {
  291. case Render::modeDisabled:
  292. return;
  293. case Render::modeLoadScreen:
  294. //! \fixme entry for seperate main drawing method -- Mongoose 2002.01.01
  295. drawLoadScreen();
  296. return;
  297. default:
  298. ;
  299. }
  300. if (mMode == Render::modeWireframe)
  301. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  302. else
  303. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  304. index = -1;
  305. if (getGame().mLara)
  306. {
  307. float yaw;
  308. int sector;
  309. float camOffsetH = 0.0f;
  310. switch (getGame().mLara->moveType)
  311. {
  312. case worldMoveType_fly:
  313. case worldMoveType_noClipping:
  314. case worldMoveType_swim:
  315. camOffsetH = 64.0f;
  316. break;
  317. case worldMoveType_walk:
  318. case worldMoveType_walkNoSwim:
  319. camOffsetH = 512.0f;
  320. break;
  321. }
  322. curPos[0] = getGame().mLara->pos[0];
  323. curPos[1] = getGame().mLara->pos[1];
  324. curPos[2] = getGame().mLara->pos[2];
  325. yaw = getGame().mLara->angles[1];
  326. index = getGame().mLara->room;
  327. // Mongoose 2002.08.24, New 3rd person camera hack
  328. camPos[0] = curPos[0];
  329. camPos[1] = curPos[1] - camOffsetH; // UP is lower val
  330. camPos[2] = curPos[2];
  331. camPos[0] -= (1024.0f * sinf(yaw));
  332. camPos[2] -= (1024.0f * cosf(yaw));
  333. sector = getWorld().getSector(index, camPos[0], camPos[2]);
  334. // Handle camera out of world
  335. if (sector < 0 || getWorld().isWall(index, sector))
  336. {
  337. camPos[0] = curPos[0] + (64.0f * sinf(yaw));
  338. camPos[1] -= 64.0f;
  339. camPos[2] = curPos[2] + (64.0f * cosf(yaw));
  340. }
  341. getCamera().setPosition(camPos);
  342. }
  343. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  344. glLoadIdentity();
  345. // Setup view in OpenGL with camera
  346. getCamera().update();
  347. getCamera().getPosition(camPos);
  348. getCamera().getTarget(atPos);
  349. // Mongoose 2002.08.13, Quick fix to render OpenRaider upside down
  350. gluLookAt(camPos[0], camPos[1], camPos[2], atPos[0], atPos[1], atPos[2], 0.0f, -1.0f, 0.0f);
  351. // Update view volume for vising
  352. updateViewVolume();
  353. // Let's see the LoS -- should be event controled
  354. if (getGame().mLara)
  355. {
  356. // SkeletalModel *mdl = getGame().mLara->tmpHook;
  357. // Draw in solid colors
  358. glDisable(GL_TEXTURE_2D);
  359. glDisable(GL_CULL_FACE);
  360. if (getGame().mLara->state == 64) // eWeaponFire
  361. {
  362. vec3_t u, v; //, s, t;
  363. // Center of getGame().mLara
  364. u[0] = curPos[0];
  365. u[1] = curPos[1] - 512.0f;
  366. u[2] = curPos[2];
  367. // Location getGame().mLara is aiming at? ( Not finished yet )
  368. v[0] = u[0] + (9000.0f * sinf(getGame().mLara->angles[1]));
  369. v[1] = u[1] + (9000.0f * sinf(getGame().mLara->angles[2]));
  370. v[2] = u[2] + (9000.0f * cosf(getGame().mLara->angles[1]));
  371. // Test tracing of aim
  372. renderTrace(0, u, v); // v = target
  373. }
  374. entity_t *route = getGame().mLara->master;
  375. while (route)
  376. {
  377. if (route->master)
  378. {
  379. renderTrace(1, route->pos, route->master->pos);
  380. }
  381. route = route->master;
  382. }
  383. glEnable(GL_CULL_FACE);
  384. glEnable(GL_TEXTURE_2D);
  385. }
  386. // Render world
  387. glColor3fv(DIM_WHITE); // was WHITE
  388. drawSkyMesh(96.0);
  389. // Figure out how much of the map to render
  390. newRoomRenderList(index);
  391. // Room solid pass, need to do depth sorting to avoid 2 pass render
  392. for (unsigned int i = 0; i < mRoomRenderList.size(); i++)
  393. {
  394. Room &room = *mRoomRenderList[i];
  395. if (mFlags & Render::fGL_Lights)
  396. {
  397. lightRoom(room);
  398. }
  399. drawRoom(room, false);
  400. }
  401. // Draw all visible enities
  402. if (mFlags & Render::fEntityModels)
  403. {
  404. entity_t *e;
  405. std::vector<entity_t *> entityRenderList;
  406. std::vector<entity_t *> *entities = getWorld().getEntities();
  407. for (unsigned int i = 0; i < entities->size(); i++)
  408. {
  409. e = entities->at(i);
  410. // Mongoose 2002.03.26, Don't show lara to it's own player
  411. if (!e || e == getGame().mLara)
  412. {
  413. continue;
  414. }
  415. // Mongoose 2002.08.15, Nothing to draw, skip
  416. // Mongoose 2002.12.24, Some entities have no animation =p
  417. if (e->tmpHook)
  418. if (e->tmpHook->model->animation.empty())
  419. continue;
  420. // Is it in view volume? ( Hack to use sphere )
  421. if (!isVisible(e->pos[0], e->pos[1], e->pos[2], 512.0f))
  422. continue;
  423. //! \fixme Is it in a room we're rendering?
  424. //if (mRoomRenderList[e->room] == 0x0)
  425. //{
  426. // continue;
  427. //}
  428. entityRenderList.push_back(e);
  429. }
  430. // Draw objects not tied to rooms
  431. glPushMatrix();
  432. drawObjects();
  433. glPopMatrix();
  434. // Depth sort entityRenderList with qsort
  435. std::sort(entityRenderList.begin(), entityRenderList.end(), compareEntites);
  436. for (unsigned int i = 0; i < entityRenderList.size(); i++)
  437. {
  438. e = entityRenderList[i];
  439. glPushMatrix();
  440. glTranslatef(e->pos[0], e->pos[1], e->pos[2]);
  441. glRotatef(e->angles[1], 0, 1, 0);
  442. drawModel(e->tmpHook);
  443. glPopMatrix();
  444. }
  445. }
  446. // Room alpha pass
  447. // Skip room alpha pass for modes w/o texture
  448. if (!(mMode == Render::modeSolid || mMode == Render::modeWireframe))
  449. {
  450. for (unsigned int i = 0; i < mRoomRenderList.size(); i++)
  451. {
  452. drawRoom(*mRoomRenderList[i], true);
  453. }
  454. }
  455. if (mMode == Render::modeWireframe)
  456. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  457. glFlush();
  458. }
  459. void Render::drawLoadScreen()
  460. {
  461. float x = 0.0f, y = 0.0f, z = -160.0f;
  462. float w, h;
  463. if (getWindow().mWidth < getWindow().mHeight)
  464. w = h = (float)getWindow().mWidth;
  465. else
  466. w = h = (float)getWindow().mHeight;
  467. if (mTexture.getTextureCount() <= 0)
  468. return;
  469. // Mongoose 2002.01.01, Rendered while game is loading...
  470. //! \fixme seperate logo/particle coor later
  471. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  472. glLoadIdentity();
  473. glColor3fv(WHITE);
  474. if (mFlags & Render::fGL_Lights)
  475. glDisable(GL_LIGHTING);
  476. // Mongoose 2002.01.01, Draw logo/load screen
  477. glTranslatef(0.0f, 0.0f, -2000.0f);
  478. glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
  479. mTexture.bindTextureId(1); //! \fixme store texture id somewhere
  480. glBegin(GL_TRIANGLE_STRIP);
  481. glTexCoord2f(1.0, 1.0);
  482. glVertex3f(x + w, y + h, z);
  483. glTexCoord2f(0.0, 1.0);
  484. glVertex3f(x - w, y + h, z);
  485. glTexCoord2f(1.0, 0.0);
  486. glVertex3f(x + w, y - h, z);
  487. glTexCoord2f(0.0, 0.0);
  488. glVertex3f(x - w, y - h, z);
  489. glEnd();
  490. if (mFlags & Render::fGL_Lights)
  491. glEnable(GL_LIGHTING);
  492. glFlush();
  493. }
  494. void Render::newRoomRenderList(int index)
  495. {
  496. static int currentRoomId = -1;
  497. if (mFlags & Render::fUsePortals)
  498. {
  499. if (index == -1) // -1 is error, so draw room 0, for the hell of it
  500. {
  501. mRoomRenderList.clear();
  502. mRoomRenderList.push_back(&getWorld().getRoom(0));
  503. }
  504. else
  505. {
  506. // Update room render list if needed
  507. if (mFlags & Render::fUpdateRoomListPerFrame ||
  508. currentRoomId != index)
  509. {
  510. buildRoomRenderList(getWorld().getRoom(index));
  511. }
  512. }
  513. }
  514. else // Render all rooms pretty much
  515. {
  516. if (currentRoomId != index || index == -1)
  517. {
  518. printf("*** Room render list -> %i\n", index);
  519. mRoomRenderList.clear();
  520. for (unsigned int i = 0; i < getWorld().sizeRoom(); i++)
  521. {
  522. vec3_t bbox[2];
  523. getWorld().getRoom(i).getBoundingBox(bbox);
  524. if (!isVisible(bbox[0], bbox[1]))
  525. continue;
  526. mRoomRenderList.push_back(&getWorld().getRoom(i));
  527. }
  528. }
  529. }
  530. currentRoomId = index;
  531. }
  532. void Render::buildRoomRenderList(Room &room)
  533. {
  534. // Must be visible
  535. //! \fixme Add depth sorting here - remove multipass
  536. vec3_t bbox[2];
  537. room.getBoundingBox(bbox);
  538. if (!isVisible(bbox[0], bbox[1]))
  539. return;
  540. // Must not already be cached
  541. for (unsigned int i = 0; i < mRoomRenderList.size(); i++)
  542. {
  543. Room &room2 = *mRoomRenderList[i];
  544. if (&room2 == &room)
  545. return;
  546. }
  547. /* Add current room to list */
  548. mRoomRenderList.push_back(&room);
  549. if (mFlags & Render::fOneRoom)
  550. {
  551. return;
  552. }
  553. else if (mFlags & Render::fAllRooms) /* Are you serious? */
  554. {
  555. for (unsigned int i = 0; i < getWorld().sizeRoom(); i++)
  556. {
  557. Room &room2 = getWorld().getRoom(i);
  558. if (&room2 != &room)
  559. {
  560. buildRoomRenderList(room2);
  561. }
  562. }
  563. return;
  564. }
  565. // Try to add adj rooms and their adj rooms, skip this room
  566. for (unsigned int i = 1; i < room.sizeAdjacentRooms(); i++)
  567. {
  568. if (room.getAdjacentRoom(i) < 0)
  569. continue;
  570. Room &room2 = getWorld().getRoom(room.getAdjacentRoom(i));
  571. // Mongoose 2002.03.22, Add portal visibility check here
  572. if (&room2 != &room)
  573. {
  574. buildRoomRenderList(room2);
  575. }
  576. }
  577. }
  578. void Render::drawSkyMesh(float scale)
  579. {
  580. skeletal_model_t *model = getWorld().getModel(mSkyMesh);
  581. if (!model)
  582. return;
  583. glDisable(GL_DEPTH_TEST);
  584. glPushMatrix();
  585. if (mSkyMeshRotation)
  586. {
  587. glRotated(90.0, 1, 0, 0);
  588. }
  589. glTranslated(0.0, 1000.0, 0.0);
  590. glScaled(scale, scale, scale);
  591. //drawModel(model);
  592. //drawModelMesh(getWorld().getMesh(mSkyMesh), );
  593. glPopMatrix();
  594. glEnable(GL_DEPTH_TEST);
  595. }
  596. void Render::drawObjects()
  597. {
  598. // Draw lara or other player model ( move to entity rendering method )
  599. if (mFlags & Render::fViewModel && getGame().mLara && getGame().mLara->tmpHook)
  600. {
  601. SkeletalModel *mdl = getGame().mLara->tmpHook;
  602. if (mdl)
  603. {
  604. int frame;
  605. // Mongoose 2002.03.22, Test 'idle' aniamtions
  606. if (!getGame().mLara->moving)
  607. {
  608. frame = mdl->getIdleAnimation();
  609. // Mongoose 2002.08.15, Stop flickering of idle lara here
  610. if (frame == 11)
  611. {
  612. mdl->setFrame(0);
  613. }
  614. }
  615. else
  616. {
  617. frame = mdl->getAnimation();
  618. }
  619. animation_frame_t *animation = mdl->model->animation[frame];
  620. if (animation && mdl->getFrame() > (int)animation->frame.size()-1)
  621. {
  622. mdl->setFrame(0);
  623. }
  624. }
  625. glPushMatrix();
  626. glTranslated(getGame().mLara->pos[0], getGame().mLara->pos[1], getGame().mLara->pos[2]);
  627. glRotated(OR_RAD_TO_DEG(getCamera().getRadianYaw()), 0, 1, 0);
  628. drawModel(getGame().mLara->tmpHook);
  629. glPopMatrix();
  630. }
  631. // Mongoose 2002.03.22, Draw sprites after player to handle alpha
  632. if (mFlags & Render::fSprites) {
  633. for (unsigned int i = 0; i < getWorld().sizeSprite(); i++) {
  634. SpriteSequence &sprite = getWorld().getSprite(i);
  635. for (unsigned int j = 0; j < sprite.size(); j++)
  636. sprite.get(j).display();
  637. }
  638. }
  639. }
  640. void Render::drawModel(SkeletalModel *model)
  641. {
  642. animation_frame_t *animation;
  643. bone_frame_t *boneframe;
  644. bone_frame_t *boneframe2 = 0x0;
  645. bone_tag_t *tag;
  646. bone_tag_t *tag2;
  647. int bframe, aframe;
  648. skeletal_model_t *mdl;
  649. if (!model || !model->model)
  650. return;
  651. mdl = model->model;
  652. aframe = model->getAnimation();
  653. bframe = model->getFrame();
  654. animation = mdl->animation[aframe];
  655. if (!animation)
  656. {
  657. #ifdef DEBUG
  658. printf("ERROR: No animation for model[%i].aframe[%i] %lu\n",
  659. mdl->id, aframe, mdl->animation.size());
  660. #endif
  661. return;
  662. }
  663. if (animation->frame.empty())
  664. {
  665. #ifdef DEBUG
  666. printf("ERROR: No boneframes?!?! *** %i:%i ***\n",
  667. mdl->id, bframe);
  668. #endif
  669. return;
  670. }
  671. boneframe = animation->frame[bframe];
  672. if (!boneframe)
  673. return;
  674. if (boneframe->tag.empty())
  675. {
  676. printf("Empty bone frame?!?!\n");
  677. return;
  678. }
  679. glTranslatef(boneframe->pos[0], boneframe->pos[1], boneframe->pos[2]);
  680. for (unsigned int a = 0; a < boneframe->tag.size(); a++)
  681. {
  682. tag = boneframe->tag[a];
  683. if (!tag)
  684. continue;
  685. if (a == 0)
  686. {
  687. if (!equalEpsilon(tag->rot[1], 0.0f)) // was just if (tag->rot[1])
  688. glRotatef(tag->rot[1], 0, 1, 0);
  689. if (!equalEpsilon(tag->rot[0], 0.0f))
  690. glRotatef(tag->rot[0], 1, 0, 0);
  691. if (!equalEpsilon(tag->rot[2], 0.0f))
  692. glRotatef(tag->rot[2], 0, 0, 1);
  693. }
  694. else
  695. {
  696. if (tag->flag & 0x01)
  697. glPopMatrix();
  698. if (tag->flag & 0x02)
  699. glPushMatrix();
  700. glTranslatef(tag->off[0], tag->off[1], tag->off[2]);
  701. if (!equalEpsilon(tag->rot[1], 0.0f))
  702. glRotatef(tag->rot[1], 0, 1, 0);
  703. if (!equalEpsilon(tag->rot[0], 0.0f))
  704. glRotatef(tag->rot[0], 1, 0, 0);
  705. if (!equalEpsilon(tag->rot[2], 0.0f))
  706. glRotatef(tag->rot[2], 0, 0, 1);
  707. }
  708. // Draw layered lara in TR4 ( 2 meshes per tag )
  709. if (mdl->tr4Overlay == 1)
  710. {
  711. boneframe2 = (mdl->animation[0])->frame[0];
  712. if (boneframe2)
  713. {
  714. tag2 = boneframe2->tag[a];
  715. if (tag2)
  716. {
  717. drawModelMesh(getWorld().getMesh(tag2->mesh), Render::skeletalMesh);
  718. }
  719. }
  720. }
  721. if (mFlags & Render::fRenderPonytail)
  722. {
  723. if (mdl->ponytailId > 0 &&
  724. a == 14)
  725. {
  726. glPushMatrix();
  727. // Mongoose 2002.08.30, TEST to align offset
  728. glTranslatef(mdl->ponytail[0], mdl->ponytail[1], mdl->ponytail[2]);
  729. glRotatef(mdl->ponytailAngle, 1, 0, 0);
  730. // HACK: To fill TR4 void between ponytail/head
  731. // since no vertex welds are implemented yet
  732. if (mdl->tr4Overlay == 1)
  733. {
  734. glScalef(1.20f, 1.20f, 1.20f);
  735. }
  736. #ifdef EXPERIMENTAL_NON_ITEM_RENDER
  737. drawModel(mModels[mdl->ponytail], 0, 0);
  738. #else
  739. for (unsigned int i = 0; i < mdl->ponytailNumMeshes; ++i)
  740. {
  741. glPushMatrix();
  742. if (i > 0)
  743. {
  744. glRotatef(randomNum(-8.0f, -10.0f), 1, 0, 0);
  745. glRotatef(randomNum(-5.0f, 5.0f), 0, 1, 0);
  746. glRotatef(randomNum(-5.0f, 5.0f), 0, 0, 1);
  747. glTranslatef(0.0, 0.0, mdl->ponyOff);
  748. }
  749. if (mdl->pigtails)
  750. {
  751. glPushMatrix();
  752. glTranslatef(mdl->ponyOff2, 0.0, 0.0);
  753. drawModelMesh(getWorld().getMesh(mdl->ponytailMeshId + i),
  754. Render::skeletalMesh);
  755. glPopMatrix();
  756. glPushMatrix();
  757. glTranslatef(-mdl->ponyOff2, 0.0, 0.0);
  758. drawModelMesh(getWorld().getMesh(mdl->ponytailMeshId + i),
  759. Render::skeletalMesh);
  760. glPopMatrix();
  761. }
  762. else
  763. {
  764. drawModelMesh(getWorld().getMesh(mdl->ponytailMeshId + i),
  765. Render::skeletalMesh);
  766. }
  767. }
  768. for (unsigned int i = 0; i < mdl->ponytailNumMeshes; ++i)
  769. {
  770. glPopMatrix();
  771. }
  772. #endif
  773. glPopMatrix();
  774. }
  775. }
  776. drawModelMesh(getWorld().getMesh(tag->mesh), Render::skeletalMesh);
  777. }
  778. // Cycle frames ( cheap hack from old ent state based system )
  779. if (mFlags & fAnimateAllModels)
  780. {
  781. if (model->getFrame() + 1 > (int)animation->frame.size()-1)
  782. {
  783. model->setFrame(0);
  784. }
  785. else
  786. {
  787. model->setFrame(model->getFrame()+1);
  788. }
  789. }
  790. }
  791. void draw_bbox(vec3_t min, vec3_t max, bool draw_points,
  792. const vec4_t c1, const vec4_t c2)
  793. {
  794. // Bind before entering now
  795. //glBindTexture(GL_TEXTURE_2D, 1);
  796. glPointSize(4.0);
  797. //glLineWidth(1.25);
  798. //! \fixme Need to make custom color key for this
  799. glColor3fv(c1);
  800. glBegin(GL_POINTS);
  801. glVertex3f(max[0], max[1], max[2]);
  802. glVertex3f(min[0], min[1], min[2]);
  803. if (draw_points)
  804. {
  805. glVertex3f(max[0], min[1], max[2]);
  806. glVertex3f(min[0], max[1], max[2]);
  807. glVertex3f(max[0], max[1], min[2]);
  808. glVertex3f(min[0], min[1], max[2]);
  809. glVertex3f(min[0], max[1], min[2]);
  810. glVertex3f(max[0], min[1], min[2]);
  811. }
  812. glEnd();
  813. glColor3fv(c2);
  814. glBegin(GL_LINES);
  815. // max, top quad
  816. glVertex3f(max[0], max[1], max[2]);
  817. glVertex3f(max[0], min[1], max[2]);
  818. glVertex3f(max[0], max[1], max[2]);
  819. glVertex3f(min[0], max[1], max[2]);
  820. glVertex3f(max[0], max[1], max[2]);
  821. glVertex3f(max[0], max[1], min[2]);
  822. // max-min, vertical quads
  823. glVertex3f(min[0], max[1], max[2]);
  824. glVertex3f(min[0], max[1], min[2]);
  825. glVertex3f(max[0], min[1], max[2]);
  826. glVertex3f(max[0], min[1], min[2]);
  827. glVertex3f(max[0], min[1], max[2]);
  828. glVertex3f(min[0], min[1], max[2]);
  829. // min-max, vertical quads
  830. glVertex3f(max[0], max[1], min[2]);
  831. glVertex3f(max[0], min[1], min[2]);
  832. glVertex3f(max[0], max[1], min[2]);
  833. glVertex3f(min[0], max[1], min[2]);
  834. glVertex3f(min[0], max[1], max[2]);
  835. glVertex3f(min[0], min[1], max[2]);
  836. // min, bottom quad
  837. glVertex3f(min[0], min[1], min[2]);
  838. glVertex3f(min[0], max[1], min[2]);
  839. glVertex3f(min[0], min[1], min[2]);
  840. glVertex3f(max[0], min[1], min[2]);
  841. glVertex3f(min[0], min[1], min[2]);
  842. glVertex3f(min[0], min[1], max[2]);
  843. glEnd();
  844. glPointSize(1.0);
  845. //glLineWidth(1.0);
  846. }
  847. void Render::drawRoom(Room &room, bool draw_alpha)
  848. {
  849. if (!(mFlags & Render::fRoomAlpha) && draw_alpha)
  850. return;
  851. glPushMatrix();
  852. //LightingSetup();
  853. mTexture.bindTextureId(0); // WHITE texture
  854. if (!draw_alpha &&
  855. (mFlags & Render::fPortals || mMode == Render::modeWireframe)) {
  856. glLineWidth(2.0);
  857. glColor3fv(RED);
  858. for (unsigned int i = 0; i < room.sizePortals(); i++) {
  859. Portal &portal = room.getPortal(i);
  860. vec3_t vertices[4];
  861. portal.getVertices(vertices);
  862. glBegin(GL_LINE_LOOP);
  863. glVertex3fv(vertices[0]);
  864. glVertex3fv(vertices[1]);
  865. glVertex3fv(vertices[2]);
  866. glVertex3fv(vertices[3]);
  867. glEnd();
  868. }
  869. glLineWidth(1.0);
  870. }
  871. if (mMode == Render::modeWireframe && !draw_alpha) {
  872. vec3_t bbox[2];
  873. room.getBoundingBox(bbox);
  874. draw_bbox(bbox[0], bbox[1], true, RED, GREEN);
  875. }
  876. vec3_t pos;
  877. room.getPos(pos);
  878. glTranslated(pos[0], pos[1], pos[2]);
  879. // Reset since GL_MODULATE used, reset to WHITE
  880. glColor3fv(WHITE);
  881. switch (mMode)
  882. {
  883. case modeWireframe:
  884. room.getMesh().mMode = Mesh::MeshModeWireframe;
  885. break;
  886. case modeSolid:
  887. room.getMesh().mMode = Mesh::MeshModeSolid;
  888. break;
  889. default:
  890. room.getMesh().mMode = Mesh::MeshModeTexture;
  891. break;
  892. }
  893. if (draw_alpha)
  894. room.getMesh().drawAlpha();
  895. else
  896. room.getMesh().drawSolid();
  897. glPopMatrix();
  898. //mTexture.bindTextureId(0);
  899. // Draw other room meshes and sprites
  900. if (draw_alpha || mMode == modeWireframe || mMode == modeSolid) {
  901. if (mFlags & Render::fRoomModels) {
  902. room.sortModels();
  903. for (unsigned int i = 0; i < room.sizeModels(); i++) {
  904. room.getModel(i).display();
  905. }
  906. }
  907. // Draw other room alpha polygon objects
  908. if (mFlags & Render::fSprites) {
  909. for (unsigned int i = 0; i < room.sizeSprites(); i++) {
  910. room.getSprite(i).display();
  911. }
  912. }
  913. }
  914. }
  915. void Render::tmpRenderModelMesh(model_mesh_t *r_mesh, texture_tri_t *ttri)
  916. {
  917. glBegin(GL_TRIANGLES);
  918. switch (mMode)
  919. {
  920. case modeSolid:
  921. case modeVertexLight:
  922. if (r_mesh->colors)
  923. {
  924. glColor3fv(r_mesh->colors+ttri->index[0]);
  925. glTexCoord2fv(ttri->st);
  926. glVertex3fv(r_mesh->vertices+ttri->index[0]*3);
  927. glColor3fv(r_mesh->colors+ttri->index[1]);
  928. glTexCoord2fv(ttri->st+2);
  929. glVertex3fv(r_mesh->vertices+ttri->index[1]*3);
  930. glColor3fv(r_mesh->colors+ttri->index[2]);
  931. glTexCoord2fv(ttri->st+4);
  932. glVertex3fv(r_mesh->vertices+ttri->index[2]*3);
  933. }
  934. else if (r_mesh->normals)
  935. {
  936. glNormal3fv(r_mesh->normals+ttri->index[0]*3);
  937. glTexCoord2fv(ttri->st);
  938. glVertex3fv(r_mesh->vertices+ttri->index[0]*3);
  939. glNormal3fv(r_mesh->normals+ttri->index[1]*3);
  940. glTexCoord2fv(ttri->st+2);
  941. glVertex3fv(r_mesh->vertices+ttri->index[1]*3);
  942. glNormal3fv(r_mesh->normals+ttri->index[2]*3);
  943. glTexCoord2fv(ttri->st+4);
  944. glVertex3fv(r_mesh->vertices+ttri->index[2]*3);
  945. }
  946. else
  947. {
  948. glTexCoord2fv(ttri->st);
  949. glVertex3fv(r_mesh->vertices+ttri->index[0]*3);
  950. glTexCoord2fv(ttri->st+2);
  951. glVertex3fv(r_mesh->vertices+ttri->index[1]*3);
  952. glTexCoord2fv(ttri->st+4);
  953. glVertex3fv(r_mesh->vertices+ttri->index[2]*3);
  954. }
  955. break;
  956. case modeWireframe:
  957. glVertex3fv(r_mesh->vertices+ttri->index[0]*3);
  958. glVertex3fv(r_mesh->vertices+ttri->index[1]*3);
  959. glVertex3fv(r_mesh->vertices+ttri->index[2]*3);
  960. break;
  961. default:
  962. glTexCoord2fv(ttri->st);
  963. glVertex3fv(r_mesh->vertices+ttri->index[0]*3);
  964. glTexCoord2fv(ttri->st+2);
  965. glVertex3fv(r_mesh->vertices+ttri->index[1]*3);
  966. glTexCoord2fv(ttri->st+4);
  967. glVertex3fv(r_mesh->vertices+ttri->index[2]*3);
  968. }
  969. glEnd();
  970. }
  971. void Render::drawModelMesh(model_mesh_t *r_mesh, RenderMeshType type)
  972. {
  973. texture_tri_t *ttri;
  974. int lastTexture = -1;
  975. // If they pass NULL structs let it hang up - this is tmp
  976. //! \fixme Duh, vis tests need to be put back
  977. //if (!isVisible(r_mesh->center, r_mesh->radius, r_mesh->bbox))
  978. //{
  979. // return;
  980. //}
  981. #ifdef USE_GL_ARRAYS
  982. // Setup Arrays ( move these to another method depends on mMode )
  983. glEnableClientState(GL_VERTEX_ARRAY);
  984. glVertexPointer(3, GL_FLOAT, 0, r_mesh->vertices);
  985. if (r_mesh->normals)
  986. {
  987. glEnableClientState(GL_NORMAL_ARRAY);
  988. glNormalPointer(3, GL_FLOAT, 0, r_mesh->normals);
  989. }
  990. if (r_mesh->colors)
  991. {
  992. glEnableClientState(GL_COLOR_ARRAY);
  993. glColorPointer(4, GL_FLOAT, 0, r_mesh->colors);
  994. }
  995. //glTexCoordPointer(2, GL_FLOAT, 0, ttri->st);
  996. //glDrawArrays(GL_TRIANGLES, i * 3, 3 * j);
  997. glBegin(GL_TRIANGLES);
  998. for (unsigned int i = 0; i < r_mesh->texturedTriangles.size(); i++)
  999. {
  1000. ttri = r_mesh->texturedTriangles[i];
  1001. if (!ttri)
  1002. continue;
  1003. for (k = 0; k < 4; ++k)
  1004. {
  1005. index = mQuads[i].quads[j*4+k];
  1006. glTexCoord2fv(mQuads[i].texcoors[j*4+k]);
  1007. glArrayElement(mVertices[index]);
  1008. }
  1009. }
  1010. glEnd();
  1011. #endif
  1012. //! \fixme 'AMBIENT' -- Mongoose 2002.01.08
  1013. glColor3fv(WHITE);
  1014. if (mMode == modeWireframe)
  1015. {
  1016. switch (type)
  1017. {
  1018. case roomMesh:
  1019. glColor3fv(YELLOW);
  1020. break;
  1021. case skeletalMesh:
  1022. glColor3fv(WHITE);
  1023. break;
  1024. }
  1025. }
  1026. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  1027. glBindTexture(GL_TEXTURE_2D, 1); // White texture for colors
  1028. // Colored Triagles
  1029. for (unsigned int i = 0; i < r_mesh->coloredTriangles.size(); i++)
  1030. {
  1031. ttri = r_mesh->coloredTriangles[i];
  1032. if (!ttri)
  1033. continue;
  1034. if (mMode != modeWireframe && mMode != modeSolid &&
  1035. ttri->texture != lastTexture)
  1036. {
  1037. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  1038. glBindTexture(GL_TEXTURE_2D, ttri->texture+1);
  1039. lastTexture = ttri->texture;
  1040. }
  1041. tmpRenderModelMesh(r_mesh, ttri);
  1042. }
  1043. // Colored Rectagles
  1044. for (unsigned int i = 0; i < r_mesh->coloredRectangles.size(); i++)
  1045. {
  1046. ttri = r_mesh->coloredRectangles[i];
  1047. if (!ttri)
  1048. continue;
  1049. if (mMode != modeWireframe && mMode != modeSolid &&
  1050. ttri->texture != lastTexture)
  1051. {
  1052. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  1053. glBindTexture(GL_TEXTURE_2D, ttri->texture+1);
  1054. lastTexture = ttri->texture;
  1055. }
  1056. tmpRenderModelMesh(r_mesh, ttri);
  1057. }
  1058. // Textured Tris
  1059. for (unsigned int i = 0; i < r_mesh->texturedTriangles.size(); i++)
  1060. {
  1061. ttri = r_mesh->texturedTriangles[i];
  1062. if (!ttri)
  1063. continue;
  1064. if (mMode != modeWireframe && mMode != modeSolid &&
  1065. ttri->texture != lastTexture)
  1066. {
  1067. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  1068. glBindTexture(GL_TEXTURE_2D, ttri->texture+1);
  1069. lastTexture = ttri->texture;
  1070. }
  1071. tmpRenderModelMesh(r_mesh, ttri);
  1072. }
  1073. // Textured Quads
  1074. for (unsigned int i = 0; i < r_mesh->texturedRectangles.size(); i++)
  1075. {
  1076. ttri = r_mesh->texturedRectangles[i];
  1077. if (!ttri)
  1078. continue;
  1079. if (mMode != modeWireframe && mMode != modeSolid &&
  1080. ttri->texture != lastTexture)
  1081. {
  1082. glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
  1083. glBindTexture(GL_TEXTURE_2D, ttri->texture+1);
  1084. lastTexture = ttri->texture;
  1085. }
  1086. tmpRenderModelMesh(r_mesh, ttri);
  1087. }
  1088. }
  1089. void Render::setSkyMesh(int index, bool rot)
  1090. {
  1091. mSkyMesh = index;
  1092. mSkyMeshRotation = rot;
  1093. }
  1094. void Render::ViewModel(entity_t *ent, int index)
  1095. {
  1096. skeletal_model_t *model;
  1097. if (!ent)
  1098. {
  1099. return;
  1100. }
  1101. model = getWorld().getModel(index);
  1102. if (model)
  1103. {
  1104. ent->modelId = index;
  1105. printf("Viewmodel skeletal model %i\n", model->id);
  1106. }
  1107. }
  1108. void Render::addSkeletalModel(SkeletalModel *mdl)
  1109. {
  1110. mModels.push_back(mdl);
  1111. }
  1112. void Render::updateViewVolume()
  1113. {
  1114. matrix_t proj;
  1115. matrix_t mdl;
  1116. glGetFloatv(GL_PROJECTION_MATRIX, proj);
  1117. glGetFloatv(GL_MODELVIEW_MATRIX, mdl);
  1118. mViewVolume.updateFrame(proj, mdl);
  1119. }
  1120. bool Render::isVisible(float bbox_min[3], float bbox_max[3])
  1121. {
  1122. // For debugging purposes
  1123. if (mMode == Render::modeWireframe)
  1124. {
  1125. //glPointSize(5.0);
  1126. //glColor3fv(PINK);
  1127. //glBegin(GL_POINTS);
  1128. //glVertex3fv(bbox_min);
  1129. //glVertex3fv(bbox_max);
  1130. //glEnd();
  1131. draw_bbox(bbox_min, bbox_max, true, PINK, RED);
  1132. }
  1133. return mViewVolume.isBboxInFrustum(bbox_min, bbox_max);
  1134. }
  1135. bool Render::isVisible(float x, float y, float z)
  1136. {
  1137. // For debugging purposes
  1138. if (mMode == Render::modeWireframe)
  1139. {
  1140. glPointSize(5.0);
  1141. glColor3fv(PINK);
  1142. glBegin(GL_POINTS);
  1143. glVertex3f(x, y, z);
  1144. glEnd();
  1145. }
  1146. return (mViewVolume.isPointInFrustum(x, y, z));
  1147. }
  1148. bool Render::isVisible(float x, float y, float z, float radius)
  1149. {
  1150. // For debugging purposes
  1151. if (mMode == Render::modeWireframe)
  1152. {
  1153. glPointSize(5.0);
  1154. glColor3fv(PINK);
  1155. glBegin(GL_POINTS);
  1156. glVertex3f(x, y, z);
  1157. glEnd();
  1158. }
  1159. return (mViewVolume.isSphereInFrustum(x, y, z, radius));
  1160. }