• 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 cvar_t	r_netgraph = CVAR2("r_netgraph","0");
88 
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","0");
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_finish = CVAR2("gl_finish","0");
101 
102 extern	cvar_t	gl_ztrick;
103 extern	cvar_t	scr_fov;
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 	//ZOID: fixed z angle
129     glRotatef (e->angles[2],  1, 0, 0);
130 }
131 
132 /*
133 =============================================================
134 
135   SPRITE MODELS
136 
137 =============================================================
138 */
139 
140 /*
141 ================
142 R_GetSpriteFrame
143 ================
144 */
R_GetSpriteFrame(entity_t * currententity)145 mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
146 {
147 	msprite_t		*psprite;
148 	mspritegroup_t	*pspritegroup;
149 	mspriteframe_t	*pspriteframe;
150 	int				i, numframes, frame;
151 	float			*pintervals, fullinterval, targettime, time;
152 
153 	psprite = currententity->model->cache.data;
154 	frame = currententity->frame;
155 
156 	if ((frame >= psprite->numframes) || (frame < 0))
157 	{
158 		Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
159 		frame = 0;
160 	}
161 
162 	if (psprite->frames[frame].type == SPR_SINGLE)
163 	{
164 		pspriteframe = psprite->frames[frame].frameptr;
165 	}
166 	else
167 	{
168 		pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
169 		pintervals = pspritegroup->intervals;
170 		numframes = pspritegroup->numframes;
171 		fullinterval = pintervals[numframes-1];
172 
173 		time = cl.time + currententity->syncbase;
174 
175 	// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
176 	// are positive, so we don't have to worry about division by 0
177 		targettime = time - ((int)(time / fullinterval)) * fullinterval;
178 
179 		for (i=0 ; i<(numframes-1) ; i++)
180 		{
181 			if (pintervals[i] > targettime)
182 				break;
183 		}
184 
185 		pspriteframe = pspritegroup->frames[i];
186 	}
187 
188 	return pspriteframe;
189 }
190 
191 
192 /*
193 =================
194 R_DrawSpriteModel
195 
196 =================
197 */
R_DrawSpriteModel(entity_t * e)198 void R_DrawSpriteModel (entity_t *e)
199 {
200 	vec3_t	point;
201 	mspriteframe_t	*frame;
202 	float		*up, *right;
203 	vec3_t		v_forward, v_right, v_up;
204 	msprite_t		*psprite;
205 
206 	// don't even bother culling, because it's just a single
207 	// polygon without a surface cache
208 	frame = R_GetSpriteFrame (e);
209 	psprite = currententity->model->cache.data;
210 
211 	if (psprite->type == SPR_ORIENTED)
212 	{	// bullet marks on walls
213 		AngleVectors (currententity->angles, v_forward, v_right, v_up);
214 		up = v_up;
215 		right = v_right;
216 	}
217 	else
218 	{	// normal sprite
219 		up = vup;
220 		right = vright;
221 	}
222 
223 	glColor3f (1,1,1);
224 
225 	GL_DisableMultitexture();
226 
227     GL_Bind(frame->gl_texturenum);
228 
229 	glEnable (GL_ALPHA_TEST);
230 
231 #ifdef USE_OPENGLES
232 	// !!! Need to implement this !!!
233 
234 #else
235 	glBegin (GL_QUADS);
236 
237 	glTexCoord2f (0, 1);
238 	VectorMA (e->origin, frame->down, up, point);
239 	VectorMA (point, frame->left, right, point);
240 	glVertex3fv (point);
241 
242 	glTexCoord2f (0, 0);
243 	VectorMA (e->origin, frame->up, up, point);
244 	VectorMA (point, frame->left, right, point);
245 	glVertex3fv (point);
246 
247 	glTexCoord2f (1, 0);
248 	VectorMA (e->origin, frame->up, up, point);
249 	VectorMA (point, frame->right, right, point);
250 	glVertex3fv (point);
251 
252 	glTexCoord2f (1, 1);
253 	VectorMA (e->origin, frame->down, up, point);
254 	VectorMA (point, frame->right, right, point);
255 	glVertex3fv (point);
256 
257 	glEnd ();
258 #endif
259 
260 	glDisable (GL_ALPHA_TEST);
261 }
262 
263 /*
264 =============================================================
265 
266   ALIAS MODELS
267 
268 =============================================================
269 */
270 
271 
272 #define NUMVERTEXNORMALS	162
273 
274 float	r_avertexnormals[NUMVERTEXNORMALS][3] = {
275 #include "anorms.h"
276 };
277 
278 vec3_t	shadevector;
279 float	shadelight, ambientlight;
280 
281 // precalculated dot products for quantized angles
282 #define SHADEDOT_QUANT 16
283 float	r_avertexnormal_dots[SHADEDOT_QUANT][256] =
284 #include "anorm_dots.h"
285 ;
286 
287 float	*shadedots = r_avertexnormal_dots[0];
288 
289 int	lastposenum;
290 
291 /*
292 =============
293 GL_DrawAliasFrame
294 =============
295 */
GL_DrawAliasFrame(aliashdr_t * paliashdr,int posenum)296 void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
297 {
298 	float 	l;
299 	trivertx_t	*verts;
300 	int		*order;
301 	int		count;
302 
303 lastposenum = posenum;
304 
305 	verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
306 	verts += posenum * paliashdr->poseverts;
307 	order = (int *)((byte *)paliashdr + paliashdr->commands);
308 
309 	while (1)
310 	{
311 		// get the vertex count and primitive type
312 		count = *order++;
313 		if (!count)
314 			break;		// done
315 
316 #ifdef USE_OPENGLES
317 		{
318 			int primType;
319 			float color[3*256];
320 			float vertex[3*256];
321 			int c;
322 			float* pColor;
323 			float* pVertex;
324 
325 			if (count < 0)
326 			{
327 				count = -count;
328 				primType = GL_TRIANGLE_FAN;
329 			}
330 			else
331 				primType = GL_TRIANGLE_STRIP;
332 
333 			// texture coordinates come from the draw list
334 			glTexCoordPointer(2, GL_FLOAT, 0, order);
335 
336 			pColor = color;
337 			pVertex = vertex;
338 			for(c = 0; c < count; c++)
339 			{
340 				// normals and vertexes come from the frame list
341 				l = shadedots[verts->lightnormalindex] * shadelight;
342 				*pColor++ = l;
343 				*pColor++ = l;
344 				*pColor++ = l;
345 				*pVertex++ = verts->v[0];
346 				*pVertex++ = verts->v[1];
347 				*pVertex++ = verts->v[2];
348 				verts++;
349 			}
350 
351 			glColorPointer(3, GL_FLOAT, 0, color);
352 			glVertexPointer(3, GL_FLOAT, 0, vertex);
353 
354 			glDrawArrays(primType, 0, count);
355 
356 			order += 2 * count;
357 		}
358 
359 #else
360 		if (count < 0)
361 		{
362 			count = -count;
363 			glBegin (GL_TRIANGLE_FAN);
364 		}
365 		else
366 			glBegin (GL_TRIANGLE_STRIP);
367 
368 		do
369 		{
370 			// texture coordinates come from the draw list
371 			glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
372 			order += 2;
373 
374 			// normals and vertexes come from the frame list
375 			l = shadedots[verts->lightnormalindex] * shadelight;
376 			glColor3f (l, l, l);
377 			glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
378 			verts++;
379 		} while (--count);
380 
381 		glEnd ();
382 #endif
383 	}
384 }
385 
386 
387 /*
388 =============
389 GL_DrawAliasShadow
390 =============
391 */
392 extern	vec3_t			lightspot;
393 
GL_DrawAliasShadow(aliashdr_t * paliashdr,int posenum)394 void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
395 {
396 	trivertx_t	*verts;
397 	int		*order;
398 	vec3_t	point;
399 	float	height, lheight;
400 	int		count;
401 
402 	lheight = currententity->origin[2] - lightspot[2];
403 
404 	height = 0;
405 	verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
406 	verts += posenum * paliashdr->poseverts;
407 	order = (int *)((byte *)paliashdr + paliashdr->commands);
408 
409 	height = -lheight + 1.0;
410 
411 	while (1)
412 	{
413 		// get the vertex count and primitive type
414 		count = *order++;
415 		if (!count)
416 			break;		// done
417 
418 #ifdef USE_OPENGLES
419 
420 		// !!! Implement this (based on GL_DrawAlias)
421 		break;
422 #else
423 
424 		if (count < 0)
425 		{
426 			count = -count;
427 			glBegin (GL_TRIANGLE_FAN);
428 		}
429 		else
430 			glBegin (GL_TRIANGLE_STRIP);
431 
432 		do
433 		{
434 			// texture coordinates come from the draw list
435 			// (skipped for shadows) glTexCoord2fv ((float *)order);
436 			order += 2;
437 
438 			// normals and vertexes come from the frame list
439 			point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
440 			point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
441 			point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
442 
443 			point[0] -= shadevector[0]*(point[2]+lheight);
444 			point[1] -= shadevector[1]*(point[2]+lheight);
445 			point[2] = height;
446 //			height -= 0.001;
447 			glVertex3fv (point);
448 
449 			verts++;
450 		} while (--count);
451 
452 		glEnd ();
453 
454 #endif
455 
456 	}
457 }
458 
459 
460 
461 /*
462 =================
463 R_SetupAliasFrame
464 
465 =================
466 */
R_SetupAliasFrame(int frame,aliashdr_t * paliashdr)467 void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
468 {
469 	int				pose, numposes;
470 	float			interval;
471 
472 	if ((frame >= paliashdr->numframes) || (frame < 0))
473 	{
474 		Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
475 		frame = 0;
476 	}
477 
478 	pose = paliashdr->frames[frame].firstpose;
479 	numposes = paliashdr->frames[frame].numposes;
480 
481 	if (numposes > 1)
482 	{
483 		interval = paliashdr->frames[frame].interval;
484 		pose += (int)(cl.time / interval) % numposes;
485 	}
486 
487 	GL_DrawAliasFrame (paliashdr, pose);
488 }
489 
490 
491 
492 /*
493 =================
494 R_DrawAliasModel
495 
496 =================
497 */
R_DrawAliasModel(entity_t * e)498 void R_DrawAliasModel (entity_t *e)
499 {
500 	int			i;
501 	int			lnum;
502 	vec3_t		dist;
503 	float		add;
504 	model_t		*clmodel;
505 	vec3_t		mins, maxs;
506 	aliashdr_t	*paliashdr;
507 	float		an;
508 	int			anim;
509 
510 	clmodel = currententity->model;
511 
512 	VectorAdd (currententity->origin, clmodel->mins, mins);
513 	VectorAdd (currententity->origin, clmodel->maxs, maxs);
514 
515 	if (R_CullBox (mins, maxs))
516 		return;
517 
518 
519 	VectorCopy (currententity->origin, r_entorigin);
520 	VectorSubtract (r_origin, r_entorigin, modelorg);
521 
522 	//
523 	// get lighting information
524 	//
525 
526 	ambientlight = shadelight = R_LightPoint (currententity->origin);
527 
528 	// allways give the gun some light
529 	if (e == &cl.viewent && ambientlight < 24)
530 		ambientlight = shadelight = 24;
531 
532 	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
533 	{
534 		if (cl_dlights[lnum].die >= cl.time)
535 		{
536 			VectorSubtract (currententity->origin,
537 							cl_dlights[lnum].origin,
538 							dist);
539 			add = cl_dlights[lnum].radius - Length(dist);
540 
541 			if (add > 0) {
542 				ambientlight += add;
543 				//ZOID models should be affected by dlights as well
544 				shadelight += add;
545 			}
546 		}
547 	}
548 
549 	// clamp lighting so it doesn't overbright as much
550 	if (ambientlight > 128)
551 		ambientlight = 128;
552 	if (ambientlight + shadelight > 192)
553 		shadelight = 192 - ambientlight;
554 
555 	// ZOID: never allow players to go totally black
556 	if (!strcmp(clmodel->name, "progs/player.mdl")) {
557 		if (ambientlight < 8)
558 			ambientlight = shadelight = 8;
559 
560 	} else if (!strcmp (clmodel->name, "progs/flame2.mdl")
561 		|| !strcmp (clmodel->name, "progs/flame.mdl") )
562 		// HACK HACK HACK -- no fullbright colors, so make torches full light
563 		ambientlight = shadelight = 256;
564 
565 	shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
566 	shadelight = shadelight / 200.0;
567 
568 	an = e->angles[1]/180*M_PI;
569 	shadevector[0] = cos(-an);
570 	shadevector[1] = sin(-an);
571 	shadevector[2] = 1;
572 	VectorNormalize (shadevector);
573 
574 	//
575 	// locate the proper data
576 	//
577 	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
578 
579 	c_alias_polys += paliashdr->numtris;
580 
581 	//
582 	// draw all the triangles
583 	//
584 
585 	GL_DisableMultitexture();
586 
587     glPushMatrix ();
588 	R_RotateForEntity (e);
589 
590 	if (!strcmp (clmodel->name, "progs/eyes.mdl") ) {
591 		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
592 	// double size of eyes, since they are really hard to see in gl
593 		glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
594 	} else {
595 		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
596 		glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
597 	}
598 
599 	anim = (int)(cl.time*10) & 3;
600     GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);
601 
602 	// we can't dynamically colormap textures, so they are cached
603 	// seperately for the players.  Heads are just uncolored.
604 	if (currententity->scoreboard && !gl_nocolors.value)
605 	{
606 		i = currententity->scoreboard - cl.players;
607 		if (!currententity->scoreboard->skin) {
608 			Skin_Find(currententity->scoreboard);
609 			R_TranslatePlayerSkin(i);
610 		}
611 		if (i >= 0 && i<MAX_CLIENTS)
612 		    GL_Bind(playertextures + i);
613 	}
614 
615 	if (gl_smoothmodels.value)
616 		glShadeModel (GL_SMOOTH);
617 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
618 
619 	if (gl_affinemodels.value)
620 		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
621 
622 	R_SetupAliasFrame (currententity->frame, paliashdr);
623 
624 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
625 
626 	glShadeModel (GL_FLAT);
627 	if (gl_affinemodels.value)
628 		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
629 
630 	glPopMatrix ();
631 
632 	if (r_shadows.value)
633 	{
634 		glPushMatrix ();
635 		R_RotateForEntity (e);
636 		glDisable (GL_TEXTURE_2D);
637 		glEnable (GL_BLEND);
638 		glColor4f (0,0,0,0.5);
639 		GL_DrawAliasShadow (paliashdr, lastposenum);
640 		glEnable (GL_TEXTURE_2D);
641 		glDisable (GL_BLEND);
642 		glColor4f (1,1,1,1);
643 		glPopMatrix ();
644 	}
645 
646 }
647 
648 //==================================================================================
649 
650 /*
651 =============
652 R_DrawEntitiesOnList
653 =============
654 */
R_DrawEntitiesOnList(void)655 void R_DrawEntitiesOnList (void)
656 {
657 	int		i;
658 
659 	if (!r_drawentities.value)
660 		return;
661 
662 	// draw sprites seperately, because of alpha blending
663 	for (i=0 ; i<cl_numvisedicts ; i++)
664 	{
665 		currententity = &cl_visedicts[i];
666 
667 		switch (currententity->model->type)
668 		{
669 		case mod_alias:
670 			R_DrawAliasModel (currententity);
671 			break;
672 
673 		case mod_brush:
674 			R_DrawBrushModel (currententity);
675 			break;
676 
677 		default:
678 			break;
679 		}
680 	}
681 
682 	for (i=0 ; i<cl_numvisedicts ; i++)
683 	{
684 		currententity = &cl_visedicts[i];
685 
686 		switch (currententity->model->type)
687 		{
688 		case mod_sprite:
689 			R_DrawSpriteModel (currententity);
690 			break;
691 
692 		default :
693 			break;
694 		}
695 	}
696 }
697 
698 /*
699 =============
700 R_DrawViewModel
701 =============
702 */
R_DrawViewModel(void)703 void R_DrawViewModel (void)
704 {
705 	float		ambient[4], diffuse[4];
706 	int			j;
707 	int			lnum;
708 	vec3_t		dist;
709 	float		add;
710 	dlight_t	*dl;
711 	int			ambientlight, shadelight;
712 
713 	if (!r_drawviewmodel.value || !Cam_DrawViewModel())
714 		return;
715 
716 	if (envmap)
717 		return;
718 
719 	if (!r_drawentities.value)
720 		return;
721 
722 	if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
723 		return;
724 
725 	if (cl.stats[STAT_HEALTH] <= 0)
726 		return;
727 
728 	currententity = &cl.viewent;
729 	if (!currententity->model)
730 		return;
731 
732 	j = R_LightPoint (currententity->origin);
733 
734 	if (j < 24)
735 		j = 24;		// allways give some light on gun
736 	ambientlight = j;
737 	shadelight = j;
738 
739 // add dynamic lights
740 	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
741 	{
742 		dl = &cl_dlights[lnum];
743 		if (!dl->radius)
744 			continue;
745 		if (!dl->radius)
746 			continue;
747 		if (dl->die < cl.time)
748 			continue;
749 
750 		VectorSubtract (currententity->origin, dl->origin, dist);
751 		add = dl->radius - Length(dist);
752 		if (add > 0)
753 			ambientlight += add;
754 	}
755 
756 	ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128;
757 	diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;
758 
759 	// hack the depth range to prevent view model from poking into walls
760 #ifdef USE_OPENGLES
761 	glDepthRangef(gldepthmin, gldepthmin + 0.3f*(gldepthmax-gldepthmin));
762 	R_DrawAliasModel (currententity);
763 	glDepthRangef(gldepthmin, gldepthmax);
764 #else
765 	glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
766 	R_DrawAliasModel (currententity);
767 	glDepthRange (gldepthmin, gldepthmax);
768 #endif
769 }
770 
771 
772 /*
773 ============
774 R_PolyBlend
775 ============
776 */
R_PolyBlend(void)777 void R_PolyBlend (void)
778 {
779 	if (!gl_polyblend.value)
780 		return;
781 	if (!v_blend[3])
782 		return;
783 
784 //Con_Printf("R_PolyBlend(): %4.2f %4.2f %4.2f %4.2f\n",v_blend[0], v_blend[1],	v_blend[2],	v_blend[3]);
785 
786  	GL_DisableMultitexture();
787 
788 	glDisable (GL_ALPHA_TEST);
789 	glEnable (GL_BLEND);
790 	glDisable (GL_DEPTH_TEST);
791 	glDisable (GL_TEXTURE_2D);
792 
793     glLoadIdentity ();
794 
795     glRotatef (-90,  1, 0, 0);	    // put Z going up
796     glRotatef (90,  0, 0, 1);	    // put Z going up
797 
798 	glColor4fv (v_blend);
799 
800 #ifdef USE_OPENGLES
801 	// !!! Implement this
802 #else
803 	glBegin (GL_QUADS);
804 
805 	glVertex3f (10, 100, 100);
806 	glVertex3f (10, -100, 100);
807 	glVertex3f (10, -100, -100);
808 	glVertex3f (10, 100, -100);
809 	glEnd ();
810 #endif
811 
812 	glDisable (GL_BLEND);
813 	glEnable (GL_TEXTURE_2D);
814 	glEnable (GL_ALPHA_TEST);
815 }
816 
817 
SignbitsForPlane(mplane_t * out)818 int SignbitsForPlane (mplane_t *out)
819 {
820 	int	bits, j;
821 
822 	// for fast box on planeside test
823 
824 	bits = 0;
825 	for (j=0 ; j<3 ; j++)
826 	{
827 		if (out->normal[j] < 0)
828 			bits |= 1<<j;
829 	}
830 	return bits;
831 }
832 
833 
R_SetFrustum(void)834 void R_SetFrustum (void)
835 {
836 	int		i;
837 
838 	if (r_refdef.fov_x == 90)
839 	{
840 		// front side is visible
841 
842 		VectorAdd (vpn, vright, frustum[0].normal);
843 		VectorSubtract (vpn, vright, frustum[1].normal);
844 
845 		VectorAdd (vpn, vup, frustum[2].normal);
846 		VectorSubtract (vpn, vup, frustum[3].normal);
847 	}
848 	else
849 	{
850 
851 		// rotate VPN right by FOV_X/2 degrees
852 		RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
853 		// rotate VPN left by FOV_X/2 degrees
854 		RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
855 		// rotate VPN up by FOV_X/2 degrees
856 		RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
857 		// rotate VPN down by FOV_X/2 degrees
858 		RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
859 	}
860 
861 	for (i=0 ; i<4 ; i++)
862 	{
863 		frustum[i].type = PLANE_ANYZ;
864 		frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
865 		frustum[i].signbits = SignbitsForPlane (&frustum[i]);
866 	}
867 }
868 
869 
870 
871 /*
872 ===============
873 R_SetupFrame
874 ===============
875 */
R_SetupFrame(void)876 void R_SetupFrame (void)
877 {
878 // don't allow cheats in multiplayer
879 	r_fullbright.value = 0;
880 	r_lightmap.value = 0;
881 	if (!atoi(Info_ValueForKey(cl.serverinfo, "watervis")))
882 		r_wateralpha.value = 1;
883 
884 	R_AnimateLight ();
885 
886 	r_framecount++;
887 
888 // build the transformation matrix for the given view angles
889 	VectorCopy (r_refdef.vieworg, r_origin);
890 
891 	AngleVectors (r_refdef.viewangles, vpn, vright, vup);
892 
893 // current viewleaf
894 	r_oldviewleaf = r_viewleaf;
895 	r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
896 
897 	V_SetContentsColor (r_viewleaf->contents);
898 	V_CalcBlend ();
899 
900 	r_cache_thrash = false;
901 
902 	c_brush_polys = 0;
903 	c_alias_polys = 0;
904 
905 }
906 
907 #ifdef USE_OPENGLES
908 
MYgluPerspective(float fovy,float aspect,float zNear,float zFar)909 void MYgluPerspective( float fovy, float aspect,
910 		     float zNear, float zFar )
911 {
912    float xmin, xmax, ymin, ymax;
913 
914    ymax = zNear * tan( fovy * M_PI / 360.0f );
915    ymin = -ymax;
916 
917    xmin = ymin * aspect;
918    xmax = ymax * aspect;
919 
920    glFrustumf( xmin, xmax, ymin, ymax, zNear, zFar );
921 }
922 
923 #else
924 
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)925 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
926 		     GLdouble zNear, GLdouble zFar )
927 {
928    GLdouble xmin, xmax, ymin, ymax;
929 
930    ymax = zNear * tan( fovy * M_PI / 360.0 );
931    ymin = -ymax;
932 
933    xmin = ymin * aspect;
934    xmax = ymax * aspect;
935 
936    glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
937 }
938 #endif
939 
940 /*
941 =============
942 R_SetupGL
943 =============
944 */
R_SetupGL(void)945 void R_SetupGL (void)
946 {
947 	float	screenaspect;
948 	extern	int glwidth, glheight;
949 	int		x, x2, y2, y, w, h;
950 
951 	//
952 	// set up viewpoint
953 	//
954 	glMatrixMode(GL_PROJECTION);
955     glLoadIdentity ();
956 	x = r_refdef.vrect.x * glwidth/vid.width;
957 	x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
958 	y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
959 	y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
960 
961 	// fudge around because of frac screen scale
962 	if (x > 0)
963 		x--;
964 	if (x2 < glwidth)
965 		x2++;
966 	if (y2 < 0)
967 		y2--;
968 	if (y < glheight)
969 		y++;
970 
971 	w = x2 - x;
972 	h = y - y2;
973 
974 	if (envmap)
975 	{
976 		x = y2 = 0;
977 		w = h = 256;
978 	}
979 
980 	glViewport (glx + x, gly + y2, w, h);
981     screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
982 //	yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
983 //	yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect;
984 //	yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI;
985 //    MYgluPerspective (yfov,  screenaspect,  4,  4096);
986     MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  4096);
987 
988 	if (mirror)
989 	{
990 		if (mirror_plane->normal[2])
991 			glScalef (1, -1, 1);
992 		else
993 			glScalef (-1, 1, 1);
994 		glCullFace(GL_BACK);
995 	}
996 	else
997 		glCullFace(GL_FRONT);
998 
999 	glMatrixMode(GL_MODELVIEW);
1000     glLoadIdentity ();
1001 
1002     glRotatef (-90,  1, 0, 0);	    // put Z going up
1003     glRotatef (90,  0, 0, 1);	    // put Z going up
1004     glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
1005     glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
1006     glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
1007     glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
1008 
1009 #ifdef USE_OPENGLES
1010 	glGetIntegerv (MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES, (GLint*) r_world_matrix);
1011 #else
1012 	glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
1013 #endif
1014 
1015 	//
1016 	// set drawing parms
1017 	//
1018 	if (gl_cull.value)
1019 		glEnable(GL_CULL_FACE);
1020 	else
1021 		glDisable(GL_CULL_FACE);
1022 
1023 	glDisable(GL_BLEND);
1024 	glDisable(GL_ALPHA_TEST);
1025 	glEnable(GL_DEPTH_TEST);
1026 }
1027 
1028 /*
1029 ================
1030 R_RenderScene
1031 
1032 r_refdef must be set before the first call
1033 ================
1034 */
R_RenderScene(void)1035 void R_RenderScene (void)
1036 {
1037 	R_SetupFrame ();
1038 
1039 	R_SetFrustum ();
1040 
1041 	R_SetupGL ();
1042 
1043 	R_MarkLeaves ();	// done here so we know if we're in water
1044 
1045 	R_DrawWorld ();		// adds static entities to the list
1046 
1047 	S_ExtraUpdate ();	// don't let sound get messed up if going slow
1048 
1049 	R_DrawEntitiesOnList ();
1050 
1051 	GL_DisableMultitexture();
1052 
1053 	R_RenderDlights ();
1054 
1055 	R_DrawParticles ();
1056 
1057 #ifdef GLTEST
1058 	Test_Draw ();
1059 #endif
1060 
1061 }
1062 
1063 
1064 /*
1065 =============
1066 R_Clear
1067 =============
1068 */
R_Clear(void)1069 void R_Clear (void)
1070 {
1071 	if (r_mirroralpha.value != 1.0)
1072 	{
1073 		if (gl_clear.value)
1074 			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1075 		else
1076 			glClear (GL_DEPTH_BUFFER_BIT);
1077 		gldepthmin = 0;
1078 		gldepthmax = 0.5;
1079 		glDepthFunc (GL_LEQUAL);
1080 	}
1081 	else if (gl_ztrick.value)
1082 	{
1083 		static int trickframe;
1084 
1085 		if (gl_clear.value)
1086 			glClear (GL_COLOR_BUFFER_BIT);
1087 
1088 		trickframe++;
1089 		if (trickframe & 1)
1090 		{
1091 			gldepthmin = 0;
1092 			gldepthmax = 0.49999;
1093 			glDepthFunc (GL_LEQUAL);
1094 		}
1095 		else
1096 		{
1097 			gldepthmin = 1;
1098 			gldepthmax = 0.5;
1099 			glDepthFunc (GL_GEQUAL);
1100 		}
1101 	}
1102 	else
1103 	{
1104 		if (gl_clear.value)
1105 			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1106 		else
1107 			glClear (GL_DEPTH_BUFFER_BIT);
1108 		gldepthmin = 0;
1109 		gldepthmax = 1;
1110 		glDepthFunc (GL_LEQUAL);
1111 	}
1112 
1113 #ifdef USE_OPENGLES
1114 	glDepthRangef (gldepthmin, gldepthmax);
1115 #else
1116 	glDepthRange (gldepthmin, gldepthmax);
1117 #endif
1118 }
1119 
1120 #if 0 //!!! FIXME, Zoid, mirror is disabled for now
1121 /*
1122 =============
1123 R_Mirror
1124 =============
1125 */
1126 void R_Mirror (void)
1127 {
1128 	float		d;
1129 	msurface_t	*s;
1130 	entity_t	*ent;
1131 
1132 	if (!mirror)
1133 		return;
1134 
1135 	memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
1136 
1137 	d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist;
1138 	VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg);
1139 
1140 	d = DotProduct (vpn, mirror_plane->normal);
1141 	VectorMA (vpn, -2*d, mirror_plane->normal, vpn);
1142 
1143 	r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
1144 	r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
1145 	r_refdef.viewangles[2] = -r_refdef.viewangles[2];
1146 
1147 	ent = &cl_entities[cl.viewentity];
1148 	if (cl_numvisedicts < MAX_VISEDICTS)
1149 	{
1150 		cl_visedicts[cl_numvisedicts] = ent;
1151 		cl_numvisedicts++;
1152 	}
1153 
1154 	gldepthmin = 0.5;
1155 	gldepthmax = 1;
1156 	glDepthRange (gldepthmin, gldepthmax);
1157 	glDepthFunc (GL_LEQUAL);
1158 
1159 	R_RenderScene ();
1160 	R_DrawWaterSurfaces ();
1161 
1162 
1163 	gldepthmin = 0;
1164 	gldepthmax = 0.5;
1165 	glDepthRange (gldepthmin, gldepthmax);
1166 	glDepthFunc (GL_LEQUAL);
1167 
1168 	// blend on top
1169 	glEnable (GL_BLEND);
1170 	glMatrixMode(GL_PROJECTION);
1171 	if (mirror_plane->normal[2])
1172 		glScalef (1,-1,1);
1173 	else
1174 		glScalef (-1,1,1);
1175 	glCullFace(GL_FRONT);
1176 	glMatrixMode(GL_MODELVIEW);
1177 
1178 	glLoadMatrixf (r_base_world_matrix);
1179 
1180 	glColor4f (1,1,1,r_mirroralpha.value);
1181 	s = cl.worldmodel->textures[mirrortexturenum]->texturechain;
1182 	for ( ; s ; s=s->texturechain)
1183 		R_RenderBrushPoly (s);
1184 	cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
1185 	glDisable (GL_BLEND);
1186 	glColor4f (1,1,1,1);
1187 }
1188 #endif
1189 
1190 /*
1191 ================
1192 R_RenderView
1193 
1194 r_refdef must be set before the first call
1195 ================
1196 */
R_RenderView(void)1197 void R_RenderView (void)
1198 {
1199 	double	time1 = 0, time2;
1200 
1201 	if (r_norefresh.value)
1202 		return;
1203 
1204 	if (!r_worldentity.model || !cl.worldmodel)
1205 		Sys_Error ("R_RenderView: NULL worldmodel");
1206 
1207 	if (r_speeds.value)
1208 	{
1209 		glFinish ();
1210 		time1 = Sys_DoubleTime ();
1211 		c_brush_polys = 0;
1212 		c_alias_polys = 0;
1213 	}
1214 
1215 	mirror = false;
1216 
1217 	if (gl_finish.value)
1218 		glFinish ();
1219 
1220 	R_Clear ();
1221 
1222 	// render normal view
1223 	R_RenderScene ();
1224 	R_DrawViewModel ();
1225 	R_DrawWaterSurfaces ();
1226 
1227 	// render mirror view
1228 //	R_Mirror ();
1229 
1230 	R_PolyBlend ();
1231 
1232 	if (r_speeds.value)
1233 	{
1234 //		glFinish ();
1235 		time2 = Sys_DoubleTime ();
1236 		Con_Printf ("%3i ms  %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys);
1237 	}
1238 }
1239