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

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