|
|
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: #include "r_local.h" ! 24: ! 25: //define PASSAGES ! 26: ! 27: void *colormap; ! 28: vec3_t viewlightvec; ! 29: alight_t r_viewlighting = {128, 192, viewlightvec}; ! 30: float r_time1; ! 31: int r_numallocatededges; ! 32: qboolean r_drawpolys; ! 33: qboolean r_drawculledpolys; ! 34: qboolean r_worldpolysbacktofront; ! 35: qboolean r_recursiveaffinetriangles = true; ! 36: int r_pixbytes = 1; ! 37: float r_aliasuvscale = 1.0; ! 38: int r_outofsurfaces; ! 39: int r_outofedges; ! 40: ! 41: qboolean r_dowarp, r_dowarpold, r_viewchanged; ! 42: ! 43: int numbtofpolys; ! 44: btofpoly_t *pbtofpolys; ! 45: mvertex_t *r_pcurrentvertbase; ! 46: ! 47: int c_surf; ! 48: int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; ! 49: qboolean r_surfsonstack; ! 50: int r_clipflags; ! 51: ! 52: byte *r_warpbuffer; ! 53: ! 54: byte *r_stack_start; ! 55: ! 56: qboolean r_fov_greater_than_90; ! 57: ! 58: entity_t r_worldentity; ! 59: ! 60: // ! 61: // view origin ! 62: // ! 63: vec3_t vup, base_vup; ! 64: vec3_t vpn, base_vpn; ! 65: vec3_t vright, base_vright; ! 66: vec3_t r_origin; ! 67: ! 68: // ! 69: // screen size info ! 70: // ! 71: refdef_t r_refdef; ! 72: float xcenter, ycenter; ! 73: float xscale, yscale; ! 74: float xscaleinv, yscaleinv; ! 75: float xscaleshrink, yscaleshrink; ! 76: float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; ! 77: ! 78: int screenwidth; ! 79: ! 80: float pixelAspect; ! 81: float screenAspect; ! 82: float verticalFieldOfView; ! 83: float xOrigin, yOrigin; ! 84: ! 85: mplane_t screenedge[4]; ! 86: ! 87: // ! 88: // refresh flags ! 89: // ! 90: int r_framecount = 1; // so frame counts initialized to 0 don't match ! 91: int r_visframecount; ! 92: int d_spanpixcount; ! 93: int r_polycount; ! 94: int r_drawnpolycount; ! 95: int r_wholepolycount; ! 96: ! 97: int *pfrustum_indexes[4]; ! 98: int r_frustum_indexes[4*6]; ! 99: ! 100: int reinit_surfcache = 1; // if 1, surface cache is currently empty and ! 101: // must be reinitialized for current cache size ! 102: ! 103: mleaf_t *r_viewleaf, *r_oldviewleaf; ! 104: ! 105: texture_t *r_notexture_mip; ! 106: ! 107: float r_aliastransition, r_resfudge; ! 108: ! 109: int d_lightstylevalue[256]; // 8.8 fraction of base light value ! 110: ! 111: float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; ! 112: float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; ! 113: ! 114: void R_MarkLeaves (void); ! 115: ! 116: cvar_t r_draworder = {"r_draworder","0"}; ! 117: cvar_t r_speeds = {"r_speeds","0"}; ! 118: cvar_t r_timegraph = {"r_timegraph","0"}; ! 119: cvar_t r_netgraph = {"r_netgraph","0"}; ! 120: cvar_t r_zgraph = {"r_zgraph","0"}; ! 121: cvar_t r_graphheight = {"r_graphheight","15"}; ! 122: cvar_t r_clearcolor = {"r_clearcolor","2"}; ! 123: cvar_t r_waterwarp = {"r_waterwarp","1"}; ! 124: cvar_t r_fullbright = {"r_fullbright","0"}; ! 125: cvar_t r_drawentities = {"r_drawentities","1"}; ! 126: cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; ! 127: cvar_t r_aliasstats = {"r_polymodelstats","0"}; ! 128: cvar_t r_dspeeds = {"r_dspeeds","0"}; ! 129: cvar_t r_drawflat = {"r_drawflat", "0"}; ! 130: cvar_t r_ambient = {"r_ambient", "0"}; ! 131: cvar_t r_reportsurfout = {"r_reportsurfout", "0"}; ! 132: cvar_t r_maxsurfs = {"r_maxsurfs", "0"}; ! 133: cvar_t r_numsurfs = {"r_numsurfs", "0"}; ! 134: cvar_t r_reportedgeout = {"r_reportedgeout", "0"}; ! 135: cvar_t r_maxedges = {"r_maxedges", "0"}; ! 136: cvar_t r_numedges = {"r_numedges", "0"}; ! 137: cvar_t r_aliastransbase = {"r_aliastransbase", "200"}; ! 138: cvar_t r_aliastransadj = {"r_aliastransadj", "100"}; ! 139: ! 140: extern cvar_t scr_fov; ! 141: ! 142: void CreatePassages (void); ! 143: void SetVisibilityByPassages (void); ! 144: ! 145: void R_NetGraph (void); ! 146: void R_ZGraph (void); ! 147: ! 148: /* ! 149: ================== ! 150: R_InitTextures ! 151: ================== ! 152: */ ! 153: void R_InitTextures (void) ! 154: { ! 155: int x,y, m; ! 156: byte *dest; ! 157: ! 158: // create a simple checkerboard texture for the default ! 159: r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture"); ! 160: ! 161: r_notexture_mip->width = r_notexture_mip->height = 16; ! 162: r_notexture_mip->offsets[0] = sizeof(texture_t); ! 163: r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; ! 164: r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8; ! 165: r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4; ! 166: ! 167: for (m=0 ; m<4 ; m++) ! 168: { ! 169: dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m]; ! 170: for (y=0 ; y< (16>>m) ; y++) ! 171: for (x=0 ; x< (16>>m) ; x++) ! 172: { ! 173: if ( (y< (8>>m) ) ^ (x< (8>>m) ) ) ! 174: *dest++ = 0; ! 175: else ! 176: *dest++ = 0xff; ! 177: } ! 178: } ! 179: } ! 180: ! 181: /* ! 182: =============== ! 183: R_Init ! 184: =============== ! 185: */ ! 186: void R_Init (void) ! 187: { ! 188: int dummy; ! 189: ! 190: // get stack position so we can guess if we are going to overflow ! 191: r_stack_start = (byte *)&dummy; ! 192: ! 193: R_InitTurb (); ! 194: ! 195: Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); ! 196: Cmd_AddCommand ("pointfile", R_ReadPointFile_f); ! 197: ! 198: Cvar_RegisterVariable (&r_draworder); ! 199: Cvar_RegisterVariable (&r_speeds); ! 200: Cvar_RegisterVariable (&r_timegraph); ! 201: Cvar_RegisterVariable (&r_netgraph); ! 202: Cvar_RegisterVariable (&r_zgraph); ! 203: Cvar_RegisterVariable (&r_graphheight); ! 204: Cvar_RegisterVariable (&r_drawflat); ! 205: Cvar_RegisterVariable (&r_ambient); ! 206: Cvar_RegisterVariable (&r_clearcolor); ! 207: Cvar_RegisterVariable (&r_waterwarp); ! 208: Cvar_RegisterVariable (&r_fullbright); ! 209: Cvar_RegisterVariable (&r_drawentities); ! 210: Cvar_RegisterVariable (&r_drawviewmodel); ! 211: Cvar_RegisterVariable (&r_aliasstats); ! 212: Cvar_RegisterVariable (&r_dspeeds); ! 213: Cvar_RegisterVariable (&r_reportsurfout); ! 214: Cvar_RegisterVariable (&r_maxsurfs); ! 215: Cvar_RegisterVariable (&r_numsurfs); ! 216: Cvar_RegisterVariable (&r_reportedgeout); ! 217: Cvar_RegisterVariable (&r_maxedges); ! 218: Cvar_RegisterVariable (&r_numedges); ! 219: Cvar_RegisterVariable (&r_aliastransbase); ! 220: Cvar_RegisterVariable (&r_aliastransadj); ! 221: ! 222: Cvar_SetValue ("r_maxedges", (float)NUMSTACKEDGES); ! 223: Cvar_SetValue ("r_maxsurfs", (float)NUMSTACKSURFACES); ! 224: ! 225: view_clipplanes[0].leftedge = true; ! 226: view_clipplanes[1].rightedge = true; ! 227: view_clipplanes[1].leftedge = view_clipplanes[2].leftedge = ! 228: view_clipplanes[3].leftedge = false; ! 229: view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = ! 230: view_clipplanes[3].rightedge = false; ! 231: ! 232: r_refdef.xOrigin = XCENTERING; ! 233: r_refdef.yOrigin = YCENTERING; ! 234: ! 235: R_InitParticles (); ! 236: ! 237: // TODO: collect 386-specific code in one place ! 238: #if id386 ! 239: Sys_MakeCodeWriteable ((long)R_EdgeCodeStart, ! 240: (long)R_EdgeCodeEnd - (long)R_EdgeCodeStart); ! 241: #endif // id386 ! 242: ! 243: D_Init (); ! 244: } ! 245: ! 246: /* ! 247: =============== ! 248: R_NewMap ! 249: =============== ! 250: */ ! 251: void R_NewMap (void) ! 252: { ! 253: int i; ! 254: ! 255: memset (&r_worldentity, 0, sizeof(r_worldentity)); ! 256: r_worldentity.model = cl.worldmodel; ! 257: ! 258: // clear out efrags in case the level hasn't been reloaded ! 259: // FIXME: is this one short? ! 260: for (i=0 ; i<cl.worldmodel->numleafs ; i++) ! 261: cl.worldmodel->leafs[i].efrags = NULL; ! 262: ! 263: r_viewleaf = NULL; ! 264: R_ClearParticles (); ! 265: ! 266: r_cnumsurfs = r_maxsurfs.value; ! 267: ! 268: if (r_cnumsurfs <= MINSURFACES) ! 269: r_cnumsurfs = MINSURFACES; ! 270: ! 271: if (r_cnumsurfs > NUMSTACKSURFACES) ! 272: { ! 273: surfaces = Hunk_AllocName (r_cnumsurfs * sizeof(surf_t), "surfaces"); ! 274: surface_p = surfaces; ! 275: surf_max = &surfaces[r_cnumsurfs]; ! 276: r_surfsonstack = false; ! 277: // surface 0 doesn't really exist; it's just a dummy because index 0 ! 278: // is used to indicate no edge attached to surface ! 279: surfaces--; ! 280: R_SurfacePatch (); ! 281: } ! 282: else ! 283: { ! 284: r_surfsonstack = true; ! 285: } ! 286: ! 287: r_maxedgesseen = 0; ! 288: r_maxsurfsseen = 0; ! 289: ! 290: r_numallocatededges = r_maxedges.value; ! 291: ! 292: if (r_numallocatededges < MINEDGES) ! 293: r_numallocatededges = MINEDGES; ! 294: ! 295: if (r_numallocatededges <= NUMSTACKEDGES) ! 296: { ! 297: auxedges = NULL; ! 298: } ! 299: else ! 300: { ! 301: auxedges = Hunk_AllocName (r_numallocatededges * sizeof(edge_t), ! 302: "edges"); ! 303: } ! 304: ! 305: r_dowarpold = false; ! 306: r_viewchanged = false; ! 307: } ! 308: ! 309: ! 310: /* ! 311: =============== ! 312: R_SetVrect ! 313: =============== ! 314: */ ! 315: void R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) ! 316: { ! 317: int h; ! 318: float size; ! 319: qboolean full = false; ! 320: ! 321: if (scr_viewsize.value >= 100.0) { ! 322: size = 100.0; ! 323: full = true; ! 324: } else ! 325: size = scr_viewsize.value; ! 326: ! 327: if (cl.intermission) ! 328: { ! 329: full = true; ! 330: size = 100.0; ! 331: lineadj = 0; ! 332: } ! 333: size /= 100.0; ! 334: ! 335: if (!cl_sbar.value && full) ! 336: h = pvrectin->height; ! 337: else ! 338: h = pvrectin->height - lineadj; ! 339: ! 340: // h = (!cl_sbar.value && size==1.0) ? pvrectin->height : (pvrectin->height - lineadj); ! 341: // h = pvrectin->height - lineadj; ! 342: if (full) ! 343: pvrect->width = pvrectin->width; ! 344: else ! 345: pvrect->width = pvrectin->width * size; ! 346: if (pvrect->width < 96) ! 347: { ! 348: size = 96.0 / pvrectin->width; ! 349: pvrect->width = 96; // min for icons ! 350: } ! 351: pvrect->width &= ~7; ! 352: pvrect->height = pvrectin->height * size; ! 353: if (cl_sbar.value || !full) { ! 354: if (pvrect->height > pvrectin->height - lineadj) ! 355: pvrect->height = pvrectin->height - lineadj; ! 356: } else ! 357: if (pvrect->height > pvrectin->height) ! 358: pvrect->height = pvrectin->height; ! 359: ! 360: pvrect->height &= ~1; ! 361: ! 362: pvrect->x = (pvrectin->width - pvrect->width)/2; ! 363: if (full) ! 364: pvrect->y = 0; ! 365: else ! 366: pvrect->y = (h - pvrect->height)/2; ! 367: } ! 368: ! 369: ! 370: /* ! 371: =============== ! 372: R_ViewChanged ! 373: ! 374: Called every time the vid structure or r_refdef changes. ! 375: Guaranteed to be called before the first refresh ! 376: =============== ! 377: */ ! 378: void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) ! 379: { ! 380: int i; ! 381: float res_scale; ! 382: ! 383: r_viewchanged = true; ! 384: ! 385: R_SetVrect (pvrect, &r_refdef.vrect, lineadj); ! 386: ! 387: r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x/360*M_PI); ! 388: r_refdef.fvrectx = (float)r_refdef.vrect.x; ! 389: r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5; ! 390: r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1; ! 391: r_refdef.fvrecty = (float)r_refdef.vrect.y; ! 392: r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5; ! 393: r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; ! 394: r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1; ! 395: r_refdef.fvrectright = (float)r_refdef.vrectright; ! 396: r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5; ! 397: r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99; ! 398: r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; ! 399: r_refdef.fvrectbottom = (float)r_refdef.vrectbottom; ! 400: r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5; ! 401: ! 402: r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale); ! 403: r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale); ! 404: r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale); ! 405: r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale); ! 406: r_refdef.aliasvrectright = r_refdef.aliasvrect.x + ! 407: r_refdef.aliasvrect.width; ! 408: r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + ! 409: r_refdef.aliasvrect.height; ! 410: ! 411: pixelAspect = aspect; ! 412: xOrigin = r_refdef.xOrigin; ! 413: yOrigin = r_refdef.yOrigin; ! 414: ! 415: screenAspect = r_refdef.vrect.width*pixelAspect / ! 416: r_refdef.vrect.height; ! 417: // 320*200 1.0 pixelAspect = 1.6 screenAspect ! 418: // 320*240 1.0 pixelAspect = 1.3333 screenAspect ! 419: // proper 320*200 pixelAspect = 0.8333333 ! 420: ! 421: verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; ! 422: ! 423: // values for perspective projection ! 424: // if math were exact, the values would range from 0.5 to to range+0.5 ! 425: // hopefully they wll be in the 0.000001 to range+.999999 and truncate ! 426: // the polygon rasterization will never render in the first row or column ! 427: // but will definately render in the [range] row and column, so adjust the ! 428: // buffer origin to get an exact edge to edge fill ! 429: xcenter = ((float)r_refdef.vrect.width * XCENTERING) + ! 430: r_refdef.vrect.x - 0.5; ! 431: aliasxcenter = xcenter * r_aliasuvscale; ! 432: ycenter = ((float)r_refdef.vrect.height * YCENTERING) + ! 433: r_refdef.vrect.y - 0.5; ! 434: aliasycenter = ycenter * r_aliasuvscale; ! 435: ! 436: xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; ! 437: aliasxscale = xscale * r_aliasuvscale; ! 438: xscaleinv = 1.0 / xscale; ! 439: yscale = xscale * pixelAspect; ! 440: aliasyscale = yscale * r_aliasuvscale; ! 441: yscaleinv = 1.0 / yscale; ! 442: xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView; ! 443: yscaleshrink = xscaleshrink*pixelAspect; ! 444: ! 445: // left side clip ! 446: screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView); ! 447: screenedge[0].normal[1] = 0; ! 448: screenedge[0].normal[2] = 1; ! 449: screenedge[0].type = PLANE_ANYZ; ! 450: ! 451: // right side clip ! 452: screenedge[1].normal[0] = ! 453: 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView); ! 454: screenedge[1].normal[1] = 0; ! 455: screenedge[1].normal[2] = 1; ! 456: screenedge[1].type = PLANE_ANYZ; ! 457: ! 458: // top side clip ! 459: screenedge[2].normal[0] = 0; ! 460: screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); ! 461: screenedge[2].normal[2] = 1; ! 462: screenedge[2].type = PLANE_ANYZ; ! 463: ! 464: // bottom side clip ! 465: screenedge[3].normal[0] = 0; ! 466: screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); ! 467: screenedge[3].normal[2] = 1; ! 468: screenedge[3].type = PLANE_ANYZ; ! 469: ! 470: for (i=0 ; i<4 ; i++) ! 471: VectorNormalize (screenedge[i].normal); ! 472: ! 473: res_scale = sqrt ((double)(r_refdef.vrect.width * r_refdef.vrect.height) / ! 474: (320.0 * 152.0)) * ! 475: (2.0 / r_refdef.horizontalFieldOfView); ! 476: r_aliastransition = r_aliastransbase.value * res_scale; ! 477: r_resfudge = r_aliastransadj.value * res_scale; ! 478: ! 479: if (scr_fov.value <= 90.0) ! 480: r_fov_greater_than_90 = false; ! 481: else ! 482: r_fov_greater_than_90 = true; ! 483: ! 484: // TODO: collect 386-specific code in one place ! 485: #if id386 ! 486: if (r_pixbytes == 1) ! 487: { ! 488: Sys_MakeCodeWriteable ((long)R_Surf8Start, ! 489: (long)R_Surf8End - (long)R_Surf8Start); ! 490: colormap = vid.colormap; ! 491: R_Surf8Patch (); ! 492: } ! 493: else ! 494: { ! 495: Sys_MakeCodeWriteable ((long)R_Surf16Start, ! 496: (long)R_Surf16End - (long)R_Surf16Start); ! 497: colormap = vid.colormap16; ! 498: R_Surf16Patch (); ! 499: } ! 500: #endif // id386 ! 501: ! 502: D_ViewChanged (); ! 503: } ! 504: ! 505: ! 506: /* ! 507: =============== ! 508: R_MarkLeaves ! 509: =============== ! 510: */ ! 511: void R_MarkLeaves (void) ! 512: { ! 513: byte *vis; ! 514: mnode_t *node; ! 515: int i; ! 516: ! 517: if (r_oldviewleaf == r_viewleaf) ! 518: return; ! 519: ! 520: r_visframecount++; ! 521: r_oldviewleaf = r_viewleaf; ! 522: ! 523: vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); ! 524: ! 525: for (i=0 ; i<cl.worldmodel->numleafs ; i++) ! 526: { ! 527: if (vis[i>>3] & (1<<(i&7))) ! 528: { ! 529: node = (mnode_t *)&cl.worldmodel->leafs[i+1]; ! 530: do ! 531: { ! 532: if (node->visframe == r_visframecount) ! 533: break; ! 534: node->visframe = r_visframecount; ! 535: node = node->parent; ! 536: } while (node); ! 537: } ! 538: } ! 539: } ! 540: ! 541: ! 542: /* ! 543: ============= ! 544: R_DrawEntitiesOnList ! 545: ============= ! 546: */ ! 547: void R_DrawEntitiesOnList (void) ! 548: { ! 549: int i, j; ! 550: int lnum; ! 551: alight_t lighting; ! 552: // FIXME: remove and do real lighting ! 553: float lightvec[3] = {-1, 0, 0}; ! 554: vec3_t dist; ! 555: float add; ! 556: ! 557: if (!r_drawentities.value) ! 558: return; ! 559: ! 560: for (i=0 ; i<cl_numvisedicts ; i++) ! 561: { ! 562: currententity = &cl_visedicts[i]; ! 563: ! 564: switch (currententity->model->type) ! 565: { ! 566: case mod_sprite: ! 567: VectorCopy (currententity->origin, r_entorigin); ! 568: VectorSubtract (r_origin, r_entorigin, modelorg); ! 569: R_DrawSprite (); ! 570: break; ! 571: ! 572: case mod_alias: ! 573: VectorCopy (currententity->origin, r_entorigin); ! 574: VectorSubtract (r_origin, r_entorigin, modelorg); ! 575: ! 576: // see if the bounding box lets us trivially reject, also sets ! 577: // trivial accept status ! 578: if (R_AliasCheckBBox ()) ! 579: { ! 580: j = R_LightPoint (currententity->origin); ! 581: ! 582: lighting.ambientlight = j; ! 583: lighting.shadelight = j; ! 584: ! 585: lighting.plightvec = lightvec; ! 586: ! 587: for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++) ! 588: { ! 589: if (cl_dlights[lnum].die >= cl.time) ! 590: { ! 591: VectorSubtract (currententity->origin, ! 592: cl_dlights[lnum].origin, ! 593: dist); ! 594: add = cl_dlights[lnum].radius - Length(dist); ! 595: ! 596: if (add > 0) ! 597: lighting.ambientlight += add; ! 598: } ! 599: } ! 600: ! 601: // clamp lighting so it doesn't overbright as much ! 602: if (lighting.ambientlight > 128) ! 603: lighting.ambientlight = 128; ! 604: if (lighting.ambientlight + lighting.shadelight > 192) ! 605: lighting.shadelight = 192 - lighting.ambientlight; ! 606: ! 607: R_AliasDrawModel (&lighting); ! 608: } ! 609: ! 610: break; ! 611: ! 612: default: ! 613: break; ! 614: } ! 615: } ! 616: } ! 617: ! 618: /* ! 619: ============= ! 620: R_DrawViewModel ! 621: ============= ! 622: */ ! 623: void R_DrawViewModel (void) ! 624: { ! 625: // FIXME: remove and do real lighting ! 626: float lightvec[3] = {-1, 0, 0}; ! 627: int j; ! 628: int lnum; ! 629: vec3_t dist; ! 630: float add; ! 631: dlight_t *dl; ! 632: ! 633: if (!r_drawviewmodel.value || r_fov_greater_than_90 || !Cam_DrawViewModel()) ! 634: return; ! 635: ! 636: if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) ! 637: return; ! 638: ! 639: if (cl.stats[STAT_HEALTH] <= 0) ! 640: return; ! 641: ! 642: currententity = &cl.viewent; ! 643: if (!currententity->model) ! 644: return; ! 645: ! 646: VectorCopy (currententity->origin, r_entorigin); ! 647: VectorSubtract (r_origin, r_entorigin, modelorg); ! 648: ! 649: VectorCopy (vup, viewlightvec); ! 650: VectorInverse (viewlightvec); ! 651: ! 652: j = R_LightPoint (currententity->origin); ! 653: ! 654: if (j < 24) ! 655: j = 24; // allways give some light on gun ! 656: r_viewlighting.ambientlight = j; ! 657: r_viewlighting.shadelight = j; ! 658: ! 659: // add dynamic lights ! 660: for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++) ! 661: { ! 662: dl = &cl_dlights[lnum]; ! 663: if (!dl->radius) ! 664: continue; ! 665: if (!dl->radius) ! 666: continue; ! 667: if (dl->die < cl.time) ! 668: continue; ! 669: ! 670: VectorSubtract (currententity->origin, dl->origin, dist); ! 671: add = dl->radius - Length(dist); ! 672: if (add > 0) ! 673: r_viewlighting.ambientlight += add; ! 674: } ! 675: ! 676: // clamp lighting so it doesn't overbright as much ! 677: if (r_viewlighting.ambientlight > 128) ! 678: r_viewlighting.ambientlight = 128; ! 679: if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192) ! 680: r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight; ! 681: ! 682: r_viewlighting.plightvec = lightvec; ! 683: ! 684: R_AliasDrawModel (&r_viewlighting); ! 685: } ! 686: ! 687: ! 688: /* ! 689: ============= ! 690: R_BmodelCheckBBox ! 691: ============= ! 692: */ ! 693: int R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) ! 694: { ! 695: int i, *pindex, clipflags; ! 696: vec3_t acceptpt, rejectpt; ! 697: double d; ! 698: ! 699: clipflags = 0; ! 700: ! 701: if (currententity->angles[0] || currententity->angles[1] ! 702: || currententity->angles[2]) ! 703: { ! 704: for (i=0 ; i<4 ; i++) ! 705: { ! 706: d = DotProduct (currententity->origin, view_clipplanes[i].normal); ! 707: d -= view_clipplanes[i].dist; ! 708: ! 709: if (d <= -clmodel->radius) ! 710: return BMODEL_FULLY_CLIPPED; ! 711: ! 712: if (d <= clmodel->radius) ! 713: clipflags |= (1<<i); ! 714: } ! 715: } ! 716: else ! 717: { ! 718: for (i=0 ; i<4 ; i++) ! 719: { ! 720: // generate accept and reject points ! 721: // FIXME: do with fast look-ups or integer tests based on the sign bit ! 722: // of the floating point values ! 723: ! 724: pindex = pfrustum_indexes[i]; ! 725: ! 726: rejectpt[0] = minmaxs[pindex[0]]; ! 727: rejectpt[1] = minmaxs[pindex[1]]; ! 728: rejectpt[2] = minmaxs[pindex[2]]; ! 729: ! 730: d = DotProduct (rejectpt, view_clipplanes[i].normal); ! 731: d -= view_clipplanes[i].dist; ! 732: ! 733: if (d <= 0) ! 734: return BMODEL_FULLY_CLIPPED; ! 735: ! 736: acceptpt[0] = minmaxs[pindex[3+0]]; ! 737: acceptpt[1] = minmaxs[pindex[3+1]]; ! 738: acceptpt[2] = minmaxs[pindex[3+2]]; ! 739: ! 740: d = DotProduct (acceptpt, view_clipplanes[i].normal); ! 741: d -= view_clipplanes[i].dist; ! 742: ! 743: if (d <= 0) ! 744: clipflags |= (1<<i); ! 745: } ! 746: } ! 747: ! 748: return clipflags; ! 749: } ! 750: ! 751: ! 752: /* ! 753: ============= ! 754: R_DrawBEntitiesOnList ! 755: ============= ! 756: */ ! 757: void R_DrawBEntitiesOnList (void) ! 758: { ! 759: int i, j, k, clipflags; ! 760: vec3_t oldorigin; ! 761: model_t *clmodel; ! 762: float minmaxs[6]; ! 763: ! 764: if (!r_drawentities.value) ! 765: return; ! 766: ! 767: VectorCopy (modelorg, oldorigin); ! 768: insubmodel = true; ! 769: r_dlightframecount = r_framecount; ! 770: ! 771: for (i=0 ; i<cl_numvisedicts ; i++) ! 772: { ! 773: currententity = &cl_visedicts[i]; ! 774: ! 775: switch (currententity->model->type) ! 776: { ! 777: case mod_brush: ! 778: ! 779: clmodel = currententity->model; ! 780: ! 781: // see if the bounding box lets us trivially reject, also sets ! 782: // trivial accept status ! 783: for (j=0 ; j<3 ; j++) ! 784: { ! 785: minmaxs[j] = currententity->origin[j] + ! 786: clmodel->mins[j]; ! 787: minmaxs[3+j] = currententity->origin[j] + ! 788: clmodel->maxs[j]; ! 789: } ! 790: ! 791: clipflags = R_BmodelCheckBBox (clmodel, minmaxs); ! 792: ! 793: if (clipflags != BMODEL_FULLY_CLIPPED) ! 794: { ! 795: VectorCopy (currententity->origin, r_entorigin); ! 796: VectorSubtract (r_origin, r_entorigin, modelorg); ! 797: // FIXME: is this needed? ! 798: VectorCopy (modelorg, r_worldmodelorg); ! 799: ! 800: r_pcurrentvertbase = clmodel->vertexes; ! 801: ! 802: // FIXME: stop transforming twice ! 803: R_RotateBmodel (); ! 804: ! 805: // calculate dynamic lighting for bmodel if it's not an ! 806: // instanced model ! 807: if (clmodel->firstmodelsurface != 0) ! 808: { ! 809: for (k=0 ; k<MAX_DLIGHTS ; k++) ! 810: { ! 811: if ((cl_dlights[k].die < cl.time) || ! 812: (!cl_dlights[k].radius)) ! 813: { ! 814: continue; ! 815: } ! 816: ! 817: R_MarkLights (&cl_dlights[k], 1<<k, ! 818: clmodel->nodes + clmodel->hulls[0].firstclipnode); ! 819: } ! 820: } ! 821: ! 822: // if the driver wants polygons, deliver those. Z-buffering is on ! 823: // at this point, so no clipping to the world tree is needed, just ! 824: // frustum clipping ! 825: if (r_drawpolys | r_drawculledpolys) ! 826: { ! 827: R_ZDrawSubmodelPolys (clmodel); ! 828: } ! 829: else ! 830: { ! 831: r_pefragtopnode = NULL; ! 832: ! 833: for (j=0 ; j<3 ; j++) ! 834: { ! 835: r_emins[j] = minmaxs[j]; ! 836: r_emaxs[j] = minmaxs[3+j]; ! 837: } ! 838: ! 839: R_SplitEntityOnNode2 (cl.worldmodel->nodes); ! 840: ! 841: if (r_pefragtopnode) ! 842: { ! 843: currententity->topnode = r_pefragtopnode; ! 844: ! 845: if (r_pefragtopnode->contents >= 0) ! 846: { ! 847: // not a leaf; has to be clipped to the world BSP ! 848: r_clipflags = clipflags; ! 849: R_DrawSolidClippedSubmodelPolygons (clmodel); ! 850: } ! 851: else ! 852: { ! 853: // falls entirely in one leaf, so we just put all the ! 854: // edges in the edge list and let 1/z sorting handle ! 855: // drawing order ! 856: R_DrawSubmodelPolygons (clmodel, clipflags); ! 857: } ! 858: ! 859: currententity->topnode = NULL; ! 860: } ! 861: } ! 862: ! 863: // put back world rotation and frustum clipping ! 864: // FIXME: R_RotateBmodel should just work off base_vxx ! 865: VectorCopy (base_vpn, vpn); ! 866: VectorCopy (base_vup, vup); ! 867: VectorCopy (base_vright, vright); ! 868: VectorCopy (base_modelorg, modelorg); ! 869: VectorCopy (oldorigin, modelorg); ! 870: R_TransformFrustum (); ! 871: } ! 872: ! 873: break; ! 874: ! 875: default: ! 876: break; ! 877: } ! 878: } ! 879: ! 880: insubmodel = false; ! 881: } ! 882: ! 883: ! 884: /* ! 885: ================ ! 886: R_EdgeDrawing ! 887: ================ ! 888: */ ! 889: void R_EdgeDrawing (void) ! 890: { ! 891: edge_t ledges[NUMSTACKEDGES + ! 892: ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1]; ! 893: surf_t lsurfs[NUMSTACKSURFACES + ! 894: ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1]; ! 895: ! 896: if (auxedges) ! 897: { ! 898: r_edges = auxedges; ! 899: } ! 900: else ! 901: { ! 902: r_edges = (edge_t *) ! 903: (((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); ! 904: } ! 905: ! 906: if (r_surfsonstack) ! 907: { ! 908: surfaces = (surf_t *) ! 909: (((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); ! 910: surf_max = &surfaces[r_cnumsurfs]; ! 911: // surface 0 doesn't really exist; it's just a dummy because index 0 ! 912: // is used to indicate no edge attached to surface ! 913: surfaces--; ! 914: R_SurfacePatch (); ! 915: } ! 916: ! 917: R_BeginEdgeFrame (); ! 918: ! 919: if (r_dspeeds.value) ! 920: { ! 921: rw_time1 = Sys_DoubleTime (); ! 922: } ! 923: ! 924: R_RenderWorld (); ! 925: ! 926: if (r_drawculledpolys) ! 927: R_ScanEdges (); ! 928: ! 929: // only the world can be drawn back to front with no z reads or compares, just ! 930: // z writes, so have the driver turn z compares on now ! 931: D_TurnZOn (); ! 932: ! 933: if (r_dspeeds.value) ! 934: { ! 935: rw_time2 = Sys_DoubleTime (); ! 936: db_time1 = rw_time2; ! 937: } ! 938: ! 939: R_DrawBEntitiesOnList (); ! 940: ! 941: if (r_dspeeds.value) ! 942: { ! 943: db_time2 = Sys_DoubleTime (); ! 944: se_time1 = db_time2; ! 945: } ! 946: ! 947: if (!r_dspeeds.value) ! 948: { ! 949: VID_UnlockBuffer (); ! 950: S_ExtraUpdate (); // don't let sound get messed up if going slow ! 951: VID_LockBuffer (); ! 952: } ! 953: ! 954: if (!(r_drawpolys | r_drawculledpolys)) ! 955: R_ScanEdges (); ! 956: } ! 957: ! 958: ! 959: /* ! 960: ================ ! 961: R_RenderView ! 962: ! 963: r_refdef must be set before the first call ! 964: ================ ! 965: */ ! 966: void R_RenderView_ (void) ! 967: { ! 968: byte warpbuffer[WARP_WIDTH * WARP_HEIGHT]; ! 969: ! 970: r_warpbuffer = warpbuffer; ! 971: ! 972: if (r_timegraph.value || r_speeds.value || r_dspeeds.value) ! 973: r_time1 = Sys_DoubleTime (); ! 974: ! 975: R_SetupFrame (); ! 976: ! 977: #ifdef PASSAGES ! 978: SetVisibilityByPassages (); ! 979: #else ! 980: R_MarkLeaves (); // done here so we know if we're in water ! 981: #endif ! 982: ! 983: // make FDIV fast. This reduces timing precision after we've been running for a ! 984: // while, so we don't do it globally. This also sets chop mode, and we do it ! 985: // here so that setup stuff like the refresh area calculations match what's ! 986: // done in screen.c ! 987: Sys_LowFPPrecision (); ! 988: ! 989: if (!r_worldentity.model || !cl.worldmodel) ! 990: Sys_Error ("R_RenderView: NULL worldmodel"); ! 991: ! 992: if (!r_dspeeds.value) ! 993: { ! 994: VID_UnlockBuffer (); ! 995: S_ExtraUpdate (); // don't let sound get messed up if going slow ! 996: VID_LockBuffer (); ! 997: } ! 998: ! 999: R_EdgeDrawing (); ! 1000: ! 1001: if (!r_dspeeds.value) ! 1002: { ! 1003: VID_UnlockBuffer (); ! 1004: S_ExtraUpdate (); // don't let sound get messed up if going slow ! 1005: VID_LockBuffer (); ! 1006: } ! 1007: ! 1008: if (r_dspeeds.value) ! 1009: { ! 1010: se_time2 = Sys_DoubleTime (); ! 1011: de_time1 = se_time2; ! 1012: } ! 1013: ! 1014: R_DrawEntitiesOnList (); ! 1015: ! 1016: if (r_dspeeds.value) ! 1017: { ! 1018: de_time2 = Sys_DoubleTime (); ! 1019: dv_time1 = de_time2; ! 1020: } ! 1021: ! 1022: R_DrawViewModel (); ! 1023: ! 1024: if (r_dspeeds.value) ! 1025: { ! 1026: dv_time2 = Sys_DoubleTime (); ! 1027: dp_time1 = Sys_DoubleTime (); ! 1028: } ! 1029: ! 1030: R_DrawParticles (); ! 1031: ! 1032: if (r_dspeeds.value) ! 1033: dp_time2 = Sys_DoubleTime (); ! 1034: ! 1035: if (r_dowarp) ! 1036: D_WarpScreen (); ! 1037: ! 1038: V_SetContentsColor (r_viewleaf->contents); ! 1039: ! 1040: if (r_timegraph.value) ! 1041: R_TimeGraph (); ! 1042: ! 1043: if (r_netgraph.value) ! 1044: R_NetGraph (); ! 1045: ! 1046: if (r_zgraph.value) ! 1047: R_ZGraph (); ! 1048: ! 1049: if (r_aliasstats.value) ! 1050: R_PrintAliasStats (); ! 1051: ! 1052: if (r_speeds.value) ! 1053: R_PrintTimes (); ! 1054: ! 1055: if (r_dspeeds.value) ! 1056: R_PrintDSpeeds (); ! 1057: ! 1058: if (r_reportsurfout.value && r_outofsurfaces) ! 1059: Con_Printf ("Short %d surfaces\n", r_outofsurfaces); ! 1060: ! 1061: if (r_reportedgeout.value && r_outofedges) ! 1062: Con_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3); ! 1063: ! 1064: // back to high floating-point precision ! 1065: Sys_HighFPPrecision (); ! 1066: } ! 1067: ! 1068: void R_RenderView (void) ! 1069: { ! 1070: int dummy; ! 1071: int delta; ! 1072: ! 1073: delta = (byte *)&dummy - r_stack_start; ! 1074: if (delta < -10000 || delta > 10000) ! 1075: Sys_Error ("R_RenderView: called without enough stack"); ! 1076: ! 1077: if ( Hunk_LowMark() & 3 ) ! 1078: Sys_Error ("Hunk is missaligned"); ! 1079: ! 1080: if ( (long)(&dummy) & 3 ) ! 1081: Sys_Error ("Stack is missaligned"); ! 1082: ! 1083: if ( (long)(&r_warpbuffer) & 3 ) ! 1084: Sys_Error ("Globals are missaligned"); ! 1085: ! 1086: R_RenderView_ (); ! 1087: } ! 1088: ! 1089: /* ! 1090: ================ ! 1091: R_InitTurb ! 1092: ================ ! 1093: */ ! 1094: void R_InitTurb (void) ! 1095: { ! 1096: int i; ! 1097: ! 1098: for (i=0 ; i<1280 ; i++) ! 1099: { ! 1100: sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP; ! 1101: intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2; // AMP2, not 20 ! 1102: } ! 1103: } ! 1104:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.