Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Render.cpp 44KB

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