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 #include "neh.h"
24 
25 entity_t	r_worldentity;
26 
27 qboolean	r_cache_thrash;		// compatability
28 
29 vec3_t		modelorg, r_entorigin;
30 entity_t	*currententity;
31 
32 int			r_visframecount;	// bumped when going to a new PVS
33 int			r_framecount;		// used for dlight push checking
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[2] = {-1, -1};     // cached
44 
45 int			particletexture;	// little dot for particles
46 int			playertextures;		// up to 16 color translated skins
47 int			skyboxtextures;
48 
49 int			mirrortexturenum;	// quake texturenum, not gltexturenum
50 qboolean	mirror;
51 mplane_t	*mirror_plane;
52 
53 //
54 // view origin
55 //
56 vec3_t	vup;
57 vec3_t	vpn;
58 vec3_t	vright;
59 vec3_t	r_origin;
60 
61 float	r_world_matrix[16];
62 float	r_base_world_matrix[16];
63 
64 //
65 // screen size info
66 //
67 refdef_t	r_refdef;
68 
69 mleaf_t		*r_viewleaf, *r_oldviewleaf;
70 
71 texture_t	*r_notexture_mip;
72 
73 int		d_lightstylevalue[256];	// 8.8 fraction of base light value
74 
75 
76 void R_MarkLeaves (void);
77 
78 // Nehahra - Interpolation
79 void GL_DrawAliasBlendedShadow (aliashdr_t *paliashdr, int pose1, int pose2, entity_t* e);
80 void R_BlendedRotateForEntity (entity_t *e);
81 void R_SetupAliasBlendedFrame (int frame, aliashdr_t *paliashdr, entity_t* e);
82 void GL_DrawAliasBlendedFrame (aliashdr_t *paliashdr, int pose1, int pose2, float blend);
83 // Nehahra - End
84 
85 cvar_t	r_norefresh = {"r_norefresh","0"};
86 cvar_t	r_drawentities = {"r_drawentities","1"};
87 cvar_t	r_drawviewmodel = {"r_drawviewmodel","1"};
88 cvar_t	r_speeds = {"r_speeds","0"};
89 cvar_t	r_fullbright = {"r_fullbright","0"};
90 cvar_t	r_lightmap = {"r_lightmap","0"};
91 cvar_t	r_shadows = {"r_shadows","0"};
92 cvar_t	r_mirroralpha = {"r_mirroralpha","1"};
93 cvar_t	r_wateralpha = {"r_wateralpha","1"};
94 cvar_t	r_dynamic = {"r_dynamic","1"};
95 cvar_t	r_novis = {"r_novis","0"};
96 cvar_t	r_flatlightstyles = {"r_flatlightstyles", "0"};
97 cvar_t	r_clearcolor = {"r_clearcolor", "251"}; // Closest to the original
98 cvar_t  r_oldsky = {"r_oldsky", "1"};
99 
100 cvar_t	gl_finish = {"gl_finish","0"};
101 cvar_t	gl_clear = {"gl_clear","0"};
102 cvar_t	gl_cull = {"gl_cull","1"};
103 cvar_t	gl_texsort = {"gl_texsort","1"};
104 cvar_t	gl_smoothmodels = {"gl_smoothmodels","1"};
105 cvar_t	gl_affinemodels = {"gl_affinemodels","0"};
106 cvar_t	gl_polyblend = {"gl_polyblend","1"};
107 cvar_t  gl_flashblend = {"gl_flashblend","0"};
108 cvar_t	gl_playermip = {"gl_playermip","0"};
109 cvar_t	gl_nocolors = {"gl_nocolors","0"};
110 cvar_t  gl_keeptjunctions = {"gl_keeptjunctions","1"};
111 cvar_t	gl_doubleeyes = {"gl_doubleeys", "1"};
112 
113 extern	cvar_t	gl_ztrick;
114 
115 // Nehahra - ender: Disabled. Now a define in neh.h
116 /*
117 =================
118 R_CullBox
119 
120 Returns true if the box is completely outside the frustom
121 =================
122 */
R_CullBox(vec3_t mins,vec3_t maxs)123 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
124 {
125 	int		i;
126 
127 	for (i=0 ; i<4 ; i++)
128 		if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
129 			return true;
130 	return false;
131 }
132 
133 
R_RotateForEntity(entity_t * e)134 void R_RotateForEntity (entity_t *e)
135 {
136     glTranslatef (e->origin[0],  e->origin[1],  e->origin[2]);
137 
138     glRotatef (e->angles[1],  0, 0, 1);
139     glRotatef (-e->angles[0],  0, 1, 0);
140     glRotatef (e->angles[2],  1, 0, 0);
141 }
142 
143 /*
144 =============================================================
145 
146   SPRITE MODELS
147 
148 =============================================================
149 */
150 
151 /*
152 ================
153 R_GetSpriteFrame
154 ================
155 */
R_GetSpriteFrame(entity_t * currententity)156 mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
157 {
158 	msprite_t	*psprite;
159 	mspritegroup_t	*pspritegroup;
160 	mspriteframe_t	*pspriteframe;
161 	int		i, numframes, frame;
162 	float		*pintervals, fullinterval, targettime, time;
163 	static float	lastmsg = 0;
164 
165 	psprite = currententity->model->cache.data;
166 	frame = currententity->frame;
167 
168 	if (frame >= psprite->numframes || frame < 0)
169 	{
170 		if (IsTimeout (&lastmsg, 2))
171 			Con_Printf ("R_GetSpriteFrame: no such frame %d (%d frames) in %s\n", frame, psprite->numframes, currententity->model->name);
172 
173 		frame = 0;
174 	}
175 
176 	if (psprite->frames[frame].type == SPR_SINGLE)
177 	{
178 		pspriteframe = psprite->frames[frame].frameptr;
179 	}
180 	else
181 	{
182 		pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
183 		pintervals = pspritegroup->intervals;
184 		numframes = pspritegroup->numframes;
185 		fullinterval = pintervals[numframes-1];
186 
187 		time = cl.time + currententity->syncbase;
188 
189 	// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
190 	// are positive, so we don't have to worry about division by 0
191 		targettime = time - ((int)(time / fullinterval)) * fullinterval;
192 
193 		for (i=0 ; i<(numframes-1) ; i++)
194 		{
195 			if (pintervals[i] > targettime)
196 				break;
197 		}
198 
199 		pspriteframe = pspritegroup->frames[i];
200 	}
201 
202 	return pspriteframe;
203 }
204 
205 
206 /*
207 =================
208 R_DrawSpriteModel
209 
210 =================
211 */
R_DrawSpriteModel(entity_t * e)212 void R_DrawSpriteModel (entity_t *e)
213 {
214 	vec3_t		point;
215 	mspriteframe_t	*frame;
216 	float		*up, *right;
217 	vec3_t		v_forward, v_right, v_up;
218 	msprite_t	*psprite;
219 
220 //        if (currententity->effects & EF_ADDITIVE)
221 //                glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
222 //        else
223 //		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
224 
225 //	glEnable(GL_BLEND);
226 //        glDepthMask(0); // disable zbuffer updates
227 
228 	// don't even bother culling, because it's just a single
229 	// polygon without a surface cache
230 	frame = R_GetSpriteFrame (e);
231 	psprite = currententity->model->cache.data;
232 
233 	if (psprite->type == SPR_ORIENTED)
234 	{	// bullet marks on walls
235 		AngleVectors (currententity->angles, v_forward, v_right, v_up);
236 		up = v_up;
237 		right = v_right;
238 	}
239 	else
240 	{	// normal sprite
241 		up = vup;
242 		right = vright;
243 	}
244 
245 	glColor3f (1,1,1);
246 
247 	GL_DisableMultitexture();
248 
249         GL_Bind(frame->gl_texturenum);
250 
251         glEnable (GL_ALPHA_TEST);
252 	glBegin (GL_QUADS);
253 
254 	glTexCoord2f (0, 1);
255 	VectorMA (e->origin, frame->down, up, point);
256 	VectorMA (point, frame->left, right, point);
257 	glVertex3fv (point);
258 
259 	glTexCoord2f (0, 0);
260 	VectorMA (e->origin, frame->up, up, point);
261 	VectorMA (point, frame->left, right, point);
262 	glVertex3fv (point);
263 
264 	glTexCoord2f (1, 0);
265 	VectorMA (e->origin, frame->up, up, point);
266 	VectorMA (point, frame->right, right, point);
267 	glVertex3fv (point);
268 
269 	glTexCoord2f (1, 1);
270 	VectorMA (e->origin, frame->down, up, point);
271 	VectorMA (point, frame->right, right, point);
272 	glVertex3fv (point);
273 
274 	glEnd ();
275 
276         glDisable (GL_ALPHA_TEST);
277 
278 //        if (currententity->effects & EF_ADDITIVE)
279 //                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // normal alpha blend
280 //	glDisable(GL_BLEND);
281 //        glDepthMask(1); // enable zbuffer updates
282 }
283 
284 /*
285 =============================================================
286 
287   ALIAS MODELS
288 
289 =============================================================
290 */
291 
292 
293 #define NUMVERTEXNORMALS	162
294 
295 float	r_avertexnormals[NUMVERTEXNORMALS][3] = {
296 #include "anorms.h"
297 };
298 
299 vec3_t	shadevector;
300 float	shadelight, ambientlight;
301 
302 // precalculated dot products for quantized angles
303 #define SHADEDOT_QUANT 16
304 float	r_avertexnormal_dots[SHADEDOT_QUANT][256] =
305 #include "anorm_dots.h"
306 ;
307 
308 float	*shadedots = r_avertexnormal_dots[0];
309 
310 int	lastposenum;
311 int     lastposenum0; // Nehahra - Interpolation
312 
313 /*
314 =============
315 GL_DrawAliasFrame
316 =============
317 */
GL_DrawAliasFrame(aliashdr_t * paliashdr,int posenum)318 void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
319 {
320 	float	s, t;
321 	float 	l;
322 	int		i, j;
323 	int		index;
324 	trivertx_t	*v, *verts;
325 	int		list;
326 	int		*order;
327 	vec3_t	point;
328 	float	*normal;
329 	int		count;
330 
331         lastposenum = posenum;
332 
333 	verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
334 	verts += posenum * paliashdr->poseverts;
335 	order = (int *)((byte *)paliashdr + paliashdr->commands);
336 
337 	while (1)
338 	{
339 		// get the vertex count and primitive type
340 		count = *order++;
341 		if (!count)
342 			break;		// done
343 		if (count < 0)
344 		{
345 			count = -count;
346 			glBegin (GL_TRIANGLE_FAN);
347 		}
348 		else
349 			glBegin (GL_TRIANGLE_STRIP);
350 
351 		do
352 		{
353 			// texture coordinates come from the draw list
354 			glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
355 			order += 2;
356 
357 			if (r_fullbright.value || !cl.worldmodel->lightdata)
358 				l = 1;
359 			else
360 				// normals and vertexes come from the frame list
361 				l = shadedots[verts->lightnormalindex] * shadelight;
362 
363 			// Nehahra - Model_alpha
364 			if (model_alpha != 1.0)
365 				glColor4f (l, l, l, model_alpha);
366 			else
367 				glColor3f (l, l, l);
368 			// Nehahra - End
369 
370 			glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
371 			verts++;
372 		} while (--count);
373 
374 		glEnd ();
375 	}
376 }
377 
378 
379 /*
380 =============
381 GL_DrawAliasShadow
382 =============
383 */
384 extern	vec3_t			lightspot;
385 
GL_DrawAliasShadow(aliashdr_t * paliashdr,int posenum)386 void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
387 {
388 	float	s, t, l;
389 	int		i, j;
390 	int		index;
391 	trivertx_t	*v, *verts;
392 	int		list;
393 	int		*order;
394 	vec3_t	point;
395 	float	*normal;
396 	float	height, lheight;
397 	int		count;
398 
399 	lheight = currententity->origin[2] - lightspot[2];
400 
401 	height = 0;
402 	verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
403 	verts += posenum * paliashdr->poseverts;
404 	order = (int *)((byte *)paliashdr + paliashdr->commands);
405 
406 	height = -lheight + 1.0;
407 
408 	while (1)
409 	{
410 		// get the vertex count and primitive type
411 		count = *order++;
412 		if (!count)
413 			break;		// done
414 		if (count < 0)
415 		{
416 			count = -count;
417 			glBegin (GL_TRIANGLE_FAN);
418 		}
419 		else
420 			glBegin (GL_TRIANGLE_STRIP);
421 
422 		do
423 		{
424 			// texture coordinates come from the draw list
425 			// (skipped for shadows) glTexCoord2fv ((float *)order);
426 			order += 2;
427 
428 			// normals and vertexes come from the frame list
429 			point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
430 			point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
431 			point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
432 
433 			point[0] -= shadevector[0]*(point[2]+lheight);
434 			point[1] -= shadevector[1]*(point[2]+lheight);
435 			point[2] = height;
436 //			height -= 0.001;
437 			glVertex3fv (point);
438 
439 			verts++;
440 		} while (--count);
441 
442 		glEnd ();
443 	}
444 }
445 
446 /*
447 =================
448 R_ChkFrame
449 =================
450 */
R_ChkFrame(char * function,int frame,aliashdr_t * pahdr,float * plastmsg)451 int R_ChkFrame (char *function, int frame, aliashdr_t *pahdr, float *plastmsg)
452 {
453 	if (frame >= pahdr->numframes || frame < 0)
454 	{
455 		if (IsTimeout (plastmsg, 2))
456 		{
457 			Con_DPrintf ("%s: no such frame ", function);
458 
459 			// Single frame?
460 			if (pahdr->frames[0].name[0])
461 				Con_DPrintf ("%d ('%s', %d frames)", frame, pahdr->frames[0].name, pahdr->numframes);
462 			else
463 				Con_DPrintf ("group %d (%d groups)", frame, pahdr->numframes);
464 
465 			Con_DPrintf (" in %s\n", currententity->model->name);
466 		}
467 
468 		frame = 0;
469 	}
470 
471 	return frame;
472 }
473 
474 /*
475 =================
476 R_SetupAliasFrame
477 
478 =================
479 */
R_SetupAliasFrame(int frame,aliashdr_t * paliashdr)480 void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
481 {
482 	int		pose, numposes;
483 	float		interval;
484 	static float	lastmsg = 0;
485 
486 	frame = R_ChkFrame ("R_SetupAliasFrame", frame, paliashdr, &lastmsg);
487 
488 	pose = paliashdr->frames[frame].firstpose;
489 	numposes = paliashdr->frames[frame].numposes;
490 
491 	if (numposes > 1)
492 	{
493 		int firstpose = pose;
494 
495 		pose = numposes * currententity->syncbase; // Hack to make flames unsynchronized
496 		interval = paliashdr->frames[frame].interval;
497 		pose += (int)(cl.time / interval) % numposes;
498 		pose = firstpose + pose % numposes;
499 	}
500 
501 	GL_DrawAliasFrame (paliashdr, pose);
502 }
503 
504 /*
505 =================
506 R_DrawAliasModel
507 
508 =================
509 */
R_DrawAliasModel(entity_t * e,int cull)510 void R_DrawAliasModel (entity_t *e, int cull)
511 {
512 	int		i, j;
513 	int		lnum;
514 	vec3_t		dist;
515 	float		add;
516 	model_t		*clmodel;
517 	vec3_t		mins, maxs;
518 	aliashdr_t	*paliashdr;
519 	trivertx_t	*verts, *v;
520 	int		index;
521 	float		s, t, an;
522 	int		anim;
523         qboolean        torch = false;
524 	int		skinnum;
525 	static float	lastmsg = 0;
526 
527 	clmodel = currententity->model;
528 // Nehahra - Model_Alpha
529 	if (!gl_notrans.value)
530 	{
531 		model_alpha = currententity->transparency;
532 		if (model_alpha == 0)
533 			model_alpha = 1;
534 	}
535 	else
536 		model_alpha = 1;
537 // Nehahra - End
538 
539 	if (e == &cl.viewent)
540 		if (cl.items & IT_INVISIBILITY)
541 			model_alpha = 0.2;
542 
543 	VectorAdd (currententity->origin, clmodel->mins, mins);
544 	VectorAdd (currententity->origin, clmodel->maxs, maxs);
545 
546         if (cull && R_CullBox (mins, maxs))
547 		return;
548 
549 
550 	VectorCopy (currententity->origin, r_entorigin);
551 	VectorSubtract (r_origin, r_entorigin, modelorg);
552 
553 	//
554 	// get lighting information
555 	//
556 
557         ambientlight = shadelight = R_LightPoint (currententity->origin);
558 
559         // allways give the gun some light
560 	if (e == &cl.viewent && ambientlight < 24)
561                 ambientlight = shadelight = 24;
562 
563 	for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
564 	{
565 		if (cl_dlights[lnum].die >= cl.time)
566 		{
567 			VectorSubtract (currententity->origin,
568 							cl_dlights[lnum].origin,
569 							dist);
570 			add = cl_dlights[lnum].radius - Length(dist);
571 
572 			if (add > 0) {
573 				ambientlight += add;
574 				//ZOID models should be affected by dlights as well
575                                 shadelight += add;
576 			}
577 		}
578 	}
579 
580 	// clamp lighting so it doesn't overbright as much
581 	if (ambientlight > 128)
582 		ambientlight = 128;
583 	if (ambientlight + shadelight > 192)
584 		shadelight = 192 - ambientlight;
585 
586 	// ZOID: never allow players to go totally black
587 	i = currententity - cl_entities;
588         if (i >= 1 && i<=cl.maxclients)
589 		if (ambientlight < 8)
590                         ambientlight = shadelight = 8;
591 
592 	if (clmodel->fullbright)
593 	{
594 		ambientlight = shadelight = 255;
595                 torch = true;
596 	}
597 	else if (gl_autobright.value)
598 	{
599 		int autobright = gl_autobright.value - 1;
600 
601 		// Clamp
602 		if (autobright < 0)
603 			autobright = 0;
604 		else if (autobright > AUTOBRIGHTS - 1)
605 			autobright = AUTOBRIGHTS - 1;
606 
607 		autobright = clmodel->autobright[autobright];
608 
609 		if (autobright)
610 		{
611 			if (autobright == 255)
612 				torch = true;
613 
614 			if (gl_autobright.value > AUTOBRIGHTS)
615 			{
616 				// High intensity
617 				autobright += 50;
618 
619 				if (autobright > 255)
620 					autobright = 255;
621 			}
622 
623 			ambientlight = shadelight = autobright;
624 		}
625 	}
626 
627 	shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
628         shadelight = shadelight / 200.0;
629 
630 	an = e->angles[1]/180*M_PI;
631 	shadevector[0] = cos(-an);
632 	shadevector[1] = sin(-an);
633 	shadevector[2] = 1;
634 	VectorNormalize (shadevector);
635 
636 	//
637 	// locate the proper data
638 	//
639 	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
640 
641 	c_alias_polys += paliashdr->numtris;
642 
643 	skinnum = currententity->skinnum;
644 
645 	// check skin bounds
646 	if (skinnum >= paliashdr->numskins || skinnum < 0)
647 	{
648 		if (IsTimeout (&lastmsg, 2))
649 			Con_DPrintf ("R_DrawAliasModel: no such skin %d (%d skins) in %s\n", skinnum, paliashdr->numskins, clmodel->name);
650 
651 		skinnum = 0;
652 	}
653 
654 	//
655 	// draw all the triangles
656 	//
657 
658 	GL_DisableMultitexture();
659 
660         glPushMatrix ();
661         // fenix@io.com: model transform interpolation
662         if (r_interpolate_model_transform.value && !torch) {
663          R_BlendedRotateForEntity (e);
664         } else {
665          R_RotateForEntity (e);
666         }
667 
668 	if (clmodel->eyes && gl_doubleeyes.value) {
669 		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
670 // double size of eyes, since they are really hard to see in gl
671 		glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
672 	} else {
673 		glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
674 		glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
675 	}
676 
677 	anim = (int)(cl.time*10) & 3;
678     GL_Bind(paliashdr->gl_texturenum[skinnum][anim]);
679 
680 	// we can't dynamically colormap textures, so they are cached
681 	// seperately for the players.  Heads are just uncolored.
682 	if (currententity->colormap != vid.colormap && !gl_nocolors.value)
683 	{
684 		i = currententity - cl_entities;
685 		if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
686 		    GL_Bind(playertextures - 1 + i);
687 	}
688 
689 	if (gl_smoothmodels.value)
690 		glShadeModel (GL_SMOOTH);
691 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
692 
693 	if (gl_affinemodels.value)
694 		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
695 
696          // fenix@io.com: model animation interpolation
697          if (r_interpolate_model_animation.value)
698             {
699             R_SetupAliasBlendedFrame (currententity->frame, paliashdr, currententity);
700             }
701          else
702             {
703             R_SetupAliasFrame (currententity->frame, paliashdr);
704             }
705 
706 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
707 
708 	glShadeModel (GL_FLAT);
709 	if (gl_affinemodels.value)
710 		glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
711 
712 	glPopMatrix ();
713 
714 // Nehahra - Model_Alpha
715         if (model_alpha != 1.0) {
716          glDisable (GL_BLEND);
717          glColor4f (1,1,1,1);
718 	}
719 // Nehahra - End
720 
721 	if (!gl_glows.value)
722 		return;
723 
724         if (torch || (clmodel->candle || clmodel->lantern) && gl_autobright.value ||
725 	    clmodel->bolt || clmodel->missile || clmodel->quaddama || clmodel->invulner)
726 	{
727 
728 		const int TORCH_STYLE = 1;      // Flicker.
729                 vec3_t    lightorigin;    // Origin of glow.
730  		vec3_t    v;                      // Vector to torch.
731 		float     radius;         // Radius of torch flare.
732 		float     distance;               // Vector distance to torch.
733 		float     intensity;              // Intensity of torch flare.
734 
735 		VectorCopy(currententity->origin, lightorigin);
736 
737 		//set radius based on what model we are doing here
738                 //jf 00-05-28 set the radius large when missile first appears
739                 if (torch)
740 			radius = 30.0;
741                 else if (clmodel->candle)
742 			radius = 15.0;
743                 else if (clmodel->lantern)
744 			radius = 25.0;
745 		else if (clmodel->missile)
746 		{
747 			if (currententity->forcelink)
748 				radius = 80.0f;
749                         else
750 				radius = 20.0f;
751 		}
752 		else if (clmodel->bolt)
753 			radius = 30.0f;
754                 else if (clmodel->quaddama || clmodel->invulner)
755 			radius = 50.0f;
756 
757 		VectorSubtract(lightorigin, r_origin, v);
758 
759 		// See if view is outside the light.
760                 distance = Length(v);
761 		if (distance > radius) {
762 
763 			glDepthMask (0);
764 			glDisable (GL_TEXTURE_2D);
765 			glShadeModel (GL_SMOOTH);
766 			glEnable (GL_BLEND);
767 			glBlendFunc (GL_ONE, GL_ONE);
768 
769                         //2000-04-29 Translate the glow to coincide with the flame. KH
770                         // or be at the tail of the missile - muff
771                         // or the Quad or Pent - muff
772                         glPushMatrix();
773                         if (torch)
774                                 glTranslatef(0.0f, 0.0f, 10.0f); //jf 2000-04-10 was 0,0,8... up a tad.
775                         else if (clmodel->candle)
776                                 glTranslatef(0.0f, 0.0f, clmodel->maxs[2] - 5.0f); // Adapt to model
777                         else if (clmodel->lantern)
778                                 glTranslatef (0.0f, 0.0f, clmodel->maxs[2] - 35.0f);
779 			else if (clmodel->missile)
780 			{
781                       //move the glow behind the rocket
782                                 glTranslatef (cos( e->angles[1]/180*M_PI)*(-20.0f),
783 					      sin( e->angles[1]/180*M_PI)*(-20.0f),
784 					      sin( e->angles[0]/180*M_PI)*(-20.0f));
785 			}
786 			else if (clmodel->quaddama || clmodel->invulner)
787 				glTranslatef(0.0f, 0.0f, 20.0f);
788 
789 			glBegin(GL_TRIANGLE_FAN);
790 
791 
792 			// Invert (fades as you approach) - if we are a torch
793                         if (torch || clmodel->candle || clmodel->lantern)
794 			{
795 				// Diminish torch flare inversely with distance.
796 				intensity = (1024.0f - distance) / 1024.0f;
797 				intensity = (1.0f - intensity);
798 			}
799 			// or fix settings if lightning or missile
800                         else if (clmodel->bolt)
801 				intensity = 0.2f;
802 			else if (clmodel->missile)
803 				intensity = 0.4f;
804 			else if (clmodel->quaddama || clmodel->invulner)
805 				intensity = 0.3f;
806 
807 			// Clamp, but don't let the flare disappear.
808                         if (intensity > 1.0f) intensity = 1.0f;
809 			if (intensity < 0.0f) intensity = 0.0f;
810 
811 			// Now modulate with flicker.
812                         i = (int)(cl.time*10);
813 			if (!cl_lightstyle[TORCH_STYLE].length) {
814 				j = 256;
815 			}
816 			else {
817 				j = i % cl_lightstyle[TORCH_STYLE].length;
818 				j = cl_lightstyle[TORCH_STYLE].map[j] - 'a';
819 				j = j*22;
820 			}
821 			intensity *= ((float)j / 255.0f);
822 
823 			// Set yellow intensity
824 
825                         //2000-04-10 set the colour of the glow - muff
826                         if (torch || clmodel->candle || clmodel->lantern)
827 				glColor3f(0.4f*intensity, 0.2f*intensity, 0.05f);
828 			else if (clmodel->missile)
829 				glColor3f(0.9f*intensity, 0.2f*intensity, 0.1f*intensity);
830 			else if (clmodel->bolt)
831 				glColor3f(0.2f*intensity, 0.2f*intensity, 0.8f*intensity);
832 			else if (clmodel->quaddama)
833 				glColor3f(0.8f*intensity, 0.8f*intensity, 0.1f*intensity);
834 			else if (clmodel->invulner)
835 				glColor3f(0.8f*intensity, 0.1f*intensity, 0.1f*intensity);
836 
837 			for (i=0 ; i<3 ; i++)
838 				v[i] = lightorigin[i] - vpn[i]*radius;
839 			glVertex3fv(v);
840 			glColor3f(0.0f, 0.0f, 0.0f);
841 			for (i=16; i>=0; i--) {
842 				float a = i/16.0f * M_PI*2;
843 				for (j=0; j<3; j++)
844 					v[j] = lightorigin[j] +
845 					    vright[j]*cos(a)*radius +
846 					    vup[j]*sin(a)*radius;
847 				glVertex3fv(v);
848 			}
849 			glEnd();
850 
851 			// Restore previous matrix! KH
852                         glPopMatrix();
853 
854 			glColor3f (1,1,1);
855 			glDisable (GL_BLEND);
856 			glEnable (GL_TEXTURE_2D);
857 			glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
858 			glDepthMask (1);
859 
860 		}
861 	}
862 
863 }
864 
865 //==================================================================================
866 
867 /*
868 =============
869 R_DrawEntitiesOnList
870 =============
871 */
R_DrawEntitiesOnList(void)872 void R_DrawEntitiesOnList (void)
873 {
874 	int i;
875 
876 	if (!r_drawentities.value)
877 		return;
878 
879 	// draw sprites seperately, because of alpha blending
880 	for (i=0 ; i<cl_numvisedicts ; i++)
881 	{
882 		if ((i + 1) % 100 == 0)
883 			S_ExtraUpdateTime ();	// don't let sound get messed up if going slow
884 
885 		currententity = cl_visedicts[i];
886 
887 		if (currententity == &cl_entities[cl.viewentity])
888 		{
889 			// chase_active.value not checked as player model is necessary for shadows
890 			currententity->angles[0] *= 0.3;
891 		}
892 
893 // Nehahra - Model_Alpha
894 
895 		if (currententity->transparency != 1 && currententity->transparency != 0 && !gl_notrans.value)
896 		{
897 			currententity->transignore = false;//model_alpha
898 			continue; // draw transparent entities last (?)
899 		}
900 // Nehahra - End
901 
902 		switch (currententity->model->type)
903 		{
904 		case mod_alias:
905 #ifdef _WIN32
906                         R_DrawAliasModel (currententity, TRUE);
907 #else
908 			R_DrawAliasModel (currententity, true);
909 #endif
910 			break;
911 
912 		case mod_brush:
913 			R_DrawBrushModel (currententity);
914 			break;
915 
916 		default:
917 			break;
918 		}
919 	}
920 
921 	for (i=0 ; i<cl_numvisedicts ; i++)
922 	{
923 		currententity = cl_visedicts[i];
924 
925 		switch (currententity->model->type)
926 		{
927 		case mod_sprite:
928 			R_DrawSpriteModel (currententity);
929 			break;
930 		}
931 	}
932 }
933 
934 // Nehahra - Model_Alpha (Function by FrikaC)
935 /*
936 =============
937 R_DrawTransEntities
938 =============
939 */
R_DrawTransEntities(void)940 void R_DrawTransEntities (void)
941 {
942 	// need to draw back to front
943 	// fixme: this isn't my favorite option
944 	int		i;
945 	float bestdist, dist;
946 	entity_t *bestent;
947 	vec3_t start, test;
948 
949 	VectorCopy(r_refdef.vieworg, start);
950 
951 	if (!r_drawentities.value)
952 		return;
953 
954 transgetent:
955 	bestdist = 0;
956 	for (i=0 ; i<cl_numvisedicts ; i++)
957 	{
958 		currententity = cl_visedicts[i];
959 		if (currententity->transignore)
960 			continue;
961 		if (currententity->transparency == 1 || currententity->transparency ==0)
962 			continue;
963 
964 		VectorCopy(currententity->origin, test);
965 		if (currententity->model->type == mod_brush)
966 		{
967 			test[0] += currententity->model->mins[0];
968 			test[1] += currententity->model->mins[1];
969 			test[2] += currententity->model->mins[2];
970 		}
971 		dist = (((test[0] - start[0]) * (test[0] - start[0])) +
972 			((test[1] - start[1]) * (test[1] - start[1])) +
973 			((test[2] - start[2]) * (test[2] - start[2])));
974 
975 		if (dist > bestdist)
976 		{
977 			bestdist = dist;
978 			bestent = currententity;
979 
980 		}
981 	}
982 	if (bestdist == 0)
983 		return;
984 	bestent->transignore = true;
985 
986 	currententity = bestent;
987 	switch (currententity->model->type)
988 	{
989 	case mod_alias:
990 #ifdef _WIN32
991                 R_DrawAliasModel (currententity, TRUE);
992 #else
993                 R_DrawAliasModel (currententity, true);
994 #endif
995 		break;
996 	case mod_brush:
997 		R_DrawBrushModel (currententity);
998 		break;
999 	default:
1000 		break;
1001 	}
1002 
1003 	goto transgetent;
1004 
1005 }
1006 
1007 /*
1008 =============
1009 R_DrawViewModel
1010 =============
1011 */
R_DrawViewModel(void)1012 void R_DrawViewModel (void)
1013 {
1014         float old_interpolate_model_transform;
1015 
1016 	if (!r_drawviewmodel.value)
1017 		return;
1018 
1019 	if (chase_active.value)
1020 		return;
1021 
1022 	if (envmap)
1023 		return;
1024 
1025 	if (!r_drawentities.value)
1026 		return;
1027 
1028 	if (cl.items & IT_INVISIBILITY)
1029 		return;
1030 
1031 	if (cl.stats[STAT_HEALTH] <= 0)
1032 		return;
1033 
1034 	currententity = &cl.viewent;
1035 	if (!currententity->model)
1036 		return;
1037 
1038 	// Prevent weapon model error
1039 	if (currententity->model->name[0] == '*')
1040 	{
1041 		Con_Printf ("\x02R_DrawViewModel: ");
1042 		Con_Printf ("viewmodel %s invalid\n", currententity->model->name);
1043 		Cvar_Set ("r_drawviewmodel", "0");
1044 		return;
1045 	}
1046 
1047         currententity->transparency = model_alpha = cl_entities[cl.viewentity].transparency; // LordHavoc: if the player is transparent, so is his gun
1048 	currententity->effects = cl_entities[cl.viewentity].effects;
1049 
1050 	// hack the depth range to prevent view model from poking into walls
1051 	glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
1052 
1053         // fenix@io.com: model transform interpolation
1054         old_interpolate_model_transform = r_interpolate_model_transform.value;
1055         r_interpolate_model_transform.value = false;
1056 #ifdef _WIN32
1057         R_DrawAliasModel (currententity, FALSE);
1058 #else
1059 	R_DrawAliasModel (currententity, false);
1060 #endif
1061 	r_interpolate_model_transform.value = old_interpolate_model_transform;
1062 
1063 	glDepthRange (gldepthmin, gldepthmax);
1064 }
1065 
1066 
1067 /*
1068 ============
1069 R_PolyBlend
1070 ============
1071 */
R_PolyBlend(void)1072 void R_PolyBlend (void)
1073 {
1074 	if (!gl_polyblend.value)
1075 		return;
1076 	if (!v_blend[3])
1077 		return;
1078 
1079 	GL_DisableMultitexture();
1080 
1081 	glDisable (GL_ALPHA_TEST);
1082 	glEnable (GL_BLEND);
1083 	glDisable (GL_DEPTH_TEST);
1084 	glDisable (GL_TEXTURE_2D);
1085 
1086     glLoadIdentity ();
1087 
1088     glRotatef (-90,  1, 0, 0);	    // put Z going up
1089     glRotatef (90,  0, 0, 1);	    // put Z going up
1090 
1091 	glColor4fv (v_blend);
1092 
1093 	glBegin (GL_QUADS);
1094 
1095 	glVertex3f (10, 100, 100);
1096 	glVertex3f (10, -100, 100);
1097 	glVertex3f (10, -100, -100);
1098 	glVertex3f (10, 100, -100);
1099 	glEnd ();
1100 
1101 	glDisable (GL_BLEND);
1102 	glEnable (GL_TEXTURE_2D);
1103 	glEnable (GL_ALPHA_TEST);
1104 }
1105 
1106 
SignbitsForPlane(mplane_t * out)1107 int SignbitsForPlane (mplane_t *out)
1108 {
1109 	int	bits, j;
1110 
1111 	// for fast box on planeside test
1112 
1113 	bits = 0;
1114 	for (j=0 ; j<3 ; j++)
1115 	{
1116 		if (out->normal[j] < 0)
1117 			bits |= 1<<j;
1118 	}
1119 	return bits;
1120 }
1121 
1122 /*
1123 ===============
1124 TurnVector
1125 
1126 turn forward towards side on the plane defined by forward and side
1127 if angle = 90, the result will be equal to side
1128 assumes side and forward are perpendicular, and normalized
1129 to turn away from side, use a negative angle
1130 ===============
1131 */
TurnVector(vec3_t out,vec3_t forward,vec3_t side,float angle)1132 void TurnVector (vec3_t out, vec3_t forward, vec3_t side, float angle)
1133 {
1134 	float scale_forward, scale_side;
1135 
1136 	scale_forward = cos (DEG2RAD(angle));
1137 	scale_side = sin (DEG2RAD(angle));
1138 
1139 	out[0] = scale_forward*forward[0] + scale_side*side[0];
1140 	out[1] = scale_forward*forward[1] + scale_side*side[1];
1141 	out[2] = scale_forward*forward[2] + scale_side*side[2];
1142 }
1143 
1144 /*
1145 ===============
1146 R_SetFrustum
1147 ===============
1148 */
R_SetFrustum(void)1149 void R_SetFrustum (void)
1150 {
1151 	int i;
1152 
1153 	TurnVector (frustum[0].normal, vpn, vright, r_refdef.fov_x/2 - 90); //left plane
1154 	TurnVector (frustum[1].normal, vpn, vright, 90 - r_refdef.fov_x/2); //right plane
1155 	TurnVector (frustum[2].normal, vpn, vup, 90 - r_refdef.fov_y/2); //bottom plane
1156 	TurnVector (frustum[3].normal, vpn, vup, r_refdef.fov_y/2 - 90); //top plane
1157 
1158 	for (i=0 ; i<4 ; i++)
1159 	{
1160 		frustum[i].type = PLANE_ANYZ;
1161 		frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
1162 		frustum[i].signbits = SignbitsForPlane (&frustum[i]);
1163 	}
1164 }
1165 
1166 /*
1167 ===============
1168 R_CheckVariables
1169 ===============
1170 */
R_CheckVariables(void)1171 void R_CheckVariables (void)
1172 {
1173 	static float oldbright = 0, oldclear = 0, oldgamma = 0, oldmodvolume = 0;
1174 
1175 	if (r_fullbright.value != oldbright)
1176 	{
1177 		oldbright = r_fullbright.value;
1178 
1179 		// Refresh view
1180 		GL_RefreshLightMaps ();
1181 	}
1182 
1183 	if (r_clearcolor.value != oldclear)
1184 	{
1185 		byte *rgb;
1186 
1187 		oldclear = r_clearcolor.value;
1188 
1189 		// Refresh view
1190 		rgb = (byte *)(d_8to24table + ((int)r_clearcolor.value & 0xFF));
1191 		glClearColor (rgb[0] / 255.0, rgb[1] / 255.0, rgb[2] / 255.0, 0);
1192 	}
1193 
1194 	if (v_gamma.value != oldgamma)
1195 	{
1196 		oldgamma = v_gamma.value;
1197 #ifdef _WIN32
1198 		// Refresh view
1199 		VID_Gamma_f ();
1200 #endif
1201 	}
1202 
1203 	if (modvolume.value != oldmodvolume)
1204 	{
1205 		oldmodvolume = modvolume.value;
1206 
1207 		// Refresh
1208 		MOD_SetVolume_f ();
1209 	}
1210 }
1211 
1212 /*
1213 ===============
1214 R_SetupFrame
1215 ===============
1216 */
R_SetupFrame(void)1217 void R_SetupFrame (void)
1218 {
1219 	int				edgecount;
1220 	vrect_t			vrect;
1221 	float			w, h;
1222 
1223 // don't allow cheats in multiplayer
1224 	if (cl.maxclients > 1)
1225 		Cvar_Set ("r_fullbright", "0");
1226 
1227 	R_CheckVariables ();
1228 
1229 	R_AnimateLight ();
1230 
1231 	r_framecount++;
1232 
1233 // build the transformation matrix for the given view angles
1234 	VectorCopy (r_refdef.vieworg, r_origin);
1235 
1236 	AngleVectors (r_refdef.viewangles, vpn, vright, vup);
1237 
1238 // current viewleaf
1239 	r_oldviewleaf = r_viewleaf;
1240 	r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
1241 
1242 	V_SetContentsColor (r_viewleaf->contents);
1243 	V_CalcBlend ();
1244 
1245 	r_cache_thrash = false;
1246 
1247 	c_brush_polys = 0;
1248 	c_alias_polys = 0;
1249 
1250 }
1251 
1252 
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)1253 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
1254 		     GLdouble zNear, GLdouble zFar )
1255 {
1256    GLdouble xmin, xmax, ymin, ymax;
1257 
1258    ymax = zNear * tan( fovy * M_PI / 360.0 );
1259    ymin = -ymax;
1260 
1261    xmin = ymin * aspect;
1262    xmax = ymax * aspect;
1263 
1264    glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
1265 }
1266 
1267 
1268 /*
1269 =============
1270 R_SetupGL
1271 =============
1272 */
R_SetupGL(void)1273 void R_SetupGL (void)
1274 {
1275 	float	screenaspect;
1276 	float	yfov;
1277 	int		i;
1278 	extern	int glwidth, glheight;
1279 	int		x, x2, y2, y, w, h;
1280 
1281 	//
1282 	// set up viewpoint
1283 	//
1284 	glMatrixMode(GL_PROJECTION);
1285     glLoadIdentity ();
1286 	x = r_refdef.vrect.x * glwidth/vid.width;
1287 	x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
1288 	y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
1289 	y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
1290 
1291 	// fudge around because of frac screen scale
1292 	if (x > 0)
1293 		x--;
1294 	if (x2 < glwidth)
1295 		x2++;
1296 	if (y2 < 0)
1297 		y2--;
1298 	if (y < glheight)
1299 		y++;
1300 
1301 	w = x2 - x;
1302 	h = y - y2;
1303 
1304 	if (envmap)
1305 	{
1306 		x = y2 = 0;
1307 		w = h = 256;
1308 	}
1309 
1310 	glViewport (glx + x, gly + y2, w, h);
1311     screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
1312 //	yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
1313       MYgluPerspective (r_refdef.fov_y,  screenaspect,  4,  GL_FARCLIP); //6144
1314 
1315 	if (mirror)
1316 	{
1317 		if (mirror_plane->normal[2])
1318 			glScalef (1, -1, 1);
1319 		else
1320 			glScalef (-1, 1, 1);
1321 		glCullFace(GL_BACK);
1322 	}
1323 	else
1324 		glCullFace(GL_FRONT);
1325 
1326 	glMatrixMode(GL_MODELVIEW);
1327     glLoadIdentity ();
1328 
1329     glRotatef (-90,  1, 0, 0);	    // put Z going up
1330     glRotatef (90,  0, 0, 1);	    // put Z going up
1331     glRotatef (-r_refdef.viewangles[2],  1, 0, 0);
1332     glRotatef (-r_refdef.viewangles[0],  0, 1, 0);
1333     glRotatef (-r_refdef.viewangles[1],  0, 0, 1);
1334     glTranslatef (-r_refdef.vieworg[0],  -r_refdef.vieworg[1],  -r_refdef.vieworg[2]);
1335 
1336 	glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
1337 
1338 	//
1339 	// set drawing parms
1340 	//
1341 	if (gl_cull.value)
1342 		glEnable(GL_CULL_FACE);
1343 	else
1344 		glDisable(GL_CULL_FACE);
1345 
1346 	glDisable(GL_BLEND);
1347 	glDisable(GL_ALPHA_TEST);
1348 	glEnable(GL_DEPTH_TEST);
1349 }
1350 
1351 /*
1352 ================
1353 R_RenderScene
1354 
1355 r_refdef must be set before the first call
1356 ================
1357 */
R_RenderScene(void)1358 void R_RenderScene (void)
1359 {
1360 	S_ExtraUpdateTime ();	// don't let sound get messed up if going slow
1361 
1362 	R_SetupFrame ();
1363 
1364 	R_SetFrustum ();
1365 
1366 	R_SetupGL ();
1367 
1368 	R_MarkLeaves ();	// done here so we know if we're in water
1369 
1370 	R_DrawWorld ();		// adds static entities to the list
1371 
1372 	S_ExtraUpdateTime ();	// don't let sound get messed up if going slow
1373 
1374 	R_DrawEntitiesOnList ();
1375 
1376 	GL_DisableMultitexture();
1377 
1378 	R_RenderDlights ();
1379 
1380 // EnderTest        R_DrawParticles ();
1381 
1382 	S_ExtraUpdateTime ();	// don't let sound get messed up if going slow
1383 
1384 #ifdef GLTEST
1385 	Test_Draw ();
1386 #endif
1387 
1388 }
1389 
1390 
1391 /*
1392 =============
1393 R_Clear
1394 =============
1395 */
R_Clear(void)1396 void R_Clear (void)
1397 {
1398 	if (r_mirroralpha.value != 1.0)
1399 	{
1400 		if (gl_clear.value)
1401 			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1402 		else
1403 			glClear (GL_DEPTH_BUFFER_BIT);
1404 		gldepthmin = 0;
1405 		gldepthmax = 0.5;
1406 		glDepthFunc (GL_LEQUAL);
1407 	}
1408 	else if (gl_ztrick.value)
1409 	{
1410 		static int trickframe;
1411 
1412 		if (gl_clear.value)
1413 			glClear (GL_COLOR_BUFFER_BIT);
1414 
1415 		trickframe++;
1416 		if (trickframe & 1)
1417 		{
1418 			gldepthmin = 0;
1419 			gldepthmax = 0.49999;
1420 			glDepthFunc (GL_LEQUAL);
1421 		}
1422 		else
1423 		{
1424 			gldepthmin = 1;
1425 			gldepthmax = 0.5;
1426 			glDepthFunc (GL_GEQUAL);
1427 		}
1428 	}
1429 	else
1430 	{
1431 		if (gl_clear.value)
1432 			glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1433 		else
1434 			glClear (GL_DEPTH_BUFFER_BIT);
1435 		gldepthmin = 0;
1436 		gldepthmax = 1;
1437 		glDepthFunc (GL_LEQUAL);
1438 	}
1439 
1440 	glDepthRange (gldepthmin, gldepthmax);
1441 }
1442 
1443 /*
1444 =============
1445 R_Mirror
1446 =============
1447 */
R_Mirror(void)1448 void R_Mirror (void)
1449 {
1450 	float		d;
1451 	msurface_t	*s;
1452 	entity_t	*ent;
1453 
1454 	if (!mirror)
1455 		return;
1456 
1457 	memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
1458 
1459 	d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist;
1460 	VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg);
1461 
1462 	d = DotProduct (vpn, mirror_plane->normal);
1463 	VectorMA (vpn, -2*d, mirror_plane->normal, vpn);
1464 
1465 	r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
1466 	r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
1467 	r_refdef.viewangles[2] = -r_refdef.viewangles[2];
1468 
1469 	ent = &cl_entities[cl.viewentity];
1470 	if (cl_numvisedicts < MAX_VISEDICTS)
1471 	{
1472 		cl_visedicts[cl_numvisedicts] = ent;
1473 		cl_numvisedicts++;
1474 	}
1475 
1476 	gldepthmin = 0.5;
1477 	gldepthmax = 1;
1478 	glDepthRange (gldepthmin, gldepthmax);
1479 	glDepthFunc (GL_LEQUAL);
1480 
1481 	R_RenderScene ();
1482 	R_DrawWaterSurfaces ();
1483 
1484 	gldepthmin = 0;
1485 	gldepthmax = 0.5;
1486 	glDepthRange (gldepthmin, gldepthmax);
1487 	glDepthFunc (GL_LEQUAL);
1488 
1489 	// blend on top
1490 	glEnable (GL_BLEND);
1491 	glMatrixMode(GL_PROJECTION);
1492 	if (mirror_plane->normal[2])
1493 		glScalef (1,-1,1);
1494 	else
1495 		glScalef (-1,1,1);
1496 	glCullFace(GL_FRONT);
1497 	glMatrixMode(GL_MODELVIEW);
1498 
1499 	glLoadMatrixf (r_base_world_matrix);
1500 
1501 	glColor4f (1,1,1,r_mirroralpha.value);
1502 	s = cl.worldmodel->textures[mirrortexturenum]->texturechain;
1503 	for ( ; s ; s=s->texturechain)
1504 		R_RenderBrushPoly (s);
1505 	cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
1506 	glDisable (GL_BLEND);
1507 	glColor4f (1,1,1,1);
1508 }
1509 
1510 /*
1511 ================
1512 R_RenderView
1513 
1514 r_refdef must be set before the first call
1515 ================
1516 */
1517 
1518 // Nehahra: Altered significantly. Move glFinish etc to SCR_UpdateScreen
R_RenderView(void)1519 void R_RenderView (void) {
1520 	if (!r_worldentity.model || !cl.worldmodel)
1521 		Sys_Error ("R_RenderView: NULL worldmodel");
1522 
1523 
1524 	R_Clear ();
1525 
1526         Neh_BeginFrame();
1527 
1528         R_RenderScene ();
1529         R_DrawViewModel ();
1530 	R_DrawWaterSurfaces ();
1531 
1532         if (!gl_notrans.value) // Nehahra - Model_Alpha
1533 		R_DrawTransEntities();
1534 
1535         Neh_EndFrame();
1536 
1537         R_DrawParticles ();   // Nehahra - Model_Alpha
1538 	R_PolyBlend ();
1539 }
1540 
1541 /*
1542 =============
1543 GL_DrawAliasBlendedFrame
1544 
1545 fenix@io.com: model animation interpolation
1546 =============
1547 */
GL_DrawAliasBlendedFrame(aliashdr_t * paliashdr,int pose1,int pose2,float blend)1548 void GL_DrawAliasBlendedFrame (aliashdr_t *paliashdr, int pose1, int pose2, float blend)
1549 {
1550 	float       l;
1551 	trivertx_t* verts1;
1552 	trivertx_t* verts2;
1553 	int*        order;
1554 	int         count;
1555 	vec3_t      d;
1556 
1557 #ifdef D3DQuake
1558 	if ( gNoAlias ) return; // D3DQuake
1559 #endif
1560 
1561         if (model_alpha != 1.0)
1562 		glEnable (GL_BLEND);
1563 
1564         lastposenum0 = pose1;
1565         lastposenum  = pose2;
1566         verts1  = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
1567         verts2  = verts1;
1568 
1569         verts1 += pose1 * paliashdr->poseverts;
1570         verts2 += pose2 * paliashdr->poseverts;
1571 
1572         order = (int *)((byte *)paliashdr + paliashdr->commands);
1573 
1574         for (;;)
1575 	{
1576 		// get the vertex count and primitive type
1577 		count = *order++;
1578 
1579 		if (!count) break;
1580 
1581 		if (count < 0)
1582 		{
1583 			count = -count;
1584 			glBegin (GL_TRIANGLE_FAN);
1585 		}
1586 		else
1587 			glBegin (GL_TRIANGLE_STRIP);
1588 
1589 		do
1590 		{
1591 			// texture coordinates come from the draw list
1592 			glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
1593 			order += 2;
1594 
1595 			// normals and vertexes come from the frame list
1596 			// blend the light intensity from the two frames together
1597 			d[0] = shadedots[verts2->lightnormalindex] -
1598 			       shadedots[verts1->lightnormalindex];
1599 
1600 			if (r_fullbright.value || !cl.worldmodel->lightdata)
1601 				l = 1;
1602 			else
1603 				l = shadelight * (shadedots[verts1->lightnormalindex] + (blend * d[0]));
1604 
1605 			if (model_alpha != 1.0)
1606 				glColor4f (l, l, l, model_alpha);
1607 			else
1608 				glColor3f (l, l, l);
1609 
1610 			VectorSubtract(verts2->v, verts1->v, d);
1611 
1612 			// blend the vertex positions from each frame together
1613 			glVertex3f (verts1->v[0] + (blend * d[0]),
1614 				    verts1->v[1] + (blend * d[1]),
1615 				    verts1->v[2] + (blend * d[2]));
1616 
1617 			verts1++;
1618 			verts2++;
1619 		}
1620 		while (--count);
1621 
1622 		glEnd ();
1623 	}
1624 }
1625 
1626 /*
1627 =================
1628 R_SetupAliasBlendedFrame
1629 
1630 fenix@io.com: model animation interpolation
1631 =================
1632 */
R_SetupAliasBlendedFrame(int frame,aliashdr_t * paliashdr,entity_t * e)1633 void R_SetupAliasBlendedFrame (int frame, aliashdr_t *paliashdr, entity_t* e)
1634 {
1635         int	     pose;
1636         int	     numposes;
1637         float	     blend;
1638         static float lastmsg = 0;
1639 
1640         frame = R_ChkFrame ("R_SetupAliasBlendedFrame", frame, paliashdr, &lastmsg);
1641 
1642         pose = paliashdr->frames[frame].firstpose;
1643         numposes = paliashdr->frames[frame].numposes;
1644 
1645         if (numposes > 1)
1646         {
1647 		int firstpose = pose;
1648 
1649 		pose = numposes * currententity->syncbase; // Hack to make flames unsynchronized
1650 		e->frame_interval = paliashdr->frames[frame].interval;
1651 		pose += (int)(cl.time / e->frame_interval) % numposes;
1652 		pose = firstpose + pose % numposes;
1653         }
1654         else
1655         {
1656 		/* One tenth of a second is a good for most Quake animations.
1657 		If the nextthink is longer then the animation is usually meant to pause
1658 		(e.g. check out the shambler magic animation in shambler.qc).  If its
1659 		shorter then things will still be smoothed partly, and the jumps will be
1660 		less noticable because of the shorter time.  So, this is probably a good
1661 		assumption. */
1662 		e->frame_interval = 0.1;
1663         }
1664 
1665         if (e->pose2 != pose)
1666         {
1667 		e->frame_start_time = realtime;
1668 		e->pose1 = e->pose2;
1669 		e->pose2 = pose;
1670 		blend = 0;
1671         }
1672         else
1673 		blend = (realtime - e->frame_start_time) / e->frame_interval;
1674 
1675         // wierd things start happening if blend passes 1
1676         if (cl.paused || blend > 1)
1677         	blend = 1;
1678 
1679         GL_DrawAliasBlendedFrame (paliashdr, e->pose1, e->pose2, blend);
1680 }
1681 
1682 /*
1683 =============
1684 R_BlendedRotateForEntity
1685 
1686 fenix@io.com: model transform interpolation
1687 =============
1688 */
R_BlendedRotateForEntity(entity_t * e)1689 void R_BlendedRotateForEntity (entity_t *e)
1690 {
1691         float 	timepassed;
1692         float 	blend;
1693         vec3_t	d;
1694         int	i;
1695 
1696         // positional interpolation
1697 
1698         timepassed = realtime - e->translate_start_time;
1699 
1700         if (e->translate_start_time == 0 || timepassed > 1)
1701         {
1702 		e->translate_start_time = realtime;
1703 		VectorCopy (e->origin, e->origin1);
1704 		VectorCopy (e->origin, e->origin2);
1705         }
1706 
1707         if (!VectorCompare (e->origin, e->origin2))
1708         {
1709 		e->translate_start_time = realtime;
1710 		VectorCopy (e->origin2, e->origin1);
1711 		VectorCopy (e->origin,  e->origin2);
1712 		blend = 0;
1713         }
1714         else
1715         {
1716 		blend =  timepassed / 0.1;
1717 
1718 		if (cl.paused || blend > 1)
1719 			blend = 1;
1720         }
1721 
1722         VectorSubtract (e->origin2, e->origin1, d);
1723 
1724         glTranslatef (e->origin1[0] + (blend * d[0]),
1725 		      e->origin1[1] + (blend * d[1]),
1726 		      e->origin1[2] + (blend * d[2]));
1727 
1728         // orientation interpolation (Euler angles, yuck!)
1729 
1730         timepassed = realtime - e->rotate_start_time;
1731 
1732         if (e->rotate_start_time == 0 || timepassed > 1)
1733         {
1734 		e->rotate_start_time = realtime;
1735 		VectorCopy (e->angles, e->angles1);
1736 		VectorCopy (e->angles, e->angles2);
1737         }
1738 
1739         if (!VectorCompare (e->angles, e->angles2))
1740         {
1741 		e->rotate_start_time = realtime;
1742 		VectorCopy (e->angles2, e->angles1);
1743 		VectorCopy (e->angles,  e->angles2);
1744 		blend = 0;
1745         }
1746         else
1747         {
1748 		blend = timepassed / 0.1;
1749 
1750 		if (cl.paused || blend > 1)
1751 			blend = 1;
1752         }
1753 
1754         VectorSubtract (e->angles2, e->angles1, d);
1755 
1756         // always interpolate along the shortest path
1757         for (i = 0; i < 3; i++)
1758         {
1759 		if (d[i] > 180)
1760 			d[i] -= 360;
1761 		else if (d[i] < -180)
1762 			d[i] += 360;
1763         }
1764 
1765         glRotatef ( e->angles1[1] + ( blend * d[1]),  0, 0, 1);
1766         glRotatef (-e->angles1[0] + (-blend * d[0]),  0, 1, 0);
1767         glRotatef ( e->angles1[2] + ( blend * d[2]),  1, 0, 0);
1768 }
1769 
1770 /*
1771 =============
1772 GL_DrawAliasBlendedShadow
1773 
1774 fenix@io.com: model animation interpolation
1775 =============
1776 */
GL_DrawAliasBlendedShadow(aliashdr_t * paliashdr,int pose1,int pose2,entity_t * e)1777 void GL_DrawAliasBlendedShadow (aliashdr_t *paliashdr, int pose1, int pose2, entity_t* e)
1778 {
1779         trivertx_t* verts1;
1780         trivertx_t* verts2;
1781         int*        order;
1782         vec3_t      point1;
1783         vec3_t      point2;
1784         vec3_t      d;
1785         float       height;
1786         float       lheight;
1787         int         count;
1788         float       blend;
1789 
1790         blend = (realtime - e->frame_start_time) / e->frame_interval;
1791 
1792         if (blend > 1)
1793         	blend = 1;
1794 
1795         lheight = e->origin[2] - lightspot[2];
1796         height  = -lheight + 1.0;
1797 
1798         verts1 = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
1799         verts2 = verts1;
1800 
1801         verts1 += pose1 * paliashdr->poseverts;
1802         verts2 += pose2 * paliashdr->poseverts;
1803 
1804         order = (int *)((byte *)paliashdr + paliashdr->commands);
1805 
1806         for (;;)
1807         {
1808 		// get the vertex count and primitive type
1809 		count = *order++;
1810 
1811 		if (!count)
1812 			break;
1813 
1814 		if (count < 0)
1815 		{
1816 			count = -count;
1817 			glBegin (GL_TRIANGLE_FAN);
1818 		}
1819 		else
1820 			glBegin (GL_TRIANGLE_STRIP);
1821 
1822 		do
1823 		{
1824 			order += 2;
1825 
1826 			point1[0] = verts1->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
1827 			point1[1] = verts1->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
1828 			point1[2] = verts1->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
1829 
1830 			point1[0] -= shadevector[0]*(point1[2]+lheight);
1831 			point1[1] -= shadevector[1]*(point1[2]+lheight);
1832 
1833 			point2[0] = verts2->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
1834 			point2[1] = verts2->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
1835 			point2[2] = verts2->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
1836 
1837 			point2[0] -= shadevector[0]*(point2[2]+lheight);
1838 			point2[1] -= shadevector[1]*(point2[2]+lheight);
1839 
1840 			VectorSubtract(point2, point1, d);
1841 
1842 			glVertex3f (point1[0] + (blend * d[0]),
1843 				    point1[1] + (blend * d[1]),
1844 				    height);
1845 
1846 			verts1++;
1847 			verts2++;
1848 		} while (--count);
1849 
1850 		glEnd ();
1851         }
1852 }
1853