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 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include "r_local.h"
27 #include "r_script.h"
28 #include "r_ragdoll.h"
29 #include "r_text.h"
30 
31 
32 void R_Clear (void);
33 
34 viddef_t	vid;
35 
36 int r_viewport[4];
37 
38 int GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2, GL_TEXTURE3, GL_TEXTURE4, GL_TEXTURE5, GL_TEXTURE6, GL_TEXTURE7;
39 
40 model_t		*r_worldmodel;
41 
42 float			gldepthmin, gldepthmax;
43 float			r_frametime;
44 
45 glconfig_t		gl_config;
46 glstate_t		gl_state;
47 
48 cvar_t	*gl_normalmaps;
49 cvar_t	*gl_bspnormalmaps;
50 cvar_t  *gl_shadowmaps;
51 cvar_t	*gl_arb_fragment_program;
52 cvar_t	*gl_glsl_shaders;
53 cvar_t	*gl_fog;
54 
55 entity_t	*currententity;
56 model_t		*currentmodel;
57 
58 cplane_t	frustum[4];
59 
60 int		r_visframecount;	// bumped when going to a new PVS
61 int		r_framecount;		// used for dlight push checking
62 int		r_shadowmapcount;	// number of shadowmaps rendered this frame
63 
64 // performance counters for r_speeds reports
65 int last_c_brush_polys, c_brush_polys;
66 int last_c_alias_polys, c_alias_polys;
67 int c_flares;
68 int c_grasses;
69 int c_beams;
70 extern int c_vbo_batches;
71 extern int c_visible_lightmaps;
72 extern int c_visible_textures;
73 
74 float		v_blend[4];			// final blending color
75 
76 float		r_farclip, r_farclip_min, r_farclip_bias = 256.0f;
77 
78 void GL_Strings_f( void );
79 
80 //
81 // view origin
82 //
83 vec3_t	vup;
84 vec3_t	vpn;
85 vec3_t	vright;
86 vec3_t	r_origin;
87 int		r_origin_leafnum;
88 
89 float	r_world_matrix[16];
90 float	r_project_matrix[16];
91 
92 //
93 // screen size info
94 //
95 refdef_t	r_newrefdef;
96 
97 int		r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
98 
99 cvar_t	*r_norefresh;
100 cvar_t	*r_drawentities;
101 cvar_t	*r_drawworld;
102 cvar_t	*r_fullbright;
103 cvar_t	*r_novis;
104 cvar_t	*r_nocull;
105 cvar_t	*r_lerpmodels;
106 cvar_t	*r_lefthand;
107 
108 cvar_t  *r_wave; // Water waves
109 
110 cvar_t	*r_shadowmapscale;
111 
112 cvar_t	*r_overbrightbits;
113 
114 cvar_t	*gl_vlights;
115 
116 cvar_t	*gl_nosubimage;
117 
118 cvar_t	*gl_usevbo;
119 
120 cvar_t	*gl_particle_min_size;
121 cvar_t	*gl_particle_max_size;
122 cvar_t	*gl_particle_size;
123 cvar_t	*gl_particle_att_a;
124 cvar_t	*gl_particle_att_b;
125 cvar_t	*gl_particle_att_c;
126 
127 cvar_t	*gl_ext_pointparameters;
128 
129 cvar_t	*gl_log;
130 cvar_t	*gl_bitdepth;
131 cvar_t	*gl_drawbuffer;
132 cvar_t	*gl_driver;
133 cvar_t	*gl_lightmap;
134 cvar_t	*gl_mode;
135 cvar_t	*gl_dynamic;
136 cvar_t	*gl_modulate;
137 cvar_t	*gl_nobind;
138 cvar_t	*gl_picmip;
139 cvar_t	*gl_skymip;
140 cvar_t	*gl_showtris;
141 cvar_t	*gl_showpolys;
142 cvar_t	*gl_finish;
143 cvar_t	*gl_clear;
144 cvar_t	*gl_cull;
145 cvar_t	*gl_polyblend;
146 cvar_t	*gl_swapinterval;
147 cvar_t	*gl_texturemode;
148 cvar_t	*gl_texturealphamode;
149 cvar_t	*gl_texturesolidmode;
150 cvar_t	*gl_lockpvs;
151 
152 cvar_t	*vid_fullscreen;
153 cvar_t	*vid_gamma;
154 cvar_t  *vid_contrast;
155 cvar_t	*vid_ref;
156 
157 cvar_t *r_anisotropic;
158 cvar_t *r_alphamasked_anisotropic;
159 cvar_t *r_ext_max_anisotropy;
160 
161 cvar_t	*r_shaders;
162 cvar_t	*r_bloom;
163 cvar_t	*r_lensflare;
164 cvar_t	*r_lensflare_intens;
165 cvar_t	*r_drawsun;
166 cvar_t	*r_lightbeam;
167 cvar_t	*r_godrays;
168 cvar_t  *r_godray_intensity;
169 cvar_t	*r_optimize;
170 
171 cvar_t	*r_lightmapfiles;
172 
173 qboolean	map_fog;
174 
175 cvar_t	*con_font;
176 
177 cvar_t	*r_minimap_size;
178 cvar_t	*r_minimap_zoom;
179 cvar_t	*r_minimap_style;
180 cvar_t	*r_minimap;
181 
182 cvar_t	*sys_affinity;
183 cvar_t	*sys_priority;
184 
185 cvar_t	*gl_screenshot_type;
186 cvar_t	*gl_screenshot_jpeg_quality;
187 
188 //no blood
189 extern cvar_t *cl_noblood;
190 
191 //first time running game
192 cvar_t	*r_firstrun;
193 
194 //for testing
195 cvar_t  *r_test;
196 
197 //ODE initialization error check
198 int r_odeinit_success; // 0 if dODEInit2() fails, 1 otherwise.
199 
200 //fog script stuff
201 struct r_fog
202 {
203 	float red;
204 	float green;
205 	float blue;
206 	float start;
207 	float end;
208 	float density;
209 } fog;
210 unsigned r_weather;
211 unsigned r_nosun;
212 float r_sunX;
213 float r_sunY;
214 float r_sunZ;
215 
216 /*
217 =================
218 R_ReadFogScript
219 =================
220 */
221 
R_ReadFogScript(char * config_file)222 void R_ReadFogScript( char *config_file )
223 {
224 	FILE *fp;
225 	int length;
226 	char a_string[128];
227 	char *buffer;
228 	char *s;
229 	size_t result;
230 
231 	if((fp = fopen(config_file, "rb" )) == NULL)
232 	{
233 		return;
234 	}
235 
236 	length = FS_filelength( fp );
237 
238 	buffer = malloc( length + 1 );
239 	if ( buffer != NULL )
240 	{
241 		buffer[length] = 0;
242 		result = fread( buffer, length, 1, fp );
243 		if ( result == 1 )
244 		{
245 			s = buffer;
246 
247 			strcpy( a_string, COM_Parse( &s ) );
248 			fog.red = atof(a_string);
249 			strcpy( a_string, COM_Parse( &s ) );
250 			fog.green = atof(a_string);
251 			strcpy( a_string, COM_Parse( &s ) );
252 			fog.blue = atof(a_string);
253 			strcpy( a_string, COM_Parse( &s ) );
254 			fog.start = atof(a_string);
255 			strcpy( a_string, COM_Parse( &s ) );
256 			fog.end = atof(a_string);
257 			strcpy( a_string, COM_Parse( &s ) );
258 			fog.density = atof(a_string);
259 			strcpy( a_string, COM_Parse( &s ) );
260 			r_weather = atoi(a_string);
261 			strcpy( a_string, COM_Parse( &s ) );
262 			r_nosun = atoi(a_string);
263 			strcpy( a_string, COM_Parse( &s ) );
264 			r_sunX = atof(a_string);
265 			strcpy( a_string, COM_Parse( &s ) );
266 			r_sunY = atof(a_string);
267 			strcpy( a_string, COM_Parse( &s ) );
268 			r_sunZ = atof(a_string);
269 
270 			if(fog.density > 0)
271 				map_fog = true;
272 
273 		}
274 		else
275 		{
276 			Com_DPrintf("R_ReadFogScript: read fail: %s\n", config_file);
277 		}
278 		free( buffer );
279 	}
280 	fclose( fp );
281 
282 	if (gl_fog->integer < 1)
283 	{
284 		map_fog = false;
285 		r_weather = false;
286 	}
287 
288 	return;
289 }
290 
291 /*
292 =================
293 R_ReadMusicScript
294 =================
295 */
296 
297 //to do - read in secondary music location(for CTF music shift)
R_ReadMusicScript(char * config_file)298 void R_ReadMusicScript( char *config_file )
299 {
300 	FILE *fp;
301 	int length;
302 	char *buffer;
303 	char *s;
304 	size_t result;
305 
306 	if((fp = fopen(config_file, "rb" )) == NULL)
307 	{
308 		return;
309 	}
310 
311 	length = FS_filelength( fp );
312 
313 	buffer = malloc( length + 1 );
314 	if ( buffer != NULL )
315 	{
316 		result = fread( buffer, length, 1, fp );
317 		if ( result == 1 )
318 		{
319 			buffer[length] = 0;
320 			s = buffer;
321 			strcpy( map_music, COM_Parse( &s ) );
322 			map_music[length] = 0; //clear any possible garbage
323 		}
324 		else
325 		{
326 			Com_DPrintf("R_ReadMusicScript: read fail: %s\n", config_file);
327 		}
328 
329 		free( buffer );
330 	}
331 	fclose( fp );
332 
333 	return;
334 }
335 
336 /*
337 =================
338 R_CullBox
339 
340 Returns true if the box is completely outside the frustom
341 =================
342 */
R_CullBox(vec3_t mins,vec3_t maxs)343 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
344 {
345 	int		i;
346 	cplane_t *p;
347 
348 	if (r_nocull->integer)
349 		return false;
350 
351 	for (i=0,p=frustum ; i<4; i++,p++)
352 	{
353 		switch (p->signbits)
354 		{
355 		case 0:
356 			if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
357 				return true;
358 			break;
359 		case 1:
360 			if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
361 				return true;
362 			break;
363 		case 2:
364 			if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
365 				return true;
366 			break;
367 		case 3:
368 			if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
369 				return true;
370 			break;
371 		case 4:
372 			if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
373 				return true;
374 			break;
375 		case 5:
376 			if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
377 				return true;
378 			break;
379 		case 6:
380 			if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
381 				return true;
382 			break;
383 		case 7:
384 			if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
385 				return true;
386 			break;
387 		default:
388 			return false;
389 		}
390 	}
391 
392 	return false;
393 }
394 
395 /*
396 =================
397 R_CullOrigin
398 
399 Returns true if the origin is completely outside the frustom
400 =================
401 */
402 
R_CullOrigin(vec3_t origin)403 qboolean R_CullOrigin(vec3_t origin)
404 {
405 	int i;
406 
407 	for (i = 0; i < 4; i++)
408 		if (BOX_ON_PLANE_SIDE(origin, origin, &frustum[i]) == 2)
409 			return true;
410 	return false;
411 }
412 
R_CullSphere(const vec3_t centre,const float radius,const int clipflags)413 qboolean R_CullSphere( const vec3_t centre, const float radius, const int clipflags )
414 {
415 	int		i;
416 	cplane_t *p;
417 
418 	if (r_nocull->value)
419 		return false;
420 
421 	for (i=0,p=frustum ; i<4; i++,p++)
422 	{
423 		if ( !(clipflags & (1<<i)) ) {
424 			continue;
425 		}
426 
427 		if ( DotProduct ( centre, p->normal ) - p->dist <= -radius )
428 			return true;
429 	}
430 
431 	return false;
432 }
433 
R_RotateForEntity(entity_t * e)434 void R_RotateForEntity (entity_t *e)
435 {
436     qglTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
437 
438     qglRotatef (e->angles[1],  0, 0, 1);
439     qglRotatef (-e->angles[0],  0, 1, 0);
440 
441     qglRotatef (-e->angles[2],  1, 0, 0);
442 }
443 
444 /*
445 =============
446 R_DrawNullModel
447 =============
448 */
R_DrawNullModel(void)449 void R_DrawNullModel (void)
450 {
451 	vec3_t	shadelight;
452 	int		i;
453 
454 	if ( currententity->flags & RF_FULLBRIGHT )
455 		shadelight[0] = shadelight[1] = shadelight[2] = 1.0F;
456 	else
457 		R_LightPoint (currententity->origin, shadelight, true);
458 
459     qglPushMatrix ();
460 	R_RotateForEntity (currententity);
461 
462 	qglDisable (GL_TEXTURE_2D);
463 	qglColor3fv (shadelight);
464 
465 	qglBegin (GL_TRIANGLE_FAN);
466 	qglVertex3f (0, 0, -16);
467 	for (i=0 ; i<=4 ; i++)
468 		qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0);
469 	qglEnd ();
470 
471 	qglBegin (GL_TRIANGLE_FAN);
472 	qglVertex3f (0, 0, 16);
473 	for (i=4 ; i>=0 ; i--)
474 		qglVertex3f (16*cos(i*M_PI/2), 16*sin(i*M_PI/2), 0);
475 	qglEnd ();
476 
477 	qglColor3f (1,1,1);
478 	qglPopMatrix ();
479 	qglEnable (GL_TEXTURE_2D);
480 }
481 
482 #include "r_lodcalc.h"
483 
484 /*
485 =============
486 R_DrawEntitiesOnList
487 =============
488 */
489 extern cvar_t *cl_simpleitems;
R_DrawEntitiesOnList(void)490 void R_DrawEntitiesOnList (void)
491 {
492 	int		i;
493 	rscript_t	*rs = NULL;
494 	vec3_t	dist;
495 
496 	if (!r_drawentities->integer)
497 		return;
498 
499 	if ( !r_odeinit_success )
500 	{ // ODE init failed, force ragdolls off
501 		r_ragdolls = Cvar_ForceSet("r_ragdolls", "0");
502 	}
503 
504 	// draw non-transparent first
505 	for (i=0 ; i<r_newrefdef.num_entities ; i++)
506 	{
507 		currententity = &r_newrefdef.entities[i];
508 		if (currententity->flags & RF_TRANSLUCENT)
509 			continue;	// transluscent
510 
511 		if (currententity->model && r_shaders->integer)
512 		{
513 			rs=(rscript_t *)currententity->model->script;
514 
515 			//custom player skin (must be done here)
516 			if (currententity->skin)
517 			{
518 			    rs = currententity->skin->script;
519                 if(rs)
520                     RS_ReadyScript(rs);
521             }
522 
523 			if (rs)
524 				currententity->script = rs;
525 			else
526 				currententity->script = NULL;
527 		}
528 
529 		currentmodel = currententity->model;
530 
531 		if (cl_simpleitems->integer && currentmodel && currentmodel->simple_texnum)
532 			continue;
533 
534 		//get distance
535 		VectorSubtract(r_origin, currententity->origin, dist);
536 
537 		//set lod if available
538 		if(VectorLength(dist) > LOD_DIST*2.0)
539 		{
540 			if(currententity->lod2)
541 				currentmodel = currententity->lod2;
542 		}
543 		else if(VectorLength(dist) > LOD_DIST)
544 		{
545 			if(currententity->lod1)
546 				currentmodel = currententity->lod1;
547 		}
548 
549 		if (!currentmodel)
550 		{
551 			R_DrawNullModel ();
552 			continue;
553 		}
554 		switch (currentmodel->type)
555 		{
556 			case mod_alias:
557 				R_DrawAliasModel ();
558 				break;
559 			case mod_brush:
560 				R_DrawBrushModel ();
561 				break;
562 			case mod_iqm:
563 				R_DrawINTERQUAKEMODEL ();
564 				break;
565 			default:
566 				Com_Error(ERR_DROP, "Bad modeltype");
567 				break;
568 		}
569 	}
570 
571 	// draw transparent entities
572 	// we could sort these if it ever becomes a problem...
573 	qglDepthMask (0);		// no z writes
574 	for (i=0 ; i<r_newrefdef.num_entities ; i++)
575 	{
576 		currententity = &r_newrefdef.entities[i];
577 		if (!(currententity->flags & RF_TRANSLUCENT))
578 			continue;	// solid
579 
580 		if (currententity->model && r_shaders->integer)
581 		{
582 			rs=(rscript_t *)currententity->model->script;
583 
584 			//custom player skin (must be done here)
585 			if (currententity->skin)
586 			{
587                 rs = currententity->skin->script;
588                 if(rs)
589                     RS_ReadyScript(rs);
590             }
591 
592 			if (rs)
593 				currententity->script = rs;
594 			else
595 				currententity->script = NULL;
596 		}
597 
598 		currentmodel = currententity->model;
599 		fadeShadow = 1.0;
600 
601 		if (!currentmodel)
602 		{
603 			R_DrawNullModel ();
604 			continue;
605 		}
606 		switch (currentmodel->type)
607 		{
608 			case mod_alias:
609 				R_DrawAliasModel ();
610 				break;
611 			case mod_brush:
612 				R_DrawBrushModel ();
613 				break;
614 			case mod_iqm:
615 				R_DrawINTERQUAKEMODEL ();
616 				break;
617 			default:
618 				Com_Error (ERR_DROP, "Bad modeltype");
619 				break;
620 		}
621 	}
622 	qglDepthMask (1);		// back to writing
623 }
624 
R_DrawViewEntitiesOnList(void)625 void R_DrawViewEntitiesOnList (void)
626 {
627 	int		i;
628 	rscript_t	*rs = NULL;
629 
630 	if (!r_drawentities->integer)
631 		return;
632 
633 	if(r_newrefdef.rdflags & RDF_NOWORLDMODEL)
634 		return;
635 
636 	// draw non-transparent first
637 	for (i=0 ; i<r_newrefdef.num_viewentities ; i++)
638 	{
639 		currententity = &r_newrefdef.viewentities[i];
640 		if (currententity->flags & RF_TRANSLUCENT)
641 			continue;	// transluscent
642 
643 		if (currententity->model && r_shaders->integer)
644 		{
645 			rs=(rscript_t *)currententity->model->script;
646 
647 			//custom player skin (must be done here)
648 			if (currententity->skin)
649 			{
650                 rs = currententity->skin->script;
651                 if(rs)
652                     RS_ReadyScript(rs);
653             }
654 
655 			if (rs)
656 				currententity->script = rs;
657 			else
658 				currententity->script = NULL;
659 		}
660 
661 		currentmodel = currententity->model;
662 
663 		if (!currentmodel)
664 		{
665 			R_DrawNullModel ();
666 			continue;
667 		}
668 		switch (currentmodel->type)
669 		{
670 		case mod_alias:
671 			R_DrawAliasModel ();
672 			break;
673 		case mod_iqm:
674 			R_DrawINTERQUAKEMODEL ();
675 			break;
676 		default:
677 			Com_Error(ERR_DROP, "Bad modeltype");
678 			break;
679 		}
680 	}
681 
682 	// draw transparent entities
683 	// we could sort these if it ever becomes a problem...
684 	qglDepthMask (0);		// no z writes
685 	for (i=0 ; i<r_newrefdef.num_viewentities ; i++)
686 	{
687 		currententity = &r_newrefdef.viewentities[i];
688 		if (!(currententity->flags & RF_TRANSLUCENT))
689 			continue;	// solid
690 
691 		if (currententity->model && r_shaders->integer)
692 		{
693 			rs=(rscript_t *)currententity->model->script;
694 
695 			//custom player skin (must be done here)
696 			if (currententity->skin)
697 			{
698                 rs = currententity->skin->script;
699                 if(rs)
700                     RS_ReadyScript(rs);
701             }
702 
703 			if (rs)
704 				currententity->script = rs;
705 			else
706 				currententity->script = NULL;
707 		}
708 
709 		currentmodel = currententity->model;
710 
711 		if (!currentmodel)
712 		{
713 			R_DrawNullModel ();
714 			continue;
715 		}
716 		switch (currentmodel->type)
717 		{
718 		case mod_alias:
719 			R_DrawAliasModel ();
720 			break;
721 		case mod_iqm:
722 			R_DrawINTERQUAKEMODEL ();
723 			break;
724 		default:
725 			Com_Error (ERR_DROP, "Bad modeltype");
726 			break;
727 		}
728 	}
729 	qglDepthMask (1);		// back to writing
730 }
731 
732 extern int r_drawing_fbeffect;
733 extern int	r_fbFxType;
734 extern float r_fbeffectTime;
735 extern cvar_t *cl_paindist;
736 /*
737 ============
738 R_PolyBlend
739 ============
740 */
R_PolyBlend(void)741 void R_PolyBlend (void)
742 {
743 	if (!gl_polyblend->integer)
744 		return;
745 	if (!v_blend[3])
746 		return;
747 
748 	if(!r_drawing_fbeffect && cl_paindist->integer) {
749 		if(v_blend[0] > 2*v_blend[1] && v_blend[0] > 2*v_blend[2]) {
750 			r_drawing_fbeffect = true;
751 			r_fbFxType = 2; //FLASH DISTORTION
752 			r_fbeffectTime = rs_realtime;
753 		}
754 	}
755 
756 	qglDisable (GL_ALPHA_TEST);
757 	qglEnable (GL_BLEND);
758 	qglDisable (GL_DEPTH_TEST);
759 	qglDisable (GL_TEXTURE_2D);
760 
761 	qglMatrixMode(GL_PROJECTION);
762     qglLoadIdentity ();
763 	qglOrtho (0, 1, 1, 0, -99999, 99999);
764 
765 	qglMatrixMode(GL_MODELVIEW);
766     qglLoadIdentity ();
767 
768 	qglColor4fv (v_blend);
769 
770 	qglBegin (GL_TRIANGLES);
771 	qglVertex2f (-5, -5);
772 	qglVertex2f (10, -5);
773 	qglVertex2f (-5, 10);
774 	qglEnd ();
775 
776 	qglDisable (GL_BLEND);
777 	qglEnable (GL_TEXTURE_2D);
778 	qglEnable (GL_ALPHA_TEST);
779 
780 	qglColor4f(1,1,1,1);
781 }
782 
783 //=======================================================================
784 
SignbitsForPlane(cplane_t * out)785 int SignbitsForPlane (cplane_t *out)
786 {
787 	int	bits, j;
788 
789 	// for fast box on planeside test
790 
791 	bits = 0;
792 	for (j=0 ; j<3 ; j++)
793 	{
794 		if (out->normal[j] < 0)
795 			bits |= 1<<j;
796 	}
797 	return bits;
798 }
799 
800 
R_SetFrustum(void)801 void R_SetFrustum (void)
802 {
803 	int		i;
804 
805 	// rotate VPN right by FOV_X/2 degrees
806 	RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_newrefdef.fov_x / 2 ) );
807 	// rotate VPN left by FOV_X/2 degrees
808 	RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_newrefdef.fov_x / 2 );
809 	// rotate VPN up by FOV_X/2 degrees
810 	RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_newrefdef.fov_y / 2 );
811 	// rotate VPN down by FOV_X/2 degrees
812 	RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_newrefdef.fov_y / 2 ) );
813 
814 	for (i=0 ; i<4 ; i++)
815 	{
816 		frustum[i].type = PLANE_ANYZ;
817 		frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
818 		frustum[i].signbits = SignbitsForPlane (&frustum[i]);
819 	}
820 }
821 
822 //=======================================================================
823 
824 /*
825 ===============
826 R_SetupFrame
827 ===============
828 */
R_SetupFrame(void)829 void R_SetupFrame (void)
830 {
831 	int i;
832 	mleaf_t *leaf;
833 
834 	r_framecount++;
835 
836 // build the transformation matrix for the given view angles
837 	VectorCopy (r_newrefdef.vieworg, r_origin);
838 
839 	AngleVectors (r_newrefdef.viewangles, vpn, vright, vup);
840 
841 // current viewcluster
842 	if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
843 	{
844 		r_oldviewcluster = r_viewcluster;
845 		r_oldviewcluster2 = r_viewcluster2;
846 		r_viewleaf = leaf = Mod_PointInLeaf (r_origin, r_worldmodel);
847 		r_origin_leafnum = CM_PointLeafnum (r_origin);
848 		r_viewcluster = r_viewcluster2 = leaf->cluster;
849 
850 		// check above and below so crossing solid water doesn't draw wrong
851 		if (!leaf->contents)
852 		{	// look down a bit
853 			vec3_t	temp;
854 
855 			VectorCopy (r_origin, temp);
856 			temp[2] -= 16;
857 			r_viewleaf2 = leaf = Mod_PointInLeaf (temp, r_worldmodel);
858 			if ( !(leaf->contents & CONTENTS_SOLID) &&
859 				(leaf->cluster != r_viewcluster2) )
860 				r_viewcluster2 = leaf->cluster;
861 		}
862 		else
863 		{	// look up a bit
864 			vec3_t	temp;
865 
866 			VectorCopy (r_origin, temp);
867 			temp[2] += 16;
868 			r_viewleaf2 = leaf = Mod_PointInLeaf (temp, r_worldmodel);
869 			if ( !(leaf->contents & CONTENTS_SOLID) &&
870 				(leaf->cluster != r_viewcluster2) )
871 				r_viewcluster2 = leaf->cluster;
872 		}
873 	}
874 
875 	for (i=0 ; i<4 ; i++)
876 		v_blend[i] = r_newrefdef.blend[i];
877 
878 	c_brush_polys = 0;
879 	c_alias_polys = 0;
880 
881 }
882 
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)883 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
884 		     GLdouble zNear, GLdouble zFar )
885 {
886 	GLdouble xmin, xmax, ymin, ymax;
887 
888 	ymax = zNear * tan( fovy * M_PI / 360.0 );
889 	ymin = -ymax;
890 
891 	xmin = ymin * aspect;
892 	xmax = ymax * aspect;
893 
894 	xmin += -( 2 * gl_state.camera_separation ) / zNear;
895 	xmax += -( 2 * gl_state.camera_separation ) / zNear;
896 
897 	qglFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
898 
899 }
900 
901 
902 
903 /*
904 =============
905 R_SetupViewport
906 =============
907 */
R_SetupViewport(void)908 void R_SetupViewport (void)
909 {
910 	int		x, y, w, h;
911 
912 	// The viewport info in r_newrefdef is constructed with the upper left
913 	// corner as the origin, whereas glViewport treats the lower left corner
914 	// as the origin. So we have to do some math to fix the y-coordinates.
915 
916 	x = r_newrefdef.x;
917 	w = r_newrefdef.width;
918 	y = vid.height - r_newrefdef.y - r_newrefdef.height;
919 	h = r_newrefdef.height;
920 
921 	qglViewport (x, y, w, h);	// MPO : note this happens every frame interestingly enough
922 }
923 
924 
925 
926 /*
927 =============
928 R_SetupGL
929 =============
930 */
R_SetupGL(void)931 void R_SetupGL (void)
932 {
933 	float	screenaspect;
934 
935 	R_SetupViewport ();
936 
937 	//
938 	// set up projection matrix
939 	//
940     screenaspect = (float)r_newrefdef.width/r_newrefdef.height;
941 	qglMatrixMode(GL_PROJECTION);
942     qglLoadIdentity ();
943 
944 	if(r_newrefdef.fov_y < 90)
945 		MYgluPerspective (r_newrefdef.fov_y,  screenaspect,  4,  128000);
946 	else
947 		MYgluPerspective(r_newrefdef.fov_y, screenaspect, 4 * 74 / r_newrefdef.fov_y, 15000); //Phenax
948 
949 	qglCullFace(GL_FRONT);
950 
951 	qglMatrixMode(GL_MODELVIEW);
952     qglLoadIdentity ();
953 
954     qglRotatef (-90, 1, 0, 0);	    // put Z going up
955     qglRotatef (90,  0, 0, 1);	    // put Z going up
956 
957     qglRotatef (-r_newrefdef.viewangles[2],  1, 0, 0);
958 	qglRotatef (-r_newrefdef.viewangles[0],  0, 1, 0);
959 	qglRotatef (-r_newrefdef.viewangles[1],  0, 0, 1);
960 	qglTranslatef (-r_newrefdef.vieworg[0],  -r_newrefdef.vieworg[1],  -r_newrefdef.vieworg[2]);
961 
962 	qglGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
963 	qglGetFloatv(GL_PROJECTION_MATRIX, r_project_matrix);
964 	qglGetIntegerv(GL_VIEWPORT, (int *) r_viewport);
965 
966 	//
967 	// set drawing parms
968 	//
969 
970 	if (gl_cull->integer)
971 		qglEnable(GL_CULL_FACE);
972 
973 	qglDisable(GL_BLEND);
974 
975 	qglDisable(GL_ALPHA_TEST);
976 	qglEnable(GL_DEPTH_TEST);
977 }
978 
979 /*
980 =============
981 R_Clear
982 =============
983 */
984 extern cvar_t *info_spectator;
985 extern cvar_t *cl_add_blend;
986 extern qboolean have_stencil;
R_Clear(void)987 void R_Clear (void)
988 {
989 	qglClearColor(0,0,0,1);
990 	if (gl_clear->integer)
991 		qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
992 	else if (!cl_add_blend->integer && info_spectator->integer && (CM_PointContents(r_newrefdef.vieworg, 0) & CONTENTS_SOLID))
993 		qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //out of map
994 	else
995 		qglClear (GL_DEPTH_BUFFER_BIT);
996 
997 	gldepthmin = 0;
998 	gldepthmax = 1;
999 	qglDepthFunc (GL_LEQUAL);
1000 
1001 	qglDepthRange (gldepthmin, gldepthmax);
1002 
1003 	 //our shadow system uses a combo of shadmaps and stencil volumes.
1004     if (have_stencil && gl_shadowmaps->integer) {
1005 
1006         qglClearStencil(0);
1007         qglClear(GL_STENCIL_BUFFER_BIT);
1008     }
1009 }
1010 
R_Flash(void)1011 void R_Flash( void )
1012 {
1013 	R_PolyBlend ();
1014 }
1015 
1016 /*
1017 ================
1018 R_RenderView
1019 
1020 r_newrefdef must be set before the first call
1021 ================
1022 */
1023 
R_RenderView(refdef_t * fd)1024 void R_RenderView (refdef_t *fd)
1025 {
1026 	GLfloat colors[4] = {(GLfloat) fog.red, (GLfloat) fog.green, (GLfloat) fog.blue, (GLfloat) 0.1};
1027 
1028 	numRadarEnts = 0;
1029 
1030 	if (r_norefresh->integer)
1031 		return;
1032 
1033 	r_newrefdef = *fd;
1034 
1035 	//shadowmaps
1036 	if(gl_shadowmaps->integer) {
1037 
1038 		qglEnable(GL_DEPTH_TEST);
1039 		qglClearColor(0,0,0,1.0f);
1040 
1041 		qglEnable(GL_CULL_FACE);
1042 
1043 		qglHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
1044 
1045 		R_DrawDynamicCaster();
1046 
1047 		R_DrawVegetationCaster();
1048 
1049 		qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0);
1050 
1051 		//Enabling color write (previously disabled for light POV z-buffer rendering)
1052 		qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1053 	}
1054 
1055 	if (!r_worldmodel && !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
1056 		Com_Error (ERR_DROP, "R_RenderView: NULL worldmodel");
1057 
1058 	// init r_speeds counters
1059 	last_c_brush_polys = c_brush_polys;
1060 	last_c_alias_polys = c_alias_polys;
1061 	c_brush_polys = 0;
1062 	c_alias_polys = 0;
1063 	c_flares = 0;
1064 	c_grasses = 0;
1065 	c_beams = 0;
1066 	c_vbo_batches = 0;
1067 
1068 	R_PushDlights ();
1069 
1070 	R_SetupFrame ();
1071 
1072 	R_SetFrustum ();
1073 
1074 	R_MarkWorldSurfs ();	// done here so we know if we're in water
1075 
1076 	if (gl_finish->integer)
1077 		qglFinish ();
1078 
1079 	// OpenGL calls come after here
1080 
1081 	R_SetupGL ();
1082 
1083 	if(map_fog)
1084 	{
1085 		qglFogi(GL_FOG_MODE, GL_LINEAR);
1086 		qglFogfv(GL_FOG_COLOR, colors);
1087 		qglFogf(GL_FOG_START, fog.start);
1088 		qglFogf(GL_FOG_END, fog.end);
1089 		qglFogf(GL_FOG_DENSITY, fog.density);
1090 		qglEnable(GL_FOG);
1091 	}
1092 
1093 	R_DrawWorldSurfs ();
1094 
1095 	if(r_lensflare->integer)
1096 		R_RenderFlares ();
1097 
1098 	R_DrawEntitiesOnList ();
1099 
1100 	R_DrawVegetationSurface ();
1101 
1102 	R_DrawSimpleItems ();
1103 
1104 	R_CastShadow();
1105 
1106 	R_RenderAllRagdolls(); //move back ahead of r_castshadow when we figure out shadow jitter bug
1107 
1108 	R_DrawViewEntitiesOnList ();
1109 
1110 	R_DrawAlphaSurfaces ();
1111 
1112 	if (r_lightbeam->integer)
1113 		R_DrawBeamSurface ();
1114 
1115 	R_DrawParticles ();
1116 
1117 	if(gl_mirror->integer)
1118 	{
1119 		int ms = Sys_Milliseconds ();
1120 		if (	ms < r_newrefdef.last_mirrorupdate_time ||
1121 				(ms-r_newrefdef.last_mirrorupdate_time) >= 16)
1122 		{
1123 			GL_SelectTexture (GL_TEXTURE0);
1124 			GL_Bind (r_mirrortexture->texnum);
1125 			qglCopyTexSubImage2D(GL_TEXTURE_2D, 0,
1126 						0, 0, 0, r_mirrortexture->upload_height/2,
1127 						r_mirrortexture->upload_width,
1128 						r_mirrortexture->upload_height);
1129 			r_newrefdef.last_mirrorupdate_time = ms;
1130 		}
1131 	}
1132 
1133 
1134 	R_BloomBlend( &r_newrefdef );//BLOOMS
1135 
1136 	R_RenderSun();
1137 
1138 	R_GLSLPostProcess();
1139 
1140 	R_DrawVehicleHUD();
1141 
1142 	R_Flash();
1143 
1144 	if(map_fog)
1145 		qglDisable(GL_FOG);
1146 
1147 	R_DrawRadar();
1148 
1149 	*fd = r_newrefdef;
1150 }
1151 
R_SetGL2D(void)1152 void	R_SetGL2D (void)
1153 {
1154 	// set 2D virtual screen size
1155 	qglViewport (0,0, vid.width, vid.height);
1156 	qglMatrixMode(GL_PROJECTION);
1157     qglLoadIdentity ();
1158 	qglOrtho  (0, vid.width, vid.height, 0, -99999, 99999);
1159 	qglMatrixMode(GL_MODELVIEW);
1160     qglLoadIdentity ();
1161 	qglDisable (GL_DEPTH_TEST);
1162 	qglDisable (GL_CULL_FACE);
1163 	qglDisable (GL_BLEND);
1164 	qglEnable (GL_ALPHA_TEST);
1165 	qglColor4f (1,1,1,1);
1166 }
1167 
1168 /*
1169 @@@@@@@@@@@@@@@@@@@@@
1170 R_RenderFrame
1171 
1172 @@@@@@@@@@@@@@@@@@@@@
1173 */
1174 
R_RenderFrame(refdef_t * fd)1175 void R_RenderFrame (refdef_t *fd)
1176 {
1177 	R_RenderView( fd );
1178 
1179 	R_SetGL2D ();
1180 }
1181 
R_RenderFramePlayerSetup(refdef_t * rfdf)1182 void R_RenderFramePlayerSetup( refdef_t *rfdf )
1183 {
1184 
1185 	numRadarEnts = 0;
1186 
1187 	r_newrefdef = *rfdf;
1188 
1189 	R_SetupFrame();
1190 	R_SetFrustum();
1191 	R_SetupGL();
1192 	R_DrawEntitiesOnList();
1193 
1194 	R_SetGL2D();
1195 
1196 }
1197 
R_Register(void)1198 void R_Register( void )
1199 {
1200 
1201 	con_font = Cvar_Get ("con_font", "default", CVAR_ARCHIVE);
1202 
1203 	r_lefthand = Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE | CVARDOC_INT);
1204 	Cvar_Describe (r_lefthand, "0 means show gun on the right, 1 means show gun on the left, 2 means hide the gun altogether.");
1205 	r_norefresh = Cvar_Get ("r_norefresh", "0", 0);
1206 	r_fullbright = Cvar_Get ("r_fullbright", "0", 0);
1207 	r_drawentities = Cvar_Get ("r_drawentities", "1", 0);
1208 	r_drawworld = Cvar_Get ("r_drawworld", "1", 0);
1209 	r_novis = Cvar_Get ("r_novis", "0", 0);
1210 	r_nocull = Cvar_Get ("r_nocull", "0", 0);
1211 	r_lerpmodels = Cvar_Get ("r_lerpmodels", "1", 0);
1212 
1213 	r_wave = Cvar_Get ("r_wave", "2", CVAR_ARCHIVE); // Water waves
1214 
1215 	gl_nosubimage = Cvar_Get( "gl_nosubimage", "0", 0 );
1216 
1217 	gl_particle_min_size = Cvar_Get( "gl_particle_min_size", ".2", CVAR_ARCHIVE );
1218 	gl_particle_max_size = Cvar_Get( "gl_particle_max_size", "40", CVAR_ARCHIVE );
1219 	gl_particle_size = Cvar_Get( "gl_particle_size", "40", CVAR_ARCHIVE );
1220 	gl_particle_att_a = Cvar_Get( "gl_particle_att_a", "0.01", CVAR_ARCHIVE );
1221 	gl_particle_att_b = Cvar_Get( "gl_particle_att_b", "0.0", CVAR_ARCHIVE );
1222 	gl_particle_att_c = Cvar_Get( "gl_particle_att_c", "0.01", CVAR_ARCHIVE );
1223 
1224 	gl_modulate = Cvar_Get ("gl_modulate", "2", CVAR_ARCHIVE|CVARDOC_INT );
1225 	Cvar_Describe (gl_modulate, "Brightness setting. Higher means brighter.");
1226 	gl_log = Cvar_Get( "gl_log", "0", 0 );
1227 	gl_bitdepth = Cvar_Get( "gl_bitdepth", "0", 0 );
1228 	gl_mode = Cvar_Get( "gl_mode", "3", CVAR_ARCHIVE );
1229 	gl_lightmap = Cvar_Get ("gl_lightmap", "0", 0);
1230 	gl_nobind = Cvar_Get ("gl_nobind", "0", 0);
1231 	gl_picmip = Cvar_Get ("gl_picmip", "0", CVAR_ARCHIVE|CVARDOC_INT);
1232 	Cvar_Describe (gl_picmip, "Texture detail. 0 means full detail. Each higher setting has 1/4 less detail.");
1233 	gl_skymip = Cvar_Get ("gl_skymip", "0", 0);
1234 	gl_showtris = Cvar_Get ("gl_showtris", "0", 0);
1235 	gl_showpolys = Cvar_Get ("gl_showpolys", "0", CVARDOC_INT);
1236 	Cvar_Describe (gl_showpolys, "Useful tool for mappers. 1 means show world polygon outlines for visible surfaces. 2 means show outlines for all surfaces in the PVS, even if they are hidden. Only works with gl_usevbo 0.");
1237 	gl_finish = Cvar_Get ("gl_finish", "0", CVAR_ARCHIVE|CVARDOC_BOOL);
1238 	Cvar_Describe (gl_finish, "Waits for graphics driver to finish drawing each frame before drawing the next one. Hurts performance but may improve smoothness on very low-end machines.");
1239 	gl_clear = Cvar_Get ("gl_clear", "0", CVARDOC_BOOL);
1240 	gl_cull = Cvar_Get ("gl_cull", "1", CVARDOC_BOOL);
1241 	Cvar_Describe (gl_cull, "Avoid rendering anything that's off the edge of the screen. Good for performance, recommend leaving it on.");
1242 	gl_polyblend = Cvar_Get ("gl_polyblend", "1", 0);
1243 
1244 // OPENGL_DRIVER defined by in config.h
1245 	gl_driver = Cvar_Get( "gl_driver", OPENGL_DRIVER, 0 );
1246 
1247 	gl_texturemode = Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE );
1248 	gl_texturealphamode = Cvar_Get( "gl_texturealphamode", "default", CVAR_ARCHIVE );
1249 	gl_texturesolidmode = Cvar_Get( "gl_texturesolidmode", "default", CVAR_ARCHIVE );
1250 	gl_lockpvs = Cvar_Get( "gl_lockpvs", "0", 0 );
1251 
1252 	gl_ext_pointparameters = Cvar_Get( "gl_ext_pointparameters", "0", CVAR_ARCHIVE );
1253 
1254 	gl_drawbuffer = Cvar_Get( "gl_drawbuffer", "GL_BACK", 0 );
1255 	gl_swapinterval = Cvar_Get( "gl_swapinterval", "1", CVAR_ARCHIVE|CVARDOC_BOOL );
1256 	Cvar_Describe (gl_swapinterval, "Sync to Vblank. Eliminates \"tearing\" effects, but it can hurt framerates.");
1257 
1258 	r_shaders = Cvar_Get ("r_shaders", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1259 
1260 	r_overbrightbits = Cvar_Get( "r_overbrightbits", "2", CVAR_ARCHIVE );
1261 
1262 	gl_usevbo = Cvar_Get("gl_usevbo", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1263 	Cvar_Describe (gl_usevbo, "Use VBOs for mesh and world geometry. Leave this on unless you've got a very old graphics card.");
1264 
1265 	gl_mirror = Cvar_Get("gl_mirror", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1266 
1267 	vid_fullscreen = Cvar_Get( "vid_fullscreen", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1268 	vid_gamma = Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE );
1269 	vid_contrast = Cvar_Get( "vid_contrast", "1.0", CVAR_ARCHIVE);
1270 	//TODO: remove, unless we decide to add GL ES support or something.
1271 	vid_ref = Cvar_Get( "vid_ref", "gl", CVAR_ARCHIVE|CVAR_ROM );
1272 
1273 	gl_vlights = Cvar_Get("gl_vlights", "1", CVAR_ARCHIVE);
1274 
1275 	gl_normalmaps = Cvar_Get("gl_normalmaps", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1276 	gl_bspnormalmaps = Cvar_Get("gl_bspnormalmaps", "0", CVAR_ARCHIVE|CVARDOC_BOOL);
1277 	gl_shadowmaps = Cvar_Get("gl_shadowmaps", "0", CVAR_ARCHIVE|CVARDOC_BOOL);
1278 	gl_fog = Cvar_Get ("gl_fog", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1279 	Cvar_Describe (gl_fog, "Fog and weather effects.");
1280 
1281 	r_shadowmapscale = Cvar_Get( "r_shadowmapscale", "1", CVAR_ARCHIVE );
1282 	r_shadowcutoff = Cvar_Get( "r_shadowcutoff", "880", CVAR_ARCHIVE );
1283 
1284 	r_lensflare = Cvar_Get( "r_lensflare", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1285 	r_lensflare_intens = Cvar_Get ("r_lensflare_intens", "3", CVAR_ARCHIVE|CVARDOC_INT);
1286 	r_drawsun =	Cvar_Get("r_drawsun", "2", CVAR_ARCHIVE);
1287 	r_lightbeam = Cvar_Get ("r_lightbeam", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1288 	r_godrays = Cvar_Get ("r_godrays", "0", CVAR_ARCHIVE|CVARDOC_BOOL);
1289 	r_godray_intensity = Cvar_Get ("r_godray_intensity", "1.0", CVAR_ARCHIVE);
1290 	r_optimize = Cvar_Get ("r_optimize", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1291 	Cvar_Describe (r_optimize, "Skip BSP recursion unless you move. Good for performance, recommend leaving it on.");
1292 
1293 	r_lightmapfiles = Cvar_Get("r_lightmapfiles", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1294 	Cvar_Describe (r_lightmapfiles, "Enables the loading of .lightmap files, with more detailed light and shadow. Turn this off if video RAM is limited.");
1295 
1296 	r_minimap_size = Cvar_Get ("r_minimap_size", "256", CVAR_ARCHIVE );
1297 	r_minimap_zoom = Cvar_Get ("r_minimap_zoom", "1", CVAR_ARCHIVE );
1298 	r_minimap_style = Cvar_Get ("r_minimap_style", "1", CVAR_ARCHIVE );
1299 	r_minimap = Cvar_Get ("r_minimap", "0", CVAR_ARCHIVE|CVARDOC_BOOL );
1300 
1301 	r_ragdolls = Cvar_Get ("r_ragdolls", "1", CVAR_ARCHIVE|CVARDOC_BOOL);
1302 	r_ragdoll_debug = Cvar_Get("r_ragdoll_debug", "0", CVAR_ARCHIVE|CVARDOC_BOOL);
1303 
1304 	sys_priority = Cvar_Get("sys_priority", "0", CVAR_ARCHIVE);
1305 	sys_affinity = Cvar_Get("sys_affinity", "1", CVAR_ARCHIVE);
1306 
1307 	gl_screenshot_type = Cvar_Get("gl_screenshot_type", "jpeg", CVAR_ARCHIVE|CVARDOC_STR);
1308 	gl_screenshot_jpeg_quality = Cvar_Get("gl_screenshot_jpeg_quality", "85", CVAR_ARCHIVE|CVARDOC_INT);
1309 
1310 	r_firstrun = Cvar_Get("r_firstrun", "0", CVAR_ARCHIVE|CVARDOC_BOOL); //first time running the game
1311 	Cvar_Describe (r_firstrun, "Set this to 0 if you want the game to auto detect your graphics settings next time you run it.");
1312 
1313 	r_test = Cvar_Get("r_test", "0", CVAR_ARCHIVE); //for testing things
1314 
1315 	// FIXME HACK copied over from the video menu code. These are initialized
1316 	// again elsewhere. TODO: work out any complications that may arise from
1317 	// deleting these duplicate initializations.
1318 	Cvar_Get( "r_bloom", "0", CVAR_ARCHIVE );
1319 	Cvar_Get( "r_bloom_intensity", "0.5", CVAR_ARCHIVE);
1320 	Cvar_Get( "r_overbrightbits", "2", CVAR_ARCHIVE);
1321 	Cvar_Get( "vid_width", "640", CVAR_ARCHIVE);
1322 	Cvar_Get( "vid_height", "400", CVAR_ARCHIVE);
1323 	Cvar_Get( "gl_glsl_shaders", "1", CVAR_ARCHIVE);
1324 
1325 	Cmd_AddCommand( "imagelist", GL_ImageList_f );
1326 	Cmd_AddCommand( "screenshot", GL_ScreenShot_f );
1327 	Cmd_AddCommand( "modellist", Mod_Modellist_f );
1328 	Cmd_AddCommand( "gl_strings", GL_Strings_f );
1329 }
1330 
1331 /*
1332 ==================
1333 R_SetMode
1334 ==================
1335 */
R_SetMode(void)1336 qboolean R_SetMode (void)
1337 {
1338 	rserr_t err;
1339 	qboolean fullscreen;
1340 
1341 	if ( vid_fullscreen->modified && !gl_config.allow_cds )
1342 	{
1343 		Com_Printf ("R_SetMode() - CDS not allowed with this driver\n" );
1344 		Cvar_SetValue( "vid_fullscreen", !vid_fullscreen->integer );
1345 		vid_fullscreen->modified = false;
1346 	}
1347 
1348 	fullscreen = vid_fullscreen->integer;
1349 
1350 	vid_fullscreen->modified = false;
1351 	gl_mode->modified = false;
1352 
1353 	if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->integer, fullscreen ) ) == rserr_ok )
1354 	{
1355 		gl_state.prev_mode = gl_mode->integer;
1356 	}
1357 	else
1358 	{
1359 		if ( err == rserr_invalid_fullscreen )
1360 		{
1361 			Cvar_SetValue( "vid_fullscreen", 0);
1362 			vid_fullscreen->modified = false;
1363 			Com_Printf ("ref_gl::R_SetMode() - fullscreen unavailable in this mode\n" );
1364 			if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->integer, false ) ) == rserr_ok )
1365 				return true;
1366 		}
1367 		else if ( err == rserr_invalid_mode )
1368 		{
1369 			Cvar_SetValue( "gl_mode", gl_state.prev_mode );
1370 			gl_mode->modified = false;
1371 			Com_Printf ("ref_gl::R_SetMode() - invalid mode\n" );
1372 		}
1373 
1374 		// try setting it back to something safe
1375 		if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_state.prev_mode, false ) ) != rserr_ok )
1376 		{
1377 			Com_Printf ("ref_gl::R_SetMode() - could not revert to safe mode\n" );
1378 			return false;
1379 		}
1380 	}
1381 	return true;
1382 }
1383 
1384 /*
1385 ===============
1386 R_SetCompatibility
1387 ===============
1388 */
1389 
R_SetCompatibility(void)1390 void R_SetCompatibility(void)
1391 {
1392 	Cmd_ExecuteString ("exec graphical_presets/compatibility.cfg");
1393 	Cbuf_Execute ();
1394 	Com_Printf("...autodetected MAX COMPATIBILITY game setting\n");
1395 }
1396 
1397 /*
1398 ===============
1399 R_SetMaxPerformance
1400 ===============
1401 */
1402 
R_SetMaxPerformance(void)1403 void R_SetMaxPerformance( void )
1404 {
1405 	Cmd_ExecuteString ("exec graphical_presets/maxperformance.cfg");
1406 	Cbuf_Execute ();
1407 	Com_Printf("...autodetected MAX PERFORMANCE game setting\n");
1408 }
1409 
1410 /*
1411 ===============
1412 R_SetPerformance
1413 ===============
1414 */
1415 
R_SetPerformance(void)1416 void R_SetPerformance( void )
1417 {
1418 	Cmd_ExecuteString ("exec graphical_presets/performance.cfg");
1419 	Cbuf_Execute ();
1420 	Com_Printf("...autodetected PERFORMANCE game setting\n");
1421 }
1422 
1423 /*
1424 ===============
1425 R_SetQuality
1426 ===============
1427 */
1428 
R_SetQuality(void)1429 void R_SetQuality( void )
1430 {
1431 	Cmd_ExecuteString ("exec graphical_presets/quality.cfg");
1432 	Cbuf_Execute ();
1433 	Com_Printf("...autodetected QUALITY game setting\n");
1434 }
1435 
1436 /*
1437 ===============
1438 R_SetMaxQuality
1439 ===============
1440 */
1441 
R_SetMaxQuality(void)1442 void R_SetMaxQuality( void )
1443 {
1444 	Cmd_ExecuteString ("exec graphical_presets/maxquality.cfg");
1445 	Cbuf_Execute ();
1446 	Com_Printf("...autodetected MAX QUALITY game setting\n");
1447 }
1448 
1449 #if defined WIN32_VARIANT
CPUSpeed()1450 double CPUSpeed()
1451 {
1452 
1453 
1454 	DWORD BufSize = _MAX_PATH;
1455 	DWORD dwMHz = _MAX_PATH;
1456 	HKEY hKey;    // open the key where the proc speed is hidden:
1457 
1458 	long lError = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1459 		"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
1460 		0,
1461 		KEY_READ,
1462 		&hKey);
1463 
1464 	if(lError != ERROR_SUCCESS)
1465 		return 0;
1466 
1467 	// query the key:
1468 	RegQueryValueEx(hKey, "~MHz", NULL, NULL, (LPBYTE) &dwMHz, &BufSize);
1469 	return (double)dwMHz;
1470 
1471 }
1472 #endif
1473 
1474 /*
1475 ===============
1476 R_Init
1477 ===============
1478 */
R_Init(void * hinstance,void * hWnd)1479 int R_Init( void *hinstance, void *hWnd )
1480 {
1481 	int		err;
1482 	int		j;
1483 	extern float r_turbsin[256];
1484 
1485 	for ( j = 0; j < 256; j++ )
1486 	{
1487 		r_turbsin[j] *= 0.5;
1488 	}
1489 
1490 	Draw_GetPalette ();
1491 
1492 	R_Register();
1493 
1494 	// initialize our QGL dynamic bindings
1495 	if ( !QGL_Init( gl_driver->string ) )
1496 	{
1497 		QGL_Shutdown();
1498 		Com_Printf ("ref_gl::R_Init() - could not load \"%s\"\n", gl_driver->string );
1499 		return -1;
1500 	}
1501 
1502 	// initialize OS-specific parts of OpenGL
1503 	if ( !GLimp_Init( hinstance, hWnd ) )
1504 	{
1505 		QGL_Shutdown();
1506 		return -1;
1507 	}
1508 
1509 	// set our "safe" modes
1510 	gl_state.prev_mode = 3;
1511 
1512 	// create the window and set up the context
1513 	if ( !R_SetMode () )
1514 	{
1515 		QGL_Shutdown();
1516 		Com_Printf ("ref_gl::R_Init() - could not R_SetMode()\n" );
1517 		return -1;
1518 	}
1519 
1520 	// Initialise TrueType fonts
1521 	if ( ! FNT_Initialise( ) ) {
1522 		QGL_Shutdown( );
1523 		Com_Printf( "ref_gl::R_Init() - could not initialise text drawing front-end\n" );
1524 		return -1;
1525 	}
1526 
1527 	/*
1528 	** get our various GL strings
1529 	*/
1530 	gl_config.vendor_string = (const char*)qglGetString (GL_VENDOR);
1531 	Com_Printf ("GL_VENDOR: %s\n", gl_config.vendor_string );
1532 	gl_config.renderer_string = (const char*)qglGetString (GL_RENDERER);
1533 	Com_Printf ("GL_RENDERER: %s\n", gl_config.renderer_string );
1534 	gl_config.version_string = (const char*)qglGetString (GL_VERSION);
1535 	Com_Printf ("GL_VERSION: %s\n", gl_config.version_string );
1536 	gl_config.extensions_string = (const char*)qglGetString (GL_EXTENSIONS);
1537 	Com_Printf ("GL_EXTENSIONS: %s\n", gl_config.extensions_string );
1538 
1539 	gl_config.allow_cds = true;
1540 	Com_Printf ("...allowing CDS\n" );
1541 
1542 	/*
1543 	** grab extensions
1544 	*/
1545 	if ( strstr( gl_config.extensions_string, "GL_EXT_compiled_vertex_array" ) ||
1546 		 strstr( gl_config.extensions_string, "GL_SGI_compiled_vertex_array" ) )
1547 	{
1548 		Com_Printf ("...enabling GL_EXT_compiled_vertex_array\n" );
1549 		qglLockArraysEXT = ( void * ) qwglGetProcAddress( "glLockArraysEXT" );
1550 		qglUnlockArraysEXT = ( void * ) qwglGetProcAddress( "glUnlockArraysEXT" );
1551 	}
1552 	else
1553 	{
1554 		Com_Printf ("...GL_EXT_compiled_vertex_array not found\n" );
1555 	}
1556 
1557 #if defined WIN32_VARIANT
1558 	if ( strstr( gl_config.extensions_string, "WGL_EXT_swap_control" ) )
1559 	{
1560 		qwglSwapIntervalEXT = ( BOOL (WINAPI *)(int)) qwglGetProcAddress( "wglSwapIntervalEXT" );
1561 		Com_Printf ("...enabling WGL_EXT_swap_control\n" );
1562 	}
1563 	else
1564 	{
1565 		Com_Printf ("...WGL_EXT_swap_control not found\n" );
1566 	}
1567 #endif
1568 
1569 	if (strstr(gl_config.extensions_string, "GL_EXT_point_parameters"))
1570 	{
1571 		if(gl_ext_pointparameters->integer)
1572 		{
1573 			qglPointParameterfEXT = (void(APIENTRY*)(GLenum, GLfloat))qwglGetProcAddress("glPointParameterfEXT");
1574 			qglPointParameterfvEXT = (void(APIENTRY*)(GLenum, const GLfloat*))qwglGetProcAddress("glPointParameterfvEXT");
1575 		}
1576 		else
1577 		{
1578 			Com_Printf ("...ignoring GL_EXT_point_parameters\n" );
1579 		}
1580 	}
1581 	else
1582 	{
1583 		Com_Printf ("...GL_EXT_point_parameters not found\n" );
1584 	}
1585 
1586 	R_InitImageSubsystem();
1587 
1588 	R_InitShadowSubsystem();
1589 
1590 	R_LoadVBOSubsystem();
1591 
1592 #if defined DARWIN_SPECIAL_CASE
1593 	/*
1594 	 * development workaround for Mac OS X / Darwin using X11
1595 	 *  problems seen with 2.1 NVIDIA-1.6.18 when calling
1596 	 *  glCreateProgramObjectARB()
1597 	 * For now, just go with low settings.
1598 	 */
1599 	gl_state.fragment_program = false;
1600 	gl_arb_fragment_program = Cvar_Get("gl_arb_fragment_program", "0", CVAR_ARCHIVE);
1601 	gl_state.glsl_shaders = false;
1602 	gl_glsl_shaders = Cvar_Get("gl_glsl_shaders", "0", CVAR_ARCHIVE);
1603 	gl_dynamic = Cvar_Get ("gl_dynamic", "0", CVAR_ARCHIVE);
1604 	Cvar_SetValue("r_firstrun", 1);
1605 	R_SetMaxPerformance();
1606 	Com_Printf("...Development Workaround. Low game settings forced.\n");
1607 #else
1608 
1609 	//always do this check for ATI drivers - they are somewhat bugged in regards to shadowmapping and use of shadow2dproj command
1610 	if(!strcmp(gl_config.vendor_string, "ATI Technologies Inc."))
1611 		gl_state.ati = true;
1612 
1613 	//load shader programs
1614 	R_LoadARBPrograms();
1615 
1616 	R_LoadGLSLPrograms();
1617 
1618 	//if running for the very first time, automatically set video settings
1619 	if(!r_firstrun->integer)
1620 	{
1621 		qboolean ati_nvidia = false;
1622 		double CPUTotalSpeed = 4000.0; //default to this
1623 		double OGLVer = atof(&gl_config.version_string[0]);
1624 		//int OGLSubVer = atoi(&gl_config.version_string[2]);
1625 
1626 #if defined WIN32_VARIANT
1627 		SYSTEM_INFO sysInfo;
1628 		GetSystemInfo(&sysInfo);
1629 
1630 		Com_Printf("...CPU: %4.2f Cores: %d\n", CPUSpeed(), sysInfo.dwNumberOfProcessors);
1631 
1632 		CPUTotalSpeed = sysInfo.dwNumberOfProcessors * CPUSpeed();
1633 
1634 #else
1635 		FILE	*fp;
1636         char	res[128];
1637 		int		cores;
1638 		size_t	szrslt;
1639 		int     irslt;
1640         fp = popen("/bin/cat /proc/cpuinfo | grep -c '^processor'","r");
1641         if ( fp == NULL )
1642         	goto cpuinfo_error;
1643         szrslt = fread(res, 1, sizeof(res)-1, fp);
1644         res[szrslt] = 0;
1645         pclose(fp);
1646         if ( !szrslt )
1647         	goto cpuinfo_error;
1648 		cores = atoi( &res[0] );
1649 		fp = popen("/bin/cat /proc/cpuinfo | grep '^cpu MHz'","r");
1650 		if ( fp == NULL )
1651 			goto cpuinfo_error;
1652         szrslt = fread(res, 1, sizeof(res)-1, fp);  // about 20 bytes/cpu
1653         res[szrslt] = 0;
1654 		pclose(fp);
1655 		if ( !szrslt )
1656 			goto cpuinfo_error;
1657 		irslt = sscanf( res, "cpu MHz : %lf", &CPUTotalSpeed );
1658 		if ( !irslt )
1659 			goto cpuinfo_error;
1660 		Com_Printf("...CPU: %4.2f Cores: %d\n", CPUTotalSpeed, cores);
1661 	    CPUTotalSpeed *= cores;
1662 	    goto cpuinfo_exit;
1663 cpuinfo_error:
1664 		Com_Printf("...Reading /proc/cpuinfo failed.\n");
1665 cpuinfo_exit:
1666 #endif
1667 
1668 		//check to see if we are using ATI or NVIDIA, otherwise, we don't want to
1669 		//deal with high settings on offbrand GPU's like Intel or Unichrome
1670 		if(!strcmp(gl_config.vendor_string, "ATI Technologies Inc.") || !strcmp(gl_config.vendor_string, "NVIDIA Corporation"))
1671 			ati_nvidia = true;
1672 
1673 		if(OGLVer < 2.1)
1674 		{
1675 			//weak GPU, set to maximum compatibility
1676 			R_SetCompatibility();
1677 		}
1678 		else if(OGLVer >= 3)
1679 		{
1680 			//GPU is modern, check CPU
1681 			if(CPUTotalSpeed > 3800.0 && ati_nvidia)
1682 				R_SetMaxQuality();
1683 			else
1684 				R_SetQuality();
1685 		}
1686 		else
1687 		{
1688 			if(CPUTotalSpeed > 3800.0 && ati_nvidia)
1689 				R_SetQuality();
1690 			else
1691 				R_SetPerformance();
1692 		}
1693 
1694 		//never run again
1695 		Cvar_SetValue("r_firstrun", 1);
1696 	}
1697 #endif
1698 
1699 	GL_SetDefaultState();
1700 
1701 	R_CheckFBOExtensions ();
1702 
1703 	GL_InitImages ();
1704 	Mod_Init ();
1705 	R_InitParticleTexture ();
1706 	Draw_InitLocal ();
1707 
1708 	R_GenerateShadowFBO();
1709 	VLight_Init();
1710 
1711 	//Initialize ODE
1712 	// ODE assert failures sometimes occur, this may or may not help.
1713 	r_odeinit_success = dInitODE2(0);
1714 	//ODE - clear out any ragdolls;
1715 	if ( r_odeinit_success )
1716 	{
1717 		Com_Printf("...ODE initialized.\n");
1718 		R_ClearAllRagdolls();
1719 		Com_Printf("...Ragdolls initialized.\n");
1720 	}
1721 	else
1722 	{
1723 		Com_Printf("...ODE initialization failed.\n...Ragdolls are disabled.\n");
1724 	}
1725 
1726 	scr_playericonalpha = 0.0;
1727 
1728 	err = qglGetError();
1729 	if ( err != GL_NO_ERROR )
1730 		Com_Printf ("glGetError() = 0x%x\n", err);
1731 
1732 	return 0;
1733 }
1734 
1735 /*
1736 ===============
1737 R_Shutdown
1738 ===============
1739 */
R_Shutdown(void)1740 void R_Shutdown (void)
1741 {
1742 	Cmd_RemoveCommand ("modellist");
1743 	Cmd_RemoveCommand ("screenshot");
1744 	Cmd_RemoveCommand ("imagelist");
1745 	Cmd_RemoveCommand ("gl_strings");
1746 
1747 	R_VCShutdown();
1748 
1749 	Mod_FreeAll ();
1750 
1751 	FNT_Shutdown( );
1752 	GL_ShutdownImages ();
1753 
1754 	/*
1755 	** shut down OS specific OpenGL stuff like contexts, etc.
1756 	*/
1757 	GLimp_Shutdown();
1758 
1759 	/*
1760 	** shutdown our QGL subsystem
1761 	*/
1762 	if(gl_state.glsl_shaders) {
1763 		glDeleteObjectARB( g_vertexShader );
1764 		glDeleteObjectARB( g_fragmentShader );
1765 		glDeleteObjectARB( g_programObj );
1766 	}
1767 
1768 	QGL_Shutdown();
1769 
1770 	//Shutdown ODE
1771 	// ODE might fail assert on close when not intialized
1772 	if ( r_odeinit_success )
1773 	{
1774 		Com_DPrintf("Closing ODE\n");
1775 		dCloseODE();
1776 	}
1777 }
1778 
1779 
1780 
1781 /*
1782 @@@@@@@@@@@@@@@@@@@@@
1783 R_BeginFrame
1784 @@@@@@@@@@@@@@@@@@@@@
1785 */
R_BeginFrame(float camera_separation)1786 void R_BeginFrame( float camera_separation )
1787 {
1788 
1789 	gl_state.camera_separation = camera_separation;
1790 
1791 	if (con_font->modified)
1792 		RefreshFont ();
1793 
1794 	/*
1795 	** change modes if necessary
1796 	*/
1797 	if ( gl_mode->modified || vid_fullscreen->modified )
1798 	{	// FIXME: only restart if CDS is required
1799 		cvar_t	*ref;
1800 
1801 		ref = Cvar_Get ("vid_ref", "gl", 0);
1802 		ref->modified = true;
1803 	}
1804 
1805 	if ( gl_log->modified )
1806 	{
1807 		GLimp_EnableLogging( gl_log->integer );
1808 		gl_log->modified = false;
1809 	}
1810 
1811 	if ( gl_log->integer )
1812 	{
1813 		GLimp_LogNewFrame();
1814 	}
1815 
1816 	GLimp_BeginFrame( camera_separation );
1817 
1818 	/*
1819 	** go into 2D mode
1820 	*/
1821 	R_SetGL2D ();
1822 
1823 	/*
1824 	** draw buffer stuff
1825 	*/
1826 	if ( gl_drawbuffer->modified )
1827 	{
1828 		gl_drawbuffer->modified = false;
1829 
1830 		if ( gl_state.camera_separation == 0 || !gl_state.stereo_enabled )
1831 		{
1832 			if ( Q_strcasecmp( gl_drawbuffer->string, "GL_FRONT" ) == 0 )
1833 				qglDrawBuffer( GL_FRONT );
1834 			else
1835 				qglDrawBuffer( GL_BACK );
1836 		}
1837 	}
1838 
1839 	/*
1840 	** texturemode stuff
1841 	*/
1842 	if ( gl_texturemode->modified )
1843 	{
1844 		GL_TextureMode( gl_texturemode->string );
1845 		gl_texturemode->modified = false;
1846 	}
1847 
1848 	if ( gl_texturealphamode->modified )
1849 	{
1850 		GL_TextureAlphaMode( gl_texturealphamode->string );
1851 		gl_texturealphamode->modified = false;
1852 	}
1853 
1854 	if ( gl_texturesolidmode->modified )
1855 	{
1856 		GL_TextureSolidMode( gl_texturesolidmode->string );
1857 		gl_texturesolidmode->modified = false;
1858 	}
1859 
1860 	/*
1861 	** swapinterval stuff
1862 	*/
1863 	GL_UpdateSwapInterval();
1864 
1865 	//
1866 	// clear screen if desired
1867 	//
1868 	R_Clear ();
1869 }
1870 
1871 /*
1872 =============
1873 R_AppActivate
1874 =============
1875 */
R_AppActivate(qboolean active)1876 void R_AppActivate( qboolean active )
1877 {
1878 	GLimp_AppActivate (active);
1879 }
1880 
1881 /*
1882 =============
1883 R_EndFrame
1884 =============
1885 */
R_EndFrame(void)1886 void R_EndFrame (void)
1887 {
1888 	 GLimp_EndFrame ();
1889 }
1890 
1891 /*
1892 =============
1893 R_SetPalette
1894 =============
1895 */
1896 unsigned r_rawpalette[256];
1897 
R_SetPalette(const unsigned char * palette)1898 void R_SetPalette ( const unsigned char *palette)
1899 {
1900 	int		i;
1901 
1902 	byte *rp = ( byte * ) r_rawpalette;
1903 
1904 	if ( palette )
1905 	{
1906 		for ( i = 0; i < 256; i++ )
1907 		{
1908 			rp[i*4+0] = palette[i*3+0];
1909 			rp[i*4+1] = palette[i*3+1];
1910 			rp[i*4+2] = palette[i*3+2];
1911 			rp[i*4+3] = 0xff;
1912 		}
1913 	}
1914 	else
1915 	{
1916 		for ( i = 0; i < 256; i++ )
1917 		{
1918 			rp[i*4+0] = d_8to24table[i] & 0xff;
1919 			rp[i*4+1] = ( d_8to24table[i] >> 8 ) & 0xff;
1920 			rp[i*4+2] = ( d_8to24table[i] >> 16 ) & 0xff;
1921 			rp[i*4+3] = 0xff;
1922 		}
1923 	}
1924 
1925 	if ( qglClear && qglClearColor)
1926 	{
1927 		// only run this if we haven't uninitialised
1928 		// OpenGL already
1929 		qglClearColor (0,0,0,0);
1930 		qglClear (GL_COLOR_BUFFER_BIT);
1931 		qglClearColor (1,0, 0.5 , 0.5);
1932 	}
1933 }
1934 
1935 /*
1936 ===============
1937 R_FarClip
1938 ===============
1939 */
R_FarClip(void)1940 float R_FarClip( void )
1941 {
1942 	float farclip, farclip_dist;
1943 	int i;
1944 	vec_t mins[4];
1945 	vec_t maxs[4];
1946 	vec_t dist;
1947 
1948 	farclip_dist = DotProduct( r_origin, vpn );
1949 
1950 	if(r_farclip_min > 256.0f)
1951 		farclip = farclip_dist + r_farclip_min;
1952 	else
1953 		farclip = farclip_dist + 256.0f;
1954 
1955 	if( r_worldmodel && !(r_newrefdef.rdflags & RDF_NOWORLDMODEL) ) {
1956 
1957 		for (i = 0; i < 3; i++) {
1958 			mins[i] = r_worldmodel->nodes[0].minmaxs[i];
1959 			maxs[i] = r_worldmodel->nodes[0].minmaxs[3+i];
1960 		}
1961 		dist = (vpn[0] < 0 ? mins[0] : maxs[0]) * vpn[0] +
1962 			(vpn[1] < 0 ? mins[1] : maxs[1]) * vpn[1] +
1963 			(vpn[2] < 0 ? mins[2] : maxs[2]) * vpn[2];
1964 		if( dist > farclip )
1965 			farclip = dist;
1966 	}
1967 
1968 	if((farclip - farclip_dist + r_farclip_bias) > r_farclip)
1969 		return ( farclip - farclip_dist + r_farclip_bias);
1970 	else
1971 		return r_farclip;
1972 }
1973 
1974 /*
1975 =============
1976 R_SetupProjectionMatrix
1977 =============
1978 */
R_SetupProjectionMatrix(refdef_t * rd,mat4x4_t m)1979 void R_SetupProjectionMatrix( refdef_t *rd, mat4x4_t m )
1980 {
1981 	double xMin, xMax, yMin, yMax, zNear, zFar;
1982 
1983 	r_farclip = R_FarClip ();
1984 
1985 	zNear = 4;
1986 	zFar = r_farclip;
1987 
1988 	yMax = zNear * tan( rd->fov_y * M_PI / 360.0 );
1989 	yMin = -yMax;
1990 
1991 	xMin = yMin * rd->width / rd->height;
1992 	xMax = yMax * rd->width / rd->height;
1993 
1994 	xMin += -( 2 * gl_state.camera_separation ) / zNear;
1995 	xMax += -( 2 * gl_state.camera_separation ) / zNear;
1996 
1997 	m[0] = (2.0 * zNear) / (xMax - xMin);
1998 	m[1] = 0.0f;
1999 	m[2] = 0.0f;
2000 	m[3] = 0.0f;
2001 	m[4] = 0.0f;
2002 	m[5] = (2.0 * zNear) / (yMax - yMin);
2003 	m[6] = 0.0f;
2004 	m[7] = 0.0f;
2005 	m[8] = (xMax + xMin) / (xMax - xMin);
2006 	m[9] = (yMax + yMin) / (yMax - yMin);
2007 	m[10] = -(zFar + zNear) / (zFar - zNear);
2008 	m[11] = -1.0f;
2009 	m[12] = 0.0f;
2010 	m[13] = 0.0f;
2011 	m[14] = -(2.0 * zFar * zNear) / (zFar - zNear);
2012 	m[15] = 0.0f;
2013 }
2014 /*
2015 =============
2016 R_SetupModelviewMatrix
2017 =============
2018 */
R_SetupModelviewMatrix(refdef_t * rd,mat4x4_t m)2019 void R_SetupModelviewMatrix( refdef_t *rd, mat4x4_t m )
2020 {
2021 	Vector4Set( &m[0], 0, 0, -1, 0 );
2022 	Vector4Set( &m[4], -1, 0, 0, 0 );
2023 	Vector4Set( &m[8], 0, 1, 0, 0 );
2024 	Vector4Set( &m[12], 0, 0, 0, 1 );
2025 
2026 	Matrix4_Rotate( m, -rd->viewangles[2], 1, 0, 0 );
2027 	Matrix4_Rotate( m, -rd->viewangles[0], 0, 1, 0 );
2028 	Matrix4_Rotate( m, -rd->viewangles[1], 0, 0, 1 );
2029 	Matrix4_Translate( m, -rd->vieworg[0], -rd->vieworg[1], -rd->vieworg[2] );
2030 }
2031 
R_TransformVectorToScreen(refdef_t * rd,vec3_t in,vec2_t out)2032 void R_TransformVectorToScreen( refdef_t *rd, vec3_t in, vec2_t out )
2033 {
2034    mat4x4_t p, m;
2035    vec4_t temp, temp2;
2036 
2037    if( !rd || !in || !out )
2038       return;
2039 
2040    temp[0] = in[0];
2041    temp[1] = in[1];
2042    temp[2] = in[2];
2043    temp[3] = 1.0f;
2044 
2045    R_SetupProjectionMatrix( rd, p );
2046    R_SetupModelviewMatrix( rd, m );
2047 
2048    Matrix4_Multiply_Vector( m, temp, temp2 );
2049    Matrix4_Multiply_Vector( p, temp2, temp );
2050 
2051    if( !temp[3] )
2052       return;
2053    out[0] = rd->x + (temp[0] / temp[3] + 1.0f) * rd->width * 0.5f;
2054    out[1] = rd->y + (temp[1] / temp[3] + 1.0f) * rd->height * 0.5f;
2055 }
2056