|
|
1.1 ! root 1: /* ! 2: Copyright (C) 1996-1997 Id Software, Inc. ! 3: ! 4: This program is free software; you can redistribute it and/or ! 5: modify it under the terms of the GNU General Public License ! 6: as published by the Free Software Foundation; either version 2 ! 7: of the License, or (at your option) any later version. ! 8: ! 9: This program is distributed in the hope that it will be useful, ! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ! 12: ! 13: See the GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with this program; if not, write to the Free Software ! 17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ! 18: ! 19: */ ! 20: // r_main.c ! 21: ! 22: #include "quakedef.h" ! 23: ! 24: entity_t r_worldentity; ! 25: ! 26: qboolean r_cache_thrash; // compatability ! 27: ! 28: vec3_t modelorg, r_entorigin; ! 29: entity_t *currententity; ! 30: ! 31: int r_visframecount; // bumped when going to a new PVS ! 32: int r_framecount; // used for dlight push checking ! 33: ! 34: mplane_t frustum[4]; ! 35: ! 36: int c_brush_polys, c_alias_polys; ! 37: ! 38: qboolean envmap; // true during envmap command capture ! 39: ! 40: int currenttexture = -1; // to avoid unnecessary texture sets ! 41: ! 42: int cnttextures[2] = {-1, -1}; // cached ! 43: ! 44: int particletexture; // little dot for particles ! 45: int playertextures; // up to 16 color translated skins ! 46: ! 47: int mirrortexturenum; // quake texturenum, not gltexturenum ! 48: qboolean mirror; ! 49: mplane_t *mirror_plane; ! 50: ! 51: // ! 52: // view origin ! 53: // ! 54: vec3_t vup; ! 55: vec3_t vpn; ! 56: vec3_t vright; ! 57: vec3_t r_origin; ! 58: ! 59: float r_world_matrix[16]; ! 60: float r_base_world_matrix[16]; ! 61: ! 62: // ! 63: // screen size info ! 64: // ! 65: refdef_t r_refdef; ! 66: ! 67: mleaf_t *r_viewleaf, *r_oldviewleaf; ! 68: ! 69: texture_t *r_notexture_mip; ! 70: ! 71: int d_lightstylevalue[256]; // 8.8 fraction of base light value ! 72: ! 73: ! 74: void R_MarkLeaves (void); ! 75: ! 76: cvar_t r_norefresh = {"r_norefresh","0"}; ! 77: cvar_t r_drawentities = {"r_drawentities","1"}; ! 78: cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; ! 79: cvar_t r_speeds = {"r_speeds","0"}; ! 80: cvar_t r_fullbright = {"r_fullbright","0"}; ! 81: cvar_t r_lightmap = {"r_lightmap","0"}; ! 82: cvar_t r_shadows = {"r_shadows","0"}; ! 83: cvar_t r_mirroralpha = {"r_mirroralpha","1"}; ! 84: cvar_t r_wateralpha = {"r_wateralpha","1"}; ! 85: cvar_t r_dynamic = {"r_dynamic","1"}; ! 86: cvar_t r_novis = {"r_novis","0"}; ! 87: cvar_t r_netgraph = {"r_netgraph","0"}; ! 88: ! 89: cvar_t gl_clear = {"gl_clear","0"}; ! 90: cvar_t gl_cull = {"gl_cull","1"}; ! 91: cvar_t gl_texsort = {"gl_texsort","1"}; ! 92: cvar_t gl_smoothmodels = {"gl_smoothmodels","1"}; ! 93: cvar_t gl_affinemodels = {"gl_affinemodels","0"}; ! 94: cvar_t gl_polyblend = {"gl_polyblend","1"}; ! 95: cvar_t gl_flashblend = {"gl_flashblend","1"}; ! 96: cvar_t gl_playermip = {"gl_playermip","0"}; ! 97: cvar_t gl_nocolors = {"gl_nocolors","0"}; ! 98: cvar_t gl_keeptjunctions = {"gl_keeptjunctions","1"}; ! 99: cvar_t gl_reporttjunctions = {"gl_reporttjunctions","0"}; ! 100: cvar_t gl_finish = {"gl_finish","0"}; ! 101: ! 102: extern cvar_t gl_ztrick; ! 103: extern cvar_t scr_fov; ! 104: /* ! 105: ================= ! 106: R_CullBox ! 107: ! 108: Returns true if the box is completely outside the frustom ! 109: ================= ! 110: */ ! 111: qboolean R_CullBox (vec3_t mins, vec3_t maxs) ! 112: { ! 113: int i; ! 114: ! 115: for (i=0 ; i<4 ; i++) ! 116: if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2) ! 117: return true; ! 118: return false; ! 119: } ! 120: ! 121: ! 122: void R_RotateForEntity (entity_t *e) ! 123: { ! 124: glTranslatef (e->origin[0], e->origin[1], e->origin[2]); ! 125: ! 126: glRotatef (e->angles[1], 0, 0, 1); ! 127: glRotatef (-e->angles[0], 0, 1, 0); ! 128: //ZOID: fixed z angle ! 129: glRotatef (e->angles[2], 1, 0, 0); ! 130: } ! 131: ! 132: /* ! 133: ============================================================= ! 134: ! 135: SPRITE MODELS ! 136: ! 137: ============================================================= ! 138: */ ! 139: ! 140: /* ! 141: ================ ! 142: R_GetSpriteFrame ! 143: ================ ! 144: */ ! 145: mspriteframe_t *R_GetSpriteFrame (entity_t *currententity) ! 146: { ! 147: msprite_t *psprite; ! 148: mspritegroup_t *pspritegroup; ! 149: mspriteframe_t *pspriteframe; ! 150: int i, numframes, frame; ! 151: float *pintervals, fullinterval, targettime, time; ! 152: ! 153: psprite = currententity->model->cache.data; ! 154: frame = currententity->frame; ! 155: ! 156: if ((frame >= psprite->numframes) || (frame < 0)) ! 157: { ! 158: Con_Printf ("R_DrawSprite: no such frame %d\n", frame); ! 159: frame = 0; ! 160: } ! 161: ! 162: if (psprite->frames[frame].type == SPR_SINGLE) ! 163: { ! 164: pspriteframe = psprite->frames[frame].frameptr; ! 165: } ! 166: else ! 167: { ! 168: pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; ! 169: pintervals = pspritegroup->intervals; ! 170: numframes = pspritegroup->numframes; ! 171: fullinterval = pintervals[numframes-1]; ! 172: ! 173: time = cl.time + currententity->syncbase; ! 174: ! 175: // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values ! 176: // are positive, so we don't have to worry about division by 0 ! 177: targettime = time - ((int)(time / fullinterval)) * fullinterval; ! 178: ! 179: for (i=0 ; i<(numframes-1) ; i++) ! 180: { ! 181: if (pintervals[i] > targettime) ! 182: break; ! 183: } ! 184: ! 185: pspriteframe = pspritegroup->frames[i]; ! 186: } ! 187: ! 188: return pspriteframe; ! 189: } ! 190: ! 191: ! 192: /* ! 193: ================= ! 194: R_DrawSpriteModel ! 195: ! 196: ================= ! 197: */ ! 198: void R_DrawSpriteModel (entity_t *e) ! 199: { ! 200: vec3_t point; ! 201: mspriteframe_t *frame; ! 202: float *up, *right; ! 203: vec3_t v_forward, v_right, v_up; ! 204: msprite_t *psprite; ! 205: ! 206: // don't even bother culling, because it's just a single ! 207: // polygon without a surface cache ! 208: frame = R_GetSpriteFrame (e); ! 209: psprite = currententity->model->cache.data; ! 210: ! 211: if (psprite->type == SPR_ORIENTED) ! 212: { // bullet marks on walls ! 213: AngleVectors (currententity->angles, v_forward, v_right, v_up); ! 214: up = v_up; ! 215: right = v_right; ! 216: } ! 217: else ! 218: { // normal sprite ! 219: up = vup; ! 220: right = vright; ! 221: } ! 222: ! 223: glColor3f (1,1,1); ! 224: ! 225: GL_DisableMultitexture(); ! 226: ! 227: GL_Bind(frame->gl_texturenum); ! 228: ! 229: glEnable (GL_ALPHA_TEST); ! 230: glBegin (GL_QUADS); ! 231: ! 232: glEnable (GL_ALPHA_TEST); ! 233: glBegin (GL_QUADS); ! 234: ! 235: glTexCoord2f (0, 1); ! 236: VectorMA (e->origin, frame->down, up, point); ! 237: VectorMA (point, frame->left, right, point); ! 238: glVertex3fv (point); ! 239: ! 240: glTexCoord2f (0, 0); ! 241: VectorMA (e->origin, frame->up, up, point); ! 242: VectorMA (point, frame->left, right, point); ! 243: glVertex3fv (point); ! 244: ! 245: glTexCoord2f (1, 0); ! 246: VectorMA (e->origin, frame->up, up, point); ! 247: VectorMA (point, frame->right, right, point); ! 248: glVertex3fv (point); ! 249: ! 250: glTexCoord2f (1, 1); ! 251: VectorMA (e->origin, frame->down, up, point); ! 252: VectorMA (point, frame->right, right, point); ! 253: glVertex3fv (point); ! 254: ! 255: glEnd (); ! 256: ! 257: glDisable (GL_ALPHA_TEST); ! 258: } ! 259: ! 260: /* ! 261: ============================================================= ! 262: ! 263: ALIAS MODELS ! 264: ! 265: ============================================================= ! 266: */ ! 267: ! 268: ! 269: #define NUMVERTEXNORMALS 162 ! 270: ! 271: float r_avertexnormals[NUMVERTEXNORMALS][3] = { ! 272: #include "anorms.h" ! 273: }; ! 274: ! 275: vec3_t shadevector; ! 276: float shadelight, ambientlight; ! 277: ! 278: // precalculated dot products for quantized angles ! 279: #define SHADEDOT_QUANT 16 ! 280: float r_avertexnormal_dots[SHADEDOT_QUANT][256] = ! 281: #include "anorm_dots.h" ! 282: ; ! 283: ! 284: float *shadedots = r_avertexnormal_dots[0]; ! 285: ! 286: int lastposenum; ! 287: ! 288: /* ! 289: ============= ! 290: GL_DrawAliasFrame ! 291: ============= ! 292: */ ! 293: void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum) ! 294: { ! 295: float l; ! 296: trivertx_t *verts; ! 297: int *order; ! 298: int count; ! 299: ! 300: lastposenum = posenum; ! 301: ! 302: verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); ! 303: verts += posenum * paliashdr->poseverts; ! 304: order = (int *)((byte *)paliashdr + paliashdr->commands); ! 305: ! 306: while (1) ! 307: { ! 308: // get the vertex count and primitive type ! 309: count = *order++; ! 310: if (!count) ! 311: break; // done ! 312: if (count < 0) ! 313: { ! 314: count = -count; ! 315: glBegin (GL_TRIANGLE_FAN); ! 316: } ! 317: else ! 318: glBegin (GL_TRIANGLE_STRIP); ! 319: ! 320: do ! 321: { ! 322: // texture coordinates come from the draw list ! 323: glTexCoord2f (((float *)order)[0], ((float *)order)[1]); ! 324: order += 2; ! 325: ! 326: // normals and vertexes come from the frame list ! 327: l = shadedots[verts->lightnormalindex] * shadelight; ! 328: glColor3f (l, l, l); ! 329: glVertex3f (verts->v[0], verts->v[1], verts->v[2]); ! 330: verts++; ! 331: } while (--count); ! 332: ! 333: glEnd (); ! 334: } ! 335: } ! 336: ! 337: ! 338: /* ! 339: ============= ! 340: GL_DrawAliasShadow ! 341: ============= ! 342: */ ! 343: extern vec3_t lightspot; ! 344: ! 345: void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum) ! 346: { ! 347: trivertx_t *verts; ! 348: int *order; ! 349: vec3_t point; ! 350: float height, lheight; ! 351: int count; ! 352: ! 353: lheight = currententity->origin[2] - lightspot[2]; ! 354: ! 355: height = 0; ! 356: verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); ! 357: verts += posenum * paliashdr->poseverts; ! 358: order = (int *)((byte *)paliashdr + paliashdr->commands); ! 359: ! 360: height = -lheight + 1.0; ! 361: ! 362: while (1) ! 363: { ! 364: // get the vertex count and primitive type ! 365: count = *order++; ! 366: if (!count) ! 367: break; // done ! 368: if (count < 0) ! 369: { ! 370: count = -count; ! 371: glBegin (GL_TRIANGLE_FAN); ! 372: } ! 373: else ! 374: glBegin (GL_TRIANGLE_STRIP); ! 375: ! 376: do ! 377: { ! 378: // texture coordinates come from the draw list ! 379: // (skipped for shadows) glTexCoord2fv ((float *)order); ! 380: order += 2; ! 381: ! 382: // normals and vertexes come from the frame list ! 383: point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0]; ! 384: point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1]; ! 385: point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]; ! 386: ! 387: point[0] -= shadevector[0]*(point[2]+lheight); ! 388: point[1] -= shadevector[1]*(point[2]+lheight); ! 389: point[2] = height; ! 390: // height -= 0.001; ! 391: glVertex3fv (point); ! 392: ! 393: verts++; ! 394: } while (--count); ! 395: ! 396: glEnd (); ! 397: } ! 398: } ! 399: ! 400: ! 401: ! 402: /* ! 403: ================= ! 404: R_SetupAliasFrame ! 405: ! 406: ================= ! 407: */ ! 408: void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr) ! 409: { ! 410: int pose, numposes; ! 411: float interval; ! 412: ! 413: if ((frame >= paliashdr->numframes) || (frame < 0)) ! 414: { ! 415: Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); ! 416: frame = 0; ! 417: } ! 418: ! 419: pose = paliashdr->frames[frame].firstpose; ! 420: numposes = paliashdr->frames[frame].numposes; ! 421: ! 422: if (numposes > 1) ! 423: { ! 424: interval = paliashdr->frames[frame].interval; ! 425: pose += (int)(cl.time / interval) % numposes; ! 426: } ! 427: ! 428: GL_DrawAliasFrame (paliashdr, pose); ! 429: } ! 430: ! 431: ! 432: ! 433: /* ! 434: ================= ! 435: R_DrawAliasModel ! 436: ! 437: ================= ! 438: */ ! 439: void R_DrawAliasModel (entity_t *e) ! 440: { ! 441: int i; ! 442: int lnum; ! 443: vec3_t dist; ! 444: float add; ! 445: model_t *clmodel; ! 446: vec3_t mins, maxs; ! 447: aliashdr_t *paliashdr; ! 448: float an; ! 449: int anim; ! 450: ! 451: clmodel = currententity->model; ! 452: ! 453: VectorAdd (currententity->origin, clmodel->mins, mins); ! 454: VectorAdd (currententity->origin, clmodel->maxs, maxs); ! 455: ! 456: if (R_CullBox (mins, maxs)) ! 457: return; ! 458: ! 459: ! 460: VectorCopy (currententity->origin, r_entorigin); ! 461: VectorSubtract (r_origin, r_entorigin, modelorg); ! 462: ! 463: // ! 464: // get lighting information ! 465: // ! 466: ! 467: ambientlight = shadelight = R_LightPoint (currententity->origin); ! 468: ! 469: // allways give the gun some light ! 470: if (e == &cl.viewent && ambientlight < 24) ! 471: ambientlight = shadelight = 24; ! 472: ! 473: for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++) ! 474: { ! 475: if (cl_dlights[lnum].die >= cl.time) ! 476: { ! 477: VectorSubtract (currententity->origin, ! 478: cl_dlights[lnum].origin, ! 479: dist); ! 480: add = cl_dlights[lnum].radius - Length(dist); ! 481: ! 482: if (add > 0) { ! 483: ambientlight += add; ! 484: //ZOID models should be affected by dlights as well ! 485: shadelight += add; ! 486: } ! 487: } ! 488: } ! 489: ! 490: // clamp lighting so it doesn't overbright as much ! 491: if (ambientlight > 128) ! 492: ambientlight = 128; ! 493: if (ambientlight + shadelight > 192) ! 494: shadelight = 192 - ambientlight; ! 495: ! 496: // ZOID: never allow players to go totally black ! 497: if (!strcmp(clmodel->name, "progs/player.mdl")) { ! 498: if (ambientlight < 8) ! 499: ambientlight = shadelight = 8; ! 500: ! 501: } else if (!strcmp (clmodel->name, "progs/flame2.mdl") ! 502: || !strcmp (clmodel->name, "progs/flame.mdl") ) ! 503: // HACK HACK HACK -- no fullbright colors, so make torches full light ! 504: ambientlight = shadelight = 256; ! 505: ! 506: shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; ! 507: shadelight = shadelight / 200.0; ! 508: ! 509: an = e->angles[1]/180*M_PI; ! 510: shadevector[0] = cos(-an); ! 511: shadevector[1] = sin(-an); ! 512: shadevector[2] = 1; ! 513: VectorNormalize (shadevector); ! 514: ! 515: // ! 516: // locate the proper data ! 517: // ! 518: paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); ! 519: ! 520: c_alias_polys += paliashdr->numtris; ! 521: ! 522: // ! 523: // draw all the triangles ! 524: // ! 525: ! 526: GL_DisableMultitexture(); ! 527: ! 528: glPushMatrix (); ! 529: R_RotateForEntity (e); ! 530: ! 531: if (!strcmp (clmodel->name, "progs/eyes.mdl") ) { ! 532: glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8)); ! 533: // double size of eyes, since they are really hard to see in gl ! 534: glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2); ! 535: } else { ! 536: glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); ! 537: glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); ! 538: } ! 539: ! 540: anim = (int)(cl.time*10) & 3; ! 541: GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]); ! 542: ! 543: // we can't dynamically colormap textures, so they are cached ! 544: // seperately for the players. Heads are just uncolored. ! 545: if (currententity->scoreboard && !gl_nocolors.value) ! 546: { ! 547: i = currententity->scoreboard - cl.players; ! 548: if (!currententity->scoreboard->skin) { ! 549: Skin_Find(currententity->scoreboard); ! 550: R_TranslatePlayerSkin(i); ! 551: } ! 552: if (i >= 0 && i<MAX_CLIENTS) ! 553: GL_Bind(playertextures + i); ! 554: } ! 555: ! 556: if (gl_smoothmodels.value) ! 557: glShadeModel (GL_SMOOTH); ! 558: glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); ! 559: ! 560: if (gl_affinemodels.value) ! 561: glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); ! 562: ! 563: R_SetupAliasFrame (currententity->frame, paliashdr); ! 564: ! 565: glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); ! 566: ! 567: glShadeModel (GL_FLAT); ! 568: if (gl_affinemodels.value) ! 569: glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); ! 570: ! 571: glPopMatrix (); ! 572: ! 573: if (r_shadows.value) ! 574: { ! 575: glPushMatrix (); ! 576: R_RotateForEntity (e); ! 577: glDisable (GL_TEXTURE_2D); ! 578: glEnable (GL_BLEND); ! 579: glColor4f (0,0,0,0.5); ! 580: GL_DrawAliasShadow (paliashdr, lastposenum); ! 581: glEnable (GL_TEXTURE_2D); ! 582: glDisable (GL_BLEND); ! 583: glColor4f (1,1,1,1); ! 584: glPopMatrix (); ! 585: } ! 586: ! 587: } ! 588: ! 589: //================================================================================== ! 590: ! 591: /* ! 592: ============= ! 593: R_DrawEntitiesOnList ! 594: ============= ! 595: */ ! 596: void R_DrawEntitiesOnList (void) ! 597: { ! 598: int i; ! 599: ! 600: if (!r_drawentities.value) ! 601: return; ! 602: ! 603: // draw sprites seperately, because of alpha blending ! 604: for (i=0 ; i<cl_numvisedicts ; i++) ! 605: { ! 606: currententity = &cl_visedicts[i]; ! 607: ! 608: switch (currententity->model->type) ! 609: { ! 610: case mod_alias: ! 611: R_DrawAliasModel (currententity); ! 612: break; ! 613: ! 614: case mod_brush: ! 615: R_DrawBrushModel (currententity); ! 616: break; ! 617: ! 618: default: ! 619: break; ! 620: } ! 621: } ! 622: ! 623: for (i=0 ; i<cl_numvisedicts ; i++) ! 624: { ! 625: currententity = &cl_visedicts[i]; ! 626: ! 627: switch (currententity->model->type) ! 628: { ! 629: case mod_sprite: ! 630: R_DrawSpriteModel (currententity); ! 631: break; ! 632: ! 633: default : ! 634: break; ! 635: } ! 636: } ! 637: } ! 638: ! 639: /* ! 640: ============= ! 641: R_DrawViewModel ! 642: ============= ! 643: */ ! 644: void R_DrawViewModel (void) ! 645: { ! 646: float ambient[4], diffuse[4]; ! 647: int j; ! 648: int lnum; ! 649: vec3_t dist; ! 650: float add; ! 651: dlight_t *dl; ! 652: int ambientlight, shadelight; ! 653: ! 654: if (!r_drawviewmodel.value || !Cam_DrawViewModel()) ! 655: return; ! 656: ! 657: if (envmap) ! 658: return; ! 659: ! 660: if (!r_drawentities.value) ! 661: return; ! 662: ! 663: if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) ! 664: return; ! 665: ! 666: if (cl.stats[STAT_HEALTH] <= 0) ! 667: return; ! 668: ! 669: currententity = &cl.viewent; ! 670: if (!currententity->model) ! 671: return; ! 672: ! 673: j = R_LightPoint (currententity->origin); ! 674: ! 675: if (j < 24) ! 676: j = 24; // allways give some light on gun ! 677: ambientlight = j; ! 678: shadelight = j; ! 679: ! 680: // add dynamic lights ! 681: for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++) ! 682: { ! 683: dl = &cl_dlights[lnum]; ! 684: if (!dl->radius) ! 685: continue; ! 686: if (!dl->radius) ! 687: continue; ! 688: if (dl->die < cl.time) ! 689: continue; ! 690: ! 691: VectorSubtract (currententity->origin, dl->origin, dist); ! 692: add = dl->radius - Length(dist); ! 693: if (add > 0) ! 694: ambientlight += add; ! 695: } ! 696: ! 697: ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128; ! 698: diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128; ! 699: ! 700: // hack the depth range to prevent view model from poking into walls ! 701: glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); ! 702: R_DrawAliasModel (currententity); ! 703: glDepthRange (gldepthmin, gldepthmax); ! 704: } ! 705: ! 706: ! 707: /* ! 708: ============ ! 709: R_PolyBlend ! 710: ============ ! 711: */ ! 712: void R_PolyBlend (void) ! 713: { ! 714: if (!gl_polyblend.value) ! 715: return; ! 716: if (!v_blend[3]) ! 717: return; ! 718: ! 719: //Con_Printf("R_PolyBlend(): %4.2f %4.2f %4.2f %4.2f\n",v_blend[0], v_blend[1], v_blend[2], v_blend[3]); ! 720: ! 721: GL_DisableMultitexture(); ! 722: ! 723: glDisable (GL_ALPHA_TEST); ! 724: glEnable (GL_BLEND); ! 725: glDisable (GL_DEPTH_TEST); ! 726: glDisable (GL_TEXTURE_2D); ! 727: ! 728: glLoadIdentity (); ! 729: ! 730: glRotatef (-90, 1, 0, 0); // put Z going up ! 731: glRotatef (90, 0, 0, 1); // put Z going up ! 732: ! 733: glColor4fv (v_blend); ! 734: ! 735: glBegin (GL_QUADS); ! 736: ! 737: glVertex3f (10, 100, 100); ! 738: glVertex3f (10, -100, 100); ! 739: glVertex3f (10, -100, -100); ! 740: glVertex3f (10, 100, -100); ! 741: glEnd (); ! 742: ! 743: glDisable (GL_BLEND); ! 744: glEnable (GL_TEXTURE_2D); ! 745: glEnable (GL_ALPHA_TEST); ! 746: } ! 747: ! 748: ! 749: int SignbitsForPlane (mplane_t *out) ! 750: { ! 751: int bits, j; ! 752: ! 753: // for fast box on planeside test ! 754: ! 755: bits = 0; ! 756: for (j=0 ; j<3 ; j++) ! 757: { ! 758: if (out->normal[j] < 0) ! 759: bits |= 1<<j; ! 760: } ! 761: return bits; ! 762: } ! 763: ! 764: ! 765: void R_SetFrustum (void) ! 766: { ! 767: int i; ! 768: ! 769: if (r_refdef.fov_x == 90) ! 770: { ! 771: // front side is visible ! 772: ! 773: VectorAdd (vpn, vright, frustum[0].normal); ! 774: VectorSubtract (vpn, vright, frustum[1].normal); ! 775: ! 776: VectorAdd (vpn, vup, frustum[2].normal); ! 777: VectorSubtract (vpn, vup, frustum[3].normal); ! 778: } ! 779: else ! 780: { ! 781: ! 782: // rotate VPN right by FOV_X/2 degrees ! 783: RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) ); ! 784: // rotate VPN left by FOV_X/2 degrees ! 785: RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 ); ! 786: // rotate VPN up by FOV_X/2 degrees ! 787: RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 ); ! 788: // rotate VPN down by FOV_X/2 degrees ! 789: RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) ); ! 790: } ! 791: ! 792: for (i=0 ; i<4 ; i++) ! 793: { ! 794: frustum[i].type = PLANE_ANYZ; ! 795: frustum[i].dist = DotProduct (r_origin, frustum[i].normal); ! 796: frustum[i].signbits = SignbitsForPlane (&frustum[i]); ! 797: } ! 798: } ! 799: ! 800: ! 801: ! 802: /* ! 803: =============== ! 804: R_SetupFrame ! 805: =============== ! 806: */ ! 807: void R_SetupFrame (void) ! 808: { ! 809: // don't allow cheats in multiplayer ! 810: r_fullbright.value = 0; ! 811: r_lightmap.value = 0; ! 812: if (!atoi(Info_ValueForKey(cl.serverinfo, "watervis"))) ! 813: r_wateralpha.value = 1; ! 814: ! 815: R_AnimateLight (); ! 816: ! 817: r_framecount++; ! 818: ! 819: // build the transformation matrix for the given view angles ! 820: VectorCopy (r_refdef.vieworg, r_origin); ! 821: ! 822: AngleVectors (r_refdef.viewangles, vpn, vright, vup); ! 823: ! 824: // current viewleaf ! 825: r_oldviewleaf = r_viewleaf; ! 826: r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); ! 827: ! 828: V_SetContentsColor (r_viewleaf->contents); ! 829: V_CalcBlend (); ! 830: ! 831: r_cache_thrash = false; ! 832: ! 833: c_brush_polys = 0; ! 834: c_alias_polys = 0; ! 835: ! 836: } ! 837: ! 838: ! 839: void MYgluPerspective( GLdouble fovy, GLdouble aspect, ! 840: GLdouble zNear, GLdouble zFar ) ! 841: { ! 842: GLdouble xmin, xmax, ymin, ymax; ! 843: ! 844: ymax = zNear * tan( fovy * M_PI / 360.0 ); ! 845: ymin = -ymax; ! 846: ! 847: xmin = ymin * aspect; ! 848: xmax = ymax * aspect; ! 849: ! 850: glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); ! 851: } ! 852: ! 853: ! 854: /* ! 855: ============= ! 856: R_SetupGL ! 857: ============= ! 858: */ ! 859: void R_SetupGL (void) ! 860: { ! 861: float screenaspect; ! 862: extern int glwidth, glheight; ! 863: int x, x2, y2, y, w, h; ! 864: ! 865: // ! 866: // set up viewpoint ! 867: // ! 868: glMatrixMode(GL_PROJECTION); ! 869: glLoadIdentity (); ! 870: x = r_refdef.vrect.x * glwidth/vid.width; ! 871: x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width; ! 872: y = (vid.height-r_refdef.vrect.y) * glheight/vid.height; ! 873: y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height; ! 874: ! 875: // fudge around because of frac screen scale ! 876: if (x > 0) ! 877: x--; ! 878: if (x2 < glwidth) ! 879: x2++; ! 880: if (y2 < 0) ! 881: y2--; ! 882: if (y < glheight) ! 883: y++; ! 884: ! 885: w = x2 - x; ! 886: h = y - y2; ! 887: ! 888: if (envmap) ! 889: { ! 890: x = y2 = 0; ! 891: w = h = 256; ! 892: } ! 893: ! 894: glViewport (glx + x, gly + y2, w, h); ! 895: screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; ! 896: // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; ! 897: // yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect; ! 898: // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI; ! 899: // MYgluPerspective (yfov, screenaspect, 4, 4096); ! 900: MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096); ! 901: ! 902: if (mirror) ! 903: { ! 904: if (mirror_plane->normal[2]) ! 905: glScalef (1, -1, 1); ! 906: else ! 907: glScalef (-1, 1, 1); ! 908: glCullFace(GL_BACK); ! 909: } ! 910: else ! 911: glCullFace(GL_FRONT); ! 912: ! 913: glMatrixMode(GL_MODELVIEW); ! 914: glLoadIdentity (); ! 915: ! 916: glRotatef (-90, 1, 0, 0); // put Z going up ! 917: glRotatef (90, 0, 0, 1); // put Z going up ! 918: glRotatef (-r_refdef.viewangles[2], 1, 0, 0); ! 919: glRotatef (-r_refdef.viewangles[0], 0, 1, 0); ! 920: glRotatef (-r_refdef.viewangles[1], 0, 0, 1); ! 921: glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); ! 922: ! 923: glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); ! 924: ! 925: // ! 926: // set drawing parms ! 927: // ! 928: if (gl_cull.value) ! 929: glEnable(GL_CULL_FACE); ! 930: else ! 931: glDisable(GL_CULL_FACE); ! 932: ! 933: glDisable(GL_BLEND); ! 934: glDisable(GL_ALPHA_TEST); ! 935: glEnable(GL_DEPTH_TEST); ! 936: } ! 937: ! 938: /* ! 939: ================ ! 940: R_RenderScene ! 941: ! 942: r_refdef must be set before the first call ! 943: ================ ! 944: */ ! 945: void R_RenderScene (void) ! 946: { ! 947: R_SetupFrame (); ! 948: ! 949: R_SetFrustum (); ! 950: ! 951: R_SetupGL (); ! 952: ! 953: R_MarkLeaves (); // done here so we know if we're in water ! 954: ! 955: R_DrawWorld (); // adds static entities to the list ! 956: ! 957: S_ExtraUpdate (); // don't let sound get messed up if going slow ! 958: ! 959: R_DrawEntitiesOnList (); ! 960: ! 961: GL_DisableMultitexture(); ! 962: ! 963: R_RenderDlights (); ! 964: ! 965: R_DrawParticles (); ! 966: ! 967: #ifdef GLTEST ! 968: Test_Draw (); ! 969: #endif ! 970: ! 971: } ! 972: ! 973: ! 974: /* ! 975: ============= ! 976: R_Clear ! 977: ============= ! 978: */ ! 979: void R_Clear (void) ! 980: { ! 981: if (r_mirroralpha.value != 1.0) ! 982: { ! 983: if (gl_clear.value) ! 984: glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ! 985: else ! 986: glClear (GL_DEPTH_BUFFER_BIT); ! 987: gldepthmin = 0; ! 988: gldepthmax = 0.5; ! 989: glDepthFunc (GL_LEQUAL); ! 990: } ! 991: else if (gl_ztrick.value) ! 992: { ! 993: static int trickframe; ! 994: ! 995: if (gl_clear.value) ! 996: glClear (GL_COLOR_BUFFER_BIT); ! 997: ! 998: trickframe++; ! 999: if (trickframe & 1) ! 1000: { ! 1001: gldepthmin = 0; ! 1002: gldepthmax = 0.49999; ! 1003: glDepthFunc (GL_LEQUAL); ! 1004: } ! 1005: else ! 1006: { ! 1007: gldepthmin = 1; ! 1008: gldepthmax = 0.5; ! 1009: glDepthFunc (GL_GEQUAL); ! 1010: } ! 1011: } ! 1012: else ! 1013: { ! 1014: if (gl_clear.value) ! 1015: glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ! 1016: else ! 1017: glClear (GL_DEPTH_BUFFER_BIT); ! 1018: gldepthmin = 0; ! 1019: gldepthmax = 1; ! 1020: glDepthFunc (GL_LEQUAL); ! 1021: } ! 1022: ! 1023: glDepthRange (gldepthmin, gldepthmax); ! 1024: } ! 1025: ! 1026: #if 0 //!!! FIXME, Zoid, mirror is disabled for now ! 1027: /* ! 1028: ============= ! 1029: R_Mirror ! 1030: ============= ! 1031: */ ! 1032: void R_Mirror (void) ! 1033: { ! 1034: float d; ! 1035: msurface_t *s; ! 1036: entity_t *ent; ! 1037: ! 1038: if (!mirror) ! 1039: return; ! 1040: ! 1041: memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix)); ! 1042: ! 1043: d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist; ! 1044: VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg); ! 1045: ! 1046: d = DotProduct (vpn, mirror_plane->normal); ! 1047: VectorMA (vpn, -2*d, mirror_plane->normal, vpn); ! 1048: ! 1049: r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180; ! 1050: r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180; ! 1051: r_refdef.viewangles[2] = -r_refdef.viewangles[2]; ! 1052: ! 1053: ent = &cl_entities[cl.viewentity]; ! 1054: if (cl_numvisedicts < MAX_VISEDICTS) ! 1055: { ! 1056: cl_visedicts[cl_numvisedicts] = ent; ! 1057: cl_numvisedicts++; ! 1058: } ! 1059: ! 1060: gldepthmin = 0.5; ! 1061: gldepthmax = 1; ! 1062: glDepthRange (gldepthmin, gldepthmax); ! 1063: glDepthFunc (GL_LEQUAL); ! 1064: ! 1065: R_RenderScene (); ! 1066: R_DrawWaterSurfaces (); ! 1067: ! 1068: ! 1069: gldepthmin = 0; ! 1070: gldepthmax = 0.5; ! 1071: glDepthRange (gldepthmin, gldepthmax); ! 1072: glDepthFunc (GL_LEQUAL); ! 1073: ! 1074: // blend on top ! 1075: glEnable (GL_BLEND); ! 1076: glMatrixMode(GL_PROJECTION); ! 1077: if (mirror_plane->normal[2]) ! 1078: glScalef (1,-1,1); ! 1079: else ! 1080: glScalef (-1,1,1); ! 1081: glCullFace(GL_FRONT); ! 1082: glMatrixMode(GL_MODELVIEW); ! 1083: ! 1084: glLoadMatrixf (r_base_world_matrix); ! 1085: ! 1086: glColor4f (1,1,1,r_mirroralpha.value); ! 1087: s = cl.worldmodel->textures[mirrortexturenum]->texturechain; ! 1088: for ( ; s ; s=s->texturechain) ! 1089: R_RenderBrushPoly (s); ! 1090: cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL; ! 1091: glDisable (GL_BLEND); ! 1092: glColor4f (1,1,1,1); ! 1093: } ! 1094: #endif ! 1095: ! 1096: /* ! 1097: ================ ! 1098: R_RenderView ! 1099: ! 1100: r_refdef must be set before the first call ! 1101: ================ ! 1102: */ ! 1103: void R_RenderView (void) ! 1104: { ! 1105: double time1 = 0, time2; ! 1106: ! 1107: if (r_norefresh.value) ! 1108: return; ! 1109: ! 1110: if (!r_worldentity.model || !cl.worldmodel) ! 1111: Sys_Error ("R_RenderView: NULL worldmodel"); ! 1112: ! 1113: if (r_speeds.value) ! 1114: { ! 1115: glFinish (); ! 1116: time1 = Sys_DoubleTime (); ! 1117: c_brush_polys = 0; ! 1118: c_alias_polys = 0; ! 1119: } ! 1120: ! 1121: mirror = false; ! 1122: ! 1123: if (gl_finish.value) ! 1124: glFinish (); ! 1125: ! 1126: R_Clear (); ! 1127: ! 1128: // render normal view ! 1129: R_RenderScene (); ! 1130: R_DrawViewModel (); ! 1131: R_DrawWaterSurfaces (); ! 1132: ! 1133: // render mirror view ! 1134: // R_Mirror (); ! 1135: ! 1136: R_PolyBlend (); ! 1137: ! 1138: if (r_speeds.value) ! 1139: { ! 1140: // glFinish (); ! 1141: time2 = Sys_DoubleTime (); ! 1142: Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); ! 1143: } ! 1144: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.