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

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