Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

gl_rmain.c (39236B)


      1 /*
      2 Copyright (C) 1997-2001 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 #include "gl_local.h"
     22 
     23 void R_Clear (void);
     24 
     25 viddef_t	vid;
     26 
     27 refimport_t	ri;
     28 
     29 model_t		*r_worldmodel;
     30 
     31 float		gldepthmin, gldepthmax;
     32 
     33 glconfig_t gl_config;
     34 glstate_t  gl_state;
     35 
     36 image_t		*r_notexture;		// use for bad textures
     37 image_t		*r_particletexture;	// little dot for particles
     38 
     39 entity_t	*currententity;
     40 model_t		*currentmodel;
     41 
     42 cplane_t	frustum[4];
     43 
     44 int			r_visframecount;	// bumped when going to a new PVS
     45 int			r_framecount;		// used for dlight push checking
     46 
     47 int			c_brush_polys, c_alias_polys;
     48 
     49 float		v_blend[4];			// final blending color
     50 
     51 void GL_Strings_f( void );
     52 
     53 //
     54 // view origin
     55 //
     56 vec3_t	vup;
     57 vec3_t	vpn;
     58 vec3_t	vright;
     59 vec3_t	r_origin;
     60 
     61 float	r_world_matrix[16];
     62 float	r_base_world_matrix[16];
     63 
     64 //
     65 // screen size info
     66 //
     67 refdef_t	r_newrefdef;
     68 
     69 int		r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
     70 
     71 cvar_t	*r_norefresh;
     72 cvar_t	*r_drawentities;
     73 cvar_t	*r_drawworld;
     74 cvar_t	*r_speeds;
     75 cvar_t	*r_fullbright;
     76 cvar_t	*r_novis;
     77 cvar_t	*r_nocull;
     78 cvar_t	*r_lerpmodels;
     79 cvar_t	*r_lefthand;
     80 
     81 cvar_t	*r_lightlevel;	// FIXME: This is a HACK to get the client's light level
     82 
     83 cvar_t	*gl_nosubimage;
     84 cvar_t	*gl_allow_software;
     85 
     86 cvar_t	*gl_vertex_arrays;
     87 
     88 cvar_t	*gl_particle_min_size;
     89 cvar_t	*gl_particle_max_size;
     90 cvar_t	*gl_particle_size;
     91 cvar_t	*gl_particle_att_a;
     92 cvar_t	*gl_particle_att_b;
     93 cvar_t	*gl_particle_att_c;
     94 
     95 cvar_t	*gl_ext_swapinterval;
     96 cvar_t	*gl_ext_palettedtexture;
     97 cvar_t	*gl_ext_multitexture;
     98 cvar_t	*gl_ext_pointparameters;
     99 cvar_t	*gl_ext_compiled_vertex_array;
    100 
    101 cvar_t	*gl_log;
    102 cvar_t	*gl_bitdepth;
    103 cvar_t	*gl_drawbuffer;
    104 cvar_t  *gl_driver;
    105 cvar_t	*gl_lightmap;
    106 cvar_t	*gl_shadows;
    107 cvar_t	*gl_mode;
    108 cvar_t	*gl_dynamic;
    109 cvar_t  *gl_monolightmap;
    110 cvar_t	*gl_modulate;
    111 cvar_t	*gl_nobind;
    112 cvar_t	*gl_round_down;
    113 cvar_t	*gl_picmip;
    114 cvar_t	*gl_skymip;
    115 cvar_t	*gl_showtris;
    116 cvar_t	*gl_ztrick;
    117 cvar_t	*gl_finish;
    118 cvar_t	*gl_clear;
    119 cvar_t	*gl_cull;
    120 cvar_t	*gl_polyblend;
    121 cvar_t	*gl_flashblend;
    122 cvar_t	*gl_playermip;
    123 cvar_t  *gl_saturatelighting;
    124 cvar_t	*gl_swapinterval;
    125 cvar_t	*gl_texturemode;
    126 cvar_t	*gl_texturealphamode;
    127 cvar_t	*gl_texturesolidmode;
    128 cvar_t	*gl_lockpvs;
    129 
    130 cvar_t	*gl_3dlabs_broken;
    131 
    132 cvar_t	*vid_fullscreen;
    133 cvar_t	*vid_gamma;
    134 cvar_t	*vid_ref;
    135 
    136 /*
    137 =================
    138 R_CullBox
    139 
    140 Returns true if the box is completely outside the frustom
    141 =================
    142 */
    143 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
    144 {
    145 	int		i;
    146 
    147 	if (r_nocull->value)
    148 		return false;
    149 
    150 	for (i=0 ; i<4 ; i++)
    151 		if ( BOX_ON_PLANE_SIDE(mins, maxs, &frustum[i]) == 2)
    152 			return true;
    153 	return false;
    154 }
    155 
    156 
    157 void R_RotateForEntity (entity_t *e)
    158 {
    159     qglTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
    160 
    161     qglRotatef (e->angles[1],  0, 0, 1);
    162     qglRotatef (-e->angles[0],  0, 1, 0);
    163     qglRotatef (-e->angles[2],  1, 0, 0);
    164 }
    165 
    166 /*
    167 =============================================================
    168 
    169   SPRITE MODELS
    170 
    171 =============================================================
    172 */
    173 
    174 
    175 /*
    176 =================
    177 R_DrawSpriteModel
    178 
    179 =================
    180 */
    181 void R_DrawSpriteModel (entity_t *e)
    182 {
    183 	float alpha = 1.0F;
    184 	vec3_t	point;
    185 	dsprframe_t	*frame;
    186 	float		*up, *right;
    187 	dsprite_t		*psprite;
    188 
    189 	// don't even bother culling, because it's just a single
    190 	// polygon without a surface cache
    191 
    192 	psprite = (dsprite_t *)currentmodel->extradata;
    193 
    194 #if 0
    195 	if (e->frame < 0 || e->frame >= psprite->numframes)
    196 	{
    197 		ri.Con_Printf (PRINT_ALL, "no such sprite frame %i\n", e->frame);
    198 		e->frame = 0;
    199 	}
    200 #endif
    201 	e->frame %= psprite->numframes;
    202 
    203 	frame = &psprite->frames[e->frame];
    204 
    205 #if 0
    206 	if (psprite->type == SPR_ORIENTED)
    207 	{	// bullet marks on walls
    208 	vec3_t		v_forward, v_right, v_up;
    209 
    210 	AngleVectors (currententity->angles, v_forward, v_right, v_up);
    211 		up = v_up;
    212 		right = v_right;
    213 	}
    214 	else
    215 #endif
    216 	{	// normal sprite
    217 		up = vup;
    218 		right = vright;
    219 	}
    220 
    221 	if ( e->flags & RF_TRANSLUCENT )
    222 		alpha = e->alpha;
    223 
    224 	if ( alpha != 1.0F )
    225 		qglEnable( GL_BLEND );
    226 
    227 	qglColor4f( 1, 1, 1, alpha );
    228 
    229     GL_Bind(currentmodel->skins[e->frame]->texnum);
    230 
    231 	GL_TexEnv( GL_MODULATE );
    232 
    233 	if ( alpha == 1.0 )
    234 		qglEnable (GL_ALPHA_TEST);
    235 	else
    236 		qglDisable( GL_ALPHA_TEST );
    237 
    238 	qglBegin (GL_QUADS);
    239 
    240 	qglTexCoord2f (0, 1);
    241 	VectorMA (e->origin, -frame->origin_y, up, point);
    242 	VectorMA (point, -frame->origin_x, right, point);
    243 	qglVertex3fv (point);
    244 
    245 	qglTexCoord2f (0, 0);
    246 	VectorMA (e->origin, frame->height - frame->origin_y, up, point);
    247 	VectorMA (point, -frame->origin_x, right, point);
    248 	qglVertex3fv (point);
    249 
    250 	qglTexCoord2f (1, 0);
    251 	VectorMA (e->origin, frame->height - frame->origin_y, up, point);
    252 	VectorMA (point, frame->width - frame->origin_x, right, point);
    253 	qglVertex3fv (point);
    254 
    255 	qglTexCoord2f (1, 1);
    256 	VectorMA (e->origin, -frame->origin_y, up, point);
    257 	VectorMA (point, frame->width - frame->origin_x, right, point);
    258 	qglVertex3fv (point);
    259 	
    260 	qglEnd ();
    261 
    262 	qglDisable (GL_ALPHA_TEST);
    263 	GL_TexEnv( GL_REPLACE );
    264 
    265 	if ( alpha != 1.0F )
    266 		qglDisable( GL_BLEND );
    267 
    268 	qglColor4f( 1, 1, 1, 1 );
    269 }
    270 
    271 //==================================================================================
    272 
    273 /*
    274 =============
    275 R_DrawNullModel
    276 =============
    277 */
    278 void R_DrawNullModel (void)
    279 {
    280 	vec3_t	shadelight;
    281 	int		i;
    282 
    283 	if ( currententity->flags & RF_FULLBRIGHT )
    284 		shadelight[0] = shadelight[1] = shadelight[2] = 1.0F;
    285 	else
    286 		R_LightPoint (currententity->origin, shadelight);
    287 
    288     qglPushMatrix ();
    289 	R_RotateForEntity (currententity);
    290 
    291 	qglDisable (GL_TEXTURE_2D);
    292 	qglColor3fv (shadelight);
    293 
    294 	qglBegin (GL_TRIANGLE_FAN);
    295 	qglVertex3f (0, 0, -16);
    296 	for (i=0 ; i<=4 ; i++)
    297 		qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0);
    298 	qglEnd ();
    299 
    300 	qglBegin (GL_TRIANGLE_FAN);
    301 	qglVertex3f (0, 0, 16);
    302 	for (i=4 ; i>=0 ; i--)
    303 		qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0);
    304 	qglEnd ();
    305 
    306 	qglColor3f (1,1,1);
    307 	qglPopMatrix ();
    308 	qglEnable (GL_TEXTURE_2D);
    309 }
    310 
    311 /*
    312 =============
    313 R_DrawEntitiesOnList
    314 =============
    315 */
    316 void R_DrawEntitiesOnList (void)
    317 {
    318 	int		i;
    319 
    320 	if (!r_drawentities->value)
    321 		return;
    322 
    323 	// draw non-transparent first
    324 	for (i=0 ; i<r_newrefdef.num_entities ; i++)
    325 	{
    326 		currententity = &r_newrefdef.entities[i];
    327 		if (currententity->flags & RF_TRANSLUCENT)
    328 			continue;	// solid
    329 
    330 		if ( currententity->flags & RF_BEAM )
    331 		{
    332 			R_DrawBeam( currententity );
    333 		}
    334 		else
    335 		{
    336 			currentmodel = currententity->model;
    337 			if (!currentmodel)
    338 			{
    339 				R_DrawNullModel ();
    340 				continue;
    341 			}
    342 			switch (currentmodel->type)
    343 			{
    344 			case mod_alias:
    345 				R_DrawAliasModel (currententity);
    346 				break;
    347 			case mod_brush:
    348 				R_DrawBrushModel (currententity);
    349 				break;
    350 			case mod_sprite:
    351 				R_DrawSpriteModel (currententity);
    352 				break;
    353 			default:
    354 				ri.Sys_Error (ERR_DROP, "Bad modeltype");
    355 				break;
    356 			}
    357 		}
    358 	}
    359 
    360 	// draw transparent entities
    361 	// we could sort these if it ever becomes a problem...
    362 	qglDepthMask (0);		// no z writes
    363 	for (i=0 ; i<r_newrefdef.num_entities ; i++)
    364 	{
    365 		currententity = &r_newrefdef.entities[i];
    366 		if (!(currententity->flags & RF_TRANSLUCENT))
    367 			continue;	// solid
    368 
    369 		if ( currententity->flags & RF_BEAM )
    370 		{
    371 			R_DrawBeam( currententity );
    372 		}
    373 		else
    374 		{
    375 			currentmodel = currententity->model;
    376 
    377 			if (!currentmodel)
    378 			{
    379 				R_DrawNullModel ();
    380 				continue;
    381 			}
    382 			switch (currentmodel->type)
    383 			{
    384 			case mod_alias:
    385 				R_DrawAliasModel (currententity);
    386 				break;
    387 			case mod_brush:
    388 				R_DrawBrushModel (currententity);
    389 				break;
    390 			case mod_sprite:
    391 				R_DrawSpriteModel (currententity);
    392 				break;
    393 			default:
    394 				ri.Sys_Error (ERR_DROP, "Bad modeltype");
    395 				break;
    396 			}
    397 		}
    398 	}
    399 	qglDepthMask (1);		// back to writing
    400 
    401 }
    402 
    403 /*
    404 ** GL_DrawParticles
    405 **
    406 */
    407 void GL_DrawParticles( int num_particles, const particle_t particles[], const unsigned colortable[768] )
    408 {
    409 	const particle_t *p;
    410 	int				i;
    411 	vec3_t			up, right;
    412 	float			scale;
    413 	byte			color[4];
    414 
    415     GL_Bind(r_particletexture->texnum);
    416 	qglDepthMask( GL_FALSE );		// no z buffering
    417 	qglEnable( GL_BLEND );
    418 	GL_TexEnv( GL_MODULATE );
    419 	qglBegin( GL_TRIANGLES );
    420 
    421 	VectorScale (vup, 1.5, up);
    422 	VectorScale (vright, 1.5, right);
    423 
    424 	for ( p = particles, i=0 ; i < num_particles ; i++,p++)
    425 	{
    426 		// hack a scale up to keep particles from disapearing
    427 		scale = ( p->origin[0] - r_origin[0] ) * vpn[0] + 
    428 			    ( p->origin[1] - r_origin[1] ) * vpn[1] +
    429 			    ( p->origin[2] - r_origin[2] ) * vpn[2];
    430 
    431 		if (scale < 20)
    432 			scale = 1;
    433 		else
    434 			scale = 1 + scale * 0.004;
    435 
    436 		*(int *)color = colortable[p->color];
    437 		color[3] = p->alpha*255;
    438 
    439 		qglColor4ubv( color );
    440 
    441 		qglTexCoord2f( 0.0625, 0.0625 );
    442 		qglVertex3fv( p->origin );
    443 
    444 		qglTexCoord2f( 1.0625, 0.0625 );
    445 		qglVertex3f( p->origin[0] + up[0]*scale, 
    446 			         p->origin[1] + up[1]*scale, 
    447 					 p->origin[2] + up[2]*scale);
    448 
    449 		qglTexCoord2f( 0.0625, 1.0625 );
    450 		qglVertex3f( p->origin[0] + right[0]*scale, 
    451 			         p->origin[1] + right[1]*scale, 
    452 					 p->origin[2] + right[2]*scale);
    453 	}
    454 
    455 	qglEnd ();
    456 	qglDisable( GL_BLEND );
    457 	qglColor4f( 1,1,1,1 );
    458 	qglDepthMask( 1 );		// back to normal Z buffering
    459 	GL_TexEnv( GL_REPLACE );
    460 }
    461 
    462 /*
    463 ===============
    464 R_DrawParticles
    465 ===============
    466 */
    467 void R_DrawParticles (void)
    468 {
    469 	if ( gl_ext_pointparameters->value && qglPointParameterfEXT )
    470 	{
    471 		int i;
    472 		unsigned char color[4];
    473 		const particle_t *p;
    474 
    475 		qglDepthMask( GL_FALSE );
    476 		qglEnable( GL_BLEND );
    477 		qglDisable( GL_TEXTURE_2D );
    478 
    479 		qglPointSize( gl_particle_size->value );
    480 
    481 		qglBegin( GL_POINTS );
    482 		for ( i = 0, p = r_newrefdef.particles; i < r_newrefdef.num_particles; i++, p++ )
    483 		{
    484 			*(int *)color = d_8to24table[p->color];
    485 			color[3] = p->alpha*255;
    486 
    487 			qglColor4ubv( color );
    488 
    489 			qglVertex3fv( p->origin );
    490 		}
    491 		qglEnd();
    492 
    493 		qglDisable( GL_BLEND );
    494 		qglColor4f( 1.0F, 1.0F, 1.0F, 1.0F );
    495 		qglDepthMask( GL_TRUE );
    496 		qglEnable( GL_TEXTURE_2D );
    497 
    498 	}
    499 	else
    500 	{
    501 		GL_DrawParticles( r_newrefdef.num_particles, r_newrefdef.particles, d_8to24table );
    502 	}
    503 }
    504 
    505 /*
    506 ============
    507 R_PolyBlend
    508 ============
    509 */
    510 void R_PolyBlend (void)
    511 {
    512 	if (!gl_polyblend->value)
    513 		return;
    514 	if (!v_blend[3])
    515 		return;
    516 
    517 	qglDisable (GL_ALPHA_TEST);
    518 	qglEnable (GL_BLEND);
    519 	qglDisable (GL_DEPTH_TEST);
    520 	qglDisable (GL_TEXTURE_2D);
    521 
    522     qglLoadIdentity ();
    523 
    524 	// FIXME: get rid of these
    525     qglRotatef (-90,  1, 0, 0);	    // put Z going up
    526     qglRotatef (90,  0, 0, 1);	    // put Z going up
    527 
    528 	qglColor4fv (v_blend);
    529 
    530 	qglBegin (GL_QUADS);
    531 
    532 	qglVertex3f (10, 100, 100);
    533 	qglVertex3f (10, -100, 100);
    534 	qglVertex3f (10, -100, -100);
    535 	qglVertex3f (10, 100, -100);
    536 	qglEnd ();
    537 
    538 	qglDisable (GL_BLEND);
    539 	qglEnable (GL_TEXTURE_2D);
    540 	qglEnable (GL_ALPHA_TEST);
    541 
    542 	qglColor4f(1,1,1,1);
    543 }
    544 
    545 //=======================================================================
    546 
    547 int SignbitsForPlane (cplane_t *out)
    548 {
    549 	int	bits, j;
    550 
    551 	// for fast box on planeside test
    552 
    553 	bits = 0;
    554 	for (j=0 ; j<3 ; j++)
    555 	{
    556 		if (out->normal[j] < 0)
    557 			bits |= 1<<j;
    558 	}
    559 	return bits;
    560 }
    561 
    562 
    563 void R_SetFrustum (void)
    564 {
    565 	int		i;
    566 
    567 #if 0
    568 	/*
    569 	** this code is wrong, since it presume a 90 degree FOV both in the
    570 	** horizontal and vertical plane
    571 	*/
    572 	// front side is visible
    573 	VectorAdd (vpn, vright, frustum[0].normal);
    574 	VectorSubtract (vpn, vright, frustum[1].normal);
    575 	VectorAdd (vpn, vup, frustum[2].normal);
    576 	VectorSubtract (vpn, vup, frustum[3].normal);
    577 
    578 	// we theoretically don't need to normalize these vectors, but I do it
    579 	// anyway so that debugging is a little easier
    580 	VectorNormalize( frustum[0].normal );
    581 	VectorNormalize( frustum[1].normal );
    582 	VectorNormalize( frustum[2].normal );
    583 	VectorNormalize( frustum[3].normal );
    584 #else
    585 	// rotate VPN right by FOV_X/2 degrees
    586 	RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_newrefdef.fov_x / 2 ) );
    587 	// rotate VPN left by FOV_X/2 degrees
    588 	RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_newrefdef.fov_x / 2 );
    589 	// rotate VPN up by FOV_X/2 degrees
    590 	RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_newrefdef.fov_y / 2 );
    591 	// rotate VPN down by FOV_X/2 degrees
    592 	RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_newrefdef.fov_y / 2 ) );
    593 #endif
    594 
    595 	for (i=0 ; i<4 ; i++)
    596 	{
    597 		frustum[i].type = PLANE_ANYZ;
    598 		frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
    599 		frustum[i].signbits = SignbitsForPlane (&frustum[i]);
    600 	}
    601 }
    602 
    603 //=======================================================================
    604 
    605 /*
    606 ===============
    607 R_SetupFrame
    608 ===============
    609 */
    610 void R_SetupFrame (void)
    611 {
    612 	int i;
    613 	mleaf_t	*leaf;
    614 
    615 	r_framecount++;
    616 
    617 // build the transformation matrix for the given view angles
    618 	VectorCopy (r_newrefdef.vieworg, r_origin);
    619 
    620 	AngleVectors (r_newrefdef.viewangles, vpn, vright, vup);
    621 
    622 // current viewcluster
    623 	if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
    624 	{
    625 		r_oldviewcluster = r_viewcluster;
    626 		r_oldviewcluster2 = r_viewcluster2;
    627 		leaf = Mod_PointInLeaf (r_origin, r_worldmodel);
    628 		r_viewcluster = r_viewcluster2 = leaf->cluster;
    629 
    630 		// check above and below so crossing solid water doesn't draw wrong
    631 		if (!leaf->contents)
    632 		{	// look down a bit
    633 			vec3_t	temp;
    634 
    635 			VectorCopy (r_origin, temp);
    636 			temp[2] -= 16;
    637 			leaf = Mod_PointInLeaf (temp, r_worldmodel);
    638 			if ( !(leaf->contents & CONTENTS_SOLID) &&
    639 				(leaf->cluster != r_viewcluster2) )
    640 				r_viewcluster2 = leaf->cluster;
    641 		}
    642 		else
    643 		{	// look up a bit
    644 			vec3_t	temp;
    645 
    646 			VectorCopy (r_origin, temp);
    647 			temp[2] += 16;
    648 			leaf = Mod_PointInLeaf (temp, r_worldmodel);
    649 			if ( !(leaf->contents & CONTENTS_SOLID) &&
    650 				(leaf->cluster != r_viewcluster2) )
    651 				r_viewcluster2 = leaf->cluster;
    652 		}
    653 	}
    654 
    655 	for (i=0 ; i<4 ; i++)
    656 		v_blend[i] = r_newrefdef.blend[i];
    657 
    658 	c_brush_polys = 0;
    659 	c_alias_polys = 0;
    660 
    661 	// clear out the portion of the screen that the NOWORLDMODEL defines
    662 	if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
    663 	{
    664 		qglEnable( GL_SCISSOR_TEST );
    665 		qglClearColor( 0.3, 0.3, 0.3, 1 );
    666 		qglScissor( r_newrefdef.x, vid.height - r_newrefdef.height - r_newrefdef.y, r_newrefdef.width, r_newrefdef.height );
    667 		qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    668 		qglClearColor( 1, 0, 0.5, 0.5 );
    669 		qglDisable( GL_SCISSOR_TEST );
    670 	}
    671 }
    672 
    673 
    674 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
    675 		     GLdouble zNear, GLdouble zFar )
    676 {
    677    GLdouble xmin, xmax, ymin, ymax;
    678 
    679    ymax = zNear * tan( fovy * M_PI / 360.0 );
    680    ymin = -ymax;
    681 
    682    xmin = ymin * aspect;
    683    xmax = ymax * aspect;
    684 
    685    xmin += -( 2 * gl_state.camera_separation ) / zNear;
    686    xmax += -( 2 * gl_state.camera_separation ) / zNear;
    687 
    688    qglFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
    689 }
    690 
    691 
    692 /*
    693 =============
    694 R_SetupGL
    695 =============
    696 */
    697 void R_SetupGL (void)
    698 {
    699 	float	screenaspect;
    700 //	float	yfov;
    701 	int		x, x2, y2, y, w, h;
    702 
    703 	//
    704 	// set up viewport
    705 	//
    706 	x = floor(r_newrefdef.x * vid.width / vid.width);
    707 	x2 = ceil((r_newrefdef.x + r_newrefdef.width) * vid.width / vid.width);
    708 	y = floor(vid.height - r_newrefdef.y * vid.height / vid.height);
    709 	y2 = ceil(vid.height - (r_newrefdef.y + r_newrefdef.height) * vid.height / vid.height);
    710 
    711 	w = x2 - x;
    712 	h = y - y2;
    713 
    714 	qglViewport (x, y2, w, h);
    715 
    716 	//
    717 	// set up projection matrix
    718 	//
    719     screenaspect = (float)r_newrefdef.width/r_newrefdef.height;
    720 //	yfov = 2*atan((float)r_newrefdef.height/r_newrefdef.width)*180/M_PI;
    721 	qglMatrixMode(GL_PROJECTION);
    722     qglLoadIdentity ();
    723     MYgluPerspective (r_newrefdef.fov_y,  screenaspect,  4,  4096);
    724 
    725 	qglCullFace(GL_FRONT);
    726 
    727 	qglMatrixMode(GL_MODELVIEW);
    728     qglLoadIdentity ();
    729 
    730     qglRotatef (-90,  1, 0, 0);	    // put Z going up
    731     qglRotatef (90,  0, 0, 1);	    // put Z going up
    732     qglRotatef (-r_newrefdef.viewangles[2],  1, 0, 0);
    733     qglRotatef (-r_newrefdef.viewangles[0],  0, 1, 0);
    734     qglRotatef (-r_newrefdef.viewangles[1],  0, 0, 1);
    735     qglTranslatef (-r_newrefdef.vieworg[0],  -r_newrefdef.vieworg[1],  -r_newrefdef.vieworg[2]);
    736 
    737 //	if ( gl_state.camera_separation != 0 && gl_state.stereo_enabled )
    738 //		qglTranslatef ( gl_state.camera_separation, 0, 0 );
    739 
    740 	qglGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
    741 
    742 	//
    743 	// set drawing parms
    744 	//
    745 	if (gl_cull->value)
    746 		qglEnable(GL_CULL_FACE);
    747 	else
    748 		qglDisable(GL_CULL_FACE);
    749 
    750 	qglDisable(GL_BLEND);
    751 	qglDisable(GL_ALPHA_TEST);
    752 	qglEnable(GL_DEPTH_TEST);
    753 }
    754 
    755 /*
    756 =============
    757 R_Clear
    758 =============
    759 */
    760 void R_Clear (void)
    761 {
    762 	if (gl_ztrick->value)
    763 	{
    764 		static int trickframe;
    765 
    766 		if (gl_clear->value)
    767 			qglClear (GL_COLOR_BUFFER_BIT);
    768 
    769 		trickframe++;
    770 		if (trickframe & 1)
    771 		{
    772 			gldepthmin = 0;
    773 			gldepthmax = 0.49999;
    774 			qglDepthFunc (GL_LEQUAL);
    775 		}
    776 		else
    777 		{
    778 			gldepthmin = 1;
    779 			gldepthmax = 0.5;
    780 			qglDepthFunc (GL_GEQUAL);
    781 		}
    782 	}
    783 	else
    784 	{
    785 		if (gl_clear->value)
    786 			qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    787 		else
    788 			qglClear (GL_DEPTH_BUFFER_BIT);
    789 		gldepthmin = 0;
    790 		gldepthmax = 1;
    791 		qglDepthFunc (GL_LEQUAL);
    792 	}
    793 
    794 	qglDepthRange (gldepthmin, gldepthmax);
    795 
    796 }
    797 
    798 void R_Flash( void )
    799 {
    800 	R_PolyBlend ();
    801 }
    802 
    803 /*
    804 ================
    805 R_RenderView
    806 
    807 r_newrefdef must be set before the first call
    808 ================
    809 */
    810 void R_RenderView (refdef_t *fd)
    811 {
    812 	if (r_norefresh->value)
    813 		return;
    814 
    815 	r_newrefdef = *fd;
    816 
    817 	if (!r_worldmodel && !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
    818 		ri.Sys_Error (ERR_DROP, "R_RenderView: NULL worldmodel");
    819 
    820 	if (r_speeds->value)
    821 	{
    822 		c_brush_polys = 0;
    823 		c_alias_polys = 0;
    824 	}
    825 
    826 	R_PushDlights ();
    827 
    828 	if (gl_finish->value)
    829 		qglFinish ();
    830 
    831 	R_SetupFrame ();
    832 
    833 	R_SetFrustum ();
    834 
    835 	R_SetupGL ();
    836 
    837 	R_MarkLeaves ();	// done here so we know if we're in water
    838 
    839 	R_DrawWorld ();
    840 
    841 	R_DrawEntitiesOnList ();
    842 
    843 	R_RenderDlights ();
    844 
    845 	R_DrawParticles ();
    846 
    847 	R_DrawAlphaSurfaces ();
    848 
    849 	R_Flash();
    850 
    851 	if (r_speeds->value)
    852 	{
    853 		ri.Con_Printf (PRINT_ALL, "%4i wpoly %4i epoly %i tex %i lmaps\n",
    854 			c_brush_polys, 
    855 			c_alias_polys, 
    856 			c_visible_textures, 
    857 			c_visible_lightmaps); 
    858 	}
    859 }
    860 
    861 
    862 void	R_SetGL2D (void)
    863 {
    864 	// set 2D virtual screen size
    865 	qglViewport (0,0, vid.width, vid.height);
    866 	qglMatrixMode(GL_PROJECTION);
    867     qglLoadIdentity ();
    868 	qglOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
    869 	qglMatrixMode(GL_MODELVIEW);
    870     qglLoadIdentity ();
    871 	qglDisable (GL_DEPTH_TEST);
    872 	qglDisable (GL_CULL_FACE);
    873 	qglDisable (GL_BLEND);
    874 	qglEnable (GL_ALPHA_TEST);
    875 	qglColor4f (1,1,1,1);
    876 }
    877 
    878 static void GL_DrawColoredStereoLinePair( float r, float g, float b, float y )
    879 {
    880 	qglColor3f( r, g, b );
    881 	qglVertex2f( 0, y );
    882 	qglVertex2f( vid.width, y );
    883 	qglColor3f( 0, 0, 0 );
    884 	qglVertex2f( 0, y + 1 );
    885 	qglVertex2f( vid.width, y + 1 );
    886 }
    887 
    888 static void GL_DrawStereoPattern( void )
    889 {
    890 	int i;
    891 
    892 	if ( !( gl_config.renderer & GL_RENDERER_INTERGRAPH ) )
    893 		return;
    894 
    895 	if ( !gl_state.stereo_enabled )
    896 		return;
    897 
    898 	R_SetGL2D();
    899 
    900 	qglDrawBuffer( GL_BACK_LEFT );
    901 
    902 	for ( i = 0; i < 20; i++ )
    903 	{
    904 		qglBegin( GL_LINES );
    905 			GL_DrawColoredStereoLinePair( 1, 0, 0, 0 );
    906 			GL_DrawColoredStereoLinePair( 1, 0, 0, 2 );
    907 			GL_DrawColoredStereoLinePair( 1, 0, 0, 4 );
    908 			GL_DrawColoredStereoLinePair( 1, 0, 0, 6 );
    909 			GL_DrawColoredStereoLinePair( 0, 1, 0, 8 );
    910 			GL_DrawColoredStereoLinePair( 1, 1, 0, 10);
    911 			GL_DrawColoredStereoLinePair( 1, 1, 0, 12);
    912 			GL_DrawColoredStereoLinePair( 0, 1, 0, 14);
    913 		qglEnd();
    914 		
    915 		GLimp_EndFrame();
    916 	}
    917 }
    918 
    919 
    920 /*
    921 ====================
    922 R_SetLightLevel
    923 
    924 ====================
    925 */
    926 void R_SetLightLevel (void)
    927 {
    928 	vec3_t		shadelight;
    929 
    930 	if (r_newrefdef.rdflags & RDF_NOWORLDMODEL)
    931 		return;
    932 
    933 	// save off light value for server to look at (BIG HACK!)
    934 
    935 	R_LightPoint (r_newrefdef.vieworg, shadelight);
    936 
    937 	// pick the greatest component, which should be the same
    938 	// as the mono value returned by software
    939 	if (shadelight[0] > shadelight[1])
    940 	{
    941 		if (shadelight[0] > shadelight[2])
    942 			r_lightlevel->value = 150*shadelight[0];
    943 		else
    944 			r_lightlevel->value = 150*shadelight[2];
    945 	}
    946 	else
    947 	{
    948 		if (shadelight[1] > shadelight[2])
    949 			r_lightlevel->value = 150*shadelight[1];
    950 		else
    951 			r_lightlevel->value = 150*shadelight[2];
    952 	}
    953 
    954 }
    955 
    956 /*
    957 @@@@@@@@@@@@@@@@@@@@@
    958 R_RenderFrame
    959 
    960 @@@@@@@@@@@@@@@@@@@@@
    961 */
    962 void R_RenderFrame (refdef_t *fd)
    963 {
    964 	R_RenderView( fd );
    965 	R_SetLightLevel ();
    966 	R_SetGL2D ();
    967 }
    968 
    969 
    970 void R_Register( void )
    971 {
    972 	r_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
    973 	r_norefresh = ri.Cvar_Get ("r_norefresh", "0", 0);
    974 	r_fullbright = ri.Cvar_Get ("r_fullbright", "0", 0);
    975 	r_drawentities = ri.Cvar_Get ("r_drawentities", "1", 0);
    976 	r_drawworld = ri.Cvar_Get ("r_drawworld", "1", 0);
    977 	r_novis = ri.Cvar_Get ("r_novis", "0", 0);
    978 	r_nocull = ri.Cvar_Get ("r_nocull", "0", 0);
    979 	r_lerpmodels = ri.Cvar_Get ("r_lerpmodels", "1", 0);
    980 	r_speeds = ri.Cvar_Get ("r_speeds", "0", 0);
    981 
    982 	r_lightlevel = ri.Cvar_Get ("r_lightlevel", "0", 0);
    983 
    984 	gl_nosubimage = ri.Cvar_Get( "gl_nosubimage", "0", 0 );
    985 	gl_allow_software = ri.Cvar_Get( "gl_allow_software", "0", 0 );
    986 
    987 	gl_particle_min_size = ri.Cvar_Get( "gl_particle_min_size", "2", CVAR_ARCHIVE );
    988 	gl_particle_max_size = ri.Cvar_Get( "gl_particle_max_size", "40", CVAR_ARCHIVE );
    989 	gl_particle_size = ri.Cvar_Get( "gl_particle_size", "40", CVAR_ARCHIVE );
    990 	gl_particle_att_a = ri.Cvar_Get( "gl_particle_att_a", "0.01", CVAR_ARCHIVE );
    991 	gl_particle_att_b = ri.Cvar_Get( "gl_particle_att_b", "0.0", CVAR_ARCHIVE );
    992 	gl_particle_att_c = ri.Cvar_Get( "gl_particle_att_c", "0.01", CVAR_ARCHIVE );
    993 
    994 	gl_modulate = ri.Cvar_Get ("gl_modulate", "1", CVAR_ARCHIVE );
    995 	gl_log = ri.Cvar_Get( "gl_log", "0", 0 );
    996 	gl_bitdepth = ri.Cvar_Get( "gl_bitdepth", "0", 0 );
    997 	gl_mode = ri.Cvar_Get( "gl_mode", "3", CVAR_ARCHIVE );
    998 	gl_lightmap = ri.Cvar_Get ("gl_lightmap", "0", 0);
    999 	gl_shadows = ri.Cvar_Get ("gl_shadows", "0", CVAR_ARCHIVE );
   1000 	gl_dynamic = ri.Cvar_Get ("gl_dynamic", "1", 0);
   1001 	gl_nobind = ri.Cvar_Get ("gl_nobind", "0", 0);
   1002 	gl_round_down = ri.Cvar_Get ("gl_round_down", "1", 0);
   1003 	gl_picmip = ri.Cvar_Get ("gl_picmip", "0", 0);
   1004 	gl_skymip = ri.Cvar_Get ("gl_skymip", "0", 0);
   1005 	gl_showtris = ri.Cvar_Get ("gl_showtris", "0", 0);
   1006 	gl_ztrick = ri.Cvar_Get ("gl_ztrick", "0", 0);
   1007 	gl_finish = ri.Cvar_Get ("gl_finish", "0", CVAR_ARCHIVE);
   1008 	gl_clear = ri.Cvar_Get ("gl_clear", "0", 0);
   1009 	gl_cull = ri.Cvar_Get ("gl_cull", "1", 0);
   1010 	gl_polyblend = ri.Cvar_Get ("gl_polyblend", "1", 0);
   1011 	gl_flashblend = ri.Cvar_Get ("gl_flashblend", "0", 0);
   1012 	gl_playermip = ri.Cvar_Get ("gl_playermip", "0", 0);
   1013 	gl_monolightmap = ri.Cvar_Get( "gl_monolightmap", "0", 0 );
   1014 	gl_driver = ri.Cvar_Get( "gl_driver", "opengl32", CVAR_ARCHIVE );
   1015 	gl_texturemode = ri.Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE );
   1016 	gl_texturealphamode = ri.Cvar_Get( "gl_texturealphamode", "default", CVAR_ARCHIVE );
   1017 	gl_texturesolidmode = ri.Cvar_Get( "gl_texturesolidmode", "default", CVAR_ARCHIVE );
   1018 	gl_lockpvs = ri.Cvar_Get( "gl_lockpvs", "0", 0 );
   1019 
   1020 	gl_vertex_arrays = ri.Cvar_Get( "gl_vertex_arrays", "0", CVAR_ARCHIVE );
   1021 
   1022 	gl_ext_swapinterval = ri.Cvar_Get( "gl_ext_swapinterval", "1", CVAR_ARCHIVE );
   1023 	gl_ext_palettedtexture = ri.Cvar_Get( "gl_ext_palettedtexture", "1", CVAR_ARCHIVE );
   1024 	gl_ext_multitexture = ri.Cvar_Get( "gl_ext_multitexture", "1", CVAR_ARCHIVE );
   1025 	gl_ext_pointparameters = ri.Cvar_Get( "gl_ext_pointparameters", "1", CVAR_ARCHIVE );
   1026 	gl_ext_compiled_vertex_array = ri.Cvar_Get( "gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE );
   1027 
   1028 	gl_drawbuffer = ri.Cvar_Get( "gl_drawbuffer", "GL_BACK", 0 );
   1029 	gl_swapinterval = ri.Cvar_Get( "gl_swapinterval", "1", CVAR_ARCHIVE );
   1030 
   1031 	gl_saturatelighting = ri.Cvar_Get( "gl_saturatelighting", "0", 0 );
   1032 
   1033 	gl_3dlabs_broken = ri.Cvar_Get( "gl_3dlabs_broken", "1", CVAR_ARCHIVE );
   1034 
   1035 	vid_fullscreen = ri.Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE );
   1036 	vid_gamma = ri.Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE );
   1037 	vid_ref = ri.Cvar_Get( "vid_ref", "soft", CVAR_ARCHIVE );
   1038 
   1039 	ri.Cmd_AddCommand( "imagelist", GL_ImageList_f );
   1040 	ri.Cmd_AddCommand( "screenshot", GL_ScreenShot_f );
   1041 	ri.Cmd_AddCommand( "modellist", Mod_Modellist_f );
   1042 	ri.Cmd_AddCommand( "gl_strings", GL_Strings_f );
   1043 }
   1044 
   1045 /*
   1046 ==================
   1047 R_SetMode
   1048 ==================
   1049 */
   1050 qboolean R_SetMode (void)
   1051 {
   1052 	rserr_t err;
   1053 	qboolean fullscreen;
   1054 
   1055 	if ( vid_fullscreen->modified && !gl_config.allow_cds )
   1056 	{
   1057 		ri.Con_Printf( PRINT_ALL, "R_SetMode() - CDS not allowed with this driver\n" );
   1058 		ri.Cvar_SetValue( "vid_fullscreen", !vid_fullscreen->value );
   1059 		vid_fullscreen->modified = false;
   1060 	}
   1061 
   1062 	fullscreen = vid_fullscreen->value;
   1063 
   1064 	vid_fullscreen->modified = false;
   1065 	gl_mode->modified = false;
   1066 
   1067 	if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->value, fullscreen ) ) == rserr_ok )
   1068 	{
   1069 		gl_state.prev_mode = gl_mode->value;
   1070 	}
   1071 	else
   1072 	{
   1073 		if ( err == rserr_invalid_fullscreen )
   1074 		{
   1075 			ri.Cvar_SetValue( "vid_fullscreen", 0);
   1076 			vid_fullscreen->modified = false;
   1077 			ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - fullscreen unavailable in this mode\n" );
   1078 			if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->value, false ) ) == rserr_ok )
   1079 				return true;
   1080 		}
   1081 		else if ( err == rserr_invalid_mode )
   1082 		{
   1083 			ri.Cvar_SetValue( "gl_mode", gl_state.prev_mode );
   1084 			gl_mode->modified = false;
   1085 			ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - invalid mode\n" );
   1086 		}
   1087 
   1088 		// try setting it back to something safe
   1089 		if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_state.prev_mode, false ) ) != rserr_ok )
   1090 		{
   1091 			ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - could not revert to safe mode\n" );
   1092 			return false;
   1093 		}
   1094 	}
   1095 	return true;
   1096 }
   1097 
   1098 /*
   1099 ===============
   1100 R_Init
   1101 ===============
   1102 */
   1103 int R_Init( void *hinstance, void *hWnd )
   1104 {	
   1105 	char renderer_buffer[1000];
   1106 	char vendor_buffer[1000];
   1107 	int		err;
   1108 	int		j;
   1109 	extern float r_turbsin[256];
   1110 
   1111 	for ( j = 0; j < 256; j++ )
   1112 	{
   1113 		r_turbsin[j] *= 0.5;
   1114 	}
   1115 
   1116 	ri.Con_Printf (PRINT_ALL, "ref_gl version: "REF_VERSION"\n");
   1117 
   1118 	Draw_GetPalette ();
   1119 
   1120 	R_Register();
   1121 
   1122 	// initialize our QGL dynamic bindings
   1123 	if ( !QGL_Init( gl_driver->string ) )
   1124 	{
   1125 		QGL_Shutdown();
   1126         ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - could not load \"%s\"\n", gl_driver->string );
   1127 		return -1;
   1128 	}
   1129 
   1130 	// initialize OS-specific parts of OpenGL
   1131 	if ( !GLimp_Init( hinstance, hWnd ) )
   1132 	{
   1133 		QGL_Shutdown();
   1134 		return -1;
   1135 	}
   1136 
   1137 	// set our "safe" modes
   1138 	gl_state.prev_mode = 3;
   1139 
   1140 	// create the window and set up the context
   1141 	if ( !R_SetMode () )
   1142 	{
   1143 		QGL_Shutdown();
   1144         ri.Con_Printf (PRINT_ALL, "ref_gl::R_Init() - could not R_SetMode()\n" );
   1145 		return -1;
   1146 	}
   1147 
   1148 	ri.Vid_MenuInit();
   1149 
   1150 	/*
   1151 	** get our various GL strings
   1152 	*/
   1153 	gl_config.vendor_string = qglGetString (GL_VENDOR);
   1154 	ri.Con_Printf (PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string );
   1155 	gl_config.renderer_string = qglGetString (GL_RENDERER);
   1156 	ri.Con_Printf (PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string );
   1157 	gl_config.version_string = qglGetString (GL_VERSION);
   1158 	ri.Con_Printf (PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string );
   1159 	gl_config.extensions_string = qglGetString (GL_EXTENSIONS);
   1160 	ri.Con_Printf (PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string );
   1161 
   1162 	strcpy( renderer_buffer, gl_config.renderer_string );
   1163 	strlwr( renderer_buffer );
   1164 
   1165 	strcpy( vendor_buffer, gl_config.vendor_string );
   1166 	strlwr( vendor_buffer );
   1167 
   1168 	if ( strstr( renderer_buffer, "voodoo" ) )
   1169 	{
   1170 		if ( !strstr( renderer_buffer, "rush" ) )
   1171 			gl_config.renderer = GL_RENDERER_VOODOO;
   1172 		else
   1173 			gl_config.renderer = GL_RENDERER_VOODOO_RUSH;
   1174 	}
   1175 	else if ( strstr( vendor_buffer, "sgi" ) )
   1176 		gl_config.renderer = GL_RENDERER_SGI;
   1177 	else if ( strstr( renderer_buffer, "permedia" ) )
   1178 		gl_config.renderer = GL_RENDERER_PERMEDIA2;
   1179 	else if ( strstr( renderer_buffer, "glint" ) )
   1180 		gl_config.renderer = GL_RENDERER_GLINT_MX;
   1181 	else if ( strstr( renderer_buffer, "glzicd" ) )
   1182 		gl_config.renderer = GL_RENDERER_REALIZM;
   1183 	else if ( strstr( renderer_buffer, "gdi" ) )
   1184 		gl_config.renderer = GL_RENDERER_MCD;
   1185 	else if ( strstr( renderer_buffer, "pcx2" ) )
   1186 		gl_config.renderer = GL_RENDERER_PCX2;
   1187 	else if ( strstr( renderer_buffer, "verite" ) )
   1188 		gl_config.renderer = GL_RENDERER_RENDITION;
   1189 	else
   1190 		gl_config.renderer = GL_RENDERER_OTHER;
   1191 
   1192 	if ( toupper( gl_monolightmap->string[1] ) != 'F' )
   1193 	{
   1194 		if ( gl_config.renderer == GL_RENDERER_PERMEDIA2 )
   1195 		{
   1196 			ri.Cvar_Set( "gl_monolightmap", "A" );
   1197 			ri.Con_Printf( PRINT_ALL, "...using gl_monolightmap 'a'\n" );
   1198 		}
   1199 		else if ( gl_config.renderer & GL_RENDERER_POWERVR ) 
   1200 		{
   1201 			ri.Cvar_Set( "gl_monolightmap", "0" );
   1202 		}
   1203 		else
   1204 		{
   1205 			ri.Cvar_Set( "gl_monolightmap", "0" );
   1206 		}
   1207 	}
   1208 
   1209 	// power vr can't have anything stay in the framebuffer, so
   1210 	// the screen needs to redraw the tiled background every frame
   1211 	if ( gl_config.renderer & GL_RENDERER_POWERVR ) 
   1212 	{
   1213 		ri.Cvar_Set( "scr_drawall", "1" );
   1214 	}
   1215 	else
   1216 	{
   1217 		ri.Cvar_Set( "scr_drawall", "0" );
   1218 	}
   1219 
   1220 	// MCD has buffering issues
   1221 	if ( gl_config.renderer == GL_RENDERER_MCD )
   1222 	{
   1223 		ri.Cvar_SetValue( "gl_finish", 1 );
   1224 	}
   1225 
   1226 	if ( gl_config.renderer & GL_RENDERER_3DLABS )
   1227 	{
   1228 		if ( gl_3dlabs_broken->value )
   1229 			gl_config.allow_cds = false;
   1230 		else
   1231 			gl_config.allow_cds = true;
   1232 	}
   1233 	else
   1234 	{
   1235 		gl_config.allow_cds = true;
   1236 	}
   1237 
   1238 	if ( gl_config.allow_cds )
   1239 		ri.Con_Printf( PRINT_ALL, "...allowing CDS\n" );
   1240 	else
   1241 		ri.Con_Printf( PRINT_ALL, "...disabling CDS\n" );
   1242 
   1243 	/*
   1244 	** grab extensions
   1245 	*/
   1246 #ifdef WIN32
   1247 	if ( strstr( gl_config.extensions_string, "GL_EXT_compiled_vertex_array" ) || 
   1248 		 strstr( gl_config.extensions_string, "GL_SGI_compiled_vertex_array" ) )
   1249 	{
   1250 		ri.Con_Printf( PRINT_ALL, "...enabling GL_EXT_compiled_vertex_array\n" );
   1251 		qglLockArraysEXT = ( void * ) qwglGetProcAddress( "glLockArraysEXT" );
   1252 		qglUnlockArraysEXT = ( void * ) qwglGetProcAddress( "glUnlockArraysEXT" );
   1253 	}
   1254 	else
   1255 	{
   1256 		ri.Con_Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
   1257 	}
   1258 
   1259 	if ( strstr( gl_config.extensions_string, "WGL_EXT_swap_control" ) )
   1260 	{
   1261 		qwglSwapIntervalEXT = ( BOOL (WINAPI *)(int)) qwglGetProcAddress( "wglSwapIntervalEXT" );
   1262 		ri.Con_Printf( PRINT_ALL, "...enabling WGL_EXT_swap_control\n" );
   1263 	}
   1264 	else
   1265 	{
   1266 		ri.Con_Printf( PRINT_ALL, "...WGL_EXT_swap_control not found\n" );
   1267 	}
   1268 
   1269 	if ( strstr( gl_config.extensions_string, "GL_EXT_point_parameters" ) )
   1270 	{
   1271 		if ( gl_ext_pointparameters->value )
   1272 		{
   1273 			qglPointParameterfEXT = ( void (APIENTRY *)( GLenum, GLfloat ) ) qwglGetProcAddress( "glPointParameterfEXT" );
   1274 			qglPointParameterfvEXT = ( void (APIENTRY *)( GLenum, const GLfloat * ) ) qwglGetProcAddress( "glPointParameterfvEXT" );
   1275 			ri.Con_Printf( PRINT_ALL, "...using GL_EXT_point_parameters\n" );
   1276 		}
   1277 		else
   1278 		{
   1279 			ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_point_parameters\n" );
   1280 		}
   1281 	}
   1282 	else
   1283 	{
   1284 		ri.Con_Printf( PRINT_ALL, "...GL_EXT_point_parameters not found\n" );
   1285 	}
   1286 
   1287 	if ( strstr( gl_config.extensions_string, "GL_EXT_paletted_texture" ) && 
   1288 		 strstr( gl_config.extensions_string, "GL_EXT_shared_texture_palette" ) )
   1289 	{
   1290 		if ( gl_ext_palettedtexture->value )
   1291 		{
   1292 			ri.Con_Printf( PRINT_ALL, "...using GL_EXT_shared_texture_palette\n" );
   1293 			qglColorTableEXT = ( void ( APIENTRY * ) ( int, int, int, int, int, const void * ) ) qwglGetProcAddress( "glColorTableEXT" );
   1294 		}
   1295 		else
   1296 		{
   1297 			ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_shared_texture_palette\n" );
   1298 		}
   1299 	}
   1300 	else
   1301 	{
   1302 		ri.Con_Printf( PRINT_ALL, "...GL_EXT_shared_texture_palette not found\n" );
   1303 	}
   1304 
   1305 	if ( strstr( gl_config.extensions_string, "GL_SGIS_multitexture" ) )
   1306 	{
   1307 		if ( gl_ext_multitexture->value )
   1308 		{
   1309 			ri.Con_Printf( PRINT_ALL, "...using GL_SGIS_multitexture\n" );
   1310 			qglMTexCoord2fSGIS = ( void * ) qwglGetProcAddress( "glMTexCoord2fSGIS" );
   1311 			qglSelectTextureSGIS = ( void * ) qwglGetProcAddress( "glSelectTextureSGIS" );
   1312 		}
   1313 		else
   1314 		{
   1315 			ri.Con_Printf( PRINT_ALL, "...ignoring GL_SGIS_multitexture\n" );
   1316 		}
   1317 	}
   1318 	else
   1319 	{
   1320 		ri.Con_Printf( PRINT_ALL, "...GL_SGIS_multitexture not found\n" );
   1321 	}
   1322 #endif
   1323 
   1324 	GL_SetDefaultState();
   1325 
   1326 	/*
   1327 	** draw our stereo patterns
   1328 	*/
   1329 #if 0 // commented out until H3D pays us the money they owe us
   1330 	GL_DrawStereoPattern();
   1331 #endif
   1332 
   1333 	GL_InitImages ();
   1334 	Mod_Init ();
   1335 	R_InitParticleTexture ();
   1336 	Draw_InitLocal ();
   1337 
   1338 	err = qglGetError();
   1339 	if ( err != GL_NO_ERROR )
   1340 		ri.Con_Printf (PRINT_ALL, "glGetError() = 0x%x\n", err);
   1341 }
   1342 
   1343 /*
   1344 ===============
   1345 R_Shutdown
   1346 ===============
   1347 */
   1348 void R_Shutdown (void)
   1349 {	
   1350 	ri.Cmd_RemoveCommand ("modellist");
   1351 	ri.Cmd_RemoveCommand ("screenshot");
   1352 	ri.Cmd_RemoveCommand ("imagelist");
   1353 	ri.Cmd_RemoveCommand ("gl_strings");
   1354 
   1355 	Mod_FreeAll ();
   1356 
   1357 	GL_ShutdownImages ();
   1358 
   1359 	/*
   1360 	** shut down OS specific OpenGL stuff like contexts, etc.
   1361 	*/
   1362 	GLimp_Shutdown();
   1363 
   1364 	/*
   1365 	** shutdown our QGL subsystem
   1366 	*/
   1367 	QGL_Shutdown();
   1368 }
   1369 
   1370 
   1371 
   1372 /*
   1373 @@@@@@@@@@@@@@@@@@@@@
   1374 R_BeginFrame
   1375 @@@@@@@@@@@@@@@@@@@@@
   1376 */
   1377 void R_BeginFrame( float camera_separation )
   1378 {
   1379 
   1380 	gl_state.camera_separation = camera_separation;
   1381 
   1382 	/*
   1383 	** change modes if necessary
   1384 	*/
   1385 	if ( gl_mode->modified || vid_fullscreen->modified )
   1386 	{	// FIXME: only restart if CDS is required
   1387 		cvar_t	*ref;
   1388 
   1389 		ref = ri.Cvar_Get ("vid_ref", "gl", 0);
   1390 		ref->modified = true;
   1391 	}
   1392 
   1393 	if ( gl_log->modified )
   1394 	{
   1395 		GLimp_EnableLogging( gl_log->value );
   1396 		gl_log->modified = false;
   1397 	}
   1398 
   1399 	if ( gl_log->value )
   1400 	{
   1401 		GLimp_LogNewFrame();
   1402 	}
   1403 
   1404 	/*
   1405 	** update 3Dfx gamma -- it is expected that a user will do a vid_restart
   1406 	** after tweaking this value
   1407 	*/
   1408 	if ( vid_gamma->modified )
   1409 	{
   1410 		vid_gamma->modified = false;
   1411 
   1412 		if ( gl_config.renderer & ( GL_RENDERER_VOODOO ) )
   1413 		{
   1414 			char envbuffer[1024];
   1415 			float g;
   1416 
   1417 			g = 2.00 * ( 0.8 - ( vid_gamma->value - 0.5 ) ) + 1.0F;
   1418 			Com_sprintf( envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g );
   1419 			putenv( envbuffer );
   1420 			Com_sprintf( envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g );
   1421 			putenv( envbuffer );
   1422 		}
   1423 	}
   1424 
   1425 	GLimp_BeginFrame( camera_separation );
   1426 
   1427 	/*
   1428 	** go into 2D mode
   1429 	*/
   1430 	qglViewport (0,0, vid.width, vid.height);
   1431 	qglMatrixMode(GL_PROJECTION);
   1432     qglLoadIdentity ();
   1433 	qglOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
   1434 	qglMatrixMode(GL_MODELVIEW);
   1435     qglLoadIdentity ();
   1436 	qglDisable (GL_DEPTH_TEST);
   1437 	qglDisable (GL_CULL_FACE);
   1438 	qglDisable (GL_BLEND);
   1439 	qglEnable (GL_ALPHA_TEST);
   1440 	qglColor4f (1,1,1,1);
   1441 
   1442 	/*
   1443 	** draw buffer stuff
   1444 	*/
   1445 	if ( gl_drawbuffer->modified )
   1446 	{
   1447 		gl_drawbuffer->modified = false;
   1448 
   1449 		if ( gl_state.camera_separation == 0 || !gl_state.stereo_enabled )
   1450 		{
   1451 			if ( Q_stricmp( gl_drawbuffer->string, "GL_FRONT" ) == 0 )
   1452 				qglDrawBuffer( GL_FRONT );
   1453 			else
   1454 				qglDrawBuffer( GL_BACK );
   1455 		}
   1456 	}
   1457 
   1458 	/*
   1459 	** texturemode stuff
   1460 	*/
   1461 	if ( gl_texturemode->modified )
   1462 	{
   1463 		GL_TextureMode( gl_texturemode->string );
   1464 		gl_texturemode->modified = false;
   1465 	}
   1466 
   1467 	if ( gl_texturealphamode->modified )
   1468 	{
   1469 		GL_TextureAlphaMode( gl_texturealphamode->string );
   1470 		gl_texturealphamode->modified = false;
   1471 	}
   1472 
   1473 	if ( gl_texturesolidmode->modified )
   1474 	{
   1475 		GL_TextureSolidMode( gl_texturesolidmode->string );
   1476 		gl_texturesolidmode->modified = false;
   1477 	}
   1478 
   1479 	/*
   1480 	** swapinterval stuff
   1481 	*/
   1482 	GL_UpdateSwapInterval();
   1483 
   1484 	//
   1485 	// clear screen if desired
   1486 	//
   1487 	R_Clear ();
   1488 }
   1489 
   1490 /*
   1491 =============
   1492 R_SetPalette
   1493 =============
   1494 */
   1495 unsigned r_rawpalette[256];
   1496 
   1497 void R_SetPalette ( const unsigned char *palette)
   1498 {
   1499 	int		i;
   1500 
   1501 	byte *rp = ( byte * ) r_rawpalette;
   1502 
   1503 	if ( palette )
   1504 	{
   1505 		for ( i = 0; i < 256; i++ )
   1506 		{
   1507 			rp[i*4+0] = palette[i*3+0];
   1508 			rp[i*4+1] = palette[i*3+1];
   1509 			rp[i*4+2] = palette[i*3+2];
   1510 			rp[i*4+3] = 0xff;
   1511 		}
   1512 	}
   1513 	else
   1514 	{
   1515 		for ( i = 0; i < 256; i++ )
   1516 		{
   1517 			rp[i*4+0] = d_8to24table[i] & 0xff;
   1518 			rp[i*4+1] = ( d_8to24table[i] >> 8 ) & 0xff;
   1519 			rp[i*4+2] = ( d_8to24table[i] >> 16 ) & 0xff;
   1520 			rp[i*4+3] = 0xff;
   1521 		}
   1522 	}
   1523 	GL_SetTexturePalette( r_rawpalette );
   1524 
   1525 	qglClearColor (0,0,0,0);
   1526 	qglClear (GL_COLOR_BUFFER_BIT);
   1527 	qglClearColor (1,0, 0.5 , 0.5);
   1528 }
   1529 
   1530 /*
   1531 ** R_DrawBeam
   1532 */
   1533 void R_DrawBeam( entity_t *e )
   1534 {
   1535 #define NUM_BEAM_SEGS 6
   1536 
   1537 	int	i;
   1538 	float r, g, b;
   1539 
   1540 	vec3_t perpvec;
   1541 	vec3_t direction, normalized_direction;
   1542 	vec3_t	start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
   1543 	vec3_t oldorigin, origin;
   1544 
   1545 	oldorigin[0] = e->oldorigin[0];
   1546 	oldorigin[1] = e->oldorigin[1];
   1547 	oldorigin[2] = e->oldorigin[2];
   1548 
   1549 	origin[0] = e->origin[0];
   1550 	origin[1] = e->origin[1];
   1551 	origin[2] = e->origin[2];
   1552 
   1553 	normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
   1554 	normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
   1555 	normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
   1556 
   1557 	if ( VectorNormalize( normalized_direction ) == 0 )
   1558 		return;
   1559 
   1560 	PerpendicularVector( perpvec, normalized_direction );
   1561 	VectorScale( perpvec, e->frame / 2, perpvec );
   1562 
   1563 	for ( i = 0; i < 6; i++ )
   1564 	{
   1565 		RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i );
   1566 		VectorAdd( start_points[i], origin, start_points[i] );
   1567 		VectorAdd( start_points[i], direction, end_points[i] );
   1568 	}
   1569 
   1570 	qglDisable( GL_TEXTURE_2D );
   1571 	qglEnable( GL_BLEND );
   1572 	qglDepthMask( GL_FALSE );
   1573 
   1574 	r = ( d_8to24table[e->skinnum & 0xFF] ) & 0xFF;
   1575 	g = ( d_8to24table[e->skinnum & 0xFF] >> 8 ) & 0xFF;
   1576 	b = ( d_8to24table[e->skinnum & 0xFF] >> 16 ) & 0xFF;
   1577 
   1578 	r *= 1/255.0F;
   1579 	g *= 1/255.0F;
   1580 	b *= 1/255.0F;
   1581 
   1582 	qglColor4f( r, g, b, e->alpha );
   1583 
   1584 	qglBegin( GL_TRIANGLE_STRIP );
   1585 	for ( i = 0; i < NUM_BEAM_SEGS; i++ )
   1586 	{
   1587 		qglVertex3fv( start_points[i] );
   1588 		qglVertex3fv( end_points[i] );
   1589 		qglVertex3fv( start_points[(i+1)%NUM_BEAM_SEGS] );
   1590 		qglVertex3fv( end_points[(i+1)%NUM_BEAM_SEGS] );
   1591 	}
   1592 	qglEnd();
   1593 
   1594 	qglEnable( GL_TEXTURE_2D );
   1595 	qglDisable( GL_BLEND );
   1596 	qglDepthMask( GL_TRUE );
   1597 }
   1598 
   1599 //===================================================================
   1600 
   1601 
   1602 void	R_BeginRegistration (char *map);
   1603 struct model_s	*R_RegisterModel (char *name);
   1604 struct image_s	*R_RegisterSkin (char *name);
   1605 void R_SetSky (char *name, float rotate, vec3_t axis);
   1606 void	R_EndRegistration (void);
   1607 
   1608 void	R_RenderFrame (refdef_t *fd);
   1609 
   1610 struct image_s	*Draw_FindPic (char *name);
   1611 
   1612 void	Draw_Pic (int x, int y, char *name);
   1613 void	Draw_Char (int x, int y, int c);
   1614 void	Draw_TileClear (int x, int y, int w, int h, char *name);
   1615 void	Draw_Fill (int x, int y, int w, int h, int c);
   1616 void	Draw_FadeScreen (void);
   1617 
   1618 /*
   1619 @@@@@@@@@@@@@@@@@@@@@
   1620 GetRefAPI
   1621 
   1622 @@@@@@@@@@@@@@@@@@@@@
   1623 */
   1624 refexport_t GetRefAPI (refimport_t rimp )
   1625 {
   1626 	refexport_t	re;
   1627 
   1628 	ri = rimp;
   1629 
   1630 	re.api_version = API_VERSION;
   1631 
   1632 	re.BeginRegistration = R_BeginRegistration;
   1633 	re.RegisterModel = R_RegisterModel;
   1634 	re.RegisterSkin = R_RegisterSkin;
   1635 	re.RegisterPic = Draw_FindPic;
   1636 	re.SetSky = R_SetSky;
   1637 	re.EndRegistration = R_EndRegistration;
   1638 
   1639 	re.RenderFrame = R_RenderFrame;
   1640 
   1641 	re.DrawGetPicSize = Draw_GetPicSize;
   1642 	re.DrawPic = Draw_Pic;
   1643 	re.DrawStretchPic = Draw_StretchPic;
   1644 	re.DrawChar = Draw_Char;
   1645 	re.DrawTileClear = Draw_TileClear;
   1646 	re.DrawFill = Draw_Fill;
   1647 	re.DrawFadeScreen= Draw_FadeScreen;
   1648 
   1649 	re.DrawStretchRaw = Draw_StretchRaw;
   1650 
   1651 	re.Init = R_Init;
   1652 	re.Shutdown = R_Shutdown;
   1653 
   1654 	re.CinematicSetPalette = R_SetPalette;
   1655 	re.BeginFrame = R_BeginFrame;
   1656 	re.EndFrame = GLimp_EndFrame;
   1657 
   1658 	re.AppActivate = GLimp_AppActivate;
   1659 
   1660 	Swap_Init ();
   1661 
   1662 	return re;
   1663 }
   1664 
   1665 
   1666 #ifndef REF_HARD_LINKED
   1667 // this is only here so the functions in q_shared.c and q_shwin.c can link
   1668 void Sys_Error (char *error, ...)
   1669 {
   1670 	va_list		argptr;
   1671 	char		text[1024];
   1672 
   1673 	va_start (argptr, error);
   1674 	vsprintf (text, error, argptr);
   1675 	va_end (argptr);
   1676 
   1677 	ri.Sys_Error (ERR_FATAL, "%s", text);
   1678 }
   1679 
   1680 void Com_Printf (char *fmt, ...)
   1681 {
   1682 	va_list		argptr;
   1683 	char		text[1024];
   1684 
   1685 	va_start (argptr, fmt);
   1686 	vsprintf (text, fmt, argptr);
   1687 	va_end (argptr);
   1688 
   1689 	ri.Con_Printf (PRINT_ALL, "%s", text);
   1690 }
   1691 
   1692 #endif