diff options
Diffstat (limited to 'source/sw_misc.c')
-rw-r--r-- | source/sw_misc.c | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/source/sw_misc.c b/source/sw_misc.c new file mode 100644 index 0000000..c23db4a --- /dev/null +++ b/source/sw_misc.c @@ -0,0 +1,529 @@ +/* +Copyright (C) 1997-2001 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_misc.c + +#include "sw_local.h" + +#define NUM_MIPS 4 + +cvar_t *sw_mipcap; +cvar_t *sw_mipscale; + +surfcache_t *d_initial_rover; +qboolean d_roverwrapped; +int d_minmip; +float d_scalemip[NUM_MIPS-1]; + +static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8}; + +extern int d_aflatcolor; + +int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; + +int d_pix_min, d_pix_max, d_pix_shift; + +int d_scantable[MAXHEIGHT]; +short *zspantable[MAXHEIGHT]; + +/* +================ +D_Patch +================ +*/ +void D_Patch (void) +{ +#if USE_ASM + extern void D_Aff8Patch( void ); + static qboolean protectset8 = qfalse; + extern void D_PolysetAff8Start( void ); + + if (!protectset8) + { + Sys_MakeCodeWriteable ((int)D_PolysetAff8Start, + (int)D_Aff8Patch - (int)D_PolysetAff8Start); + Sys_MakeCodeWriteable ((long)R_Surf8Start, + (long)R_Surf8End - (long)R_Surf8Start); + protectset8 = qtrue; + } + + R_Surf8Patch (); + D_Aff8Patch(); +#endif +} +/* +================ +D_ViewChanged +================ +*/ +void D_ViewChanged (void) +{ + int i; + + scale_for_mip = xscale; + if (yscale > xscale) + scale_for_mip = yscale; + + d_zrowbytes = vid.width * 2; + d_zwidth = vid.width; + + d_pix_min = r_refdef.vrect.width / 320; + if (d_pix_min < 1) + d_pix_min = 1; + + d_pix_max = (int)((float)r_refdef.vrect.width / (320.0 / 4.0) + 0.5); + d_pix_shift = 8 - (int)((float)r_refdef.vrect.width / 320.0 + 0.5); + if (d_pix_max < 1) + d_pix_max = 1; + + d_vrectx = r_refdef.vrect.x; + d_vrecty = r_refdef.vrect.y; + d_vrectright_particle = r_refdef.vrectright - d_pix_max; + d_vrectbottom_particle = + r_refdef.vrectbottom - d_pix_max; + + for (i=0 ; i<vid.height; i++) + { + d_scantable[i] = i*r_screenwidth; + zspantable[i] = d_pzbuffer + i*d_zwidth; + } + + /* + ** clear Z-buffer and color-buffers if we're doing the gallery + */ + if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) + { + memset( d_pzbuffer, 0xff, vid.width * vid.height * sizeof( d_pzbuffer[0] ) ); + Draw_Fill( r_newrefdef.x, r_newrefdef.y, r_newrefdef.width, r_newrefdef.height, /*( int ) sw_clearcolor->value & 0xff*/0 ); + } + + D_Patch (); +} + + + +/* +============= +R_PrintTimes +============= +*/ +void R_PrintTimes (void) +{ + int r_time2; + int ms; + + r_time2 = sys.Milliseconds (); + + ms = r_time2 - r_time1; + + Com_Printf("%5i ms %3i/%3i/%3i poly %3i surf\n", + ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf); + c_surf = 0; +} + + +/* +============= +R_PrintDSpeeds +============= +*/ +void R_PrintDSpeeds (void) +{ + int ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, da_time; + + r_time2 = sys.Milliseconds (); + + da_time = (da_time2 - da_time1); + dp_time = (dp_time2 - dp_time1); + rw_time = (rw_time2 - rw_time1); + db_time = (db_time2 - db_time1); + se_time = (se_time2 - se_time1); + de_time = (de_time2 - de_time1); + ms = (r_time2 - r_time1); + + Com_Printf("%3i %2ip %2iw %2ib %2is %2ie %2ia\n", + ms, dp_time, rw_time, db_time, se_time, de_time, da_time); +} + + +/* +============= +R_PrintAliasStats +============= +*/ +void R_PrintAliasStats (void) +{ + Com_Printf("%3i polygon model drawn\n", r_amodels_drawn); +} + + + +/* +=================== +R_TransformFrustum +=================== +*/ +void R_TransformFrustum (void) +{ + int i; + vec3_t v, v2; + + for (i=0 ; i<4 ; i++) + { + v[0] = screenedge[i].normal[2]; + v[1] = -screenedge[i].normal[0]; + v[2] = screenedge[i].normal[1]; + + v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0]; + v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1]; + v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2]; + + VectorCopy (v2, view_clipplanes[i].normal); + + view_clipplanes[i].dist = DotProduct (modelorg, v2); + } +} + + +/* +================ +TransformVector +================ +*/ +void TransformVector (vec3_t in, vec3_t out) +{ + out[0] = DotProduct(in,vright); + out[1] = DotProduct(in,vup); + out[2] = DotProduct(in,vpn); +} + +/* +================ +R_TransformPlane +================ +*/ +void R_TransformPlane (mplane_t *p, float *normal, float *dist) +{ + float d; + + d = DotProduct (r_origin, p->normal); + *dist = p->dist - d; +// TODO: when we have rotating entities, this will need to use the view matrix + TransformVector (p->normal, normal); +} + + +/* +=============== +R_SetUpFrustumIndexes +=============== +*/ +void R_SetUpFrustumIndexes (void) +{ + int i, j, *pindex; + + pindex = r_frustum_indexes; + + for (i=0 ; i<4 ; i++) + { + for (j=0 ; j<3 ; j++) + { + if (view_clipplanes[i].normal[j] < 0) + { + pindex[j] = j; + pindex[j+3] = j+3; + } + else + { + pindex[j] = j+3; + pindex[j+3] = j; + } + } + + // FIXME: do just once at start + pfrustum_indexes[i] = pindex; + pindex += 6; + } +} + +/* +=============== +R_ViewChanged + +Called every time the vid structure or r_refdef changes. +Guaranteed to be called before the first refresh +=============== +*/ +void R_ViewChanged (vrectSoft_t *vr) +{ + int i; + + r_refdef.vrect = *vr; + + r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);; + verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/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; + + xOrigin = r_refdef.xOrigin; + yOrigin = r_refdef.yOrigin; + +// 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; + aliasyscale = yscale * r_aliasuvscale; + yscaleinv = 1.0 / yscale; + xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView; + yscaleshrink = xscaleshrink; + +// 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); + + D_ViewChanged (); +} + + +/* +=============== +R_SetupFrame +=============== +*/ +void R_SetupFrame (void) +{ + int i; + vrectSoft_t vrect; + + if (r_fullbright->modified) + { + r_fullbright->modified = qfalse; + D_FlushCaches (); // so all lighting changes + } + + r_framecount++; + + +// build the transformation matrix for the given view angles + VectorCopy (r_refdef.vieworg, modelorg); + VectorCopy (r_refdef.vieworg, r_origin); + + AngleVectors (r_refdef.viewangles, vpn, vright, vup); + +// current viewleaf + if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) ) + { + r_viewleaf = Mod_PointInLeaf (r_origin, r_worldmodel); + r_viewcluster = r_viewleaf->cluster; + } + + if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) ) + r_dowarp = qtrue; + else + r_dowarp = qfalse; + + if (r_dowarp) + { // warp into off screen buffer + vrect.x = 0; + vrect.y = 0; + vrect.width = r_newrefdef.width < WARP_WIDTH ? r_newrefdef.width : WARP_WIDTH; + vrect.height = r_newrefdef.height < WARP_HEIGHT ? r_newrefdef.height : WARP_HEIGHT; + + d_viewbuffer = r_warpbuffer; + r_screenwidth = WARP_WIDTH; + } + else + { + vrect.x = r_newrefdef.x; + vrect.y = r_newrefdef.y; + vrect.width = r_newrefdef.width; + vrect.height = r_newrefdef.height; + + d_viewbuffer = (void *)vid.buffer; + r_screenwidth = vid.rowbytes; + } + + R_ViewChanged (&vrect); + +// start off with just the four screen edge clip planes + R_TransformFrustum (); + R_SetUpFrustumIndexes (); + +// save base values + VectorCopy (vpn, base_vpn); + VectorCopy (vright, base_vright); + VectorCopy (vup, base_vup); + +// clear frame counts + c_faceclip = 0; + d_spanpixcount = 0; + r_polycount = 0; + r_drawnpolycount = 0; + r_wholepolycount = 0; + r_amodels_drawn = 0; + r_outofsurfaces = 0; + r_outofedges = 0; + +// d_setup + d_roverwrapped = qfalse; + d_initial_rover = sc_rover; + + d_minmip = sw_mipcap->value; + if (d_minmip > 3) + d_minmip = 3; + else if (d_minmip < 0) + d_minmip = 0; + + for (i=0 ; i<(NUM_MIPS-1) ; i++) + d_scalemip[i] = basemip[i] * sw_mipscale->value; + + d_aflatcolor = 0; +} + +/* +============================================================================== + + SCREEN SHOTS + +============================================================================== +*/ + +#if 0 + + + +/* +================== +R_ScreenShot_f +================== +*/ +void R_ScreenShot_f (void) +{ + int i; + char pcxname[80]; + char checkname[MAX_OSPATH]; + FILE *f; + byte palette[768]; + + // create the scrnshots directory if it doesn't exist + Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", fs.Gamedir()); + Sys_Mkdir (checkname); + +// +// find a file name to save it to +// + strcpy(pcxname,"quake00.pcx"); + + for (i=0 ; i<=99 ; i++) + { + pcxname[5] = i/10 + '0'; + pcxname[6] = i%10 + '0'; + Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", fs.Gamedir(), pcxname); + f = fopen (checkname, "r"); + if (!f) + break; // file doesn't exist + fclose (f); + } + if (i==100) + { + Com_Printf( "R_ScreenShot_f: Couldn't create a PCX"); + return; + } + + // turn the current 32 bit palette into a 24 bit palette + for (i=0 ; i<256 ; i++) + { + palette[i*3+0] = sw_state.currentpalette[i*4+0]; + palette[i*3+1] = sw_state.currentpalette[i*4+1]; + palette[i*3+2] = sw_state.currentpalette[i*4+2]; + } + +// +// save the pcx file +// + + WritePCXfile (checkname, vid.buffer, vid.width, vid.height, vid.rowbytes, + palette); + + Com_Printf( "Wrote %s\n", checkname); +} + +#else +void R_ScreenShot_f (void) {} +#endif + |