1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 // r_main.c
21 
22 #include "quakedef.h"
23 
24 entity_t	r_worldentity;
25 
26 qboolean	r_cache_thrash;		// compatability
27 
28 vec3_t		modelorg, r_entorigin;
29 entity_t	*currententity;
30 
31 int			r_visframecount;	// bumped when going to a new PVS
32 int			r_framecount;		// used for dlight push checking
33 int			r_lightTimestamp;	// PENTA: incresed when next light is started
34 
35 mplane_t	frustum[4];
36 
37 int			c_brush_polys, c_alias_polys;
38 
39 qboolean	envmap;				// true during envmap command capture
40 
41 int			currenttexture = -1;		// to avoid unnecessary texture sets
42 
43 int			cnttextures[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };     // cached
44 
45 int			particletexture;	// little dot for particles
46 int			particletexture_smoke;
47 int			particletexture_glow;
48 int			particletexture_glow2;
49 int			particletexture_tele;
50 int			particletexture_blood;
51 int			particletexture_dirblood;
52 int			playertextures;		// up to 16 color translated skins
53 
54 int			mirrortexturenum;	// quake texturenum, not gltexturenum
55 qboolean	mirror;
56 qboolean	glare;
57 mplane_t	*mirror_plane;
58 mplane_t	mirror_far_plane; //far plane of the view frustum for mirrors
59 int			mirror_clipside;
60 msurface_t	*causticschain;
61 int			caustics_textures[8];
62 qboolean	busy_caustics = false;
63 
64 //
65 // view origin
66 //
67 vec3_t	vup;
68 vec3_t	vpn;
69 vec3_t	vright;
70 vec3_t	r_origin;
71 
72 float	r_projection_matrix[16];
73 float	r_world_matrix[16];
74 float	r_base_world_matrix[16];
75 double	r_Dproject_matrix[16];//PENTA
76 double	r_Dworld_matrix[16];//PENTA
77 int		r_Iviewport[4];//PENTA
78 int		numClearsSaved;//PENTA
79 
80 float color_black[4] = {0.0, 0.0, 0.0, 0.0};
81 
82 //
83 // screen size info
84 //
85 refdef_t	r_refdef;
86 
87 mleaf_t		*r_viewleaf, *r_oldviewleaf;
88 
89 texture_t	*r_notexture_mip;
90 
91 int		d_lightstylevalue[256];	// 8.8 fraction of base light value
92 
93 
94 void R_MarkLeaves (void);
95 void R_Clear (void);
96 
97 cvar_t	r_norefresh = {"r_norefresh","0"};
98 cvar_t	r_drawentities = {"r_drawentities","1"};
99 cvar_t	r_drawviewmodel = {"r_drawviewmodel","1"};
100 cvar_t	r_fullbright = {"r_fullbright","0"};
101 cvar_t	r_lightmap = {"r_lightmap","0"};
102 cvar_t	r_shadows = {"r_shadows","0"};
103 //cvar_t	r_mirroralpha = {"r_mirroralpha","1"};
104 cvar_t	r_wateralpha = {"r_wateralpha","0.5"};//PENTA: different default
105 cvar_t	r_dynamic = {"r_dynamic","1"};
106 cvar_t	r_novis = {"r_novis","0"};
107 
108 cvar_t	gl_finish = {"gl_finish","0"};
109 cvar_t	gl_clear = {"gl_clear","0"};
110 cvar_t	gl_cull = {"gl_cull","1"};
111 //cvar_t	gl_texsort = {"gl_texsort","1"};
112 cvar_t	gl_smoothmodels = {"gl_smoothmodels","1"};
113 cvar_t	gl_affinemodels = {"gl_affinemodels","0"};
114 cvar_t	gl_polyblend = {"gl_polyblend","1"};
115 cvar_t	gl_flashblend = {"gl_flashblend","1"};
116 cvar_t	gl_playermip = {"gl_playermip","0"};
117 cvar_t	gl_nocolors = {"gl_nocolors","0"};
118 //cvar_t	gl_keeptjunctions = {"gl_keeptjunctions","0"}; PENTA: Don't remove t-junctions
119 cvar_t	gl_reporttjunctions = {"gl_reporttjunctions","0"};
120 cvar_t	gl_doubleeyes = {"gl_doubleeys", "1"};
121 
122 cvar_t	gl_watershader = {"gl_watershader","1"};//PENTA: water shaders ON/OFF
123 cvar_t	gl_calcdepth = {"gl_calcdepth","0"};
124 
125 cvar_t	sh_lightmapbright = {"sh_lightmapbright","0.5"};//PENTA: brightness of lightmaps
126 cvar_t	sh_radiusscale = {"sh_radiusscale","0.5"};//PENTA: brightness of lightmaps
127 cvar_t	sh_visiblevolumes = {"sh_visiblevolumes","0"};//PENTA: draw shadow volumes on/off
128 cvar_t  sh_entityshadows = {"sh_entityshadows","1"};//PENTA: entities cast shadows on/off
129 cvar_t  sh_worldshadows = {"sh_worldshadows","1"};//PENTA: brushes cast shadows on/off
130 cvar_t  sh_showlightnum = {"sh_showlightnum","0"};//PENTA: draw numer of lights used this frame
131 cvar_t  sh_glows = {"sh_glows","1"};//PENTA: draw glows around some light sources
132 cvar_t	sh_fps = {"sh_fps","0", true};	// set for running times - muff
133 cvar_t	sh_debuginfo = {"sh_debuginfo","0"};
134 cvar_t	sh_norevis = {"sh_norevis","0"};//PENTA: no recalculating the vis for light positions
135 cvar_t	sh_nosvbsp = {"sh_nosvbsp","0"};//PENTA: no shadow bsp
136 cvar_t	sh_noeclip = {"sh_noeclip","0"};//PENTA: no entity/leaf clipping for shadows
137 cvar_t  sh_infinitevolumes = {"sh_infinitevolumes","0", true};//PENTA: Nvidia infinite volumes
138 cvar_t  sh_noscissor = {"sh_noscissor","0"};//PENTA: no scissoring
139 cvar_t	sh_nocleversave = {"sh_nocleversave","0"};//PENTA: don't change light drawing order to reduce stencil clears
140 cvar_t	sh_bumpmaps = {"sh_bumpmaps","1"};//PENTA: enable disable bump mapping
141 cvar_t	sh_colormaps = {"sh_colormaps","1"};//PENTA: enable disable textures on the world (light will remain)
142 cvar_t	sh_playershadow = {"sh_playershadow","1"};//PENTA: the player casts a shadow (the one YOU are playing with, others always cast shadows)
143 cvar_t	sh_nocache = {"sh_nocache","0"};
144 cvar_t	sh_glares = {"sh_glares","0",true};
145 cvar_t	sh_noefrags = {"sh_noefrags","0",true};
146 cvar_t	sh_showtangent = {"sh_showtangent","0"};
147 cvar_t	sh_noshadowpopping = {"sh_noshadowpopping","1"};
148 
149 cvar_t	mir_detail = {"mir_detail","1",true};
150 cvar_t	mir_frameskip = {"mir_frameskip","1",true};
151 cvar_t	mir_forcewater = {"mir_forcewater","0"};
152 cvar_t	mir_distance = {"mir_distance","400",true};
153 cvar_t  gl_wireframe = {"gl_wireframe","0"};
154 cvar_t  gl_caustics = {"gl_caustics","1"};
155 cvar_t  gl_truform = {"gl_truform","0"};
156 cvar_t  gl_truform_tesselation = {"gl_truform_tesselation","4"};
157 cvar_t	gl_transformlerp = {"gl_transformlerp","0",true};//Erad - transform interpolation cvar (off by default due to bugs)
158 
159 cvar_t	fog_r = {"fog_r","0.2"};
160 cvar_t	fog_g = {"fog_g","0.1"};
161 cvar_t	fog_b = {"fog_b","0.0"};
162 cvar_t	fog_start = {"fog_start","256"};
163 cvar_t	fog_end = {"fog_end","700"};
164 cvar_t	fog_enabled = {"fog_enabled","1"};
165 cvar_t  fog_waterfog = {"fog_waterfog","1"};
166 float fog_color[4];
167 
168 mirrorplane_t mirrorplanes[NUM_MIRROR_PLANES];
169 int mirror_contents;
170 
171 #ifndef GL_ATI_pn_triangles
172 #define GL_PN_TRIANGLES_ATI                       0x87F0
173 #define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
174 #define GL_PN_TRIANGLES_POINT_MODE_ATI            0x87F2
175 #define GL_PN_TRIANGLES_NORMAL_MODE_ATI           0x87F3
176 #define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI     0x87F4
177 #define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI     0x87F5
178 #define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI      0x87F6
179 #define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI    0x87F7
180 #define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
181 
182 typedef void (APIENTRY *PFNGLPNTRIANGLESIATIPROC)(GLenum pname, GLint param);
183 typedef void (APIENTRY *PFNGLPNTRIANGLESFATIPROC)(GLenum pname, GLfloat param);
184 #endif
185 
186 // actually in gl_bumpradeon (duh...)
187 extern PFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI;
188 extern PFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI;
189 
190 #define GL_INCR_WRAP_EXT                                        0x8507
191 #define GL_DECR_WRAP_EXT                                        0x8508
192 
193 
194 #define	MIN_PLAYER_MIRROR 48 //max size of player bounding box
195 
196 //extern	cvar_t	gl_ztrick; PENTA: Removed
197 
198 /*
199 =================
200 R_CullBox
201 
202 Returns true if the box is completely outside the frustom
203 =================
204 */
R_CullBox(vec3_t mins,vec3_t maxs)205 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
206 {
207 	int		i;
208 
209 	for (i=0 ; i<4 ; i++)
210 		if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
211 			return true;
212 	return false;
213 }
214 
215 
216 /*
217 =============
218 R_RotateForEntity
219 
220 Erad - transform interpolation
221 =============
222 */
R_RotateForEntity(entity_t * e)223 void R_RotateForEntity (entity_t *e)
224 {
225 	float timepassed;
226 	float blend;
227 	vec3_t d;
228 	int i;
229 
230 	//Hack to stop t lerping view models and player - Eradicator
231     if ((!strcmp (e->model->name, "progs/v_shot.mdl")) || (!strcmp (e->model->name, "progs/v_shot2.mdl"))
232 		|| (!strcmp (e->model->name, "progs/v_nail.mdl")) || (!strcmp (e->model->name, "progs/v_nail2.mdl"))
233         || (!strcmp (e->model->name, "progs/v_rock.mdl")) || (!strcmp (e->model->name, "progs/v_rock2.mdl"))
234         || (!strcmp (e->model->name, "progs/v_axe.mdl")) || (!strcmp (e->model->name, "progs/v_light.mdl"))
235 		|| (!strcmp (e->model->name, "progs/players.mdl")) || (!gl_transformlerp.value))
236     {
237 		R_UnlerpedRotateForEntity(e);
238 		return;
239 	}
240 
241     timepassed = realtime - e->translate_start_time;
242 
243     if (e->translate_start_time == 0 || timepassed > 1)
244     {
245 		e->translate_start_time = realtime;
246 		VectorCopy (e->origin, e->origin1);
247 		VectorCopy (e->origin, e->origin2);
248 	}
249 
250 	if (!VectorCompare (e->origin, e->origin2))
251 	{
252 		e->translate_start_time = realtime;
253 		VectorCopy (e->origin2, e->origin1);
254 		VectorCopy (e->origin,  e->origin2);
255 		blend = 0;
256 	}
257 	else
258 	{
259 		blend =  timepassed / 0.1;
260 
261 		if (cl.paused || blend > 1) blend = 1;
262 	}
263 
264 	VectorSubtract (e->origin2, e->origin1, d);
265 
266 	glTranslatef (
267 		e->origin1[0] + (blend * d[0]),
268 		e->origin1[1] + (blend * d[1]),
269 		e->origin1[2] + (blend * d[2]));
270 
271 	timepassed = realtime - e->rotate_start_time;
272 
273 	if (e->rotate_start_time == 0 || timepassed > 1)
274 	{
275 		e->rotate_start_time = realtime;
276 		VectorCopy (e->angles, e->angles1);
277 		VectorCopy (e->angles, e->angles2);
278 	}
279 
280 	if (!VectorCompare (e->angles, e->angles2))
281 	{
282 		e->rotate_start_time = realtime;
283 		VectorCopy (e->angles2, e->angles1);
284 		VectorCopy (e->angles,  e->angles2);
285 		blend = 0;
286 	}
287 	else
288 	{
289 		blend = timepassed / 0.1;
290 
291 		if (cl.paused || blend > 1) blend = 1;
292 		}
293 			VectorSubtract (e->angles2, e->angles1, d);
294 
295              for (i = 0; i < 3; i++)
296              {
297                  if (d[i] > 180)
298                  {
299                      d[i] -= 360;
300                  }
301                  else if (d[i] < -180)
302                  {
303                      d[i] += 360;
304                  }
305 			}
306 		glRotatef ( e->angles1[1] + ( blend * d[1]),  0, 0, 1);
307 		glRotatef (-e->angles1[0] + (-blend * d[0]),  0, 1, 0);
308 		glRotatef ( e->angles1[2] + ( blend * d[2]),  1, 0, 0);
309 	}
310 
R_UnlerpedRotateForEntity(entity_t * e)311 void R_UnlerpedRotateForEntity (entity_t *e)
312 {
313     glTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
314 
315     glRotatef (e->angles[1],  0, 0, 1);
316     glRotatef (-e->angles[0],  0, 1, 0);
317     glRotatef (e->angles[2],  1, 0, 0);
318 }
319 
CL_PointContents(vec3_t p)320 int CL_PointContents (vec3_t p)
321 {
322 	int		cont;
323 
324 	cont = SV_HullPointContents (&cl.worldmodel->hulls[0], 0, p);
325 	if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN)
326 		cont = CONTENTS_WATER;
327 	return cont;
328 }
329 
330 /*
331 =============================================================
332 
333   SPRITE MODELS
334 
335 =============================================================
336 */
337 
338 /*
339 ================
340 R_GetSpriteFrame
341 ================
342 */
R_GetSpriteFrame(entity_t * currententity)343 mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
344 {
345 	msprite_t		*psprite;
346 	mspritegroup_t	*pspritegroup;
347 	mspriteframe_t	*pspriteframe;
348 	int				i, numframes, frame;
349 	float			*pintervals, fullinterval, targettime, time;
350 
351 	psprite = currententity->model->cache.data;
352 	frame = currententity->frame;
353 
354 	if ((frame >= psprite->numframes) || (frame < 0))
355 	{
356 		Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
357 		frame = 0;
358 	}
359 
360 	if (psprite->frames[frame].type == SPR_SINGLE)
361 	{
362 		pspriteframe = psprite->frames[frame].frameptr;
363 	}
364 	else
365 	{
366 		pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
367 		pintervals = pspritegroup->intervals;
368 		numframes = pspritegroup->numframes;
369 		fullinterval = pintervals[numframes-1];
370 
371 		time = cl.time + currententity->syncbase;
372 
373 	// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
374 	// are positive, so we don't have to worry about division by 0
375 		targettime = time - ((int)(time / fullinterval)) * fullinterval;
376 
377 		for (i=0 ; i<(numframes-1) ; i++)
378 		{
379 			if (pintervals[i] > targettime)
380 				break;
381 		}
382 
383 		pspriteframe = pspritegroup->frames[i];
384 	}
385 
386 	return pspriteframe;
387 }
388 
389 /*
390 =================
391 R_DrawSpriteModel
392 
393 =================
394 */
395 #define VectorScalarMult(a,b,c) {c[0]=a[0]*b;c[1]=a[1]*b;c[2]=a[2]*b;}
R_DrawSpriteModel(entity_t * e)396 void R_DrawSpriteModel (entity_t *e) //Oriented Sprite Fix - Eradicator
397 {
398 	vec3_t	point;
399 	mspriteframe_t	*frame;
400 	float		*up, *right;
401 	vec3_t		v_forward, v_right, v_up;
402 	msprite_t		*psprite;
403 	vec3_t		fixed_origin;
404 	vec3_t		temp;
405 
406 	// don't even bother culling, because it's just a single
407 	// polygon without a surface cache
408 	frame = R_GetSpriteFrame (e);
409 	psprite = currententity->model->cache.data;
410 
411 	VectorCopy(e->origin,fixed_origin);
412 
413 	if (psprite->type == SPR_ORIENTED)
414 	{	// bullet marks on walls
415 		AngleVectors (currententity->angles, v_forward, v_right, v_up);
416 		VectorScalarMult(v_forward,-2,temp);
417 		VectorAdd(temp,fixed_origin,fixed_origin);
418 		up = v_up;
419 		right = v_right;
420 	}
421 	else
422 	{	// normal sprite
423 		up = vup;
424 		right = vright;
425 	}
426 
427 	GL_DisableMultitexture();
428 
429     GL_Bind(frame->gl_texturenum);
430 
431 	glEnable (GL_ALPHA_TEST);
432 	glBegin (GL_QUADS);
433 
434 	glTexCoord2f (0, 1);
435 	//VectorMA (e->origin, frame->down, up, point); //Old
436 	VectorMA (fixed_origin, frame->down, up, point); //Fixed Origin
437 	VectorMA (point, frame->left, right, point);
438 	glVertex3fv (point);
439 
440 	glTexCoord2f (0, 0);
441 	VectorMA (fixed_origin, frame->up, up, point);
442 	VectorMA (point, frame->left, right, point);
443 	glVertex3fv (point);
444 
445 	glTexCoord2f (1, 0);
446 	VectorMA (fixed_origin, frame->up, up, point);
447 	VectorMA (point, frame->right, right, point);
448 	glVertex3fv (point);
449 
450 	glTexCoord2f (1, 1);
451 	VectorMA (fixed_origin, frame->down, up, point);
452 	VectorMA (point, frame->right, right, point);
453 	glVertex3fv (point);
454 
455 	glEnd ();
456 
457 	glDisable (GL_ALPHA_TEST);
458 }
459 
460 /*
461 =============================================================
462 
463   ALIAS MODELS
464 
465 =============================================================
466 */
467 
468 
469 float	r_avertexnormals[NUMVERTEXNORMALS][3] = {
470 #include "anorms.h"
471 };
472 
473 vec3_t	shadevector;
474 float	shadelight, ambientlight;
475 
476 // precalculated dot products for quantized angles
477 #define SHADEDOT_QUANT 16
478 float	r_avertexnormal_dots[SHADEDOT_QUANT][256] =
479 #include "anorm_dots.h"
480 ;
481 
482 float	*shadedots = r_avertexnormal_dots[0];
483 
484 int	lastposenum;
485 
486 void GL_DrawPentaAliasFrame (aliashdr_t *paliashdr, int posenum);
487 /*
488 =============
489 GL_DrawAliasFrame
490 =============
491 */
492 
GL_DrawAliasFrame(aliashdr_t * paliashdr,int posenum)493 void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
494 {
495 	//Crappy
496 }
497 
498 
499 ftrivertx_t *apverts;
GL_DrawPentaAliasFrame(aliashdr_t * paliashdr,int posenum)500 void GL_DrawPentaAliasFrame (aliashdr_t *paliashdr, int posenum) {
501 
502 	mtriangle_t *ptri;
503 	ftrivertx_t	*verts;
504 	plane_t		*planes;
505 	int i,j;
506 
507 	return;
508 
509 	//verts = apverts;
510 	verts = (ftrivertx_t *)((byte *)paliashdr + paliashdr->posedata);
511 	verts += posenum * paliashdr->poseverts;
512 	ptri = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
513 	planes = (plane_t *)((byte *)paliashdr + paliashdr->planes);
514 	planes += posenum * paliashdr->numtris;
515 
516 	for (i=0 ; i<paliashdr->numtris ; i++, ptri++, planes++)
517 	{
518 		glBegin(GL_TRIANGLES);
519 		//Con_Printf("%i %i %i\n", (int)ptri->vertindex[0], (int)ptri->vertindex[1], (int)ptri->vertindex[2]);
520 		glTexCoord2f(0.5, 0.5);
521 		for (j=0; j<3; j++) {
522 			glVertex3f(verts[ptri->vertindex[j]].v[0],
523 					   verts[ptri->vertindex[j]].v[1],
524 					   verts[ptri->vertindex[j]].v[2]);
525 			//Con_Printf("%i \n",ptri->vertindex[j]);
526 		}
527 		glEnd();
528 	}
529 
530 }
531 
532 extern	vec3_t			lightspot;
533 
534 
535 int		extrudeTimeStamp;
536 vec3_t	extrudedVerts[MAXALIASVERTS];	//PENTA: Temp buffer for extruded vertices
537 int		extrudedTimestamp[MAXALIASVERTS];	//PENTA: Temp buffer for extruded vertices
538 qboolean	triangleVis[MAXALIASTRIS];	//PENTA: Temp buffer for light facingness of triangles
539 
R_CalcAliasFrameShadowVolume(aliashdr_t * paliashdr,int posenum)540 void R_CalcAliasFrameShadowVolume (aliashdr_t *paliashdr,int posenum) {
541 
542 	plane_t *planes;
543 	ftrivertx_t	*verts;
544 	mtriangle_t	*tris, *triangle;
545 	float d, scale;
546 	int i, j;
547 	vec3_t v2, *v1;
548 
549 	planes = (plane_t *)((byte *)paliashdr + paliashdr->planes);
550 	planes += posenum * paliashdr->numtris;
551 	verts = (ftrivertx_t *)((byte *)paliashdr + paliashdr->posedata);
552 	verts += posenum * paliashdr->poseverts;
553 	tris = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
554 
555 	extrudeTimeStamp++;
556 	//calculate visibility
557 	for (i=0; i<paliashdr->numtris; i++) {
558 		d = DotProduct(planes[i].normal, currentshadowlight->origin) - planes[i].dist;
559 		if (d > 0)
560 			triangleVis[i] = true;
561 		else
562 			triangleVis[i] = false;
563 	}
564 
565 
566 	//extude vertices
567 	triangle = tris;
568 	for (i=0; i<paliashdr->numtris; i++, triangle++) {
569 
570 		if (triangleVis[i]) {//backfacing extrude it!
571 
572 			for (j=0; j<3; j++) {
573 
574 				int index = triangle->vertindex[j];
575 				if (extrudedTimestamp[index] == extrudeTimeStamp) continue;
576 				extrudedTimestamp[index] = extrudeTimeStamp;
577 
578 				v1 = &extrudedVerts[index];
579 
580 				/*
581 				for (k=0; k<3; k++)
582 					v2[k] = (verts[index].v[k] * paliashdr->scale[k]) + paliashdr->scale_origin[k];
583 				*/
584 				VectorCopy(verts[index].v,v2);
585 
586 				VectorSubtract (v2, currentshadowlight->origin, (*v1));
587 				scale = Length ((*v1));
588 
589 				if (sh_visiblevolumes.value) {
590 					//make them short so that we see them
591 					VectorScale ((*v1), (1/scale)* 70, (*v1));
592 				} else {
593 					//we don't have to be afraid they will clip with the far plane
594 					//since we use the infinite matrix trick
595 					VectorScale ((*v1), (1/scale)* currentshadowlight->radius*10, (*v1));
596 				}
597 				VectorAdd ((*v1), v2 ,(*v1));
598 			}
599 		}
600 	}
601 }
602 
R_DrawAliasFrameShadowVolume2(aliashdr_t * paliashdr,aliasframeinstant_t * instant)603 void R_DrawAliasFrameShadowVolume2 (aliashdr_t *paliashdr,aliasframeinstant_t *instant) {
604 
605 	mtriangle_t	*tris, *triangle;
606 	int i, j;
607 	aliaslightinstant_t *linstant = instant->lightinstant;
608 
609 	tris = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
610 
611 
612 	//FIXME: what's faster? less begin/ends or iterating the list multiple times?
613 	//extude vertices
614 	triangle = tris;
615 	for (i=0; i<paliashdr->numtris; i++, triangle++) {
616 
617 		if (linstant->triangleVis[i]) {
618 
619 			for (j=0; j<3; j++) {
620 
621 				qboolean shadow = false;
622 				if (triangle->neighbours[j] == -1) {
623 					shadow = true;
624 				} else if (!linstant->triangleVis[triangle->neighbours[j]]) {
625 					shadow = true;
626 				}
627 
628 				if (shadow) {
629 					int index = triangle->vertindex[j];
630 					glBegin(GL_QUAD_STRIP);
631 
632 					/*
633 					glVertex3f(verts[index].v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0],
634 					           verts[index].v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1],
635 						       verts[index].v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]
636 					);
637 					*/
638 					glVertex3fv(&instant->vertices[index][0]);
639 					glVertex3fv(&linstant->extvertices[index][0]);
640 
641 					index = triangle->vertindex[(j+1)%3];
642 					/*glVertex3f(verts[index].v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0],
643 					           verts[index].v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1],
644 						       verts[index].v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]
645 					);
646 					*/
647 					glVertex3fv(&instant->vertices[index][0]);
648 					glVertex3fv(&linstant->extvertices[index][0]);
649 					glEnd();
650 
651 				}
652 			}
653 
654 
655 			glBegin(GL_TRIANGLES);
656 			for (j=0; j<3; j++) {
657 				int index = triangle->vertindex[j];
658 				/*
659 				glVertex3f(verts[index].v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0],
660 					       verts[index].v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1],
661 						   verts[index].v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]
662 				);
663 				*/
664 				glVertex3fv(&instant->vertices[index][0]);
665 			}
666 			glEnd();
667 
668 			glBegin(GL_TRIANGLES);
669 			for (j=2; j>=0; j--) {
670 				glVertex3fv(&linstant->extvertices[triangle->vertindex[j]][0]);
671 			}
672 			glEnd();
673 
674 		}
675 
676 		/*
677 		glBegin(GL_LINES);
678 		for (j=0; j<3; j++) {
679 			v2[j] = verts[ triangle->vertindex[0]].v[j] * paliashdr->scale[j] + paliashdr->scale_origin[j];
680 		}
681 		glVertex3fv(&v2[0]);
682 		VectorMA(v2, 5, planes[i].normal, v2);
683 		glVertex3fv(&v2[0]);
684 		glEnd();
685 		*/
686 	}
687 }
688 /*
689 =============
690 R_DrawAliasFrameShadowVolume
691 =============
692 */
693 extern	vec3_t			lightspot;
694 
695 /*
696 void R_DrawAliasFrameShadowVolume (aliashdr_t *paliashdr, int posenum)
697 {
698 	float	s, t, l;
699 	int		i, j;
700 	int		index;
701 	ftrivertx_t	*v, *verts;
702 	int		list;
703 	int		*order;
704 	vec3_t	point,dir;
705 	vec3_t	*normal;
706 	int		count;
707 	vec3_t	fnormal;
708 	verts = (ftrivertx_t *)((byte *)paliashdr + paliashdr->posedata);
709 	verts += posenum * paliashdr->poseverts;
710 	order = (int *)((byte *)paliashdr + paliashdr->commands);
711 
712 	while (1)
713 	{
714 		// get the vertex count and primitive type
715 		count = *order++;
716 		if (!count)
717 			break;		// done
718 		if (count < 0)
719 		{
720 			count = -count;
721 			glBegin (GL_TRIANGLE_FAN);
722 		}
723 		else
724 			glBegin (GL_TRIANGLE_STRIP);
725 
726 		do
727 		{
728 			// texture coordinates come from the draw list
729 			// (skipped for shadow volumes) glTexCoord2fv ((float *)order);
730 			order += 2;
731 
732 			// normals and vertexes come from the frame list
733 
734 			//point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
735 			//point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
736 			//point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
737 
738 
739 			normal = &r_avertexnormals[verts->lightnormalindex];
740 
741 			//VectorSubtract(point,currentshadowlight->origin,dir);
742 			VectorSubtract(verts->v,currentshadowlight->origin,dir);
743 			VectorNormalize(dir);
744 
745 			if (DotProduct(dir,(*normal)) <= 0) {
746 				//etrude to "infinity"
747 				if (sh_visiblevolumes.value) {
748 					VectorScale(dir,50,dir);
749 				} else {
750 					VectorScale(dir,currentshadowlight->radius*10,dir);
751 				}
752 				//VectorAdd(point,dir,point);
753 				VectorAdd(verts->v,dir,point);
754 			} else
755 				VectorCopy(verts->v,point);
756 
757 			glVertex3fv (point);
758 			verts++;
759 		} while (--count);
760 
761 		glEnd ();
762 	}
763 }
764 */
765 
766 /*
767 =================
768 R_DrawAliasShadowVolume
769 
770 =================
771 */
772 
R_DrawAliasSurfaceShadowVolume(aliashdr_t * paliashdr,aliasframeinstant_t * aliasframeinstant)773 void R_DrawAliasSurfaceShadowVolume (aliashdr_t	*paliashdr, aliasframeinstant_t *aliasframeinstant)
774 {
775 #if 1
776 	//
777 	//Pass 1 increase
778 	//
779 	glCullFace(GL_BACK);
780 	glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
781 	glCullFace(GL_FRONT);
782 
783 	R_DrawAliasFrameShadowVolume2 (paliashdr, aliasframeinstant);
784 
785 	//
786 	// Second Pass. Decrease Stencil Value In The Shadow
787 	//
788 	glCullFace(GL_FRONT);
789 	glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
790 	glCullFace(GL_BACK);
791 
792 	R_DrawAliasFrameShadowVolume2 (paliashdr, aliasframeinstant);
793 #else
794         glDisable(GL_CULL_FACE);
795 	glCullFace(GL_FRONT_AND_BACK);
796         checkerror();
797 	glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
798         checkerror();
799 	qglStencilFuncSeparateATI(GL_ALWAYS, GL_ALWAYS, 0, ~0);
800         checkerror();
801 	qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
802         checkerror();
803 	qglStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
804         checkerror();
805 	R_DrawAliasFrameShadowVolume2 (paliashdr, aliasframeinstant);
806 
807         glEnable(GL_CULL_FACE);
808 	glCullFace(GL_BACK);
809 #endif
810 }
811 
812 
R_DrawAliasShadowVolume(entity_t * e)813 void R_DrawAliasShadowVolume (entity_t *e)
814 {
815     model_t		*clmodel;
816     aliashdr_t	*paliashdr;
817     alias3data_t    *data;
818     aliasframeinstant_t *aliasframeinstant;
819     int i,maxnumsurf;
820     //vec3_t		oldlightpos;
821 
822     currententity = e;
823 
824     clmodel = currententity->model;
825 
826     /* no shadows casting for these */
827     if (clmodel->flags & EF_NOSHADOW)
828 		return;
829 
830     //
831     // locate the proper data
832     //
833     if (!e->aliasframeinstant) {
834 		Con_Printf("no instant for ent %s\n", clmodel->name);
835 		return;
836     }
837 
838     /*
839       Don't cull to frustum models behind you may still cast shadows
840 
841       if (R_CullBox (mins, maxs))
842       return;
843     */
844 
845     VectorCopy (currententity->origin, r_entorigin);
846     VectorSubtract (r_origin, r_entorigin, modelorg);
847 
848     //
849     // locate the proper data
850     //
851     // data = (alias3data_t *)Mod_Extradata (e->model);
852 
853     aliasframeinstant = e->aliasframeinstant;
854 
855     data = (alias3data_t *)Mod_Extradata (e->model);
856     maxnumsurf = data->numSurfaces;
857 
858     glPushMatrix ();
859     R_RotateForEntity (e);
860 
861     for (i=0;i<maxnumsurf;++i)
862     {
863 		paliashdr = (aliashdr_t *)((char*)data + data->ofsSurfaces[i]);
864 
865 		if (!aliasframeinstant) {
866 			glPopMatrix ();
867             Con_Printf("R_DrawAliasShadowVolume: missing instant for ent %s\n", e->model->name);
868 			return;
869 		}
870 
871 		/*  doesn't fit with new structs
872 		if (paliashdr != ((aliasframeinstant_t *)e->model->aliasframeinstant)->paliashdr) {
873 		//Sys_Error("Cache trashed");
874 		r_cache_thrash = true;
875 		((aliasframeinstant_t *)e->model->aliasframeinstant)->paliashdr = paliashdr;
876 		}
877 		*/
878 
879 		if ((e->frame >= paliashdr->numframes) || (e->frame < 0))
880 		{
881 			glPopMatrix ();
882 			return;
883 		}
884 
885 		//
886 		// draw all the triangles
887 		//
888 		R_DrawAliasSurfaceShadowVolume(paliashdr,aliasframeinstant);
889 		aliasframeinstant = aliasframeinstant->_next;
890 		//VectorCopy(oldlightpos,currentshadowlight->origin);
891     } /* for paliashdr */
892 
893     glPopMatrix();
894 }
895 
896 /*
897 =================
898 R_SetupAliasFrame
899 
900 =================
901 */
902 
R_SetupAliasFrame(aliashdr_t * paliashdr,aliasframeinstant_t * instant)903 void R_SetupAliasFrame (aliashdr_t *paliashdr, aliasframeinstant_t *instant)
904 {
905 	float*			texcoos;
906 	int*			indecies;
907 	/*
908 	if ((frame >= paliashdr->numframes) || (frame < 0))
909 	{
910 		Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
911 		frame = 0;
912 	}
913 
914 	pose = paliashdr->frames[frame].firstpose;
915 	numposes = paliashdr->frames[frame].numposes;
916 
917 	apverts = (ftrivertx_t *)((byte *)paliashdr + paliashdr->frames[frame].frame);
918 
919 	if (numposes > 1)
920 	{
921 		interval = paliashdr->frames[frame].interval;
922 		pose += (int)(cl.time / interval) % numposes;
923 	}
924 	*/
925 
926 	texcoos = (float *)((byte *)paliashdr + paliashdr->texcoords);
927 	indecies = (int *)((byte *)paliashdr + paliashdr->indecies);
928 	//GL_DrawAliasFrame (paliashdr, pose);
929 	glVertexPointer(3, GL_FLOAT, 0, instant->vertices);
930 	glEnableClientState(GL_VERTEX_ARRAY);
931 	glNormalPointer(GL_FLOAT, 0, instant->normals);
932 	glEnableClientState(GL_NORMAL_ARRAY);
933 	glTexCoordPointer(2, GL_FLOAT, 0, texcoos);
934 	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
935 
936 	glDrawElements(GL_TRIANGLES,paliashdr->numtris*3,GL_UNSIGNED_INT,indecies);
937 
938 	glDisableClientState(GL_VERTEX_ARRAY);
939 	glDisableClientState(GL_NORMAL_ARRAY);
940 	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
941 }
942 
943 /*
944 	Draws the tangent space of the model
945 */
R_DrawAliasTangent(aliashdr_t * paliashdr,aliasframeinstant_t * instant)946 void R_DrawAliasTangent (aliashdr_t *paliashdr, aliasframeinstant_t *instant)
947 {
948 	float*			texcoos;
949 	int*			indecies;
950 	vec3_t			extr;
951 	int				i;
952 
953 	texcoos = (float *)((byte *)paliashdr + paliashdr->texcoords);
954 	indecies = (int *)((byte *)paliashdr + paliashdr->indecies);
955 	//GL_DrawAliasFrame (paliashdr, pose);
956 
957 	for (i=0; i<paliashdr->poseverts; i++) {
958 
959 		glColor3ub(255,0,0);
960 		glBegin(GL_LINES);
961 			glVertex3fv(&instant->vertices[i][0]);
962 			VectorMA(instant->vertices[i],1,instant->normals[i],extr);
963 			glVertex3fv(&extr[0]);
964 		glEnd();
965 
966 		glColor3ub(0,255,0);
967 		glBegin(GL_LINES);
968 			glVertex3fv(&instant->vertices[i][0]);
969 			VectorMA(instant->vertices[i],1,instant->tangents[i],extr);
970 			glVertex3fv(&extr[0]);
971 		glEnd();
972 
973 		glColor3ub(0,0,255);
974 		glBegin(GL_LINES);
975 			glVertex3fv(&instant->vertices[i][0]);
976 			VectorMA(instant->vertices[i],1,instant->binomials[i],extr);
977 			glVertex3fv(&extr[0]);
978 		glEnd();
979 	}
980 }
981 
982 
983 /*
984 =================
985 R_DrawAliasSurface
986 DC : draw one surface from a model
987 
988 =================
989 */
990 
991 
992 
R_DrawAliasSurface(aliashdr_t * paliashdr,float bright,aliasframeinstant_t * instant)993 void R_DrawAliasSurface (aliashdr_t *paliashdr, float bright, aliasframeinstant_t *instant)
994 {
995         int i;
996 	int			anim;
997 
998 	//
999 	// draw all the triangles
1000 	//
1001 
1002 	if (!busy_caustics) {
1003 		anim = (int)(cl.time*10) & 3;
1004 		GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);
1005 
1006 		// we can't dynamically colormap textures, so they are cached
1007 		// seperately for the players.  Heads are just uncolored.
1008 		if (currententity->colormap != vid.colormap && !gl_nocolors.value)
1009 		{
1010 			i = currententity - cl_entities;
1011 			if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
1012 				GL_Bind(playertextures - 1 + i);
1013 		}
1014 	}
1015 
1016 	//XYZ
1017 	if (gl_wireframe.value) {
1018 		glDisable(GL_TEXTURE_2D);
1019 	}
1020 
1021 	if ( gl_truform.value )
1022 	{
1023 	    glEnable(GL_PN_TRIANGLES_ATI);
1024 	    qglPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI);
1025 	    qglPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI);
1026 	    qglPNTrianglesiATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_truform_tesselation.value);
1027 	}
1028 
1029 
1030 
1031 	glColor3f(bright, bright, bright);
1032 	//if (busy_caustics)
1033 	//	glColor3f(1,1,1);
1034         R_SetupAliasFrame (paliashdr, instant);
1035 
1036         // Draw luma if present
1037         if ( !busy_caustics )
1038         {
1039             anim = (int)(cl.time*10) & 3;
1040             if ( paliashdr->gl_lumatex[currententity->skinnum][anim] != 0)
1041             {
1042                 glFogfv(GL_FOG_COLOR, color_black);
1043                 glEnable(GL_BLEND);
1044                 glBlendFunc(GL_ONE, GL_ONE);
1045                 GL_SelectTexture(GL_TEXTURE1_ARB);
1046                 glDisable(GL_TEXTURE_2D);
1047                 GL_SelectTexture(GL_TEXTURE0_ARB);
1048                 glColor3f(1, 1, 1);
1049 
1050                 GL_Bind( paliashdr->gl_lumatex[currententity->skinnum][anim] );
1051 
1052                 R_SetupAliasFrame (paliashdr, instant);
1053 
1054 
1055                 glColor3f(sh_lightmapbright.value,sh_lightmapbright.value,sh_lightmapbright.value);
1056                 GL_SelectTexture(GL_TEXTURE1_ARB);
1057                 glEnable(GL_TEXTURE_2D);
1058                 GL_SelectTexture(GL_TEXTURE0_ARB);
1059                 GL_SelectTexture(GL_TEXTURE1_ARB);
1060                 glDisable(GL_BLEND);
1061                 glFogfv(GL_FOG_COLOR, fog_color);
1062             }
1063         }
1064 
1065 	if ((sh_showtangent.value) && (!busy_caustics)) {
1066 		glDisable(GL_TEXTURE_2D);
1067              R_DrawAliasTangent(paliashdr, instant);
1068 		glEnable(GL_TEXTURE_2D);
1069 	}
1070 
1071 	c_alias_polys += paliashdr->numtris;
1072 
1073 
1074 	if ( gl_truform.value )
1075 	{
1076 	    glDisable(GL_PN_TRIANGLES_ATI);
1077 	}
1078 }
1079 
1080 
1081 
1082 /*
1083 =================
1084 R_DrawAliasModel
1085 
1086 =================
1087 */
1088 
1089 /*
1090 void R_PrepareEntityForDraw (float bright)
1091 {
1092 	float		an;
1093 
1094 
1095 
1096 	model_t		*clmodel;
1097 
1098 	clmodel = currententity->model;
1099 
1100 	VectorAdd (currententity->origin, clmodel->mins, mins);
1101 	VectorAdd (currententity->origin, clmodel->maxs, maxs);
1102 
1103 	if (R_CullBox (mins, maxs))
1104 		return;
1105 
1106 
1107 	VectorCopy (currententity->origin, r_entorigin);
1108 	VectorSubtract (r_origin, r_entorigin, modelorg);
1109 
1110 	shadelight = bright;
1111 
1112 	an = currententity->angles[1]/180*M_PI;
1113 	shadevector[0] = cos(-an);
1114 	shadevector[1] = sin(-an);
1115 	shadevector[2] = 1;
1116 	VectorNormalize (shadevector);
1117 
1118 }
1119 */
1120 
R_DrawAliasModel(float bright)1121 void R_DrawAliasModel (float bright)
1122 {
1123 	int			i,maxnumsurf;
1124 	aliashdr_t	*paliashdr;
1125         aliasframeinstant_t *aliasframeinstant;
1126         alias3data_t *data;
1127 	vec3_t	mins,maxs;
1128 
1129         //R_PrepareEntityForDraw (bright);
1130 
1131         GL_DisableMultitexture();
1132 
1133         glPushMatrix ();
1134 
1135         R_RotateForEntity (currententity);
1136 
1137 	data = (alias3data_t *)Mod_Extradata (currententity->model);
1138         maxnumsurf = data->numSurfaces;
1139 
1140         aliasframeinstant = currententity->aliasframeinstant;
1141 
1142 	if (gl_smoothmodels.value)
1143 		glShadeModel (GL_SMOOTH);
1144 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1145 
1146 	if (gl_affinemodels.value)
1147 		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1148 
1149         for (i=0;i<maxnumsurf;++i){
1150 
1151              paliashdr = (aliashdr_t *)((char*)data + data->ofsSurfaces[i]);
1152 
1153              if (!aliasframeinstant) {
1154                   glPopMatrix();
1155                   Con_Printf("R_DrawAliasModel: missing instant for ent %s\n", currententity->model->name);
1156                   return;
1157              }
1158 
1159              /* disabled for now because it doesn't work with viewent
1160              VectorAdd (currententity->origin,paliashdr->mins, mins);
1161              VectorAdd (currententity->origin,paliashdr->maxs, maxs);
1162 
1163              if (!R_CullBox (mins, maxs))                  */
1164                   R_DrawAliasSurface (paliashdr, bright, aliasframeinstant);
1165              aliasframeinstant = aliasframeinstant->_next;
1166         }
1167 
1168 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1169 
1170 	glShadeModel (GL_FLAT);
1171 
1172 	if (gl_affinemodels.value)
1173 		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1174 
1175 	glPopMatrix ();
1176 
1177 }
1178 
1179 //==================================================================================
1180 
1181 
R_DrawAmbientAlias(void (* r_func)(float bright))1182 void R_DrawAmbientAlias (void (*r_func)(float bright))
1183 {
1184      float	brightness;
1185      if (currententity->model->flags & EF_FULLBRIGHT)
1186      {
1187           r_func ( 1.0);
1188           //XYZ
1189      } else if (gl_wireframe.value) {
1190           r_func ( 0.0);
1191      }else {
1192           brightness = (R_LightPoint (currententity->origin)/255.0) * sh_lightmapbright.value;
1193           r_func (brightness);
1194      }
1195 }
1196 
1197 
1198 /*
1199 =============
1200 PENTA:
1201 R_DrawAmbientEntities
1202 =============
1203 */
R_DrawAmbientEntities()1204 void R_DrawAmbientEntities ()
1205 {
1206 	int		i;
1207 	vec3_t	mins,maxs;
1208 
1209 	if (!r_drawentities.value)
1210 		return;
1211 
1212 	//We don't draw sprites they do not cast shadows
1213 	for (i=0 ; i<cl_numvisedicts ; i++)
1214 	{
1215 		currententity = cl_visedicts[i];
1216 
1217 		if (currententity->angles[0] || currententity->angles[1] || currententity->angles[2])
1218 		{
1219 			int i;
1220 			for (i=0 ; i<3 ; i++)
1221 			{
1222 				mins[i] = currententity->origin[i] - currententity->model->radius;
1223 				maxs[i] = currententity->origin[i] + currententity->model->radius;
1224 			}
1225 		} else {
1226 			VectorAdd (currententity->origin,currententity->model->mins, mins);
1227 			VectorAdd (currententity->origin,currententity->model->maxs, maxs);
1228 		}
1229 
1230 		if (R_CullBox (mins, maxs))
1231 			continue;
1232 
1233 		if (mirror) {
1234 			if (mirror_clipside == BoxOnPlaneSide(mins, maxs, mirror_plane)) {
1235 				continue;
1236 			}
1237 
1238 			if ( BoxOnPlaneSide(mins, maxs, &mirror_far_plane) == 1) {
1239 				return;
1240 			}
1241 		}
1242 
1243 		switch (currententity->model->type)
1244 		{
1245 		case mod_alias:
1246                      R_DrawAmbientAlias (R_DrawAliasModel);
1247 			break;
1248 		case mod_brush:
1249 			glColor3f(sh_lightmapbright.value,sh_lightmapbright.value,sh_lightmapbright.value);
1250 			R_DrawBrushModel(currententity);
1251 			break;
1252 
1253 		default:
1254 			break;
1255 		}
1256 	}
1257 }
1258 
1259 /*
1260 =============
1261 PENTA:
1262 R_DrawLightEntities
1263 -> moved to gl_bumpdriver.c
1264 =============
1265 */
1266 
1267 
1268 /*
1269 =============
1270 R_DrawEntitiesOnList
1271 
1272 Post multiply the textures with the frame buff.
1273 =============
1274 */
R_DrawEntitiesOnList(void)1275 void R_DrawEntitiesOnList (void)
1276 {
1277 	int		i;
1278 
1279 	if (!r_drawentities.value)
1280 		return;
1281 
1282         if ( cl_numvisedicts == 0 )
1283             return;
1284 
1285 	glBlendFunc(GL_ZERO,GL_SRC_COLOR);
1286 	glEnable(GL_BLEND);
1287 
1288         glColor3f(1.0f, 1.0f, 1.0f);
1289 
1290 	//Con_Printf("cl_numvisedicts %d\n",cl_numvisedicts);
1291 	// draw sprites seperately, because of alpha blending
1292 	for (i=0 ; i<cl_numvisedicts ; i++)
1293 	{
1294 		currententity = cl_visedicts[i];
1295 
1296 		switch (currententity->model->type)
1297 		{
1298 		case mod_alias:
1299 			R_DrawAliasModel (1.0);
1300 			break;
1301 
1302 		case mod_brush:
1303 			//glColor3f(1.0,1.0,1.0);
1304 			//R_DrawBrushModel (currententity);
1305 			break;
1306 
1307 		default:
1308 			break;
1309 		}
1310 	}
1311 
1312 
1313 	glDisable(GL_BLEND);
1314 	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1315 
1316 	//sprites are drawn the usual way
1317 	for (i=0 ; i<cl_numvisedicts ; i++)
1318 	{
1319 		currententity = cl_visedicts[i];
1320 
1321 		switch (currententity->model->type)
1322 		{
1323 		case mod_sprite:
1324 			R_DrawSpriteModel (currententity);
1325                 default:				// <AWE> added default to suppress compiler warning.
1326 			break;
1327 		}
1328 	}
1329 
1330 
1331 }
1332 
1333 
1334 /*
1335 =============
1336 R_MarkEntitiesOnList
1337 =============
1338 */
R_MarkEntitiesOnList(void)1339 void R_MarkEntitiesOnList (void)
1340 {
1341 	int		i;
1342 	float	angle;
1343 
1344 	if (!r_drawentities.value)
1345 		return;
1346 
1347 	for (i=0 ; i<cl_numlightvisedicts ; i++)
1348 	{
1349 		currententity = cl_lightvisedicts[i];
1350 
1351 		switch (currententity->model->type)
1352 		{
1353 		case mod_brush:
1354 			//R_MarkBrushModelSurfaces(currententity);
1355 			R_SetupBrushInstantForLight(currententity);
1356 			break;
1357 		case mod_alias:
1358 			R_SetupInstantForLight(currententity);
1359 			break;
1360 		default:
1361 			break;
1362 		}
1363 	}
1364 
1365 	if (cl.viewent.model)
1366 		R_SetupInstantForLight(&cl.viewent);
1367 	//for player Hack: Dont let it rotate when player looks up/down this looks
1368 	//very unrealistic
1369 
1370 	if (mirror) return;
1371 	if (!cl_entities[cl.viewentity].model) return;
1372 	if (cl_entities[cl.viewentity].model->type != mod_alias) return;
1373 
1374 	angle = cl_entities[cl.viewentity].angles[0];
1375 	cl_entities[cl.viewentity].angles[0] = 0;
1376 	R_SetupInstantForLight(&cl_entities[cl.viewentity]);
1377 	cl_entities[cl.viewentity].angles[0] = 	angle;
1378 }
1379 
1380 /*
1381 =============
1382 R_DrawEntitiesShadowVolumes
1383 =============
1384 */
R_DrawEntitiesShadowVolumes(int type)1385 void R_DrawEntitiesShadowVolumes (int type)
1386 {
1387 	int		i;
1388 	float	colorscale;
1389 	vec3_t	dist;
1390 	vec3_t	angles;
1391 	if (!r_drawentities.value)
1392 		return;
1393 
1394 
1395 	for (i=0 ; i<cl_numlightvisedicts ; i++)
1396 	{
1397 		currententity = cl_lightvisedicts[i];
1398 
1399 		if (currententity->model->type != type) continue;
1400 
1401 		switch (currententity->model->type)
1402 		{
1403 		case mod_alias:
1404 
1405 			VectorSubtract (currententity->origin, currentshadowlight->origin,dist);
1406 			colorscale = 1 - (Length(dist) / currentshadowlight->radius);
1407 
1408 			//it will be a verry faint shadow
1409 			if (colorscale < 0.1) continue;
1410 			R_DrawAliasShadowVolume(currententity);
1411 
1412 			break;
1413 
1414 		case mod_brush:
1415 			R_DrawBrushModelVolumes(currententity);
1416 			break;
1417 
1418 		default:
1419 			break;
1420 		}
1421 	}
1422 
1423 	if (mirror) return;
1424 	currententity = &cl_entities[cl.viewentity];
1425 	VectorCopy(currententity->angles,angles);
1426 	//during intermissions the viewent model is nil
1427 	if (currententity->model)
1428              if ((currententity->model->type == type)
1429                  && (type == mod_alias)
1430                  && (sh_playershadow.value)
1431                  && (!chase_active.value)) { //Fix for two player shadows in chase cam - Eradicator
1432 			//for lights cast by the player don't add the player's shadow
1433 			if (currentshadowlight->owner != currententity) {
1434 				//HACK: only horizontal angle this looks better
1435 				currententity->angles[0] = 0;
1436 				currententity->angles[2] = 0;
1437 				R_DrawAliasShadowVolume(currententity);
1438 			}
1439 		}
1440 	VectorCopy(angles,currententity->angles);
1441 
1442 }
1443 
1444 /*
1445 =============
1446 R_DrawLightSprites
1447 
1448 Draw the overriden sprites that are lit by a cube map
1449 =============
1450 */
R_DrawLightSprites(void)1451 void R_DrawLightSprites (void)
1452 {
1453     int		i;
1454     vec3_t	dist;
1455     float	colorscale;
1456 
1457     if (!r_drawentities.value)
1458         return;
1459 
1460     if ( cl_numlightvisedicts == 0 )
1461         return;
1462 
1463     glEnable(GL_BLEND);
1464     glBlendFunc(GL_ONE,GL_ONE);
1465     glDepthMask(0);
1466 
1467     if ( currentshadowlight->filtercube )
1468     {
1469         glMatrixMode(GL_TEXTURE);
1470         glPushMatrix();
1471         GL_SetupCubeMapMatrix(true);
1472 
1473         GL_EnableColorShader (false);
1474     }
1475     else
1476     {
1477         GL_SelectTexture(GL_TEXTURE0_ARB);
1478         glEnable(GL_TEXTURE_2D);
1479         glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1480         glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1481         glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1482         glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
1483     }
1484 
1485     for ( i = 0; i < cl_numlightvisedicts; i++ )
1486     {
1487         currententity = cl_lightvisedicts[i];
1488 
1489         if (currententity->model->type == mod_sprite)
1490         {
1491             if (((msprite_t *)currententity->model->cache.data)->type
1492                 >= SPR_VP_PARALLEL_UPRIGHT_OVER)
1493             {
1494                 if (currententity->light_lev)
1495                     continue;
1496 
1497                 //We do attent instead of opengl since gl doesn't seem to do
1498                 //what we want, it never really gets to zero.
1499                 VectorSubtract (currententity->origin, currentshadowlight->origin,
1500                                 dist);
1501                 colorscale = 1 - (Length(dist) / currentshadowlight->radius);
1502 
1503                 //if it's to dark we save time by not drawing it
1504                 if (colorscale < 0.1)
1505                     continue;
1506 
1507                 glColor3f(currentshadowlight->color[0]*colorscale,
1508                           currentshadowlight->color[1]*colorscale,
1509                           currentshadowlight->color[2]*colorscale);
1510 
1511                 if ( currentshadowlight->filtercube )
1512                     R_DrawSpriteModelWV(currententity);
1513                 else
1514                     R_DrawSpriteModel(currententity);
1515 
1516             }
1517         }
1518     }
1519 
1520     glDisable(GL_BLEND);
1521 
1522     if ( currentshadowlight->filtercube )
1523     {
1524         GL_DisableColorShader (false);
1525 
1526         glPopMatrix();
1527         glMatrixMode(GL_MODELVIEW);
1528     }
1529 }
1530 
1531 /*
1532 =============
1533 
1534 =============
1535 */
R_DrawFullbrightSprites(void)1536 void R_DrawFullbrightSprites (void)
1537 {
1538 	int		i;
1539 
1540 	if (!r_drawentities.value)
1541 		return;
1542 
1543 	if ( cl_numvisedicts == 0 )
1544             return;
1545 
1546 	glEnable(GL_BLEND);
1547 	glBlendFunc(GL_SRC_ALPHA,GL_ONE);
1548 	glDepthMask(0);
1549 	GL_DisableMultitexture();
1550 	for (i=0 ; i<cl_numvisedicts ; i++)
1551 	{
1552 		currententity = cl_visedicts[i];
1553 
1554 		if (currententity->model->type == mod_sprite) {
1555 			if (((msprite_t *)currententity->model->cache.data)->type >= SPR_VP_PARALLEL_UPRIGHT_OVER) {
1556 				if (currententity->light_lev) {
1557 
1558 					glColor3fv(&currententity->color[0]);
1559 					R_DrawSpriteModel(currententity);
1560 				}
1561 			} else {
1562                             glColor3f(1.0f,1.0f,1.0f);
1563                             R_DrawSpriteModel(currententity);
1564 			}
1565 		}
1566 	}
1567 
1568 	glDisable(GL_BLEND);
1569 	glDepthMask(1);
1570 }
1571 
1572 /*
1573 =============
1574 R_DrawViewModel
1575 
1576 Gunnetje
1577 
1578 =============
1579 */
R_DrawViewModel(void)1580 void R_DrawViewModel (void)
1581 {
1582 
1583 	/*
1584 	if (!r_drawviewmodel.value)
1585 		return;
1586 
1587 	if (chase_active.value)
1588 		return;
1589 
1590 	if (envmap)
1591 		return;
1592 
1593 	if (!r_drawentities.value)
1594 		return;
1595 
1596 	if (cl.items & IT_INVISIBILITY)
1597 		return;
1598 
1599 	if (cl.stats[STAT_HEALTH] <= 0)
1600 		return;
1601 
1602 	if (mirror)
1603 		return;
1604 
1605 	currententity = &cl.viewent;
1606 	if (!currententity->model)
1607 		return;
1608 
1609 	if (currententity->model->type != mod_alias) return;
1610 	*/
1611 
1612 	if (!R_ShouldDrawViewModel()) return;
1613 
1614 	// hack the depth range to prevent view model from poking into walls
1615 	//PENTA: would this work with stencil shadows?
1616 	if ( gl_calcdepth.value ) //Calc Depth (disables shadows on v_ models,
1617 							  //but they don't poke into walls) - Eradicator
1618 		glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
1619 
1620 	//Erad - don't want to lerp view models (disable this to see why ;)
1621 	if (gl_transformlerp.value)
1622 	{
1623 		gl_transformlerp.value = 0;
1624 		R_DrawAliasModel (0.1);
1625 		gl_transformlerp.value = 1;
1626 	}
1627 	else
1628 		R_DrawAliasModel (0.1);
1629 
1630 	if ( gl_calcdepth.value ) //Calc Depth - Eradicator
1631 		glDepthRange (gldepthmin, gldepthmax);
1632 }
1633 
1634 /*
1635 =============
1636 R_DrawViewModel
1637 
1638   Gunnetje
1639 
1640 =============
1641 */
R_DrawViewModelLight(void)1642 void R_DrawViewModelLight (void)
1643 {
1644 	float		colorscale;
1645 	vec3_t		dist;
1646 
1647 	/*
1648 	if (!r_drawviewmodel.value)
1649 		return;
1650 
1651 	if (chase_active.value)
1652 		return;
1653 
1654 	if (envmap)
1655 		return;
1656 
1657 	if (!r_drawentities.value)
1658 		return;
1659 
1660 	if (cl.items & IT_INVISIBILITY)
1661 		return;
1662 
1663 	if (cl.stats[STAT_HEALTH] <= 0)
1664 		return;
1665 
1666 	if (mirror)
1667 		return;
1668 
1669 	currententity = &cl.viewent;
1670 	if (!currententity->model)
1671 		return;
1672 	*/
1673 	if (!R_ShouldDrawViewModel()) return;
1674 
1675 	//We do attent instead of opengl since gl doesn't seem to do
1676 	//what we want, it never really gets to zero.
1677 	VectorSubtract (currententity->origin,currentshadowlight->origin,dist);
1678 	colorscale = 1 - (Length(dist) / currentshadowlight->radius);
1679 
1680 	//if it's to dark we save time by not drawing it
1681 	if (colorscale < 0.1) return;
1682 
1683 	glColor4f(colorscale,colorscale,colorscale,colorscale);
1684 
1685 	R_DrawAliasObjectLight(currententity,R_DrawAliasBumped);
1686 }
1687 
1688 /*
1689 	Returns true if we should draw the view model
1690 */
R_ShouldDrawViewModel(void)1691 qboolean R_ShouldDrawViewModel (void)
1692 {
1693 	if (!r_drawviewmodel.value)
1694 		return false;
1695 
1696 	if (chase_active.value)
1697 		return false;
1698 
1699 	if (envmap)
1700 		return false;
1701 
1702 	if (!r_drawentities.value)
1703 		return false;
1704 
1705 	if (cl.items & IT_INVISIBILITY)
1706 		return false;
1707 
1708 	if (cl.stats[STAT_HEALTH] <= 0)
1709 		return false;
1710 
1711 	if (mirror)
1712 		return false;
1713 	currententity = &cl.viewent;
1714 	if (!currententity->model)
1715 		return false;
1716 
1717 	if (currententity->model->type != mod_alias)
1718 		return false;
1719 
1720 	return true;
1721 }
1722 
1723 extern	cvar_t		v_gamma;
1724 /*
1725 ============
1726 R_AdjustGamma
1727 ============
1728 */
R_AdjustGamma(void)1729 void R_AdjustGamma(void) //Gamma - Eradicator
1730 {
1731 	if (v_gamma.value < 0.2f)
1732 		v_gamma.value = 0.2f;
1733 	if (v_gamma.value >= 1)
1734 	{
1735 		v_gamma.value = 1;
1736 		return;
1737 	}
1738 
1739 	glBlendFunc (GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
1740 	glColor4f (1, 1, 1, v_gamma.value );
1741 	glBegin (GL_QUADS);
1742 	glVertex3f (10, 100, 100);
1743 	glVertex3f (10, -100, 100);
1744 	glVertex3f (10, -100, -100);
1745 	glVertex3f (10, 100, -100);
1746 
1747 	glVertex3f (11, 100, 100);
1748 	glVertex3f (11, -100, 100);
1749 	glVertex3f (11, -100, -100);
1750 	glVertex3f (11, 100, -100);
1751 
1752 	glEnd ();
1753 }
1754 
1755 /*
1756 ============
1757 R_PolyBlend
1758 ============
1759 */
R_PolyBlend(void)1760 void R_PolyBlend (void)
1761 {
1762 	if (!gl_polyblend.value)
1763 		return;
1764 
1765 	GL_DisableMultitexture();
1766 
1767 	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1768 
1769 	glEnable (GL_BLEND);
1770 	glDisable (GL_DEPTH_TEST);
1771 	glDisable (GL_TEXTURE_2D);
1772 
1773       	glLoadIdentity ();
1774 
1775       	glRotatef (-90,  1, 0, 0);	    // put Z going up
1776       	glRotatef (90,  0, 0, 1);	    // put Z going up
1777 
1778 	if (v_blend[3])
1779 	{
1780 		glColor4fv (v_blend);
1781 
1782 		glBegin (GL_QUADS);
1783 
1784 		glVertex3f (10, 100, 100);
1785 		glVertex3f (10, -100, 100);
1786 		glVertex3f (10, -100, -100);
1787 		glVertex3f (10, 100, -100);
1788 		glEnd ();
1789 
1790 	}
1791 
1792 	if (v_gamma.value != 1) //Gamma - Eradicator
1793 		R_AdjustGamma();
1794 
1795 	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1796 	glDisable (GL_BLEND);
1797 	glEnable (GL_TEXTURE_2D);
1798 	glEnable (GL_ALPHA_TEST);
1799 }
1800 
1801 
SignbitsForPlane(mplane_t * out)1802 int SignbitsForPlane (mplane_t *out)
1803 {
1804 	int	bits, j;
1805 
1806 	// for fast box on planeside test
1807 
1808 	bits = 0;
1809 	for (j=0 ; j<3 ; j++)
1810 	{
1811 		if (out->normal[j] < 0)
1812 			bits |= 1<<j;
1813 	}
1814 	return bits;
1815 }
1816 
1817 
R_SetFrustum(void)1818 void R_SetFrustum (void)
1819 {
1820 	int		i;
1821 
1822 	if (r_refdef.fov_x == 90)
1823 	{
1824 		// front side is visible
1825 
1826 		VectorAdd (vpn, vright, frustum[0].normal);
1827 		VectorSubtract (vpn, vright, frustum[1].normal);
1828 
1829 		VectorAdd (vpn, vup, frustum[2].normal);
1830 		VectorSubtract (vpn, vup, frustum[3].normal);
1831 	}
1832 	else
1833 	{
1834 		//Spedup Small Calculations - Eradicator
1835 		RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x * 0.5 ) );
1836 		RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x * 0.5 );
1837 		RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y * 0.5 );
1838 		RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y * 0.5 ) );
1839 	}
1840 
1841 	for (i=0 ; i<4 ; i++)
1842 	{
1843 		frustum[i].type = PLANE_ANYZ;
1844 		frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
1845 		frustum[i].signbits = SignbitsForPlane (&frustum[i]);
1846 	}
1847 }
1848 
1849 
1850 
1851 /*
1852 ===============
1853 R_SetupFrame
1854 ===============
1855 */
R_SetupFrame(void)1856 void R_SetupFrame (void)
1857 {
1858 
1859 // don't allow cheats in multiplayer
1860 	if (cl.maxclients > 1)
1861 	{
1862 		Cvar_Set ("r_fullbright", "0");
1863 		Cvar_Set ("gl_wireframe", "0"); //Disable this is multiplayer  - Eradicator
1864 	}
1865 
1866 	R_AnimateLight ();
1867 
1868 	r_framecount++;
1869 
1870 // build the transformation matrix for the given view angles
1871 	VectorCopy (r_refdef.vieworg, r_origin);
1872 
1873 	AngleVectors (r_refdef.viewangles, vpn, vright, vup);
1874 
1875 // current viewleaf
1876 	r_oldviewleaf = r_viewleaf;
1877 	r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
1878 
1879 	V_SetContentsColor (r_viewleaf->contents);
1880 	V_CalcBlend ();
1881 
1882 	r_cache_thrash = false;
1883 
1884 	c_brush_polys = 0;
1885 	c_alias_polys = 0;
1886 
1887 }
1888 
1889 //PENTA: wasnt in math
1890 //<AWE> Unused. Remove it?
cotan(GLdouble angle)1891 GLdouble cotan(GLdouble angle) {
1892 	return (cos(angle))/sin(angle);
1893 }
1894 
1895 //PENTA: Matrix with infinite far clipping plane
1896 //<AWE> - optimized with static matrix.
1897 //	- "nudge" is now defined as static const.
1898 // 	- p[2][3] was "-nudge" [causing heavy z-fighting on MacOS X], but has to be -1.0.
1899 //	  This issue indicates less precision on the Windows side.
1900 //	- replaced the custom cotan () with 1.0 / tan () [cotan () = cos () / sin ()].
1901 
1902 static const GLdouble nudge = 1.0 - 1.0 / ((GLdouble) (1<<23));
1903 
pentaGlPerspective(GLdouble fov,GLdouble aspectr,GLdouble zNear)1904 void	pentaGlPerspective (GLdouble fov, GLdouble aspectr, GLdouble zNear)
1905 {
1906     static GLdouble	p[4][4]	= {
1907                                         { 0.0,    0.0,    0.0,    0.0 },
1908                                         { 0.0,    0.0,    0.0,    0.0 },
1909                                         { 0.0,    0.0,    0.0,   -1.0 },
1910                                         { 0.0,    0.0,    0.0,    0.0 }
1911                                   };
1912 
1913     p[0][0] = 1.0 / (aspectr * tan (fov));	// <AWE> was: p[0][0] = cotan (fov) / aspectr;
1914     p[1][1] = 1.0 / tan (fov);			// <AWE> was: p[1][1] = cotan (fov);
1915     p[2][2] = -nudge;				// PM: changed again compile error otherwise
1916     p[3][2] = -2.0 * zNear * nudge;
1917 
1918     glLoadMatrixd (&p[0][0]);
1919 }
1920 
1921 //PENTA: Matrix with infinite far clipping plane
1922 //<AWE> Updated with "nudge". Unused. Remove it?
pentaGlFrustum(GLdouble xmin,GLdouble xmax,GLdouble ymin,GLdouble ymax,GLdouble zNear)1923 void pentaGlFrustum( GLdouble xmin, GLdouble xmax, GLdouble ymin, GLdouble ymax, GLdouble zNear)
1924 {
1925     static GLdouble	p[4][4]	= {
1926                                         { 0.0,    0.0,    0.0,    0.0 },
1927                                         { 0.0,    0.0,    0.0,    0.0 },
1928                                         { 0.0,    0.0,	  0.0,   -1.0 },
1929                                         { 0.0,    0.0,    0.0,    0.0 }
1930                                   };
1931 
1932     p[0][0] = 2 * zNear / (xmax - xmin);
1933     p[1][1] = 2 * zNear / (ymax - ymin);
1934     p[2][2] = -nudge;				 // PM: changed again compile error otherwise
1935     p[2][0] = (xmax + xmin) / (xmax - xmin);
1936     p[2][1] = (ymax + ymin) / (ymax - ymin);
1937     p[3][2] = -2.0 * zNear * nudge;		// <AWE> updated with MUL "nudge".
1938 
1939     glLoadMatrixd(&p[0][0]);
1940 }
1941 
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)1942 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
1943 		     GLdouble zNear, GLdouble zFar )
1944 {
1945 /*
1946 <AWE> Unused. Can be removed.
1947    GLdouble xmin, xmax, ymin, ymax;
1948 
1949    ymax = zNear * tan (fovy * M_PI / 360.0);
1950    ymin = -ymax;
1951 
1952    xmin = ymin * aspect;
1953    xmax = ymax * aspect;
1954 
1955    pentaGlFrustum( xmin, xmax, ymin, ymax, zNear);
1956 */
1957    pentaGlPerspective(fovy * M_PI / 360.0, aspect, zNear);
1958 }
1959 
1960 /*
1961 PENTA:
1962 from http://www.markmorley.com/opengl/frustumculling.html
1963 Should clean it up by using procedures.
1964 */
1965 float frustumPlanes[6][4];
1966 
ExtractFrustum()1967 void	ExtractFrustum()	// <AWE> added return type.
1968 {
1969    float   proj[16];
1970    float   modl[16];
1971    float   clip[16];
1972    float   t;
1973 
1974    /* Get the current PROJECTION matrix from OpenGL */
1975    glGetFloatv( GL_PROJECTION_MATRIX, proj );
1976 
1977    /* Get the current MODELVIEW matrix from OpenGL */
1978    glGetFloatv( GL_MODELVIEW_MATRIX, modl );
1979 
1980    /* Combine the two matrices (multiply projection by modelview) */
1981    clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
1982    clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
1983    clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
1984    clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];
1985 
1986    clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
1987    clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
1988    clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
1989    clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];
1990 
1991    clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
1992    clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
1993    clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
1994    clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];
1995 
1996    clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
1997    clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
1998    clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
1999    clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];
2000 
2001    /* Extract the numbers for the RIGHT plane */
2002    frustumPlanes[0][0] = clip[ 3] - clip[ 0];
2003    frustumPlanes[0][1] = clip[ 7] - clip[ 4];
2004    frustumPlanes[0][2] = clip[11] - clip[ 8];
2005    frustumPlanes[0][3] = clip[15] - clip[12];
2006 
2007    /* Normalize the result */
2008    t = sqrt( frustumPlanes[0][0] * frustumPlanes[0][0] + frustumPlanes[0][1] * frustumPlanes[0][1] + frustumPlanes[0][2] * frustumPlanes[0][2] );
2009    frustumPlanes[0][0] /= t;
2010    frustumPlanes[0][1] /= t;
2011    frustumPlanes[0][2] /= t;
2012    frustumPlanes[0][3] /= t;
2013 
2014    /* Extract the numbers for the LEFT plane */
2015    frustumPlanes[1][0] = clip[ 3] + clip[ 0];
2016    frustumPlanes[1][1] = clip[ 7] + clip[ 4];
2017    frustumPlanes[1][2] = clip[11] + clip[ 8];
2018    frustumPlanes[1][3] = clip[15] + clip[12];
2019 
2020    /* Normalize the result */
2021    t = sqrt( frustumPlanes[1][0] * frustumPlanes[1][0] + frustumPlanes[1][1] * frustumPlanes[1][1] + frustumPlanes[1][2] * frustumPlanes[1][2] );
2022    frustumPlanes[1][0] /= t;
2023    frustumPlanes[1][1] /= t;
2024    frustumPlanes[1][2] /= t;
2025    frustumPlanes[1][3] /= t;
2026 
2027    /* Extract the BOTTOM plane */
2028    frustumPlanes[2][0] = clip[ 3] + clip[ 1];
2029    frustumPlanes[2][1] = clip[ 7] + clip[ 5];
2030    frustumPlanes[2][2] = clip[11] + clip[ 9];
2031    frustumPlanes[2][3] = clip[15] + clip[13];
2032 
2033    /* Normalize the result */
2034    t = sqrt( frustumPlanes[2][0] * frustumPlanes[2][0] + frustumPlanes[2][1] * frustumPlanes[2][1] + frustumPlanes[2][2] * frustumPlanes[2][2] );
2035    frustumPlanes[2][0] /= t;
2036    frustumPlanes[2][1] /= t;
2037    frustumPlanes[2][2] /= t;
2038    frustumPlanes[2][3] /= t;
2039 
2040    /* Extract the TOP plane */
2041    frustumPlanes[3][0] = clip[ 3] - clip[ 1];
2042    frustumPlanes[3][1] = clip[ 7] - clip[ 5];
2043    frustumPlanes[3][2] = clip[11] - clip[ 9];
2044    frustumPlanes[3][3] = clip[15] - clip[13];
2045 
2046    /* Normalize the result */
2047    t = sqrt( frustumPlanes[3][0] * frustumPlanes[3][0] + frustumPlanes[3][1] * frustumPlanes[3][1] + frustumPlanes[3][2] * frustumPlanes[3][2] );
2048    frustumPlanes[3][0] /= t;
2049    frustumPlanes[3][1] /= t;
2050    frustumPlanes[3][2] /= t;
2051    frustumPlanes[3][3] /= t;
2052 
2053    /* Extract the FAR plane */
2054    frustumPlanes[4][0] = clip[ 3] - clip[ 2];
2055    frustumPlanes[4][1] = clip[ 7] - clip[ 6];
2056    frustumPlanes[4][2] = clip[11] - clip[10];
2057    frustumPlanes[4][3] = clip[15] - clip[14];
2058 
2059    /* Normalize the result */
2060    t = sqrt( frustumPlanes[4][0] * frustumPlanes[4][0] + frustumPlanes[4][1] * frustumPlanes[4][1] + frustumPlanes[4][2] * frustumPlanes[4][2] );
2061    frustumPlanes[4][0] /= t;
2062    frustumPlanes[4][1] /= t;
2063    frustumPlanes[4][2] /= t;
2064    frustumPlanes[4][3] /= t;
2065 
2066    /* Extract the NEAR plane */
2067    frustumPlanes[5][0] = clip[ 3] + clip[ 2];
2068    frustumPlanes[5][1] = clip[ 7] + clip[ 6];
2069    frustumPlanes[5][2] = clip[11] + clip[10];
2070    frustumPlanes[5][3] = clip[15] + clip[14];
2071 
2072    /* Normalize the result */
2073    t = sqrt( frustumPlanes[5][0] * frustumPlanes[5][0] + frustumPlanes[5][1] * frustumPlanes[5][1] + frustumPlanes[5][2] * frustumPlanes[5][2] );
2074    frustumPlanes[5][0] /= t;
2075    frustumPlanes[5][1] /= t;
2076    frustumPlanes[5][2] /= t;
2077    frustumPlanes[5][3] /= t;
2078 }
2079 
2080 /*
2081 =============
2082 R_SetupGL
2083 =============
2084 */
R_SetupGL(void)2085 void R_SetupGL (void)
2086 {
2087 	float	screenaspect;
2088 	extern	int glwidth, glheight;
2089 	int		x, x2, y2, y, w, h;
2090 
2091 	//
2092 	// set up viewpoint
2093 	//
2094 	glMatrixMode(GL_PROJECTION);
2095     glLoadIdentity ();
2096 	x = r_refdef.vrect.x * glwidth/vid.width;
2097 	x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
2098 	y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
2099 	y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
2100 
2101 	// fudge around because of frac screen scale
2102 	if (x > 0)
2103 		x--;
2104 	if (x2 < glwidth)
2105 		x2++;
2106 	if (y2 < 0)
2107 		y2--;
2108 	if (y < glheight)
2109 		y++;
2110 
2111 	w = x2 - x;
2112 	h = y - y2;
2113 
2114 	if (envmap || mirror || glare)
2115 	{
2116 		x = y2 = 0;
2117 		w = r_refdef.vrect.width;
2118 		h = r_refdef.vrect.height;
2119 	}
2120 
2121 	glViewport (glx + x, gly + y2, w, h);
2122 
2123     screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
2124 	if (mirror) screenaspect = 1.0;
2125 //	yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
2126 	//PENTA: decreased zfar from 4096 to reduce z-fighting on alias models
2127 	// is this ok for quake or do we need to be able to look that far??
2128 	// seems to work, I incr. znear to 5 instead of 4
2129         MYgluPerspective (2.0 *atan((GLdouble) r_refdef.vrect.height / (GLdouble) r_refdef.vrect.width) * 180.0 / M_PI /* r_refdef.fov_y */,  screenaspect,  5.0,  2048.0);
2130 
2131 	if (mirror || glare)
2132 	{
2133 		//If we are mirroring we want to use the screen projection matrix
2134 		//not the texture (=> we just calculated this) one.
2135 		glLoadIdentity();
2136 		glMultMatrixf(r_projection_matrix);
2137 
2138 		if (mirror){
2139 			if (mirror_plane->normal[2])
2140 				glScalef (1, -1, 1);
2141 			else
2142 				glScalef (-1, 1, 1);
2143 		}
2144 	} else {
2145 		//Store it for later mirror use
2146 		glGetFloatv (GL_PROJECTION_MATRIX, r_projection_matrix);
2147 	}
2148 
2149 
2150 	glMatrixMode(GL_MODELVIEW);
2151     glLoadIdentity ();
2152 
2153     glRotatef (-90,  1, 0, 0);	    // put Z going up
2154     glRotatef (90,  0, 0, 1);	    // put Z going up
2155     glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
2156     glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
2157     glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
2158     glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
2159 
2160 	glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
2161 	glGetDoublev (GL_MODELVIEW_MATRIX, r_Dworld_matrix);
2162 	glGetDoublev (GL_PROJECTION_MATRIX, r_Dproject_matrix);
2163 	glGetIntegerv (GL_VIEWPORT, (GLint *) r_Iviewport);	// <AWE> added cast.
2164 	ExtractFrustum();
2165 	//
2166 	// set drawing parms
2167 	//
2168 	if (gl_cull.value)
2169 		glEnable(GL_CULL_FACE);
2170 	else
2171 		glDisable(GL_CULL_FACE);
2172 
2173 	glDisable(GL_BLEND);
2174 	glDisable(GL_ALPHA_TEST);
2175 	glEnable(GL_DEPTH_TEST);
2176 }
2177 
2178 /*
2179 ================
2180 R_RenderScene
2181 
2182 r_refdef must be set before the first call
2183 ================
2184 */
R_RenderScene(void)2185 void R_RenderScene (void)
2186 {
2187 	int i, j;
2188 	shadowlight_t *l = NULL;
2189 
2190 	R_SetupFrame ();
2191 
2192 	R_SetFrustum ();
2193 
2194 	R_SetupGL ();
2195 
2196 	R_MarkLeaves ();	// done here so we know if we're in water, gaat visible leafs marken
2197 
2198 	//if (!mirror)
2199 	R_InitShadowsForFrame ();
2200 
2201 	R_InitDrawWorld();
2202 
2203 	//if (!mirror) {
2204 		//To ensure invariance we have to enable scissoring even for the ambient term
2205 		//But in reality this doen't work (at least on my Geforce2 card) and you still
2206 		//get (few) z-buffer fighting.
2207 	if (!sh_noscissor.value) {
2208 		glScissor(r_Iviewport[0], r_Iviewport[1], r_Iviewport[2], r_Iviewport[3]);
2209 		glEnable(GL_SCISSOR_TEST);
2210 	}
2211 
2212 		//Ambient light drawing
2213 		//this uses the light maps as an ambient term
2214 		//it fills the z buffer
2215 	R_SetupInstants();
2216 
2217 
2218 	//XYZ - moved upwards
2219 	if (gl_wireframe.value) {
2220 		float old = sh_lightmapbright.value;
2221 		sh_lightmapbright.value = 1.0;
2222 		glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
2223 
2224 		R_DrawAmbientEntities();
2225 		//glDisable(GL_TEXTURE_2D);
2226 		R_WorldMultiplyTextures();
2227 		glEnable(GL_TEXTURE_2D);
2228 		sh_lightmapbright.value = old;
2229 		glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
2230 		return;
2231 	}
2232 
2233 	R_DrawViewModel();
2234 	R_DrawAmbientEntities();
2235 	glDepthFunc(GL_LEQUAL);
2236 
2237 	R_WorldMultiplyTextures();
2238 
2239 	//if (mirror) {
2240 	//	sh_lightmapbright.value = 0.3;
2241 	//	return;
2242 	//}
2243 
2244 	if (!sh_noscissor.value) {
2245 		glClear(GL_STENCIL_BUFFER_BIT);
2246 		R_ClearRectList();
2247 	}
2248 
2249 	numClearsSaved = 0;
2250 	aliasCacheRequests = aliasFullCacheHits = aliasPartialCacheHits = 0;
2251 	brushCacheRequests = brushFullCacheHits = brushPartialCacheHits = 0;
2252 
2253 	glFogfv(GL_FOG_COLOR, color_black);
2254 
2255 	for (i=0; i<numUsedShadowLights; i++) {
2256 
2257 		//find a lights that still fits on our current screen plane
2258 		//using the first fit method.
2259 		//Other methods may give better results (exhaustive for example)
2260 		//but i'm convinced you can't save more clears than those that you
2261 		//save with this.
2262 		if ((!sh_nocleversave.value) && (!sh_noscissor.value)) {
2263 			qboolean foundone = false;
2264 			for (j=0; j<numUsedShadowLights; j++) {
2265 
2266 				if (!usedshadowlights[j]->visible) continue;
2267 
2268 				l = usedshadowlights[j];
2269 				currentshadowlight = l;
2270 				if (R_CheckRectList(&l->scizz)) {
2271 					foundone = true;
2272 					break;
2273 				}
2274 			}
2275 
2276 			if (!foundone) {
2277 				R_SetTotalRect(); //Only clear dirty part
2278 				glClear(GL_STENCIL_BUFFER_BIT);
2279 				R_ClearRectList();
2280 				for (j=0; j<numUsedShadowLights; j++) {
2281 					l = usedshadowlights[j];
2282 					currentshadowlight = l;
2283 					if (usedshadowlights[j]->visible) break;
2284 				}
2285 			}
2286 
2287 		} else {
2288 			l = usedshadowlights[i];
2289 			currentshadowlight = l;
2290 		}
2291 
2292 		//Find the polygons that cast shadows for this light
2293 		if (!R_FillShadowChain(l))
2294 			continue;
2295 
2296 		if (sh_visiblevolumes.value) {
2297 			glDepthFunc(GL_LEQUAL);
2298 			glDepthMask(GL_TRUE);
2299 		} else {
2300 			glDepthMask(GL_FALSE);
2301 
2302 			if (l->castShadow) {
2303   				glDepthFunc(GL_LESS);
2304   				glEnable(GL_STENCIL_TEST);
2305 				//glClear(GL_STENCIL_BUFFER_BIT);
2306 				glColorMask(false, false, false, false);
2307 				glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
2308 				if (!sh_noscissor.value) {
2309 					if (R_CheckRectList(&l->scizz)) {
2310 							//we can have another go without clearing
2311 						R_AddRectList(&l->scizz);
2312 						numClearsSaved++;
2313 
2314 					} else {
2315 						R_SetTotalRect(); //Only clear dirty part
2316 						glClear(GL_STENCIL_BUFFER_BIT);
2317 						R_ClearRectList();
2318 						R_AddRectList(&l->scizz);
2319 					}
2320 				} else {
2321 					glClear(GL_STENCIL_BUFFER_BIT);
2322 				}
2323 			}
2324 		}
2325 
2326 		//All right now the shadow stuff
2327 
2328 		glScissor(l->scizz.coords[0], l->scizz.coords[1],
2329 			l->scizz.coords[2]-l->scizz.coords[0],  l->scizz.coords[3]-l->scizz.coords[1]);
2330 
2331 		R_MarkEntitiesOnList();
2332 
2333 		//Shadow casting is on by default
2334 		if (l->castShadow) {
2335 			//Calculate the shadow volume (does nothing when static)
2336 			R_ConstructShadowVolume(l);
2337 
2338 #if 1
2339 			//Pass 1 increase
2340 			glCullFace(GL_BACK);
2341 			glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
2342 			if (sh_worldshadows.value) R_DrawShadowVolume(l);
2343 
2344 			// Second Pass. Decrease Stencil Value In The Shadow
2345 			glCullFace(GL_FRONT);
2346 			glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
2347   			if (sh_worldshadows.value) R_DrawShadowVolume(l);
2348 
2349 			//PENTA: we could do the same thing for brushes as for aliasses
2350 			//Pass 1 increase
2351 			glCullFace(GL_BACK);
2352 			glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
2353 			if (sh_entityshadows.value) R_DrawEntitiesShadowVolumes(mod_brush);
2354 
2355 			// Second Pass. Decrease Stencil Value In The Shadow
2356 			glCullFace(GL_FRONT);
2357 			glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
2358 			if (sh_entityshadows.value) R_DrawEntitiesShadowVolumes(mod_brush);
2359 
2360 #else
2361 //                        glCullFace(GL_FRONT_AND_BACK);
2362                         glDisable(GL_CULL_FACE);
2363                         checkerror();
2364     	                glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
2365                         checkerror();
2366 	                qglStencilFuncSeparateATI(GL_ALWAYS, GL_ALWAYS, 0, ~0);
2367                         checkerror();
2368 	                qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
2369                         checkerror();
2370 	                qglStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
2371                         checkerror();
2372 
2373 			if (sh_worldshadows.value) R_DrawShadowVolume(l);
2374 
2375                         //PENTA: we could do the same thing for brushes as for aliasses
2376 			//Pass 1 increase
2377 			if (sh_entityshadows.value) R_DrawEntitiesShadowVolumes(mod_brush);
2378 
2379                         glEnable(GL_CULL_FACE);
2380 #endif
2381 			if (sh_entityshadows.value)
2382 			    R_DrawEntitiesShadowVolumes(mod_alias);
2383 
2384 			//Reenable drawing
2385 			glCullFace(GL_FRONT);
2386  			glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2387 			glDepthFunc(GL_LEQUAL);
2388 			glStencilFunc(GL_EQUAL, 0, 0xffffffff);
2389 		}
2390 		if (!sh_visiblevolumes.value) {
2391 			R_DrawWorldBumped();
2392 			glPolygonOffset(0,-5);
2393 			glEnable(GL_POLYGON_OFFSET_FILL);
2394 			R_DrawLightEntities(l);
2395 			glDisable(GL_POLYGON_OFFSET_FILL);
2396 		}
2397 		glDisable (GL_BLEND);
2398 		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2399 		glDisable(GL_STENCIL_TEST);
2400 
2401 		//sprites only recive "shadows" from the cubemap not the stencil
2402 
2403 		if (!sh_visiblevolumes.value) {
2404 			R_DrawLightSprites ();
2405 		}
2406 
2407 		glDepthMask(GL_TRUE);
2408 
2409 		if ((i%8) == 0)
2410 			// don't let sound get messed up if going slow
2411 			S_ExtraUpdate ();
2412 
2413 		l->visible = false;
2414 	}
2415 
2416 	glScissor(0, 0, r_Iviewport[2], r_Iviewport[3]);
2417 	glDisable(GL_SCISSOR_TEST);
2418 
2419 	glDepthFunc(GL_LEQUAL);
2420 
2421 	GL_DisableMultitexture();
2422 
2423 	glFogfv(GL_FOG_COLOR, color_black);
2424 
2425 	R_DrawFullbrightSprites();
2426 
2427 	if (skytexturenum >= 0) {
2428 		glColor3f(1,1,1);
2429 		R_DrawSkyChain (cl.worldmodel->textures[skytexturenum]->texturechain);
2430 		cl.worldmodel->textures[skytexturenum]->texturechain = NULL;
2431 	}
2432 
2433 
2434 	R_DrawCaustics();
2435 
2436 	//Removed to fix particle & water bug (see R_RenderView) - Eradicator
2437 	//R_DrawParticles (); //to fix the particles triangles showing up after water
2438 						//put this behind the water drawing#ifdef GLTEST
2439 	R_DrawDecals();
2440 
2441 	glFogfv(GL_FOG_COLOR, fog_color);
2442 }
2443 
R_InitMirrorChains()2444 void R_InitMirrorChains()
2445 {
2446 	int i;
2447 
2448 	for (i=0; i<NUM_MIRROR_PLANES; i++) {
2449 		mirrorplanes[i].texture_object = EasyTgaLoad("penta/mirrordummy.tga");
2450 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
2451 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
2452 	}
2453 
2454 }
2455 
2456 
R_NewMirrorChains()2457 void R_NewMirrorChains()
2458 {
2459 	int i;
2460 
2461 	for (i=0; i<NUM_MIRROR_PLANES; i++) {
2462 		mirrorplanes[i].lockframe = 0;
2463 		mirrorplanes[i].updateframe = 0;
2464 		mirrorplanes[i].chain = NULL;
2465 	}
2466 
2467 }
2468 
2469 
R_ClearMirrorChains()2470 void R_ClearMirrorChains()
2471 {
2472 	int i;
2473 
2474 	for (i=0; i<NUM_MIRROR_PLANES; i++) {
2475 		mirrorplanes[i].chain = NULL;
2476 	}
2477 
2478 	for (i=0 ; i<cl.worldmodel->numtextures ; i++)
2479 	{
2480 		if (!cl.worldmodel->textures[i])
2481 			continue;
2482 		cl.worldmodel->textures[i]->texturechain = NULL;
2483 	}
2484 }
2485 
R_AllocateMirror(msurface_t * surf)2486 void R_AllocateMirror(msurface_t *surf)
2487 {
2488 	int i,oldest,oindex;
2489 	mirrorplane_t *mir = NULL;
2490 	vec3_t	tempnormal;
2491 
2492 	//#define NUM_MIRROR_PLANES 8
2493 	//extern mirrorplane_t mirrorplanes[NUM_MIRROR_PLANES];
2494 
2495 	//see if surface is part of an existing mirror
2496 	for (i=0; i<NUM_MIRROR_PLANES; i++) {
2497 
2498 		VectorCopy(surf->plane->normal,tempnormal);
2499 		//if (surf->flags & SURF_PLANEBACK) {
2500 		//	VectorInverse(tempnormal);
2501 		//}
2502 
2503 		if ((tempnormal[0] == mirrorplanes[i].plane.normal[0]) &&
2504 			(tempnormal[1] == mirrorplanes[i].plane.normal[1]) &&
2505 			(tempnormal[2] == mirrorplanes[i].plane.normal[2]) &&
2506 			(surf->plane->dist == mirrorplanes[i].plane.dist))
2507 		{
2508 			mir = &mirrorplanes[i];
2509 			//Con_Printf("reuse mir %i\n",i);
2510 			break;
2511 		}
2512 	}
2513 
2514 	//allocate new mirror
2515 	if (!mir) {
2516 		oldest = r_framecount;
2517 		oindex = -1;
2518 		for (i=0; i<NUM_MIRROR_PLANES; i++) {
2519 			if (mirrorplanes[i].lockframe < oldest) {
2520 				oldest = mirrorplanes[i].lockframe;
2521 				oindex = i;
2522 			}
2523 		}
2524 
2525 		if (oindex == -1) {
2526 			//Be silent about this
2527 			return;
2528 		}
2529 
2530 		mir = &mirrorplanes[oindex];
2531 		VectorCopy(surf->plane->normal,mir->plane.normal);
2532 		//if (surf->flags & SURF_PLANEBACK) {
2533 		//	VectorInverse(mir->plane.normal);
2534 		//}
2535 		mir->plane.dist = surf->plane->dist;
2536 		mir->plane.type = surf->plane->type;
2537 		mir->plane.signbits = surf->plane->signbits;
2538 		//Con_Printf("New mirror: n: %f %f %f  d:%f\n i: %i",mir->plane.normal[0],mir->plane.normal[1],mir->plane.normal[2],mir->plane.dist,oindex);
2539 	}
2540 
2541 	mir->lockframe = r_framecount;
2542 	surf->texturechain = mir->chain;
2543 	mir->chain = surf;
2544 }
2545 /*
2546 =============
2547 R_Mirror
2548 =============
2549 */
R_Mirror(mirrorplane_t * mir)2550 void R_Mirror (mirrorplane_t *mir)
2551 {
2552 	float		d, olddrawents = 0.0f;
2553 	entity_t	*ent;
2554 	int			ox, oy, ow, oh, ofovx, ofovy, cl_oldvisedicts;
2555 	vec3_t		oang, oorg;
2556 	qboolean	drawplayer;
2557 
2558 	if (mirror) {
2559 		Con_Printf("Warning: Resursive mirrors\n");
2560 		return;
2561 	}
2562 
2563 	mirror = true;
2564 	mirror_plane = &mir->plane;
2565 	memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
2566 
2567 	AngleVectors (r_refdef.viewangles, vpn, vright, vup);
2568 
2569 	//setup mirrored view origin & direction
2570 	VectorCopy(r_refdef.vieworg, oorg);
2571 	d = DotProduct (r_refdef.vieworg, mir->plane.normal) - mir->plane.dist;
2572 
2573 	//camera is to far away from mirror don't update it...
2574 	if (abs(d) > mir_distance.value) {
2575 		mirror = false;
2576 		return;
2577 	}
2578 
2579 	//player is very close to mirror don't draw it since he interects it and this gives bad artefacts
2580 	if (abs(d) < MIN_PLAYER_MIRROR) {
2581 		drawplayer = false;
2582 	} else {
2583 		drawplayer = true;
2584 	}
2585 
2586 	//calculate a far plane for the mirror, stuff to far away from mirrors is not drawn anymore...
2587 	VectorCopy(mir->plane.normal,mirror_far_plane.normal);
2588 	//VectorInverse(mirror_far_plane.normal);
2589 	mirror_far_plane.dist = DotProduct(r_refdef.vieworg,mir->plane.normal) + mir_distance.value;
2590 
2591 	VectorMA (r_refdef.vieworg, -2*d, mir->plane.normal, r_refdef.vieworg);
2592 
2593 	if (d < 0) {
2594 		mirror_clipside = 1;
2595 	} else {
2596 		mirror_clipside = 2;
2597 	}
2598 
2599 	d = DotProduct (vpn, mir->plane.normal);
2600 	VectorMA (vpn, -2*d, mir->plane.normal, vpn);
2601 
2602 	VectorCopy(r_refdef.viewangles, oang);
2603 	r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
2604 	r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
2605 	r_refdef.viewangles[2] = -r_refdef.viewangles[2];
2606 
2607 	//Render to a small view rectangle
2608 	ox = r_refdef.vrect.x;
2609 	oy = r_refdef.vrect.y;
2610 	ow = r_refdef.vrect.width;
2611 	oh = r_refdef.vrect.height;
2612 	ofovx = r_refdef.fov_x;
2613 	ofovy = r_refdef.fov_y;
2614 	r_refdef.vrect.x = 0;
2615 	r_refdef.vrect.y = 0;
2616 	r_refdef.vrect.width = 256;
2617 	r_refdef.vrect.height = 256;
2618 
2619 
2620 //	r_refdef.fov_x = 90.0;
2621 //	r_refdef.fov_y = 90.0;//CalcFov (90.0, r_refdef.vrect.width, r_refdef.vrect.height);
2622 	r_refdef.fov_x = scr_fov.value;
2623 	r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
2624 
2625 
2626 	//Note:  This was probably already a problem with the original quake mirrors
2627 	//the static entities are added in all mirror passes making that by the end of
2628 	//mirror rendering we are rendering the statics multiple times.
2629 	//so we back up the number of entities (dynamics are in front) and later restore it
2630 	cl_oldvisedicts = cl_numvisedicts;
2631 
2632 
2633 	olddrawents = r_drawentities.value;
2634 	if (mir_detail.value < 2) {
2635 		//Don't draw entities
2636 		r_drawentities.value = 0;
2637 	} else {
2638 		//Hack add player to back of list
2639 		if (drawplayer && cl_entities[cl.viewentity].model  && cl_entities[cl.viewentity].model->type == mod_alias) {
2640 			ent = &cl_entities[cl.viewentity];
2641 			if (cl_numvisedicts < MAX_VISEDICTS)
2642 			{
2643 				cl_visedicts[cl_numvisedicts] = ent;
2644 				cl_numvisedicts++;
2645 			}
2646 		}
2647 	}
2648 	//r_drawentities.value = 0;
2649 
2650 	glFrontFace(GL_CW);
2651 	//R_RenderView ();
2652 	//Con_Printf("Render mirror\n");
2653 
2654 	//olddrawents = r_drawentities.value;
2655 	//r_drawentities.value = mir_detail.value-1;
2656 
2657 
2658 	R_RenderScene ();
2659 
2660 	r_drawentities.value = olddrawents;
2661 
2662 	Q_memcpy (mir->matrix, r_world_matrix, sizeof(r_world_matrix));
2663 
2664 	GL_Bind(mir->texture_object);
2665 	glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 256, 256);
2666 	glClear (GL_DEPTH_BUFFER_BIT);
2667 
2668 
2669 	if (mir_detail.value < 2) {
2670 		r_drawentities.value = olddrawents;
2671 	}
2672 
2673 //	r_drawentities.value = 1;
2674 
2675 	r_refdef.vrect.x = ox;
2676 	r_refdef.vrect.y = oy;
2677 	r_refdef.vrect.width = ow;
2678 	r_refdef.vrect.height = oh;
2679 	r_refdef.fov_x = ofovx;
2680 	r_refdef.fov_y = ofovy;
2681 
2682 	cl_numvisedicts = cl_oldvisedicts;
2683 
2684 	VectorCopy(oorg, r_refdef.vieworg);
2685 	VectorCopy(oang, r_refdef.viewangles);
2686 
2687 	// blend on top
2688 	/*
2689 	glMatrixMode(GL_PROJECTION);
2690 	if (mir->plane.normal[2])
2691 		glScalef (1,-1,1);
2692 	else
2693 		glScalef (-1,1,1);
2694 	*/
2695 	glFrontFace(GL_CCW);
2696 	glMatrixMode(GL_MODELVIEW);
2697 
2698 	//glLoadMatrixf (r_base_world_matrix);
2699 	memcpy(r_world_matrix, r_base_world_matrix, sizeof(r_base_world_matrix));
2700 
2701 	mirror = false;
2702 	Sbar_Changed ();
2703 }
2704 
R_RenderMirrors()2705 void R_RenderMirrors()
2706 {
2707 	int i;
2708 	for (i=0; i<NUM_MIRROR_PLANES; i++) {
2709 		if (mirrorplanes[i].chain && ((r_framecount - mirrorplanes[i].updateframe) > mir_frameskip.value)) {
2710 			R_Mirror(&mirrorplanes[i]);
2711 			mirrorplanes[i].lockframe = r_framecount;
2712 			mirrorplanes[i].updateframe = r_framecount;
2713 		}
2714 	}
2715 }
2716 
R_SetupMirrorShader(msurface_t * surf,mirrorplane_t * mir)2717 void R_SetupMirrorShader(msurface_t *surf,mirrorplane_t *mir) {
2718 
2719 	if (mir_detail.value < 1) {
2720 		GL_Bind(newenvmap);
2721 	} else
2722 		GL_Bind(mir->texture_object);
2723 
2724 	if ((surf->flags & SURF_DRAWTURB) && !(surf->flags & SURF_GLASS)) {
2725 		//it is water
2726 		//glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
2727 		glBlendFunc(GL_SRC_ALPHA,GL_ONE);
2728 		glEnable(GL_BLEND);
2729 		return;
2730 	} else {
2731 
2732 		if (surf->flags & SURF_DRAWTURB) {
2733 			glBlendFunc(GL_SRC_ALPHA,GL_ONE);
2734 			glEnable(GL_BLEND);
2735 			return;
2736 		}
2737 
2738 		//it is glass or a mirror
2739 		//GL_EnableMultiTexture();
2740 		glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
2741 		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
2742 		glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
2743 
2744 		GL_EnableMultitexture();
2745 		GL_Bind(surf->texinfo->texture->gl_texturenum);
2746 
2747 		//No colormaps: Color maps are bound on tmu 0 so disable it
2748 		//and let tu1 modulate itself with the light map brightness
2749 		glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
2750 		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
2751 		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
2752 		glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
2753 		glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
2754 		glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
2755 
2756 		GL_Bind(surf->texinfo->texture->gl_texturenum);
2757 	}
2758 }
2759 
R_DisableMirrorShader(msurface_t * surf,mirrorplane_t * mir)2760 void R_DisableMirrorShader(msurface_t *surf,mirrorplane_t *mir) {
2761 
2762 
2763 	if ((surf->flags & SURF_DRAWTURB) && !(surf->flags & SURF_GLASS)) {
2764 		//it is water
2765 		glDisable(GL_BLEND);
2766 		return;
2767 	} else {
2768 
2769 		if (surf->flags & SURF_DRAWTURB) {
2770 			glDisable(GL_BLEND);
2771 			return;
2772 		}
2773 
2774 		glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
2775 		GL_DisableMultitexture();
2776 	}
2777 }
2778 
R_DrawMirrorSurfaces()2779 void R_DrawMirrorSurfaces()
2780 {
2781 	int i;
2782 	msurface_t *s;
2783 
2784 	glBlendFunc(GL_SRC_ALPHA,GL_ONE);
2785 	for (i=0; i<NUM_MIRROR_PLANES; i++) {
2786 		if (mirrorplanes[i].chain) {
2787 
2788 			glMatrixMode(GL_TEXTURE);
2789 
2790 			glPushMatrix();
2791 			if (mir_detail.value > 0) {
2792 				glLoadIdentity();
2793 				glTranslatef(0.5, 0.5, 0);
2794 				glScalef(0.5, 0.5, 0);
2795 				glMultMatrixf (r_projection_matrix);
2796 				glMultMatrixf (r_world_matrix);
2797 			} else {
2798 				//glMultMatrixf (r_projection_matrix);
2799 				glTranslatef(r_refdef.vieworg[0]/1000,r_refdef.vieworg[1]/1000,r_refdef.vieworg[2]/1000);
2800 				glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
2801 				glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
2802 				glEnable(GL_TEXTURE_GEN_S);
2803 				glEnable(GL_TEXTURE_GEN_T);
2804 			}
2805 
2806 			R_SetupMirrorShader(mirrorplanes[i].chain,&mirrorplanes[i]);
2807 
2808 			s = mirrorplanes[i].chain;
2809 
2810 			glNormal3fv(mirrorplanes[i].plane.normal);
2811 			for ( ; s ; s=s->texturechain) {
2812 			if ((s->flags & SURF_GLASS) && (s->flags & SURF_DRAWTURB)) {
2813 					glColor4f(1,1,1,0.5);
2814 					EmitMirrorPolys (s);
2815 				} else if (s->flags & SURF_DRAWTURB) {
2816 					glColor4f(1,1,1,r_wateralpha.value);
2817 					EmitMirrorWaterPolys (s);
2818 				}  else {
2819 					glColor4f(1,1,1,1);
2820 					EmitMirrorPolys (s);
2821 				}
2822 			}
2823 
2824 			R_DisableMirrorShader(mirrorplanes[i].chain,&mirrorplanes[i]);
2825 
2826 			glPopMatrix();
2827         		if (mir_detail.value == 0) {
2828 				glDisable(GL_TEXTURE_GEN_S);
2829 				glDisable(GL_TEXTURE_GEN_T);
2830 			}
2831 			glMatrixMode(GL_MODELVIEW);
2832 		}
2833 	}
2834 	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
2835 }
2836 
2837 /*
2838 =============
2839 R_Clear
2840 =============
2841 */
R_Clear(void)2842 void R_Clear (void)
2843 {
2844 	/*if (r_mirroralpha.value != 1.0)
2845 	{
2846 		if (gl_clear.value)
2847 			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2848 		else
2849 			glClear (GL_DEPTH_BUFFER_BIT);
2850 		gldepthmin = 0;
2851 		gldepthmax = 0.5;
2852 		glDepthFunc (GL_LEQUAL);
2853 	}
2854 	else if (gl_ztrick.value) PENTA: Removed
2855 	{
2856 		static int trickframe;
2857 
2858 		if (gl_clear.value)
2859 			glClear (GL_COLOR_BUFFER_BIT);
2860 
2861 		trickframe++;
2862 		if (trickframe & 1)
2863 		{
2864 			gldepthmin = 0;
2865 			gldepthmax = 0.49999;
2866 			glDepthFunc (GL_LEQUAL);
2867 		}
2868 		else
2869 		{
2870 			gldepthmin = 1;
2871 			gldepthmax = 0.5;
2872 			glDepthFunc (GL_GEQUAL);
2873 		}
2874 	}
2875 	else*/
2876 
2877 	{
2878 		if (gl_clear.value || gl_wireframe.value)
2879 			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2880 		else
2881 			glClear (GL_DEPTH_BUFFER_BIT);
2882 		gldepthmin = 0;
2883 		gldepthmax = 1;
2884 		glDepthFunc (GL_LEQUAL);
2885 	}
2886 
2887 	glDepthRange (gldepthmin, gldepthmax);
2888 }
2889 
2890 /*
2891 ================
2892 R_RenderView
2893 
2894 r_refdef must be set before the first call
2895 ================
2896 */
R_RenderView(void)2897 void R_RenderView (void)
2898 {
2899 	double	time1 = 0.0, time2;
2900 	GLfloat colors[4] = {(GLfloat) 0.2, (GLfloat) 0.1, (GLfloat) 0.0, (GLfloat) 0.20};
2901 	float oldfogen;
2902 	int	viewcont;
2903 
2904 	if (r_norefresh.value)
2905 		return;
2906 
2907 	if (!r_worldentity.model || !cl.worldmodel)
2908 		Sys_Error ("R_RenderView: NULL worldmodel");
2909 
2910 	mirror = false;
2911 
2912 
2913 	if (gl_finish.value)
2914 		glFinish ();
2915 
2916 	R_Clear ();
2917 
2918 	viewcont = CL_PointContents(r_origin);
2919 	fog_color[3] = 1.0;
2920 	if ((viewcont == CONTENTS_WATER) && (fog_waterfog.value)){
2921 		glFogi(GL_FOG_MODE, GL_LINEAR);
2922 		fog_color[0] = 64/255.0;
2923 		fog_color[1] = 48/255.0;
2924 		fog_color[2] = 0.0;
2925 		glFogfv(GL_FOG_COLOR, fog_color);
2926 		glFogf(GL_FOG_END, 512);
2927 		glFogf(GL_FOG_START, 0);
2928 		glEnable(GL_FOG);
2929 		oldfogen = fog_enabled.value;
2930 		fog_enabled.value = 1.0;
2931 	} else 	if ((viewcont == CONTENTS_SLIME) && (fog_waterfog.value)){
2932 		glFogi(GL_FOG_MODE, GL_LINEAR);
2933 		fog_color[0] = 0.0;
2934 		fog_color[1] = 128/255.0;
2935 		fog_color[2] = 32/255.0;
2936 		glFogfv(GL_FOG_COLOR, fog_color);
2937 		glFogf(GL_FOG_END, 256);
2938 		glFogf(GL_FOG_START, 0);
2939 		glEnable(GL_FOG);
2940 		oldfogen = fog_enabled.value;
2941 		fog_enabled.value = 1.0;
2942 	} else 	if ((viewcont == CONTENTS_LAVA) && (fog_waterfog.value)){
2943 		glFogi(GL_FOG_MODE, GL_LINEAR);
2944 		fog_color[0] = 255/255.0;
2945 		fog_color[1] = 64/255.0;
2946 		fog_color[2] = 0.0;
2947 		glFogfv(GL_FOG_COLOR, fog_color);
2948 		glFogf(GL_FOG_END, 256);
2949 		glFogf(GL_FOG_START, 0);
2950 		glEnable(GL_FOG);
2951 		oldfogen = fog_enabled.value;
2952 		fog_enabled.value = 1.0;
2953 
2954 	} else {
2955 		glFogi(GL_FOG_MODE, GL_LINEAR);
2956 		fog_color[0] = fog_r.value/255.0;
2957 		fog_color[1] = fog_g.value/255.0;
2958 		fog_color[2] = fog_b.value/255.0;
2959 		glFogfv(GL_FOG_COLOR, fog_color);
2960 		glFogf(GL_FOG_END, fog_end.value);
2961 		glFogf(GL_FOG_START, fog_start.value);
2962 		if (fog_enabled.value && !gl_wireframe.value)
2963 			glEnable(GL_FOG);
2964 	}
2965 
2966 	if (mir_detail.value > 0) {
2967 		R_RenderMirrors();
2968 		//	glClear (GL_DEPTH_BUFFER_BIT);
2969 	}
2970 
2971 	R_ClearMirrorChains();
2972 
2973 	R_Glare ();
2974 
2975 	R_ClearMirrorChains();
2976 
2977 	// render normal view
2978 
2979 	R_RenderScene ();
2980 	//R_DrawViewModel ();
2981 
2982 	/*Rendering fog in black for particles is done to stop triangle effect on the
2983 	particles. It is done right before and fixed after each particle draw function
2984 	to avoid effection fog on the water. A particle draw is done after the water
2985 	draw to make sure particles are rendered over the surface of the water. - Eradicator*/
2986 
2987 	R_DrawWaterSurfaces ();
2988 	R_DrawMirrorSurfaces ();
2989 
2990 //  More fog right here :)
2991 
2992 	if ((viewcont == CONTENTS_WATER) && (fog_waterfog.value)){
2993 		fog_enabled.value = oldfogen;
2994 	}
2995 	glDisable(GL_FOG);
2996 //  End of all fog code...
2997 
2998 	//glFogfv(GL_FOG_COLOR, color_black); //Stops triangle effect on particles
2999 	R_DrawParticles (); //Fixes particle & water bug
3000 	//glFogfv(GL_FOG_COLOR, fog_color); //Real fog colour
3001 
3002 	//Draw a poly over the screen (underwater, slime, blood hit)
3003 	R_DrawGlare() ;
3004 	R_PolyBlend ();
3005 }
3006