1 /*
2  * Copyright (C) 1997-2001 Id Software, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License as published by the Free
6  * Software Foundation; either version 2 of the License, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * 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 along with
16  * this program; if not, write to the Free Software Foundation, Inc., 59
17  * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  */
20 /* r_main.c */
21 #include "gl_local.h"
22 
23 #include "gl_refl.h"		/* MPO */
24 
25 /***************************************************************************** */
26 /* nVidia extensions */
27 /***************************************************************************** */
28 PFNGLCOMBINERPARAMETERFVNVPROC qglCombinerParameterfvNV;
29 PFNGLCOMBINERPARAMETERFNVPROC qglCombinerParameterfNV;
30 PFNGLCOMBINERPARAMETERIVNVPROC qglCombinerParameterivNV;
31 PFNGLCOMBINERPARAMETERINVPROC qglCombinerParameteriNV;
32 PFNGLCOMBINERINPUTNVPROC qglCombinerInputNV;
33 PFNGLCOMBINEROUTPUTNVPROC qglCombinerOutputNV;
34 PFNGLFINALCOMBINERINPUTNVPROC qglFinalCombinerInputNV;
35 PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC qglGetCombinerInputParameterfvNV;
36 PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC qglGetCombinerInputParameterivNV;
37 PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC qglGetCombinerOutputParameterfvNV;
38 PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC qglGetCombinerOutputParameterivNV;
39 PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC qglGetFinalCombinerInputParameterfvNV;
40 PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC qglGetFinalCombinerInputParameterivNV;
41 
42 /***************************************************************************** */
43 
44 int		g_numGlLights = 0;			/* dynamic lights for models .. */
45 int		numberOfWallLights = 0;			/* wall lights made into dynamic lights .. :) */
46 wallLight_t    *wallLightArray[MAX_WALL_LIGHTS];	/* array of wall lights .. 500 should be enough */
47 
48 void		R_Clear(void);
49 
50 #ifdef QMAX
51 #define random()	((rand () & 0x7fff) / ((float)0x7fff))
52 #define crandom()	(2.0 * (random() - 0.5))
53 #endif
54 
55 viddef_t	vid;
56 
57 refimport_t	ri;
58 
59 int		GL_TEXTURE0, GL_TEXTURE1, GL_TEXTURE2;	/* MH add extra texture unit here */
60 int		maxTextureUnits;			/* MH max number of texture units */
61 
62 model_t        *r_worldmodel;
63 
64 float		gldepthmin, gldepthmax;
65 
66 glconfig_t	gl_config;
67 glstate_t	gl_state;
68 
69 #ifdef QMAX
70 image_t        *r_particletextures[PARTICLE_TYPES];	/* list for particles */
71 image_t        *r_particlebeam;	/* used for beam ents */
72 
73 #else
74 image_t        *r_particletexture;	/* little dot for particles */
75 
76 #endif
77 image_t        *r_notexture;	/* use for bad textures */
78 image_t        *r_shelltexture;	/* c14 added shell texture */
79 image_t        *r_radarmap;	/* wall texture for radar texgen */
80 image_t        *r_around;
81 image_t        *r_caustictexture;	/* Water caustic texture */
82 image_t        *r_bholetexture;
83 
84 entity_t       *currententity;
85 model_t        *currentmodel;
86 
87 cplane_t	frustum[4];
88 
89 int		r_visframecount;/* bumped when going to a new PVS */
90 int		r_framecount;	/* used for dlight push checking */
91 
92 int		c_brush_polys, c_alias_polys;
93 
94 float		v_blend[4];	/* final blending color */
95 
96 void		GL_Strings_f(void);
97 
98 //
99 /* view origin */
100 //
101 vec3_t vup;
102 vec3_t		vpn;
103 vec3_t		vright;
104 vec3_t		r_origin;
105 
106 float		r_world_matrix[16];
107 float		r_base_world_matrix[16];
108 
109 //
110 /* screen size info */
111 //
112 refdef_t r_refdef;
113 
114 int		r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
115 
116 cvar_t         *skydistance;	/* DMP - skybox size change */
117 
118 #ifdef QMAX
119 cvar_t         *gl_partscale;
120 cvar_t         *gl_transrendersort;
121 cvar_t         *gl_particlelighting;
122 cvar_t         *gl_particledistance;
123 #else
124 cvar_t         *gl_particle_min_size;
125 cvar_t         *gl_particle_max_size;
126 cvar_t         *gl_particle_size;
127 cvar_t         *gl_particle_att_a;
128 cvar_t         *gl_particle_att_b;
129 cvar_t         *gl_particle_att_c;
130 cvar_t         *gl_particles;
131 #endif
132 
133 cvar_t         *r_norefresh;
134 cvar_t         *r_drawentities;
135 cvar_t         *r_drawworld;
136 cvar_t         *r_speeds;
137 cvar_t         *r_fullbright;
138 cvar_t         *r_novis;
139 cvar_t         *r_nocull;
140 cvar_t         *r_lerpmodels;
141 cvar_t         *r_model_lightlerp;
142 cvar_t         *r_model_alpha;
143 cvar_t         *r_lefthand;
144 
145 cvar_t         *gl_stainmaps;
146 
147 cvar_t         *r_lightlevel;	/* FIXME: This is a HACK to get the client's light level */
148 
149 cvar_t         *r_overbrightbits;
150 
151 cvar_t         *gl_nosubimage;
152 
153 cvar_t         *gl_vertex_arrays;
154 
155 cvar_t         *r_cellshading;
156 cvar_t         *r_cellshading_width;
157 
158 cvar_t         *font_color;
159 
160 cvar_t         *gl_ext_multitexture;
161 cvar_t         *gl_ext_pointparameters;
162 cvar_t         *gl_ext_compiled_vertex_array;
163 cvar_t         *gl_ext_palettedtexture;
164 
165 cvar_t         *gl_log;
166 cvar_t         *gl_bitdepth;
167 cvar_t         *gl_drawbuffer;
168 cvar_t         *gl_driver;
169 cvar_t         *gl_lightmap;
170 cvar_t         *gl_shadows;
171 cvar_t         *gl_shadows_alpha;
172 cvar_t         *gl_shellstencil;
173 cvar_t         *gl_mode;
174 cvar_t         *gl_dynamic;
175 cvar_t         *gl_monolightmap;
176 cvar_t         *gl_modulate;
177 cvar_t         *gl_nobind;
178 cvar_t         *gl_round_down;
179 cvar_t         *gl_picmip;
180 cvar_t         *gl_skymip;
181 cvar_t         *gl_showtris;
182 cvar_t         *gl_finish;
183 cvar_t         *gl_clear;
184 cvar_t         *gl_cull;
185 cvar_t         *gl_polyblend;
186 cvar_t         *gl_flashblend;
187 cvar_t         *gl_playermip;
188 cvar_t         *gl_saturatelighting;
189 cvar_t         *gl_texturemode;
190 cvar_t         *gl_texturealphamode;
191 cvar_t         *gl_texturesolidmode;
192 cvar_t         *gl_lockpvs;
193 
194 cvar_t         *gl_3dlabs_broken;
195 
196 cvar_t         *gl_ext_texture_compression;	/* Heffo - ARB Texture Compression */
197 cvar_t         *gl_ext_mtexcombine;
198 cvar_t         *gl_anisotropic;
199 cvar_t         *gl_anisotropic_avail;
200 cvar_t         *gl_ext_nv_multisample_filter_hint;	/* r1ch extensions */
201 cvar_t         *gl_nv_fog;
202 cvar_t         *gl_lightmap_texture_saturation;	/* jitsaturation */
203 cvar_t         *gl_lightmap_saturation;	/* jitsaturation */
204 cvar_t         *gl_screenshot_jpeg;	/* Heffo - JPEG Screenshots */
205 cvar_t         *gl_screenshot_jpeg_quality;	/* Heffo - JPEG Screenshots */
206 cvar_t         *gl_water_waves;	/* Water waves */
207 cvar_t         *gl_water_caustics;	/* Water Caustics */
208 
209 /* Knightmare- allow disabling the nVidia water warp */
210 cvar_t         *gl_water_pixel_shader_warp;
211 cvar_t         *gl_blooms;
212 cvar_t         *gl_motionblur;	/* motionblur */
213 cvar_t         *gl_motionblur_intensity;	/* motionblur */
214 
215 /* ========= Engine Fog ============== */
216 cvar_t         *gl_fogenable;	  /* Enable */
217 cvar_t         *gl_fogred;	  /* Red */
218 cvar_t         *gl_foggreen;	  /* Green */
219 cvar_t         *gl_fogblue;	  /* Blue */
220 cvar_t         *gl_fogstart;	  /* Start */
221 cvar_t         *gl_fogend;	  /* End */
222 cvar_t         *gl_fogdensity;	  /* Density */
223 cvar_t         *gl_fogunderwater; /* Under Water Fof */
224 /* ============ End =================== */
225 
226 cvar_t         *gl_shading;
227 cvar_t         *gl_decals;
228 cvar_t         *gl_decals_time;
229 cvar_t         *gl_glares;
230 cvar_t         *gl_glares_size;
231 cvar_t         *gl_glares_intens;
232 cvar_t         *gl_dlight_cutoff;
233 
234 cvar_t         *gl_minimap;
235 cvar_t         *gl_minimap_size;
236 cvar_t         *gl_minimap_zoom;
237 cvar_t         *gl_minimap_style;
238 cvar_t         *gl_minimap_x;
239 cvar_t         *gl_minimap_y;
240 
241 cvar_t         *gl_alpha_surfaces;
242 
243 cvar_t         *gl_flares;
244 cvar_t         *gl_flare_force_size;
245 cvar_t         *gl_flare_force_style;
246 cvar_t         *gl_flare_intensity;
247 cvar_t         *gl_flare_maxdist;
248 cvar_t         *gl_flare_scale;
249 
250 cvar_t         *gl_coloredlightmaps; /* NiceAss */
251 
252 cvar_t         *vid_fullscreen;
253 cvar_t         *vid_gamma;
254 cvar_t         *vid_ref;
255 cvar_t         *cl_hudscale;
256 cvar_t         *cl_big_maps;
257 cvar_t         *cl_3dcam;
258 cvar_t         *deathmatch;
259 
260 cvar_t         *gl_reflection_fragment_program;
261 cvar_t         *gl_reflection;			/* MPO	alpha transparency, 1.0 is full bright */
262 cvar_t         *gl_reflection_debug;		/* MPO	for debugging the reflection */
263 cvar_t         *gl_reflection_max;		/* MPO  max number of water reflections */
264 cvar_t         *gl_reflection_shader;		/* MPO	enable/disable fragment shaders */
265 cvar_t         *gl_reflection_shader_image;
266 cvar_t         *gl_reflection_water_surface;	/* MPO	enable/disable fragment shaders */
267 
268 /* MH - detail textures begin */
269 cvar_t         *gl_detailtextures;
270 /* MH - detail textures begin */
271 
272 /* mpo - needed for fragment shaders */
273 void            (APIENTRY * qglGenProgramsARB) (GLint n, GLuint * programs);
274 void            (APIENTRY * qglDeleteProgramsARB) (GLint n, const GLuint * programs);
275 void            (APIENTRY * qglBindProgramARB) (GLenum target, GLuint program);
276 void            (APIENTRY * qglProgramStringARB) (GLenum target, GLenum format, GLint len, const void *string);
277 void            (APIENTRY * qglProgramEnvParameter4fARB) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
278 void            (APIENTRY * qglProgramLocalParameter4fARB) (GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
279 
280 /* mpo - needed for fragment shaders */
281 
282 /*
283  * ================= GL_Stencil
284  *
285  * setting stencil buffer =================
286  */
287 extern qboolean	have_stencil;
288 void
GL_Stencil(qboolean enable)289 GL_Stencil(qboolean enable)
290 {
291 	if (!have_stencil)
292 		return;
293 
294 	if (enable) {
295 		qglEnable(GL_STENCIL_TEST);
296 		qglStencilFunc(GL_EQUAL, 1, 2);
297 		qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
298 	} else {
299 		qglDisable(GL_STENCIL_TEST);
300 	}
301 }
302 
303 /*
304  * ================= R_CullBox
305  *
306  * Returns true if the box is completely outside the frustom =================
307  */
308 qboolean
R_CullBox(vec3_t mins,vec3_t maxs)309 R_CullBox(vec3_t mins, vec3_t maxs)
310 {
311 	int		i;
312 
313 	if (r_nocull->value)
314 		return false;
315 
316 	for (i = 0; i < 4; i++)
317 		if (BoxOnPlaneSide(mins, maxs, &frustum[i]) == 2)
318 			return true;
319 	return false;
320 }
321 
322 void
R_RotateForEntity(entity_t * e)323 R_RotateForEntity(entity_t * e)
324 {
325 	qglTranslatef(e->origin[0], e->origin[1], e->origin[2]);
326 
327 	qglRotatef(e->angles[1], 0, 0, 1);
328 	qglRotatef(-e->angles[0], 0, 1, 0);
329 	qglRotatef(-e->angles[2], 1, 0, 0);
330 }
331 
332 /*
333  * =============================================================
334  *
335  * SPRITE MODELS
336  *
337  * =============================================================
338  */
339 
340 
341 /*
342  * ================= R_DrawSpriteModel
343  *
344  * =================
345  */
346 void
R_DrawSpriteModel(entity_t * e)347 R_DrawSpriteModel(entity_t * e)
348 {
349 	float		alpha = 1.0;
350 	vec3_t		point, up, right;
351 	dsprframe_t    *frame;
352 	dsprite_t      *psprite;
353 
354 	/* don't even bother culling, because it's just a single */
355 	/* polygon without a surface cache */
356 
357 	psprite = (dsprite_t *) currentmodel->extradata;
358 
359 	e->frame %= psprite->numframes;
360 
361 	frame = &psprite->frames[e->frame];
362 
363 	if (!frame)
364 		return;
365 
366 	/* normal sprite */
367 	VectorCopy(vup, up);
368 	VectorCopy(vright, right);
369 
370 
371 	if (e->flags & RF_TRANSLUCENT)
372 		alpha = e->alpha;
373 
374 	if (!currentmodel->skins[e->frame])
375 		return;
376 
377 	GL_Bind(currentmodel->skins[e->frame]->texnum);
378 
379 	if ((currententity->flags & RF_TRANS_ADDITIVE) && (alpha != 1.0)) {
380 		GLSTATE_ENABLE_BLEND
381 		    GL_TexEnv(GL_MODULATE);
382 
383 		GLSTATE_DISABLE_ALPHATEST
384 		    GL_BlendFunction(GL_SRC_ALPHA, GL_ONE);
385 
386 		qglColor4ub(255, 255, 255, alpha * 254);
387 	} else {
388 		if (alpha != 1.0)
389 			GLSTATE_ENABLE_BLEND
390 
391 			    GL_TexEnv(GL_MODULATE);
392 
393 		if (alpha == 1.0) {
394 			GLSTATE_ENABLE_ALPHATEST
395 			    else
396 			GLSTATE_DISABLE_ALPHATEST
397 		}
398 		qglColor4f(1, 1, 1, alpha);
399 	}
400 
401 	qglBegin(GL_QUADS);
402 
403 	qglTexCoord2f(0, 1);
404 	VectorMA(e->origin, -frame->origin_y, up, point);
405 	VectorMA(point, -frame->origin_x, right, point);
406 	qglVertex3fv(point);
407 
408 	qglTexCoord2f(0, 0);
409 	VectorMA(e->origin, frame->height - frame->origin_y, up, point);
410 	VectorMA(point, -frame->origin_x, right, point);
411 	qglVertex3fv(point);
412 
413 	qglTexCoord2f(1, 0);
414 	VectorMA(e->origin, frame->height - frame->origin_y, up, point);
415 	VectorMA(point, frame->width - frame->origin_x, right, point);
416 	qglVertex3fv(point);
417 
418 	qglTexCoord2f(1, 1);
419 	VectorMA(e->origin, -frame->origin_y, up, point);
420 	VectorMA(point, frame->width - frame->origin_x, right, point);
421 	qglVertex3fv(point);
422 
423 	qglEnd();
424 
425 
426 	GL_BlendFunction(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
427 	GLSTATE_DISABLE_ALPHATEST
428 
429 	    GL_TexEnv(GL_REPLACE);
430 
431 	if (alpha != 1.0)
432 		GLSTATE_DISABLE_BLEND
433 
434 		    qglColor4f(1, 1, 1, 1);
435 }
436 
437 /*
438  * ===========================================================================
439  * =======
440  */
441 
442 /*
443  * ============= R_DrawNullModel =============
444  */
445 void
R_DrawNullModel(void)446 R_DrawNullModel(void)
447 {
448 	vec3_t		shadelight;
449 	int		i;
450 
451 	if (currententity->flags & RF_FULLBRIGHT)
452 		shadelight[0] = shadelight[1] = shadelight[2] = 1.0;
453 	else
454 		R_LightPoint(currententity->origin, shadelight);
455 
456 	qglPushMatrix();
457 	R_RotateForEntity(currententity);
458 
459 	qglDisable(GL_TEXTURE_2D);
460 	qglColor3fv(shadelight);
461 
462 	qglBegin(GL_TRIANGLE_FAN);
463 	qglVertex3f(0, 0, -16);
464 	for (i = 0; i <= 4; i++)
465 		qglVertex3f(16 * cos(i * M_PI / 2), 16 * sin(i * M_PI / 2), 0);
466 	qglEnd();
467 
468 	qglBegin(GL_TRIANGLE_FAN);
469 	qglVertex3f(0, 0, 16);
470 	for (i = 4; i >= 0; i--)
471 		qglVertex3f(16 * cos(i * M_PI / 2), 16 * sin(i * M_PI / 2), 0);
472 	qglEnd();
473 
474 	qglColor3f(1, 1, 1);
475 	qglPopMatrix();
476 	qglEnable(GL_TEXTURE_2D);
477 }
478 
479 /*
480  * ============= R_DrawEntitiesOnList =============
481  */
482 #ifdef QMAX
483 typedef struct sortedent_s {
484 	entity_t       *ent;
485 	vec_t		len;
486 	qboolean	inwater;
487 } sortedent_t;
488 
489 sortedent_t	theents[MAX_ENTITIES];
490 
491 int
transCompare(const void * arg1,const void * arg2)492 transCompare(const void *arg1, const void *arg2)
493 {
494 	const sortedent_t *a1, *a2;
495 
496 	a1 = (sortedent_t *) arg1;
497 	a2 = (sortedent_t *) arg2;
498 	return (a2->len - a1->len);
499 }
500 
501 sortedent_t
NewSortEnt(entity_t * ent,qboolean waterstart)502 NewSortEnt(entity_t * ent, qboolean waterstart)
503 {
504 	vec3_t		result;
505 	sortedent_t	s_ent;
506 
507 	s_ent.ent = ent;
508 
509 	VectorSubtract(ent->origin, r_origin, result);
510 	s_ent.len = (result[0] * result[0]) + (result[1] * result[1]) + (result[2] * result[2]);
511 
512 	s_ent.inwater = (Mod_PointInLeaf(ent->origin, r_worldmodel)->contents & MASK_WATER);
513 	if (ent->flags & RF_WEAPONMODEL || ent->flags & RF_VIEWERMODEL)
514 		s_ent.inwater = waterstart;
515 
516 	return s_ent;
517 }
518 void
R_SortEntitiesOnList(qboolean inwater)519 R_SortEntitiesOnList(qboolean inwater)
520 {
521 	int		i;
522 
523 	for (i = 0; i < r_refdef.num_entities; i++)
524 		theents[i] = NewSortEnt(&r_refdef.entities[i], inwater);
525 
526 	qsort((void *)theents, r_refdef.num_entities, sizeof(sortedent_t), transCompare);
527 }
528 
529 void
R_DrawEntitiesOnList(qboolean inWater,qboolean solids)530 R_DrawEntitiesOnList(qboolean inWater, qboolean solids)
531 {
532 	vec3_t		origin;
533 	int		i, j;
534 
535 	if (!r_drawentities->value)
536 		return;
537 
538 	/* draw non-transparent first */
539 	if (solids)
540 		for (i = 0; i < r_refdef.num_entities; i++) {
541 			currententity = &r_refdef.entities[i];
542 
543 			if (currententity->flags & RF_TRANSLUCENT || currententity->flags & RF_VIEWERMODEL)
544 				continue;
545 
546 			for (j = 0; j < 3; j++)
547 				origin[j] = currententity->origin[j];
548 
549 			if (currententity->flags & RF_BEAM) {
550 				R_DrawBeam(currententity);
551 			} else {
552 				currentmodel = currententity->model;
553 				if (!currentmodel) {
554 					R_DrawNullModel();
555 					continue;
556 				}
557 				switch (currentmodel->type) {
558 				case mod_alias:
559 					R_DrawAliasModel(currententity);
560 					break;
561 					/* Harven MD3 ++ */
562 				case mod_alias_md3:
563 					R_DrawAliasMD3Model(currententity);
564 					break;
565 					/* Harven MD3 -- */
566 				case mod_brush:
567 					R_DrawBrushModel(currententity);
568 					break;
569 				case mod_sprite:
570 					R_DrawSpriteModel(currententity);
571 					break;
572 				default:
573 					ri.Sys_Error(ERR_DROP, "Bad modeltype");
574 					break;
575 				}
576 			}
577 		}
578 
579 	qglDepthMask(0);
580 	for (i = 0; i < r_refdef.num_entities; i++) {
581 		if (gl_transrendersort->value && !(r_refdef.rdflags & RDF_NOWORLDMODEL)) {
582 			currententity = theents[i].ent;
583 
584 			if (!(currententity->flags & RF_TRANSLUCENT || currententity->flags & RF_VIEWERMODEL) ||
585 			    (inWater && !theents[i].inwater) || (!inWater && theents[i].inwater))
586 				continue;	/* solid */
587 		} else if (inWater) {
588 			currententity = &r_refdef.entities[i];
589 
590 			if (!(currententity->flags & RF_TRANSLUCENT || currententity->flags & RF_VIEWERMODEL))
591 				continue;	/* solid */
592 		} else
593 			continue;
594 
595 		if (currententity->flags & RF_BEAM) {
596 			R_DrawBeam(currententity);
597 		} else {
598 			currentmodel = currententity->model;
599 
600 			if (!currentmodel) {
601 				R_DrawNullModel();
602 				continue;
603 			}
604 			switch (currentmodel->type) {
605 			case mod_alias:
606 				R_DrawAliasModel(currententity);
607 				break;
608 				/* Harven MD3 ++ */
609 			case mod_alias_md3:
610 				R_DrawAliasMD3Model(currententity);
611 				break;
612 				/* Harven MD3 -- */
613 			case mod_brush:
614 				R_DrawBrushModel(currententity);
615 				break;
616 			case mod_sprite:
617 				R_DrawSpriteModel(currententity);
618 				break;
619 			default:
620 				ri.Sys_Error(ERR_DROP, "Bad modeltype");
621 				break;
622 			}
623 		}
624 	}
625 	qglDepthMask(1);	/* back to writing */
626 
627 }
628 #else
629 void
R_DrawEntitiesOnList(void)630 R_DrawEntitiesOnList(void)
631 {
632 	int		i;
633 
634 	if (!r_drawentities->value)
635 		return;
636 
637 	/* draw non-transparent first */
638 	for (i = 0; i < r_refdef.num_entities; i++) {
639 		currententity = &r_refdef.entities[i];
640 		if (currententity->flags & RF_TRANSLUCENT)
641 			continue;	/* solid */
642 
643 		if (currententity->flags & RF_BEAM) {
644 			R_DrawBeam(currententity);
645 		} else {
646 			currentmodel = currententity->model;
647 			if (!currentmodel) {
648 				R_DrawNullModel();
649 				continue;
650 			}
651 			switch (currentmodel->type) {
652 			case mod_alias:
653 				R_DrawAliasModel(currententity);
654 				break;
655 				/* Harven MD3 ++ */
656 			case mod_alias_md3:
657 				R_DrawAliasMD3Model(currententity);
658 				break;
659 				/* Harven MD3 -- */
660 			case mod_brush:
661 				R_DrawBrushModel(currententity);
662 				break;
663 			case mod_sprite:
664 				R_DrawSpriteModel(currententity);
665 				break;
666 			default:
667 				ri.Sys_Error(ERR_DROP, "Bad modeltype");
668 				break;
669 			}
670 		}
671 	}
672 
673 	/* draw transparent entities */
674 	/* we could sort these if it ever becomes a problem... */
675 	qglDepthMask(0);	/* no z writes */
676 	for (i = 0; i < r_refdef.num_entities; i++) {
677 		currententity = &r_refdef.entities[i];
678 		if (!(currententity->flags & RF_TRANSLUCENT))
679 			continue;	/* solid */
680 
681 		if (currententity->flags & RF_BEAM) {
682 			R_DrawBeam(currententity);
683 		} else {
684 			currentmodel = currententity->model;
685 
686 			if (!currentmodel) {
687 				R_DrawNullModel();
688 				continue;
689 			}
690 			switch (currentmodel->type) {
691 			case mod_alias:
692 				R_DrawAliasModel(currententity);
693 				break;
694 				/* Harven MD3 ++ */
695 			case mod_alias_md3:
696 				R_DrawAliasMD3Model(currententity);
697 				break;
698 				/* Harven MD3 -- */
699 			case mod_brush:
700 				R_DrawBrushModel(currententity);
701 				break;
702 			case mod_sprite:
703 				R_DrawSpriteModel(currententity);
704 				break;
705 			default:
706 				ri.Sys_Error(ERR_DROP, "Bad modeltype");
707 				break;
708 			}
709 		}
710 	}
711 	qglDepthMask(1);	/* back to writing */
712 
713 }
714 #endif
715 
716 /*
717  * * GL_DrawParticles *
718  *
719  */
720 
721 #ifdef QMAX
722 typedef struct sortedpart_s {
723 	particle_t     *p;
724 	vec_t		len;
725 	qboolean	inwater;
726 } sortedpart_t;
727 
728 sortedpart_t	theparts[MAX_PARTICLES];
729 
730 sortedpart_t
NewSortPart(particle_t * p)731 NewSortPart(particle_t * p)
732 {
733 	vec3_t		result;
734 	sortedpart_t	s_part;
735 
736 	s_part.p = p;
737 	VectorSubtract(p->origin, r_origin, result);
738 	s_part.len = (result[0] * result[0]) + (result[1] * result[1]) + (result[2] * result[2]);
739 	s_part.inwater = (Mod_PointInLeaf(p->origin, r_worldmodel)->contents & MASK_WATER);
740 
741 	return s_part;
742 }
743 
744 void
R_SortParticlesOnList(int num_particles,const particle_t particles[])745 R_SortParticlesOnList(int num_particles, const particle_t particles[])
746 {
747 	int		i;
748 
749 	for (i = 0; i < num_particles; i++)
750 		theparts[i] = NewSortPart((particle_t *) & particles[i]);
751 
752 	qsort((void *)theparts, num_particles, sizeof(sortedpart_t), transCompare);
753 }
754 
755 int
texParticle(int type)756 texParticle(int type)
757 {
758 	image_t        *part_img;
759 
760 	part_img = r_particletextures[type];
761 
762 	return part_img->texnum;
763 }
764 
765 void
vectoanglerolled(vec3_t value1,float angleyaw,vec3_t angles)766 vectoanglerolled(vec3_t value1, float angleyaw, vec3_t angles)
767 {
768 	float		forward , yaw, pitch;
769 
770 	yaw = (int)(atan2(value1[1], value1[0]) * 180 / M_PI);
771 	forward = sqrt(value1[0] * value1[0] + value1[1] * value1[1]);
772 	pitch = (int)(atan2(value1[2], forward) * 180 / M_PI);
773 
774 	if (pitch < 0)
775 		pitch += 360;
776 
777 	angles[PITCH] = -pitch;
778 	angles[YAW] = yaw;
779 	angles[ROLL] = -angleyaw;
780 }
781 
782 float
AngleFind(float input)783 AngleFind(float input)
784 {
785 	return 180.0 / input;
786 }
787 void
GL_DrawParticles(int num_particles,qboolean inWater)788 GL_DrawParticles(int num_particles, qboolean inWater)
789 {
790 	int		i;
791 	float		size, lighting = gl_particlelighting->value;
792 	int		oldrender = 0, rendertype = 0;
793 
794 	byte		alpha;
795 
796 	vec3_t		up = {vup[0] * 0.75, vup[1] * 0.75, vup[2] * 0.75};
797 	vec3_t		right = {vright[0] * 0.75, vright[1] * 0.75, vright[2] * 0.75};
798 	vec3_t		coord   [4], shadelight;
799 
800 	particle_t     *p;
801 
802 	VectorAdd(up, right, coord[0]);
803 	VectorSubtract(right, up, coord[1]);
804 	VectorNegate(coord[0], coord[2]);
805 	VectorNegate(coord[1], coord[3]);
806 
807 	qglEnable(GL_TEXTURE_2D);
808 	GL_TexEnv(GL_MODULATE);
809 	qglDepthMask(false);
810 	qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
811 	qglEnable(GL_BLEND);
812 	qglShadeModel(GL_SMOOTH);
813 
814 
815 
816 	for (i = 0; i < num_particles; i++) {
817 		if (!(r_refdef.rdflags & RDF_NOWORLDMODEL)) {
818 			if (gl_transrendersort->value == 2) {	/* sorted with ents etc */
819 				p = theparts[i].p;
820 
821 				if ((inWater && !theparts[i].inwater) || (!inWater && theparts[i].inwater))
822 					continue;
823 
824 				if (gl_particledistance->value > 0 && theparts[i].len > (100.0 * gl_particledistance->value))
825 					continue;
826 			} else if (gl_transrendersort->value) {	/* sorted by itself */
827 				p = theparts[i].p;
828 
829 				if ((inWater && !theparts[i].inwater) || (!inWater && theparts[i].inwater))
830 					continue;
831 
832 				if (gl_particledistance->value > 0 && theparts[i].len > (100.0 * gl_particledistance->value))
833 					continue;
834 			} else if (inWater)
835 				p = &r_refdef.particles[i];
836 			else
837 				continue;
838 		} else if (inWater)
839 			p = &r_refdef.particles[i];
840 		else
841 			continue;
842 
843 		oldrender = rendertype;
844 		rendertype = (p->flags & PART_TRANS) ? 1 : 0;
845 		if (rendertype != oldrender) {
846 			if (rendertype == 1)
847 				qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
848 			else
849 				qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
850 		}
851 		if (!(p->flags & PART_SPARK))
852 			GL_Bind(texParticle(p->image));
853 
854 		alpha = p->alpha * 254.0;
855 		size = (p->size > 0.1) ? p->size : 0.1;
856 
857 		if (p->flags & PART_SHADED) {
858 			int		j;
859 			float		lightest = 0;
860 
861 			R_LightPoint(p->origin, shadelight);
862 
863 			shadelight[0] = (lighting * shadelight[0] + (1 - lighting)) * p->red;
864 			shadelight[1] = (lighting * shadelight[1] + (1 - lighting)) * p->green;
865 			shadelight[2] = (lighting * shadelight[2] + (1 - lighting)) * p->blue;
866 
867 			/* this cleans up the lighting */
868 			{
869 				for (j = 0; j < 3; j++)
870 					if (shadelight[j] > lightest)
871 						lightest = shadelight[j];
872 				if (lightest > 255)
873 					for (j = 0; j < 3; j++)
874 						shadelight[j] *= 255 / lightest;
875 			}
876 
877 			qglColor4ub(shadelight[0], shadelight[1], shadelight[2], alpha);
878 		} else
879 			qglColor4ub(p->red, p->green, p->blue, alpha);
880 
881 		/*
882 		 * id move this somewhere less dirty, but im too damn lazy -
883 		 * psychospaz
884 		 */
885 #define DEPTHHACK_RANGE_SHORT	0.9985f
886 #define DEPTHHACK_RANGE_MID	0.975f
887 #define DEPTHHACK_RANGE_LONG	0.95f
888 
889 		if (p->flags & PART_DEPTHHACK_SHORT)	/* nice little
890 							 * poly-peeking -
891 							 * psychospaz */
892 			qglDepthRange(gldepthmin, gldepthmin + DEPTHHACK_RANGE_SHORT * (gldepthmax - gldepthmin));
893 		if (p->flags & PART_DEPTHHACK_MID)
894 			qglDepthRange(gldepthmin, gldepthmin + DEPTHHACK_RANGE_MID * (gldepthmax - gldepthmin));
895 		if (p->flags & PART_DEPTHHACK_LONG)
896 			qglDepthRange(gldepthmin, gldepthmin + DEPTHHACK_RANGE_LONG * (gldepthmax - gldepthmin));
897 
898 		if (p->flags & PART_SPARK) {	/* QMB style particles */
899 			int		angle;
900 			vec3_t		v;
901 
902 			qglDisable(GL_TEXTURE_2D);
903 
904 			qglPushMatrix();
905 			{
906 				qglBegin(GL_TRIANGLE_FAN);
907 				{
908 #define MAGICNUMBER 32
909 					float		magicnumber = AngleFind(MAGICNUMBER);
910 
911 
912 					qglVertex3fv(p->origin);
913 					qglColor4ub(0, 0, 0, 0);
914 
915 					for (angle = magicnumber * fabs(1 - MAGICNUMBER); angle >= 0; angle -= magicnumber) {
916 						v[0] = p->origin[0] - p->angle[0] * size + (right[0] * cos(angle) + up[0] * sin(angle));
917 						v[1] = p->origin[1] - p->angle[1] * size + (right[1] * cos(angle) + up[1] * sin(angle));
918 						v[2] = p->origin[2] - p->angle[2] * size + (right[2] * cos(angle) + up[2] * sin(angle));
919 						qglVertex3fv(v);
920 					}
921 				}
922 				qglEnd();
923 			}
924 			qglPopMatrix();
925 
926 			qglEnable(GL_TEXTURE_2D);
927 		} else if (p->flags & PART_BEAM) {	/* given start and end
928 							 * positions, will have
929 			 				 * fun here :)
930 							 */
931 			/* p->angle = start */
932 			/* p->origin= end */
933 			vec3_t		angl_coord[4];
934 			vec3_t		ang_up, ang_right, vdelta;
935 
936 			VectorSubtract(p->origin, p->angle, vdelta);
937 			VectorNormalize(vdelta);
938 
939 			VectorCopy(vdelta, ang_up);
940 			VectorSubtract(r_refdef.vieworg, p->angle, vdelta);
941 			CrossProduct(ang_up, vdelta, ang_right);
942 			if (!VectorCompare(ang_right, vec3_origin))
943 				VectorNormalize(ang_right);
944 
945 			VectorScale(ang_right, size, ang_right);
946 
947 			VectorAdd(p->origin, ang_right, angl_coord[0]);
948 			VectorAdd(p->angle, ang_right, angl_coord[1]);
949 			VectorSubtract(p->angle, ang_right, angl_coord[2]);
950 			VectorSubtract(p->origin, ang_right, angl_coord[3]);
951 
952 			qglPushMatrix();
953 			{
954 				qglBegin(GL_QUADS);
955 				{
956 					qglTexCoord2f(0, 1);
957 					qglVertex3fv(angl_coord[0]);
958 					qglTexCoord2f(0, 0);
959 					qglVertex3fv(angl_coord[1]);
960 					qglTexCoord2f(1, 0);
961 					qglVertex3fv(angl_coord[2]);
962 					qglTexCoord2f(1, 1);
963 					qglVertex3fv(angl_coord[3]);
964 				}
965 				qglEnd();
966 
967 			}
968 			qglPopMatrix();
969 		} else if (p->flags & PART_LIGHTNING) {	/* given start and end
970 							 * positions, will have
971 			 				 * fun here :)
972 							 */
973 			/* p->angle = start */
974 			/* p->origin= end */
975 			float		tlen, halflen, len, dec = size, warpfactor,
976 					warpadd, oldwarpadd, warpsize, time, i = 0,
977 					factor;
978 			vec3_t		move, lastvec, thisvec, tempvec;
979 			vec3_t		angl_coord[4];
980 			vec3_t		ang_up, ang_right, vdelta;
981 
982 			oldwarpadd = 0;
983 			warpsize = dec * 0.01;
984 			warpfactor = M_PI * 1.0;
985 			time = -r_refdef.time * 10.0;
986 
987 			VectorSubtract(p->origin, p->angle, move);
988 			len = VectorNormalize(move);
989 
990 			VectorCopy(move, ang_up);
991 			VectorSubtract(r_refdef.vieworg, p->angle, vdelta);
992 			CrossProduct(ang_up, vdelta, ang_right);
993 			if (!VectorCompare(ang_right, vec3_origin))
994 				VectorNormalize(ang_right);
995 
996 			VectorScale(ang_right, dec, ang_right);
997 			VectorScale(ang_up, dec, ang_up);
998 
999 			VectorScale(move, dec, move);
1000 			VectorCopy(p->angle, lastvec);
1001 			VectorAdd(lastvec, move, thisvec);
1002 			VectorCopy(thisvec, tempvec);
1003 
1004 			/* lightning starts at point and then flares out */
1005 #define LIGHTNINGWARPFUNCTION 0.25*sin(time+i+warpfactor)*(dec/len)
1006 
1007 			warpadd = LIGHTNINGWARPFUNCTION;
1008 			factor = 1;
1009 			halflen = len / 2.0;
1010 
1011 
1012 			thisvec[0] = (thisvec[0] * 2 + crandom() * 5) / 2;
1013 			thisvec[1] = (thisvec[1] * 2 + crandom() * 5) / 2;
1014 			thisvec[2] = (thisvec[2] * 2 + crandom() * 5) / 2;
1015 
1016 			/*
1017 			 * thisvec[0]= (thisvec[0]*2 + 5)/2; thisvec[1]=
1018 			 * (thisvec[1]*2 + 5)/2; thisvec[2]= (thisvec[2]*2 +
1019 			 * 5)/2;
1020 			 */
1021 			while (len > dec) {
1022 				i += warpsize;
1023 
1024 				VectorAdd(thisvec, ang_right, angl_coord[0]);
1025 				VectorAdd(lastvec, ang_right, angl_coord[1]);
1026 				VectorSubtract(lastvec, ang_right, angl_coord[2]);
1027 				VectorSubtract(thisvec, ang_right, angl_coord[3]);
1028 
1029 				qglPushMatrix();
1030 				{
1031 					qglBegin(GL_QUADS);
1032 					{
1033 						qglTexCoord2f(0 + warpadd, 1);
1034 						qglVertex3fv(angl_coord[0]);
1035 						qglTexCoord2f(0 + oldwarpadd, 0);
1036 						qglVertex3fv(angl_coord[1]);
1037 						qglTexCoord2f(1 + oldwarpadd, 0);
1038 						qglVertex3fv(angl_coord[2]);
1039 						qglTexCoord2f(1 + warpadd, 1);
1040 						qglVertex3fv(angl_coord[3]);
1041 					}
1042 					qglEnd();
1043 
1044 				}
1045 				qglPopMatrix();
1046 
1047 				tlen = (len < halflen) ? fabs(len - halflen) : fabs(len - halflen);
1048 				factor = tlen / (size * size);
1049 
1050 				if (factor > 4)
1051 					factor = 4;
1052 				else if (factor < 1)
1053 					factor = 1;
1054 
1055 				oldwarpadd = warpadd;
1056 				warpadd = LIGHTNINGWARPFUNCTION;
1057 
1058 				len -= dec;
1059 				VectorCopy(thisvec, lastvec);
1060 				VectorAdd(tempvec, move, tempvec);
1061 				VectorAdd(lastvec, move, thisvec);
1062 
1063 
1064 				/*
1065 				 * thisvec[0]= ((thisvec[0] +
1066 				 * (crandom()*size)) +
1067 				 * tempvec[0]*factor)/(factor+1); thisvec[1]=
1068 				 * ((thisvec[1] + (crandom()*size)) +
1069 				 * tempvec[1]*factor)/(factor+1); thisvec[2]=
1070 				 * ((thisvec[2] + (crandom()*size)) +
1071 				 * tempvec[2]*factor)/(factor+1);
1072 				 */
1073 				thisvec[0] = ((thisvec[0] + (size)) + tempvec[0] * factor) / (factor + 1);
1074 				thisvec[1] = ((thisvec[1] + (size)) + tempvec[1] * factor) / (factor + 1);
1075 				thisvec[2] = ((thisvec[2] + (size)) + tempvec[2] * factor) / (factor + 1);
1076 
1077 			}
1078 
1079 			i += warpsize;
1080 
1081 			/* one more time */
1082 			if (len > 0) {
1083 				VectorAdd(p->origin, ang_right, angl_coord[0]);
1084 				VectorAdd(lastvec, ang_right, angl_coord[1]);
1085 				VectorSubtract(lastvec, ang_right, angl_coord[2]);
1086 				VectorSubtract(p->origin, ang_right, angl_coord[3]);
1087 
1088 				qglPushMatrix();
1089 				{
1090 					qglBegin(GL_QUADS);
1091 					{
1092 						qglTexCoord2f(0 + warpadd, 1);
1093 						qglVertex3fv(angl_coord[0]);
1094 						qglTexCoord2f(0 + oldwarpadd, 0);
1095 						qglVertex3fv(angl_coord[1]);
1096 						qglTexCoord2f(1 + oldwarpadd, 0);
1097 						qglVertex3fv(angl_coord[2]);
1098 						qglTexCoord2f(1 + warpadd, 1);
1099 						qglVertex3fv(angl_coord[3]);
1100 					}
1101 					qglEnd();
1102 
1103 				}
1104 				qglPopMatrix();
1105 			}
1106 		} else if (p->flags & PART_DIRECTION) {	/* streched out in
1107 							 * direction...tracers
1108 							 * etc... */
1109 
1110 			/*
1111 			 * never dissapears because of angle like other
1112 			 * engines :D
1113 			 */
1114 			float		len, dot;
1115 			vec3_t		angl_coord[4];
1116 			vec3_t		ang_up, ang_right, vdelta;
1117 
1118 			VectorCopy(p->angle, ang_up);
1119 			len = VectorNormalize(ang_up);
1120 			VectorSubtract(r_refdef.vieworg, p->origin, vdelta);
1121 			CrossProduct(ang_up, vdelta, ang_right);
1122 			if (!VectorCompare(ang_right, vec3_origin))
1123 				VectorNormalize(ang_right);
1124 
1125 
1126 			/*
1127 			 * the more you look into ang_up, the more it looks
1128 			 * like normal sprite (recalc ang_up)
1129 			 */
1130 			if (false) {
1131 				vec3_t		temp_up [3], tempfor;
1132 
1133 				AngleVectors(r_refdef.viewangles, tempfor, NULL, NULL);
1134 				dot = 1 - fabs(DotProduct(ang_up, tempfor));
1135 
1136 				/*
1137 				 * if (DotProduct (vdelta, ang_up)<0 ||
1138 				 * DotProduct (vdelta, ang_right)<0)
1139 				 */
1140 				/* VectorScale(tempfor, -1.0, tempfor); */
1141 
1142 				VectorSubtract(p->origin, r_refdef.vieworg, vdelta);
1143 				Com_Printf("up:%f right:%f\n", DotProduct(vdelta, ang_up), DotProduct(vdelta, ang_right));
1144 
1145 				ProjectPointOnPlane(temp_up[2], ang_up, tempfor);
1146 				VectorNormalize(temp_up[2]);
1147 
1148 				VectorScale(ang_up, dot, temp_up[0]);
1149 				VectorScale(temp_up[2], 1 - dot, temp_up[1]);
1150 				VectorAdd(temp_up[1], temp_up[0], ang_up);
1151 
1152 				len = 1 + dot * (len - 1);
1153 
1154 				/* dont mess with stuff harder than needed */
1155 				if (dot < 0.015) {
1156 					len = 1;
1157 					VectorCopy(up, ang_up);
1158 					VectorCopy(right, ang_right);
1159 				}
1160 			}
1161 			VectorScale(ang_right, 0.75, ang_right);
1162 			VectorScale(ang_up, 0.75 * len, ang_up);
1163 
1164 			VectorAdd(ang_up, ang_right, angl_coord[0]);
1165 			VectorSubtract(ang_right, ang_up, angl_coord[1]);
1166 			VectorNegate(angl_coord[0], angl_coord[2]);
1167 			VectorNegate(angl_coord[1], angl_coord[3]);
1168 
1169 			qglPushMatrix();
1170 			{
1171 				qglTranslatef(p->origin[0], p->origin[1], p->origin[2]);
1172 				qglScalef(size, size, size);
1173 
1174 				qglBegin(GL_QUADS);
1175 				{
1176 					qglTexCoord2f(0, 1);
1177 					qglVertex3fv(angl_coord[0]);
1178 					qglTexCoord2f(0, 0);
1179 					qglVertex3fv(angl_coord[1]);
1180 					qglTexCoord2f(1, 0);
1181 					qglVertex3fv(angl_coord[2]);
1182 					qglTexCoord2f(1, 1);
1183 					qglVertex3fv(angl_coord[3]);
1184 				}
1185 				qglEnd();
1186 			}
1187 			qglPopMatrix();
1188 		} else if (p->flags & PART_ANGLED) {	/* facing direction...
1189 							 * (decal wannabes) */
1190 			vec3_t		angl_coord[4];
1191 			vec3_t		ang_up, ang_right, ang_forward;
1192 
1193 			AngleVectors(p->angle, ang_forward, ang_right, ang_up);
1194 
1195 			VectorScale(ang_right, 0.75, ang_right);
1196 			VectorScale(ang_up, 0.75, ang_up);
1197 
1198 			VectorAdd(ang_up, ang_right, angl_coord[0]);
1199 			VectorSubtract(ang_right, ang_up, angl_coord[1]);
1200 			VectorNegate(angl_coord[0], angl_coord[2]);
1201 			VectorNegate(angl_coord[1], angl_coord[3]);
1202 
1203 			if (p->flags & PART_DEPTHHACK) {
1204 				qglDisable(GL_CULL_FACE);
1205 				qglPushMatrix();
1206 				{
1207 					if (p->flags & (PART_DEPTHHACK_SHORT | PART_DEPTHHACK_MID | PART_DEPTHHACK_LONG)) {
1208 						VectorMA(p->origin, size, angl_coord[0], angl_coord[0]);
1209 						VectorMA(p->origin, size, angl_coord[1], angl_coord[1]);
1210 						VectorMA(p->origin, size, angl_coord[2], angl_coord[2]);
1211 						VectorMA(p->origin, size, angl_coord[3], angl_coord[3]);
1212 					} else {
1213 						qglTranslatef(p->origin[0], p->origin[1], p->origin[2]);
1214 						qglScalef(size, size, size);
1215 					}
1216 
1217 					qglBegin(GL_QUADS);
1218 					{
1219 						qglTexCoord2f(0, 1);
1220 						qglVertex3fv(angl_coord[0]);
1221 						qglTexCoord2f(0, 0);
1222 						qglVertex3fv(angl_coord[1]);
1223 						qglTexCoord2f(1, 0);
1224 						qglVertex3fv(angl_coord[2]);
1225 						qglTexCoord2f(1, 1);
1226 						qglVertex3fv(angl_coord[3]);
1227 					}
1228 					qglEnd();
1229 				}
1230 				qglPopMatrix();
1231 				qglEnable(GL_CULL_FACE);
1232 			}
1233 		} else {	/* normal sprites */
1234 			qglPushMatrix();
1235 			{
1236 				if (!(p->flags & PART_DEPTHHACK)) {
1237 					qglTranslatef(p->origin[0], p->origin[1], p->origin[2]);
1238 					qglScalef(size, size, size);
1239 				}
1240 				qglBegin(GL_QUADS);
1241 				{
1242 					if (p->angle[2]) {	/* if we have roll, we
1243 								 * do calcs */
1244 						vec3_t		angl_coord[4];
1245 						vec3_t		ang_up, ang_right,
1246 								ang_forward;
1247 
1248 						VectorSubtract(p->origin, r_refdef.vieworg, angl_coord[0]);
1249 
1250 						vectoanglerolled(angl_coord[0], p->angle[2], angl_coord[1]);
1251 						AngleVectors(angl_coord[1], ang_forward, ang_right, ang_up);
1252 
1253 						VectorScale(ang_forward, 0.75, ang_forward);
1254 						VectorScale(ang_right, 0.75, ang_right);
1255 						VectorScale(ang_up, 0.75, ang_up);
1256 
1257 						VectorAdd(ang_up, ang_right, angl_coord[0]);
1258 						VectorSubtract(ang_right, ang_up, angl_coord[1]);
1259 						VectorNegate(angl_coord[0], angl_coord[2]);
1260 						VectorNegate(angl_coord[1], angl_coord[3]);
1261 
1262 						if (p->flags & PART_DEPTHHACK) {
1263 							VectorMA(p->origin, size, angl_coord[0], angl_coord[0]);
1264 							VectorMA(p->origin, size, angl_coord[1], angl_coord[1]);
1265 							VectorMA(p->origin, size, angl_coord[2], angl_coord[2]);
1266 							VectorMA(p->origin, size, angl_coord[3], angl_coord[3]);
1267 						}
1268 						qglTexCoord2f(0, 1);
1269 						qglVertex3fv(angl_coord[0]);
1270 						qglTexCoord2f(0, 0);
1271 						qglVertex3fv(angl_coord[1]);
1272 						qglTexCoord2f(1, 0);
1273 						qglVertex3fv(angl_coord[2]);
1274 						qglTexCoord2f(1, 1);
1275 						qglVertex3fv(angl_coord[3]);
1276 					} else if (p->flags & PART_DEPTHHACK) {
1277 						vec3_t		angl_coord[4];
1278 
1279 						VectorMA(p->origin, size, coord[0], angl_coord[0]);
1280 						VectorMA(p->origin, size, coord[1], angl_coord[1]);
1281 						VectorMA(p->origin, size, coord[2], angl_coord[2]);
1282 						VectorMA(p->origin, size, coord[3], angl_coord[3]);
1283 
1284 						qglTexCoord2f(0, 1);
1285 						qglVertex3fv(angl_coord[0]);
1286 						qglTexCoord2f(0, 0);
1287 						qglVertex3fv(angl_coord[1]);
1288 						qglTexCoord2f(1, 0);
1289 						qglVertex3fv(angl_coord[2]);
1290 						qglTexCoord2f(1, 1);
1291 						qglVertex3fv(angl_coord[3]);
1292 					} else {
1293 						qglTexCoord2f(0, 1);
1294 						qglVertex3fv(coord[0]);
1295 						qglTexCoord2f(0, 0);
1296 						qglVertex3fv(coord[1]);
1297 						qglTexCoord2f(1, 0);
1298 						qglVertex3fv(coord[2]);
1299 						qglTexCoord2f(1, 1);
1300 						qglVertex3fv(coord[3]);
1301 
1302 					}
1303 				}
1304 				qglEnd();
1305 			}
1306 			qglPopMatrix();
1307 		}
1308 
1309 		if (p->flags & PART_DEPTHHACK)
1310 			qglDepthRange(gldepthmin, gldepthmax);
1311 	}
1312 
1313 	qglDepthRange(gldepthmin, gldepthmax);
1314 	qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1315 	GL_TexEnv(GL_MODULATE);
1316 	qglDepthMask(true);
1317 	qglDisable(GL_BLEND);
1318 	qglColor4f(1, 1, 1, 1);
1319 }
1320 #else
1321 void
GL_DrawParticles(int num_particles,const particle_t particles[],const unsigned colortable[768])1322 GL_DrawParticles(int num_particles, const particle_t particles[], const unsigned colortable[768])
1323 {
1324 	const particle_t *p;
1325 	int		i;
1326 	vec3_t		up, right;
1327 	float		scale;
1328 	byte		color[4];
1329 
1330 	GL_Bind(r_particletexture->texnum);
1331 	qglDepthMask(GL_FALSE);	/* no z buffering */
1332 	qglEnable(GL_BLEND);
1333 	GL_TexEnv(GL_MODULATE);
1334 	qglBegin(GL_TRIANGLES);
1335 
1336 	VectorScale(vup, 1.5, up);
1337 	VectorScale(vright, 1.5, right);
1338 
1339 	for (p = particles, i = 0; i < num_particles; i++, p++) {
1340 		/* hack a scale up to keep particles from disapearing */
1341 		scale = (p->origin[0] - r_origin[0]) * vpn[0] +
1342 		    (p->origin[1] - r_origin[1]) * vpn[1] +
1343 		    (p->origin[2] - r_origin[2]) * vpn[2];
1344 
1345 		if (scale < 20)
1346 			scale = 1;
1347 		else
1348 			scale = 1 + scale * 0.004;
1349 
1350 		*(int *)color = colortable[p->color];
1351 		color[3] = p->alpha * 255;
1352 
1353 		qglColor4ubv(color);
1354 
1355 		qglTexCoord2f(0.0625, 0.0625);
1356 		qglVertex3fv(p->origin);
1357 
1358 		qglTexCoord2f(1.0625, 0.0625);
1359 		qglVertex3f(p->origin[0] + up[0] * scale,
1360 		    p->origin[1] + up[1] * scale,
1361 		    p->origin[2] + up[2] * scale);
1362 
1363 		qglTexCoord2f(0.0625, 1.0625);
1364 		qglVertex3f(p->origin[0] + right[0] * scale,
1365 		    p->origin[1] + right[1] * scale,
1366 		    p->origin[2] + right[2] * scale);
1367 	}
1368 
1369 	qglEnd();
1370 	qglDisable(GL_BLEND);
1371 	qglColor4f(1, 1, 1, 1);
1372 	qglDepthMask(1);	/* back to normal Z buffering */
1373 	GL_TexEnv(GL_REPLACE);
1374 }
1375 #endif
1376 
1377 /*
1378  * =============== R_DrawParticles ===============
1379  */
1380 #ifdef QMAX
1381 void
R_DrawParticles(qboolean inWater)1382 R_DrawParticles(qboolean inWater)
1383 {
1384 	qglDisable(GL_FOG);	/* no fogging my precious */
1385 
1386 	GL_DrawParticles(r_refdef.num_particles, inWater);
1387 
1388 	/* Dont know if it was on... */
1389 	/* qglEnable(GL_FOG); */
1390 }
1391 #else
1392 void
R_DrawParticles(void)1393 R_DrawParticles(void)
1394 {
1395 	if (gl_particles->value) {
1396 		const particle_t *p;
1397 		int		i, k;
1398 		vec3_t		up, right;
1399 		float		scale, size = 1.0, r, g, b;
1400 
1401 		qglDepthMask(GL_FALSE);	/* no z buffering */
1402 		qglEnable(GL_BLEND);
1403 		GL_TexEnv(GL_MODULATE);
1404 		qglEnable(GL_TEXTURE_2D);
1405 		qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
1406 
1407 		/* Vertex arrays  */
1408 		qglEnableClientState(GL_VERTEX_ARRAY);
1409 		qglEnableClientState(GL_TEXTURE_COORD_ARRAY);
1410 		qglEnableClientState(GL_COLOR_ARRAY);
1411 
1412 		qglTexCoordPointer(2, GL_FLOAT, sizeof(tex_array[0]), tex_array[0]);
1413 		qglVertexPointer(3, GL_FLOAT, sizeof(vert_array[0]), vert_array[0]);
1414 		qglColorPointer(4, GL_FLOAT, sizeof(col_array[0]), col_array[0]);
1415 
1416 		GL_Bind(r_particletexture->texnum);
1417 
1418 		VectorScale(vup, size, up);
1419 		VectorScale(vright, size, right);
1420 
1421 		for (p = r_refdef.particles, i = 0, k = 0; i < r_refdef.num_particles; i++, p++, k += 4) {
1422 			/* hack a scale up to keep particles from disapearing */
1423 			scale = (p->origin[0] - r_origin[0]) * vpn[0] +
1424 			    (p->origin[1] - r_origin[1]) * vpn[1] +
1425 			    (p->origin[2] - r_origin[2]) * vpn[2];
1426 
1427 			scale = (scale < 20) ? 1 : 1 + scale * 0.0004;
1428 
1429 			r = d_8to24tablef[p->color & 0xFF][0];
1430 			g = d_8to24tablef[p->color & 0xFF][1];
1431 			b = d_8to24tablef[p->color & 0xFF][2];
1432 
1433 			VA_SetElem2(tex_array[k], 0, 0);
1434 			VA_SetElem4(col_array[k], r, g, b, p->alpha);
1435 			VA_SetElem3(vert_array[k], p->origin[0] - (up[0] * scale) - (right[0] * scale), p->origin[1] - (up[1] * scale) - (right[1] * scale), p->origin[2] - (up[2] * scale) - (right[2] * scale));
1436 
1437 			VA_SetElem2(tex_array[k + 1], 1, 0);
1438 			VA_SetElem4(col_array[k + 1], r, g, b, p->alpha);
1439 			VA_SetElem3(vert_array[k + 1], p->origin[0] + (up[0] * scale) - (right[0] * scale), p->origin[1] + (up[1] * scale) - (right[1] * scale), p->origin[2] + (up[2] * scale) - (right[2] * scale));
1440 
1441 			VA_SetElem2(tex_array[k + 2], 1, 1);
1442 			VA_SetElem4(col_array[k + 2], r, g, b, p->alpha);
1443 			VA_SetElem3(vert_array[k + 2], p->origin[0] + (right[0] * scale) + (up[0] * scale), p->origin[1] + (right[1] * scale) + (up[1] * scale), p->origin[2] + (right[2] * scale) + (up[2] * scale));
1444 
1445 			VA_SetElem2(tex_array[k + 3], 0, 1);
1446 			VA_SetElem4(col_array[k + 3], r, g, b, p->alpha);
1447 			VA_SetElem3(vert_array[k + 3], p->origin[0] + (right[0] * scale) - (up[0] * scale), p->origin[1] + (right[1] * scale) - (up[1] * scale), p->origin[2] + (right[2] * scale) - (up[2] * scale));
1448 		}
1449 
1450 		qglDrawArrays(GL_QUADS, 0, k);
1451 
1452 		qglDisable(GL_BLEND);
1453 		qglColor3f(1, 1, 1);
1454 		qglDepthMask(1);/* back to normal Z buffering */
1455 		GL_TexEnv(GL_REPLACE);
1456 		qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1457 		qglDisableClientState(GL_VERTEX_ARRAY);
1458 		qglDisableClientState(GL_TEXTURE_COORD_ARRAY);
1459 		qglDisableClientState(GL_COLOR_ARRAY);
1460 	} else if (gl_ext_pointparameters->value && qglPointParameterfEXT) {
1461 		int		i;
1462 		unsigned char	color[4];
1463 		const particle_t *p;
1464 
1465 		qglDepthMask(GL_FALSE);
1466 		qglEnable(GL_BLEND);
1467 		qglDisable(GL_TEXTURE_2D);
1468 
1469 		qglPointSize(gl_particle_size->value);
1470 
1471 		qglBegin(GL_POINTS);
1472 		for (i = 0, p = r_refdef.particles; i < r_refdef.num_particles; i++, p++) {
1473 			*(int *)color = d_8to24table[p->color];
1474 			color[3] = p->alpha * 255;
1475 
1476 			qglColor4ubv(color);
1477 
1478 			qglVertex3fv(p->origin);
1479 		}
1480 		qglEnd();
1481 
1482 		qglDisable(GL_BLEND);
1483 		qglColor4f(1.0, 1.0, 1.0, 1.0);
1484 		qglDepthMask(GL_TRUE);
1485 		qglEnable(GL_TEXTURE_2D);
1486 
1487 	} else {
1488 		GL_DrawParticles(r_refdef.num_particles, r_refdef.particles, d_8to24table);
1489 	}
1490 }
1491 #endif
1492 
1493 /*
1494  * ============ R_PolyBlend ============
1495  */
1496 void
R_PolyBlend(void)1497 R_PolyBlend(void)
1498 {
1499 	if (!gl_polyblend->value)
1500 		return;
1501 	if (!v_blend[3])
1502 		return;
1503 
1504 	qglDisable(GL_ALPHA_TEST);
1505 	qglEnable(GL_BLEND);
1506 	qglDisable(GL_DEPTH_TEST);
1507 	qglDisable(GL_TEXTURE_2D);
1508 
1509 	qglLoadIdentity();
1510 
1511 	/* FIXME: get rid of these */
1512 	qglRotatef(-90, 1, 0, 0);	/* put Z going up */
1513 	qglRotatef(90, 0, 0, 1);/* put Z going up */
1514 
1515 	qglColor4fv(v_blend);
1516 
1517 	qglBegin(GL_QUADS);
1518 
1519 	qglVertex3f(10, 100, 100);
1520 	qglVertex3f(10, -100, 100);
1521 	qglVertex3f(10, -100, -100);
1522 	qglVertex3f(10, 100, -100);
1523 	qglEnd();
1524 
1525 	qglDisable(GL_BLEND);
1526 	qglEnable(GL_TEXTURE_2D);
1527 	qglEnable(GL_ALPHA_TEST);
1528 
1529 	qglColor4f(1, 1, 1, 1);
1530 }
1531 
1532 /* ======================================================================= */
1533 
1534 int
SignbitsForPlane(cplane_t * out)1535 SignbitsForPlane(cplane_t * out)
1536 {
1537 	int		bits, j;
1538 
1539 	/* for fast box on planeside test */
1540 
1541 	bits = 0;
1542 	for (j = 0; j < 3; j++) {
1543 		if (out->normal[j] < 0)
1544 			bits |= 1 << j;
1545 	}
1546 	return bits;
1547 }
1548 
1549 
1550 void
R_SetFrustum(void)1551 R_SetFrustum(void)
1552 {
1553 	int		i;
1554 
1555 	/* rotate VPN right by FOV_X/2 degrees */
1556 	RotatePointAroundVector(frustum[0].normal, vup, vpn, -(90 - r_refdef.fov_x / 2));
1557 	/* rotate VPN left by FOV_X/2 degrees */
1558 	RotatePointAroundVector(frustum[1].normal, vup, vpn, 90 - r_refdef.fov_x / 2);
1559 	/* rotate VPN up by FOV_X/2 degrees */
1560 	RotatePointAroundVector(frustum[2].normal, vright, vpn, 90 - r_refdef.fov_y / 2);
1561 	/* rotate VPN down by FOV_X/2 degrees */
1562 	RotatePointAroundVector(frustum[3].normal, vright, vpn, -(90 - r_refdef.fov_y / 2));
1563 
1564 	for (i = 0; i < 4; i++) {
1565 		frustum[i].type = PLANE_ANYZ;
1566 		frustum[i].dist = DotProduct(r_origin, frustum[i].normal);
1567 		frustum[i].signbits = SignbitsForPlane(&frustum[i]);
1568 	}
1569 }
1570 
1571 /* ======================================================================= */
1572 
1573 /*
1574  * =============== R_SetupFrame ===============
1575  */
1576 void
R_SetupFrame(void)1577 R_SetupFrame(void)
1578 {
1579 	int		i;
1580 	mleaf_t        *leaf;
1581 
1582 	r_framecount++;
1583 
1584 	/* build the transformation matrix for the given view angles */
1585 	VectorCopy(r_refdef.vieworg, r_origin);
1586 
1587 	if (!g_drawing_refl) {
1588 
1589 		/* build the transformation matrix for the given view angles */
1590 		AngleVectors(r_refdef.viewangles, vpn, vright, vup);
1591 	}
1592 	/* start MPO */
1593 
1594 	/*
1595 	 * we want to look from the mirrored origin's perspective when
1596 	 * drawing reflections
1597 	 */
1598 	if (g_drawing_refl) {
1599 		float		distance;
1600 
1601 		distance = DotProduct(r_origin, waterNormals[g_active_refl]) - g_waterDistance2[g_active_refl];
1602 		VectorMA(r_refdef.vieworg, distance * -2, waterNormals[g_active_refl], r_origin);
1603 
1604 		if (!(r_refdef.rdflags & RDF_NOWORLDMODEL)) {
1605 			vec3_t		temp;
1606 
1607 			temp[0] = g_refl_X[g_active_refl];	/* sets PVS over x */
1608 			temp[1] = g_refl_Y[g_active_refl];	/* and y coordinate of water surface */
1609 
1610 			VectorCopy(r_origin, temp);
1611 			if (r_refdef.rdflags & RDF_UNDERWATER) {
1612 				temp[2] = g_refl_Z[g_active_refl] - 1;	/* just above water level */
1613 			} else {
1614 				temp[2] = g_refl_Z[g_active_refl] + 1;	/* just below water level */
1615 			}
1616 
1617 			leaf = Mod_PointInLeaf(temp, r_worldmodel);
1618 
1619 			if (!(leaf->contents & CONTENTS_SOLID) &&
1620 			    (leaf->cluster != r_viewcluster)) {
1621 				r_viewcluster2 = leaf->cluster;
1622 			}
1623 		}
1624 		return;
1625 	}
1626 	/* stop MPO */
1627 
1628 	/* current viewcluster */
1629 	if (!(r_refdef.rdflags & RDF_NOWORLDMODEL)) {
1630 		r_oldviewcluster = r_viewcluster;
1631 		r_oldviewcluster2 = r_viewcluster2;
1632 		leaf = Mod_PointInLeaf(r_origin, r_worldmodel);
1633 		r_viewcluster = r_viewcluster2 = leaf->cluster;
1634 
1635 		/*
1636 		 * check above and below so crossing solid water doesn't draw
1637 		 * wrong
1638 		 */
1639 		if (!leaf->contents) {	/* look down a bit */
1640 			vec3_t		temp;
1641 
1642 			VectorCopy(r_origin, temp);
1643 			temp[2] -= 16;
1644 			leaf = Mod_PointInLeaf(temp, r_worldmodel);
1645 			if (!(leaf->contents & CONTENTS_SOLID) &&
1646 			    (leaf->cluster != r_viewcluster2))
1647 				r_viewcluster2 = leaf->cluster;
1648 		} else {	/* look up a bit */
1649 			vec3_t		temp;
1650 
1651 			VectorCopy(r_origin, temp);
1652 			temp[2] += 16;
1653 			leaf = Mod_PointInLeaf(temp, r_worldmodel);
1654 			if (!(leaf->contents & CONTENTS_SOLID) &&
1655 			    (leaf->cluster != r_viewcluster2))
1656 				r_viewcluster2 = leaf->cluster;
1657 		}
1658 	}
1659 	for (i = 0; i < 4; i++)
1660 		v_blend[i] = r_refdef.blend[i];
1661 
1662 	c_brush_polys = 0;
1663 	c_alias_polys = 0;
1664 
1665 	/* clear out the portion of the screen that the NOWORLDMODEL defines */
1666 	if (r_refdef.rdflags & RDF_NOWORLDMODEL) {
1667 		qglEnable(GL_SCISSOR_TEST);
1668 		qglScissor(r_refdef.x, vid.height - r_refdef.height - r_refdef.y, r_refdef.width, r_refdef.height);
1669 		if (!(r_refdef.rdflags & RDF_NOCLEAR)) {
1670 			qglClearColor(0.3, 0.3, 0.3, 1);
1671 			qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1672 			qglClearColor(1, 0, 0.5, 0.5);
1673 		}
1674 		qglDisable(GL_SCISSOR_TEST);
1675 	}
1676 }
1677 
1678 
1679 void
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)1680 MYgluPerspective(GLdouble fovy, GLdouble aspect,
1681     GLdouble zNear, GLdouble zFar)
1682 {
1683 	GLdouble	xmin  , xmax, ymin, ymax;
1684 
1685 	ymax = zNear * tan(fovy * M_PI / 360.0);
1686 	ymin = -ymax;
1687 
1688 	xmin = ymin * aspect;
1689 	xmax = ymax * aspect;
1690 
1691 	xmin += -(2 * gl_state.camera_separation) / zNear;
1692 	xmax += -(2 * gl_state.camera_separation) / zNear;
1693 
1694 	qglFrustum(xmin, xmax, ymin, ymax, zNear, zFar);
1695 }
1696 
1697 
1698 /*
1699  * ============= R_SetupGL =============
1700  */
1701 void
R_SetupGL(void)1702 R_SetupGL(void)
1703 {
1704 	static GLdouble	farz;	/* DMP skybox size change */
1705 	GLdouble	boxsize;/* DMP skybox size change */
1706 	int		x, x2, y2, y, w, h;
1707 	float		screenaspect;
1708 
1709 	/* Knightmare- update gl_modulate in real time */
1710 	/* FIXME NightHunters demos */
1711     	if (gl_modulate->modified && (r_worldmodel)) { /* Don't do this if no map is loaded */
1712 		msurface_t *surf;
1713 		int i;
1714 
1715         	for (i=0,surf = r_worldmodel->surfaces; i<r_worldmodel->numsurfaces; i++,surf++)
1716 			surf->cached_light[0]=0;
1717         		gl_modulate->modified = 0;
1718 	}
1719 
1720 	/* set up viewport */
1721 	x = floor(r_refdef.x * vid.width / vid.width);
1722 	x2 = ceil((r_refdef.x + r_refdef.width) * vid.width / vid.width);
1723 	y = floor(vid.height - r_refdef.y * vid.height / vid.height);
1724 	y2 = ceil(vid.height - (r_refdef.y + r_refdef.height) * vid.height / vid.height);
1725 
1726 	w = x2 - x;
1727 	h = y - y2;
1728 
1729 	if (skydistance->modified) {
1730 		skydistance->modified = false;
1731 		boxsize = skydistance->value;
1732 		boxsize -= 252 * ceil(boxsize / 2300);
1733 		farz = 1.0;
1734 		while (farz < boxsize) {	/* DMP: make this value a
1735 						 * power-of-2 */
1736 			farz *= 2.0;
1737 			if (farz >= 65536.0)	/* DMP: don't make it larger
1738 						 * than this */
1739 				break;
1740 		}
1741 		farz *= 2.0;	/* DMP: double since boxsize is distance from camera to */
1742 		/* edge of skybox - not total size of skybox */
1743 		ri.Con_Printf(PRINT_DEVELOPER, "farz now set to %g\n", farz);
1744 	}
1745 
1746 	/*
1747 	 * MPO : we only want to set the viewport if we aren't drawing the
1748 	 * reflection
1749 	 */
1750 	if (!g_drawing_refl) {
1751 		qglViewport(x, y2, w, h); /* MPO : note this happens every
1752 		                           * frame interestingly enough
1753 					   */
1754 	} else {
1755 		qglViewport(0, 0, g_reflTexW, g_reflTexH); /* width/height of texture size,
1756 		                                            * not screen size
1757 							    */
1758 	}
1759 	/* stop MPO */
1760 
1761 	/* set up projection matrix */
1762 	screenaspect = (float)r_refdef.width / r_refdef.height;
1763 
1764 	/*
1765 	 * yfov =
1766 	 * 2*atan((float)r_refdef.height/r_refdef.width)*180/M_PI;
1767 	 */
1768 	qglMatrixMode(GL_PROJECTION);
1769 	qglLoadIdentity();
1770 
1771 	/* MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  4096); */
1772 	MYgluPerspective(r_refdef.fov_y, screenaspect, 4, farz);	/* DMP skybox */
1773 
1774 
1775 	qglCullFace(GL_FRONT);
1776 
1777 	qglMatrixMode(GL_MODELVIEW);
1778 	qglLoadIdentity();
1779 
1780 	qglRotatef(-90, 1, 0, 0);	/* put Z going up */
1781 	qglRotatef(90, 0, 0, 1);/* put Z going up */
1782 
1783 	/*
1784 	 * MPO : +Z is up, +X is forward, +Y is left according to my
1785 	 * calculations
1786 	 */
1787 
1788 	/* start MPO */
1789 	/* standard transformation */
1790 	if (!g_drawing_refl) {
1791 
1792 		qglRotatef(-r_refdef.viewangles[2], 1, 0, 0);	/* MPO : this handles rolling (ie when we
1793 								* strafe side to side we roll slightly) */
1794 		qglRotatef(-r_refdef.viewangles[0], 0, 1, 0);	/* MPO : this handles up/down rotation */
1795 		qglRotatef(-r_refdef.viewangles[1], 0, 0, 1);	/* MPO : this handles left/right rotation */
1796 		qglTranslatef(-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
1797 
1798 		/*
1799 		 * MPO : this translate call puts the player at the proper
1800 		 * spot in the map
1801 		 */
1802 		/* MPO : The map is drawn to absolute coordinates */
1803 	}
1804 	/* mirrored transformation for reflection */
1805 	else {
1806 
1807 		R_DoReflTransform(true);
1808 	}
1809 	/* end MPO */
1810 	if (gl_state.camera_separation != 0 && gl_state.stereo_enabled)
1811 		qglTranslatef(gl_state.camera_separation, 0, 0);
1812 
1813 	qglGetFloatv(GL_MODELVIEW_MATRIX, r_world_matrix);
1814 
1815 	/* set drawing parms */
1816 	if ((gl_cull->value) && (!g_drawing_refl)) /* MPO : we must disable culling when drawing the reflection */
1817 		qglEnable(GL_CULL_FACE);
1818 	else
1819 		qglDisable(GL_CULL_FACE);
1820 
1821 	qglDisable(GL_BLEND);
1822 	qglDisable(GL_ALPHA_TEST);
1823 	qglEnable(GL_DEPTH_TEST);
1824 }
1825 
1826 /*
1827  * ============= R_Clear =============
1828  */
1829 void
R_Clear(void)1830 R_Clear(void)
1831 {
1832 
1833 	if (gl_clear->value) {
1834 		qglClearColor(0.5f, 0.5f, 0.5f, 1.0f);
1835 		qglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1836 	}
1837 	else {
1838 		qglClear(GL_DEPTH_BUFFER_BIT);
1839 	}
1840 
1841 	if (have_stencil) {
1842 		qglClearStencil(1);
1843 		qglClear(GL_STENCIL_BUFFER_BIT);
1844 	}
1845 
1846 	gldepthmin = 0;
1847 	gldepthmax = 1;
1848 	qglDepthFunc(GL_LEQUAL);
1849 
1850 	qglDepthRange(gldepthmin, gldepthmax);
1851 
1852 }
1853 
1854 void
R_Flash(void)1855 R_Flash(void)
1856 {
1857 	R_PolyBlend();
1858 }
1859 
1860 void
setupModelLighting(void)1861 setupModelLighting(void)
1862 {
1863 
1864 	int		lnum;
1865 	int		newNumGlLights;
1866 	float		vec4[4] = {1, 1, 1, 1};
1867 
1868 	lnum = 0;
1869 	newNumGlLights = 0;
1870 
1871 	qglLightModelfv(GL_LIGHT_MODEL_AMBIENT, vec4);
1872 	qglMaterialfv(GL_FRONT, GL_DIFFUSE, vec4);
1873 	/* qglMaterialfv	( GL_FRONT, GL_AMBIENT,   vec4	); */
1874 	qglColorMaterial(GL_FRONT, GL_AMBIENT);
1875 
1876 
1877 	for (; (lnum < r_refdef.num_dlights) && (newNumGlLights < 8); lnum++) {
1878 		dlight_t       *dl = &r_refdef.dlights[lnum];
1879 
1880 		if (dl->intensity <= 64)
1881 			continue;
1882 
1883 		memcpy(vec4, dl->origin, sizeof(dl->origin));
1884 		qglLightfv(GL_LIGHT0 + newNumGlLights, GL_POSITION, vec4);
1885 
1886 		qglLightf(GL_LIGHT0 + newNumGlLights,
1887 		    GL_QUADRATIC_ATTENUATION,
1888 		    0.000000001 * dl->intensity);
1889 
1890 		memcpy(vec4, dl->color, sizeof(dl->color));
1891 		vec4[0] *= gl_modulate->value;
1892 		vec4[1] *= gl_modulate->value;
1893 		vec4[2] *= gl_modulate->value;
1894 		qglLightfv(GL_LIGHT0 + newNumGlLights, GL_DIFFUSE, vec4);
1895 
1896 		++newNumGlLights;
1897 	}
1898 
1899 	if (newNumGlLights < g_numGlLights) {
1900 		while (g_numGlLights != newNumGlLights) {
1901 			--g_numGlLights;
1902 			qglDisable(GL_LIGHT0 + g_numGlLights);
1903 		}
1904 	} else if (g_numGlLights != newNumGlLights)
1905 		g_numGlLights = newNumGlLights;
1906 }
1907 
1908 /*
1909  * ================ R_RenderView
1910  *
1911  * r_refdef must be set before the first call ================
1912  */
1913 void
R_RenderView(refdef_t * fd)1914 R_RenderView(refdef_t * fd)
1915 {
1916 #ifdef QMAX
1917 	qboolean	inWater;
1918 #endif
1919 	vec3_t		colors;	/* Fog */
1920 
1921 	if (r_norefresh->value)
1922 		return;
1923 
1924 	r_refdef = *fd;
1925 
1926 	/* (gl_scale) NiceAss: Scale back up from client's false width/height */
1927 	r_refdef.width *= cl_hudscale->value;
1928 	r_refdef.height *= cl_hudscale->value;
1929 	r_refdef.x *= cl_hudscale->value;
1930 	r_refdef.y *= cl_hudscale->value;
1931 
1932 	if (!r_worldmodel && !(r_refdef.rdflags & RDF_NOWORLDMODEL))
1933 		ri.Sys_Error(ERR_DROP, "R_RenderView: NULL worldmodel");
1934 
1935 	if (r_speeds->value) {
1936 		c_brush_polys = 0;
1937 		c_alias_polys = 0;
1938 	}
1939 	R_PushDlights();
1940 
1941 	if (gl_finish->value)
1942 		qglFinish();
1943 
1944 	if ((r_refdef.num_newstains > 0) && (gl_stainmaps->value)) {
1945 		R_ApplyStains();
1946 	}
1947 	R_SetupGL();		/* MPO moved here .. */
1948 
1949 	R_SetupFrame();
1950 
1951 	R_SetFrustum();
1952 
1953 	setupClippingPlanes();	/* MPO clipping planes for water */
1954 
1955 	/* R_SetupGL (); */
1956 
1957 	R_MarkLeaves();		/* done here so we know if we're in water */
1958 
1959 	drawPlayerReflection();
1960 
1961 	R_DrawWorld();
1962 
1963 #ifdef QMAX
1964 	if (r_refdef.rdflags & RDF_NOWORLDMODEL || !gl_transrendersort->value) {
1965 		inWater = false;
1966 	} else {
1967 		inWater = Mod_PointInLeaf(fd->vieworg, r_worldmodel)->contents;
1968 	}
1969 	if (!(r_refdef.rdflags & RDF_NOWORLDMODEL) && gl_transrendersort->value) {
1970 		R_SortParticlesOnList(r_refdef.num_particles, r_refdef.particles);
1971 		R_SortEntitiesOnList(inWater);
1972 	}
1973 #endif
1974 
1975 	R_AddDecals(); /* Decals */
1976 
1977 	if (gl_flares->value) {
1978 		if (gl_fogenable->value /*|| gl_fogunderwater->value*/) {
1979 			qglDisable(GL_FOG);
1980 			R_RenderFlares();
1981 			qglEnable(GL_FOG);
1982 		}
1983 		else {
1984 			R_RenderFlares();
1985 		}
1986 	}
1987 
1988 	setupModelLighting();	/* dukey sets up opengl dynamic lighting for entitites. */
1989 
1990 #ifdef QMAX
1991 	R_DrawEntitiesOnList((inWater) ? false : true, true);
1992 #else
1993 	R_DrawEntitiesOnList();
1994 #endif
1995 
1996 	/* R_RenderDlights (); */
1997 #ifdef QMAX
1998 	R_DrawParticles((inWater) ? false : true);
1999 #else
2000 
2001 	if (!gl_ext_texture_compression->value) {
2002 		R_BloomBlend(fd);	/* BLOOMS */
2003 	}
2004 	R_DrawParticles();
2005 #endif
2006 
2007 	if (gl_alpha_surfaces->value) {
2008 		R_DrawAlphaSurfaces_Jitspoe();
2009 	} else {
2010 		R_DrawAlphaSurfaces();
2011 	}
2012 
2013 #ifdef QMAX
2014 	R_DrawEntitiesOnList((inWater) ? true : false, false);
2015 
2016 	if (!gl_ext_texture_compression->value) {
2017 		R_BloomBlend(fd);	/* BLOOMS */
2018 	}
2019 	R_DrawParticles((inWater) ? true : false);
2020 #else
2021 	R_DrawParticles();
2022 #endif
2023 
2024 	/* start MPO */
2025 	/* if we are doing a reflection, turn off clipping now */
2026 	if (g_drawing_refl) {
2027 		qglDisable(GL_CLIP_PLANE0);
2028 	}
2029 
2030 	/*
2031 	 * if we aren't doing a reflection then we can do the flash and r
2032 	 * speeds
2033 	 */
2034 	/* (we don't want them showing up in our reflection) */
2035 	else {
2036 		R_Flash();
2037 	}
2038 	/* stop MPO */
2039 	/* ===================== Engine Fog ================= */
2040 	qglDisable(GL_FOG);
2041 
2042 	if (gl_fogenable->value && !(r_refdef.rdflags & RDF_UNDERWATER)) {
2043 		qglEnable(GL_FOG);
2044 		qglFogi(GL_FOG_MODE, GL_BLEND);
2045 		colors[0] = gl_fogred->value;
2046 		colors[1] = gl_foggreen->value;
2047 		colors[2] = gl_fogblue->value;
2048 
2049 		qglFogf(GL_FOG_DENSITY, gl_fogdensity->value);
2050 		qglFogfv(GL_FOG_COLOR, colors);
2051 		qglFogf(GL_FOG_START, gl_fogstart->value);
2052 		qglFogf(GL_FOG_END, gl_fogend->value);
2053 
2054 	} else if (gl_fogunderwater->value && (r_refdef.rdflags & RDF_UNDERWATER)) {
2055 		qglEnable(GL_FOG);
2056 
2057 		qglFogi(GL_FOG_MODE, GL_BLEND);
2058 		colors[0] = gl_fogred->value;
2059 		colors[1] = gl_foggreen->value;
2060 		colors[2] = gl_fogblue->value;
2061 
2062 		qglFogf(GL_FOG_START, 0.0);
2063 	    	qglFogf(GL_FOG_END, 2048);
2064 		qglFogf(GL_FOG_DENSITY, 0.0);
2065 
2066 		if (inlava) {
2067 			colors[0] = 0.7;
2068        		}
2069 		if (inslime) {
2070 			colors[1] = 0.7;
2071         	}
2072 		if (inwater) {
2073 			colors[2] = 0.6;
2074 		}
2075 
2076 		qglFogf(GL_FOG_DENSITY, 0.001);
2077 		qglFogf(GL_FOG_START, 0.0);
2078 		qglFogfv(GL_FOG_COLOR, colors);
2079 		qglFogf(GL_FOG_END, 450);
2080 
2081 	} else {
2082 		qglDisable(GL_FOG);
2083 	}
2084 
2085 	/* ====================== End ======================= */
2086 
2087 	if (!deathmatch->value && gl_minimap_size->value > 32 && !(r_refdef.rdflags & RDF_IRGOGGLES)) {
2088 		{
2089 			GLSTATE_DISABLE_ALPHATEST;
2090 			GL_DrawRadar();
2091 		}
2092 		numRadarEnts = 0;
2093 	}
2094 }
2095 
2096 int
R_DrawRSpeeds(char * S)2097 R_DrawRSpeeds(char *S)
2098 {
2099 	return sprintf(S, "%4i wpoly %4i epoly %i tex %i lmaps",
2100 
2101 	c_brush_polys,
2102 	c_alias_polys,
2103 	c_visible_textures,
2104 	c_visible_lightmaps);
2105 }
2106 
2107 unsigned int	blurtex = 0;
2108 void
R_MotionBlur(void)2109 R_MotionBlur (void)
2110 {
2111 
2112 	if (!gl_state.tex_rectangle)
2113 		return;
2114 
2115 	if (gl_state.tex_rectangle) {
2116 		if (blurtex) {
2117 			GL_TexEnv(GL_MODULATE);
2118 			qglDisable(GL_TEXTURE_2D);
2119 			qglEnable(GL_TEXTURE_RECTANGLE_NV);
2120 			qglEnable(GL_BLEND);
2121 			qglDisable(GL_ALPHA_TEST);
2122 			qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2123 			if (gl_motionblur_intensity->value >= 1.0)
2124 				qglColor4f(1.0, 1.0, 1.0, 0.45);
2125 			else
2126 				qglColor4f(1.0, 1.0, 1.0, gl_motionblur_intensity->value);
2127 			qglBegin(GL_QUADS);
2128 			{
2129 				qglTexCoord2f(0, vid.height);
2130 				qglVertex2f(0, 0);
2131 				qglTexCoord2f(vid.width, vid.height);
2132 				qglVertex2f(vid.width, 0);
2133 				qglTexCoord2f(vid.width, 0);
2134 				qglVertex2f(vid.width, vid.height);
2135 				qglTexCoord2f(0, 0);
2136 				qglVertex2f(0, vid.height);
2137 			}
2138 			qglEnd();
2139 			qglDisable(GL_TEXTURE_RECTANGLE_NV);
2140 			qglEnable(GL_TEXTURE_2D);
2141 		}
2142 		if (!blurtex)
2143 			qglGenTextures(1, &blurtex);
2144 		qglBindTexture(GL_TEXTURE_RECTANGLE_NV, blurtex);
2145 		qglCopyTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGB, 0, 0, vid.width, vid.height, 0);
2146 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2147 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2148 	}
2149 }
2150 
2151 void
R_SetGL2D(void)2152 R_SetGL2D(void)
2153 {
2154 	/* set 2D virtual screen size */
2155 	qglViewport(0, 0, vid.width, vid.height);
2156 	qglMatrixMode(GL_PROJECTION);
2157 	qglLoadIdentity();
2158 	/* NiceAss: Scale the screen */
2159 	qglOrtho(0, vid.width / cl_hudscale->value, vid.height / cl_hudscale->value, 0, -99999, 99999);
2160 	/* qglOrtho  (0, vid.width, vid.height, 0, -99999, 99999); */
2161 
2162 	qglMatrixMode(GL_MODELVIEW);
2163 	qglLoadIdentity();
2164 	qglDisable(GL_DEPTH_TEST);
2165 	qglDisable(GL_CULL_FACE);
2166 	if (gl_motionblur->value == 1 && r_refdef.rdflags & RDF_UNDERWATER)
2167 		R_MotionBlur();
2168 	else if (gl_motionblur->value == 2)
2169 		R_MotionBlur();
2170 	qglDisable(GL_BLEND);
2171 	qglEnable(GL_ALPHA_TEST);
2172 	qglColor4f(1, 1, 1, 1);
2173 	/* ECHON */
2174 	if (r_speeds->value) {
2175 		char		S[128];
2176 		int		n = 0;
2177 		int		i;
2178 
2179 		n = R_DrawRSpeeds(S);
2180 
2181 		for (i = 0; i < n; i++)
2182 			Draw_Char(r_refdef.width - 4 + ((i - n) * 8), r_refdef.height - 40, 128 + S[i], 255);
2183 	}
2184 }
2185 
2186 static void
GL_DrawColoredStereoLinePair(float r,float g,float b,float y)2187 GL_DrawColoredStereoLinePair(float r, float g, float b, float y)
2188 {
2189 	qglColor3f(r, g, b);
2190 	qglVertex2f(0, y);
2191 	qglVertex2f(vid.width, y);
2192 	qglColor3f(0, 0, 0);
2193 	qglVertex2f(0, y + 1);
2194 	qglVertex2f(vid.width, y + 1);
2195 }
2196 
2197 static void
GL_DrawStereoPattern(void)2198 GL_DrawStereoPattern(void)
2199 {
2200 	int		i;
2201 
2202 	if (!(gl_config.renderer & GL_RENDERER_INTERGRAPH))
2203 		return;
2204 
2205 	if (!gl_state.stereo_enabled)
2206 		return;
2207 
2208 	R_SetGL2D();
2209 
2210 	qglDrawBuffer(GL_BACK_LEFT);
2211 
2212 	for (i = 0; i < 20; i++) {
2213 		qglBegin(GL_LINES);
2214 		GL_DrawColoredStereoLinePair(1, 0, 0, 0);
2215 		GL_DrawColoredStereoLinePair(1, 0, 0, 2);
2216 		GL_DrawColoredStereoLinePair(1, 0, 0, 4);
2217 		GL_DrawColoredStereoLinePair(1, 0, 0, 6);
2218 		GL_DrawColoredStereoLinePair(0, 1, 0, 8);
2219 		GL_DrawColoredStereoLinePair(1, 1, 0, 10);
2220 		GL_DrawColoredStereoLinePair(1, 1, 0, 12);
2221 		GL_DrawColoredStereoLinePair(0, 1, 0, 14);
2222 		qglEnd();
2223 
2224 		GLimp_EndFrame();
2225 	}
2226 }
2227 
2228 
2229 /*
2230  * ==================== R_SetLightLevel
2231  *
2232  * ====================
2233  */
2234 void
R_SetLightLevel(void)2235 R_SetLightLevel(void)
2236 {
2237 	vec3_t		shadelight;
2238 
2239 	if (r_refdef.rdflags & RDF_NOWORLDMODEL)
2240 		return;
2241 
2242 	/* save off light value for server to look at (BIG HACK!) */
2243 
2244 	R_LightPoint(r_refdef.vieworg, shadelight);
2245 
2246 	/* pick the greatest component, which should be the same */
2247 	/* as the mono value returned by software */
2248 	if (shadelight[0] > shadelight[1]) {
2249 		if (shadelight[0] > shadelight[2])
2250 			r_lightlevel->value = 150 * shadelight[0];
2251 		else
2252 			r_lightlevel->value = 150 * shadelight[2];
2253 	} else {
2254 		if (shadelight[1] > shadelight[2])
2255 			r_lightlevel->value = 150 * shadelight[1];
2256 		else
2257 			r_lightlevel->value = 150 * shadelight[2];
2258 	}
2259 
2260 }
2261 
2262 /*
2263  * @@@@@@@@@@@@@@@@@@@@@ R_RenderFrame
2264  *
2265  * @@@@@@@@@@@@@@@@@@@@@
2266  */
2267 void
R_RenderFrame(refdef_t * fd)2268 R_RenderFrame(refdef_t * fd)
2269 {
2270 	/* start MPO */
2271 	if (gl_reflection->value) {
2272 
2273 		r_refdef = *fd;	/* need to do this so eye coords
2274 					 * update b4 frame is drawn */
2275 
2276 		R_clear_refl();	/* clear our reflections found in last frame */
2277 		R_RecursiveFindRefl(r_worldmodel->nodes);	/* find reflections for
2278 								 * this frame */
2279 		R_UpdateReflTex(fd);	/* render reflections to textures */
2280 	} else {
2281 		R_clear_refl();
2282 	}
2283 	/* end MPO */
2284 	R_PreRenderDynamic(fd);
2285 	R_RenderView(fd);
2286 	R_SetLightLevel();
2287 	R_SetGL2D();
2288 	R_RenderGlares(fd);
2289 
2290 	/* start MPO */
2291 	/* if debugging is enabled and reflections are enabled.. draw it */
2292 	if ((gl_reflection_debug->value) && (g_refl_enabled)) {
2293 		R_DrawDebugReflTexture();
2294 	}
2295 	/* end MPO */
2296 }
2297 
2298 
2299 void
R_Register(void)2300 R_Register(void)
2301 {
2302 
2303 	cl_hudscale = ri.Cvar_Get("cl_hudscale", "1", CVAR_ARCHIVE);
2304 	cl_big_maps = ri.Cvar_Get("cl_big_maps", "1",  0);
2305 	cl_3dcam = ri.Cvar_Get("cl_3dcam", "0", CVAR_ARCHIVE);
2306 
2307 	deathmatch = ri.Cvar_Get("deathmatch", "0", 0);
2308 
2309 	font_color = ri.Cvar_Get("font_color", "default", CVAR_ARCHIVE);
2310 
2311 #ifdef QMAX
2312 	gl_partscale = ri.Cvar_Get("gl_partscale", "100", 0);
2313 	gl_transrendersort = ri.Cvar_Get("gl_transrendersort", "1", 0);
2314 	gl_particlelighting = ri.Cvar_Get("gl_particlelighting", "0.75", 0);
2315 	gl_particledistance = ri.Cvar_Get("gl_particledistance", "0", 0);
2316 #else
2317 	gl_particle_min_size = ri.Cvar_Get("gl_particle_min_size", "2", 0);
2318 	gl_particle_max_size = ri.Cvar_Get("gl_particle_max_size", "40", 0);
2319 	gl_particle_size = ri.Cvar_Get("gl_particle_size", "40", 0);
2320 	gl_particle_att_a = ri.Cvar_Get("gl_particle_att_a", "0.01", 0);
2321 	gl_particle_att_b = ri.Cvar_Get("gl_particle_att_b", "0.0", 0);
2322 	gl_particle_att_c = ri.Cvar_Get("gl_particle_att_c", "0.01", 0);
2323 	gl_particles = ri.Cvar_Get("gl_particles", "0", CVAR_ARCHIVE);
2324 #endif
2325 	gl_stainmaps = ri.Cvar_Get("gl_stainmaps", "0", CVAR_ARCHIVE);
2326 	gl_dlight_cutoff = ri.Cvar_Get("gl_dlight_cutoff", "0", CVAR_ARCHIVE);
2327 	gl_shellstencil = ri.Cvar_Get("gl_shellstencil", "1", CVAR_ARCHIVE);
2328 	gl_nosubimage = ri.Cvar_Get("gl_nosubimage", "0", 0);
2329 	gl_modulate = ri.Cvar_Get("gl_modulate", "1", CVAR_ARCHIVE);
2330 	gl_log = ri.Cvar_Get("gl_log", "0", 0);
2331 	gl_bitdepth = ri.Cvar_Get("gl_bitdepth", "0", 0);
2332 	gl_mode = ri.Cvar_Get("gl_mode", "4", CVAR_ARCHIVE);
2333 	gl_lightmap = ri.Cvar_Get("gl_lightmap", "0", 0);
2334 	gl_shadows = ri.Cvar_Get("gl_shadows", "0", CVAR_ARCHIVE);
2335 	gl_shadows_alpha = ri.Cvar_Get("gl_shadows_alpha", "0.5", 0);
2336 	gl_dynamic = ri.Cvar_Get("gl_dynamic", "1", 0);
2337 	gl_nobind = ri.Cvar_Get("gl_nobind", "0", 0);
2338 	gl_round_down = ri.Cvar_Get("gl_round_down", "1", 0);
2339 	gl_picmip = ri.Cvar_Get("gl_picmip", "0", 0);
2340 	gl_skymip = ri.Cvar_Get("gl_skymip", "0", 0);
2341 	gl_showtris = ri.Cvar_Get("gl_showtris", "0", 0);
2342 	gl_finish = ri.Cvar_Get("gl_finish", "0", 0);
2343 	gl_clear = ri.Cvar_Get("gl_clear", "0", 0);
2344 	gl_cull = ri.Cvar_Get("gl_cull", "1", 0);
2345 	gl_polyblend = ri.Cvar_Get("gl_polyblend", "1", 0);
2346 	gl_flashblend = ri.Cvar_Get("gl_flashblend", "0", 0);
2347 	gl_playermip = ri.Cvar_Get("gl_playermip", "0", 0);
2348 	gl_monolightmap = ri.Cvar_Get("gl_monolightmap", "0", 0);
2349 	gl_driver = ri.Cvar_Get("gl_driver", "libGL.so", CVAR_ARCHIVE);
2350 	gl_texturemode = ri.Cvar_Get("gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE);
2351 	gl_texturealphamode = ri.Cvar_Get("gl_texturealphamode", "default", CVAR_ARCHIVE);
2352 	gl_texturesolidmode = ri.Cvar_Get("gl_texturesolidmode", "default", CVAR_ARCHIVE);
2353 	gl_lockpvs = ri.Cvar_Get("gl_lockpvs", "0", 0);
2354 	gl_ext_mtexcombine = ri.Cvar_Get("gl_ext_mtexcombine", "1", CVAR_ARCHIVE);
2355 	gl_vertex_arrays = ri.Cvar_Get("gl_vertex_arrays", "0", CVAR_ARCHIVE);
2356 	gl_ext_multitexture = ri.Cvar_Get("gl_ext_multitexture", "1", CVAR_ARCHIVE);
2357 	gl_ext_pointparameters = ri.Cvar_Get("gl_ext_pointparameters", "1", CVAR_ARCHIVE);
2358 	gl_ext_compiled_vertex_array = ri.Cvar_Get("gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE);
2359 	gl_ext_palettedtexture = ri.Cvar_Get("gl_ext_palettedtexture", "0", 0);
2360 	gl_drawbuffer = ri.Cvar_Get("gl_drawbuffer", "GL_BACK", 0);
2361 	gl_saturatelighting = ri.Cvar_Get("gl_saturatelighting", "0", 0);
2362 	gl_3dlabs_broken = ri.Cvar_Get("gl_3dlabs_broken", "1", CVAR_ARCHIVE);
2363 	gl_ext_texture_compression = ri.Cvar_Get("gl_ext_texture_compression", "0", CVAR_ARCHIVE);
2364 	gl_anisotropic = ri.Cvar_Get("gl_anisotropic", "0", CVAR_ARCHIVE);
2365 	gl_anisotropic_avail = ri.Cvar_Get("gl_anisotropic_avail", "0", 0);
2366 	gl_nv_fog = ri.Cvar_Get("gl_nv_fog", "0", CVAR_ARCHIVE);
2367 	gl_ext_nv_multisample_filter_hint = ri.Cvar_Get("gl_ext_nv_multisample_filter_hint", "fastest", 0);
2368 	gl_lightmap_texture_saturation = ri.Cvar_Get("gl_lightmap_texture_saturation", "1", 0);
2369 	gl_lightmap_saturation = ri.Cvar_Get("gl_lightmap_saturation", "1", 0);
2370 	gl_alpha_surfaces = ri.Cvar_Get("gl_alpha_surfaces", "0", 0);
2371 	gl_screenshot_jpeg = ri.Cvar_Get("gl_screenshot_jpeg", "1", CVAR_ARCHIVE);
2372 	gl_screenshot_jpeg_quality = ri.Cvar_Get("gl_screenshot_jpeg_quality", "95", CVAR_ARCHIVE);
2373 	gl_water_waves = ri.Cvar_Get("gl_water_waves", "0", CVAR_ARCHIVE);
2374 	gl_water_caustics = ri.Cvar_Get("gl_water_caustics", "1", CVAR_ARCHIVE);
2375 	gl_water_pixel_shader_warp = ri.Cvar_Get("gl_water_pixel_shader_warp", "1", CVAR_ARCHIVE);
2376 	gl_blooms = ri.Cvar_Get("gl_blooms", "0", CVAR_ARCHIVE);
2377 	gl_motionblur = ri.Cvar_Get("gl_motionblur", "0", CVAR_ARCHIVE);
2378 	gl_motionblur_intensity = ri.Cvar_Get("gl_motionblur_intensity", "0.6", CVAR_ARCHIVE);
2379 	gl_fogenable = ri.Cvar_Get("gl_fogenable", "0", CVAR_ARCHIVE);
2380 	gl_fogstart = ri.Cvar_Get("gl_fogstart", "50.0", CVAR_ARCHIVE);
2381 	gl_fogend = ri.Cvar_Get("gl_fogend", "1500.0", CVAR_ARCHIVE);
2382 	gl_fogdensity = ri.Cvar_Get("gl_fogdensity", "0.001", CVAR_ARCHIVE);
2383 	gl_fogred = ri.Cvar_Get("gl_fogred", "0.4", CVAR_ARCHIVE);
2384 	gl_foggreen = ri.Cvar_Get("gl_foggreen", "0.4", CVAR_ARCHIVE);
2385 	gl_fogblue = ri.Cvar_Get("gl_fogblue", "0.4", CVAR_ARCHIVE);
2386 	gl_fogunderwater = ri.Cvar_Get("gl_fogunderwater", "0", CVAR_ARCHIVE);
2387 	gl_reflection_fragment_program = ri.Cvar_Get("gl_reflection_fragment_program", "0", CVAR_ARCHIVE);
2388 	gl_reflection = ri.Cvar_Get("gl_reflection", "0", CVAR_ARCHIVE);
2389 	gl_reflection_debug = ri.Cvar_Get("gl_reflection_debug", "0", 0);
2390 	gl_reflection_max = ri.Cvar_Get("gl_reflection_max", "2", 0);
2391 	gl_reflection_shader = ri.Cvar_Get("gl_reflection_shader", "0", CVAR_ARCHIVE);
2392 	gl_reflection_shader_image = ri.Cvar_Get("gl_reflection_shader_image",
2393 	                                          "/textures/water/distortion.pcx", CVAR_ARCHIVE);
2394 	gl_reflection_water_surface = ri.Cvar_Get("gl_reflection_water_surface", "1", 0);
2395 	gl_minimap = ri.Cvar_Get("gl_minimap", "0", CVAR_ARCHIVE);
2396 	gl_minimap_size = ri.Cvar_Get("gl_minimap_size", "400", CVAR_ARCHIVE);
2397 	gl_minimap_zoom = ri.Cvar_Get("gl_minimap_zoom", "1.5", CVAR_ARCHIVE);
2398 	gl_minimap_style = ri.Cvar_Get("gl_minimap_style", "1", CVAR_ARCHIVE);
2399 	gl_minimap_x = ri.Cvar_Get("gl_minimap_x", "800", CVAR_ARCHIVE);
2400 	gl_minimap_y = ri.Cvar_Get("gl_minimap_y", "400", CVAR_ARCHIVE);
2401 	gl_detailtextures = ri.Cvar_Get("gl_detailtextures", "0.0", CVAR_ARCHIVE);
2402 	gl_shading = ri.Cvar_Get("gl_shading", "1", CVAR_ARCHIVE);
2403 	gl_decals = ri.Cvar_Get("gl_decals", "1", CVAR_ARCHIVE);
2404 	gl_decals_time = ri.Cvar_Get("gl_decals_time", "30", CVAR_ARCHIVE);
2405 	gl_glares = ri.Cvar_Get("gl_glares", "0", CVAR_ARCHIVE);
2406 	gl_glares_size = ri.Cvar_Get("gl_glares_size", "128", CVAR_ARCHIVE);
2407 	gl_glares_intens = ri.Cvar_Get("gl_glares_intens", "0.35", CVAR_ARCHIVE);
2408 	gl_flares = ri.Cvar_Get("gl_flares", "1", CVAR_ARCHIVE);
2409 	gl_flare_force_size = ri.Cvar_Get("gl_flare_force_size", "0", CVAR_ARCHIVE);
2410 	gl_flare_force_style = ri.Cvar_Get("gl_flare_force_style", "1", CVAR_ARCHIVE);
2411 	gl_flare_intensity = ri.Cvar_Get("gl_flare_intensity", "1", CVAR_ARCHIVE);
2412 	gl_flare_maxdist = ri.Cvar_Get("gl_flare_maxdist", "150", CVAR_ARCHIVE);
2413 	gl_flare_scale = ri.Cvar_Get("gl_flare_scale", "1.5", CVAR_ARCHIVE);
2414 	gl_coloredlightmaps = ri.Cvar_Get( "gl_coloredlightmaps", "1", 0);
2415 
2416 	r_lefthand = ri.Cvar_Get("hand", "0", CVAR_USERINFO | CVAR_ARCHIVE);
2417 	r_norefresh = ri.Cvar_Get("r_norefresh", "0", 0);
2418 	r_fullbright = ri.Cvar_Get("r_fullbright", "0", 0);
2419 	r_drawentities = ri.Cvar_Get("r_drawentities", "1", 0);
2420 	r_drawworld = ri.Cvar_Get("r_drawworld", "1", 0);
2421 	r_novis = ri.Cvar_Get("r_novis", "0", 0);
2422 	r_nocull = ri.Cvar_Get("r_nocull", "0", 0);
2423 	r_lerpmodels = ri.Cvar_Get("r_lerpmodels", "1", 0);
2424 	r_model_lightlerp = ri.Cvar_Get("r_model_lightlerp", "1", 0);
2425 	r_model_alpha = ri.Cvar_Get("r_model_alpha", "0", 0);
2426 	r_speeds = ri.Cvar_Get("r_speeds", "0", 0);
2427 	r_lightlevel = ri.Cvar_Get("r_lightlevel", "0", 0);
2428 	r_overbrightbits = ri.Cvar_Get("r_overbrightbits", "2", CVAR_ARCHIVE);
2429 	r_cellshading = ri.Cvar_Get("r_cellshading", "0", CVAR_ARCHIVE);
2430 	r_cellshading_width = ri.Cvar_Get("r_cellshading_width", "4", CVAR_ARCHIVE);
2431 
2432 	skydistance = ri.Cvar_Get("skydistance", "2300", CVAR_ARCHIVE);
2433 
2434 	vid_fullscreen = ri.Cvar_Get("vid_fullscreen", "1", CVAR_ARCHIVE);
2435 	vid_gamma = ri.Cvar_Get("vid_gamma", "1.0", CVAR_ARCHIVE);
2436 	vid_ref = ri.Cvar_Get("vid_ref", "q2glx", CVAR_ARCHIVE);
2437 
2438 	ri.Cmd_AddCommand("imagelist", GL_ImageList_f);
2439 	ri.Cmd_AddCommand("screenshot", GL_ScreenShot_f);
2440 	ri.Cmd_AddCommand("modellist", Mod_Modellist_f);
2441 	ri.Cmd_AddCommand("gl_strings", GL_Strings_f);
2442 	ri.Cmd_AddCommand("pngshot", GL_ScreenShot_PNG);
2443 }
2444 
2445 /*
2446  * ================== R_SetMode ==================
2447  */
2448 qboolean
R_SetMode(void)2449 R_SetMode(void)
2450 {
2451 	rserr_t		err;
2452 	qboolean	fullscreen;
2453 
2454 	fullscreen = vid_fullscreen->value;
2455 
2456 	skydistance->modified = true;	/* DMP skybox size change */
2457 	vid_fullscreen->modified = false;
2458 	gl_mode->modified = false;
2459 	gl_coloredlightmaps->modified = false;
2460 
2461 	if ((err = GLimp_SetMode(&vid.width, &vid.height, gl_mode->value, fullscreen)) == rserr_ok) {
2462 		gl_state.prev_mode = gl_mode->value;
2463 	} else {
2464 		if (err == rserr_invalid_fullscreen) {
2465 			ri.Cvar_SetValue("vid_fullscreen", 0);
2466 			vid_fullscreen->modified = false;
2467 			ri.Con_Printf(PRINT_ALL, "Video ref::R_SetMode() - fullscreen unavailable in this mode\n");
2468 			if ((err = GLimp_SetMode(&vid.width, &vid.height, gl_mode->value, false)) == rserr_ok)
2469 				return true;
2470 		} else if (err == rserr_invalid_mode) {
2471 			ri.Cvar_SetValue("gl_mode", gl_state.prev_mode);
2472 			gl_mode->modified = false;
2473 			ri.Con_Printf(PRINT_ALL, "Video ref::R_SetMode() - invalid mode\n");
2474 		}
2475 		/* try setting it back to something safe */
2476 		if ((err = GLimp_SetMode(&vid.width, &vid.height, gl_state.prev_mode, false)) != rserr_ok) {
2477 			ri.Con_Printf(PRINT_ALL, "Video ref::R_SetMode() - could not revert to safe mode\n");
2478 			return false;
2479 		}
2480 	}
2481 	return true;
2482 }
2483 
2484 /*
2485  * =============== R_Init ===============
2486  */
2487 
2488 int
R_Init(void * hinstance,void * hWnd)2489 R_Init(void *hinstance, void *hWnd)
2490 {
2491 	char		renderer_buffer[1000];
2492 	char		vendor_buffer[1000];
2493 	int		err;
2494 	int		j;
2495 	extern float	r_turbsin[256];
2496 	int		init_time;
2497 
2498 	init_time = Sys_Milliseconds();
2499 
2500 	for (j = 0; j < 256; j++) {
2501 		r_turbsin[j] *= 0.5;
2502 	}
2503 
2504 	ri.Con_Printf(PRINT_ALL, "Video ref version: " REF_VERSION "\n");
2505 
2506 	Draw_GetPalette();
2507 
2508 	R_Register();
2509 
2510 	VLight_Init();
2511 
2512 	/* initialize our QGL dynamic bindings */
2513 	if (!QGL_Init(gl_driver->string)) {
2514 		QGL_Shutdown();
2515 		ri.Con_Printf(PRINT_ALL, "Video ref::R_Init() - could not load \"%s\"\n", gl_driver->string);
2516 		return -1;
2517 	}
2518 	/* initialize OS-specific parts of OpenGL */
2519 	if (!GLimp_Init(hinstance, hWnd)) {
2520 		QGL_Shutdown();
2521 		return -1;
2522 	}
2523 	/* set our "safe" modes */
2524 	gl_state.prev_mode = 3;
2525 
2526 	/* create the window and set up the context */
2527 	if (!R_SetMode()) {
2528 		QGL_Shutdown();
2529 		ri.Con_Printf(PRINT_ALL, "Video ref::R_Init() - could not R_SetMode()\n");
2530 		return -1;
2531 	}
2532 	ri.Vid_MenuInit();
2533 
2534 	/*
2535 	 * * get our various GL strings
2536 	 */
2537 	gl_config.vendor_string = (char *)qglGetString(GL_VENDOR);
2538 	ri.Con_Printf(PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string);
2539 	gl_config.renderer_string = (char *)qglGetString(GL_RENDERER);
2540 	ri.Con_Printf(PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string);
2541 	gl_config.version_string = (char *)qglGetString(GL_VERSION);
2542 	ri.Con_Printf(PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string);
2543 	gl_config.extensions_string = (char *)qglGetString(GL_EXTENSIONS);
2544 	ri.Con_Printf(PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string);
2545 
2546 	Q_strncpyz(renderer_buffer, gl_config.renderer_string, sizeof(renderer_buffer));
2547 	Q_strlwr(renderer_buffer);
2548 
2549 	Q_strncpyz(vendor_buffer, gl_config.vendor_string, sizeof(vendor_buffer));
2550 	Q_strlwr(vendor_buffer);
2551 
2552 	if (strcasecmp(renderer_buffer, "voodoo")) {
2553 		if (!strcasecmp(renderer_buffer, "rush"))
2554 			gl_config.renderer = GL_RENDERER_VOODOO;
2555 		else
2556 			gl_config.renderer = GL_RENDERER_VOODOO_RUSH;
2557 	} else if (strcasecmp(vendor_buffer, "sgi"))
2558 		gl_config.renderer = GL_RENDERER_SGI;
2559 	else if (strcasecmp(renderer_buffer, "permedia"))
2560 		gl_config.renderer = GL_RENDERER_PERMEDIA2;
2561 	else if (strcasecmp(renderer_buffer, "glint"))
2562 		gl_config.renderer = GL_RENDERER_GLINT_MX;
2563 	else if (strcasecmp(renderer_buffer, "glzicd"))
2564 		gl_config.renderer = GL_RENDERER_REALIZM;
2565 	else if (strcasecmp(renderer_buffer, "gdi"))
2566 		gl_config.renderer = GL_RENDERER_MCD;
2567 	else if (strcasecmp(renderer_buffer, "pcx2"))
2568 		gl_config.renderer = GL_RENDERER_PCX2;
2569 	else if (strcasecmp(renderer_buffer, "verite"))
2570 		gl_config.renderer = GL_RENDERER_RENDITION;
2571 	else
2572 		gl_config.renderer = GL_RENDERER_OTHER;
2573 
2574 	if (!(gl_monolightmap->string[1] == 'F' ||
2575 	    gl_monolightmap->string[1] == 'f')) {
2576 		if (gl_config.renderer == GL_RENDERER_PERMEDIA2) {
2577 			ri.Cvar_Set("gl_monolightmap", "A");
2578 			ri.Con_Printf(PRINT_ALL, "...using gl_monolightmap 'a'\n");
2579 		} else if (gl_config.renderer & GL_RENDERER_POWERVR) {
2580 			ri.Cvar_Set("gl_monolightmap", "0");
2581 		} else {
2582 			ri.Cvar_Set("gl_monolightmap", "0");
2583 		}
2584 	}
2585 
2586 	/* power vr can't have anything stay in the framebuffer, so */
2587 	/* the screen needs to redraw the tiled background every frame */
2588 	if (gl_config.renderer & GL_RENDERER_POWERVR) {
2589 		ri.Cvar_Set("scr_drawall", "1");
2590 	} else {
2591 		ri.Cvar_Set("scr_drawall", "0");
2592 	}
2593 
2594 #if defined (__unix__)
2595 	ri.Cvar_SetValue("gl_finish", 1);
2596 #endif
2597 
2598 	/* MCD has buffering issues */
2599 	if (gl_config.renderer == GL_RENDERER_MCD) {
2600 		ri.Cvar_SetValue("gl_finish", 1);
2601 	}
2602 	if (gl_config.renderer & GL_RENDERER_3DLABS) {
2603 		if (gl_3dlabs_broken->value)
2604 			gl_config.allow_cds = false;
2605 		else
2606 			gl_config.allow_cds = true;
2607 	} else {
2608 		gl_config.allow_cds = true;
2609 	}
2610 
2611 	if (gl_config.allow_cds)
2612 		ri.Con_Printf(PRINT_ALL, "...allowing CDS\n");
2613 	else
2614 		ri.Con_Printf(PRINT_ALL, "...disabling CDS\n");
2615 
2616 	/*
2617 	 * * grab extensions
2618 	 */
2619 	if (strstr(gl_config.extensions_string, "GL_EXT_compiled_vertex_array") ||
2620 	    strstr(gl_config.extensions_string, "GL_SGI_compiled_vertex_array")) {
2621 		ri.Con_Printf(PRINT_ALL, "...enabling GL_EXT_compiled_vertex_array\n");
2622 		qglLockArraysEXT = (void *)qwglGetProcAddress("glLockArraysEXT");
2623 		qglUnlockArraysEXT = (void *)qwglGetProcAddress("glUnlockArraysEXT");
2624 	} else {
2625 		ri.Con_Printf(PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n");
2626 	}
2627 
2628 	if (strstr(gl_config.extensions_string, "GL_EXT_point_parameters")) {
2629 		if (gl_ext_pointparameters->value) {
2630 			qglPointParameterfEXT = (void (APIENTRY *) (GLenum, GLfloat))qwglGetProcAddress("glPointParameterfEXT");
2631 			qglPointParameterfvEXT = (void (APIENTRY *) (GLenum, const GLfloat *))qwglGetProcAddress("glPointParameterfvEXT");
2632 			ri.Con_Printf(PRINT_ALL, "...using GL_EXT_point_parameters\n");
2633 		} else {
2634 			ri.Con_Printf(PRINT_ALL, "...ignoring GL_EXT_point_parameters\n");
2635 		}
2636 	} else {
2637 		ri.Con_Printf(PRINT_ALL, "...GL_EXT_point_parameters not found\n");
2638 	}
2639 
2640 	if (strstr(gl_config.extensions_string, "GL_ARB_multitexture")) {
2641 		if (gl_ext_multitexture->value) {
2642 			ri.Con_Printf(PRINT_ALL, "...using GL_ARB_multitexture\n");
2643 			qglMTexCoord2fSGIS = (void *)qwglGetProcAddress("glMultiTexCoord2fARB");
2644 			qglActiveTextureARB = (void *)qwglGetProcAddress("glActiveTextureARB");
2645 			qglClientActiveTextureARB = (void *)qwglGetProcAddress("glClientActiveTextureARB");
2646 			qglMultiTexCoord3fvARB = (void *)qwglGetProcAddress("glMultiTexCoord3fvARB");	/* mpo */
2647 
2648 			qglGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);/* MH - see how many
2649 										    * texture units card
2650 										    * supports */
2651 			GL_TEXTURE0 = GL_TEXTURE0_ARB;
2652 			GL_TEXTURE1 = GL_TEXTURE1_ARB;
2653 			GL_TEXTURE2 = GL_TEXTURE2_ARB;	/* MH - add extra
2654 							 * texture unit here */
2655 
2656 			ri.Con_Printf(PRINT_ALL, "Texture units available: %d\n", maxTextureUnits);
2657 		} else {
2658 			ri.Con_Printf(PRINT_ALL, "...ignoring GL_ARB_multitexture\n");
2659 		}
2660 	} else {
2661 		ri.Con_Printf(PRINT_ALL, "...GL_ARB_multitexture not found\n");
2662 	}
2663 
2664 	/* retreive information */
2665 	qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &gl_state.maxtexsize);
2666 	if (gl_state.maxtexsize <= 0)
2667 		gl_state.maxtexsize = 256;
2668 
2669 	Com_Printf("Maximum Texture Size: %ix%i\n", gl_state.maxtexsize, gl_state.maxtexsize);
2670 
2671 	if (strstr(gl_config.extensions_string, "GL_SGIS_multitexture")) {
2672 		if (qglActiveTextureARB) {
2673 			ri.Con_Printf(PRINT_ALL, "...GL_SGIS_multitexture deprecated in favor of ARB_multitexture\n");
2674 		} else if (gl_ext_multitexture->value) {
2675 			ri.Con_Printf(PRINT_ALL, "...using GL_SGIS_multitexture\n");
2676 			qglMTexCoord2fSGIS = (void *)qwglGetProcAddress("glMTexCoord2fSGIS");
2677 			qglSelectTextureSGIS = (void *)qwglGetProcAddress("glSelectTextureSGIS");
2678 
2679 			qglGetIntegerv(GL_MAX_TEXTURE_UNITS_SGIS, &maxTextureUnits);	/* MH - see how many
2680 											 * texture units card
2681 											 * supports */
2682 			GL_TEXTURE0 = GL_TEXTURE0_SGIS;
2683 			GL_TEXTURE1 = GL_TEXTURE1_SGIS;
2684 			GL_TEXTURE2 = GL_TEXTURE2_SGIS;	/* MH - add extra
2685 							 * texture unit */
2686 		} else {
2687 			ri.Con_Printf(PRINT_ALL, "...ignoring GL_SGIS_multitexture\n");
2688 		}
2689 	} else {
2690 		ri.Con_Printf(PRINT_ALL, "...GL_SGIS_multitexture not found\n");
2691 	}
2692 
2693 	if (strstr(gl_config.extensions_string, "GL_SGIS_generate_mipmap")) {
2694 		ri.Con_Printf(PRINT_ALL, "...using GL_SGIS_generate_mipmap\n");
2695 		gl_state.sgis_mipmap = true;
2696 	} else {
2697 		ri.Con_Printf(PRINT_ALL, "...GL_SGIS_generate_mipmap not found\n");
2698 		gl_state.sgis_mipmap = false;
2699 	}
2700 
2701 	/* Vic - begin */
2702 	gl_config.mtexcombine = false;
2703 
2704 	if (strstr(gl_config.extensions_string, "GL_ARB_texture_env_combine")) {
2705 		if (gl_ext_mtexcombine->value) {
2706 			Com_Printf("...using GL_ARB_texture_env_combine\n");
2707 			gl_config.mtexcombine = true;
2708 		} else {
2709 			Com_Printf("...ignoring GL_ARB_texture_env_combine\n");
2710 		}
2711 	} else {
2712 		Com_Printf("...GL_ARB_texture_env_combine not found\n");
2713 	}
2714 
2715 	if (!gl_config.mtexcombine) {
2716 		if (strstr(gl_config.extensions_string, "GL_EXT_texture_env_combine")) {
2717 			if (gl_ext_mtexcombine->value) {
2718 				Com_Printf("...using GL_EXT_texture_env_combine\n");
2719 				gl_config.mtexcombine = true;
2720 			} else {
2721 				Com_Printf("...ignoring GL_EXT_texture_env_combine\n");
2722 			}
2723 		} else {
2724 			Com_Printf("...GL_EXT_texture_env_combine not found\n");
2725 		}
2726 	}
2727 	/* Vic - end */
2728 
2729 	/* NeVo - Anisotropic Filtering Support */
2730 	gl_config.anisotropic = false;
2731 	if (strstr(gl_config.extensions_string, "GL_EXT_texture_filter_anisotropic")) {
2732 		ri.Con_Printf(PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic\n");
2733 		gl_config.anisotropic = true;
2734 		qglGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_config.max_anisotropy);
2735 		ri.Cvar_SetValue("gl_anisotropic_avail", gl_config.max_anisotropy);
2736 	} else {
2737 		ri.Con_Printf(PRINT_ALL, "..GL_EXT_texture_filter_anisotropic not found\n");
2738 		gl_config.anisotropic = false;
2739 		gl_config.max_anisotropy = 0.0;
2740 		ri.Cvar_SetValue("gl_anisotropic_avail", 0.0);
2741 	}
2742 	ri.Con_Printf(PRINT_ALL, "Maximum anisotropy level: %g\n", gl_config.max_anisotropy);
2743 
2744 	gl_state.nv_fog = false;
2745 
2746 	if (strstr(gl_config.extensions_string, "GL_NV_fog_distance")) {
2747 		if (!gl_nv_fog->value) {
2748 
2749 			ri.Con_Printf(PRINT_ALL, "...ignoring GL_NV_fog_distance\n");
2750 			gl_state.nv_fog = false;
2751 
2752 		} else {
2753 
2754 			ri.Con_Printf(PRINT_ALL, "...using GL_NV_fog_distance\n");
2755 			gl_state.nv_fog = true;
2756 		}
2757 
2758 	} else {
2759 		ri.Con_Printf(PRINT_ALL, "...GL_NV_fog_distance not found\n");
2760 		gl_state.nv_fog = false;
2761 		ri.Cvar_Set("gl_nv_fog", "0");
2762 
2763 	}
2764 
2765 	/*
2766 	 * ri.Con_Printf( PRINT_ALL, "Initializing NVIDIA-only extensions:\n" );
2767 	 */
2768 
2769 	if (strstr(gl_config.extensions_string, "GL_NV_texture_rectangle")) {
2770 		Com_Printf("...using GL_NV_texture_rectangle\n");
2771 		gl_state.tex_rectangle = true;
2772 	} else if (strstr(gl_config.extensions_string, "GL_EXT_texture_rectangle")) {
2773 		Com_Printf("...using GL_EXT_texture_rectangle\n");
2774 		gl_state.tex_rectangle = true;
2775 	} else {
2776 		Com_Printf("...GL_NV_texture_rectangle not found\n");
2777 		gl_state.tex_rectangle = false;
2778 	}
2779 
2780 	if (strstr(gl_config.extensions_string, "GL_NV_register_combiners")) {
2781 		ri.Con_Printf(PRINT_ALL, "...using GL_NV_register_combiners\n");
2782 
2783 		qglCombinerParameterfvNV = (PFNGLCOMBINERPARAMETERFVNVPROC) qwglGetProcAddress("glCombinerParameterfvNV");
2784 		qglCombinerParameterfNV = (PFNGLCOMBINERPARAMETERFNVPROC) qwglGetProcAddress("glCombinerParameterfNV");
2785 		qglCombinerParameterivNV = (PFNGLCOMBINERPARAMETERIVNVPROC) qwglGetProcAddress("glCombinerParameterivNV");
2786 		qglCombinerParameteriNV = (PFNGLCOMBINERPARAMETERINVPROC) qwglGetProcAddress("glCombinerParameteriNV");
2787 		qglCombinerInputNV = (PFNGLCOMBINERINPUTNVPROC) qwglGetProcAddress("glCombinerInputNV");
2788 		qglCombinerOutputNV = (PFNGLCOMBINEROUTPUTNVPROC) qwglGetProcAddress("glCombinerOutputNV");
2789 		qglFinalCombinerInputNV = (PFNGLFINALCOMBINERINPUTNVPROC) qwglGetProcAddress("glFinalCombinerInputNV");
2790 		qglGetCombinerInputParameterfvNV = (PFNGLGETCOMBINERINPUTPARAMETERFVNVPROC) qwglGetProcAddress("glGetCombinerInputParameterfvNV");
2791 		qglGetCombinerInputParameterivNV = (PFNGLGETCOMBINERINPUTPARAMETERIVNVPROC) qwglGetProcAddress("glGetCombinerInputParameterivNV");
2792 		qglGetCombinerOutputParameterfvNV = (PFNGLGETCOMBINEROUTPUTPARAMETERFVNVPROC) qwglGetProcAddress("glGetCombinerOutputParameterfvNV");
2793 		qglGetCombinerOutputParameterivNV = (PFNGLGETCOMBINEROUTPUTPARAMETERIVNVPROC) qwglGetProcAddress("glGetCombinerOutputParameterivNV");
2794 		qglGetFinalCombinerInputParameterfvNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERFVNVPROC) qwglGetProcAddress("glGetFinalCombinerInputParameterfvNV");
2795 		qglGetFinalCombinerInputParameterivNV = (PFNGLGETFINALCOMBINERINPUTPARAMETERIVNVPROC) qwglGetProcAddress("glGetFinalCombinerInputParameterivNV");
2796 
2797 		gl_state.reg_combiners = true;
2798 	} else {
2799 		ri.Con_Printf(PRINT_ALL, "...ignoring GL_NV_register_combiners\n");
2800 		gl_state.reg_combiners = false;
2801 	}
2802 
2803 	/* Texture Shader support - MrG */
2804 	if (strstr(gl_config.extensions_string, "GL_NV_texture_shader")) {
2805 		ri.Con_Printf(PRINT_ALL, "...using GL_NV_texture_shader\n");
2806 		gl_config.NV_texshaders = true;
2807 	} else {
2808 		ri.Con_Printf(PRINT_ALL, "...GL_NV_texture_shader not found\n");
2809 		gl_config.NV_texshaders = false;
2810 	}
2811 
2812 	if (strstr(gl_config.extensions_string, "GL_NV_multisample_filter_hint")) {
2813 		gl_config.GL_EXT_nv_multisample_filter_hint = true;
2814 		ri.Con_Printf(PRINT_ALL, "...using GL_NV_multisample_filter_hint\n");
2815 	} else {
2816 		ri.Con_Printf(PRINT_ALL, "...GL_NV_multisample_filter_hint not found\n");
2817 		gl_config.GL_EXT_nv_multisample_filter_hint = true;
2818 	}
2819 
2820 	if (strstr(gl_config.extensions_string, "GL_ARB_texture_compression")) {
2821 		if (!gl_ext_texture_compression->value) {
2822 			ri.Con_Printf(PRINT_ALL, "...ignoring GL_ARB_texture_compression\n");
2823 			gl_state.texture_compression = false;
2824 		} else {
2825 			ri.Con_Printf(PRINT_ALL, "...using GL_ARB_texture_compression\n");
2826 			gl_state.texture_compression = true;
2827 		}
2828 	} else {
2829 		ri.Con_Printf(PRINT_ALL, "...GL_ARB_texture_compression not found\n");
2830 		gl_state.texture_compression = false;
2831 		ri.Cvar_Set("gl_ext_texture_compression", "0");
2832 	}
2833 
2834 	/* mpo === jitwater */
2835 	if (strstr(gl_config.extensions_string, "GL_ARB_fragment_program")) {
2836 
2837 		if (maxTextureUnits >= 3 && (gl_reflection_fragment_program->value))
2838 			gl_state.fragment_program = true;
2839 
2840 		ri.Con_Printf(PRINT_ALL, "...using GL_ARB_fragment_program\n");
2841 
2842 		qglGenProgramsARB = (void *)qwglGetProcAddress("glGenProgramsARB");
2843 		qglDeleteProgramsARB = (void *)qwglGetProcAddress("glDeleteProgramsARB");
2844 		qglBindProgramARB = (void *)qwglGetProcAddress("glBindProgramARB");
2845 		qglProgramStringARB = (void *)qwglGetProcAddress("glProgramStringARB");
2846 		qglProgramEnvParameter4fARB = (void *)qwglGetProcAddress("glProgramEnvParameter4fARB");
2847 		qglProgramLocalParameter4fARB = (void *)qwglGetProcAddress("glProgramLocalParameter4fARB");
2848 
2849 		if (!gl_reflection_fragment_program->value) {
2850 			gl_state.fragment_program = false;
2851 			ri.Con_Printf(PRINT_ALL, "\x02" "GL_ARB_fragment_program available but disabled, set the variable gl_reflection_fragment_program to 1 and type vid_restart\n");
2852 		}
2853 
2854 		if (!(qglGenProgramsARB &&
2855 		      qglDeleteProgramsARB &&
2856 		      qglBindProgramARB &&
2857 		      qglProgramStringARB &&
2858 		      qglProgramEnvParameter4fARB &&
2859 		      qglProgramLocalParameter4fARB)) {
2860 				gl_state.fragment_program = false;
2861 				ri.Cvar_Set("gl_reflection_fragment_program", "0");
2862 				ri.Con_Printf(PRINT_ALL, "... Failed!  Fragment programs disabled\n");
2863 		}
2864 	}
2865 	else {
2866 		gl_state.fragment_program = false;
2867 		ri.Con_Printf(PRINT_ALL,"\x02" "GL_ARB_fragment_program not found\n");
2868 		ri.Con_Printf(PRINT_ALL,"\x02" "Don't try to run water distorsion, it will crash\n");
2869 	}
2870 	/* mpo === jitwater */
2871 
2872 	GL_SetDefaultState();
2873 
2874 	/*
2875 	 * * draw our stereo patterns
2876 	 */
2877 	/* #if 0 // commented out until H3D pays us the money they owe us */
2878 	GL_DrawStereoPattern();
2879 	/* #endif */
2880 
2881 	/* jitanisotropy(make sure nobody goes out of bounds) */
2882 	if (gl_anisotropic->value < 0)
2883 		ri.Cvar_Set("gl_anisotropic", "0");
2884 	else if (gl_anisotropic->value > gl_config.max_anisotropy)
2885 		ri.Cvar_SetValue("gl_anisotropic", gl_config.max_anisotropy);
2886 
2887 	if (gl_lightmap_texture_saturation->value > 1 || gl_lightmap_texture_saturation->value < 0)
2888 		ri.Cvar_Set("gl_lightmap_texture_saturation", "1");	/* jitsaturation */
2889 
2890 	GL_InitImages();
2891 	Mod_Init();
2892 	R_InitParticleTexture();
2893 	Draw_InitLocal();
2894 
2895 	ri.Con_Printf(PRINT_ALL, "-------------------------------\n");
2896 	ri.Con_Printf(PRINT_ALL, "\x02" "Render Initialised in: %.2fs\n", (Sys_Milliseconds() - init_time) * 0.001);
2897 	ri.Con_Printf(PRINT_ALL, "-------------------------------\n");
2898 
2899 	err = qglGetError();
2900 	if (err != GL_NO_ERROR)
2901 		ri.Con_Printf(PRINT_ALL, "glGetError() = 0x%x\n", err);
2902 
2903 	R_init_refl(gl_reflection_max->value);	/* MPO : init reflections */
2904 
2905 	return 0;
2906 }
2907 
2908 /*
2909  * =============== R_Shutdown ===============
2910  */
2911 void
R_Shutdown(void)2912 R_Shutdown(void)
2913 {
2914 	ri.Cmd_RemoveCommand("modellist");
2915 	ri.Cmd_RemoveCommand("screenshot");
2916 	ri.Cmd_RemoveCommand("imagelist");
2917 	ri.Cmd_RemoveCommand("gl_strings");
2918 	ri.Cmd_RemoveCommand ("pngshot");
2919 
2920 	Mod_FreeAll();
2921 
2922 	GL_ShutdownImages();
2923 
2924 	/*
2925 	 * * shut down OS specific OpenGL stuff like contexts, etc.
2926 	 */
2927 	GLimp_Shutdown();
2928 
2929 	/*
2930 	 * * shutdown our QGL subsystem
2931 	 */
2932 	QGL_Shutdown();
2933 
2934 	/*
2935 	 * * shutdown our reflective arrays
2936 	 */
2937 	R_shutdown_refl();
2938 }
2939 
2940 
2941 
2942 /*
2943  * @@@@@@@@@@@@@@@@@@@@@ R_BeginFrame @@@@@@@@@@@@@@@@@@@@@
2944  */
2945 void		RefreshFont(void);
2946 void
R_BeginFrame(float camera_separation)2947 R_BeginFrame(float camera_separation)
2948 {
2949 
2950 	gl_state.camera_separation = camera_separation;
2951 
2952 	if (font_color->modified) {
2953 		RefreshFont();
2954 	}
2955 
2956 	/*
2957 	 * * change modes if necessary
2958 	 */
2959 	if (gl_mode->modified || vid_fullscreen->modified || gl_coloredlightmaps->modified) {	/* FIXME: only restart if CDS is required */
2960 		cvar_t         *ref;
2961 
2962 		ref = ri.Cvar_Get("vid_ref", "q2glx", 0);
2963 		ref->modified = true;
2964 	}
2965 	if (gl_ext_nv_multisample_filter_hint->modified) {
2966 		gl_ext_nv_multisample_filter_hint->modified = false;
2967 
2968 		if (gl_config.GL_EXT_nv_multisample_filter_hint) {
2969 			if (!strcmp(gl_ext_nv_multisample_filter_hint->string, "nicest"))
2970 				qglHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
2971 			else
2972 				qglHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_FASTEST);
2973 		}
2974 	}
2975 	/* NiceAss: scale -Maniac */
2976 	if (cl_hudscale->modified) {
2977 		int		width     , height;
2978 
2979 		if (cl_hudscale->value < 1.0)
2980 			ri.Cvar_SetValue("cl_hudscale", 1.0);
2981 
2982 		/* get the current resolution */
2983 		ri.Vid_GetModeInfo(&width, &height, gl_mode->value);
2984 		/* lie to client about new scaled window size */
2985 		ri.Vid_NewWindow(width / cl_hudscale->value, height / cl_hudscale->value);
2986 
2987 		cl_hudscale->modified = false;
2988 	}
2989 	if (gl_log->modified) {
2990 		GLimp_EnableLogging(gl_log->value);
2991 		gl_log->modified = false;
2992 	}
2993 	if (gl_log->value) {
2994 		GLimp_LogNewFrame();
2995 	}
2996 
2997 	/*
2998 	 * * update 3Dfx gamma -- it is expected that a user will do a
2999 	 * vid_restart * after tweaking this value
3000 	 */
3001 	if (vid_gamma->modified) {
3002 		vid_gamma->modified = false;
3003 
3004 		if (gl_state.hwgamma) {
3005 			UpdateHardwareGamma();
3006 		} else if (gl_config.renderer & (GL_RENDERER_VOODOO)) {
3007 			char		envbuffer[1024];
3008 			float		g;
3009 
3010 			g = 2.00 * (0.8 - (vid_gamma->value - 0.5)) + 1.0;
3011 			Com_sprintf(envbuffer, sizeof(envbuffer), "SSTV2_GAMMA=%f", g);
3012 			putenv(envbuffer);
3013 			Com_sprintf(envbuffer, sizeof(envbuffer), "SST_GAMMA=%f", g);
3014 			putenv(envbuffer);
3015 		}
3016 	}
3017 #ifdef QMAX
3018 	if (gl_particlelighting->modified) {
3019 		gl_particlelighting->modified = false;
3020 		if (gl_particlelighting->value < 0)
3021 			gl_particlelighting->value = 0;
3022 		if (gl_particlelighting->value > 1)
3023 			gl_particlelighting->value = 1;
3024 	}
3025 #endif
3026 
3027 	GLimp_BeginFrame(camera_separation);
3028 
3029 	/*
3030 	 * * go into 2D mode
3031 	 */
3032 	qglViewport(0, 0, vid.width, vid.height);
3033 	qglMatrixMode(GL_PROJECTION);
3034 	qglLoadIdentity();
3035 	/* NiceAss: Scale the screen */
3036 	qglOrtho(0, vid.width / cl_hudscale->value, vid.height / cl_hudscale->value, 0, -99999, 99999);
3037 	/* qglOrtho  (0, vid.width, vid.height, 0, -99999, 99999); */
3038 	qglMatrixMode(GL_MODELVIEW);
3039 	qglLoadIdentity();
3040 	qglDisable(GL_DEPTH_TEST);
3041 	qglDisable(GL_CULL_FACE);
3042 	qglDisable(GL_BLEND);
3043 	qglEnable(GL_ALPHA_TEST);
3044 	qglColor4f(1, 1, 1, 1);
3045 
3046 	/*
3047 	 * * draw buffer stuff
3048 	 */
3049 	if (gl_drawbuffer->modified) {
3050 		gl_drawbuffer->modified = false;
3051 
3052 		if (gl_state.camera_separation == 0 || !gl_state.stereo_enabled) {
3053 			if (Q_stricmp(gl_drawbuffer->string, "GL_FRONT") == 0)
3054 				qglDrawBuffer(GL_FRONT);
3055 			else
3056 				qglDrawBuffer(GL_BACK);
3057 		}
3058 	}
3059 
3060 	/*
3061 	 * * texturemode stuff
3062 	 */
3063 	if (gl_texturemode->modified) {
3064 		GL_TextureMode(gl_texturemode->string);
3065 		gl_texturemode->modified = false;
3066 	}
3067 	if (gl_texturealphamode->modified) {
3068 		GL_TextureAlphaMode(gl_texturealphamode->string);
3069 		gl_texturealphamode->modified = false;
3070 	}
3071 	if (gl_texturesolidmode->modified) {
3072 		GL_TextureSolidMode(gl_texturesolidmode->string);
3073 		gl_texturesolidmode->modified = false;
3074 	}
3075 
3076 	/* clear screen if desired */
3077 	R_Clear();
3078 }
3079 
3080 /*
3081  * ============= R_SetPalette =============
3082  */
3083 unsigned	r_rawpalette[256];
3084 
3085 void
R_SetPalette(const unsigned char * palette)3086 R_SetPalette(const unsigned char *palette)
3087 {
3088 	int		i;
3089 
3090 	byte           *rp = (byte *) r_rawpalette;
3091 
3092 	if (palette) {
3093 		for (i = 0; i < 256; i++) {
3094 			rp[i * 4 + 0] = palette[i * 3 + 0];
3095 			rp[i * 4 + 1] = palette[i * 3 + 1];
3096 			rp[i * 4 + 2] = palette[i * 3 + 2];
3097 			rp[i * 4 + 3] = 0xff;
3098 		}
3099 	} else {
3100 		for (i = 0; i < 256; i++) {
3101 #ifdef QMAX
3102 			rp[i * 4 + 0] = d_8to24table[i] & 0xff;
3103 			rp[i * 4 + 1] = (d_8to24table[i] >> 8) & 0xff;
3104 			rp[i * 4 + 2] = (d_8to24table[i] >> 16) & 0xff;
3105 #else
3106 			rp[i * 4 + 0] = LittleLong(d_8to24table[i]) & 0xff;
3107 			rp[i * 4 + 1] = (LittleLong(d_8to24table[i]) >> 8) & 0xff;
3108 			rp[i * 4 + 2] = (LittleLong(d_8to24table[i]) >> 16) & 0xff;
3109 #endif
3110 			rp[i * 4 + 3] = 0xff;
3111 		}
3112 	}
3113 #ifndef QMAX
3114 	GL_SetTexturePalette(r_rawpalette);
3115 #endif
3116 
3117 	qglClearColor(0, 0, 0, 0);
3118 	qglClear(GL_COLOR_BUFFER_BIT);
3119 	qglClearColor(1, 0, 0.5, 0.5);
3120 
3121 }
3122 
3123 /*
3124  * * R_DrawBeam
3125  */
3126 #ifdef QMAX
3127 void		R_RenderBeam(vec3_t start, vec3_t end, float size, float red, float green, float blue, float alpha);
3128 void
R_DrawBeam(entity_t * e)3129 R_DrawBeam(entity_t * e)
3130 {
3131 
3132 	R_RenderBeam(e->origin, e->oldorigin, e->frame,
3133 	    (d_8to24table[e->skinnum & 0xFF]) & 0xFF,
3134 	    (d_8to24table[e->skinnum & 0xFF] >> 8) & 0xFF,
3135 	    (d_8to24table[e->skinnum & 0xFF] >> 16) & 0xFF,
3136 	    e->alpha * 254);
3137 }
3138 
3139 void
R_RenderBeam(vec3_t start,vec3_t end,float size,float red,float green,float blue,float alpha)3140 R_RenderBeam(vec3_t start, vec3_t end, float size, float red, float green, float blue, float alpha)
3141 {
3142 	float		len;
3143 	vec3_t		coord[4], ang_up, ang_right, vdelta;
3144 
3145 	GL_TexEnv(GL_MODULATE);
3146 	qglDepthMask(false);
3147 	qglBlendFunc(GL_SRC_ALPHA, GL_ONE);
3148 	qglEnable(GL_BLEND);
3149 	qglShadeModel(GL_SMOOTH);
3150 	GL_Bind(r_particlebeam->texnum);
3151 	qglColor4ub(red, green, blue, alpha);
3152 
3153 	VectorSubtract(start, end, ang_up);
3154 	len = VectorNormalize(ang_up);
3155 
3156 	VectorSubtract(r_refdef.vieworg, start, vdelta);
3157 	CrossProduct(ang_up, vdelta, ang_right);
3158 	if (!VectorCompare(ang_right, vec3_origin))
3159 		VectorNormalize(ang_right);
3160 
3161 	VectorScale(ang_right, size * 3.0, ang_right);
3162 
3163 	VectorAdd(start, ang_right, coord[0]);
3164 	VectorAdd(end, ang_right, coord[1]);
3165 	VectorSubtract(end, ang_right, coord[2]);
3166 	VectorSubtract(start, ang_right, coord[3]);
3167 
3168 	qglPushMatrix();
3169 	{
3170 		qglBegin(GL_QUADS);
3171 		{
3172 			qglTexCoord2f(0, 1);
3173 			qglVertex3fv(coord[0]);
3174 			qglTexCoord2f(0, 0);
3175 			qglVertex3fv(coord[1]);
3176 			qglTexCoord2f(1, 0);
3177 			qglVertex3fv(coord[2]);
3178 			qglTexCoord2f(1, 1);
3179 			qglVertex3fv(coord[3]);
3180 		}
3181 		qglEnd();
3182 	}
3183 	qglPopMatrix();
3184 
3185 	qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
3186 	GL_TexEnv(GL_MODULATE);
3187 	qglDepthMask(true);
3188 	qglDisable(GL_BLEND);
3189 	qglColor4f(1, 1, 1, 1);
3190 }
3191 
3192 #else
3193 void
R_DrawBeam(entity_t * e)3194 R_DrawBeam(entity_t * e)
3195 {
3196 #define NUM_BEAM_SEGS 6
3197 
3198 	int		i;
3199 	float		r       , g, b;
3200 
3201 	vec3_t		perpvec;
3202 	vec3_t		direction, normalized_direction;
3203 	vec3_t		start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS];
3204 	vec3_t		oldorigin, origin;
3205 
3206 	oldorigin[0] = e->oldorigin[0];
3207 	oldorigin[1] = e->oldorigin[1];
3208 	oldorigin[2] = e->oldorigin[2];
3209 
3210 	origin[0] = e->origin[0];
3211 	origin[1] = e->origin[1];
3212 	origin[2] = e->origin[2];
3213 
3214 	normalized_direction[0] = direction[0] = oldorigin[0] - origin[0];
3215 	normalized_direction[1] = direction[1] = oldorigin[1] - origin[1];
3216 	normalized_direction[2] = direction[2] = oldorigin[2] - origin[2];
3217 
3218 	if (VectorNormalize(normalized_direction) == 0)
3219 		return;
3220 
3221 	PerpendicularVector(perpvec, normalized_direction);
3222 	VectorScale(perpvec, e->frame / 2, perpvec);
3223 
3224 	for (i = 0; i < 6; i++) {
3225 		RotatePointAroundVector(start_points[i], normalized_direction, perpvec, (360.0 / NUM_BEAM_SEGS) * i);
3226 		VectorAdd(start_points[i], origin, start_points[i]);
3227 		VectorAdd(start_points[i], direction, end_points[i]);
3228 	}
3229 
3230 	qglDisable(GL_TEXTURE_2D);
3231 	qglEnable(GL_BLEND);
3232 	qglDepthMask(GL_FALSE);
3233 
3234 	r = (LittleLong(d_8to24table[e->skinnum & 0xFF])) & 0xFF;
3235 	g = (LittleLong(d_8to24table[e->skinnum & 0xFF]) >> 8) & 0xFF;
3236 	b = (LittleLong(d_8to24table[e->skinnum & 0xFF]) >> 16) & 0xFF;
3237 
3238 	r *= 1 / 255.0;
3239 	g *= 1 / 255.0;
3240 	b *= 1 / 255.0;
3241 
3242 	qglColor4f(r, g, b, e->alpha);
3243 
3244 	qglBegin(GL_TRIANGLE_STRIP);
3245 	for (i = 0; i < NUM_BEAM_SEGS; i++) {
3246 		qglVertex3fv(start_points[i]);
3247 		qglVertex3fv(end_points[i]);
3248 		qglVertex3fv(start_points[(i + 1) % NUM_BEAM_SEGS]);
3249 		qglVertex3fv(end_points[(i + 1) % NUM_BEAM_SEGS]);
3250 	}
3251 	qglEnd();
3252 
3253 	qglEnable(GL_TEXTURE_2D);
3254 	qglDisable(GL_BLEND);
3255 	qglDepthMask(GL_TRUE);
3256 }
3257 
3258 #endif
3259 /* =================================================================== */
3260 
3261 
3262 void		R_BeginRegistration(char *map);
3263 struct model_s *R_RegisterModel(char *name);
3264 struct image_s *R_RegisterSkin(char *name);
3265 void		R_SetSky  (char *name, float rotate, vec3_t axis);
3266 void		R_EndRegistration(void);
3267 
3268 void		R_RenderFrame(refdef_t * fd);
3269 
3270 struct image_s *Draw_FindPic(char *name);
3271 
3272 void		Draw_ScaledPic(int x, int y, float scale, float alpha, char *pic, float red, float green, float blue, qboolean fixcoords, qboolean repscale);
3273 void		Draw_Pic  (int x, int y, char *name, float alpha);
3274 void		Draw_Char (int x, int y, int num, int alpha);
3275 void		Draw_TileClear(int x, int y, int w, int h, char *name);
3276 void		Draw_Fill (int x, int y, int w, int h, int c);
3277 void		Draw_FadeScreen(void);
3278 
3279 #ifdef QMAX
3280 void		SetParticlePicture(int num, char *name);
3281 
3282 #endif
3283 
3284 /*
3285  * @@@@@@@@@@@@@@@@@@@@@ GetRefAPI
3286  *
3287  * @@@@@@@@@@@@@@@@@@@@@
3288  */
3289 refexport_t
GetRefAPI(refimport_t rimp)3290 GetRefAPI(refimport_t rimp)
3291 {
3292 	refexport_t	re;
3293 
3294 	ri = rimp;
3295 
3296 	re.api_version = API_VERSION;
3297 
3298 	re.BeginRegistration = R_BeginRegistration;
3299 	re.RegisterModel = R_RegisterModel;
3300 	re.RegisterSkin = R_RegisterSkin;
3301 	re.RegisterPic = Draw_FindPic;
3302 	re.SetSky = R_SetSky;
3303 	re.EndRegistration = R_EndRegistration;
3304 
3305 	re.RenderFrame = R_RenderFrame;
3306 #ifdef QMAX
3307 	re.SetParticlePicture = SetParticlePicture;
3308 #endif
3309 
3310 	re.DrawGetPicSize = Draw_GetPicSize;
3311 	re.DrawScaledPic = Draw_ScaledPic;
3312 	re.DrawPic = Draw_Pic;
3313 	re.DrawStretchPic = Draw_StretchPic;
3314 	re.DrawChar = Draw_Char;
3315 	re.DrawTileClear = Draw_TileClear;
3316 	re.DrawFill = Draw_Fill;
3317 	re.DrawFadeScreen = Draw_FadeScreen;
3318 
3319 	re.DrawStretchRaw = Draw_StretchRaw;
3320 
3321 	re.Init = R_Init;
3322 	re.Shutdown = R_Shutdown;
3323 
3324 	re.CinematicSetPalette = R_SetPalette;
3325 	re.BeginFrame = R_BeginFrame;
3326 	re.EndFrame = GLimp_EndFrame;
3327 
3328 	re.AppActivate = GLimp_AppActivate;
3329 
3330 	re.AddDecal = R_AddDecal;
3331 
3332 	Swap_Init();
3333 
3334 	return re;
3335 }
3336 
3337 
3338 #ifndef REF_HARD_LINKED
3339 /* this is only here so the functions in q_shared.c and q_shwin.c can link */
3340 void
Sys_Error(char * error,...)3341 Sys_Error(char *error,...)
3342 {
3343 	va_list		argptr;
3344 	char		text[1024];
3345 
3346 	va_start(argptr, error);
3347 	vsprintf(text, error, argptr);
3348 	va_end(argptr);
3349 
3350 	ri.Sys_Error(ERR_FATAL, "%s", text);
3351 }
3352 
3353 void
Com_Printf(char * fmt,...)3354 Com_Printf(char *fmt,...)
3355 {
3356 	va_list		argptr;
3357 	char		text[1024];
3358 
3359 	va_start(argptr, fmt);
3360 	vsprintf(text, fmt, argptr);
3361 	va_end(argptr);
3362 
3363 	ri.Con_Printf(PRINT_ALL, "%s", text);
3364 }
3365 
3366 #endif
3367