1 /*
2 ===========================================================================
3 
4 Return to Castle Wolfenstein single player GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Return to Castle Wolfenstein single player GPL Source Code (“RTCW SP Source Code”).
8 
9 RTCW SP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 RTCW SP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with RTCW SP Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 /*
30  * name:		tr_main.c
31  *
32  * desc:		main control flow for each frame
33  *
34 */
35 
36 #include "tr_local.h"
37 
38 #include <string.h> // memcpy
39 
40 trGlobals_t tr;
41 
42 static float s_flipMatrix[16] = {
43 	// convert from our coordinate system (looking down X)
44 	// to OpenGL's coordinate system (looking down -Z)
45 	0, 0, -1, 0,
46 	-1, 0, 0, 0,
47 	0, 1, 0, 0,
48 	0, 0, 0, 1
49 };
50 
51 
52 refimport_t ri;
53 
54 // entities that will have procedurally generated surfaces will just
55 // point at this for their sorting surface
56 surfaceType_t entitySurface = SF_ENTITY;
57 
58 // fog stuff
59 glfog_t glfogsettings[NUM_FOGS];
60 glfogType_t glfogNum = FOG_NONE;
61 
62 //----(SA)
63 /*
64 ==============
65 R_SetFog
66 
67   if fogvar == FOG_CMD_SWITCHFOG {
68 	fogvar is the command
69 	var1 is the fog to switch to
70 	var2 is the time to transition
71   }
72   else {
73 	fogvar is the fog that's being set
74 	var1 is the near fog z value
75 	var2 is the far fog z value
76 	rgb = color
77 	density is density, and is used to derive the values of 'mode', 'drawsky', and 'clearscreen'
78   }
79 ==============
80 */
R_SetFog(int fogvar,int var1,int var2,float r,float g,float b,float density)81 void R_SetFog( int fogvar, int var1, int var2, float r, float g, float b, float density ) {
82 	if ( fogvar != FOG_CMD_SWITCHFOG ) {   // just set the parameters and return
83 
84 		if ( var1 == 0 && var2 == 0 ) {    // clear this fog
85 			glfogsettings[fogvar].registered = qfalse;
86 			return;
87 		}
88 
89 		glfogsettings[fogvar].color[0]      = r;
90 		glfogsettings[fogvar].color[1]      = g;
91 		glfogsettings[fogvar].color[2]      = b;
92 		glfogsettings[fogvar].color[3]      = 1;
93 		glfogsettings[fogvar].start         = var1;
94 		glfogsettings[fogvar].end           = var2;
95 		if ( density >= 1 ) {
96 			glfogsettings[fogvar].mode          = GL_LINEAR;
97 			glfogsettings[fogvar].drawsky       = qfalse;
98 			glfogsettings[fogvar].clearscreen   = qtrue;
99 			glfogsettings[fogvar].density       = 1.0;
100 		} else
101 		{
102 			glfogsettings[fogvar].mode          = GL_EXP;
103 			glfogsettings[fogvar].drawsky       = qtrue;
104 			glfogsettings[fogvar].clearscreen   = qfalse;
105 			glfogsettings[fogvar].density       = density;
106 		}
107 		glfogsettings[fogvar].hint          = GL_DONT_CARE;
108 		glfogsettings[fogvar].registered    = qtrue;
109 
110 		return;
111 	}
112 
113 	// FOG_MAP now used to mean 'no fog'
114 	if ( var1 == FOG_MAP ) {
115 
116 		// transitioning from...
117 		if ( glfogsettings[FOG_CURRENT].registered ) {
118 			memcpy( &glfogsettings[FOG_LAST], &glfogsettings[FOG_CURRENT], sizeof( glfog_t ) );
119 		}
120 
121 		memcpy( &glfogsettings[FOG_TARGET], &glfogsettings[glfogNum], sizeof( glfog_t ) );
122 
123 
124 		// clear, clear, clear
125 		memset( &glfogsettings[FOG_MAP], 0, sizeof( glfog_t ) );
126 //		memset(&glfogsettings[FOG_CURRENT], 0, sizeof(glfog_t));
127 		memset( &glfogsettings[FOG_TARGET], 0, sizeof( glfog_t ) );
128 //		glfogsettings[FOG_CURRENT].registered = qfalse;
129 //		glfogsettings[FOG_TARGET].registered = qfalse;
130 		glfogNum = FOG_NONE;
131 		return;
132 	}
133 
134 	// don't switch to invalid fogs
135 	if ( glfogsettings[var1].registered != qtrue ) {
136 		return;
137 	}
138 
139 
140 	glfogNum = var1;
141 
142 	// transitioning to new fog, store the current values as the 'from'
143 
144 	if ( glfogsettings[FOG_CURRENT].registered ) {
145 		memcpy( &glfogsettings[FOG_LAST], &glfogsettings[FOG_CURRENT], sizeof( glfog_t ) );
146 	} else {
147 		// if no current fog fall back to world fog
148 		// FIXME: handle transition if there is no FOG_MAP fog
149 //		memcpy(&glfogsettings[FOG_LAST], &glfogsettings[FOG_MAP], sizeof(glfog_t));
150 		memcpy( &glfogsettings[FOG_LAST], &glfogsettings[glfogNum], sizeof( glfog_t ) );
151 	}
152 
153 	memcpy( &glfogsettings[FOG_TARGET], &glfogsettings[glfogNum], sizeof( glfog_t ) );
154 
155 	if ( !var2 ) { // instant
156 		glfogsettings[FOG_TARGET].startTime = 0;
157 		glfogsettings[FOG_TARGET].finishTime = 0;
158 		glfogsettings[FOG_TARGET].dirty = 1;
159 		glfogsettings[FOG_CURRENT].dirty = 1;
160 	} else {
161 		// setup transition times
162 		glfogsettings[FOG_TARGET].startTime = tr.refdef.time;
163 		glfogsettings[FOG_TARGET].finishTime = tr.refdef.time + var2;
164 	}
165 }
166 //----(SA) end
167 
168 /*
169 ================
170 R_CompareVert
171 ================
172 */
R_CompareVert(srfVert_t * v1,srfVert_t * v2,qboolean checkST)173 qboolean R_CompareVert(srfVert_t * v1, srfVert_t * v2, qboolean checkST)
174 {
175 	int             i;
176 
177 	for(i = 0; i < 3; i++)
178 	{
179 		if(floor(v1->xyz[i] + 0.1) != floor(v2->xyz[i] + 0.1))
180 		{
181 			return qfalse;
182 		}
183 
184 		if(checkST && ((v1->st[0] != v2->st[0]) || (v1->st[1] != v2->st[1])))
185 		{
186 			return qfalse;
187 		}
188 	}
189 
190 	return qtrue;
191 }
192 
193 
194 /*
195 =============
196 R_CalcTexDirs
197 
198 Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
199 =============
200 */
R_CalcTexDirs(vec3_t sdir,vec3_t tdir,const vec3_t v1,const vec3_t v2,const vec3_t v3,const vec2_t w1,const vec2_t w2,const vec2_t w3)201 void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2,
202 				   const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3)
203 {
204 	float			x1, x2, y1, y2, z1, z2;
205 	float			s1, s2, t1, t2, r;
206 
207 	x1 = v2[0] - v1[0];
208 	x2 = v3[0] - v1[0];
209 	y1 = v2[1] - v1[1];
210 	y2 = v3[1] - v1[1];
211 	z1 = v2[2] - v1[2];
212 	z2 = v3[2] - v1[2];
213 
214 	s1 = w2[0] - w1[0];
215 	s2 = w3[0] - w1[0];
216 	t1 = w2[1] - w1[1];
217 	t2 = w3[1] - w1[1];
218 
219 	r = s1 * t2 - s2 * t1;
220 	if (r) r = 1.0f / r;
221 
222 	VectorSet(sdir, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
223 	VectorSet(tdir, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
224 }
225 
226 /*
227 =============
228 R_CalcTangentSpace
229 
230 Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
231 =============
232 */
R_CalcTangentSpace(vec3_t tangent,vec3_t bitangent,const vec3_t normal,const vec3_t sdir,const vec3_t tdir)233 vec_t R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, const vec3_t normal, const vec3_t sdir, const vec3_t tdir)
234 {
235 	vec3_t n_cross_t;
236 	vec_t n_dot_t, handedness;
237 
238 	// Gram-Schmidt orthogonalize
239 	n_dot_t = DotProduct(normal, sdir);
240 	VectorMA(sdir, -n_dot_t, normal, tangent);
241 	VectorNormalize(tangent);
242 
243 	// Calculate handedness
244 	CrossProduct(normal, sdir, n_cross_t);
245 	handedness = (DotProduct(n_cross_t, tdir) < 0.0f) ? -1.0f : 1.0f;
246 
247 	// Calculate orthogonal bitangent, if necessary
248 	if (bitangent)
249 		CrossProduct(normal, tangent, bitangent);
250 
251 	return handedness;
252 }
253 
254 
R_CalcTangentVectors(srfVert_t * dv[3])255 qboolean R_CalcTangentVectors(srfVert_t * dv[3])
256 {
257 	int             i;
258 	float           bb, s, t;
259 	vec3_t          bary;
260 
261 
262 	/* calculate barycentric basis for the triangle */
263 	bb = (dv[1]->st[0] - dv[0]->st[0]) * (dv[2]->st[1] - dv[0]->st[1]) - (dv[2]->st[0] - dv[0]->st[0]) * (dv[1]->st[1] - dv[0]->st[1]);
264 	if(fabs(bb) < 0.00000001f)
265 		return qfalse;
266 
267 	/* do each vertex */
268 	for(i = 0; i < 3; i++)
269 	{
270 		vec4_t tangent;
271 		vec3_t normal, bitangent, nxt;
272 
273 		// calculate s tangent vector
274 		s = dv[i]->st[0] + 10.0f;
275 		t = dv[i]->st[1];
276 		bary[0] = ((dv[1]->st[0] - s) * (dv[2]->st[1] - t) - (dv[2]->st[0] - s) * (dv[1]->st[1] - t)) / bb;
277 		bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
278 		bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
279 
280 		tangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
281 		tangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
282 		tangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
283 
284 		VectorSubtract(tangent, dv[i]->xyz, tangent);
285 		VectorNormalize(tangent);
286 
287 		// calculate t tangent vector
288 		s = dv[i]->st[0];
289 		t = dv[i]->st[1] + 10.0f;
290 		bary[0] = ((dv[1]->st[0] - s) * (dv[2]->st[1] - t) - (dv[2]->st[0] - s) * (dv[1]->st[1] - t)) / bb;
291 		bary[1] = ((dv[2]->st[0] - s) * (dv[0]->st[1] - t) - (dv[0]->st[0] - s) * (dv[2]->st[1] - t)) / bb;
292 		bary[2] = ((dv[0]->st[0] - s) * (dv[1]->st[1] - t) - (dv[1]->st[0] - s) * (dv[0]->st[1] - t)) / bb;
293 
294 		bitangent[0] = bary[0] * dv[0]->xyz[0] + bary[1] * dv[1]->xyz[0] + bary[2] * dv[2]->xyz[0];
295 		bitangent[1] = bary[0] * dv[0]->xyz[1] + bary[1] * dv[1]->xyz[1] + bary[2] * dv[2]->xyz[1];
296 		bitangent[2] = bary[0] * dv[0]->xyz[2] + bary[1] * dv[1]->xyz[2] + bary[2] * dv[2]->xyz[2];
297 
298 		VectorSubtract(bitangent, dv[i]->xyz, bitangent);
299 		VectorNormalize(bitangent);
300 
301 		// store bitangent handedness
302 		R_VaoUnpackNormal(normal, dv[i]->normal);
303 		CrossProduct(normal, tangent, nxt);
304 		tangent[3] = (DotProduct(nxt, bitangent) < 0.0f) ? -1.0f : 1.0f;
305 
306 		R_VaoPackTangent(dv[i]->tangent, tangent);
307 
308 		// debug code
309 		//% Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,
310 		//%     stv[ i ][ 0 ], stv[ i ][ 1 ], stv[ i ][ 2 ], ttv[ i ][ 0 ], ttv[ i ][ 1 ], ttv[ i ][ 2 ] );
311 	}
312 
313 	return qtrue;
314 }
315 
316 /*
317 =================
318 R_CullLocalBox
319 
320 Returns CULL_IN, CULL_CLIP, or CULL_OUT
321 =================
322 */
R_CullLocalBox(vec3_t localBounds[2])323 int R_CullLocalBox(vec3_t localBounds[2]) {
324 #if 0
325 	int i, j;
326 	vec3_t transformed[8];
327 	float dists[8];
328 	vec3_t v;
329 	cplane_t    *frust;
330 	int anyBack;
331 	int front, back;
332 
333 	if ( r_nocull->integer ) {
334 		return CULL_CLIP;
335 	}
336 
337 	// transform into world space
338 	for ( i = 0 ; i < 8 ; i++ ) {
339 		v[0] = bounds[i & 1][0];
340 		v[1] = bounds[( i >> 1 ) & 1][1];
341 		v[2] = bounds[( i >> 2 ) & 1][2];
342 
343 		VectorCopy( tr.or.origin, transformed[i] );
344 		VectorMA( transformed[i], v[0], tr.or.axis[0], transformed[i] );
345 		VectorMA( transformed[i], v[1], tr.or.axis[1], transformed[i] );
346 		VectorMA( transformed[i], v[2], tr.or.axis[2], transformed[i] );
347 	}
348 
349 	// check against frustum planes
350 	anyBack = 0;
351 	for ( i = 0 ; i < 4 ; i++ ) {
352 		frust = &tr.viewParms.frustum[i];
353 
354 		front = back = 0;
355 		for ( j = 0 ; j < 8 ; j++ ) {
356 			dists[j] = DotProduct( transformed[j], frust->normal );
357 			if ( dists[j] > frust->dist ) {
358 				front = 1;
359 				if ( back ) {
360 					break;      // a point is in front
361 				}
362 			} else {
363 				back = 1;
364 			}
365 		}
366 		if ( !front ) {
367 			// all points were behind one of the planes
368 			return CULL_OUT;
369 		}
370 		anyBack |= back;
371 	}
372 
373 	if ( !anyBack ) {
374 		return CULL_IN;     // completely inside frustum
375 	}
376 
377 	return CULL_CLIP;       // partially clipped
378 #else
379 	int             j;
380 	vec3_t          transformed;
381 	vec3_t          v;
382 	vec3_t          worldBounds[2];
383 
384 	if(r_nocull->integer)
385 	{
386 		return CULL_CLIP;
387 	}
388 
389 	// transform into world space
390 	ClearBounds(worldBounds[0], worldBounds[1]);
391 
392 	for(j = 0; j < 8; j++)
393 	{
394 		v[0] = localBounds[j & 1][0];
395 		v[1] = localBounds[(j >> 1) & 1][1];
396 		v[2] = localBounds[(j >> 2) & 1][2];
397 
398 		R_LocalPointToWorld(v, transformed);
399 
400 		AddPointToBounds(transformed, worldBounds[0], worldBounds[1]);
401 	}
402 
403 	return R_CullBox(worldBounds);
404 #endif
405 }
406 
407 /*
408 =================
409 R_CullBox
410 
411 Returns CULL_IN, CULL_CLIP, or CULL_OUT
412 =================
413 */
R_CullBox(vec3_t worldBounds[2])414 int R_CullBox(vec3_t worldBounds[2]) {
415 	int             i;
416 	cplane_t       *frust;
417 	qboolean        anyClip;
418 	int             r, numPlanes;
419 
420 	numPlanes = (tr.viewParms.flags & VPF_FARPLANEFRUSTUM) ? 5 : 4;
421 
422 	// check against frustum planes
423 	anyClip = qfalse;
424 	for(i = 0; i < numPlanes; i++)
425 	{
426 		frust = &tr.viewParms.frustum[i];
427 
428 		r = BoxOnPlaneSide(worldBounds[0], worldBounds[1], frust);
429 
430 		if(r == 2)
431 		{
432 			// completely outside frustum
433 			return CULL_OUT;
434 		}
435 		if(r == 3)
436 		{
437 			anyClip = qtrue;
438 		}
439 	}
440 
441 	if(!anyClip)
442 	{
443 		// completely inside frustum
444 		return CULL_IN;
445 	}
446 
447 	// partially clipped
448 	return CULL_CLIP;
449 }
450 
451 /*
452 ** R_CullLocalPointAndRadius
453 */
R_CullLocalPointAndRadius(const vec3_t pt,float radius)454 int R_CullLocalPointAndRadius( const vec3_t pt, float radius ) {
455 	vec3_t transformed;
456 
457 	R_LocalPointToWorld( pt, transformed );
458 
459 	return R_CullPointAndRadius( transformed, radius );
460 }
461 
462 /*
463 ** R_CullPointAndRadius
464 */
R_CullPointAndRadiusEx(const vec3_t pt,float radius,const cplane_t * frustum,int numPlanes)465 int R_CullPointAndRadiusEx( const vec3_t pt, float radius, const cplane_t* frustum, int numPlanes ) {
466 	int i;
467 	float dist;
468 	const cplane_t	*frust;
469 	qboolean mightBeClipped = qfalse;
470 
471 	if ( r_nocull->integer ) {
472 		return CULL_CLIP;
473 	}
474 
475 	// check against frustum planes
476 	for ( i = 0 ; i < numPlanes ; i++ )
477 	{
478 		frust = &frustum[i];
479 
480 		dist = DotProduct( pt, frust->normal ) - frust->dist;
481 		if ( dist < -radius ) {
482 			return CULL_OUT;
483 		} else if ( dist <= radius )   {
484 			mightBeClipped = qtrue;
485 		}
486 	}
487 
488 	if ( mightBeClipped ) {
489 		return CULL_CLIP;
490 	}
491 
492 	return CULL_IN;     // completely inside frustum
493 }
494 
495 /*
496 ** R_CullPointAndRadius
497 */
R_CullPointAndRadius(const vec3_t pt,float radius)498 int R_CullPointAndRadius( const vec3_t pt, float radius )
499 {
500 	return R_CullPointAndRadiusEx(pt, radius, tr.viewParms.frustum, (tr.viewParms.flags & VPF_FARPLANEFRUSTUM) ? 5 : 4);
501 }
502 
503 /*
504 =================
505 R_LocalNormalToWorld
506 
507 =================
508 */
R_LocalNormalToWorld(const vec3_t local,vec3_t world)509 void R_LocalNormalToWorld (const vec3_t local, vec3_t world) {
510 	world[0] = local[0] * tr.or.axis[0][0] + local[1] * tr.or.axis[1][0] + local[2] * tr.or.axis[2][0];
511 	world[1] = local[0] * tr.or.axis[0][1] + local[1] * tr.or.axis[1][1] + local[2] * tr.or.axis[2][1];
512 	world[2] = local[0] * tr.or.axis[0][2] + local[1] * tr.or.axis[1][2] + local[2] * tr.or.axis[2][2];
513 }
514 
515 /*
516 =================
517 R_LocalPointToWorld
518 
519 =================
520 */
R_LocalPointToWorld(const vec3_t local,vec3_t world)521 void R_LocalPointToWorld (const vec3_t local, vec3_t world) {
522 	world[0] = local[0] * tr.or.axis[0][0] + local[1] * tr.or.axis[1][0] + local[2] * tr.or.axis[2][0] + tr.or.origin[0];
523 	world[1] = local[0] * tr.or.axis[0][1] + local[1] * tr.or.axis[1][1] + local[2] * tr.or.axis[2][1] + tr.or.origin[1];
524 	world[2] = local[0] * tr.or.axis[0][2] + local[1] * tr.or.axis[1][2] + local[2] * tr.or.axis[2][2] + tr.or.origin[2];
525 }
526 
527 /*
528 =================
529 R_WorldToLocal
530 
531 =================
532 */
R_WorldToLocal(const vec3_t world,vec3_t local)533 void R_WorldToLocal (const vec3_t world, vec3_t local) {
534 	local[0] = DotProduct( world, tr.or.axis[0] );
535 	local[1] = DotProduct( world, tr.or.axis[1] );
536 	local[2] = DotProduct( world, tr.or.axis[2] );
537 }
538 
539 /*
540 ==========================
541 R_TransformModelToClip
542 
543 ==========================
544 */
R_TransformModelToClip(const vec3_t src,const float * modelMatrix,const float * projectionMatrix,vec4_t eye,vec4_t dst)545 void R_TransformModelToClip( const vec3_t src, const float *modelMatrix, const float *projectionMatrix,
546 							 vec4_t eye, vec4_t dst ) {
547 	int i;
548 
549 	for ( i = 0 ; i < 4 ; i++ ) {
550 		eye[i] =
551 			src[0] * modelMatrix[ i + 0 * 4 ] +
552 			src[1] * modelMatrix[ i + 1 * 4 ] +
553 			src[2] * modelMatrix[ i + 2 * 4 ] +
554 			1 * modelMatrix[ i + 3 * 4 ];
555 	}
556 
557 	for ( i = 0 ; i < 4 ; i++ ) {
558 		dst[i] =
559 			eye[0] * projectionMatrix[ i + 0 * 4 ] +
560 			eye[1] * projectionMatrix[ i + 1 * 4 ] +
561 			eye[2] * projectionMatrix[ i + 2 * 4 ] +
562 			eye[3] * projectionMatrix[ i + 3 * 4 ];
563 	}
564 }
565 
566 /*
567 ==========================
568 R_TransformClipToWindow
569 
570 ==========================
571 */
R_TransformClipToWindow(const vec4_t clip,const viewParms_t * view,vec4_t normalized,vec4_t window)572 void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t normalized, vec4_t window ) {
573 	normalized[0] = clip[0] / clip[3];
574 	normalized[1] = clip[1] / clip[3];
575 	normalized[2] = ( clip[2] + clip[3] ) / ( 2 * clip[3] );
576 
577 	window[0] = 0.5f * ( 1.0f + normalized[0] ) * view->viewportWidth;
578 	window[1] = 0.5f * ( 1.0f + normalized[1] ) * view->viewportHeight;
579 	window[2] = normalized[2];
580 
581 	window[0] = (int) ( window[0] + 0.5 );
582 	window[1] = (int) ( window[1] + 0.5 );
583 }
584 
585 
586 /*
587 ==========================
588 myGlMultMatrix
589 
590 ==========================
591 */
myGlMultMatrix(const float * a,const float * b,float * out)592 void myGlMultMatrix( const float *a, const float *b, float *out ) {
593 	int i, j;
594 
595 	for ( i = 0 ; i < 4 ; i++ ) {
596 		for ( j = 0 ; j < 4 ; j++ ) {
597 			out[ i * 4 + j ] =
598 				a [ i * 4 + 0 ] * b [ 0 * 4 + j ]
599 				+ a [ i * 4 + 1 ] * b [ 1 * 4 + j ]
600 				+ a [ i * 4 + 2 ] * b [ 2 * 4 + j ]
601 				+ a [ i * 4 + 3 ] * b [ 3 * 4 + j ];
602 		}
603 	}
604 }
605 
606 /*
607 =================
608 R_RotateForEntity
609 
610 Generates an orientation for an entity and viewParms
611 Does NOT produce any GL calls
612 Called by both the front end and the back end
613 =================
614 */
R_RotateForEntity(const trRefEntity_t * ent,const viewParms_t * viewParms,orientationr_t * or)615 void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms,
616 						orientationr_t *or ) {
617 	float glMatrix[16];
618 	vec3_t delta;
619 	float axisLength;
620 
621 	if ( ent->e.reType != RT_MODEL ) {
622 		*or = viewParms->world;
623 		return;
624 	}
625 
626 	VectorCopy( ent->e.origin, or->origin );
627 
628 	VectorCopy( ent->e.axis[0], or->axis[0] );
629 	VectorCopy( ent->e.axis[1], or->axis[1] );
630 	VectorCopy( ent->e.axis[2], or->axis[2] );
631 
632 	glMatrix[0] = or->axis[0][0];
633 	glMatrix[4] = or->axis[1][0];
634 	glMatrix[8] = or->axis[2][0];
635 	glMatrix[12] = or->origin[0];
636 
637 	glMatrix[1] = or->axis[0][1];
638 	glMatrix[5] = or->axis[1][1];
639 	glMatrix[9] = or->axis[2][1];
640 	glMatrix[13] = or->origin[1];
641 
642 	glMatrix[2] = or->axis[0][2];
643 	glMatrix[6] = or->axis[1][2];
644 	glMatrix[10] = or->axis[2][2];
645 	glMatrix[14] = or->origin[2];
646 
647 	glMatrix[3] = 0;
648 	glMatrix[7] = 0;
649 	glMatrix[11] = 0;
650 	glMatrix[15] = 1;
651 
652 	Mat4Copy(glMatrix, or->transformMatrix);
653 	myGlMultMatrix( glMatrix, viewParms->world.modelMatrix, or->modelMatrix );
654 
655 	// calculate the viewer origin in the model's space
656 	// needed for fog, specular, and environment mapping
657 	VectorSubtract( viewParms->or.origin, or->origin, delta );
658 
659 	// compensate for scale in the axes if necessary
660 	if ( ent->e.nonNormalizedAxes ) {
661 		axisLength = VectorLength( ent->e.axis[0] );
662 		if ( !axisLength ) {
663 			axisLength = 0;
664 		} else {
665 			axisLength = 1.0f / axisLength;
666 		}
667 	} else {
668 		axisLength = 1.0f;
669 	}
670 
671 	or->viewOrigin[0] = DotProduct( delta, or->axis[0] ) * axisLength;
672 	or->viewOrigin[1] = DotProduct( delta, or->axis[1] ) * axisLength;
673 	or->viewOrigin[2] = DotProduct( delta, or->axis[2] ) * axisLength;
674 }
675 
676 /*
677 =================
678 R_RotateForViewer
679 
680 Sets up the modelview matrix for a given viewParm
681 =================
682 */
R_RotateForViewer(void)683 void R_RotateForViewer( void ) {
684 	float viewerMatrix[16];
685 	vec3_t origin;
686 
687 	memset( &tr.or, 0, sizeof( tr.or ) );
688 	tr.or.axis[0][0] = 1;
689 	tr.or.axis[1][1] = 1;
690 	tr.or.axis[2][2] = 1;
691 	VectorCopy( tr.viewParms.or.origin, tr.or.viewOrigin );
692 
693 	// transform by the camera placement
694 	VectorCopy( tr.viewParms.or.origin, origin );
695 
696 	viewerMatrix[0] = tr.viewParms.or.axis[0][0];
697 	viewerMatrix[4] = tr.viewParms.or.axis[0][1];
698 	viewerMatrix[8] = tr.viewParms.or.axis[0][2];
699 	viewerMatrix[12] = -origin[0] * viewerMatrix[0] + - origin[1] * viewerMatrix[4] + - origin[2] * viewerMatrix[8];
700 
701 	viewerMatrix[1] = tr.viewParms.or.axis[1][0];
702 	viewerMatrix[5] = tr.viewParms.or.axis[1][1];
703 	viewerMatrix[9] = tr.viewParms.or.axis[1][2];
704 	viewerMatrix[13] = -origin[0] * viewerMatrix[1] + - origin[1] * viewerMatrix[5] + - origin[2] * viewerMatrix[9];
705 
706 	viewerMatrix[2] = tr.viewParms.or.axis[2][0];
707 	viewerMatrix[6] = tr.viewParms.or.axis[2][1];
708 	viewerMatrix[10] = tr.viewParms.or.axis[2][2];
709 	viewerMatrix[14] = -origin[0] * viewerMatrix[2] + - origin[1] * viewerMatrix[6] + - origin[2] * viewerMatrix[10];
710 
711 	viewerMatrix[3] = 0;
712 	viewerMatrix[7] = 0;
713 	viewerMatrix[11] = 0;
714 	viewerMatrix[15] = 1;
715 
716 	// convert from our coordinate system (looking down X)
717 	// to OpenGL's coordinate system (looking down -Z)
718 	myGlMultMatrix( viewerMatrix, s_flipMatrix, tr.or.modelMatrix );
719 
720 	tr.viewParms.world = tr.or;
721 
722 }
723 
724 
725 
726 /*
727 ==============
728 R_SetFrameFog
729 ==============
730 */
R_SetFrameFog(void)731 void R_SetFrameFog( void ) {
732 
733 	if ( r_speeds->integer == 5 ) {
734 		if ( !glfogsettings[FOG_TARGET].registered ) {
735 			ri.Printf( PRINT_ALL, "no fog - calc zFar: %0.1f\n", tr.viewParms.zFar );
736 			return;
737 		}
738 	}
739 
740 	// still fading
741 	if ( glfogsettings[FOG_TARGET].finishTime && glfogsettings[FOG_TARGET].finishTime >= tr.refdef.time ) {
742 		float lerpPos;
743 		int fadeTime;
744 
745 		// transitioning from density to distance
746 		if ( glfogsettings[FOG_LAST].mode == GL_EXP && glfogsettings[FOG_TARGET].mode == GL_LINEAR ) {
747 			// for now just fast transition to the target when dissimilar fogs are
748 			memcpy( &glfogsettings[FOG_CURRENT], &glfogsettings[FOG_TARGET], sizeof( glfog_t ) );
749 			glfogsettings[FOG_TARGET].finishTime = 0;
750 		}
751 		// transitioning from distance to density
752 		else if ( glfogsettings[FOG_LAST].mode == GL_LINEAR && glfogsettings[FOG_TARGET].mode == GL_EXP ) {
753 			memcpy( &glfogsettings[FOG_CURRENT], &glfogsettings[FOG_TARGET], sizeof( glfog_t ) );
754 			glfogsettings[FOG_TARGET].finishTime = 0;
755 		}
756 		// transitioning like fog modes
757 		else {
758 
759 			fadeTime = glfogsettings[FOG_TARGET].finishTime - glfogsettings[FOG_TARGET].startTime;
760 			if ( fadeTime <= 0 ) {
761 				fadeTime = 1;   // avoid divide by zero
762 
763 
764 			}
765 			lerpPos = (float)( tr.refdef.time - glfogsettings[FOG_TARGET].startTime ) / (float)fadeTime;
766 			if ( lerpPos > 1 ) {
767 				lerpPos = 1;
768 			}
769 
770 			// lerp near/far
771 			glfogsettings[FOG_CURRENT].start        = glfogsettings[FOG_LAST].start + ( ( glfogsettings[FOG_TARGET].start - glfogsettings[FOG_LAST].start ) * lerpPos );
772 			glfogsettings[FOG_CURRENT].end          = glfogsettings[FOG_LAST].end + ( ( glfogsettings[FOG_TARGET].end - glfogsettings[FOG_LAST].end ) * lerpPos );
773 
774 			// lerp color
775 			glfogsettings[FOG_CURRENT].color[0]     = glfogsettings[FOG_LAST].color[0] + ( ( glfogsettings[FOG_TARGET].color[0] - glfogsettings[FOG_LAST].color[0] ) * lerpPos );
776 			glfogsettings[FOG_CURRENT].color[1]     = glfogsettings[FOG_LAST].color[1] + ( ( glfogsettings[FOG_TARGET].color[1] - glfogsettings[FOG_LAST].color[1] ) * lerpPos );
777 			glfogsettings[FOG_CURRENT].color[2]     = glfogsettings[FOG_LAST].color[2] + ( ( glfogsettings[FOG_TARGET].color[2] - glfogsettings[FOG_LAST].color[2] ) * lerpPos );
778 
779 			glfogsettings[FOG_CURRENT].density      = glfogsettings[FOG_TARGET].density;
780 			glfogsettings[FOG_CURRENT].mode         = glfogsettings[FOG_TARGET].mode;
781 			glfogsettings[FOG_CURRENT].registered   = qtrue;
782 
783 			// if either fog in the transition clears the screen, clear the background this frame to avoid hall of mirrors
784 			glfogsettings[FOG_CURRENT].clearscreen  = ( glfogsettings[FOG_TARGET].clearscreen || glfogsettings[FOG_LAST].clearscreen );
785 		}
786 
787 		glfogsettings[FOG_CURRENT].dirty = 1;
788 	} else {
789 		// potential FIXME: since this is the most common occurance, diff first and only set changes
790 //		if(glfogsettings[FOG_CURRENT].dirty) {
791 		memcpy( &glfogsettings[FOG_CURRENT], &glfogsettings[FOG_TARGET], sizeof( glfog_t ) );
792 		glfogsettings[FOG_CURRENT].dirty = 0;
793 //		}
794 	}
795 
796 
797 	// shorten the far clip if the fog opaque distance is closer than the procedural farcip dist
798 
799 	if ( glfogsettings[FOG_CURRENT].mode == GL_LINEAR ) {
800 		if ( glfogsettings[FOG_CURRENT].end < tr.viewParms.zFar ) {
801 			tr.viewParms.zFar = glfogsettings[FOG_CURRENT].end;
802 		}
803 		if ( backEnd.refdef.rdflags & RDF_SNOOPERVIEW ) {
804 			tr.viewParms.zFar += 1000;  // zfar out slightly further for snooper.  this works fine with our maps, but could be 'funky' with later maps
805 
806 		}
807 	}
808 //	else
809 //		glfogsettings[FOG_CURRENT].end = 5;
810 
811 
812 	if ( r_speeds->integer == 5 ) {
813 		if ( glfogsettings[FOG_CURRENT].mode == GL_LINEAR ) {
814 			ri.Printf( PRINT_ALL, "farclip fog - den: %0.1f  calc zFar: %0.1f  fog zfar: %0.1f\n", glfogsettings[FOG_CURRENT].density, tr.viewParms.zFar, glfogsettings[FOG_CURRENT].end );
815 		} else {
816 			ri.Printf( PRINT_ALL, "density fog - den: %0.6f  calc zFar: %0.1f  fog zFar: %0.1f\n", glfogsettings[FOG_CURRENT].density, tr.viewParms.zFar, glfogsettings[FOG_CURRENT].end );
817 		}
818 	}
819 }
820 
821 
822 /*
823 ==============
824 R_SetFarClip
825 ==============
826 */
R_SetFarClip(void)827 static void R_SetFarClip( void ) {
828 	float farthestCornerDistance = 0;
829 	int i;
830 
831 	// if not rendering the world (icons, menus, etc)
832 	// set a 2k far clip plane
833 	if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
834 		tr.viewParms.zFar = 2048;
835 		return;
836 	}
837 
838 	//----(SA)	this lets you use r_zfar from the command line to experiment with different
839 	//			distances, but setting it back to 0 uses the map (or procedurally generated) default
840 	if ( r_zfar->value ) {
841 
842 		tr.viewParms.zFar = r_zfar->integer;
843 		R_SetFrameFog();
844 
845 		if ( r_speeds->integer == 5 ) {
846 			ri.Printf( PRINT_ALL, "r_zfar value forcing farclip at: %f\n", tr.viewParms.zFar );
847 		}
848 
849 		return;
850 	}
851 
852 	//
853 	// set far clipping planes dynamically
854 	//
855 	farthestCornerDistance = 0;
856 	for ( i = 0; i < 8; i++ )
857 	{
858 		vec3_t v;
859 		vec3_t vecTo;
860 		float distance;
861 
862 		if ( i & 1 ) {
863 			v[0] = tr.viewParms.visBounds[0][0];
864 		} else
865 		{
866 			v[0] = tr.viewParms.visBounds[1][0];
867 		}
868 
869 		if ( i & 2 ) {
870 			v[1] = tr.viewParms.visBounds[0][1];
871 		} else
872 		{
873 			v[1] = tr.viewParms.visBounds[1][1];
874 		}
875 
876 		if ( i & 4 ) {
877 			v[2] = tr.viewParms.visBounds[0][2];
878 		} else
879 		{
880 			v[2] = tr.viewParms.visBounds[1][2];
881 		}
882 
883 		VectorSubtract( v, tr.viewParms.or.origin, vecTo );
884 
885 		distance = vecTo[0] * vecTo[0] + vecTo[1] * vecTo[1] + vecTo[2] * vecTo[2];
886 
887 		if ( distance > farthestCornerDistance ) {
888 			farthestCornerDistance = distance;
889 		}
890 	}
891 
892 	tr.viewParms.zFar = sqrt( farthestCornerDistance );
893 	R_SetFrameFog();
894 }
895 
896 /*
897 =================
898 R_SetupFrustum
899 
900 Set up the culling frustum planes for the current view using the results we got from computing the first two rows of
901 the projection matrix.
902 =================
903 */
R_SetupFrustum(viewParms_t * dest,float xmin,float xmax,float ymax,float zProj,float zFar,float stereoSep)904 void R_SetupFrustum (viewParms_t *dest, float xmin, float xmax, float ymax, float zProj, float zFar, float stereoSep)
905 {
906 	vec3_t ofsorigin;
907 	float oppleg, adjleg, length;
908 	int i;
909 
910 	if(stereoSep == 0 && xmin == -xmax)
911 	{
912 		// symmetric case can be simplified
913 		VectorCopy(dest->or.origin, ofsorigin);
914 
915 		length = sqrt(xmax * xmax + zProj * zProj);
916 		oppleg = xmax / length;
917 		adjleg = zProj / length;
918 
919 		VectorScale(dest->or.axis[0], oppleg, dest->frustum[0].normal);
920 		VectorMA(dest->frustum[0].normal, adjleg, dest->or.axis[1], dest->frustum[0].normal);
921 
922 		VectorScale(dest->or.axis[0], oppleg, dest->frustum[1].normal);
923 		VectorMA(dest->frustum[1].normal, -adjleg, dest->or.axis[1], dest->frustum[1].normal);
924 	}
925 	else
926 	{
927 		// In stereo rendering, due to the modification of the projection matrix, dest->or.origin is not the
928 		// actual origin that we're rendering so offset the tip of the view pyramid.
929 		VectorMA(dest->or.origin, stereoSep, dest->or.axis[1], ofsorigin);
930 
931 		oppleg = xmax + stereoSep;
932 		length = sqrt(oppleg * oppleg + zProj * zProj);
933 		VectorScale(dest->or.axis[0], oppleg / length, dest->frustum[0].normal);
934 		VectorMA(dest->frustum[0].normal, zProj / length, dest->or.axis[1], dest->frustum[0].normal);
935 
936 		oppleg = xmin + stereoSep;
937 		length = sqrt(oppleg * oppleg + zProj * zProj);
938 		VectorScale(dest->or.axis[0], -oppleg / length, dest->frustum[1].normal);
939 		VectorMA(dest->frustum[1].normal, -zProj / length, dest->or.axis[1], dest->frustum[1].normal);
940 	}
941 
942 	length = sqrt(ymax * ymax + zProj * zProj);
943 	oppleg = ymax / length;
944 	adjleg = zProj / length;
945 
946 	VectorScale(dest->or.axis[0], oppleg, dest->frustum[2].normal);
947 	VectorMA(dest->frustum[2].normal, adjleg, dest->or.axis[2], dest->frustum[2].normal);
948 
949 	VectorScale(dest->or.axis[0], oppleg, dest->frustum[3].normal);
950 	VectorMA(dest->frustum[3].normal, -adjleg, dest->or.axis[2], dest->frustum[3].normal);
951 
952 	for (i=0 ; i<4 ; i++) {
953 		dest->frustum[i].type = PLANE_NON_AXIAL;
954 		dest->frustum[i].dist = DotProduct (ofsorigin, dest->frustum[i].normal);
955 		SetPlaneSignbits( &dest->frustum[i] );
956 	}
957 
958 	if (zFar != 0.0f)
959 	{
960 		vec3_t farpoint;
961 
962 		VectorMA(ofsorigin, zFar, dest->or.axis[0], farpoint);
963 		VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal);
964 
965 		dest->frustum[4].type = PLANE_NON_AXIAL;
966 		dest->frustum[4].dist = DotProduct (farpoint, dest->frustum[4].normal);
967 		SetPlaneSignbits( &dest->frustum[4] );
968 		dest->flags |= VPF_FARPLANEFRUSTUM;
969 	}
970 }
971 
972 /*
973 ===============
974 R_SetupProjection
975 ===============
976 */
R_SetupProjection(viewParms_t * dest,float zProj,float zFar,qboolean computeFrustum)977 void R_SetupProjection(viewParms_t *dest, float zProj, float zFar, qboolean computeFrustum)
978 {
979 	float	xmin, xmax, ymin, ymax;
980 	float	width, height, stereoSep = r_stereoSeparation->value;
981 
982 	/*
983 	 * offset the view origin of the viewer for stereo rendering
984 	 * by setting the projection matrix appropriately.
985 	 */
986 
987 	if(stereoSep != 0)
988 	{
989 		if(dest->stereoFrame == STEREO_LEFT)
990 			stereoSep = zProj / stereoSep;
991 		else if(dest->stereoFrame == STEREO_RIGHT)
992 			stereoSep = zProj / -stereoSep;
993 		else
994 			stereoSep = 0;
995 	}
996 
997 	ymax = zProj * tan(dest->fovY * M_PI / 360.0f);
998 	ymin = -ymax;
999 
1000 	xmax = zProj * tan(dest->fovX * M_PI / 360.0f);
1001 	xmin = -xmax;
1002 
1003 	width = xmax - xmin;
1004 	height = ymax - ymin;
1005 
1006 	dest->projectionMatrix[0] = 2 * zProj / width;
1007 	dest->projectionMatrix[4] = 0;
1008 	dest->projectionMatrix[8] = (xmax + xmin + 2 * stereoSep) / width;
1009 	dest->projectionMatrix[12] = 2 * zProj * stereoSep / width;
1010 
1011 	dest->projectionMatrix[1] = 0;
1012 	dest->projectionMatrix[5] = 2 * zProj / height;
1013 	dest->projectionMatrix[9] = ( ymax + ymin ) / height;	// normally 0
1014 	dest->projectionMatrix[13] = 0;
1015 
1016 	dest->projectionMatrix[3] = 0;
1017 	dest->projectionMatrix[7] = 0;
1018 	dest->projectionMatrix[11] = -1;
1019 	dest->projectionMatrix[15] = 0;
1020 
1021 	// Now that we have all the data for the projection matrix we can also setup the view frustum.
1022 	if(computeFrustum)
1023 		R_SetupFrustum(dest, xmin, xmax, ymax, zProj, zFar, stereoSep);
1024 }
1025 
1026 /*
1027 ===============
1028 R_SetupProjectionZ
1029 
1030 Sets the z-component transformation part in the projection matrix
1031 ===============
1032 */
R_SetupProjectionZ(viewParms_t * dest)1033 void R_SetupProjectionZ(viewParms_t *dest)
1034 {
1035 	float zNear, zFar, depth;
1036 
1037 	zNear = r_znear->value;
1038 	zFar	= dest->zFar;
1039 
1040 	depth	= zFar - zNear;
1041 
1042 	dest->projectionMatrix[2] = 0;
1043 	dest->projectionMatrix[6] = 0;
1044 	dest->projectionMatrix[10] = -( zFar + zNear ) / depth;
1045 	dest->projectionMatrix[14] = -2 * zFar * zNear / depth;
1046 
1047 	if (dest->isPortal)
1048 	{
1049 		float	plane[4];
1050 		float	plane2[4];
1051 		vec4_t q, c;
1052 
1053 		// transform portal plane into camera space
1054 		plane[0] = dest->portalPlane.normal[0];
1055 		plane[1] = dest->portalPlane.normal[1];
1056 		plane[2] = dest->portalPlane.normal[2];
1057 		plane[3] = dest->portalPlane.dist;
1058 
1059 		plane2[0] = -DotProduct (dest->or.axis[1], plane);
1060 		plane2[1] = DotProduct (dest->or.axis[2], plane);
1061 		plane2[2] = -DotProduct (dest->or.axis[0], plane);
1062 		plane2[3] = DotProduct (plane, dest->or.origin) - plane[3];
1063 
1064 		// Lengyel, Eric. "Modifying the Projection Matrix to Perform Oblique Near-plane Clipping".
1065 		// Terathon Software 3D Graphics Library, 2004. http://www.terathon.com/code/oblique.html
1066 		q[0] = (SGN(plane2[0]) + dest->projectionMatrix[8]) / dest->projectionMatrix[0];
1067 		q[1] = (SGN(plane2[1]) + dest->projectionMatrix[9]) / dest->projectionMatrix[5];
1068 		q[2] = -1.0f;
1069 		q[3] = (1.0f + dest->projectionMatrix[10]) / dest->projectionMatrix[14];
1070 
1071 		VectorScale4(plane2, 2.0f / DotProduct4(plane2, q), c);
1072 
1073 		dest->projectionMatrix[2]  = c[0];
1074 		dest->projectionMatrix[6]  = c[1];
1075 		dest->projectionMatrix[10] = c[2] + 1.0f;
1076 		dest->projectionMatrix[14] = c[3];
1077 
1078 	}
1079 }
1080 
1081 /*
1082 ===============
1083 R_SetupProjectionOrtho
1084 ===============
1085 */
R_SetupProjectionOrtho(viewParms_t * dest,vec3_t viewBounds[2])1086 void R_SetupProjectionOrtho(viewParms_t *dest, vec3_t viewBounds[2])
1087 {
1088 	float xmin, xmax, ymin, ymax, znear, zfar;
1089 	//viewParms_t *dest = &tr.viewParms;
1090 	int i;
1091 	vec3_t pop;
1092 
1093 	// Quake3:   Projection:
1094 	//
1095 	//    Z  X   Y  Z
1096 	//    | /    | /
1097 	//    |/     |/
1098 	// Y--+      +--X
1099 
1100 	xmin  =  viewBounds[0][1];
1101 	xmax  =  viewBounds[1][1];
1102 	ymin  = -viewBounds[1][2];
1103 	ymax  = -viewBounds[0][2];
1104 	znear =  viewBounds[0][0];
1105 	zfar  =  viewBounds[1][0];
1106 
1107 	dest->projectionMatrix[0]  = 2 / (xmax - xmin);
1108 	dest->projectionMatrix[4]  = 0;
1109 	dest->projectionMatrix[8]  = 0;
1110 	dest->projectionMatrix[12] = (xmax + xmin) / (xmax - xmin);
1111 
1112 	dest->projectionMatrix[1]  = 0;
1113 	dest->projectionMatrix[5]  = 2 / (ymax - ymin);
1114 	dest->projectionMatrix[9]  = 0;
1115 	dest->projectionMatrix[13] = (ymax + ymin) / (ymax - ymin);
1116 
1117 	dest->projectionMatrix[2]  = 0;
1118 	dest->projectionMatrix[6]  = 0;
1119 	dest->projectionMatrix[10] = -2 / (zfar - znear);
1120 	dest->projectionMatrix[14] = -(zfar + znear) / (zfar - znear);
1121 
1122 	dest->projectionMatrix[3]  = 0;
1123 	dest->projectionMatrix[7]  = 0;
1124 	dest->projectionMatrix[11] = 0;
1125 	dest->projectionMatrix[15] = 1;
1126 
1127 	VectorScale(dest->or.axis[1],  1.0f, dest->frustum[0].normal);
1128 	VectorMA(dest->or.origin, viewBounds[0][1], dest->frustum[0].normal, pop);
1129 	dest->frustum[0].dist = DotProduct(pop, dest->frustum[0].normal);
1130 
1131 	VectorScale(dest->or.axis[1], -1.0f, dest->frustum[1].normal);
1132 	VectorMA(dest->or.origin, -viewBounds[1][1], dest->frustum[1].normal, pop);
1133 	dest->frustum[1].dist = DotProduct(pop, dest->frustum[1].normal);
1134 
1135 	VectorScale(dest->or.axis[2],  1.0f, dest->frustum[2].normal);
1136 	VectorMA(dest->or.origin, viewBounds[0][2], dest->frustum[2].normal, pop);
1137 	dest->frustum[2].dist = DotProduct(pop, dest->frustum[2].normal);
1138 
1139 	VectorScale(dest->or.axis[2], -1.0f, dest->frustum[3].normal);
1140 	VectorMA(dest->or.origin, -viewBounds[1][2], dest->frustum[3].normal, pop);
1141 	dest->frustum[3].dist = DotProduct(pop, dest->frustum[3].normal);
1142 
1143 	VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal);
1144 	VectorMA(dest->or.origin, -viewBounds[1][0], dest->frustum[4].normal, pop);
1145 	dest->frustum[4].dist = DotProduct(pop, dest->frustum[4].normal);
1146 
1147 	for (i = 0; i < 5; i++)
1148 	{
1149 		dest->frustum[i].type = PLANE_NON_AXIAL;
1150 		SetPlaneSignbits (&dest->frustum[i]);
1151 	}
1152 
1153 	dest->flags |= VPF_FARPLANEFRUSTUM;
1154 }
1155 
1156 /*
1157 =================
1158 R_MirrorPoint
1159 =================
1160 */
R_MirrorPoint(vec3_t in,orientation_t * surface,orientation_t * camera,vec3_t out)1161 void R_MirrorPoint( vec3_t in, orientation_t *surface, orientation_t *camera, vec3_t out ) {
1162 	int i;
1163 	vec3_t local;
1164 	vec3_t transformed;
1165 	float d;
1166 
1167 	VectorSubtract( in, surface->origin, local );
1168 
1169 	VectorClear( transformed );
1170 	for ( i = 0 ; i < 3 ; i++ ) {
1171 		d = DotProduct( local, surface->axis[i] );
1172 		VectorMA( transformed, d, camera->axis[i], transformed );
1173 	}
1174 
1175 	VectorAdd( transformed, camera->origin, out );
1176 }
1177 
R_MirrorVector(vec3_t in,orientation_t * surface,orientation_t * camera,vec3_t out)1178 void R_MirrorVector( vec3_t in, orientation_t *surface, orientation_t *camera, vec3_t out ) {
1179 	int i;
1180 	float d;
1181 
1182 	VectorClear( out );
1183 	for ( i = 0 ; i < 3 ; i++ ) {
1184 		d = DotProduct( in, surface->axis[i] );
1185 		VectorMA( out, d, camera->axis[i], out );
1186 	}
1187 }
1188 
1189 
1190 /*
1191 =============
1192 R_PlaneForSurface
1193 =============
1194 */
R_PlaneForSurface(surfaceType_t * surfType,cplane_t * plane)1195 void R_PlaneForSurface( surfaceType_t *surfType, cplane_t *plane ) {
1196 	srfBspSurface_t	*tri;
1197 	srfPoly_t       *poly;
1198 	srfVert_t		*v1, *v2, *v3;
1199 	vec4_t plane4;
1200 
1201 	if ( !surfType ) {
1202 		memset( plane, 0, sizeof( *plane ) );
1203 		plane->normal[0] = 1;
1204 		return;
1205 	}
1206 	switch ( *surfType ) {
1207 	case SF_FACE:
1208 		*plane = ((srfBspSurface_t *)surfType)->cullPlane;
1209 		return;
1210 	case SF_TRIANGLES:
1211 		tri = (srfBspSurface_t *)surfType;
1212 		v1 = tri->verts + tri->indexes[0];
1213 		v2 = tri->verts + tri->indexes[1];
1214 		v3 = tri->verts + tri->indexes[2];
1215 		PlaneFromPoints( plane4, v1->xyz, v2->xyz, v3->xyz );
1216 		VectorCopy( plane4, plane->normal );
1217 		plane->dist = plane4[3];
1218 		return;
1219 	case SF_POLY:
1220 		poly = (srfPoly_t *)surfType;
1221 		PlaneFromPoints( plane4, poly->verts[0].xyz, poly->verts[1].xyz, poly->verts[2].xyz );
1222 		VectorCopy( plane4, plane->normal );
1223 		plane->dist = plane4[3];
1224 		return;
1225 	default:
1226 		memset( plane, 0, sizeof( *plane ) );
1227 		plane->normal[0] = 1;
1228 		return;
1229 	}
1230 }
1231 
1232 /*
1233 =================
1234 R_GetPortalOrientation
1235 
1236 entityNum is the entity that the portal surface is a part of, which may
1237 be moving and rotating.
1238 
1239 Returns qtrue if it should be mirrored
1240 =================
1241 */
R_GetPortalOrientations(drawSurf_t * drawSurf,int entityNum,orientation_t * surface,orientation_t * camera,vec3_t pvsOrigin,qboolean * mirror)1242 qboolean R_GetPortalOrientations( drawSurf_t *drawSurf, int entityNum,
1243 								  orientation_t *surface, orientation_t *camera,
1244 								  vec3_t pvsOrigin, qboolean *mirror ) {
1245 	int i;
1246 	cplane_t originalPlane, plane;
1247 	trRefEntity_t   *e;
1248 	float d;
1249 	vec3_t transformed;
1250 
1251 	// create plane axis for the portal we are seeing
1252 	R_PlaneForSurface( drawSurf->surface, &originalPlane );
1253 
1254 	// rotate the plane if necessary
1255 	if ( entityNum != REFENTITYNUM_WORLD ) {
1256 		tr.currentEntityNum = entityNum;
1257 		tr.currentEntity = &tr.refdef.entities[entityNum];
1258 
1259 		// get the orientation of the entity
1260 		R_RotateForEntity( tr.currentEntity, &tr.viewParms, &tr.or );
1261 
1262 		// rotate the plane, but keep the non-rotated version for matching
1263 		// against the portalSurface entities
1264 		R_LocalNormalToWorld( originalPlane.normal, plane.normal );
1265 		plane.dist = originalPlane.dist + DotProduct( plane.normal, tr.or.origin );
1266 
1267 		// translate the original plane
1268 		originalPlane.dist = originalPlane.dist + DotProduct( originalPlane.normal, tr.or.origin );
1269 	} else {
1270 		plane = originalPlane;
1271 	}
1272 
1273 	VectorCopy( plane.normal, surface->axis[0] );
1274 	PerpendicularVector( surface->axis[1], surface->axis[0] );
1275 	CrossProduct( surface->axis[0], surface->axis[1], surface->axis[2] );
1276 
1277 	// locate the portal entity closest to this plane.
1278 	// origin will be the origin of the portal, origin2 will be
1279 	// the origin of the camera
1280 	for ( i = 0 ; i < tr.refdef.num_entities ; i++ ) {
1281 		e = &tr.refdef.entities[i];
1282 		if ( e->e.reType != RT_PORTALSURFACE ) {
1283 			continue;
1284 		}
1285 
1286 		d = DotProduct( e->e.origin, originalPlane.normal ) - originalPlane.dist;
1287 		if ( d > 64 || d < -64 ) {
1288 			continue;
1289 		}
1290 
1291 		// get the pvsOrigin from the entity
1292 		VectorCopy( e->e.oldorigin, pvsOrigin );
1293 
1294 		// if the entity is just a mirror, don't use as a camera point
1295 		if ( e->e.oldorigin[0] == e->e.origin[0] &&
1296 			 e->e.oldorigin[1] == e->e.origin[1] &&
1297 			 e->e.oldorigin[2] == e->e.origin[2] ) {
1298 			VectorScale( plane.normal, plane.dist, surface->origin );
1299 			VectorCopy( surface->origin, camera->origin );
1300 			VectorSubtract( vec3_origin, surface->axis[0], camera->axis[0] );
1301 			VectorCopy( surface->axis[1], camera->axis[1] );
1302 			VectorCopy( surface->axis[2], camera->axis[2] );
1303 
1304 			*mirror = qtrue;
1305 			return qtrue;
1306 		}
1307 
1308 		// project the origin onto the surface plane to get
1309 		// an origin point we can rotate around
1310 		d = DotProduct( e->e.origin, plane.normal ) - plane.dist;
1311 		VectorMA( e->e.origin, -d, surface->axis[0], surface->origin );
1312 
1313 		// now get the camera origin and orientation
1314 		VectorCopy( e->e.oldorigin, camera->origin );
1315 		AxisCopy( e->e.axis, camera->axis );
1316 		VectorSubtract( vec3_origin, camera->axis[0], camera->axis[0] );
1317 		VectorSubtract( vec3_origin, camera->axis[1], camera->axis[1] );
1318 
1319 		// optionally rotate
1320 		if ( e->e.oldframe ) {
1321 			// if a speed is specified
1322 			if ( e->e.frame ) {
1323 				// continuous rotate
1324 				d = ( tr.refdef.time / 1000.0f ) * e->e.frame;
1325 				VectorCopy( camera->axis[1], transformed );
1326 				RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
1327 				CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] );
1328 			} else {
1329 				// bobbing rotate, with skinNum being the rotation offset
1330 				d = sin( tr.refdef.time * 0.003f );
1331 				d = e->e.skinNum + d * 4;
1332 				VectorCopy( camera->axis[1], transformed );
1333 				RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
1334 				CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] );
1335 			}
1336 		} else if ( e->e.skinNum )   {
1337 			d = e->e.skinNum;
1338 			VectorCopy( camera->axis[1], transformed );
1339 			RotatePointAroundVector( camera->axis[1], camera->axis[0], transformed, d );
1340 			CrossProduct( camera->axis[0], camera->axis[1], camera->axis[2] );
1341 		}
1342 		*mirror = qfalse;
1343 		return qtrue;
1344 	}
1345 
1346 	// if we didn't locate a portal entity, don't render anything.
1347 	// We don't want to just treat it as a mirror, because without a
1348 	// portal entity the server won't have communicated a proper entity set
1349 	// in the snapshot
1350 
1351 	// unfortunately, with local movement prediction it is easily possible
1352 	// to see a surface before the server has communicated the matching
1353 	// portal surface entity, so we don't want to print anything here...
1354 
1355 	//ri.Printf( PRINT_ALL, "Portal surface without a portal entity\n" );
1356 
1357 	return qfalse;
1358 }
1359 
IsMirror(const drawSurf_t * drawSurf,int entityNum)1360 static qboolean IsMirror( const drawSurf_t *drawSurf, int entityNum ) {
1361 	int i;
1362 	cplane_t originalPlane, plane;
1363 	trRefEntity_t   *e;
1364 	float d;
1365 
1366 	// create plane axis for the portal we are seeing
1367 	R_PlaneForSurface( drawSurf->surface, &originalPlane );
1368 
1369 	// rotate the plane if necessary
1370 	if ( entityNum != REFENTITYNUM_WORLD ) {
1371 		tr.currentEntityNum = entityNum;
1372 		tr.currentEntity = &tr.refdef.entities[entityNum];
1373 
1374 		// get the orientation of the entity
1375 		R_RotateForEntity( tr.currentEntity, &tr.viewParms, &tr.or );
1376 
1377 		// rotate the plane, but keep the non-rotated version for matching
1378 		// against the portalSurface entities
1379 		R_LocalNormalToWorld( originalPlane.normal, plane.normal );
1380 		plane.dist = originalPlane.dist + DotProduct( plane.normal, tr.or.origin );
1381 
1382 		// translate the original plane
1383 		originalPlane.dist = originalPlane.dist + DotProduct( originalPlane.normal, tr.or.origin );
1384 	}
1385 
1386 	// locate the portal entity closest to this plane.
1387 	// origin will be the origin of the portal, origin2 will be
1388 	// the origin of the camera
1389 	for ( i = 0 ; i < tr.refdef.num_entities ; i++ )
1390 	{
1391 		e = &tr.refdef.entities[i];
1392 		if ( e->e.reType != RT_PORTALSURFACE ) {
1393 			continue;
1394 		}
1395 
1396 		d = DotProduct( e->e.origin, originalPlane.normal ) - originalPlane.dist;
1397 		if ( d > 64 || d < -64 ) {
1398 			continue;
1399 		}
1400 
1401 		// if the entity is just a mirror, don't use as a camera point
1402 		if ( e->e.oldorigin[0] == e->e.origin[0] &&
1403 			 e->e.oldorigin[1] == e->e.origin[1] &&
1404 			 e->e.oldorigin[2] == e->e.origin[2] ) {
1405 			return qtrue;
1406 		}
1407 
1408 		return qfalse;
1409 	}
1410 	return qfalse;
1411 }
1412 
1413 /*
1414 ** SurfIsOffscreen
1415 **
1416 ** Determines if a surface is completely offscreen.
1417 */
SurfIsOffscreen(const drawSurf_t * drawSurf,vec4_t clipDest[128])1418 static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128] ) {
1419 	float shortest = 100000000;
1420 	int entityNum;
1421 	int numTriangles;
1422 	shader_t *shader;
1423 	int fogNum;
1424 	int dlighted;
1425 	int pshadowed;
1426 // GR - tessellation flag
1427 	int atiTess;
1428 	vec4_t clip, eye;
1429 	int i;
1430 	unsigned int pointOr = 0;
1431 	unsigned int pointAnd = (unsigned int)~0;
1432 
1433 	R_RotateForViewer();
1434 
1435 // GR - decompose with tessellation flag
1436 	R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed, &atiTess );
1437 	RB_BeginSurface( shader, fogNum, drawSurf->cubemapIndex);
1438 	rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
1439 
1440 	assert( tess.numVertexes < 128 );
1441 
1442 	for ( i = 0; i < tess.numVertexes; i++ )
1443 	{
1444 		int j;
1445 		unsigned int pointFlags = 0;
1446 
1447 		R_TransformModelToClip( tess.xyz[i], tr.or.modelMatrix, tr.viewParms.projectionMatrix, eye, clip );
1448 
1449 		for ( j = 0; j < 3; j++ )
1450 		{
1451 			if ( clip[j] >= clip[3] ) {
1452 				pointFlags |= ( 1 << ( j * 2 ) );
1453 			} else if ( clip[j] <= -clip[3] )   {
1454 				pointFlags |= ( 1 << ( j * 2 + 1 ) );
1455 			}
1456 		}
1457 		pointAnd &= pointFlags;
1458 		pointOr |= pointFlags;
1459 	}
1460 
1461 	// trivially reject
1462 	if ( pointAnd ) {
1463 		return qtrue;
1464 	}
1465 
1466 	// determine if this surface is backfaced and also determine the distance
1467 	// to the nearest vertex so we can cull based on portal range.  Culling
1468 	// based on vertex distance isn't 100% correct (we should be checking for
1469 	// range to the surface), but it's good enough for the types of portals
1470 	// we have in the game right now.
1471 	numTriangles = tess.numIndexes / 3;
1472 
1473 	for ( i = 0; i < tess.numIndexes; i += 3 )
1474 	{
1475 		vec3_t normal, tNormal;
1476 
1477 		float len;
1478 
1479 		VectorSubtract( tess.xyz[tess.indexes[i]], tr.viewParms.or.origin, normal );
1480 
1481 		len = VectorLengthSquared( normal );            // lose the sqrt
1482 		if ( len < shortest ) {
1483 			shortest = len;
1484 		}
1485 
1486 		R_VaoUnpackNormal(tNormal, tess.normal[tess.indexes[i]]);
1487 
1488 		if ( DotProduct( normal, tNormal ) >= 0 )
1489  		{
1490 			numTriangles--;
1491 		}
1492 	}
1493 	if ( !numTriangles ) {
1494 		return qtrue;
1495 	}
1496 
1497 	// mirrors can early out at this point, since we don't do a fade over distance
1498 	// with them (although we could)
1499 	if ( IsMirror( drawSurf, entityNum ) ) {
1500 		return qfalse;
1501 	}
1502 
1503 	if ( shortest > ( tess.shader->portalRange * tess.shader->portalRange ) ) {
1504 		return qtrue;
1505 	}
1506 
1507 	return qfalse;
1508 }
1509 
1510 /*
1511 ========================
1512 R_MirrorViewBySurface
1513 
1514 Returns qtrue if another view has been rendered
1515 ========================
1516 */
R_MirrorViewBySurface(drawSurf_t * drawSurf,int entityNum)1517 qboolean R_MirrorViewBySurface( drawSurf_t *drawSurf, int entityNum ) {
1518 	vec4_t clipDest[128];
1519 	viewParms_t newParms;
1520 	viewParms_t oldParms;
1521 	orientation_t surface, camera;
1522 
1523 	// don't recursively mirror
1524 	if ( tr.viewParms.isPortal ) {
1525 		ri.Printf( PRINT_DEVELOPER, "WARNING: recursive mirror/portal found\n" );
1526 		return qfalse;
1527 	}
1528 
1529 //	if ( r_noportals->integer || r_fastsky->integer || tr.levelGLFog) {
1530 	if ( r_noportals->integer || r_fastsky->integer ) {
1531 		return qfalse;
1532 	}
1533 
1534 	// trivially reject portal/mirror
1535 	if ( SurfIsOffscreen( drawSurf, clipDest ) ) {
1536 		return qfalse;
1537 	}
1538 
1539 	// save old viewParms so we can return to it after the mirror view
1540 	oldParms = tr.viewParms;
1541 
1542 	newParms = tr.viewParms;
1543 	newParms.isPortal = qtrue;
1544 	newParms.zFar = 0.0f;
1545 	newParms.flags &= ~VPF_FARPLANEFRUSTUM;
1546 	if ( !R_GetPortalOrientations( drawSurf, entityNum, &surface, &camera,
1547 								   newParms.pvsOrigin, &newParms.isMirror ) ) {
1548 		return qfalse;      // bad portal, no portalentity
1549 	}
1550 
1551 	// Never draw viewmodels in portal or mirror views.
1552 	newParms.flags |= VPF_NOVIEWMODEL;
1553 
1554 	R_MirrorPoint( oldParms.or.origin, &surface, &camera, newParms.or.origin );
1555 
1556 	VectorSubtract( vec3_origin, camera.axis[0], newParms.portalPlane.normal );
1557 	newParms.portalPlane.dist = DotProduct( camera.origin, newParms.portalPlane.normal );
1558 
1559 	R_MirrorVector( oldParms.or.axis[0], &surface, &camera, newParms.or.axis[0] );
1560 	R_MirrorVector( oldParms.or.axis[1], &surface, &camera, newParms.or.axis[1] );
1561 	R_MirrorVector( oldParms.or.axis[2], &surface, &camera, newParms.or.axis[2] );
1562 
1563 	// OPTIMIZE: restrict the viewport on the mirrored view
1564 
1565 	// render the mirror view
1566 	R_RenderView( &newParms );
1567 
1568 	tr.viewParms = oldParms;
1569 
1570 	return qtrue;
1571 }
1572 
1573 /*
1574 =================
1575 R_SpriteFogNum
1576 
1577 See if a sprite is inside a fog volume
1578 =================
1579 */
R_SpriteFogNum(trRefEntity_t * ent)1580 int R_SpriteFogNum( trRefEntity_t *ent ) {
1581 	int i, j;
1582 	fog_t           *fog;
1583 
1584 	if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
1585 		return 0;
1586 	}
1587 
1588 	if ( ent->e.renderfx & RF_CROSSHAIR ) {
1589 		return 0;
1590 	}
1591 
1592 	for ( i = 1 ; i < tr.world->numfogs ; i++ ) {
1593 		fog = &tr.world->fogs[i];
1594 		for ( j = 0 ; j < 3 ; j++ ) {
1595 			if ( ent->e.origin[j] - ent->e.radius >= fog->bounds[1][j] ) {
1596 				break;
1597 			}
1598 			if ( ent->e.origin[j] + ent->e.radius <= fog->bounds[0][j] ) {
1599 				break;
1600 			}
1601 		}
1602 		if ( j == 3 ) {
1603 			return i;
1604 		}
1605 	}
1606 
1607 	return 0;
1608 }
1609 
1610 /*
1611 ==========================================================================================
1612 
1613 DRAWSURF SORTING
1614 
1615 ==========================================================================================
1616 */
1617 
1618 /*
1619 ===============
1620 R_Radix
1621 ===============
1622 */
R_Radix(int byte,int size,drawSurf_t * source,drawSurf_t * dest)1623 static ID_INLINE void R_Radix( int byte, int size, drawSurf_t *source, drawSurf_t *dest )
1624 {
1625   int           count[ 256 ] = { 0 };
1626   int           index[ 256 ];
1627   int           i;
1628   unsigned char *sortKey = NULL;
1629   unsigned char *end = NULL;
1630 
1631   sortKey = ( (unsigned char *)&source[ 0 ].sort ) + byte;
1632   end = sortKey + ( size * sizeof( drawSurf_t ) );
1633   for( ; sortKey < end; sortKey += sizeof( drawSurf_t ) )
1634     ++count[ *sortKey ];
1635 
1636   index[ 0 ] = 0;
1637 
1638   for( i = 1; i < 256; ++i )
1639     index[ i ] = index[ i - 1 ] + count[ i - 1 ];
1640 
1641   sortKey = ( (unsigned char *)&source[ 0 ].sort ) + byte;
1642   for( i = 0; i < size; ++i, sortKey += sizeof( drawSurf_t ) )
1643     dest[ index[ *sortKey ]++ ] = source[ i ];
1644 }
1645 
1646 /*
1647 ===============
1648 R_RadixSort
1649 
1650 Radix sort with 4 byte size buckets
1651 ===============
1652 */
R_RadixSort(drawSurf_t * source,int size)1653 static void R_RadixSort( drawSurf_t *source, int size )
1654 {
1655   static drawSurf_t scratch[ MAX_DRAWSURFS ];
1656 #ifdef Q3_LITTLE_ENDIAN
1657   R_Radix( 0, size, source, scratch );
1658   R_Radix( 1, size, scratch, source );
1659   R_Radix( 2, size, source, scratch );
1660   R_Radix( 3, size, scratch, source );
1661 #else
1662   R_Radix( 3, size, source, scratch );
1663   R_Radix( 2, size, scratch, source );
1664   R_Radix( 1, size, source, scratch );
1665   R_Radix( 0, size, scratch, source );
1666 #endif //Q3_LITTLE_ENDIAN
1667 }
1668 
1669 //==========================================================================================
1670 
1671 /*
1672 =================
1673 R_AddDrawSurf
1674 =================
1675 */
R_AddDrawSurf(surfaceType_t * surface,shader_t * shader,int fogIndex,int dlightMap,int pshadowMap,int cubemap,int atiTess)1676 void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader,
1677 					int fogIndex, int dlightMap, int pshadowMap, int cubemap, int atiTess ) {
1678 	int index;
1679 
1680 	// instead of checking for overflow, we just mask the index
1681 	// so it wraps around
1682 	index = tr.refdef.numDrawSurfs & DRAWSURF_MASK;
1683 	// the sort data is packed into a single 32 bit value so it can be
1684 	// compared quickly during the qsorting process
1685 // GR - add tesselation flag to the sort
1686 	tr.refdef.drawSurfs[index].sort = ( shader->sortedIndex << QSORT_SHADERNUM_SHIFT )
1687 		| ( atiTess << QSORT_ATI_TESS_SHIFT )
1688 		| tr.shiftedEntityNum | ( fogIndex << QSORT_FOGNUM_SHIFT )
1689 		| ((int)pshadowMap << QSORT_PSHADOW_SHIFT) | (int)dlightMap;
1690 	tr.refdef.drawSurfs[index].cubemapIndex = cubemap;
1691 	tr.refdef.drawSurfs[index].surface = surface;
1692 	tr.refdef.numDrawSurfs++;
1693 }
1694 
1695 /*
1696 =================
1697 R_DecomposeSort
1698 =================
1699 */
1700 // GR - decompose  with tessellation flag
R_DecomposeSort(unsigned sort,int * entityNum,shader_t ** shader,int * fogNum,int * dlightMap,int * pshadowMap,int * atiTess)1701 void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader,
1702 					  int *fogNum, int *dlightMap, int *pshadowMap, int *atiTess ) {
1703 	*fogNum = ( sort >> QSORT_FOGNUM_SHIFT ) & 31;
1704 	*shader = tr.sortedShaders[ ( sort >> QSORT_SHADERNUM_SHIFT ) & ( MAX_SHADERS - 1 ) ];
1705 //	*entityNum = ( sort >> QSORT_REFENTITYNUM_SHIFT ) & ( MAX_GENTITIES - 1 );   // (SA) uppded entity count for Wolf to 11 bits
1706 	*entityNum = ( sort >> QSORT_REFENTITYNUM_SHIFT ) & REFENTITYNUM_MASK;
1707 	*pshadowMap = (sort >> QSORT_PSHADOW_SHIFT ) & 1;
1708 	*dlightMap = sort & 1;
1709 //GR - extract tessellation flag
1710 	*atiTess = ( sort >> QSORT_ATI_TESS_SHIFT ) & 1;
1711 }
1712 
1713 /*
1714 =================
1715 R_SortDrawSurfs
1716 =================
1717 */
R_SortDrawSurfs(drawSurf_t * drawSurfs,int numDrawSurfs)1718 void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) {
1719 	shader_t        *shader;
1720 	int fogNum;
1721 	int entityNum;
1722 	int dlighted;
1723 	int             pshadowed;
1724 	int i;
1725 // GR - tessellation flag
1726 	int atiTess;
1727 
1728 	//ri.Printf(PRINT_ALL, "firstDrawSurf %d numDrawSurfs %d\n", (int)(drawSurfs - tr.refdef.drawSurfs), numDrawSurfs);
1729 
1730 	// it is possible for some views to not have any surfaces
1731 	if ( numDrawSurfs < 1 ) {
1732 		// we still need to add it for hyperspace cases
1733 		R_AddDrawSurfCmd( drawSurfs, numDrawSurfs );
1734 		return;
1735 	}
1736 
1737 	// sort the drawsurfs by sort type, then orientation, then shader
1738 	R_RadixSort( drawSurfs, numDrawSurfs );
1739 
1740 	// skip pass through drawing if rendering a shadow map
1741 	if (tr.viewParms.flags & (VPF_SHADOWMAP | VPF_DEPTHSHADOW))
1742 	{
1743 		R_AddDrawSurfCmd( drawSurfs, numDrawSurfs );
1744 		return;
1745 	}
1746 
1747 	// check for any pass through drawing, which
1748 	// may cause another view to be rendered first
1749 	for ( i = 0 ; i < numDrawSurfs ; i++ ) {
1750 // GR - decompose with tessellation flag
1751 		R_DecomposeSort( ( drawSurfs + i )->sort, &entityNum, &shader, &fogNum, &dlighted, &pshadowed, &atiTess );
1752 
1753 		if ( shader->sort > SS_PORTAL ) {
1754 			break;
1755 		}
1756 
1757 		// no shader should ever have this sort type
1758 		if ( shader->sort == SS_BAD ) {
1759 			ri.Error( ERR_DROP, "Shader '%s'with sort == SS_BAD", shader->name );
1760 		}
1761 
1762 		// if the mirror was completely clipped away, we may need to check another surface
1763 		if ( R_MirrorViewBySurface( ( drawSurfs + i ), entityNum ) ) {
1764 			// this is a debug option to see exactly what is being mirrored
1765 			if ( r_portalOnly->integer ) {
1766 				return;
1767 			}
1768 			break;      // only one mirror view at a time
1769 		}
1770 	}
1771 
1772 	R_AddDrawSurfCmd( drawSurfs, numDrawSurfs );
1773 }
1774 
1775 /*
1776 =============
1777 R_AddEntitySurfaces
1778 =============
1779 */
R_AddEntitySurface(int entityNum)1780 static void R_AddEntitySurface (int entityNum)
1781 {
1782 	trRefEntity_t   *ent;
1783 	shader_t        *shader;
1784 
1785 	tr.currentEntityNum = entityNum;
1786 
1787 	ent = tr.currentEntity = &tr.refdef.entities[tr.currentEntityNum];
1788 
1789 	ent->needDlights = qfalse;
1790 
1791 	// preshift the value we are going to OR into the drawsurf sort
1792 	tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
1793 
1794 	//
1795 	// the weapon model must be handled special --
1796 	// we don't want the hacked weapon position showing in
1797 	// mirrors, because the true body position will already be drawn
1798 	//
1799 	if ( (ent->e.renderfx & RF_FIRST_PERSON) && (tr.viewParms.flags & VPF_NOVIEWMODEL)) {
1800 		return;
1801 	}
1802 
1803 	// simple generated models, like sprites and beams, are not culled
1804 	switch ( ent->e.reType ) {
1805 	case RT_PORTALSURFACE:
1806 		break;      // don't draw anything
1807 	case RT_SPRITE:
1808 	case RT_SPLASH:
1809 	case RT_BEAM:
1810 	case RT_LIGHTNING:
1811 	case RT_RAIL_CORE:
1812 	case RT_RAIL_CORE_TAPER:
1813 	case RT_RAIL_RINGS:
1814 		// self blood sprites, talk balloons, etc should not be drawn in the primary
1815 		// view.  We can't just do this check for all entities, because md3
1816 		// entities may still want to cast shadows from them
1817 		if ( ( ent->e.renderfx & RF_THIRD_PERSON ) && !tr.viewParms.isPortal ) {
1818 				return;
1819 		}
1820 		shader = R_GetShaderByHandle( ent->e.customShader );
1821 		R_AddDrawSurf( &entitySurface, shader, R_SpriteFogNum( ent ), 0, 0,  0, /*cubeMap*/ ATI_TESS_NONE );
1822 		break;
1823 
1824 	case RT_MODEL:
1825 		// we must set up parts of tr.or for model culling
1826 		R_RotateForEntity( ent, &tr.viewParms, &tr.or );
1827 
1828 		tr.currentModel = R_GetModelByHandle( ent->e.hModel );
1829 		if ( !tr.currentModel ) {
1830 			R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0, 0, /*cubeMap*/ ATI_TESS_NONE );
1831 		} else {
1832 			switch ( tr.currentModel->type ) {
1833 			case MOD_MESH:
1834 				R_AddMD3Surfaces( ent );
1835 				break;
1836 			case MOD_MDS:
1837 				R_AddAnimSurfaces( ent );
1838 				break;
1839 			case MOD_MDR:
1840 				R_MDRAddAnimSurfaces( ent );
1841 				break;
1842 			case MOD_IQM:
1843 				R_AddIQMSurfaces( ent );
1844 				break;
1845 			case MOD_BRUSH:
1846 				R_AddBrushModelSurfaces( ent );
1847 				break;
1848 			case MOD_BAD:       // null model axis
1849 				if ( ( ent->e.renderfx & RF_THIRD_PERSON ) && !tr.viewParms.isPortal ) {
1850 					break;
1851 				}
1852 				R_AddDrawSurf( &entitySurface, tr.defaultShader, 0, 0, 0, 0, ATI_TESS_NONE );
1853 				break;
1854 			default:
1855 				ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad modeltype" );
1856 				break;
1857 			}
1858 		}
1859 		break;
1860 	default:
1861 		ri.Error( ERR_DROP, "R_AddEntitySurfaces: Bad reType" );
1862 	}
1863 
1864 }
1865 
1866 /*
1867 =============
1868 R_AddEntitySurfaces
1869 =============
1870 */
R_AddEntitySurfaces(void)1871 void R_AddEntitySurfaces (void) {
1872 	int i;
1873 
1874 	if ( !r_drawentities->integer ) {
1875 		return;
1876 	}
1877 
1878 	for ( i = 0; i < tr.refdef.num_entities; i++)
1879 		R_AddEntitySurface(i);
1880 }
1881 
1882 /*
1883 ====================
1884 R_GenerateDrawSurfs
1885 ====================
1886 */
R_GenerateDrawSurfs(void)1887 void R_GenerateDrawSurfs( void ) {
1888 	R_AddWorldSurfaces();
1889 
1890 	R_AddPolygonSurfaces();
1891 
1892 	// set the projection matrix with the minimum zfar
1893 	// now that we have the world bounded
1894 	// this needs to be done before entities are
1895 	// added, because they use the projection
1896 	// matrix for lod calculation
1897 
1898 	// dynamically compute far clip plane distance
1899 	if (!(tr.viewParms.flags & VPF_SHADOWMAP))
1900 	{
1901 		R_SetFarClip();
1902 	}
1903 
1904 	// we know the size of the clipping volume. Now set the rest of the projection matrix.
1905 	R_SetupProjectionZ (&tr.viewParms);
1906 
1907 	R_AddEntitySurfaces();
1908 }
1909 
1910 /*
1911 ================
1912 R_DebugPolygon
1913 ================
1914 */
R_DebugPolygon(int color,int numPoints,float * points)1915 void R_DebugPolygon( int color, int numPoints, float *points ) {
1916 	// FIXME: implement this
1917 #if 0
1918 	int i;
1919 
1920 	GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
1921 
1922 	// draw solid shade
1923 
1924 	qglColor3f( color & 1, ( color >> 1 ) & 1, ( color >> 2 ) & 1 );
1925 	qglBegin( GL_POLYGON );
1926 	for ( i = 0 ; i < numPoints ; i++ ) {
1927 		qglVertex3fv( points + i * 3 );
1928 	}
1929 	qglEnd();
1930 
1931 	// draw wireframe outline
1932 	GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE );
1933 	qglDepthRange( 0, 0 );
1934 	qglColor3f( 1, 1, 1 );
1935 	qglBegin( GL_POLYGON );
1936 	for ( i = 0 ; i < numPoints ; i++ ) {
1937 		qglVertex3fv( points + i * 3 );
1938 	}
1939 	qglEnd();
1940 	qglDepthRange( 0, 1 );
1941 #endif
1942 }
1943 
1944 /*
1945 ====================
1946 R_DebugGraphics
1947 
1948 Visualization aid for movement clipping debugging
1949 ====================
1950 */
R_DebugGraphics(void)1951 void R_DebugGraphics( void ) {
1952 	if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) {
1953 		return;
1954 	}
1955 	if ( !r_debugSurface->integer ) {
1956 		return;
1957 	}
1958 
1959 	R_IssuePendingRenderCommands();
1960 
1961 	GL_BindToTMU(tr.whiteImage, TB_COLORMAP);
1962 	GL_Cull( CT_FRONT_SIDED );
1963 	ri.CM_DrawDebugSurface( R_DebugPolygon );
1964 }
1965 
1966 
1967 /*
1968 ================
1969 R_RenderView
1970 
1971 A view may be either the actual camera view,
1972 or a mirror / remote location
1973 ================
1974 */
R_RenderView(viewParms_t * parms)1975 void R_RenderView( viewParms_t *parms ) {
1976 	int firstDrawSurf;
1977 	int numDrawSurfs;
1978 
1979 	if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) {
1980 		return;
1981 	}
1982 
1983 	tr.viewCount++;
1984 
1985 	tr.viewParms = *parms;
1986 	tr.viewParms.frameSceneNum = tr.frameSceneNum;
1987 	tr.viewParms.frameCount = tr.frameCount;
1988 
1989 	firstDrawSurf = tr.refdef.numDrawSurfs;
1990 
1991 	tr.viewCount++;
1992 
1993 	// set viewParms.world
1994 	R_RotateForViewer();
1995 
1996 	R_SetupProjection(&tr.viewParms, r_zproj->value, tr.viewParms.zFar, qtrue);
1997 
1998 	R_GenerateDrawSurfs();
1999 
2000 	// if we overflowed MAX_DRAWSURFS, the drawsurfs
2001 	// wrapped around in the buffer and we will be missing
2002 	// the first surfaces, not the last ones
2003 	numDrawSurfs = tr.refdef.numDrawSurfs;
2004 	if ( numDrawSurfs > MAX_DRAWSURFS ) {
2005 		numDrawSurfs = MAX_DRAWSURFS;
2006 	}
2007 
2008 	R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, numDrawSurfs - firstDrawSurf );
2009 
2010 	// draw main system development information (surface outlines, etc)
2011 	R_DebugGraphics();
2012 }
2013 
R_RenderDlightCubemaps(const refdef_t * fd)2014 void R_RenderDlightCubemaps(const refdef_t *fd)
2015 {
2016 	int i;
2017 
2018 	for (i = 0; i < tr.refdef.num_dlights; i++)
2019 	{
2020 		viewParms_t		shadowParms;
2021 		int j;
2022 
2023 		// use previous frame to determine visible dlights
2024 		if ((1 << i) & tr.refdef.dlightMask)
2025 			continue;
2026 
2027 		Com_Memset( &shadowParms, 0, sizeof( shadowParms ) );
2028 
2029 		shadowParms.viewportX = tr.refdef.x;
2030 		shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + PSHADOW_MAP_SIZE );
2031 		shadowParms.viewportWidth = PSHADOW_MAP_SIZE;
2032 		shadowParms.viewportHeight = PSHADOW_MAP_SIZE;
2033 		shadowParms.isPortal = qfalse;
2034 		shadowParms.isMirror = qtrue; // because it is
2035 
2036 		shadowParms.fovX = 90;
2037 		shadowParms.fovY = 90;
2038 
2039 		shadowParms.flags = VPF_SHADOWMAP | VPF_DEPTHSHADOW | VPF_NOVIEWMODEL;
2040 		shadowParms.zFar = tr.refdef.dlights[i].radius;
2041 
2042 		VectorCopy( tr.refdef.dlights[i].origin, shadowParms.or.origin );
2043 
2044 		for (j = 0; j < 6; j++)
2045 		{
2046 			switch(j)
2047 			{
2048 				case 0:
2049 					// -X
2050 					VectorSet( shadowParms.or.axis[0], -1,  0,  0);
2051 					VectorSet( shadowParms.or.axis[1],  0,  0, -1);
2052 					VectorSet( shadowParms.or.axis[2],  0,  1,  0);
2053 					break;
2054 				case 1:
2055 					// +X
2056 					VectorSet( shadowParms.or.axis[0],  1,  0,  0);
2057 					VectorSet( shadowParms.or.axis[1],  0,  0,  1);
2058 					VectorSet( shadowParms.or.axis[2],  0,  1,  0);
2059 					break;
2060 				case 2:
2061 					// -Y
2062 					VectorSet( shadowParms.or.axis[0],  0, -1,  0);
2063 					VectorSet( shadowParms.or.axis[1],  1,  0,  0);
2064 					VectorSet( shadowParms.or.axis[2],  0,  0, -1);
2065 					break;
2066 				case 3:
2067 					// +Y
2068 					VectorSet( shadowParms.or.axis[0],  0,  1,  0);
2069 					VectorSet( shadowParms.or.axis[1],  1,  0,  0);
2070 					VectorSet( shadowParms.or.axis[2],  0,  0,  1);
2071 					break;
2072 				case 4:
2073 					// -Z
2074 					VectorSet( shadowParms.or.axis[0],  0,  0, -1);
2075 					VectorSet( shadowParms.or.axis[1],  1,  0,  0);
2076 					VectorSet( shadowParms.or.axis[2],  0,  1,  0);
2077 					break;
2078 				case 5:
2079 					// +Z
2080 					VectorSet( shadowParms.or.axis[0],  0,  0,  1);
2081 					VectorSet( shadowParms.or.axis[1], -1,  0,  0);
2082 					VectorSet( shadowParms.or.axis[2],  0,  1,  0);
2083 					break;
2084 			}
2085 
2086 			R_RenderView(&shadowParms);
2087 			R_AddCapShadowmapCmd( i, j );
2088 		}
2089 	}
2090 }
2091 
2092 
R_RenderPshadowMaps(const refdef_t * fd)2093 void R_RenderPshadowMaps(const refdef_t *fd)
2094 {
2095 	viewParms_t		shadowParms;
2096 	int i;
2097 
2098 	// first, make a list of shadows
2099 	for ( i = 0; i < tr.refdef.num_entities; i++)
2100 	{
2101 		trRefEntity_t *ent = &tr.refdef.entities[i];
2102 
2103 		if((ent->e.renderfx & (RF_FIRST_PERSON | RF_NOSHADOW)))
2104 			continue;
2105 
2106 		//if((ent->e.renderfx & RF_THIRD_PERSON))
2107 			//continue;
2108 
2109 		if (ent->e.reType == RT_MODEL)
2110 		{
2111 			model_t *model = R_GetModelByHandle( ent->e.hModel );
2112 			pshadow_t shadow;
2113 			float radius = 0.0f;
2114 			float scale = 1.0f;
2115 			vec3_t diff;
2116 			int j;
2117 
2118 			if (!model)
2119 				continue;
2120 
2121 			if (ent->e.nonNormalizedAxes)
2122 			{
2123 				scale = VectorLength( ent->e.axis[0] );
2124 			}
2125 
2126 			switch (model->type)
2127 			{
2128 				case MOD_MESH:
2129 				{
2130 					mdvFrame_t *frame = &model->mdv[0]->frames[ent->e.frame];
2131 
2132 					radius = frame->radius * scale;
2133 				}
2134 				break;
2135 				case MOD_MDS:
2136 				{
2137 					mdsHeader_t *header = model->mds;
2138 					int frameSize = (size_t)( &((mdsFrame_t *)0)->bones[ header->numBones ] );
2139 					mdsFrame_t *frame = ( mdsFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
2140 
2141 					radius = frame->radius;
2142 				}
2143 				break;
2144 				case MOD_MDR:
2145 				{
2146 					// FIXME: never actually tested this
2147 					mdrHeader_t *header = model->modelData;
2148 					int frameSize = (size_t)( &((mdrFrame_t *)0)->bones[ header->numBones ] );
2149 					mdrFrame_t *frame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame);
2150 
2151 					radius = frame->radius;
2152 				}
2153 				break;
2154 				case MOD_IQM:
2155 				{
2156 					// FIXME: never actually tested this
2157 					iqmData_t *data = model->modelData;
2158 					vec3_t diag;
2159 					float *framebounds;
2160 
2161 					framebounds = data->bounds + 6*ent->e.frame;
2162 					VectorSubtract( framebounds+3, framebounds, diag );
2163 					radius = 0.5f * VectorLength( diag );
2164 				}
2165 				break;
2166 
2167 				default:
2168 					break;
2169 			}
2170 
2171 			if (!radius)
2172 				continue;
2173 
2174 			// Cull entities that are behind the viewer by more than lightRadius
2175 			VectorSubtract(ent->e.origin, fd->vieworg, diff);
2176 			if (DotProduct(diff, fd->viewaxis[0]) < -r_pshadowDist->value)
2177 				continue;
2178 
2179 			memset(&shadow, 0, sizeof(shadow));
2180 
2181 			shadow.numEntities = 1;
2182 			shadow.entityNums[0] = i;
2183 			shadow.viewRadius = radius;
2184 			shadow.lightRadius = r_pshadowDist->value;
2185 			VectorCopy(ent->e.origin, shadow.viewOrigin);
2186 			shadow.sort = DotProduct(diff, diff) / (radius * radius);
2187 			VectorCopy(ent->e.origin, shadow.entityOrigins[0]);
2188 			shadow.entityRadiuses[0] = radius;
2189 
2190 			for (j = 0; j < MAX_CALC_PSHADOWS; j++)
2191 			{
2192 				pshadow_t swap;
2193 
2194 				if (j + 1 > tr.refdef.num_pshadows)
2195 				{
2196 					tr.refdef.num_pshadows = j + 1;
2197 					tr.refdef.pshadows[j] = shadow;
2198 					break;
2199 				}
2200 
2201 				// sort shadows by distance from camera divided by radius
2202 				// FIXME: sort better
2203 				if (tr.refdef.pshadows[j].sort <= shadow.sort)
2204 					continue;
2205 
2206 				swap = tr.refdef.pshadows[j];
2207 				tr.refdef.pshadows[j] = shadow;
2208 				shadow = swap;
2209 			}
2210 		}
2211 	}
2212 
2213 	// next, merge touching pshadows
2214 	for ( i = 0; i < tr.refdef.num_pshadows; i++)
2215 	{
2216 		pshadow_t *ps1 = &tr.refdef.pshadows[i];
2217 		int j;
2218 
2219 		for (j = i + 1; j < tr.refdef.num_pshadows; j++)
2220 		{
2221 			pshadow_t *ps2 = &tr.refdef.pshadows[j];
2222 			int k;
2223 			qboolean touch;
2224 
2225 			if (ps1->numEntities == 8)
2226 				break;
2227 
2228 			touch = qfalse;
2229 			if (SpheresIntersect(ps1->viewOrigin, ps1->viewRadius, ps2->viewOrigin, ps2->viewRadius))
2230 			{
2231 				for (k = 0; k < ps1->numEntities; k++)
2232 				{
2233 					if (SpheresIntersect(ps1->entityOrigins[k], ps1->entityRadiuses[k], ps2->viewOrigin, ps2->viewRadius))
2234 					{
2235 						touch = qtrue;
2236 						break;
2237 					}
2238 				}
2239 			}
2240 
2241 			if (touch)
2242 			{
2243 				vec3_t newOrigin;
2244 				float newRadius;
2245 
2246 				BoundingSphereOfSpheres(ps1->viewOrigin, ps1->viewRadius, ps2->viewOrigin, ps2->viewRadius, newOrigin, &newRadius);
2247 				VectorCopy(newOrigin, ps1->viewOrigin);
2248 				ps1->viewRadius = newRadius;
2249 
2250 				ps1->entityNums[ps1->numEntities] = ps2->entityNums[0];
2251 				VectorCopy(ps2->viewOrigin, ps1->entityOrigins[ps1->numEntities]);
2252 				ps1->entityRadiuses[ps1->numEntities] = ps2->viewRadius;
2253 
2254 				ps1->numEntities++;
2255 
2256 				for (k = j; k < tr.refdef.num_pshadows - 1; k++)
2257 				{
2258 					tr.refdef.pshadows[k] = tr.refdef.pshadows[k + 1];
2259 				}
2260 
2261 				j--;
2262 				tr.refdef.num_pshadows--;
2263 			}
2264 		}
2265 	}
2266 
2267 	// cap number of drawn pshadows
2268 	if (tr.refdef.num_pshadows > MAX_DRAWN_PSHADOWS)
2269 	{
2270 		tr.refdef.num_pshadows = MAX_DRAWN_PSHADOWS;
2271 	}
2272 
2273 	// next, fill up the rest of the shadow info
2274 	for ( i = 0; i < tr.refdef.num_pshadows; i++)
2275 	{
2276 		pshadow_t *shadow = &tr.refdef.pshadows[i];
2277 		vec3_t up;
2278 		vec3_t ambientLight, directedLight, lightDir;
2279 
2280 		VectorSet(lightDir, 0.57735f, 0.57735f, 0.57735f);
2281 #if 1
2282 		R_LightForPoint(shadow->viewOrigin, ambientLight, directedLight, lightDir);
2283 
2284 		// sometimes there's no light
2285 		if (DotProduct(lightDir, lightDir) < 0.9f)
2286 			VectorSet(lightDir, 0.0f, 0.0f, 1.0f);
2287 #endif
2288 
2289 		if (shadow->viewRadius * 3.0f > shadow->lightRadius)
2290 		{
2291 			shadow->lightRadius = shadow->viewRadius * 3.0f;
2292 		}
2293 
2294 		VectorMA(shadow->viewOrigin, shadow->viewRadius, lightDir, shadow->lightOrigin);
2295 
2296 		// make up a projection, up doesn't matter
2297 		VectorScale(lightDir, -1.0f, shadow->lightViewAxis[0]);
2298 		VectorSet(up, 0, 0, -1);
2299 
2300 		if ( fabs(DotProduct(up, shadow->lightViewAxis[0])) > 0.9f )
2301 		{
2302 			VectorSet(up, -1, 0, 0);
2303 		}
2304 
2305 		CrossProduct(shadow->lightViewAxis[0], up, shadow->lightViewAxis[1]);
2306 		VectorNormalize(shadow->lightViewAxis[1]);
2307 		CrossProduct(shadow->lightViewAxis[0], shadow->lightViewAxis[1], shadow->lightViewAxis[2]);
2308 
2309 		VectorCopy(shadow->lightViewAxis[0], shadow->cullPlane.normal);
2310 		shadow->cullPlane.dist = DotProduct(shadow->cullPlane.normal, shadow->lightOrigin);
2311 		shadow->cullPlane.type = PLANE_NON_AXIAL;
2312 		SetPlaneSignbits(&shadow->cullPlane);
2313 	}
2314 
2315 	// next, render shadowmaps
2316 	for ( i = 0; i < tr.refdef.num_pshadows; i++)
2317 	{
2318 		int firstDrawSurf;
2319 		pshadow_t *shadow = &tr.refdef.pshadows[i];
2320 		int j;
2321 
2322 		Com_Memset( &shadowParms, 0, sizeof( shadowParms ) );
2323 
2324 		if (glRefConfig.framebufferObject)
2325 		{
2326 			shadowParms.viewportX = 0;
2327 			shadowParms.viewportY = 0;
2328 		}
2329 		else
2330 		{
2331 			shadowParms.viewportX = tr.refdef.x;
2332 			shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + PSHADOW_MAP_SIZE );
2333 		}
2334 		shadowParms.viewportWidth = PSHADOW_MAP_SIZE;
2335 		shadowParms.viewportHeight = PSHADOW_MAP_SIZE;
2336 		shadowParms.isPortal = qfalse;
2337 		shadowParms.isMirror = qfalse;
2338 
2339 		shadowParms.fovX = 90;
2340 		shadowParms.fovY = 90;
2341 
2342 		if (glRefConfig.framebufferObject)
2343 			shadowParms.targetFbo = tr.pshadowFbos[i];
2344 
2345 		shadowParms.flags = VPF_DEPTHSHADOW | VPF_NOVIEWMODEL;
2346 		shadowParms.zFar = shadow->lightRadius;
2347 
2348 		VectorCopy(shadow->lightOrigin, shadowParms.or.origin);
2349 
2350 		VectorCopy(shadow->lightViewAxis[0], shadowParms.or.axis[0]);
2351 		VectorCopy(shadow->lightViewAxis[1], shadowParms.or.axis[1]);
2352 		VectorCopy(shadow->lightViewAxis[2], shadowParms.or.axis[2]);
2353 
2354 		{
2355 			tr.viewCount++;
2356 
2357 			tr.viewParms = shadowParms;
2358 			tr.viewParms.frameSceneNum = tr.frameSceneNum;
2359 			tr.viewParms.frameCount = tr.frameCount;
2360 
2361 			firstDrawSurf = tr.refdef.numDrawSurfs;
2362 
2363 			tr.viewCount++;
2364 
2365 			// set viewParms.world
2366 			R_RotateForViewer ();
2367 
2368 			{
2369 				float xmin, xmax, ymin, ymax, znear, zfar;
2370 				viewParms_t *dest = &tr.viewParms;
2371 				vec3_t pop;
2372 
2373 				xmin = ymin = -shadow->viewRadius;
2374 				xmax = ymax = shadow->viewRadius;
2375 				znear = 0;
2376 				zfar = shadow->lightRadius;
2377 
2378 				dest->projectionMatrix[0] = 2 / (xmax - xmin);
2379 				dest->projectionMatrix[4] = 0;
2380 				dest->projectionMatrix[8] = (xmax + xmin) / (xmax - xmin);
2381 				dest->projectionMatrix[12] =0;
2382 
2383 				dest->projectionMatrix[1] = 0;
2384 				dest->projectionMatrix[5] = 2 / (ymax - ymin);
2385 				dest->projectionMatrix[9] = ( ymax + ymin ) / (ymax - ymin);	// normally 0
2386 				dest->projectionMatrix[13] = 0;
2387 
2388 				dest->projectionMatrix[2] = 0;
2389 				dest->projectionMatrix[6] = 0;
2390 				dest->projectionMatrix[10] = 2 / (zfar - znear);
2391 				dest->projectionMatrix[14] = 0;
2392 
2393 				dest->projectionMatrix[3] = 0;
2394 				dest->projectionMatrix[7] = 0;
2395 				dest->projectionMatrix[11] = 0;
2396 				dest->projectionMatrix[15] = 1;
2397 
2398 				VectorScale(dest->or.axis[1],  1.0f, dest->frustum[0].normal);
2399 				VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[0].normal, pop);
2400 				dest->frustum[0].dist = DotProduct(pop, dest->frustum[0].normal);
2401 
2402 				VectorScale(dest->or.axis[1], -1.0f, dest->frustum[1].normal);
2403 				VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[1].normal, pop);
2404 				dest->frustum[1].dist = DotProduct(pop, dest->frustum[1].normal);
2405 
2406 				VectorScale(dest->or.axis[2],  1.0f, dest->frustum[2].normal);
2407 				VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[2].normal, pop);
2408 				dest->frustum[2].dist = DotProduct(pop, dest->frustum[2].normal);
2409 
2410 				VectorScale(dest->or.axis[2], -1.0f, dest->frustum[3].normal);
2411 				VectorMA(dest->or.origin, -shadow->viewRadius, dest->frustum[3].normal, pop);
2412 				dest->frustum[3].dist = DotProduct(pop, dest->frustum[3].normal);
2413 
2414 				VectorScale(dest->or.axis[0], -1.0f, dest->frustum[4].normal);
2415 				VectorMA(dest->or.origin, -shadow->lightRadius, dest->frustum[4].normal, pop);
2416 				dest->frustum[4].dist = DotProduct(pop, dest->frustum[4].normal);
2417 
2418 				for (j = 0; j < 5; j++)
2419 				{
2420 					dest->frustum[j].type = PLANE_NON_AXIAL;
2421 					SetPlaneSignbits (&dest->frustum[j]);
2422 				}
2423 
2424 				dest->flags |= VPF_FARPLANEFRUSTUM;
2425 			}
2426 
2427 			for (j = 0; j < shadow->numEntities; j++)
2428 			{
2429 				R_AddEntitySurface(shadow->entityNums[j]);
2430 			}
2431 
2432 			R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
2433 
2434 			if (!glRefConfig.framebufferObject)
2435 				R_AddCapShadowmapCmd( i, -1 );
2436 		}
2437 	}
2438 }
2439 
CalcSplit(float n,float f,float i,float m)2440 static float CalcSplit(float n, float f, float i, float m)
2441 {
2442 	return (n * pow(f / n, i / m) + (f - n) * i / m) / 2.0f;
2443 }
2444 
2445 
R_RenderSunShadowMaps(const refdef_t * fd,int level)2446 void R_RenderSunShadowMaps(const refdef_t *fd, int level)
2447 {
2448 	viewParms_t		shadowParms;
2449 	vec4_t lightDir, lightCol;
2450 	vec3_t lightViewAxis[3];
2451 	vec3_t lightOrigin;
2452 	float splitZNear, splitZFar, splitBias;
2453 	float viewZNear, viewZFar;
2454 	vec3_t lightviewBounds[2];
2455 	qboolean lightViewIndependentOfCameraView = qfalse;
2456 
2457 	if (r_forceSun->integer == 2)
2458 	{
2459 		int scale = 32768;
2460 		float angle = (fd->time % scale) / (float)scale * M_PI;
2461 		lightDir[0] = cos(angle);
2462 		lightDir[1] = sin(35.0f * M_PI / 180.0f);
2463 		lightDir[2] = sin(angle) * cos(35.0f * M_PI / 180.0f);
2464 		lightDir[3] = 0.0f;
2465 
2466 		if (1) //((fd->time % (scale * 2)) < scale)
2467 		{
2468 			lightCol[0] =
2469 			lightCol[1] =
2470 			lightCol[2] = CLAMP(sin(angle) * 2.0f, 0.0f, 1.0f) * 2.0f;
2471 			lightCol[3] = 1.0f;
2472 		}
2473 		else
2474 		{
2475 			lightCol[0] =
2476 			lightCol[1] =
2477 			lightCol[2] = CLAMP(sin(angle) * 2.0f * 0.1f, 0.0f, 0.1f);
2478 			lightCol[3] = 1.0f;
2479 		}
2480 
2481 		VectorCopy4(lightDir, tr.refdef.sunDir);
2482 		VectorCopy4(lightCol, tr.refdef.sunCol);
2483 		VectorScale4(lightCol, 0.2f, tr.refdef.sunAmbCol);
2484 	}
2485 	else
2486 	{
2487 		VectorCopy4(tr.refdef.sunDir, lightDir);
2488 	}
2489 
2490 	viewZNear = r_shadowCascadeZNear->value;
2491 	viewZFar = r_shadowCascadeZFar->value;
2492 	splitBias = r_shadowCascadeZBias->value;
2493 
2494 	switch(level)
2495 	{
2496 		case 0:
2497 		default:
2498 			//splitZNear = r_znear->value;
2499 			//splitZFar  = 256;
2500 			splitZNear = viewZNear;
2501 			splitZFar = CalcSplit(viewZNear, viewZFar, 1, 3) + splitBias;
2502 			break;
2503 		case 1:
2504 			splitZNear = CalcSplit(viewZNear, viewZFar, 1, 3) + splitBias;
2505 			splitZFar = CalcSplit(viewZNear, viewZFar, 2, 3) + splitBias;
2506 			//splitZNear = 256;
2507 			//splitZFar  = 896;
2508 			break;
2509 		case 2:
2510 			splitZNear = CalcSplit(viewZNear, viewZFar, 2, 3) + splitBias;
2511 			splitZFar = viewZFar;
2512 			//splitZNear = 896;
2513 			//splitZFar  = 3072;
2514 			break;
2515 	}
2516 
2517 	if (level != 3)
2518 		VectorCopy(fd->vieworg, lightOrigin);
2519 	else
2520 		VectorCopy(tr.world->lightGridOrigin, lightOrigin);
2521 
2522 	// Make up a projection
2523 	VectorScale(lightDir, -1.0f, lightViewAxis[0]);
2524 
2525 	if (level == 3 || lightViewIndependentOfCameraView)
2526 	{
2527 		// Use world up as light view up
2528 		VectorSet(lightViewAxis[2], 0, 0, 1);
2529 	}
2530 	else if (level == 0)
2531 	{
2532 		// Level 0 tries to use a diamond texture orientation relative to camera view
2533 		// Use halfway between camera view forward and left for light view up
2534 		VectorAdd(fd->viewaxis[0], fd->viewaxis[1], lightViewAxis[2]);
2535 	}
2536 	else
2537 	{
2538 		// Use camera view up as light view up
2539 		VectorCopy(fd->viewaxis[2], lightViewAxis[2]);
2540 	}
2541 
2542 	// Check if too close to parallel to light direction
2543 	if (fabs(DotProduct(lightViewAxis[2], lightViewAxis[0])) > 0.9f)
2544 	{
2545 		if (level == 3 || lightViewIndependentOfCameraView)
2546 		{
2547 			// Use world left as light view up
2548 			VectorSet(lightViewAxis[2], 0, 1, 0);
2549 		}
2550 		else if (level == 0)
2551 		{
2552 			// Level 0 tries to use a diamond texture orientation relative to camera view
2553 			// Use halfway between camera view forward and up for light view up
2554 			VectorAdd(fd->viewaxis[0], fd->viewaxis[2], lightViewAxis[2]);
2555 		}
2556 		else
2557 		{
2558 			// Use camera view left as light view up
2559 			VectorCopy(fd->viewaxis[1], lightViewAxis[2]);
2560 		}
2561 	}
2562 
2563 	// clean axes
2564 	CrossProduct(lightViewAxis[2], lightViewAxis[0], lightViewAxis[1]);
2565 	VectorNormalize(lightViewAxis[1]);
2566 	CrossProduct(lightViewAxis[0], lightViewAxis[1], lightViewAxis[2]);
2567 
2568 	// Create bounds for light projection using slice of view projection
2569 	{
2570 		mat4_t lightViewMatrix;
2571 		vec4_t point, base, lightViewPoint;
2572 		float lx, ly;
2573 
2574 		base[3] = 1;
2575 		point[3] = 1;
2576 		lightViewPoint[3] = 1;
2577 
2578 		Mat4View(lightViewAxis, lightOrigin, lightViewMatrix);
2579 
2580 		ClearBounds(lightviewBounds[0], lightviewBounds[1]);
2581 
2582 		if (level != 3)
2583 		{
2584 			// add view near plane
2585 			lx = splitZNear * tan(fd->fov_x * M_PI / 360.0f);
2586 			ly = splitZNear * tan(fd->fov_y * M_PI / 360.0f);
2587 			VectorMA(fd->vieworg, splitZNear, fd->viewaxis[0], base);
2588 
2589 			VectorMA(base,   lx, fd->viewaxis[1], point);
2590 			VectorMA(point,  ly, fd->viewaxis[2], point);
2591 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2592 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2593 
2594 			VectorMA(base,  -lx, fd->viewaxis[1], point);
2595 			VectorMA(point,  ly, fd->viewaxis[2], point);
2596 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2597 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2598 
2599 			VectorMA(base,   lx, fd->viewaxis[1], point);
2600 			VectorMA(point, -ly, fd->viewaxis[2], point);
2601 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2602 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2603 
2604 			VectorMA(base,  -lx, fd->viewaxis[1], point);
2605 			VectorMA(point, -ly, fd->viewaxis[2], point);
2606 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2607 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2608 
2609 			// add view far plane
2610 			lx = splitZFar * tan(fd->fov_x * M_PI / 360.0f);
2611 			ly = splitZFar * tan(fd->fov_y * M_PI / 360.0f);
2612 			VectorMA(fd->vieworg, splitZFar, fd->viewaxis[0], base);
2613 
2614 			VectorMA(base,   lx, fd->viewaxis[1], point);
2615 			VectorMA(point,  ly, fd->viewaxis[2], point);
2616 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2617 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2618 
2619 			VectorMA(base,  -lx, fd->viewaxis[1], point);
2620 			VectorMA(point,  ly, fd->viewaxis[2], point);
2621 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2622 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2623 
2624 			VectorMA(base,   lx, fd->viewaxis[1], point);
2625 			VectorMA(point, -ly, fd->viewaxis[2], point);
2626 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2627 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2628 
2629 			VectorMA(base,  -lx, fd->viewaxis[1], point);
2630 			VectorMA(point, -ly, fd->viewaxis[2], point);
2631 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2632 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2633 		}
2634 		else
2635 		{
2636 			// use light grid size as level size
2637 			// FIXME: could be tighter
2638 			vec3_t bounds;
2639 
2640 			bounds[0] = tr.world->lightGridSize[0] * tr.world->lightGridBounds[0];
2641 			bounds[1] = tr.world->lightGridSize[1] * tr.world->lightGridBounds[1];
2642 			bounds[2] = tr.world->lightGridSize[2] * tr.world->lightGridBounds[2];
2643 
2644 			point[0] = tr.world->lightGridOrigin[0];
2645 			point[1] = tr.world->lightGridOrigin[1];
2646 			point[2] = tr.world->lightGridOrigin[2];
2647 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2648 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2649 
2650 			point[0] = tr.world->lightGridOrigin[0] + bounds[0];
2651 			point[1] = tr.world->lightGridOrigin[1];
2652 			point[2] = tr.world->lightGridOrigin[2];
2653 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2654 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2655 
2656 			point[0] = tr.world->lightGridOrigin[0];
2657 			point[1] = tr.world->lightGridOrigin[1] + bounds[1];
2658 			point[2] = tr.world->lightGridOrigin[2];
2659 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2660 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2661 
2662 			point[0] = tr.world->lightGridOrigin[0] + bounds[0];
2663 			point[1] = tr.world->lightGridOrigin[1] + bounds[1];
2664 			point[2] = tr.world->lightGridOrigin[2];
2665 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2666 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2667 
2668 			point[0] = tr.world->lightGridOrigin[0];
2669 			point[1] = tr.world->lightGridOrigin[1];
2670 			point[2] = tr.world->lightGridOrigin[2] + bounds[2];
2671 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2672 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2673 
2674 			point[0] = tr.world->lightGridOrigin[0] + bounds[0];
2675 			point[1] = tr.world->lightGridOrigin[1];
2676 			point[2] = tr.world->lightGridOrigin[2] + bounds[2];
2677 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2678 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2679 
2680 			point[0] = tr.world->lightGridOrigin[0];
2681 			point[1] = tr.world->lightGridOrigin[1] + bounds[1];
2682 			point[2] = tr.world->lightGridOrigin[2] + bounds[2];
2683 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2684 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2685 
2686 			point[0] = tr.world->lightGridOrigin[0] + bounds[0];
2687 			point[1] = tr.world->lightGridOrigin[1] + bounds[1];
2688 			point[2] = tr.world->lightGridOrigin[2] + bounds[2];
2689 			Mat4Transform(lightViewMatrix, point, lightViewPoint);
2690 			AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]);
2691 		}
2692 
2693 		if (!glRefConfig.depthClamp)
2694 			lightviewBounds[0][0] = lightviewBounds[1][0] - 8192;
2695 
2696 		// Moving the Light in Texel-Sized Increments
2697 		// from http://msdn.microsoft.com/en-us/library/windows/desktop/ee416324%28v=vs.85%29.aspx
2698 		//
2699 		if (lightViewIndependentOfCameraView)
2700 		{
2701 			float cascadeBound, worldUnitsPerTexel, invWorldUnitsPerTexel;
2702 
2703 			cascadeBound = MAX(lightviewBounds[1][0] - lightviewBounds[0][0], lightviewBounds[1][1] - lightviewBounds[0][1]);
2704 			cascadeBound = MAX(cascadeBound, lightviewBounds[1][2] - lightviewBounds[0][2]);
2705 			worldUnitsPerTexel = cascadeBound / tr.sunShadowFbo[level]->width;
2706 			invWorldUnitsPerTexel = 1.0f / worldUnitsPerTexel;
2707 
2708 			VectorScale(lightviewBounds[0], invWorldUnitsPerTexel, lightviewBounds[0]);
2709 			lightviewBounds[0][0] = floor(lightviewBounds[0][0]);
2710 			lightviewBounds[0][1] = floor(lightviewBounds[0][1]);
2711 			lightviewBounds[0][2] = floor(lightviewBounds[0][2]);
2712 			VectorScale(lightviewBounds[0], worldUnitsPerTexel, lightviewBounds[0]);
2713 
2714 			VectorScale(lightviewBounds[1], invWorldUnitsPerTexel, lightviewBounds[1]);
2715 			lightviewBounds[1][0] = floor(lightviewBounds[1][0]);
2716 			lightviewBounds[1][1] = floor(lightviewBounds[1][1]);
2717 			lightviewBounds[1][2] = floor(lightviewBounds[1][2]);
2718 			VectorScale(lightviewBounds[1], worldUnitsPerTexel, lightviewBounds[1]);
2719 		}
2720 
2721 		//ri.Printf(PRINT_ALL, "level %d znear %f zfar %f\n", level, lightviewBounds[0][0], lightviewBounds[1][0]);
2722 		//ri.Printf(PRINT_ALL, "xmin %f xmax %f ymin %f ymax %f\n", lightviewBounds[0][1], lightviewBounds[1][1], -lightviewBounds[1][2], -lightviewBounds[0][2]);
2723 	}
2724 
2725 
2726 	{
2727 		int firstDrawSurf;
2728 
2729 		Com_Memset( &shadowParms, 0, sizeof( shadowParms ) );
2730 
2731 		if (glRefConfig.framebufferObject)
2732 		{
2733 			shadowParms.viewportX = 0;
2734 			shadowParms.viewportY = 0;
2735 		}
2736 		else
2737 		{
2738 			shadowParms.viewportX = tr.refdef.x;
2739 			shadowParms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.sunShadowFbo[level]->height );
2740 		}
2741 		shadowParms.viewportWidth  = tr.sunShadowFbo[level]->width;
2742 		shadowParms.viewportHeight = tr.sunShadowFbo[level]->height;
2743 		shadowParms.isPortal = qfalse;
2744 		shadowParms.isMirror = qfalse;
2745 
2746 		shadowParms.fovX = 90;
2747 		shadowParms.fovY = 90;
2748 
2749 		if (glRefConfig.framebufferObject)
2750 			shadowParms.targetFbo = tr.sunShadowFbo[level];
2751 
2752 		shadowParms.flags = VPF_DEPTHSHADOW | VPF_DEPTHCLAMP | VPF_ORTHOGRAPHIC | VPF_NOVIEWMODEL;
2753 		shadowParms.zFar = lightviewBounds[1][0];
2754 
2755 		VectorCopy(lightOrigin, shadowParms.or.origin);
2756 
2757 		VectorCopy(lightViewAxis[0], shadowParms.or.axis[0]);
2758 		VectorCopy(lightViewAxis[1], shadowParms.or.axis[1]);
2759 		VectorCopy(lightViewAxis[2], shadowParms.or.axis[2]);
2760 
2761 		VectorCopy(lightOrigin, shadowParms.pvsOrigin );
2762 
2763 		{
2764 			tr.viewCount++;
2765 
2766 			tr.viewParms = shadowParms;
2767 			tr.viewParms.frameSceneNum = tr.frameSceneNum;
2768 			tr.viewParms.frameCount = tr.frameCount;
2769 
2770 			firstDrawSurf = tr.refdef.numDrawSurfs;
2771 
2772 			tr.viewCount++;
2773 
2774 			// set viewParms.world
2775 			R_RotateForViewer ();
2776 
2777 			R_SetupProjectionOrtho(&tr.viewParms, lightviewBounds);
2778 
2779 			R_AddWorldSurfaces ();
2780 
2781 			R_AddPolygonSurfaces();
2782 
2783 			R_AddEntitySurfaces ();
2784 
2785 			R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf );
2786 		}
2787 
2788 		Mat4Multiply(tr.viewParms.projectionMatrix, tr.viewParms.world.modelMatrix, tr.refdef.sunShadowMvp[level]);
2789 	}
2790 }
2791 
R_RenderCubemapSide(int cubemapIndex,int cubemapSide,qboolean subscene)2792 void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene )
2793 {
2794 	refdef_t refdef;
2795 	viewParms_t	parms;
2796 
2797 	memset( &refdef, 0, sizeof( refdef ) );
2798 	refdef.rdflags = 0;
2799 	VectorCopy(tr.cubemaps[cubemapIndex].origin, refdef.vieworg);
2800 
2801 	switch(cubemapSide)
2802 	{
2803 		case 0:
2804 			// -X
2805 			VectorSet( refdef.viewaxis[0], -1,  0,  0);
2806 			VectorSet( refdef.viewaxis[1],  0,  0, -1);
2807 			VectorSet( refdef.viewaxis[2],  0,  1,  0);
2808 			break;
2809 		case 1:
2810 			// +X
2811 			VectorSet( refdef.viewaxis[0],  1,  0,  0);
2812 			VectorSet( refdef.viewaxis[1],  0,  0,  1);
2813 			VectorSet( refdef.viewaxis[2],  0,  1,  0);
2814 			break;
2815 		case 2:
2816 			// -Y
2817 			VectorSet( refdef.viewaxis[0],  0, -1,  0);
2818 			VectorSet( refdef.viewaxis[1],  1,  0,  0);
2819 			VectorSet( refdef.viewaxis[2],  0,  0, -1);
2820 			break;
2821 		case 3:
2822 			// +Y
2823 			VectorSet( refdef.viewaxis[0],  0,  1,  0);
2824 			VectorSet( refdef.viewaxis[1],  1,  0,  0);
2825 			VectorSet( refdef.viewaxis[2],  0,  0,  1);
2826 			break;
2827 		case 4:
2828 			// -Z
2829 			VectorSet( refdef.viewaxis[0],  0,  0, -1);
2830 			VectorSet( refdef.viewaxis[1],  1,  0,  0);
2831 			VectorSet( refdef.viewaxis[2],  0,  1,  0);
2832 			break;
2833 		case 5:
2834 			// +Z
2835 			VectorSet( refdef.viewaxis[0],  0,  0,  1);
2836 			VectorSet( refdef.viewaxis[1], -1,  0,  0);
2837 			VectorSet( refdef.viewaxis[2],  0,  1,  0);
2838 			break;
2839 	}
2840 
2841 	refdef.fov_x = 90;
2842 	refdef.fov_y = 90;
2843 
2844 	refdef.x = 0;
2845 	refdef.y = 0;
2846 	refdef.width = tr.renderCubeFbo->width;
2847 	refdef.height = tr.renderCubeFbo->height;
2848 
2849 	refdef.time = 0;
2850 
2851 	if (!subscene)
2852 	{
2853 		RE_BeginScene(&refdef);
2854 
2855 		// FIXME: sun shadows aren't rendered correctly in cubemaps
2856 		// fix involves changing r_FBufScale to fit smaller cubemap image size, or rendering cubemap to framebuffer first
2857 		if(0) //(glRefConfig.framebufferObject && r_sunlightMode->integer && (r_forceSun->integer || tr.sunShadows))
2858 		{
2859 			R_RenderSunShadowMaps(&refdef, 0);
2860 			R_RenderSunShadowMaps(&refdef, 1);
2861 			R_RenderSunShadowMaps(&refdef, 2);
2862 			R_RenderSunShadowMaps(&refdef, 3);
2863 		}
2864 	}
2865 
2866 	{
2867 		vec3_t ambient, directed, lightDir;
2868 		float scale;
2869 
2870 		R_LightForPoint(tr.refdef.vieworg, ambient, directed, lightDir);
2871 		scale = directed[0] + directed[1] + directed[2] + ambient[0] + ambient[1] + ambient[2] + 1.0f;
2872 
2873 		// only print message for first side
2874 		if (scale < 1.0001f && cubemapSide == 0)
2875 		{
2876 			ri.Printf(PRINT_ALL, "cubemap %d %s (%f, %f, %f) is outside the lightgrid or inside a wall!\n", cubemapIndex, tr.cubemaps[cubemapIndex].name, tr.refdef.vieworg[0], tr.refdef.vieworg[1], tr.refdef.vieworg[2]);
2877 		}
2878 	}
2879 
2880 	Com_Memset( &parms, 0, sizeof( parms ) );
2881 
2882 	parms.viewportX = 0;
2883 	parms.viewportY = 0;
2884 	parms.viewportWidth = tr.renderCubeFbo->width;
2885 	parms.viewportHeight = tr.renderCubeFbo->height;
2886 	parms.isPortal = qfalse;
2887 	parms.isMirror = qtrue;
2888 	parms.flags =  VPF_NOVIEWMODEL | VPF_NOCUBEMAPS;
2889 
2890 	parms.fovX = 90;
2891 	parms.fovY = 90;
2892 
2893 	VectorCopy( refdef.vieworg, parms.or.origin );
2894 	VectorCopy( refdef.viewaxis[0], parms.or.axis[0] );
2895 	VectorCopy( refdef.viewaxis[1], parms.or.axis[1] );
2896 	VectorCopy( refdef.viewaxis[2], parms.or.axis[2] );
2897 
2898 	VectorCopy( refdef.vieworg, parms.pvsOrigin );
2899 
2900 	// FIXME: sun shadows aren't rendered correctly in cubemaps
2901 	// fix involves changing r_FBufScale to fit smaller cubemap image size, or rendering cubemap to framebuffer first
2902 	if (0) //(r_depthPrepass->value && ((r_forceSun->integer) || tr.sunShadows))
2903 	{
2904 		parms.flags = VPF_USESUNLIGHT;
2905 	}
2906 
2907 	parms.targetFbo = tr.renderCubeFbo;
2908 	parms.targetFboLayer = cubemapSide;
2909 	parms.targetFboCubemapIndex = cubemapIndex;
2910 
2911 	R_RenderView(&parms);
2912 
2913 	if (!subscene)
2914 		RE_EndScene();
2915 }
2916 
2917