Home | History | Annotate | Download | only in WinQuake
      1 /*
      2 Copyright (C) 1996-1997 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     12 
     13 See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License
     16 along with this program; if not, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // r_main.c
     21 
     22 #include "quakedef.h"
     23 
     24 entity_t	r_worldentity;
     25 
     26 qboolean	r_cache_thrash;		// compatability
     27 
     28 vec3_t		modelorg, r_entorigin;
     29 entity_t	*currententity;
     30 
     31 int			r_visframecount;	// bumped when going to a new PVS
     32 int			r_framecount;		// used for dlight push checking
     33 
     34 mplane_t	frustum[4];
     35 
     36 int			c_brush_polys, c_alias_polys;
     37 
     38 qboolean	envmap;				// true during envmap command capture
     39 
     40 int			currenttexture = -1;		// to avoid unnecessary texture sets
     41 
     42 int			cnttextures[2] = {-1, -1};     // cached
     43 
     44 int			particletexture;	// little dot for particles
     45 int			playertextures;		// up to 16 color translated skins
     46 
     47 int			mirrortexturenum;	// quake texturenum, not gltexturenum
     48 qboolean	mirror;
     49 mplane_t	*mirror_plane;
     50 
     51 //
     52 // view origin
     53 //
     54 vec3_t	vup;
     55 vec3_t	vpn;
     56 vec3_t	vright;
     57 vec3_t	r_origin;
     58 
     59 float	r_world_matrix[16];
     60 float	r_base_world_matrix[16];
     61 
     62 //
     63 // screen size info
     64 //
     65 refdef_t	r_refdef;
     66 
     67 mleaf_t		*r_viewleaf, *r_oldviewleaf;
     68 
     69 texture_t	*r_notexture_mip;
     70 
     71 int		d_lightstylevalue[256];	// 8.8 fraction of base light value
     72 
     73 
     74 void R_MarkLeaves (void);
     75 
     76 cvar_t	r_norefresh = CVAR2("r_norefresh","0");
     77 cvar_t	r_drawentities = CVAR2("r_drawentities","1");
     78 cvar_t	r_drawviewmodel = CVAR2("r_drawviewmodel","1");
     79 cvar_t	r_speeds = CVAR2("r_speeds","0");
     80 cvar_t	r_fullbright = CVAR2("r_fullbright","0");
     81 cvar_t	r_lightmap = CVAR2("r_lightmap","0");
     82 cvar_t	r_shadows = CVAR2("r_shadows","0");
     83 cvar_t	r_mirroralpha = CVAR2("r_mirroralpha","1");
     84 cvar_t	r_wateralpha = CVAR2("r_wateralpha","1");
     85 cvar_t	r_dynamic = CVAR2("r_dynamic","1");
     86 cvar_t	r_novis = CVAR2("r_novis","0");
     87 
     88 cvar_t	gl_finish = CVAR2("gl_finish","0");
     89 cvar_t	gl_clear = CVAR2("gl_clear","0");
     90 cvar_t	gl_cull = CVAR2("gl_cull","1");
     91 cvar_t	gl_texsort = CVAR2("gl_texsort","1");
     92 cvar_t	gl_smoothmodels = CVAR2("gl_smoothmodels","1");
     93 cvar_t	gl_affinemodels = CVAR2("gl_affinemodels","1");
     94 cvar_t	gl_polyblend = CVAR2("gl_polyblend","1");
     95 cvar_t	gl_flashblend = CVAR2("gl_flashblend","1");
     96 cvar_t	gl_playermip = CVAR2("gl_playermip","0");
     97 cvar_t	gl_nocolors = CVAR2("gl_nocolors","0");
     98 cvar_t	gl_keeptjunctions = CVAR2("gl_keeptjunctions","1");
     99 cvar_t	gl_reporttjunctions = CVAR2("gl_reporttjunctions","0");
    100 cvar_t	gl_doubleeyes = CVAR2("gl_doubleeys", "1");
    101 
    102 extern	cvar_t	gl_ztrick;
    103 
    104 /*
    105 =================
    106 R_CullBox
    107 
    108 Returns true if the box is completely outside the frustom
    109 =================
    110 */
    111 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
    112 {
    113 	int		i;
    114 
    115 	for (i=0 ; i<4 ; i++)
    116 		if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
    117 			return true;
    118 	return false;
    119 }
    120 
    121 
    122 void R_RotateForEntity (entity_t *e)
    123 {
    124     glTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
    125 
    126     glRotatef (e->angles[1],  0, 0, 1);
    127     glRotatef (-e->angles[0],  0, 1, 0);
    128     glRotatef (e->angles[2],  1, 0, 0);
    129 }
    130 
    131 /*
    132 =============================================================
    133 
    134   SPRITE MODELS
    135 
    136 =============================================================
    137 */
    138 
    139 /*
    140 ================
    141 R_GetSpriteFrame
    142 ================
    143 */
    144 mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
    145 {
    146 	msprite_t		*psprite;
    147 	mspritegroup_t	*pspritegroup;
    148 	mspriteframe_t	*pspriteframe;
    149 	int				i, numframes, frame;
    150 	float			*pintervals, fullinterval, targettime, time;
    151 
    152 	psprite = (msprite_t*) currententity->model->cache.data;
    153 	frame = currententity->frame;
    154 
    155 	if ((frame >= psprite->numframes) || (frame < 0))
    156 	{
    157 		Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
    158 		frame = 0;
    159 	}
    160 
    161 	if (psprite->frames[frame].type == SPR_SINGLE)
    162 	{
    163 		pspriteframe = psprite->frames[frame].frameptr;
    164 	}
    165 	else
    166 	{
    167 		pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
    168 		pintervals = pspritegroup->intervals;
    169 		numframes = pspritegroup->numframes;
    170 		fullinterval = pintervals[numframes-1];
    171 
    172 		time = cl.time + currententity->syncbase;
    173 
    174 	// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
    175 	// are positive, so we don't have to worry about division by 0
    176 		targettime = time - ((int)(time / fullinterval)) * fullinterval;
    177 
    178 		for (i=0 ; i<(numframes-1) ; i++)
    179 		{
    180 			if (pintervals[i] > targettime)
    181 				break;
    182 		}
    183 
    184 		pspriteframe = pspritegroup->frames[i];
    185 	}
    186 
    187 	return pspriteframe;
    188 }
    189 
    190 
    191 /*
    192 =================
    193 R_DrawSpriteModel
    194 
    195 =================
    196 */
    197 void R_DrawSpriteModel (entity_t *e)
    198 {
    199 	vec3_t	point;
    200 	mspriteframe_t	*frame;
    201 	float		*up, *right;
    202 	vec3_t		v_forward, v_right, v_up;
    203 	msprite_t		*psprite;
    204 
    205 	// don't even bother culling, because it's just a single
    206 	// polygon without a surface cache
    207 	frame = R_GetSpriteFrame (e);
    208 	psprite = (msprite_t*) currententity->model->cache.data;
    209 
    210 	if (psprite->type == SPR_ORIENTED)
    211 	{	// bullet marks on walls
    212 		AngleVectors (currententity->angles, v_forward, v_right, v_up);
    213 		up = v_up;
    214 		right = v_right;
    215 	}
    216 	else
    217 	{	// normal sprite
    218 		up = vup;
    219 		right = vright;
    220 	}
    221 
    222 	glColor3f (1,1,1);
    223 
    224 	GL_DisableMultitexture();
    225 
    226     GL_Bind(frame->gl_texturenum);
    227 
    228 	glEnable (GL_ALPHA_TEST);
    229 
    230 #ifdef USE_OPENGLES
    231 
    232 	{
    233 	    float* pPoint = gVertexBuffer;
    234 	    float texCoords[] = {
    235 			0, 1,
    236 			0, 0,
    237 			1, 0,
    238 			1, 1
    239 		};
    240 
    241 		VectorMA (e->origin, frame->down, up, point);
    242 		VectorMA (point, frame->left, right, pPoint);
    243 		pPoint += 3;
    244 
    245 		VectorMA (e->origin, frame->up, up, point);
    246 		VectorMA (point, frame->left, right, pPoint);
    247 		pPoint += 3;
    248 
    249 		VectorMA (e->origin, frame->up, up, point);
    250 		VectorMA (point, frame->right, right, pPoint);
    251 		pPoint += 3;
    252 
    253 		VectorMA (e->origin, frame->down, up, point);
    254 		VectorMA (point, frame->right, right, pPoint);
    255 
    256 		glVertexPointer(3, GL_FLOAT, 0, gVertexBuffer);
    257 		glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
    258 		glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    259 	}
    260 
    261 #else
    262 	glBegin (GL_QUADS);
    263 
    264 	glTexCoord2f (0, 1);
    265 	VectorMA (e->origin, frame->down, up, point);
    266 	VectorMA (point, frame->left, right, point);
    267 	glVertex3fv (point);
    268 
    269 	glTexCoord2f (0, 0);
    270 	VectorMA (e->origin, frame->up, up, point);
    271 	VectorMA (point, frame->left, right, point);
    272 	glVertex3fv (point);
    273 
    274 	glTexCoord2f (1, 0);
    275 	VectorMA (e->origin, frame->up, up, point);
    276 	VectorMA (point, frame->right, right, point);
    277 	glVertex3fv (point);
    278 
    279 	glTexCoord2f (1, 1);
    280 	VectorMA (e->origin, frame->down, up, point);
    281 	VectorMA (point, frame->right, right, point);
    282 	glVertex3fv (point);
    283 
    284 	glEnd ();
    285 #endif
    286 
    287 	glDisable (GL_ALPHA_TEST);
    288 }
    289 
    290 /*
    291 =============================================================
    292 
    293   ALIAS MODELS
    294 
    295 =============================================================
    296 */
    297 
    298 
    299 #define NUMVERTEXNORMALS	162
    300 
    301 float	r_avertexnormals[NUMVERTEXNORMALS][3] = {
    302 #include "anorms.h"
    303 };
    304 
    305 vec3_t	shadevector;
    306 float	shadelight, ambientlight;
    307 
    308 // precalculated dot products for quantized angles
    309 #define SHADEDOT_QUANT 16
    310 float	r_avertexnormal_dots[SHADEDOT_QUANT][256] =
    311 #include "anorm_dots.h"
    312 ;
    313 
    314 float	*shadedots = r_avertexnormal_dots[0];
    315 
    316 int	lastposenum;
    317 
    318 /*
    319 =============
    320 GL_DrawAliasFrame
    321 =============
    322 */
    323 void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
    324 {
    325 	float	s, t;
    326 	float 	l;
    327 	int		i, j;
    328 	int		index;
    329 	trivertx_t	*v, *verts;
    330 	int		list;
    331 	int		*order;
    332 	vec3_t	point;
    333 	float	*normal;
    334 	int		count;
    335 
    336 #ifdef USE_OPENGLES
    337 	glEnableClientState(GL_COLOR_ARRAY);
    338 #endif
    339 
    340 lastposenum = posenum;
    341 
    342 	verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
    343 	verts += posenum * paliashdr->poseverts;
    344 	order = (int *)((byte *)paliashdr + paliashdr->commands);
    345 
    346 	while (1)
    347 	{
    348 		// get the vertex count and primitive type
    349 		count = *order++;
    350 		if (!count)
    351 			break;		// done
    352 
    353 #ifdef USE_OPENGLES
    354 		{
    355 			int primType;
    356 			int c;
    357 			float* pColor;
    358 			float* pTexCoord;
    359 			float* pPos;
    360 
    361 			if (count < 0)
    362 			{
    363 				count = -count;
    364 				primType = GL_TRIANGLE_FAN;
    365 			}
    366 			else
    367 				primType = GL_TRIANGLE_STRIP;
    368 
    369 			// texture coordinates come from the draw list
    370 			glTexCoordPointer(2, GL_FLOAT, 0, gTexCoordBuffer);
    371 			glVertexPointer(3, GL_FLOAT, 0, gVertexBuffer);
    372 			glColorPointer(4, GL_FLOAT, 0, gColorBuffer);
    373 
    374 			pColor = gColorBuffer;
    375 			pPos = gVertexBuffer;
    376 			pTexCoord = gTexCoordBuffer;
    377 			c = count;
    378 			do
    379 			{
    380 				// texture coordinates come from the draw list
    381 				*pTexCoord++ = ((float *)order)[0];
    382 				*pTexCoord++ = ((float *)order)[1];
    383 				order += 2;
    384 
    385 				// normals and vertexes come from the frame list
    386 				l = shadedots[verts->lightnormalindex] * shadelight;
    387 				*pColor++ = l;
    388 				*pColor++ = l;
    389 				*pColor++ = l;
    390 				*pColor++ = 1.0f;
    391 				*pPos++ = verts->v[0];
    392 				*pPos++ = verts->v[1];
    393 				*pPos++ = verts->v[2];
    394 				verts++;
    395 		    } while (--c);
    396 
    397 			glDrawArrays(primType, 0, count);
    398 		}
    399 
    400 #else
    401 		if (count < 0)
    402 		{
    403 			count = -count;
    404 			glBegin (GL_TRIANGLE_FAN);
    405 		}
    406 		else
    407 			glBegin (GL_TRIANGLE_STRIP);
    408 
    409 		do
    410 		{
    411 			// texture coordinates come from the draw list
    412 			glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
    413 			order += 2;
    414 
    415 			// normals and vertexes come from the frame list
    416 			l = shadedots[verts->lightnormalindex] * shadelight;
    417 			glColor3f (l, l, l);
    418 			glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
    419 			verts++;
    420 		} while (--count);
    421 
    422 		glEnd ();
    423 #endif
    424 	}
    425 
    426 #ifdef USE_OPENGLES
    427 	glDisableClientState(GL_COLOR_ARRAY);
    428 #endif
    429 
    430 }
    431 
    432 
    433 /*
    434 =============
    435 GL_DrawAliasShadow
    436 =============
    437 */
    438 extern	vec3_t			lightspot;
    439 
    440 void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
    441 {
    442 	float	s, t, l;
    443 	int		i, j;
    444 	int		index;
    445 	trivertx_t	*v, *verts;
    446 	int		list;
    447 	int		*order;
    448 	vec3_t	point;
    449 	float	*normal;
    450 	float	height, lheight;
    451 	int		count;
    452 
    453 	lheight = currententity->origin[2] - lightspot[2];
    454 
    455 	height = 0;
    456 	verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
    457 	verts += posenum * paliashdr->poseverts;
    458 	order = (int *)((byte *)paliashdr + paliashdr->commands);
    459 
    460 	height = -lheight + 1.0;
    461 
    462 	while (1)
    463 	{
    464 		// get the vertex count and primitive type
    465 		count = *order++;
    466 		if (!count)
    467 			break;		// done
    468 
    469 #ifdef USE_OPENGLES
    470 
    471 		{
    472 			int primType;
    473 			int c;
    474 			float* pVertex;
    475 
    476 			if (count < 0)
    477 			{
    478 				count = -count;
    479 				primType = GL_TRIANGLE_FAN;
    480 			}
    481 			else
    482 				primType = GL_TRIANGLE_STRIP;
    483 
    484 			pVertex = gVertexBuffer;
    485 			for(c = 0; c < count; c++)
    486 			{
    487 				// texture coordinates come from the draw list
    488 				// (skipped for shadows) glTexCoord2fv ((float *)order);
    489 				order += 2;
    490 
    491 				// normals and vertexes come from the frame list
    492 				pVertex[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
    493 				pVertex[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
    494 				pVertex[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
    495 
    496 				pVertex[0] -= shadevector[0]*(pVertex[2]+lheight);
    497 				pVertex[1] -= shadevector[1]*(pVertex[2]+lheight);
    498 				pVertex[2] = height;
    499 	//			height -= 0.001;
    500 
    501 				pVertex += 3;
    502 				verts++;
    503 			}
    504 
    505 			glVertexPointer(3, GL_FLOAT, 0, gVertexBuffer);
    506 			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    507 			glDrawArrays(primType, 0, count);
    508 			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    509 		}
    510 
    511 #else
    512 
    513 		if (count < 0)
    514 		{
    515 			count = -count;
    516 			glBegin (GL_TRIANGLE_FAN);
    517 		}
    518 		else
    519 			glBegin (GL_TRIANGLE_STRIP);
    520 
    521 		do
    522 		{
    523 			// texture coordinates come from the draw list
    524 			// (skipped for shadows) glTexCoord2fv ((float *)order);
    525 			order += 2;
    526 
    527 			// normals and vertexes come from the frame list
    528 			point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
    529 			point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
    530 			point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
    531 
    532 			point[0] -= shadevector[0]*(point[2]+lheight);
    533 			point[1] -= shadevector[1]*(point[2]+lheight);
    534 			point[2] = height;
    535 //			height -= 0.001;
    536 			glVertex3fv (point);
    537 
    538 			verts++;
    539 		} while (--count);
    540 
    541 		glEnd ();
    542 
    543 #endif
    544 
    545 	}
    546 }
    547 
    548 
    549 
    550 /*
    551 =================
    552 R_SetupAliasFrame
    553 
    554 =================
    555 */
    556 void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
    557 {
    558 	int				pose, numposes;
    559 	float			interval;
    560 
    561 	if ((frame >= paliashdr->numframes) || (frame < 0))
    562 	{
    563 		Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
    564 		frame = 0;
    565 	}
    566 
    567 	pose = paliashdr->frames[frame].firstpose;
    568 	numposes = paliashdr->frames[frame].numposes;
    569 
    570 	if (numposes > 1)
    571 	{
    572 		interval = paliashdr->frames[frame].interval;
    573 		pose += (int)(cl.time / interval) % numposes;
    574 	}
    575 
    576 	GL_DrawAliasFrame (paliashdr, pose);
    577 }
    578 
    579 
    580 
    581 /*
    582 =================
    583 R_DrawAliasModel
    584 
    585 =================
    586 */
    587 void R_DrawAliasModel (entity_t *e)
    588 {
    589 	int			i, j;
    590 	int			lnum;
    591 	vec3_t		dist;
    592 	float		add;
    593 	model_t		*clmodel;
    594 	vec3_t		mins, maxs;
    595 	aliashdr_t	*paliashdr;
    596 	trivertx_t	*verts, *v;
    597 	int			index;
    598 	float		s, t, an;
    599 	int			anim;
    600 
    601 	clmodel = currententity->model;
    602 
    603 	VectorAdd (currententity->origin, clmodel->mins, mins);
    604 	VectorAdd (currententity->origin, clmodel->maxs, maxs);
    605 
    606 	if (R_CullBox (mins, maxs))
    607 		return;
    608 
    609 
    610 	VectorCopy (currententity->origin, r_entorigin);
    611 	VectorSubtract (r_origin, r_entorigin, modelorg);
    612 
    613 	//
    614 	// get lighting information
    615 	//
    616 
    617 	ambientlight = shadelight = R_LightPoint (currententity->origin);
    618 
    619 	// allways give the gun some light
    620 	if (e == &cl.viewent && ambientlight < 24)
    621 		ambientlight = shadelight = 24;
    622 
    623 	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
    624 	{
    625 		if (cl_dlights[lnum].die >= cl.time)
    626 		{
    627 			VectorSubtract (currententity->origin,
    628 							cl_dlights[lnum].origin,
    629 							dist);
    630 			add = cl_dlights[lnum].radius - Length(dist);
    631 
    632 			if (add > 0) {
    633 				ambientlight += add;
    634 				//ZOID models should be affected by dlights as well
    635 				shadelight += add;
    636 			}
    637 		}
    638 	}
    639 
    640 	// clamp lighting so it doesn't overbright as much
    641 	if (ambientlight > 128)
    642 		ambientlight = 128;
    643 	if (ambientlight + shadelight > 192)
    644 		shadelight = 192 - ambientlight;
    645 
    646 	// ZOID: never allow players to go totally black
    647 	i = currententity - cl_entities;
    648 	if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
    649 		if (ambientlight < 8)
    650 			ambientlight = shadelight = 8;
    651 
    652 	// HACK HACK HACK -- no fullbright colors, so make torches full light
    653 	if (!strcmp (clmodel->name, "progs/flame2.mdl")
    654 		|| !strcmp (clmodel->name, "progs/flame.mdl") )
    655 		ambientlight = shadelight = 256;
    656 
    657 	shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
    658 	shadelight = shadelight / 200.0;
    659 
    660 	an = e->angles[1]/180*M_PI;
    661 	shadevector[0] = cos(-an);
    662 	shadevector[1] = sin(-an);
    663 	shadevector[2] = 1;
    664 	VectorNormalize (shadevector);
    665 
    666 	//
    667 	// locate the proper data
    668 	//
    669 	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
    670 
    671 	c_alias_polys += paliashdr->numtris;
    672 
    673 	//
    674 	// draw all the triangles
    675 	//
    676 
    677 	GL_DisableMultitexture();
    678 
    679     glPushMatrix ();
    680 	R_RotateForEntity (e);
    681 
    682 	if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) {
    683 		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
    684 // double size of eyes, since they are really hard to see in gl
    685 		glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
    686 	} else {
    687 		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
    688 		glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
    689 	}
    690 
    691 	anim = (int)(cl.time*10) & 3;
    692     GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);
    693 
    694 	// we can't dynamically colormap textures, so they are cached
    695 	// seperately for the players.  Heads are just uncolored.
    696 	if (currententity->colormap != vid.colormap && !gl_nocolors.value)
    697 	{
    698 		i = currententity - cl_entities;
    699 		if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
    700 		    GL_Bind(playertextures - 1 + i);
    701 	}
    702 
    703 	if (gl_smoothmodels.value)
    704 		glShadeModel (GL_SMOOTH);
    705 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    706 
    707 	if (gl_affinemodels.value)
    708 		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    709 
    710 	R_SetupAliasFrame (currententity->frame, paliashdr);
    711 
    712 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    713 
    714 	glShadeModel (GL_FLAT);
    715 	if (gl_affinemodels.value)
    716 		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    717 
    718 	glPopMatrix ();
    719 
    720 	if (r_shadows.value)
    721 	{
    722 		glPushMatrix ();
    723 		R_RotateForEntity (e);
    724 		glDisable (GL_TEXTURE_2D);
    725 		glEnable (GL_BLEND);
    726 		glColor4f (0,0,0,0.5);
    727 		GL_DrawAliasShadow (paliashdr, lastposenum);
    728 		glEnable (GL_TEXTURE_2D);
    729 		glDisable (GL_BLEND);
    730 		glColor4f (1,1,1,1);
    731 		glPopMatrix ();
    732 	}
    733 
    734 }
    735 
    736 //==================================================================================
    737 
    738 /*
    739 =============
    740 R_DrawEntitiesOnList
    741 =============
    742 */
    743 void R_DrawEntitiesOnList (void)
    744 {
    745 	int		i;
    746 
    747 	if (!r_drawentities.value)
    748 		return;
    749 
    750 	// draw sprites seperately, because of alpha blending
    751 	for (i=0 ; i<cl_numvisedicts ; i++)
    752 	{
    753 		currententity = cl_visedicts[i];
    754 
    755 		switch (currententity->model->type)
    756 		{
    757 		case mod_alias:
    758 			R_DrawAliasModel (currententity);
    759 			break;
    760 
    761 		case mod_brush:
    762 			R_DrawBrushModel (currententity);
    763 			break;
    764 
    765 		default:
    766 			break;
    767 		}
    768 	}
    769 
    770 	for (i=0 ; i<cl_numvisedicts ; i++)
    771 	{
    772 		currententity = cl_visedicts[i];
    773 
    774 		switch (currententity->model->type)
    775 		{
    776 		case mod_sprite:
    777 			R_DrawSpriteModel (currententity);
    778 			break;
    779 
    780 		default :
    781 			break;
    782 		}
    783 	}
    784 }
    785 
    786 /*
    787 =============
    788 R_DrawViewModel
    789 =============
    790 */
    791 void R_DrawViewModel (void)
    792 {
    793 	float		ambient[4], diffuse[4];
    794 	int			j;
    795 	int			lnum;
    796 	vec3_t		dist;
    797 	float		add;
    798 	dlight_t	*dl;
    799 	int			ambientlight, shadelight;
    800 
    801 	if (!r_drawviewmodel.value)
    802 		return;
    803 
    804 	if (chase_active.value)
    805 		return;
    806 
    807 	if (envmap)
    808 		return;
    809 
    810 	if (!r_drawentities.value)
    811 		return;
    812 
    813 	if (cl.items & IT_INVISIBILITY)
    814 		return;
    815 
    816 	if (cl.stats[STAT_HEALTH] <= 0)
    817 		return;
    818 
    819 	currententity = &cl.viewent;
    820 	if (!currententity->model)
    821 		return;
    822 
    823 	j = R_LightPoint (currententity->origin);
    824 
    825 	if (j < 24)
    826 		j = 24;		// allways give some light on gun
    827 	ambientlight = j;
    828 	shadelight = j;
    829 
    830 // add dynamic lights
    831 	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
    832 	{
    833 		dl = &cl_dlights[lnum];
    834 		if (!dl->radius)
    835 			continue;
    836 		if (!dl->radius)
    837 			continue;
    838 		if (dl->die < cl.time)
    839 			continue;
    840 
    841 		VectorSubtract (currententity->origin, dl->origin, dist);
    842 		add = dl->radius - Length(dist);
    843 		if (add > 0)
    844 			ambientlight += (int) add;
    845 	}
    846 
    847 	ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128;
    848 	diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;
    849 
    850 	// hack the depth range to prevent view model from poking into walls
    851 #ifdef USE_OPENGLES
    852 	glDepthRangef(gldepthmin, gldepthmin + 0.3f*(gldepthmax-gldepthmin));
    853 	R_DrawAliasModel (currententity);
    854 	glDepthRangef(gldepthmin, gldepthmax);
    855 #else
    856 	glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
    857 	R_DrawAliasModel (currententity);
    858 	glDepthRange (gldepthmin, gldepthmax);
    859 #endif
    860 }
    861 
    862 
    863 /*
    864 ============
    865 R_PolyBlend
    866 ============
    867 */
    868 void R_PolyBlend (void)
    869 {
    870 	if (!gl_polyblend.value)
    871 		return;
    872 	if (!v_blend[3])
    873 		return;
    874 
    875 	GL_DisableMultitexture();
    876 
    877 	glDisable (GL_ALPHA_TEST);
    878 	glEnable (GL_BLEND);
    879 	glDisable (GL_DEPTH_TEST);
    880 	glDisable (GL_TEXTURE_2D);
    881 
    882     glLoadIdentity ();
    883 
    884     glRotatef (-90,  1, 0, 0);	    // put Z going up
    885     glRotatef (90,  0, 0, 1);	    // put Z going up
    886 
    887 	glColor4fv (v_blend);
    888 
    889 #ifdef USE_OPENGLES
    890 	float vertex[3*4] = {
    891 		10, 100, 100,
    892 		10, -100, 100,
    893 		10, -100, -100,
    894 		10, 100, -100
    895 	};
    896 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    897 	glVertexPointer( 3, GL_FLOAT, 0, vertex);
    898 	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    899 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    900 #else
    901 	glBegin (GL_QUADS);
    902 
    903 	glVertex3f (10, 100, 100);
    904 	glVertex3f (10, -100, 100);
    905 	glVertex3f (10, -100, -100);
    906 	glVertex3f (10, 100, -100);
    907 	glEnd ();
    908 #endif
    909 
    910 	glDisable (GL_BLEND);
    911 	glEnable (GL_TEXTURE_2D);
    912 	glEnable (GL_ALPHA_TEST);
    913 }
    914 
    915 
    916 int SignbitsForPlane (mplane_t *out)
    917 {
    918 	int	bits, j;
    919 
    920 	// for fast box on planeside test
    921 
    922 	bits = 0;
    923 	for (j=0 ; j<3 ; j++)
    924 	{
    925 		if (out->normal[j] < 0)
    926 			bits |= 1<<j;
    927 	}
    928 	return bits;
    929 }
    930 
    931 
    932 void R_SetFrustum (void)
    933 {
    934 	int		i;
    935 
    936 	if (r_refdef.fov_x == 90)
    937 	{
    938 		// front side is visible
    939 
    940 		VectorAdd (vpn, vright, frustum[0].normal);
    941 		VectorSubtract (vpn, vright, frustum[1].normal);
    942 
    943 		VectorAdd (vpn, vup, frustum[2].normal);
    944 		VectorSubtract (vpn, vup, frustum[3].normal);
    945 	}
    946 	else
    947 	{
    948 		// rotate VPN right by FOV_X/2 degrees
    949 		RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
    950 		// rotate VPN left by FOV_X/2 degrees
    951 		RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
    952 		// rotate VPN up by FOV_X/2 degrees
    953 		RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
    954 		// rotate VPN down by FOV_X/2 degrees
    955 		RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
    956 	}
    957 
    958 	for (i=0 ; i<4 ; i++)
    959 	{
    960 		frustum[i].type = PLANE_ANYZ;
    961 		frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
    962 		frustum[i].signbits = SignbitsForPlane (&frustum[i]);
    963 	}
    964 }
    965 
    966 
    967 
    968 /*
    969 ===============
    970 R_SetupFrame
    971 ===============
    972 */
    973 void R_SetupFrame (void)
    974 {
    975 	int				edgecount;
    976 	vrect_t			vrect;
    977 	float			w, h;
    978 
    979 // don't allow cheats in multiplayer
    980 	if (cl.maxclients > 1)
    981 		Cvar_Set ("r_fullbright", "0");
    982 
    983 	R_AnimateLight ();
    984 
    985 	r_framecount++;
    986 
    987 // build the transformation matrix for the given view angles
    988 	VectorCopy (r_refdef.vieworg, r_origin);
    989 
    990 	AngleVectors (r_refdef.viewangles, vpn, vright, vup);
    991 
    992 // current viewleaf
    993 	r_oldviewleaf = r_viewleaf;
    994 	r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
    995 
    996 	V_SetContentsColor (r_viewleaf->contents);
    997 	V_CalcBlend ();
    998 
    999 	r_cache_thrash = false;
   1000 
   1001 	c_brush_polys = 0;
   1002 	c_alias_polys = 0;
   1003 
   1004 }
   1005 
   1006 #ifdef USE_OPENGLES
   1007 
   1008 void MYgluPerspective( float fovy, float aspect,
   1009 		     float zNear, float zFar )
   1010 {
   1011    float xmin, xmax, ymin, ymax;
   1012 
   1013    ymax = zNear * tan( fovy * M_PI / 360.0f );
   1014    ymin = -ymax;
   1015 
   1016    xmin = ymin * aspect;
   1017    xmax = ymax * aspect;
   1018 
   1019    glFrustumf( xmin, xmax, ymin, ymax, zNear, zFar );
   1020 }
   1021 
   1022 #else
   1023 
   1024 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
   1025 		     GLdouble zNear, GLdouble zFar )
   1026 {
   1027    GLdouble xmin, xmax, ymin, ymax;
   1028 
   1029    ymax = zNear * tan( fovy * M_PI / 360.0 );
   1030    ymin = -ymax;
   1031 
   1032    xmin = ymin * aspect;
   1033    xmax = ymax * aspect;
   1034 
   1035    glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
   1036 }
   1037 #endif
   1038 
   1039 #define DO_OWN_MATRIX_MATH
   1040 #ifdef DO_OWN_MATRIX_MATH
   1041 // We can't count on being able to read back the model view matrix, so calculate it ourselves.
   1042 
   1043 #define I(_i, _j) ((_j)+ 4*(_i))
   1044 
   1045 void mulMM(float* r, const float* lhs, const float* rhs)
   1046 {
   1047     float const* const m = lhs;
   1048     for (int i=0 ; i<4 ; i++) {
   1049         register const float rhs_i0 = rhs[ I(i,0) ];
   1050         register float ri0 = m[ I(0,0) ] * rhs_i0;
   1051         register float ri1 = m[ I(0,1) ] * rhs_i0;
   1052         register float ri2 = m[ I(0,2) ] * rhs_i0;
   1053         register float ri3 = m[ I(0,3) ] * rhs_i0;
   1054         for (int j=1 ; j<4 ; j++) {
   1055             register const float rhs_ij = rhs[ I(i,j) ];
   1056             ri0 += m[ I(j,0) ] * rhs_ij;
   1057             ri1 += m[ I(j,1) ] * rhs_ij;
   1058             ri2 += m[ I(j,2) ] * rhs_ij;
   1059             ri3 += m[ I(j,3) ] * rhs_ij;
   1060         }
   1061         r[ I(i,0) ] = ri0;
   1062         r[ I(i,1) ] = ri1;
   1063         r[ I(i,2) ] = ri2;
   1064         r[ I(i,3) ] = ri3;
   1065     }
   1066 }
   1067 
   1068 static void setIdentityM(float* sm, int smOffset) {
   1069     for (int i=0 ; i<16 ; i++) {
   1070         sm[smOffset + i] = 0;
   1071     }
   1072     for(int i = 0; i < 16; i += 5) {
   1073         sm[smOffset + i] = 1.0f;
   1074     }
   1075 }
   1076 
   1077 static void translateM(float* m, int mOffset,
   1078         float x, float y, float z) {
   1079     for (int i=0 ; i<4 ; i++) {
   1080         int mi = mOffset + i;
   1081         m[12 + mi] += m[mi] * x + m[4 + mi] * y + m[8 + mi] * z;
   1082     }
   1083 }
   1084 
   1085 static float length(float x, float y, float z) {
   1086 	return (float) sqrtf(x * x + y * y + z * z);
   1087 }
   1088 
   1089 static void setRotateM(float* rm, int rmOffset,
   1090             float a, float x, float y, float z)
   1091 {
   1092     rm[rmOffset + 3] = 0;
   1093     rm[rmOffset + 7] = 0;
   1094     rm[rmOffset + 11]= 0;
   1095     rm[rmOffset + 12]= 0;
   1096     rm[rmOffset + 13]= 0;
   1097     rm[rmOffset + 14]= 0;
   1098     rm[rmOffset + 15]= 1;
   1099     a *= (float) (M_PI / 180.0f);
   1100     float s = (float) sinf(a);
   1101     float c = (float) cosf(a);
   1102     if (1.0f == x && 0.0f == y && 0.0f == z) {
   1103         rm[rmOffset + 5] = c;   rm[rmOffset + 10]= c;
   1104         rm[rmOffset + 6] = s;   rm[rmOffset + 9] = -s;
   1105         rm[rmOffset + 1] = 0;   rm[rmOffset + 2] = 0;
   1106         rm[rmOffset + 4] = 0;   rm[rmOffset + 8] = 0;
   1107         rm[rmOffset + 0] = 1;
   1108     } else if (0.0f == x && 1.0f == y && 0.0f == z) {
   1109         rm[rmOffset + 0] = c;   rm[rmOffset + 10]= c;
   1110         rm[rmOffset + 8] = s;   rm[rmOffset + 2] = -s;
   1111         rm[rmOffset + 1] = 0;   rm[rmOffset + 4] = 0;
   1112         rm[rmOffset + 6] = 0;   rm[rmOffset + 9] = 0;
   1113         rm[rmOffset + 5] = 1;
   1114     } else if (0.0f == x && 0.0f == y && 1.0f == z) {
   1115         rm[rmOffset + 0] = c;   rm[rmOffset + 5] = c;
   1116         rm[rmOffset + 1] = s;   rm[rmOffset + 4] = -s;
   1117         rm[rmOffset + 2] = 0;   rm[rmOffset + 6] = 0;
   1118         rm[rmOffset + 8] = 0;   rm[rmOffset + 9] = 0;
   1119         rm[rmOffset + 10]= 1;
   1120     } else {
   1121         float len = length(x, y, z);
   1122         if (1.0f != len) {
   1123             float recipLen = 1.0f / len;
   1124             x *= recipLen;
   1125             y *= recipLen;
   1126             z *= recipLen;
   1127         }
   1128         float nc = 1.0f - c;
   1129         float xy = x * y;
   1130         float yz = y * z;
   1131         float zx = z * x;
   1132         float xs = x * s;
   1133         float ys = y * s;
   1134         float zs = z * s;
   1135         rm[rmOffset +  0] = x*x*nc +  c;
   1136         rm[rmOffset +  4] =  xy*nc - zs;
   1137         rm[rmOffset +  8] =  zx*nc + ys;
   1138         rm[rmOffset +  1] =  xy*nc + zs;
   1139         rm[rmOffset +  5] = y*y*nc +  c;
   1140         rm[rmOffset +  9] =  yz*nc - xs;
   1141         rm[rmOffset +  2] =  zx*nc - ys;
   1142         rm[rmOffset +  6] =  yz*nc + xs;
   1143         rm[rmOffset + 10] = z*z*nc +  c;
   1144     }
   1145 }
   1146 
   1147 static void rotateM(float* m,
   1148             float a, float x, float y, float z) {
   1149     float temp[16];
   1150     float temp2[16];
   1151     setRotateM(temp, 0, a, x, y, z);
   1152     mulMM(temp2, m, temp);
   1153     memcpy(m, temp2, 16 * sizeof(float));
   1154 }
   1155 
   1156 #undef I
   1157 
   1158 #endif // DO_OWN_MATRIX_MATH
   1159 
   1160 /*
   1161 =============
   1162 R_SetupGL
   1163 =============
   1164 */
   1165 void R_SetupGL (void)
   1166 {
   1167 	float	screenaspect;
   1168 	float	yfov;
   1169 	int		i;
   1170 	extern	int glwidth, glheight;
   1171 	int		x, x2, y2, y, w, h;
   1172 
   1173 	//
   1174 	// set up viewpoint
   1175 	//
   1176 	glMatrixMode(GL_PROJECTION);
   1177     glLoadIdentity ();
   1178 	x = r_refdef.vrect.x * glwidth/vid.width;
   1179 	x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
   1180 	y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
   1181 	y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
   1182 
   1183 	// fudge around because of frac screen scale
   1184 	if (x > 0)
   1185 		x--;
   1186 	if (x2 < glwidth)
   1187 		x2++;
   1188 	if (y2 < 0)
   1189 		y2--;
   1190 	if (y < glheight)
   1191 		y++;
   1192 
   1193 	w = x2 - x;
   1194 	h = y - y2;
   1195 
   1196 	if (envmap)
   1197 	{
   1198 		x = y2 = 0;
   1199 		w = h = 256;
   1200 	}
   1201 
   1202 	glViewport (glx + x, gly + y2, w, h);
   1203     screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
   1204 //	yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
   1205     MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  4096);
   1206 
   1207 	if (mirror)
   1208 	{
   1209 		if (mirror_plane->normal[2])
   1210 			glScalef (1, -1, 1);
   1211 		else
   1212 			glScalef (-1, 1, 1);
   1213 		glCullFace(GL_BACK);
   1214 	}
   1215 	else
   1216 		glCullFace(GL_FRONT);
   1217 
   1218 	glMatrixMode(GL_MODELVIEW);
   1219 
   1220 #ifdef DO_OWN_MATRIX_MATH
   1221 
   1222 	float mv[16];
   1223     setIdentityM(mv, 0);
   1224 
   1225     rotateM(mv, -90,  1, 0, 0);	    // put Z going up
   1226     rotateM(mv, 90,  0, 0, 1);	    // put Z going up
   1227     rotateM(mv, -r_refdef.viewangles[2],  1, 0, 0);
   1228     rotateM(mv, -r_refdef.viewangles[0],  0, 1, 0);
   1229     rotateM(mv, -r_refdef.viewangles[1],  0, 0, 1);
   1230     translateM(mv, 0, -r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
   1231 
   1232     glLoadMatrixf(mv);
   1233 
   1234     memcpy(r_world_matrix, mv, sizeof(r_world_matrix));
   1235 
   1236 #else
   1237     glLoadIdentity ();
   1238 
   1239     glRotatef (-90,  1, 0, 0);	    // put Z going up
   1240     glRotatef (90,  0, 0, 1);	    // put Z going up
   1241     glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
   1242     glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
   1243     glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
   1244     glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
   1245 
   1246 #ifdef USE_OPENGLES
   1247 
   1248     static qboolean initialized;
   1249     static qboolean haveGL_OES_matrix_get;
   1250     static qboolean haveGL_OES_query_matrix;
   1251 
   1252 #if 0
   1253     if (! initialized) {
   1254         const char* extensions = (const char*) glGetString(GL_EXTENSIONS);
   1255         haveGL_OES_matrix_get =
   1256             strstr(extensions, "GL_OES_matrix_get") != NULL;
   1257         haveGL_OES_query_matrix =
   1258             strstr(extensions, "GL_OES_query_matrix") != NULL;
   1259         initialized = true;
   1260     }
   1261     if (haveGL_OES_query_matrix) {
   1262         GLfixed mantissa[16];
   1263         GLint exponent[16];
   1264         glQueryMatrixxOES( mantissa, exponent );
   1265         for(int i = 0; i < 16; i++) {
   1266             r_world_matrix[i] = scalbnf(mantissa[i], exponent[i]-16);
   1267         }
   1268     }
   1269     else if (haveGL_OES_matrix_get) {
   1270         glGetIntegerv (MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,
   1271                 (GLint*) r_world_matrix);
   1272     }
   1273     else
   1274 #endif
   1275     	{
   1276         // No way to get the world matix, set to identity
   1277         memset(r_world_matrix, 0, sizeof(r_world_matrix));
   1278         for(i = 0; i < 16; i += 5) {
   1279             r_world_matrix[i] = 1.0f;
   1280         }
   1281     }
   1282 #else
   1283 	glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
   1284 #endif
   1285 #endif // DO_OWN_MATRIX_MATH
   1286 	//
   1287 	// set drawing parms
   1288 	//
   1289 	if (gl_cull.value)
   1290 		glEnable(GL_CULL_FACE);
   1291 	else
   1292 		glDisable(GL_CULL_FACE);
   1293 
   1294 	glDisable(GL_BLEND);
   1295 	glDisable(GL_ALPHA_TEST);
   1296 	glEnable(GL_DEPTH_TEST);
   1297 }
   1298 
   1299 /*
   1300 ================
   1301 R_RenderScene
   1302 
   1303 r_refdef must be set before the first call
   1304 ================
   1305 */
   1306 void R_RenderScene (void)
   1307 {
   1308 	R_SetupFrame ();
   1309 
   1310 	R_SetFrustum ();
   1311 
   1312 	R_SetupGL ();
   1313 
   1314 	R_MarkLeaves ();	// done here so we know if we're in water
   1315 
   1316 	R_DrawWorld ();		// adds static entities to the list
   1317 
   1318 	S_ExtraUpdate ();	// don't let sound get messed up if going slow
   1319 
   1320 	R_DrawEntitiesOnList ();
   1321 
   1322 	GL_DisableMultitexture();
   1323 
   1324 	R_RenderDlights ();
   1325 
   1326 	R_DrawParticles ();
   1327 
   1328 #ifdef GLTEST
   1329 	Test_Draw ();
   1330 #endif
   1331 
   1332 }
   1333 
   1334 
   1335 /*
   1336 =============
   1337 R_Clear
   1338 =============
   1339 */
   1340 void R_Clear (void)
   1341 {
   1342 	if (r_mirroralpha.value != 1.0)
   1343 	{
   1344 		if (gl_clear.value)
   1345 			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   1346 		else
   1347 			glClear (GL_DEPTH_BUFFER_BIT);
   1348 		gldepthmin = 0;
   1349 		gldepthmax = 0.5;
   1350 		glDepthFunc (GL_LEQUAL);
   1351 	}
   1352 	else if (gl_ztrick.value)
   1353 	{
   1354 		static int trickframe;
   1355 
   1356 		if (gl_clear.value)
   1357 			glClear (GL_COLOR_BUFFER_BIT);
   1358 
   1359 		trickframe++;
   1360 		if (trickframe & 1)
   1361 		{
   1362 			gldepthmin = 0;
   1363 			gldepthmax = 0.49999;
   1364 			glDepthFunc (GL_LEQUAL);
   1365 		}
   1366 		else
   1367 		{
   1368 			gldepthmin = 1;
   1369 			gldepthmax = 0.5;
   1370 			glDepthFunc (GL_GEQUAL);
   1371 		}
   1372 	}
   1373 	else
   1374 	{
   1375 		if (gl_clear.value)
   1376 			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
   1377 		else
   1378 			glClear (GL_DEPTH_BUFFER_BIT);
   1379 		gldepthmin = 0;
   1380 		gldepthmax = 1;
   1381 		glDepthFunc (GL_LEQUAL);
   1382 	}
   1383 
   1384 #ifdef USE_OPENGLES
   1385 	glDepthRangef (gldepthmin, gldepthmax);
   1386 #else
   1387 	glDepthRange (gldepthmin, gldepthmax);
   1388 #endif
   1389 }
   1390 
   1391 /*
   1392 =============
   1393 R_Mirror
   1394 =============
   1395 */
   1396 void R_Mirror (void)
   1397 {
   1398 	float		d;
   1399 	msurface_t	*s;
   1400 	entity_t	*ent;
   1401 
   1402 	if (!mirror)
   1403 		return;
   1404 
   1405 	memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
   1406 
   1407 	d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist;
   1408 	VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg);
   1409 
   1410 	d = DotProduct (vpn, mirror_plane->normal);
   1411 	VectorMA (vpn, -2*d, mirror_plane->normal, vpn);
   1412 
   1413 	r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
   1414 	r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
   1415 	r_refdef.viewangles[2] = -r_refdef.viewangles[2];
   1416 
   1417 	ent = &cl_entities[cl.viewentity];
   1418 	if (cl_numvisedicts < MAX_VISEDICTS)
   1419 	{
   1420 		cl_visedicts[cl_numvisedicts] = ent;
   1421 		cl_numvisedicts++;
   1422 	}
   1423 
   1424 	gldepthmin = 0.5;
   1425 	gldepthmax = 1;
   1426 #ifdef USE_OPENGLES
   1427 	glDepthRangef (gldepthmin, gldepthmax);
   1428 #else
   1429 	glDepthRange (gldepthmin, gldepthmax);
   1430 #endif
   1431 	glDepthFunc (GL_LEQUAL);
   1432 
   1433 	R_RenderScene ();
   1434 	R_DrawWaterSurfaces ();
   1435 
   1436 	gldepthmin = 0;
   1437 	gldepthmax = 0.5;
   1438 #ifdef USE_OPENGLES
   1439 	glDepthRangef (gldepthmin, gldepthmax);
   1440 #else
   1441 	glDepthRange (gldepthmin, gldepthmax);
   1442 #endif
   1443 	glDepthFunc (GL_LEQUAL);
   1444 
   1445 	// blend on top
   1446 	glEnable (GL_BLEND);
   1447 	glMatrixMode(GL_PROJECTION);
   1448 	if (mirror_plane->normal[2])
   1449 		glScalef (1,-1,1);
   1450 	else
   1451 		glScalef (-1,1,1);
   1452 	glCullFace(GL_FRONT);
   1453 	glMatrixMode(GL_MODELVIEW);
   1454 
   1455 	glLoadMatrixf (r_base_world_matrix);
   1456 
   1457 	glColor4f (1,1,1,r_mirroralpha.value);
   1458 	s = cl.worldmodel->textures[mirrortexturenum]->texturechain;
   1459 	for ( ; s ; s=s->texturechain)
   1460 		R_RenderBrushPoly (s);
   1461 	cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
   1462 	glDisable (GL_BLEND);
   1463 	glColor4f (1,1,1,1);
   1464 }
   1465 
   1466 /*
   1467 ================
   1468 R_RenderView
   1469 
   1470 r_refdef must be set before the first call
   1471 ================
   1472 */
   1473 void R_RenderView (void)
   1474 {
   1475 	double time1 = 0.0;
   1476 	double time2;
   1477 	GLfloat colors[4] = {(GLfloat) 0.0, (GLfloat) 0.0, (GLfloat) 1, (GLfloat) 0.20};
   1478 
   1479 	if (r_norefresh.value)
   1480 		return;
   1481 
   1482 	if (!r_worldentity.model || !cl.worldmodel)
   1483 		Sys_Error ("R_RenderView: NULL worldmodel");
   1484 
   1485 	if (r_speeds.value)
   1486 	{
   1487 		glFinish ();
   1488 		time1 = Sys_FloatTime ();
   1489 		c_brush_polys = 0;
   1490 		c_alias_polys = 0;
   1491 	}
   1492 
   1493 	mirror = false;
   1494 
   1495 	if (gl_finish.value)
   1496 		glFinish ();
   1497 
   1498 	R_Clear ();
   1499 
   1500 	// render normal view
   1501 
   1502 /***** Experimental silly looking fog ******
   1503 ****** Use r_fullbright if you enable ******
   1504 	glFogi(GL_FOG_MODE, GL_LINEAR);
   1505 	glFogfv(GL_FOG_COLOR, colors);
   1506 	glFogf(GL_FOG_END, 512.0);
   1507 	glEnable(GL_FOG);
   1508 ********************************************/
   1509 
   1510 	R_RenderScene ();
   1511 	R_DrawViewModel ();
   1512 	R_DrawWaterSurfaces ();
   1513 
   1514 //  More fog right here :)
   1515 //	glDisable(GL_FOG);
   1516 //  End of all fog code...
   1517 
   1518 	// render mirror view
   1519 	R_Mirror ();
   1520 
   1521 	R_PolyBlend ();
   1522 
   1523 	if (r_speeds.value)
   1524 	{
   1525 //		glFinish ();
   1526 		time2 = Sys_FloatTime ();
   1527 		Con_Printf ("%3i ms  %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys);
   1528 	}
   1529 }
   1530