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/gl_rmain.c | 2318 +++++++++++++++++++++++++-------------------------- 1 file changed, 1159 insertions(+), 1159 deletions(-) (limited to 'WinQuake/gl_rmain.c') diff --git a/WinQuake/gl_rmain.c b/WinQuake/gl_rmain.c index d9bf41e..b760b71 100644 --- a/WinQuake/gl_rmain.c +++ b/WinQuake/gl_rmain.c @@ -1,1159 +1,1159 @@ -/* -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" - -entity_t r_worldentity; - -qboolean r_cache_thrash; // compatability - -vec3_t modelorg, r_entorigin; -entity_t *currententity; - -int r_visframecount; // bumped when going to a new PVS -int r_framecount; // used for dlight push checking - -mplane_t frustum[4]; - -int c_brush_polys, c_alias_polys; - -qboolean envmap; // true during envmap command capture - -int currenttexture = -1; // to avoid unnecessary texture sets - -int cnttextures[2] = {-1, -1}; // cached - -int particletexture; // little dot for particles -int playertextures; // up to 16 color translated skins - -int mirrortexturenum; // quake texturenum, not gltexturenum -qboolean mirror; -mplane_t *mirror_plane; - -// -// view origin -// -vec3_t vup; -vec3_t vpn; -vec3_t vright; -vec3_t r_origin; - -float r_world_matrix[16]; -float r_base_world_matrix[16]; - -// -// screen size info -// -refdef_t r_refdef; - -mleaf_t *r_viewleaf, *r_oldviewleaf; - -texture_t *r_notexture_mip; - -int d_lightstylevalue[256]; // 8.8 fraction of base light value - - -void R_MarkLeaves (void); - -cvar_t r_norefresh = {"r_norefresh","0"}; -cvar_t r_drawentities = {"r_drawentities","1"}; -cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; -cvar_t r_speeds = {"r_speeds","0"}; -cvar_t r_fullbright = {"r_fullbright","0"}; -cvar_t r_lightmap = {"r_lightmap","0"}; -cvar_t r_shadows = {"r_shadows","0"}; -cvar_t r_mirroralpha = {"r_mirroralpha","1"}; -cvar_t r_wateralpha = {"r_wateralpha","1"}; -cvar_t r_dynamic = {"r_dynamic","1"}; -cvar_t r_novis = {"r_novis","0"}; - -cvar_t gl_finish = {"gl_finish","0"}; -cvar_t gl_clear = {"gl_clear","0"}; -cvar_t gl_cull = {"gl_cull","1"}; -cvar_t gl_texsort = {"gl_texsort","1"}; -cvar_t gl_smoothmodels = {"gl_smoothmodels","1"}; -cvar_t gl_affinemodels = {"gl_affinemodels","0"}; -cvar_t gl_polyblend = {"gl_polyblend","1"}; -cvar_t gl_flashblend = {"gl_flashblend","1"}; -cvar_t gl_playermip = {"gl_playermip","0"}; -cvar_t gl_nocolors = {"gl_nocolors","0"}; -cvar_t gl_keeptjunctions = {"gl_keeptjunctions","0"}; -cvar_t gl_reporttjunctions = {"gl_reporttjunctions","0"}; -cvar_t gl_doubleeyes = {"gl_doubleeys", "1"}; - -extern cvar_t gl_ztrick; - -/* -================= -R_CullBox - -Returns true if the box is completely outside the frustom -================= -*/ -qboolean R_CullBox (vec3_t mins, vec3_t maxs) -{ - int i; - - for (i=0 ; i<4 ; i++) - if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2) - return true; - return false; -} - - -void R_RotateForEntity (entity_t *e) -{ - glTranslatef (e->origin[0], e->origin[1], e->origin[2]); - - glRotatef (e->angles[1], 0, 0, 1); - glRotatef (-e->angles[0], 0, 1, 0); - glRotatef (e->angles[2], 1, 0, 0); -} - -/* -============================================================= - - SPRITE MODELS - -============================================================= -*/ - -/* -================ -R_GetSpriteFrame -================ -*/ -mspriteframe_t *R_GetSpriteFrame (entity_t *currententity) -{ - msprite_t *psprite; - mspritegroup_t *pspritegroup; - mspriteframe_t *pspriteframe; - int i, numframes, frame; - float *pintervals, fullinterval, targettime, time; - - psprite = currententity->model->cache.data; - frame = currententity->frame; - - if ((frame >= psprite->numframes) || (frame < 0)) - { - Con_Printf ("R_DrawSprite: no such frame %d\n", frame); - frame = 0; - } - - if (psprite->frames[frame].type == SPR_SINGLE) - { - pspriteframe = psprite->frames[frame].frameptr; - } - else - { - pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; - pintervals = pspritegroup->intervals; - numframes = pspritegroup->numframes; - fullinterval = pintervals[numframes-1]; - - time = cl.time + currententity->syncbase; - - // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values - // are positive, so we don't have to worry about division by 0 - targettime = time - ((int)(time / fullinterval)) * fullinterval; - - for (i=0 ; i<(numframes-1) ; i++) - { - if (pintervals[i] > targettime) - break; - } - - pspriteframe = pspritegroup->frames[i]; - } - - return pspriteframe; -} - - -/* -================= -R_DrawSpriteModel - -================= -*/ -void R_DrawSpriteModel (entity_t *e) -{ - vec3_t point; - mspriteframe_t *frame; - float *up, *right; - vec3_t v_forward, v_right, v_up; - msprite_t *psprite; - - // don't even bother culling, because it's just a single - // polygon without a surface cache - frame = R_GetSpriteFrame (e); - psprite = currententity->model->cache.data; - - if (psprite->type == SPR_ORIENTED) - { // bullet marks on walls - AngleVectors (currententity->angles, v_forward, v_right, v_up); - up = v_up; - right = v_right; - } - else - { // normal sprite - up = vup; - right = vright; - } - - glColor3f (1,1,1); - - GL_DisableMultitexture(); - - GL_Bind(frame->gl_texturenum); - - glEnable (GL_ALPHA_TEST); - glBegin (GL_QUADS); - - glTexCoord2f (0, 1); - VectorMA (e->origin, frame->down, up, point); - VectorMA (point, frame->left, right, point); - glVertex3fv (point); - - glTexCoord2f (0, 0); - VectorMA (e->origin, frame->up, up, point); - VectorMA (point, frame->left, right, point); - glVertex3fv (point); - - glTexCoord2f (1, 0); - VectorMA (e->origin, frame->up, up, point); - VectorMA (point, frame->right, right, point); - glVertex3fv (point); - - glTexCoord2f (1, 1); - VectorMA (e->origin, frame->down, up, point); - VectorMA (point, frame->right, right, point); - glVertex3fv (point); - - glEnd (); - - glDisable (GL_ALPHA_TEST); -} - -/* -============================================================= - - ALIAS MODELS - -============================================================= -*/ - - -#define NUMVERTEXNORMALS 162 - -float r_avertexnormals[NUMVERTEXNORMALS][3] = { -#include "anorms.h" -}; - -vec3_t shadevector; -float shadelight, ambientlight; - -// precalculated dot products for quantized angles -#define SHADEDOT_QUANT 16 -float r_avertexnormal_dots[SHADEDOT_QUANT][256] = -#include "anorm_dots.h" -; - -float *shadedots = r_avertexnormal_dots[0]; - -int lastposenum; - -/* -============= -GL_DrawAliasFrame -============= -*/ -void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum) -{ - float s, t; - float l; - int i, j; - int index; - trivertx_t *v, *verts; - int list; - int *order; - vec3_t point; - float *normal; - int count; - -lastposenum = posenum; - - verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); - verts += posenum * paliashdr->poseverts; - order = (int *)((byte *)paliashdr + paliashdr->commands); - - while (1) - { - // get the vertex count and primitive type - count = *order++; - if (!count) - break; // done - if (count < 0) - { - count = -count; - glBegin (GL_TRIANGLE_FAN); - } - else - glBegin (GL_TRIANGLE_STRIP); - - do - { - // texture coordinates come from the draw list - glTexCoord2f (((float *)order)[0], ((float *)order)[1]); - order += 2; - - // normals and vertexes come from the frame list - l = shadedots[verts->lightnormalindex] * shadelight; - glColor3f (l, l, l); - glVertex3f (verts->v[0], verts->v[1], verts->v[2]); - verts++; - } while (--count); - - glEnd (); - } -} - - -/* -============= -GL_DrawAliasShadow -============= -*/ -extern vec3_t lightspot; - -void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum) -{ - float s, t, l; - int i, j; - int index; - trivertx_t *v, *verts; - int list; - int *order; - vec3_t point; - float *normal; - float height, lheight; - int count; - - lheight = currententity->origin[2] - lightspot[2]; - - height = 0; - verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); - verts += posenum * paliashdr->poseverts; - order = (int *)((byte *)paliashdr + paliashdr->commands); - - height = -lheight + 1.0; - - while (1) - { - // get the vertex count and primitive type - count = *order++; - if (!count) - break; // done - if (count < 0) - { - count = -count; - glBegin (GL_TRIANGLE_FAN); - } - else - glBegin (GL_TRIANGLE_STRIP); - - do - { - // texture coordinates come from the draw list - // (skipped for shadows) glTexCoord2fv ((float *)order); - order += 2; - - // normals and vertexes come from the frame list - point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0]; - point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1]; - point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]; - - point[0] -= shadevector[0]*(point[2]+lheight); - point[1] -= shadevector[1]*(point[2]+lheight); - point[2] = height; -// height -= 0.001; - glVertex3fv (point); - - verts++; - } while (--count); - - glEnd (); - } -} - - - -/* -================= -R_SetupAliasFrame - -================= -*/ -void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr) -{ - int pose, numposes; - float interval; - - if ((frame >= paliashdr->numframes) || (frame < 0)) - { - Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); - frame = 0; - } - - pose = paliashdr->frames[frame].firstpose; - numposes = paliashdr->frames[frame].numposes; - - if (numposes > 1) - { - interval = paliashdr->frames[frame].interval; - pose += (int)(cl.time / interval) % numposes; - } - - GL_DrawAliasFrame (paliashdr, pose); -} - - - -/* -================= -R_DrawAliasModel - -================= -*/ -void R_DrawAliasModel (entity_t *e) -{ - int i, j; - int lnum; - vec3_t dist; - float add; - model_t *clmodel; - vec3_t mins, maxs; - aliashdr_t *paliashdr; - trivertx_t *verts, *v; - int index; - float s, t, an; - int anim; - - clmodel = currententity->model; - - VectorAdd (currententity->origin, clmodel->mins, mins); - VectorAdd (currententity->origin, clmodel->maxs, maxs); - - if (R_CullBox (mins, maxs)) - return; - - - VectorCopy (currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - - // - // get lighting information - // - - ambientlight = shadelight = R_LightPoint (currententity->origin); - - // allways give the gun some light - if (e == &cl.viewent && ambientlight < 24) - ambientlight = shadelight = 24; - - for (lnum=0 ; lnum= cl.time) - { - VectorSubtract (currententity->origin, - cl_dlights[lnum].origin, - dist); - add = cl_dlights[lnum].radius - Length(dist); - - if (add > 0) { - ambientlight += add; - //ZOID models should be affected by dlights as well - shadelight += add; - } - } - } - - // clamp lighting so it doesn't overbright as much - if (ambientlight > 128) - ambientlight = 128; - if (ambientlight + shadelight > 192) - shadelight = 192 - ambientlight; - - // ZOID: never allow players to go totally black - i = currententity - cl_entities; - if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) - if (ambientlight < 8) - ambientlight = shadelight = 8; - - // HACK HACK HACK -- no fullbright colors, so make torches full light - if (!strcmp (clmodel->name, "progs/flame2.mdl") - || !strcmp (clmodel->name, "progs/flame.mdl") ) - ambientlight = shadelight = 256; - - shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; - shadelight = shadelight / 200.0; - - an = e->angles[1]/180*M_PI; - shadevector[0] = cos(-an); - shadevector[1] = sin(-an); - shadevector[2] = 1; - VectorNormalize (shadevector); - - // - // locate the proper data - // - paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); - - c_alias_polys += paliashdr->numtris; - - // - // draw all the triangles - // - - GL_DisableMultitexture(); - - glPushMatrix (); - R_RotateForEntity (e); - - if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) { - glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8)); -// double size of eyes, since they are really hard to see in gl - glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2); - } else { - glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); - glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); - } - - anim = (int)(cl.time*10) & 3; - GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]); - - // we can't dynamically colormap textures, so they are cached - // seperately for the players. Heads are just uncolored. - if (currententity->colormap != vid.colormap && !gl_nocolors.value) - { - i = currententity - cl_entities; - if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) - GL_Bind(playertextures - 1 + i); - } - - if (gl_smoothmodels.value) - glShadeModel (GL_SMOOTH); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - if (gl_affinemodels.value) - glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - - R_SetupAliasFrame (currententity->frame, paliashdr); - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - glShadeModel (GL_FLAT); - if (gl_affinemodels.value) - glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - - glPopMatrix (); - - if (r_shadows.value) - { - glPushMatrix (); - R_RotateForEntity (e); - glDisable (GL_TEXTURE_2D); - glEnable (GL_BLEND); - glColor4f (0,0,0,0.5); - GL_DrawAliasShadow (paliashdr, lastposenum); - glEnable (GL_TEXTURE_2D); - glDisable (GL_BLEND); - glColor4f (1,1,1,1); - glPopMatrix (); - } - -} - -//================================================================================== - -/* -============= -R_DrawEntitiesOnList -============= -*/ -void R_DrawEntitiesOnList (void) -{ - int i; - - if (!r_drawentities.value) - return; - - // draw sprites seperately, because of alpha blending - for (i=0 ; imodel->type) - { - case mod_alias: - R_DrawAliasModel (currententity); - break; - - case mod_brush: - R_DrawBrushModel (currententity); - break; - - default: - break; - } - } - - for (i=0 ; imodel->type) - { - case mod_sprite: - R_DrawSpriteModel (currententity); - break; - } - } -} - -/* -============= -R_DrawViewModel -============= -*/ -void R_DrawViewModel (void) -{ - float ambient[4], diffuse[4]; - int j; - int lnum; - vec3_t dist; - float add; - dlight_t *dl; - int ambientlight, shadelight; - - if (!r_drawviewmodel.value) - return; - - if (chase_active.value) - return; - - if (envmap) - return; - - if (!r_drawentities.value) - return; - - if (cl.items & IT_INVISIBILITY) - return; - - if (cl.stats[STAT_HEALTH] <= 0) - return; - - currententity = &cl.viewent; - if (!currententity->model) - return; - - j = R_LightPoint (currententity->origin); - - if (j < 24) - j = 24; // allways give some light on gun - ambientlight = j; - 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) - ambientlight += add; - } - - ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128; - diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128; - - // hack the depth range to prevent view model from poking into walls - glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); - R_DrawAliasModel (currententity); - glDepthRange (gldepthmin, gldepthmax); -} - - -/* -============ -R_PolyBlend -============ -*/ -void R_PolyBlend (void) -{ - if (!gl_polyblend.value) - return; - if (!v_blend[3]) - return; - - GL_DisableMultitexture(); - - glDisable (GL_ALPHA_TEST); - glEnable (GL_BLEND); - glDisable (GL_DEPTH_TEST); - glDisable (GL_TEXTURE_2D); - - glLoadIdentity (); - - glRotatef (-90, 1, 0, 0); // put Z going up - glRotatef (90, 0, 0, 1); // put Z going up - - glColor4fv (v_blend); - - glBegin (GL_QUADS); - - glVertex3f (10, 100, 100); - glVertex3f (10, -100, 100); - glVertex3f (10, -100, -100); - glVertex3f (10, 100, -100); - glEnd (); - - glDisable (GL_BLEND); - glEnable (GL_TEXTURE_2D); - glEnable (GL_ALPHA_TEST); -} - - -int SignbitsForPlane (mplane_t *out) -{ - int bits, j; - - // for fast box on planeside test - - bits = 0; - for (j=0 ; j<3 ; j++) - { - if (out->normal[j] < 0) - bits |= 1< 1) - Cvar_Set ("r_fullbright", "0"); - - R_AnimateLight (); - - r_framecount++; - -// build the transformation matrix for the given view angles - VectorCopy (r_refdef.vieworg, r_origin); - - AngleVectors (r_refdef.viewangles, vpn, vright, vup); - -// current viewleaf - r_oldviewleaf = r_viewleaf; - r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); - - V_SetContentsColor (r_viewleaf->contents); - V_CalcBlend (); - - r_cache_thrash = false; - - c_brush_polys = 0; - c_alias_polys = 0; - -} - - -void MYgluPerspective( GLdouble fovy, GLdouble aspect, - GLdouble zNear, GLdouble zFar ) -{ - GLdouble xmin, xmax, ymin, ymax; - - ymax = zNear * tan( fovy * M_PI / 360.0 ); - ymin = -ymax; - - xmin = ymin * aspect; - xmax = ymax * aspect; - - glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); -} - - -/* -============= -R_SetupGL -============= -*/ -void R_SetupGL (void) -{ - float screenaspect; - float yfov; - int i; - extern int glwidth, glheight; - int x, x2, y2, y, w, h; - - // - // set up viewpoint - // - glMatrixMode(GL_PROJECTION); - glLoadIdentity (); - x = r_refdef.vrect.x * glwidth/vid.width; - x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width; - y = (vid.height-r_refdef.vrect.y) * glheight/vid.height; - y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height; - - // fudge around because of frac screen scale - if (x > 0) - x--; - if (x2 < glwidth) - x2++; - if (y2 < 0) - y2--; - if (y < glheight) - y++; - - w = x2 - x; - h = y - y2; - - if (envmap) - { - x = y2 = 0; - w = h = 256; - } - - glViewport (glx + x, gly + y2, w, h); - screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; -// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; - MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096); - - if (mirror) - { - if (mirror_plane->normal[2]) - glScalef (1, -1, 1); - else - glScalef (-1, 1, 1); - glCullFace(GL_BACK); - } - else - glCullFace(GL_FRONT); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity (); - - glRotatef (-90, 1, 0, 0); // put Z going up - glRotatef (90, 0, 0, 1); // put Z going up - glRotatef (-r_refdef.viewangles[2], 1, 0, 0); - glRotatef (-r_refdef.viewangles[0], 0, 1, 0); - glRotatef (-r_refdef.viewangles[1], 0, 0, 1); - glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); - - glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); - - // - // set drawing parms - // - if (gl_cull.value) - glEnable(GL_CULL_FACE); - else - glDisable(GL_CULL_FACE); - - glDisable(GL_BLEND); - glDisable(GL_ALPHA_TEST); - glEnable(GL_DEPTH_TEST); -} - -/* -================ -R_RenderScene - -r_refdef must be set before the first call -================ -*/ -void R_RenderScene (void) -{ - R_SetupFrame (); - - R_SetFrustum (); - - R_SetupGL (); - - R_MarkLeaves (); // done here so we know if we're in water - - R_DrawWorld (); // adds static entities to the list - - S_ExtraUpdate (); // don't let sound get messed up if going slow - - R_DrawEntitiesOnList (); - - GL_DisableMultitexture(); - - R_RenderDlights (); - - R_DrawParticles (); - -#ifdef GLTEST - Test_Draw (); -#endif - -} - - -/* -============= -R_Clear -============= -*/ -void R_Clear (void) -{ - if (r_mirroralpha.value != 1.0) - { - if (gl_clear.value) - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - glClear (GL_DEPTH_BUFFER_BIT); - gldepthmin = 0; - gldepthmax = 0.5; - glDepthFunc (GL_LEQUAL); - } - else if (gl_ztrick.value) - { - static int trickframe; - - if (gl_clear.value) - glClear (GL_COLOR_BUFFER_BIT); - - trickframe++; - if (trickframe & 1) - { - gldepthmin = 0; - gldepthmax = 0.49999; - glDepthFunc (GL_LEQUAL); - } - else - { - gldepthmin = 1; - gldepthmax = 0.5; - glDepthFunc (GL_GEQUAL); - } - } - else - { - if (gl_clear.value) - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - else - glClear (GL_DEPTH_BUFFER_BIT); - gldepthmin = 0; - gldepthmax = 1; - glDepthFunc (GL_LEQUAL); - } - - glDepthRange (gldepthmin, gldepthmax); -} - -/* -============= -R_Mirror -============= -*/ -void R_Mirror (void) -{ - float d; - msurface_t *s; - entity_t *ent; - - if (!mirror) - return; - - memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix)); - - d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist; - VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg); - - d = DotProduct (vpn, mirror_plane->normal); - VectorMA (vpn, -2*d, mirror_plane->normal, vpn); - - r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180; - r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180; - r_refdef.viewangles[2] = -r_refdef.viewangles[2]; - - ent = &cl_entities[cl.viewentity]; - if (cl_numvisedicts < MAX_VISEDICTS) - { - cl_visedicts[cl_numvisedicts] = ent; - cl_numvisedicts++; - } - - gldepthmin = 0.5; - gldepthmax = 1; - glDepthRange (gldepthmin, gldepthmax); - glDepthFunc (GL_LEQUAL); - - R_RenderScene (); - R_DrawWaterSurfaces (); - - gldepthmin = 0; - gldepthmax = 0.5; - glDepthRange (gldepthmin, gldepthmax); - glDepthFunc (GL_LEQUAL); - - // blend on top - glEnable (GL_BLEND); - glMatrixMode(GL_PROJECTION); - if (mirror_plane->normal[2]) - glScalef (1,-1,1); - else - glScalef (-1,1,1); - glCullFace(GL_FRONT); - glMatrixMode(GL_MODELVIEW); - - glLoadMatrixf (r_base_world_matrix); - - glColor4f (1,1,1,r_mirroralpha.value); - s = cl.worldmodel->textures[mirrortexturenum]->texturechain; - for ( ; s ; s=s->texturechain) - R_RenderBrushPoly (s); - cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL; - glDisable (GL_BLEND); - glColor4f (1,1,1,1); -} - -/* -================ -R_RenderView - -r_refdef must be set before the first call -================ -*/ -void R_RenderView (void) -{ - double time1, time2; - GLfloat colors[4] = {(GLfloat) 0.0, (GLfloat) 0.0, (GLfloat) 1, (GLfloat) 0.20}; - - if (r_norefresh.value) - return; - - if (!r_worldentity.model || !cl.worldmodel) - Sys_Error ("R_RenderView: NULL worldmodel"); - - if (r_speeds.value) - { - glFinish (); - time1 = Sys_FloatTime (); - c_brush_polys = 0; - c_alias_polys = 0; - } - - mirror = false; - - if (gl_finish.value) - glFinish (); - - R_Clear (); - - // render normal view - -/***** Experimental silly looking fog ****** -****** Use r_fullbright if you enable ****** - glFogi(GL_FOG_MODE, GL_LINEAR); - glFogfv(GL_FOG_COLOR, colors); - glFogf(GL_FOG_END, 512.0); - glEnable(GL_FOG); -********************************************/ - - R_RenderScene (); - R_DrawViewModel (); - R_DrawWaterSurfaces (); - -// More fog right here :) -// glDisable(GL_FOG); -// End of all fog code... - - // render mirror view - R_Mirror (); - - R_PolyBlend (); - - if (r_speeds.value) - { -// glFinish (); - time2 = Sys_FloatTime (); - Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); - } -} +/* +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" + +entity_t r_worldentity; + +qboolean r_cache_thrash; // compatability + +vec3_t modelorg, r_entorigin; +entity_t *currententity; + +int r_visframecount; // bumped when going to a new PVS +int r_framecount; // used for dlight push checking + +mplane_t frustum[4]; + +int c_brush_polys, c_alias_polys; + +qboolean envmap; // true during envmap command capture + +int currenttexture = -1; // to avoid unnecessary texture sets + +int cnttextures[2] = {-1, -1}; // cached + +int particletexture; // little dot for particles +int playertextures; // up to 16 color translated skins + +int mirrortexturenum; // quake texturenum, not gltexturenum +qboolean mirror; +mplane_t *mirror_plane; + +// +// view origin +// +vec3_t vup; +vec3_t vpn; +vec3_t vright; +vec3_t r_origin; + +float r_world_matrix[16]; +float r_base_world_matrix[16]; + +// +// screen size info +// +refdef_t r_refdef; + +mleaf_t *r_viewleaf, *r_oldviewleaf; + +texture_t *r_notexture_mip; + +int d_lightstylevalue[256]; // 8.8 fraction of base light value + + +void R_MarkLeaves (void); + +cvar_t r_norefresh = {"r_norefresh","0"}; +cvar_t r_drawentities = {"r_drawentities","1"}; +cvar_t r_drawviewmodel = {"r_drawviewmodel","1"}; +cvar_t r_speeds = {"r_speeds","0"}; +cvar_t r_fullbright = {"r_fullbright","0"}; +cvar_t r_lightmap = {"r_lightmap","0"}; +cvar_t r_shadows = {"r_shadows","0"}; +cvar_t r_mirroralpha = {"r_mirroralpha","1"}; +cvar_t r_wateralpha = {"r_wateralpha","1"}; +cvar_t r_dynamic = {"r_dynamic","1"}; +cvar_t r_novis = {"r_novis","0"}; + +cvar_t gl_finish = {"gl_finish","0"}; +cvar_t gl_clear = {"gl_clear","0"}; +cvar_t gl_cull = {"gl_cull","1"}; +cvar_t gl_texsort = {"gl_texsort","1"}; +cvar_t gl_smoothmodels = {"gl_smoothmodels","1"}; +cvar_t gl_affinemodels = {"gl_affinemodels","0"}; +cvar_t gl_polyblend = {"gl_polyblend","1"}; +cvar_t gl_flashblend = {"gl_flashblend","1"}; +cvar_t gl_playermip = {"gl_playermip","0"}; +cvar_t gl_nocolors = {"gl_nocolors","0"}; +cvar_t gl_keeptjunctions = {"gl_keeptjunctions","0"}; +cvar_t gl_reporttjunctions = {"gl_reporttjunctions","0"}; +cvar_t gl_doubleeyes = {"gl_doubleeys", "1"}; + +extern cvar_t gl_ztrick; + +/* +================= +R_CullBox + +Returns true if the box is completely outside the frustom +================= +*/ +qboolean R_CullBox (vec3_t mins, vec3_t maxs) +{ + int i; + + for (i=0 ; i<4 ; i++) + if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2) + return true; + return false; +} + + +void R_RotateForEntity (entity_t *e) +{ + glTranslatef (e->origin[0], e->origin[1], e->origin[2]); + + glRotatef (e->angles[1], 0, 0, 1); + glRotatef (-e->angles[0], 0, 1, 0); + glRotatef (e->angles[2], 1, 0, 0); +} + +/* +============================================================= + + SPRITE MODELS + +============================================================= +*/ + +/* +================ +R_GetSpriteFrame +================ +*/ +mspriteframe_t *R_GetSpriteFrame (entity_t *currententity) +{ + msprite_t *psprite; + mspritegroup_t *pspritegroup; + mspriteframe_t *pspriteframe; + int i, numframes, frame; + float *pintervals, fullinterval, targettime, time; + + psprite = currententity->model->cache.data; + frame = currententity->frame; + + if ((frame >= psprite->numframes) || (frame < 0)) + { + Con_Printf ("R_DrawSprite: no such frame %d\n", frame); + frame = 0; + } + + if (psprite->frames[frame].type == SPR_SINGLE) + { + pspriteframe = psprite->frames[frame].frameptr; + } + else + { + pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; + pintervals = pspritegroup->intervals; + numframes = pspritegroup->numframes; + fullinterval = pintervals[numframes-1]; + + time = cl.time + currententity->syncbase; + + // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values + // are positive, so we don't have to worry about division by 0 + targettime = time - ((int)(time / fullinterval)) * fullinterval; + + for (i=0 ; i<(numframes-1) ; i++) + { + if (pintervals[i] > targettime) + break; + } + + pspriteframe = pspritegroup->frames[i]; + } + + return pspriteframe; +} + + +/* +================= +R_DrawSpriteModel + +================= +*/ +void R_DrawSpriteModel (entity_t *e) +{ + vec3_t point; + mspriteframe_t *frame; + float *up, *right; + vec3_t v_forward, v_right, v_up; + msprite_t *psprite; + + // don't even bother culling, because it's just a single + // polygon without a surface cache + frame = R_GetSpriteFrame (e); + psprite = currententity->model->cache.data; + + if (psprite->type == SPR_ORIENTED) + { // bullet marks on walls + AngleVectors (currententity->angles, v_forward, v_right, v_up); + up = v_up; + right = v_right; + } + else + { // normal sprite + up = vup; + right = vright; + } + + glColor3f (1,1,1); + + GL_DisableMultitexture(); + + GL_Bind(frame->gl_texturenum); + + glEnable (GL_ALPHA_TEST); + glBegin (GL_QUADS); + + glTexCoord2f (0, 1); + VectorMA (e->origin, frame->down, up, point); + VectorMA (point, frame->left, right, point); + glVertex3fv (point); + + glTexCoord2f (0, 0); + VectorMA (e->origin, frame->up, up, point); + VectorMA (point, frame->left, right, point); + glVertex3fv (point); + + glTexCoord2f (1, 0); + VectorMA (e->origin, frame->up, up, point); + VectorMA (point, frame->right, right, point); + glVertex3fv (point); + + glTexCoord2f (1, 1); + VectorMA (e->origin, frame->down, up, point); + VectorMA (point, frame->right, right, point); + glVertex3fv (point); + + glEnd (); + + glDisable (GL_ALPHA_TEST); +} + +/* +============================================================= + + ALIAS MODELS + +============================================================= +*/ + + +#define NUMVERTEXNORMALS 162 + +float r_avertexnormals[NUMVERTEXNORMALS][3] = { +#include "anorms.h" +}; + +vec3_t shadevector; +float shadelight, ambientlight; + +// precalculated dot products for quantized angles +#define SHADEDOT_QUANT 16 +float r_avertexnormal_dots[SHADEDOT_QUANT][256] = +#include "anorm_dots.h" +; + +float *shadedots = r_avertexnormal_dots[0]; + +int lastposenum; + +/* +============= +GL_DrawAliasFrame +============= +*/ +void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum) +{ + float s, t; + float l; + int i, j; + int index; + trivertx_t *v, *verts; + int list; + int *order; + vec3_t point; + float *normal; + int count; + +lastposenum = posenum; + + verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); + verts += posenum * paliashdr->poseverts; + order = (int *)((byte *)paliashdr + paliashdr->commands); + + while (1) + { + // get the vertex count and primitive type + count = *order++; + if (!count) + break; // done + if (count < 0) + { + count = -count; + glBegin (GL_TRIANGLE_FAN); + } + else + glBegin (GL_TRIANGLE_STRIP); + + do + { + // texture coordinates come from the draw list + glTexCoord2f (((float *)order)[0], ((float *)order)[1]); + order += 2; + + // normals and vertexes come from the frame list + l = shadedots[verts->lightnormalindex] * shadelight; + glColor3f (l, l, l); + glVertex3f (verts->v[0], verts->v[1], verts->v[2]); + verts++; + } while (--count); + + glEnd (); + } +} + + +/* +============= +GL_DrawAliasShadow +============= +*/ +extern vec3_t lightspot; + +void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum) +{ + float s, t, l; + int i, j; + int index; + trivertx_t *v, *verts; + int list; + int *order; + vec3_t point; + float *normal; + float height, lheight; + int count; + + lheight = currententity->origin[2] - lightspot[2]; + + height = 0; + verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata); + verts += posenum * paliashdr->poseverts; + order = (int *)((byte *)paliashdr + paliashdr->commands); + + height = -lheight + 1.0; + + while (1) + { + // get the vertex count and primitive type + count = *order++; + if (!count) + break; // done + if (count < 0) + { + count = -count; + glBegin (GL_TRIANGLE_FAN); + } + else + glBegin (GL_TRIANGLE_STRIP); + + do + { + // texture coordinates come from the draw list + // (skipped for shadows) glTexCoord2fv ((float *)order); + order += 2; + + // normals and vertexes come from the frame list + point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0]; + point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1]; + point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]; + + point[0] -= shadevector[0]*(point[2]+lheight); + point[1] -= shadevector[1]*(point[2]+lheight); + point[2] = height; +// height -= 0.001; + glVertex3fv (point); + + verts++; + } while (--count); + + glEnd (); + } +} + + + +/* +================= +R_SetupAliasFrame + +================= +*/ +void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr) +{ + int pose, numposes; + float interval; + + if ((frame >= paliashdr->numframes) || (frame < 0)) + { + Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); + frame = 0; + } + + pose = paliashdr->frames[frame].firstpose; + numposes = paliashdr->frames[frame].numposes; + + if (numposes > 1) + { + interval = paliashdr->frames[frame].interval; + pose += (int)(cl.time / interval) % numposes; + } + + GL_DrawAliasFrame (paliashdr, pose); +} + + + +/* +================= +R_DrawAliasModel + +================= +*/ +void R_DrawAliasModel (entity_t *e) +{ + int i, j; + int lnum; + vec3_t dist; + float add; + model_t *clmodel; + vec3_t mins, maxs; + aliashdr_t *paliashdr; + trivertx_t *verts, *v; + int index; + float s, t, an; + int anim; + + clmodel = currententity->model; + + VectorAdd (currententity->origin, clmodel->mins, mins); + VectorAdd (currententity->origin, clmodel->maxs, maxs); + + if (R_CullBox (mins, maxs)) + return; + + + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + // + // get lighting information + // + + ambientlight = shadelight = R_LightPoint (currententity->origin); + + // allways give the gun some light + if (e == &cl.viewent && ambientlight < 24) + ambientlight = shadelight = 24; + + for (lnum=0 ; lnum= cl.time) + { + VectorSubtract (currententity->origin, + cl_dlights[lnum].origin, + dist); + add = cl_dlights[lnum].radius - Length(dist); + + if (add > 0) { + ambientlight += add; + //ZOID models should be affected by dlights as well + shadelight += add; + } + } + } + + // clamp lighting so it doesn't overbright as much + if (ambientlight > 128) + ambientlight = 128; + if (ambientlight + shadelight > 192) + shadelight = 192 - ambientlight; + + // ZOID: never allow players to go totally black + i = currententity - cl_entities; + if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) + if (ambientlight < 8) + ambientlight = shadelight = 8; + + // HACK HACK HACK -- no fullbright colors, so make torches full light + if (!strcmp (clmodel->name, "progs/flame2.mdl") + || !strcmp (clmodel->name, "progs/flame.mdl") ) + ambientlight = shadelight = 256; + + shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; + shadelight = shadelight / 200.0; + + an = e->angles[1]/180*M_PI; + shadevector[0] = cos(-an); + shadevector[1] = sin(-an); + shadevector[2] = 1; + VectorNormalize (shadevector); + + // + // locate the proper data + // + paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); + + c_alias_polys += paliashdr->numtris; + + // + // draw all the triangles + // + + GL_DisableMultitexture(); + + glPushMatrix (); + R_RotateForEntity (e); + + if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) { + glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8)); +// double size of eyes, since they are really hard to see in gl + glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2); + } else { + glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); + glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); + } + + anim = (int)(cl.time*10) & 3; + GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]); + + // we can't dynamically colormap textures, so they are cached + // seperately for the players. Heads are just uncolored. + if (currententity->colormap != vid.colormap && !gl_nocolors.value) + { + i = currententity - cl_entities; + if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) + GL_Bind(playertextures - 1 + i); + } + + if (gl_smoothmodels.value) + glShadeModel (GL_SMOOTH); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + if (gl_affinemodels.value) + glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + + R_SetupAliasFrame (currententity->frame, paliashdr); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + glShadeModel (GL_FLAT); + if (gl_affinemodels.value) + glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + glPopMatrix (); + + if (r_shadows.value) + { + glPushMatrix (); + R_RotateForEntity (e); + glDisable (GL_TEXTURE_2D); + glEnable (GL_BLEND); + glColor4f (0,0,0,0.5); + GL_DrawAliasShadow (paliashdr, lastposenum); + glEnable (GL_TEXTURE_2D); + glDisable (GL_BLEND); + glColor4f (1,1,1,1); + glPopMatrix (); + } + +} + +//================================================================================== + +/* +============= +R_DrawEntitiesOnList +============= +*/ +void R_DrawEntitiesOnList (void) +{ + int i; + + if (!r_drawentities.value) + return; + + // draw sprites seperately, because of alpha blending + for (i=0 ; imodel->type) + { + case mod_alias: + R_DrawAliasModel (currententity); + break; + + case mod_brush: + R_DrawBrushModel (currententity); + break; + + default: + break; + } + } + + for (i=0 ; imodel->type) + { + case mod_sprite: + R_DrawSpriteModel (currententity); + break; + } + } +} + +/* +============= +R_DrawViewModel +============= +*/ +void R_DrawViewModel (void) +{ + float ambient[4], diffuse[4]; + int j; + int lnum; + vec3_t dist; + float add; + dlight_t *dl; + int ambientlight, shadelight; + + if (!r_drawviewmodel.value) + return; + + if (chase_active.value) + return; + + if (envmap) + return; + + if (!r_drawentities.value) + return; + + if (cl.items & IT_INVISIBILITY) + return; + + if (cl.stats[STAT_HEALTH] <= 0) + return; + + currententity = &cl.viewent; + if (!currententity->model) + return; + + j = R_LightPoint (currententity->origin); + + if (j < 24) + j = 24; // allways give some light on gun + ambientlight = j; + 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) + ambientlight += add; + } + + ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128; + diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128; + + // hack the depth range to prevent view model from poking into walls + glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); + R_DrawAliasModel (currententity); + glDepthRange (gldepthmin, gldepthmax); +} + + +/* +============ +R_PolyBlend +============ +*/ +void R_PolyBlend (void) +{ + if (!gl_polyblend.value) + return; + if (!v_blend[3]) + return; + + GL_DisableMultitexture(); + + glDisable (GL_ALPHA_TEST); + glEnable (GL_BLEND); + glDisable (GL_DEPTH_TEST); + glDisable (GL_TEXTURE_2D); + + glLoadIdentity (); + + glRotatef (-90, 1, 0, 0); // put Z going up + glRotatef (90, 0, 0, 1); // put Z going up + + glColor4fv (v_blend); + + glBegin (GL_QUADS); + + glVertex3f (10, 100, 100); + glVertex3f (10, -100, 100); + glVertex3f (10, -100, -100); + glVertex3f (10, 100, -100); + glEnd (); + + glDisable (GL_BLEND); + glEnable (GL_TEXTURE_2D); + glEnable (GL_ALPHA_TEST); +} + + +int SignbitsForPlane (mplane_t *out) +{ + int bits, j; + + // for fast box on planeside test + + bits = 0; + for (j=0 ; j<3 ; j++) + { + if (out->normal[j] < 0) + bits |= 1< 1) + Cvar_Set ("r_fullbright", "0"); + + R_AnimateLight (); + + r_framecount++; + +// build the transformation matrix for the given view angles + VectorCopy (r_refdef.vieworg, r_origin); + + AngleVectors (r_refdef.viewangles, vpn, vright, vup); + +// current viewleaf + r_oldviewleaf = r_viewleaf; + r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); + + V_SetContentsColor (r_viewleaf->contents); + V_CalcBlend (); + + r_cache_thrash = false; + + c_brush_polys = 0; + c_alias_polys = 0; + +} + + +void MYgluPerspective( GLdouble fovy, GLdouble aspect, + GLdouble zNear, GLdouble zFar ) +{ + GLdouble xmin, xmax, ymin, ymax; + + ymax = zNear * tan( fovy * M_PI / 360.0 ); + ymin = -ymax; + + xmin = ymin * aspect; + xmax = ymax * aspect; + + glFrustum( xmin, xmax, ymin, ymax, zNear, zFar ); +} + + +/* +============= +R_SetupGL +============= +*/ +void R_SetupGL (void) +{ + float screenaspect; + float yfov; + int i; + extern int glwidth, glheight; + int x, x2, y2, y, w, h; + + // + // set up viewpoint + // + glMatrixMode(GL_PROJECTION); + glLoadIdentity (); + x = r_refdef.vrect.x * glwidth/vid.width; + x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width; + y = (vid.height-r_refdef.vrect.y) * glheight/vid.height; + y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height; + + // fudge around because of frac screen scale + if (x > 0) + x--; + if (x2 < glwidth) + x2++; + if (y2 < 0) + y2--; + if (y < glheight) + y++; + + w = x2 - x; + h = y - y2; + + if (envmap) + { + x = y2 = 0; + w = h = 256; + } + + glViewport (glx + x, gly + y2, w, h); + screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height; +// yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI; + MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096); + + if (mirror) + { + if (mirror_plane->normal[2]) + glScalef (1, -1, 1); + else + glScalef (-1, 1, 1); + glCullFace(GL_BACK); + } + else + glCullFace(GL_FRONT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity (); + + glRotatef (-90, 1, 0, 0); // put Z going up + glRotatef (90, 0, 0, 1); // put Z going up + glRotatef (-r_refdef.viewangles[2], 1, 0, 0); + glRotatef (-r_refdef.viewangles[0], 0, 1, 0); + glRotatef (-r_refdef.viewangles[1], 0, 0, 1); + glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]); + + glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix); + + // + // set drawing parms + // + if (gl_cull.value) + glEnable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); + + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glEnable(GL_DEPTH_TEST); +} + +/* +================ +R_RenderScene + +r_refdef must be set before the first call +================ +*/ +void R_RenderScene (void) +{ + R_SetupFrame (); + + R_SetFrustum (); + + R_SetupGL (); + + R_MarkLeaves (); // done here so we know if we're in water + + R_DrawWorld (); // adds static entities to the list + + S_ExtraUpdate (); // don't let sound get messed up if going slow + + R_DrawEntitiesOnList (); + + GL_DisableMultitexture(); + + R_RenderDlights (); + + R_DrawParticles (); + +#ifdef GLTEST + Test_Draw (); +#endif + +} + + +/* +============= +R_Clear +============= +*/ +void R_Clear (void) +{ + if (r_mirroralpha.value != 1.0) + { + if (gl_clear.value) + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + else + glClear (GL_DEPTH_BUFFER_BIT); + gldepthmin = 0; + gldepthmax = 0.5; + glDepthFunc (GL_LEQUAL); + } + else if (gl_ztrick.value) + { + static int trickframe; + + if (gl_clear.value) + glClear (GL_COLOR_BUFFER_BIT); + + trickframe++; + if (trickframe & 1) + { + gldepthmin = 0; + gldepthmax = 0.49999; + glDepthFunc (GL_LEQUAL); + } + else + { + gldepthmin = 1; + gldepthmax = 0.5; + glDepthFunc (GL_GEQUAL); + } + } + else + { + if (gl_clear.value) + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + else + glClear (GL_DEPTH_BUFFER_BIT); + gldepthmin = 0; + gldepthmax = 1; + glDepthFunc (GL_LEQUAL); + } + + glDepthRange (gldepthmin, gldepthmax); +} + +/* +============= +R_Mirror +============= +*/ +void R_Mirror (void) +{ + float d; + msurface_t *s; + entity_t *ent; + + if (!mirror) + return; + + memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix)); + + d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist; + VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg); + + d = DotProduct (vpn, mirror_plane->normal); + VectorMA (vpn, -2*d, mirror_plane->normal, vpn); + + r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180; + r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180; + r_refdef.viewangles[2] = -r_refdef.viewangles[2]; + + ent = &cl_entities[cl.viewentity]; + if (cl_numvisedicts < MAX_VISEDICTS) + { + cl_visedicts[cl_numvisedicts] = ent; + cl_numvisedicts++; + } + + gldepthmin = 0.5; + gldepthmax = 1; + glDepthRange (gldepthmin, gldepthmax); + glDepthFunc (GL_LEQUAL); + + R_RenderScene (); + R_DrawWaterSurfaces (); + + gldepthmin = 0; + gldepthmax = 0.5; + glDepthRange (gldepthmin, gldepthmax); + glDepthFunc (GL_LEQUAL); + + // blend on top + glEnable (GL_BLEND); + glMatrixMode(GL_PROJECTION); + if (mirror_plane->normal[2]) + glScalef (1,-1,1); + else + glScalef (-1,1,1); + glCullFace(GL_FRONT); + glMatrixMode(GL_MODELVIEW); + + glLoadMatrixf (r_base_world_matrix); + + glColor4f (1,1,1,r_mirroralpha.value); + s = cl.worldmodel->textures[mirrortexturenum]->texturechain; + for ( ; s ; s=s->texturechain) + R_RenderBrushPoly (s); + cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL; + glDisable (GL_BLEND); + glColor4f (1,1,1,1); +} + +/* +================ +R_RenderView + +r_refdef must be set before the first call +================ +*/ +void R_RenderView (void) +{ + double time1, time2; + GLfloat colors[4] = {(GLfloat) 0.0, (GLfloat) 0.0, (GLfloat) 1, (GLfloat) 0.20}; + + if (r_norefresh.value) + return; + + if (!r_worldentity.model || !cl.worldmodel) + Sys_Error ("R_RenderView: NULL worldmodel"); + + if (r_speeds.value) + { + glFinish (); + time1 = Sys_FloatTime (); + c_brush_polys = 0; + c_alias_polys = 0; + } + + mirror = false; + + if (gl_finish.value) + glFinish (); + + R_Clear (); + + // render normal view + +/***** Experimental silly looking fog ****** +****** Use r_fullbright if you enable ****** + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogfv(GL_FOG_COLOR, colors); + glFogf(GL_FOG_END, 512.0); + glEnable(GL_FOG); +********************************************/ + + R_RenderScene (); + R_DrawViewModel (); + R_DrawWaterSurfaces (); + +// More fog right here :) +// glDisable(GL_FOG); +// End of all fog code... + + // render mirror view + R_Mirror (); + + R_PolyBlend (); + + if (r_speeds.value) + { +// glFinish (); + time2 = Sys_FloatTime (); + Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys); + } +} -- cgit v1.2.3