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