diff options
| author | wyatt8740 <wyatt8740@yahoo.com> | 2014-01-06 12:02:16 -0500 |
|---|---|---|
| committer | wyatt8740 <wyatt8740@yahoo.com> | 2014-01-06 12:02:16 -0500 |
| commit | a8f828a066773a59fdf646299359d35ae0e845af (patch) | |
| tree | 86123409fc6f231cf4136e81159b63cb1e9ec102 /WinQuake/r_main.c | |
| parent | b2951690415054ae8705c07f8df7a4ba7cde382a (diff) | |
| download | quake-pum-a8f828a066773a59fdf646299359d35ae0e845af.tar.gz | |
Removed accidental upload of copyrighted map files
Diffstat (limited to 'WinQuake/r_main.c')
| -rw-r--r-- | WinQuake/r_main.c | 2170 |
1 files changed, 1085 insertions, 1085 deletions
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 ; i<cl.worldmodel->numleafs ; 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 ; i<cl.worldmodel->numleafs ; 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 ; i<cl_numvisedicts ; i++) - { - currententity = cl_visedicts[i]; - - if (currententity == &cl_entities[cl.viewentity]) - continue; // don't draw the player - - switch (currententity->model->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<MAX_DLIGHTS ; lnum++) - { - if (cl_dlights[lnum].die >= 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 ; lnum<MAX_DLIGHTS ; lnum++) - { - dl = &cl_dlights[lnum]; - if (!dl->radius) - 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<<i); - } - } - else - { - for (i=0 ; i<4 ; i++) - { - // generate accept and reject points - // FIXME: do with fast look-ups or integer tests based on the sign bit - // of the floating point values - - pindex = pfrustum_indexes[i]; - - rejectpt[0] = minmaxs[pindex[0]]; - rejectpt[1] = minmaxs[pindex[1]]; - rejectpt[2] = minmaxs[pindex[2]]; - - d = DotProduct (rejectpt, view_clipplanes[i].normal); - d -= view_clipplanes[i].dist; - - if (d <= 0) - return BMODEL_FULLY_CLIPPED; - - acceptpt[0] = minmaxs[pindex[3+0]]; - acceptpt[1] = minmaxs[pindex[3+1]]; - acceptpt[2] = minmaxs[pindex[3+2]]; - - d = DotProduct (acceptpt, view_clipplanes[i].normal); - d -= view_clipplanes[i].dist; - - if (d <= 0) - clipflags |= (1<<i); - } - } - - return clipflags; -} - - -/* -============= -R_DrawBEntitiesOnList -============= -*/ -void R_DrawBEntitiesOnList (void) -{ - int i, j, k, clipflags; - vec3_t oldorigin; - model_t *clmodel; - float minmaxs[6]; - - if (!r_drawentities.value) - return; - - VectorCopy (modelorg, oldorigin); - insubmodel = true; - r_dlightframecount = r_framecount; - - for (i=0 ; i<cl_numvisedicts ; i++) - { - currententity = cl_visedicts[i]; - - switch (currententity->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 ; k<MAX_DLIGHTS ; k++) - { - if ((cl_dlights[k].die < cl.time) || - (!cl_dlights[k].radius)) - { - continue; - } - - R_MarkLights (&cl_dlights[k], 1<<k, - clmodel->nodes + 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 ; i<cl.worldmodel->numleafs ; 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 ; i<cl.worldmodel->numleafs ; 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 ; i<cl_numvisedicts ; i++)
+ {
+ currententity = cl_visedicts[i];
+
+ if (currententity == &cl_entities[cl.viewentity])
+ continue; // don't draw the player
+
+ switch (currententity->model->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<MAX_DLIGHTS ; lnum++)
+ {
+ if (cl_dlights[lnum].die >= 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 ; lnum<MAX_DLIGHTS ; lnum++)
+ {
+ dl = &cl_dlights[lnum];
+ if (!dl->radius)
+ 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<<i);
+ }
+ }
+ else
+ {
+ for (i=0 ; i<4 ; i++)
+ {
+ // generate accept and reject points
+ // FIXME: do with fast look-ups or integer tests based on the sign bit
+ // of the floating point values
+
+ pindex = pfrustum_indexes[i];
+
+ rejectpt[0] = minmaxs[pindex[0]];
+ rejectpt[1] = minmaxs[pindex[1]];
+ rejectpt[2] = minmaxs[pindex[2]];
+
+ d = DotProduct (rejectpt, view_clipplanes[i].normal);
+ d -= view_clipplanes[i].dist;
+
+ if (d <= 0)
+ return BMODEL_FULLY_CLIPPED;
+
+ acceptpt[0] = minmaxs[pindex[3+0]];
+ acceptpt[1] = minmaxs[pindex[3+1]];
+ acceptpt[2] = minmaxs[pindex[3+2]];
+
+ d = DotProduct (acceptpt, view_clipplanes[i].normal);
+ d -= view_clipplanes[i].dist;
+
+ if (d <= 0)
+ clipflags |= (1<<i);
+ }
+ }
+
+ return clipflags;
+}
+
+
+/*
+=============
+R_DrawBEntitiesOnList
+=============
+*/
+void R_DrawBEntitiesOnList (void)
+{
+ int i, j, k, clipflags;
+ vec3_t oldorigin;
+ model_t *clmodel;
+ float minmaxs[6];
+
+ if (!r_drawentities.value)
+ return;
+
+ VectorCopy (modelorg, oldorigin);
+ insubmodel = true;
+ r_dlightframecount = r_framecount;
+
+ for (i=0 ; i<cl_numvisedicts ; i++)
+ {
+ currententity = cl_visedicts[i];
+
+ switch (currententity->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 ; k<MAX_DLIGHTS ; k++)
+ {
+ if ((cl_dlights[k].die < cl.time) ||
+ (!cl_dlights[k].radius))
+ {
+ continue;
+ }
+
+ R_MarkLights (&cl_dlights[k], 1<<k,
+ clmodel->nodes + 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
+ }
+}
+
|
