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 46KB

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