From a8f828a066773a59fdf646299359d35ae0e845af Mon Sep 17 00:00:00 2001 From: wyatt8740 Date: Mon, 6 Jan 2014 12:02:16 -0500 Subject: Removed accidental upload of copyrighted map files --- WinQuake/r_main.c | 2170 ++++++++++++++++++++++++++--------------------------- 1 file changed, 1085 insertions(+), 1085 deletions(-) (limited to 'WinQuake/r_main.c') diff --git a/WinQuake/r_main.c b/WinQuake/r_main.c index 3fe5146..e0e06ba 100644 --- a/WinQuake/r_main.c +++ b/WinQuake/r_main.c @@ -1,1085 +1,1085 @@ -/* -Copyright (C) 1996-1997 Id Software, Inc. - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ -// r_main.c - -#include "quakedef.h" -#include "r_local.h" - -//define PASSAGES - -void *colormap; -vec3_t viewlightvec; -alight_t r_viewlighting = {128, 192, viewlightvec}; -float r_time1; -int r_numallocatededges; -qboolean r_drawpolys; -qboolean r_drawculledpolys; -qboolean r_worldpolysbacktofront; -qboolean r_recursiveaffinetriangles = true; -int r_pixbytes = 1; -float r_aliasuvscale = 1.0; -int r_outofsurfaces; -int r_outofedges; - -qboolean r_dowarp, r_dowarpold, r_viewchanged; - -int numbtofpolys; -btofpoly_t *pbtofpolys; -mvertex_t *r_pcurrentvertbase; - -int c_surf; -int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; -qboolean r_surfsonstack; -int r_clipflags; - -byte *r_warpbuffer; - -byte *r_stack_start; - -qboolean r_fov_greater_than_90; - -// -// view origin -// -vec3_t vup, base_vup; -vec3_t vpn, base_vpn; -vec3_t vright, base_vright; -vec3_t r_origin; - -// -// screen size info -// -refdef_t r_refdef; -float xcenter, ycenter; -float xscale, yscale; -float xscaleinv, yscaleinv; -float xscaleshrink, yscaleshrink; -float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; - -int screenwidth; - -float pixelAspect; -float screenAspect; -float verticalFieldOfView; -float xOrigin, yOrigin; - -mplane_t screenedge[4]; - -// -// refresh flags -// -int r_framecount = 1; // so frame counts initialized to 0 don't match -int r_visframecount; -int d_spanpixcount; -int r_polycount; -int r_drawnpolycount; -int r_wholepolycount; - -#define VIEWMODNAME_LENGTH 256 -char viewmodname[VIEWMODNAME_LENGTH+1]; -int modcount; - -int *pfrustum_indexes[4]; -int r_frustum_indexes[4*6]; - -int reinit_surfcache = 1; // if 1, surface cache is currently empty and - // must be reinitialized for current cache size - -mleaf_t *r_viewleaf, *r_oldviewleaf; - -texture_t *r_notexture_mip; - -float r_aliastransition, r_resfudge; - -int d_lightstylevalue[256]; // 8.8 fraction of base light value - -float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; -float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; - -void R_MarkLeaves (void); - -cvar_t r_draworder = {"r_draworder","0"}; -cvar_t r_speeds = {"r_speeds","0"}; -cvar_t r_timegraph = {"r_timegraph","0"}; -cvar_t r_graphheight = {"r_graphheight","10"}; -cvar_t r_clearcolor = {"r_clearcolor","2"}; -cvar_t r_waterwarp = {"r_waterwarp","1"}; -cvar_t r_fullbright = {"r_fullbright","0"}; -cvar_t r_drawentities = {"r_drawentities","1"}; -cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; -cvar_t r_aliasstats = {"r_polymodelstats","0"}; -cvar_t r_dspeeds = {"r_dspeeds","0"}; -cvar_t r_drawflat = {"r_drawflat", "0"}; -cvar_t r_ambient = {"r_ambient", "0"}; -cvar_t r_reportsurfout = {"r_reportsurfout", "0"}; -cvar_t r_maxsurfs = {"r_maxsurfs", "0"}; -cvar_t r_numsurfs = {"r_numsurfs", "0"}; -cvar_t r_reportedgeout = {"r_reportedgeout", "0"}; -cvar_t r_maxedges = {"r_maxedges", "0"}; -cvar_t r_numedges = {"r_numedges", "0"}; -cvar_t r_aliastransbase = {"r_aliastransbase", "200"}; -cvar_t r_aliastransadj = {"r_aliastransadj", "100"}; - -extern cvar_t scr_fov; - -void CreatePassages (void); -void SetVisibilityByPassages (void); - -/* -================== -R_InitTextures -================== -*/ -void R_InitTextures (void) -{ - int x,y, m; - byte *dest; - -// create a simple checkerboard texture for the default - r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture"); - - r_notexture_mip->width = r_notexture_mip->height = 16; - r_notexture_mip->offsets[0] = sizeof(texture_t); - r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; - r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8; - r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4; - - for (m=0 ; m<4 ; m++) - { - dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m]; - for (y=0 ; y< (16>>m) ; y++) - for (x=0 ; x< (16>>m) ; x++) - { - if ( (y< (8>>m) ) ^ (x< (8>>m) ) ) - *dest++ = 0; - else - *dest++ = 0xff; - } - } -} - -/* -=============== -R_Init -=============== -*/ -void R_Init (void) -{ - int dummy; - -// get stack position so we can guess if we are going to overflow - r_stack_start = (byte *)&dummy; - - R_InitTurb (); - - Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); - Cmd_AddCommand ("pointfile", R_ReadPointFile_f); - - Cvar_RegisterVariable (&r_draworder); - Cvar_RegisterVariable (&r_speeds); - Cvar_RegisterVariable (&r_timegraph); - Cvar_RegisterVariable (&r_graphheight); - Cvar_RegisterVariable (&r_drawflat); - Cvar_RegisterVariable (&r_ambient); - Cvar_RegisterVariable (&r_clearcolor); - Cvar_RegisterVariable (&r_waterwarp); - Cvar_RegisterVariable (&r_fullbright); - Cvar_RegisterVariable (&r_drawentities); - Cvar_RegisterVariable (&r_drawviewmodel); - Cvar_RegisterVariable (&r_aliasstats); - Cvar_RegisterVariable (&r_dspeeds); - Cvar_RegisterVariable (&r_reportsurfout); - Cvar_RegisterVariable (&r_maxsurfs); - Cvar_RegisterVariable (&r_numsurfs); - Cvar_RegisterVariable (&r_reportedgeout); - Cvar_RegisterVariable (&r_maxedges); - Cvar_RegisterVariable (&r_numedges); - Cvar_RegisterVariable (&r_aliastransbase); - Cvar_RegisterVariable (&r_aliastransadj); - - Cvar_SetValue ("r_maxedges", (float)NUMSTACKEDGES); - Cvar_SetValue ("r_maxsurfs", (float)NUMSTACKSURFACES); - - view_clipplanes[0].leftedge = true; - view_clipplanes[1].rightedge = true; - view_clipplanes[1].leftedge = view_clipplanes[2].leftedge = - view_clipplanes[3].leftedge = false; - view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = - view_clipplanes[3].rightedge = false; - - r_refdef.xOrigin = XCENTERING; - r_refdef.yOrigin = YCENTERING; - - R_InitParticles (); - -// TODO: collect 386-specific code in one place -#if id386 - Sys_MakeCodeWriteable ((long)R_EdgeCodeStart, - (long)R_EdgeCodeEnd - (long)R_EdgeCodeStart); -#endif // id386 - - D_Init (); -} - -/* -=============== -R_NewMap -=============== -*/ -void R_NewMap (void) -{ - int i; - -// clear out efrags in case the level hasn't been reloaded -// FIXME: is this one short? - for (i=0 ; inumleafs ; i++) - cl.worldmodel->leafs[i].efrags = NULL; - - r_viewleaf = NULL; - R_ClearParticles (); - - r_cnumsurfs = r_maxsurfs.value; - - if (r_cnumsurfs <= MINSURFACES) - r_cnumsurfs = MINSURFACES; - - if (r_cnumsurfs > NUMSTACKSURFACES) - { - surfaces = Hunk_AllocName (r_cnumsurfs * sizeof(surf_t), "surfaces"); - surface_p = surfaces; - surf_max = &surfaces[r_cnumsurfs]; - r_surfsonstack = false; - // surface 0 doesn't really exist; it's just a dummy because index 0 - // is used to indicate no edge attached to surface - surfaces--; - R_SurfacePatch (); - } - else - { - r_surfsonstack = true; - } - - r_maxedgesseen = 0; - r_maxsurfsseen = 0; - - r_numallocatededges = r_maxedges.value; - - if (r_numallocatededges < MINEDGES) - r_numallocatededges = MINEDGES; - - if (r_numallocatededges <= NUMSTACKEDGES) - { - auxedges = NULL; - } - else - { - auxedges = Hunk_AllocName (r_numallocatededges * sizeof(edge_t), - "edges"); - } - - r_dowarpold = false; - r_viewchanged = false; -#ifdef PASSAGES -CreatePassages (); -#endif -} - - -/* -=============== -R_SetVrect -=============== -*/ -void R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) -{ - int h; - float size; - - size = scr_viewsize.value > 100 ? 100 : scr_viewsize.value; - if (cl.intermission) - { - size = 100; - lineadj = 0; - } - size /= 100; - - h = pvrectin->height - lineadj; - pvrect->width = pvrectin->width * size; - if (pvrect->width < 96) - { - size = 96.0 / pvrectin->width; - pvrect->width = 96; // min for icons - } - pvrect->width &= ~7; - pvrect->height = pvrectin->height * size; - if (pvrect->height > pvrectin->height - lineadj) - pvrect->height = pvrectin->height - lineadj; - - pvrect->height &= ~1; - - pvrect->x = (pvrectin->width - pvrect->width)/2; - pvrect->y = (h - pvrect->height)/2; - - { - if (lcd_x.value) - { - pvrect->y >>= 1; - pvrect->height >>= 1; - } - } -} - - -/* -=============== -R_ViewChanged - -Called every time the vid structure or r_refdef changes. -Guaranteed to be called before the first refresh -=============== -*/ -void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) -{ - int i; - float res_scale; - - r_viewchanged = true; - - R_SetVrect (pvrect, &r_refdef.vrect, lineadj); - - r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x/360*M_PI); - r_refdef.fvrectx = (float)r_refdef.vrect.x; - r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5; - r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1; - r_refdef.fvrecty = (float)r_refdef.vrect.y; - r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5; - r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; - r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1; - r_refdef.fvrectright = (float)r_refdef.vrectright; - r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5; - r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99; - r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; - r_refdef.fvrectbottom = (float)r_refdef.vrectbottom; - r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5; - - r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale); - r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale); - r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale); - r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale); - r_refdef.aliasvrectright = r_refdef.aliasvrect.x + - r_refdef.aliasvrect.width; - r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + - r_refdef.aliasvrect.height; - - pixelAspect = aspect; - xOrigin = r_refdef.xOrigin; - yOrigin = r_refdef.yOrigin; - - screenAspect = r_refdef.vrect.width*pixelAspect / - r_refdef.vrect.height; -// 320*200 1.0 pixelAspect = 1.6 screenAspect -// 320*240 1.0 pixelAspect = 1.3333 screenAspect -// proper 320*200 pixelAspect = 0.8333333 - - verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; - -// values for perspective projection -// if math were exact, the values would range from 0.5 to to range+0.5 -// hopefully they wll be in the 0.000001 to range+.999999 and truncate -// the polygon rasterization will never render in the first row or column -// but will definately render in the [range] row and column, so adjust the -// buffer origin to get an exact edge to edge fill - xcenter = ((float)r_refdef.vrect.width * XCENTERING) + - r_refdef.vrect.x - 0.5; - aliasxcenter = xcenter * r_aliasuvscale; - ycenter = ((float)r_refdef.vrect.height * YCENTERING) + - r_refdef.vrect.y - 0.5; - aliasycenter = ycenter * r_aliasuvscale; - - xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; - aliasxscale = xscale * r_aliasuvscale; - xscaleinv = 1.0 / xscale; - yscale = xscale * pixelAspect; - aliasyscale = yscale * r_aliasuvscale; - yscaleinv = 1.0 / yscale; - xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView; - yscaleshrink = xscaleshrink*pixelAspect; - -// left side clip - screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView); - screenedge[0].normal[1] = 0; - screenedge[0].normal[2] = 1; - screenedge[0].type = PLANE_ANYZ; - -// right side clip - screenedge[1].normal[0] = - 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView); - screenedge[1].normal[1] = 0; - screenedge[1].normal[2] = 1; - screenedge[1].type = PLANE_ANYZ; - -// top side clip - screenedge[2].normal[0] = 0; - screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); - screenedge[2].normal[2] = 1; - screenedge[2].type = PLANE_ANYZ; - -// bottom side clip - screenedge[3].normal[0] = 0; - screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); - screenedge[3].normal[2] = 1; - screenedge[3].type = PLANE_ANYZ; - - for (i=0 ; i<4 ; i++) - VectorNormalize (screenedge[i].normal); - - res_scale = sqrt ((double)(r_refdef.vrect.width * r_refdef.vrect.height) / - (320.0 * 152.0)) * - (2.0 / r_refdef.horizontalFieldOfView); - r_aliastransition = r_aliastransbase.value * res_scale; - r_resfudge = r_aliastransadj.value * res_scale; - - if (scr_fov.value <= 90.0) - r_fov_greater_than_90 = false; - else - r_fov_greater_than_90 = true; - -// TODO: collect 386-specific code in one place -#if id386 - if (r_pixbytes == 1) - { - Sys_MakeCodeWriteable ((long)R_Surf8Start, - (long)R_Surf8End - (long)R_Surf8Start); - colormap = vid.colormap; - R_Surf8Patch (); - } - else - { - Sys_MakeCodeWriteable ((long)R_Surf16Start, - (long)R_Surf16End - (long)R_Surf16Start); - colormap = vid.colormap16; - R_Surf16Patch (); - } -#endif // id386 - - D_ViewChanged (); -} - - -/* -=============== -R_MarkLeaves -=============== -*/ -void R_MarkLeaves (void) -{ - byte *vis; - mnode_t *node; - int i; - - if (r_oldviewleaf == r_viewleaf) - return; - - r_visframecount++; - r_oldviewleaf = r_viewleaf; - - vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); - - for (i=0 ; inumleafs ; i++) - { - if (vis[i>>3] & (1<<(i&7))) - { - node = (mnode_t *)&cl.worldmodel->leafs[i+1]; - do - { - if (node->visframe == r_visframecount) - break; - node->visframe = r_visframecount; - node = node->parent; - } while (node); - } - } -} - - -/* -============= -R_DrawEntitiesOnList -============= -*/ -void R_DrawEntitiesOnList (void) -{ - int i, j; - int lnum; - alight_t lighting; -// FIXME: remove and do real lighting - float lightvec[3] = {-1, 0, 0}; - vec3_t dist; - float add; - - if (!r_drawentities.value) - return; - - for (i=0 ; imodel->type) - { - case mod_sprite: - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - R_DrawSprite (); - break; - - case mod_alias: - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - - // see if the bounding box lets us trivially reject, also sets - // trivial accept status - if (R_AliasCheckBBox ()) - { - j = R_LightPoint (currententity->origin); - - lighting.ambientlight = j; - lighting.shadelight = j; - - lighting.plightvec = lightvec; - - for (lnum=0 ; lnum= cl.time) - { - VectorSubtract (currententity->origin, - cl_dlights[lnum].origin, - dist); - add = cl_dlights[lnum].radius - Length(dist); - - if (add > 0) - lighting.ambientlight += add; - } - } - - // clamp lighting so it doesn't overbright as much - if (lighting.ambientlight > 128) - lighting.ambientlight = 128; - if (lighting.ambientlight + lighting.shadelight > 192) - lighting.shadelight = 192 - lighting.ambientlight; - - R_AliasDrawModel (&lighting); - } - - break; - - default: - break; - } - } -} - -/* -============= -R_DrawViewModel -============= -*/ -void R_DrawViewModel (void) -{ -// FIXME: remove and do real lighting - float lightvec[3] = {-1, 0, 0}; - int j; - int lnum; - vec3_t dist; - float add; - dlight_t *dl; - - if (!r_drawviewmodel.value || r_fov_greater_than_90) - return; - - if (cl.items & IT_INVISIBILITY) - return; - - if (cl.stats[STAT_HEALTH] <= 0) - return; - - currententity = &cl.viewent; - if (!currententity->model) - return; - - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - - VectorCopy (vup, viewlightvec); - VectorInverse (viewlightvec); - - j = R_LightPoint (currententity->origin); - - if (j < 24) - j = 24; // allways give some light on gun - r_viewlighting.ambientlight = j; - r_viewlighting.shadelight = j; - -// add dynamic lights - for (lnum=0 ; lnumradius) - continue; - if (!dl->radius) - continue; - if (dl->die < cl.time) - continue; - - VectorSubtract (currententity->origin, dl->origin, dist); - add = dl->radius - Length(dist); - if (add > 0) - r_viewlighting.ambientlight += add; - } - -// clamp lighting so it doesn't overbright as much - if (r_viewlighting.ambientlight > 128) - r_viewlighting.ambientlight = 128; - if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192) - r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight; - - r_viewlighting.plightvec = lightvec; - -#ifdef QUAKE2 - cl.light_level = r_viewlighting.ambientlight; -#endif - - R_AliasDrawModel (&r_viewlighting); -} - - -/* -============= -R_BmodelCheckBBox -============= -*/ -int R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) -{ - int i, *pindex, clipflags; - vec3_t acceptpt, rejectpt; - double d; - - clipflags = 0; - - if (currententity->angles[0] || currententity->angles[1] - || currententity->angles[2]) - { - for (i=0 ; i<4 ; i++) - { - d = DotProduct (currententity->origin, view_clipplanes[i].normal); - d -= view_clipplanes[i].dist; - - if (d <= -clmodel->radius) - return BMODEL_FULLY_CLIPPED; - - if (d <= clmodel->radius) - clipflags |= (1<model->type) - { - case mod_brush: - - clmodel = currententity->model; - - // see if the bounding box lets us trivially reject, also sets - // trivial accept status - for (j=0 ; j<3 ; j++) - { - minmaxs[j] = currententity->origin[j] + - clmodel->mins[j]; - minmaxs[3+j] = currententity->origin[j] + - clmodel->maxs[j]; - } - - clipflags = R_BmodelCheckBBox (clmodel, minmaxs); - - if (clipflags != BMODEL_FULLY_CLIPPED) - { - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - // FIXME: is this needed? - VectorCopy (modelorg, r_worldmodelorg); - - r_pcurrentvertbase = clmodel->vertexes; - - // FIXME: stop transforming twice - R_RotateBmodel (); - - // calculate dynamic lighting for bmodel if it's not an - // instanced model - if (clmodel->firstmodelsurface != 0) - { - for (k=0 ; knodes + clmodel->hulls[0].firstclipnode); - } - } - - // if the driver wants polygons, deliver those. Z-buffering is on - // at this point, so no clipping to the world tree is needed, just - // frustum clipping - if (r_drawpolys | r_drawculledpolys) - { - R_ZDrawSubmodelPolys (clmodel); - } - else - { - r_pefragtopnode = NULL; - - for (j=0 ; j<3 ; j++) - { - r_emins[j] = minmaxs[j]; - r_emaxs[j] = minmaxs[3+j]; - } - - R_SplitEntityOnNode2 (cl.worldmodel->nodes); - - if (r_pefragtopnode) - { - currententity->topnode = r_pefragtopnode; - - if (r_pefragtopnode->contents >= 0) - { - // not a leaf; has to be clipped to the world BSP - r_clipflags = clipflags; - R_DrawSolidClippedSubmodelPolygons (clmodel); - } - else - { - // falls entirely in one leaf, so we just put all the - // edges in the edge list and let 1/z sorting handle - // drawing order - R_DrawSubmodelPolygons (clmodel, clipflags); - } - - currententity->topnode = NULL; - } - } - - // put back world rotation and frustum clipping - // FIXME: R_RotateBmodel should just work off base_vxx - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (base_modelorg, modelorg); - VectorCopy (oldorigin, modelorg); - R_TransformFrustum (); - } - - break; - - default: - break; - } - } - - insubmodel = false; -} - - -/* -================ -R_EdgeDrawing -================ -*/ -void R_EdgeDrawing (void) -{ - edge_t ledges[NUMSTACKEDGES + - ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1]; - surf_t lsurfs[NUMSTACKSURFACES + - ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1]; - - if (auxedges) - { - r_edges = auxedges; - } - else - { - r_edges = (edge_t *) - (((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - } - - if (r_surfsonstack) - { - surfaces = (surf_t *) - (((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); - surf_max = &surfaces[r_cnumsurfs]; - // surface 0 doesn't really exist; it's just a dummy because index 0 - // is used to indicate no edge attached to surface - surfaces--; - R_SurfacePatch (); - } - - R_BeginEdgeFrame (); - - if (r_dspeeds.value) - { - rw_time1 = Sys_FloatTime (); - } - - R_RenderWorld (); - - if (r_drawculledpolys) - R_ScanEdges (); - -// only the world can be drawn back to front with no z reads or compares, just -// z writes, so have the driver turn z compares on now - D_TurnZOn (); - - if (r_dspeeds.value) - { - rw_time2 = Sys_FloatTime (); - db_time1 = rw_time2; - } - - R_DrawBEntitiesOnList (); - - if (r_dspeeds.value) - { - db_time2 = Sys_FloatTime (); - se_time1 = db_time2; - } - - if (!r_dspeeds.value) - { - VID_UnlockBuffer (); - S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); - } - - if (!(r_drawpolys | r_drawculledpolys)) - R_ScanEdges (); -} - - -/* -================ -R_RenderView - -r_refdef must be set before the first call -================ -*/ -void R_RenderView_ (void) -{ - byte warpbuffer[WARP_WIDTH * WARP_HEIGHT]; - - r_warpbuffer = warpbuffer; - - if (r_timegraph.value || r_speeds.value || r_dspeeds.value) - r_time1 = Sys_FloatTime (); - - R_SetupFrame (); - -#ifdef PASSAGES -SetVisibilityByPassages (); -#else - R_MarkLeaves (); // done here so we know if we're in water -#endif - -// make FDIV fast. This reduces timing precision after we've been running for a -// while, so we don't do it globally. This also sets chop mode, and we do it -// here so that setup stuff like the refresh area calculations match what's -// done in screen.c - Sys_LowFPPrecision (); - - if (!cl_entities[0].model || !cl.worldmodel) - Sys_Error ("R_RenderView: NULL worldmodel"); - - if (!r_dspeeds.value) - { - VID_UnlockBuffer (); - S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); - } - - R_EdgeDrawing (); - - if (!r_dspeeds.value) - { - VID_UnlockBuffer (); - S_ExtraUpdate (); // don't let sound get messed up if going slow - VID_LockBuffer (); - } - - if (r_dspeeds.value) - { - se_time2 = Sys_FloatTime (); - de_time1 = se_time2; - } - - R_DrawEntitiesOnList (); - - if (r_dspeeds.value) - { - de_time2 = Sys_FloatTime (); - dv_time1 = de_time2; - } - - R_DrawViewModel (); - - if (r_dspeeds.value) - { - dv_time2 = Sys_FloatTime (); - dp_time1 = Sys_FloatTime (); - } - - R_DrawParticles (); - - if (r_dspeeds.value) - dp_time2 = Sys_FloatTime (); - - if (r_dowarp) - D_WarpScreen (); - - V_SetContentsColor (r_viewleaf->contents); - - if (r_timegraph.value) - R_TimeGraph (); - - if (r_aliasstats.value) - R_PrintAliasStats (); - - if (r_speeds.value) - R_PrintTimes (); - - if (r_dspeeds.value) - R_PrintDSpeeds (); - - if (r_reportsurfout.value && r_outofsurfaces) - Con_Printf ("Short %d surfaces\n", r_outofsurfaces); - - if (r_reportedgeout.value && r_outofedges) - Con_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3); - -// back to high floating-point precision - Sys_HighFPPrecision (); -} - -void R_RenderView (void) -{ - int dummy; - int delta; - - delta = (byte *)&dummy - r_stack_start; - if (delta < -10000 || delta > 10000) - Sys_Error ("R_RenderView: called without enough stack"); - - if ( Hunk_LowMark() & 3 ) - Sys_Error ("Hunk is missaligned"); - - if ( (long)(&dummy) & 3 ) - Sys_Error ("Stack is missaligned"); - - if ( (long)(&r_warpbuffer) & 3 ) - Sys_Error ("Globals are missaligned"); - - R_RenderView_ (); -} - -/* -================ -R_InitTurb -================ -*/ -void R_InitTurb (void) -{ - int i; - - for (i=0 ; i<(SIN_BUFFER_SIZE) ; i++) - { - sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP; - intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2; // AMP2, not 20 - } -} - +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// r_main.c + +#include "quakedef.h" +#include "r_local.h" + +//define PASSAGES + +void *colormap; +vec3_t viewlightvec; +alight_t r_viewlighting = {128, 192, viewlightvec}; +float r_time1; +int r_numallocatededges; +qboolean r_drawpolys; +qboolean r_drawculledpolys; +qboolean r_worldpolysbacktofront; +qboolean r_recursiveaffinetriangles = true; +int r_pixbytes = 1; +float r_aliasuvscale = 1.0; +int r_outofsurfaces; +int r_outofedges; + +qboolean r_dowarp, r_dowarpold, r_viewchanged; + +int numbtofpolys; +btofpoly_t *pbtofpolys; +mvertex_t *r_pcurrentvertbase; + +int c_surf; +int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; +qboolean r_surfsonstack; +int r_clipflags; + +byte *r_warpbuffer; + +byte *r_stack_start; + +qboolean r_fov_greater_than_90; + +// +// view origin +// +vec3_t vup, base_vup; +vec3_t vpn, base_vpn; +vec3_t vright, base_vright; +vec3_t r_origin; + +// +// screen size info +// +refdef_t r_refdef; +float xcenter, ycenter; +float xscale, yscale; +float xscaleinv, yscaleinv; +float xscaleshrink, yscaleshrink; +float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; + +int screenwidth; + +float pixelAspect; +float screenAspect; +float verticalFieldOfView; +float xOrigin, yOrigin; + +mplane_t screenedge[4]; + +// +// refresh flags +// +int r_framecount = 1; // so frame counts initialized to 0 don't match +int r_visframecount; +int d_spanpixcount; +int r_polycount; +int r_drawnpolycount; +int r_wholepolycount; + +#define VIEWMODNAME_LENGTH 256 +char viewmodname[VIEWMODNAME_LENGTH+1]; +int modcount; + +int *pfrustum_indexes[4]; +int r_frustum_indexes[4*6]; + +int reinit_surfcache = 1; // if 1, surface cache is currently empty and + // must be reinitialized for current cache size + +mleaf_t *r_viewleaf, *r_oldviewleaf; + +texture_t *r_notexture_mip; + +float r_aliastransition, r_resfudge; + +int d_lightstylevalue[256]; // 8.8 fraction of base light value + +float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; +float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; + +void R_MarkLeaves (void); + +cvar_t r_draworder = {"r_draworder","0"}; +cvar_t r_speeds = {"r_speeds","0"}; +cvar_t r_timegraph = {"r_timegraph","0"}; +cvar_t r_graphheight = {"r_graphheight","10"}; +cvar_t r_clearcolor = {"r_clearcolor","2"}; +cvar_t r_waterwarp = {"r_waterwarp","1"}; +cvar_t r_fullbright = {"r_fullbright","0"}; +cvar_t r_drawentities = {"r_drawentities","1"}; +cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; +cvar_t r_aliasstats = {"r_polymodelstats","0"}; +cvar_t r_dspeeds = {"r_dspeeds","0"}; +cvar_t r_drawflat = {"r_drawflat", "0"}; +cvar_t r_ambient = {"r_ambient", "0"}; +cvar_t r_reportsurfout = {"r_reportsurfout", "0"}; +cvar_t r_maxsurfs = {"r_maxsurfs", "0"}; +cvar_t r_numsurfs = {"r_numsurfs", "0"}; +cvar_t r_reportedgeout = {"r_reportedgeout", "0"}; +cvar_t r_maxedges = {"r_maxedges", "0"}; +cvar_t r_numedges = {"r_numedges", "0"}; +cvar_t r_aliastransbase = {"r_aliastransbase", "200"}; +cvar_t r_aliastransadj = {"r_aliastransadj", "100"}; + +extern cvar_t scr_fov; + +void CreatePassages (void); +void SetVisibilityByPassages (void); + +/* +================== +R_InitTextures +================== +*/ +void R_InitTextures (void) +{ + int x,y, m; + byte *dest; + +// create a simple checkerboard texture for the default + r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture"); + + r_notexture_mip->width = r_notexture_mip->height = 16; + r_notexture_mip->offsets[0] = sizeof(texture_t); + r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16; + r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8; + r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4; + + for (m=0 ; m<4 ; m++) + { + dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m]; + for (y=0 ; y< (16>>m) ; y++) + for (x=0 ; x< (16>>m) ; x++) + { + if ( (y< (8>>m) ) ^ (x< (8>>m) ) ) + *dest++ = 0; + else + *dest++ = 0xff; + } + } +} + +/* +=============== +R_Init +=============== +*/ +void R_Init (void) +{ + int dummy; + +// get stack position so we can guess if we are going to overflow + r_stack_start = (byte *)&dummy; + + R_InitTurb (); + + Cmd_AddCommand ("timerefresh", R_TimeRefresh_f); + Cmd_AddCommand ("pointfile", R_ReadPointFile_f); + + Cvar_RegisterVariable (&r_draworder); + Cvar_RegisterVariable (&r_speeds); + Cvar_RegisterVariable (&r_timegraph); + Cvar_RegisterVariable (&r_graphheight); + Cvar_RegisterVariable (&r_drawflat); + Cvar_RegisterVariable (&r_ambient); + Cvar_RegisterVariable (&r_clearcolor); + Cvar_RegisterVariable (&r_waterwarp); + Cvar_RegisterVariable (&r_fullbright); + Cvar_RegisterVariable (&r_drawentities); + Cvar_RegisterVariable (&r_drawviewmodel); + Cvar_RegisterVariable (&r_aliasstats); + Cvar_RegisterVariable (&r_dspeeds); + Cvar_RegisterVariable (&r_reportsurfout); + Cvar_RegisterVariable (&r_maxsurfs); + Cvar_RegisterVariable (&r_numsurfs); + Cvar_RegisterVariable (&r_reportedgeout); + Cvar_RegisterVariable (&r_maxedges); + Cvar_RegisterVariable (&r_numedges); + Cvar_RegisterVariable (&r_aliastransbase); + Cvar_RegisterVariable (&r_aliastransadj); + + Cvar_SetValue ("r_maxedges", (float)NUMSTACKEDGES); + Cvar_SetValue ("r_maxsurfs", (float)NUMSTACKSURFACES); + + view_clipplanes[0].leftedge = true; + view_clipplanes[1].rightedge = true; + view_clipplanes[1].leftedge = view_clipplanes[2].leftedge = + view_clipplanes[3].leftedge = false; + view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = + view_clipplanes[3].rightedge = false; + + r_refdef.xOrigin = XCENTERING; + r_refdef.yOrigin = YCENTERING; + + R_InitParticles (); + +// TODO: collect 386-specific code in one place +#if id386 + Sys_MakeCodeWriteable ((long)R_EdgeCodeStart, + (long)R_EdgeCodeEnd - (long)R_EdgeCodeStart); +#endif // id386 + + D_Init (); +} + +/* +=============== +R_NewMap +=============== +*/ +void R_NewMap (void) +{ + int i; + +// clear out efrags in case the level hasn't been reloaded +// FIXME: is this one short? + for (i=0 ; inumleafs ; i++) + cl.worldmodel->leafs[i].efrags = NULL; + + r_viewleaf = NULL; + R_ClearParticles (); + + r_cnumsurfs = r_maxsurfs.value; + + if (r_cnumsurfs <= MINSURFACES) + r_cnumsurfs = MINSURFACES; + + if (r_cnumsurfs > NUMSTACKSURFACES) + { + surfaces = Hunk_AllocName (r_cnumsurfs * sizeof(surf_t), "surfaces"); + surface_p = surfaces; + surf_max = &surfaces[r_cnumsurfs]; + r_surfsonstack = false; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } + else + { + r_surfsonstack = true; + } + + r_maxedgesseen = 0; + r_maxsurfsseen = 0; + + r_numallocatededges = r_maxedges.value; + + if (r_numallocatededges < MINEDGES) + r_numallocatededges = MINEDGES; + + if (r_numallocatededges <= NUMSTACKEDGES) + { + auxedges = NULL; + } + else + { + auxedges = Hunk_AllocName (r_numallocatededges * sizeof(edge_t), + "edges"); + } + + r_dowarpold = false; + r_viewchanged = false; +#ifdef PASSAGES +CreatePassages (); +#endif +} + + +/* +=============== +R_SetVrect +=============== +*/ +void R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) +{ + int h; + float size; + + size = scr_viewsize.value > 100 ? 100 : scr_viewsize.value; + if (cl.intermission) + { + size = 100; + lineadj = 0; + } + size /= 100; + + h = pvrectin->height - lineadj; + pvrect->width = pvrectin->width * size; + if (pvrect->width < 96) + { + size = 96.0 / pvrectin->width; + pvrect->width = 96; // min for icons + } + pvrect->width &= ~7; + pvrect->height = pvrectin->height * size; + if (pvrect->height > pvrectin->height - lineadj) + pvrect->height = pvrectin->height - lineadj; + + pvrect->height &= ~1; + + pvrect->x = (pvrectin->width - pvrect->width)/2; + pvrect->y = (h - pvrect->height)/2; + + { + if (lcd_x.value) + { + pvrect->y >>= 1; + pvrect->height >>= 1; + } + } +} + + +/* +=============== +R_ViewChanged + +Called every time the vid structure or r_refdef changes. +Guaranteed to be called before the first refresh +=============== +*/ +void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) +{ + int i; + float res_scale; + + r_viewchanged = true; + + R_SetVrect (pvrect, &r_refdef.vrect, lineadj); + + r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x/360*M_PI); + r_refdef.fvrectx = (float)r_refdef.vrect.x; + r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5; + r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1; + r_refdef.fvrecty = (float)r_refdef.vrect.y; + r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5; + r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; + r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1; + r_refdef.fvrectright = (float)r_refdef.vrectright; + r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5; + r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99; + r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; + r_refdef.fvrectbottom = (float)r_refdef.vrectbottom; + r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5; + + r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale); + r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale); + r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale); + r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale); + r_refdef.aliasvrectright = r_refdef.aliasvrect.x + + r_refdef.aliasvrect.width; + r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + + r_refdef.aliasvrect.height; + + pixelAspect = aspect; + xOrigin = r_refdef.xOrigin; + yOrigin = r_refdef.yOrigin; + + screenAspect = r_refdef.vrect.width*pixelAspect / + r_refdef.vrect.height; +// 320*200 1.0 pixelAspect = 1.6 screenAspect +// 320*240 1.0 pixelAspect = 1.3333 screenAspect +// proper 320*200 pixelAspect = 0.8333333 + + verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; + +// values for perspective projection +// if math were exact, the values would range from 0.5 to to range+0.5 +// hopefully they wll be in the 0.000001 to range+.999999 and truncate +// the polygon rasterization will never render in the first row or column +// but will definately render in the [range] row and column, so adjust the +// buffer origin to get an exact edge to edge fill + xcenter = ((float)r_refdef.vrect.width * XCENTERING) + + r_refdef.vrect.x - 0.5; + aliasxcenter = xcenter * r_aliasuvscale; + ycenter = ((float)r_refdef.vrect.height * YCENTERING) + + r_refdef.vrect.y - 0.5; + aliasycenter = ycenter * r_aliasuvscale; + + xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; + aliasxscale = xscale * r_aliasuvscale; + xscaleinv = 1.0 / xscale; + yscale = xscale * pixelAspect; + aliasyscale = yscale * r_aliasuvscale; + yscaleinv = 1.0 / yscale; + xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView; + yscaleshrink = xscaleshrink*pixelAspect; + +// left side clip + screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView); + screenedge[0].normal[1] = 0; + screenedge[0].normal[2] = 1; + screenedge[0].type = PLANE_ANYZ; + +// right side clip + screenedge[1].normal[0] = + 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView); + screenedge[1].normal[1] = 0; + screenedge[1].normal[2] = 1; + screenedge[1].type = PLANE_ANYZ; + +// top side clip + screenedge[2].normal[0] = 0; + screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); + screenedge[2].normal[2] = 1; + screenedge[2].type = PLANE_ANYZ; + +// bottom side clip + screenedge[3].normal[0] = 0; + screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); + screenedge[3].normal[2] = 1; + screenedge[3].type = PLANE_ANYZ; + + for (i=0 ; i<4 ; i++) + VectorNormalize (screenedge[i].normal); + + res_scale = sqrt ((double)(r_refdef.vrect.width * r_refdef.vrect.height) / + (320.0 * 152.0)) * + (2.0 / r_refdef.horizontalFieldOfView); + r_aliastransition = r_aliastransbase.value * res_scale; + r_resfudge = r_aliastransadj.value * res_scale; + + if (scr_fov.value <= 90.0) + r_fov_greater_than_90 = false; + else + r_fov_greater_than_90 = true; + +// TODO: collect 386-specific code in one place +#if id386 + if (r_pixbytes == 1) + { + Sys_MakeCodeWriteable ((long)R_Surf8Start, + (long)R_Surf8End - (long)R_Surf8Start); + colormap = vid.colormap; + R_Surf8Patch (); + } + else + { + Sys_MakeCodeWriteable ((long)R_Surf16Start, + (long)R_Surf16End - (long)R_Surf16Start); + colormap = vid.colormap16; + R_Surf16Patch (); + } +#endif // id386 + + D_ViewChanged (); +} + + +/* +=============== +R_MarkLeaves +=============== +*/ +void R_MarkLeaves (void) +{ + byte *vis; + mnode_t *node; + int i; + + if (r_oldviewleaf == r_viewleaf) + return; + + r_visframecount++; + r_oldviewleaf = r_viewleaf; + + vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); + + for (i=0 ; inumleafs ; i++) + { + if (vis[i>>3] & (1<<(i&7))) + { + node = (mnode_t *)&cl.worldmodel->leafs[i+1]; + do + { + if (node->visframe == r_visframecount) + break; + node->visframe = r_visframecount; + node = node->parent; + } while (node); + } + } +} + + +/* +============= +R_DrawEntitiesOnList +============= +*/ +void R_DrawEntitiesOnList (void) +{ + int i, j; + int lnum; + alight_t lighting; +// FIXME: remove and do real lighting + float lightvec[3] = {-1, 0, 0}; + vec3_t dist; + float add; + + if (!r_drawentities.value) + return; + + for (i=0 ; imodel->type) + { + case mod_sprite: + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + R_DrawSprite (); + break; + + case mod_alias: + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + // see if the bounding box lets us trivially reject, also sets + // trivial accept status + if (R_AliasCheckBBox ()) + { + j = R_LightPoint (currententity->origin); + + lighting.ambientlight = j; + lighting.shadelight = j; + + lighting.plightvec = lightvec; + + for (lnum=0 ; lnum= cl.time) + { + VectorSubtract (currententity->origin, + cl_dlights[lnum].origin, + dist); + add = cl_dlights[lnum].radius - Length(dist); + + if (add > 0) + lighting.ambientlight += add; + } + } + + // clamp lighting so it doesn't overbright as much + if (lighting.ambientlight > 128) + lighting.ambientlight = 128; + if (lighting.ambientlight + lighting.shadelight > 192) + lighting.shadelight = 192 - lighting.ambientlight; + + R_AliasDrawModel (&lighting); + } + + break; + + default: + break; + } + } +} + +/* +============= +R_DrawViewModel +============= +*/ +void R_DrawViewModel (void) +{ +// FIXME: remove and do real lighting + float lightvec[3] = {-1, 0, 0}; + int j; + int lnum; + vec3_t dist; + float add; + dlight_t *dl; + + if (!r_drawviewmodel.value || r_fov_greater_than_90) + return; + + if (cl.items & IT_INVISIBILITY) + return; + + if (cl.stats[STAT_HEALTH] <= 0) + return; + + currententity = &cl.viewent; + if (!currententity->model) + return; + + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + VectorCopy (vup, viewlightvec); + VectorInverse (viewlightvec); + + j = R_LightPoint (currententity->origin); + + if (j < 24) + j = 24; // allways give some light on gun + r_viewlighting.ambientlight = j; + r_viewlighting.shadelight = j; + +// add dynamic lights + for (lnum=0 ; lnumradius) + continue; + if (!dl->radius) + continue; + if (dl->die < cl.time) + continue; + + VectorSubtract (currententity->origin, dl->origin, dist); + add = dl->radius - Length(dist); + if (add > 0) + r_viewlighting.ambientlight += add; + } + +// clamp lighting so it doesn't overbright as much + if (r_viewlighting.ambientlight > 128) + r_viewlighting.ambientlight = 128; + if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192) + r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight; + + r_viewlighting.plightvec = lightvec; + +#ifdef QUAKE2 + cl.light_level = r_viewlighting.ambientlight; +#endif + + R_AliasDrawModel (&r_viewlighting); +} + + +/* +============= +R_BmodelCheckBBox +============= +*/ +int R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) +{ + int i, *pindex, clipflags; + vec3_t acceptpt, rejectpt; + double d; + + clipflags = 0; + + if (currententity->angles[0] || currententity->angles[1] + || currententity->angles[2]) + { + for (i=0 ; i<4 ; i++) + { + d = DotProduct (currententity->origin, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= -clmodel->radius) + return BMODEL_FULLY_CLIPPED; + + if (d <= clmodel->radius) + clipflags |= (1<model->type) + { + case mod_brush: + + clmodel = currententity->model; + + // see if the bounding box lets us trivially reject, also sets + // trivial accept status + for (j=0 ; j<3 ; j++) + { + minmaxs[j] = currententity->origin[j] + + clmodel->mins[j]; + minmaxs[3+j] = currententity->origin[j] + + clmodel->maxs[j]; + } + + clipflags = R_BmodelCheckBBox (clmodel, minmaxs); + + if (clipflags != BMODEL_FULLY_CLIPPED) + { + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + // FIXME: is this needed? + VectorCopy (modelorg, r_worldmodelorg); + + r_pcurrentvertbase = clmodel->vertexes; + + // FIXME: stop transforming twice + R_RotateBmodel (); + + // calculate dynamic lighting for bmodel if it's not an + // instanced model + if (clmodel->firstmodelsurface != 0) + { + for (k=0 ; knodes + clmodel->hulls[0].firstclipnode); + } + } + + // if the driver wants polygons, deliver those. Z-buffering is on + // at this point, so no clipping to the world tree is needed, just + // frustum clipping + if (r_drawpolys | r_drawculledpolys) + { + R_ZDrawSubmodelPolys (clmodel); + } + else + { + r_pefragtopnode = NULL; + + for (j=0 ; j<3 ; j++) + { + r_emins[j] = minmaxs[j]; + r_emaxs[j] = minmaxs[3+j]; + } + + R_SplitEntityOnNode2 (cl.worldmodel->nodes); + + if (r_pefragtopnode) + { + currententity->topnode = r_pefragtopnode; + + if (r_pefragtopnode->contents >= 0) + { + // not a leaf; has to be clipped to the world BSP + r_clipflags = clipflags; + R_DrawSolidClippedSubmodelPolygons (clmodel); + } + else + { + // falls entirely in one leaf, so we just put all the + // edges in the edge list and let 1/z sorting handle + // drawing order + R_DrawSubmodelPolygons (clmodel, clipflags); + } + + currententity->topnode = NULL; + } + } + + // put back world rotation and frustum clipping + // FIXME: R_RotateBmodel should just work off base_vxx + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (base_modelorg, modelorg); + VectorCopy (oldorigin, modelorg); + R_TransformFrustum (); + } + + break; + + default: + break; + } + } + + insubmodel = false; +} + + +/* +================ +R_EdgeDrawing +================ +*/ +void R_EdgeDrawing (void) +{ + edge_t ledges[NUMSTACKEDGES + + ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1]; + surf_t lsurfs[NUMSTACKSURFACES + + ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1]; + + if (auxedges) + { + r_edges = auxedges; + } + else + { + r_edges = (edge_t *) + (((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + } + + if (r_surfsonstack) + { + surfaces = (surf_t *) + (((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + surf_max = &surfaces[r_cnumsurfs]; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } + + R_BeginEdgeFrame (); + + if (r_dspeeds.value) + { + rw_time1 = Sys_FloatTime (); + } + + R_RenderWorld (); + + if (r_drawculledpolys) + R_ScanEdges (); + +// only the world can be drawn back to front with no z reads or compares, just +// z writes, so have the driver turn z compares on now + D_TurnZOn (); + + if (r_dspeeds.value) + { + rw_time2 = Sys_FloatTime (); + db_time1 = rw_time2; + } + + R_DrawBEntitiesOnList (); + + if (r_dspeeds.value) + { + db_time2 = Sys_FloatTime (); + se_time1 = db_time2; + } + + if (!r_dspeeds.value) + { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + } + + if (!(r_drawpolys | r_drawculledpolys)) + R_ScanEdges (); +} + + +/* +================ +R_RenderView + +r_refdef must be set before the first call +================ +*/ +void R_RenderView_ (void) +{ + byte warpbuffer[WARP_WIDTH * WARP_HEIGHT]; + + r_warpbuffer = warpbuffer; + + if (r_timegraph.value || r_speeds.value || r_dspeeds.value) + r_time1 = Sys_FloatTime (); + + R_SetupFrame (); + +#ifdef PASSAGES +SetVisibilityByPassages (); +#else + R_MarkLeaves (); // done here so we know if we're in water +#endif + +// make FDIV fast. This reduces timing precision after we've been running for a +// while, so we don't do it globally. This also sets chop mode, and we do it +// here so that setup stuff like the refresh area calculations match what's +// done in screen.c + Sys_LowFPPrecision (); + + if (!cl_entities[0].model || !cl.worldmodel) + Sys_Error ("R_RenderView: NULL worldmodel"); + + if (!r_dspeeds.value) + { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + } + + R_EdgeDrawing (); + + if (!r_dspeeds.value) + { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + } + + if (r_dspeeds.value) + { + se_time2 = Sys_FloatTime (); + de_time1 = se_time2; + } + + R_DrawEntitiesOnList (); + + if (r_dspeeds.value) + { + de_time2 = Sys_FloatTime (); + dv_time1 = de_time2; + } + + R_DrawViewModel (); + + if (r_dspeeds.value) + { + dv_time2 = Sys_FloatTime (); + dp_time1 = Sys_FloatTime (); + } + + R_DrawParticles (); + + if (r_dspeeds.value) + dp_time2 = Sys_FloatTime (); + + if (r_dowarp) + D_WarpScreen (); + + V_SetContentsColor (r_viewleaf->contents); + + if (r_timegraph.value) + R_TimeGraph (); + + if (r_aliasstats.value) + R_PrintAliasStats (); + + if (r_speeds.value) + R_PrintTimes (); + + if (r_dspeeds.value) + R_PrintDSpeeds (); + + if (r_reportsurfout.value && r_outofsurfaces) + Con_Printf ("Short %d surfaces\n", r_outofsurfaces); + + if (r_reportedgeout.value && r_outofedges) + Con_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3); + +// back to high floating-point precision + Sys_HighFPPrecision (); +} + +void R_RenderView (void) +{ + int dummy; + int delta; + + delta = (byte *)&dummy - r_stack_start; + if (delta < -10000 || delta > 10000) + Sys_Error ("R_RenderView: called without enough stack"); + + if ( Hunk_LowMark() & 3 ) + Sys_Error ("Hunk is missaligned"); + + if ( (long)(&dummy) & 3 ) + Sys_Error ("Stack is missaligned"); + + if ( (long)(&r_warpbuffer) & 3 ) + Sys_Error ("Globals are missaligned"); + + R_RenderView_ (); +} + +/* +================ +R_InitTurb +================ +*/ +void R_InitTurb (void) +{ + int i; + + for (i=0 ; i<(SIN_BUFFER_SIZE) ; i++) + { + sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP; + intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2; // AMP2, not 20 + } +} + -- cgit v1.2.3