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

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