Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Render.cpp 48KB

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