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

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