Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Render.cpp 45KB

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