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 #include "tr_local.h"
31 
32 int r_firstSceneDrawSurf;
33 
34 int r_numdlights;
35 int r_firstSceneDlight;
36 
37 int r_numcoronas;
38 int r_firstSceneCorona;
39 
40 int r_numentities;
41 int r_firstSceneEntity;
42 
43 int r_numpolys;
44 int r_firstScenePoly;
45 
46 int r_numpolyverts;
47 
48 int skyboxportal;
49 int drawskyboxportal;
50 
51 /*
52 ====================
53 R_InitNextFrame
54 ====================
55 */
R_InitNextFrame(void)56 void R_InitNextFrame( void ) {
57 	backEndData->commands.used = 0;
58 
59 	r_firstSceneDrawSurf = 0;
60 
61 	r_numdlights = 0;
62 	r_firstSceneDlight = 0;
63 
64 	r_numcoronas = 0;
65 	r_firstSceneCorona = 0;
66 
67 	r_numentities = 0;
68 	r_firstSceneEntity = 0;
69 
70 	r_numpolys = 0;
71 	r_firstScenePoly = 0;
72 
73 	r_numpolyverts = 0;
74 }
75 
76 
77 /*
78 ====================
79 RE_ClearScene
80 
81 ====================
82 */
RE_ClearScene(void)83 void RE_ClearScene( void ) {
84 	r_firstSceneDlight = r_numdlights;
85 	r_firstSceneCorona = r_numcoronas;
86 	r_firstSceneEntity = r_numentities;
87 	r_firstScenePoly = r_numpolys;
88 }
89 
90 /*
91 ===========================================================================
92 
93 DISCRETE POLYS
94 
95 ===========================================================================
96 */
97 
98 /*
99 =====================
100 R_AddPolygonSurfaces
101 
102 Adds all the scene's polys into this view's drawsurf list
103 =====================
104 */
R_AddPolygonSurfaces(void)105 void R_AddPolygonSurfaces( void ) {
106 	int i;
107 	shader_t    *sh;
108 	srfPoly_t   *poly;
109 
110 	tr.currentEntityNum = REFENTITYNUM_WORLD;
111 	tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
112 
113 	for ( i = 0, poly = tr.refdef.polys; i < tr.refdef.numPolys ; i++, poly++ ) {
114 		sh = R_GetShaderByHandle( poly->hShader );
115 // GR - not tessellated
116 		R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex, qfalse, ATI_TESS_NONE );
117 	}
118 }
119 
120 /*
121 =====================
122 RE_AddPolyToScene
123 
124 =====================
125 */
RE_AddPolyToScene(qhandle_t hShader,int numVerts,const polyVert_t * verts)126 void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts ) {
127 	srfPoly_t   *poly;
128 	int i;
129 	int fogIndex;
130 	fog_t       *fog;
131 	vec3_t bounds[2];
132 
133 	if ( !tr.registered ) {
134 		return;
135 	}
136 
137 	if ( !hShader ) {
138 		ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n" );
139 		return;
140 	}
141 
142 	if ( ( ( r_numpolyverts + numVerts ) >= max_polyverts ) || ( r_numpolys >= max_polys ) ) {
143 		return;
144 	}
145 
146 	poly = &backEndData->polys[r_numpolys];
147 	poly->surfaceType = SF_POLY;
148 	poly->hShader = hShader;
149 	poly->numVerts = numVerts;
150 	poly->verts = &backEndData->polyVerts[r_numpolyverts];
151 
152 	memcpy( poly->verts, verts, numVerts * sizeof( *verts ) );
153 	// Ridah
154 	if ( glConfig.hardwareType == GLHW_RAGEPRO ) {
155 		poly->verts->modulate[0] = 255;
156 		poly->verts->modulate[1] = 255;
157 		poly->verts->modulate[2] = 255;
158 		poly->verts->modulate[3] = 255;
159 	}
160 	// done.
161 	r_numpolys++;
162 	r_numpolyverts += numVerts;
163 
164 	// see if it is in a fog volume
165 	if ( tr.world->numfogs == 1 ) {
166 		fogIndex = 0;
167 	} else {
168 		// find which fog volume the poly is in
169 		VectorCopy( poly->verts[0].xyz, bounds[0] );
170 		VectorCopy( poly->verts[0].xyz, bounds[1] );
171 		for ( i = 1 ; i < poly->numVerts ; i++ ) {
172 			AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
173 		}
174 		for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
175 			fog = &tr.world->fogs[fogIndex];
176 			if ( bounds[1][0] >= fog->bounds[0][0]
177 				 && bounds[1][1] >= fog->bounds[0][1]
178 				 && bounds[1][2] >= fog->bounds[0][2]
179 				 && bounds[0][0] <= fog->bounds[1][0]
180 				 && bounds[0][1] <= fog->bounds[1][1]
181 				 && bounds[0][2] <= fog->bounds[1][2] ) {
182 				break;
183 			}
184 		}
185 		if ( fogIndex == tr.world->numfogs ) {
186 			fogIndex = 0;
187 		}
188 	}
189 	poly->fogIndex = fogIndex;
190 }
191 
192 // Ridah
193 /*
194 =====================
195 RE_AddPolysToScene
196 
197 =====================
198 */
RE_AddPolysToScene(qhandle_t hShader,int numVerts,const polyVert_t * verts,int numPolys)199 void RE_AddPolysToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) {
200 	srfPoly_t   *poly;
201 	int i;
202 	int fogIndex;
203 	fog_t       *fog;
204 	vec3_t bounds[2];
205 	int j;
206 
207 	if ( !tr.registered ) {
208 		return;
209 	}
210 
211 	if ( !hShader ) {
212 		ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolysToScene: NULL poly shader\n" );
213 		return;
214 	}
215 
216 	for ( j = 0; j < numPolys; j++ ) {
217 		if ( r_numpolyverts + numVerts >= max_polyverts || r_numpolys >= max_polys ) {
218 //			ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolysToScene: MAX_POLYS or MAX_POLYVERTS reached\n");
219 			return;
220 		}
221 
222 		poly = &backEndData->polys[r_numpolys];
223 		poly->surfaceType = SF_POLY;
224 		poly->hShader = hShader;
225 		poly->numVerts = numVerts;
226 		poly->verts = &backEndData->polyVerts[r_numpolyverts];
227 
228 		memcpy( poly->verts, &verts[numVerts * j], numVerts * sizeof( *verts ) );
229 		// Ridah
230 		if ( glConfig.hardwareType == GLHW_RAGEPRO ) {
231 			poly->verts->modulate[0] = 255;
232 			poly->verts->modulate[1] = 255;
233 			poly->verts->modulate[2] = 255;
234 			poly->verts->modulate[3] = 255;
235 		}
236 		// done.
237 		r_numpolys++;
238 		r_numpolyverts += numVerts;
239 
240 		// if no world is loaded
241 		if ( tr.world == NULL ) {
242 			fogIndex = 0;
243 		}
244 		// see if it is in a fog volume
245 		else if ( tr.world->numfogs == 1 ) {
246 			fogIndex = 0;
247 		} else {
248 			// find which fog volume the poly is in
249 			VectorCopy( poly->verts[0].xyz, bounds[0] );
250 			VectorCopy( poly->verts[0].xyz, bounds[1] );
251 			for ( i = 1 ; i < poly->numVerts ; i++ ) {
252 				AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
253 			}
254 			for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
255 				fog = &tr.world->fogs[fogIndex];
256 				if ( bounds[1][0] >= fog->bounds[0][0]
257 					 && bounds[1][1] >= fog->bounds[0][1]
258 					 && bounds[1][2] >= fog->bounds[0][2]
259 					 && bounds[0][0] <= fog->bounds[1][0]
260 					 && bounds[0][1] <= fog->bounds[1][1]
261 					 && bounds[0][2] <= fog->bounds[1][2] ) {
262 					break;
263 				}
264 			}
265 			if ( fogIndex == tr.world->numfogs ) {
266 				fogIndex = 0;
267 			}
268 		}
269 		poly->fogIndex = fogIndex;
270 	}
271 }
272 // done.
273 
274 
275 //=================================================================================
276 
277 
278 /*
279 =====================
280 RE_AddRefEntityToScene
281 
282 =====================
283 */
RE_AddRefEntityToScene(const refEntity_t * ent)284 void RE_AddRefEntityToScene( const refEntity_t *ent ) {
285 	if ( !tr.registered ) {
286 		return;
287 	}
288 	// show_bug.cgi?id=402
289 	if ( r_numentities >= MAX_REFENTITIES ) {
290 		ri.Printf(PRINT_DEVELOPER, "RE_AddRefEntityToScene: Dropping refEntity, reached MAX_REFENTITIES\n");
291 		return;
292 	}
293 	if ( Q_isnan(ent->origin[0]) || Q_isnan(ent->origin[1]) || Q_isnan(ent->origin[2]) ) {
294 		static qboolean firstTime = qtrue;
295 		if (firstTime) {
296 			firstTime = qfalse;
297 			ri.Printf( PRINT_WARNING, "RE_AddRefEntityToScene passed a refEntity which has an origin with a NaN component\n");
298 		}
299 		return;
300 	}
301 	if ( (int)ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) {
302 		ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
303 	}
304 
305 	backEndData->entities[r_numentities].e = *ent;
306 	backEndData->entities[r_numentities].lightingCalculated = qfalse;
307 
308 	r_numentities++;
309 }
310 
311 // Ridah, added support for overdraw field
312 /*
313 =====================
314 RE_AddLightToScene
315 
316 =====================
317 */
RE_AddLightToScene(const vec3_t org,float intensity,float r,float g,float b,int overdraw)318 void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b, int overdraw ) {
319 	dlight_t    *dl;
320 
321 	if ( !tr.registered ) {
322 		return;
323 	}
324 	if ( r_numdlights >= MAX_DLIGHTS ) {
325 		return;
326 	}
327 	if ( intensity <= 0 ) {
328 		return;
329 	}
330 	// these cards don't have the correct blend mode
331 	if ( glConfig.hardwareType == GLHW_RIVA128 || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
332 		return;
333 	}
334 	// RF, allow us to force some dlights under all circumstances
335 	if ( !( overdraw & REF_FORCE_DLIGHT ) ) {
336 		if ( r_dynamiclight->integer == 0 ) {
337 			return;
338 		}
339 		if ( r_dynamiclight->integer == 2 && !( backEndData->dlights[r_numdlights].forced ) ) {
340 			return;
341 		}
342 	}
343 
344 	if ( r_dlightScale->value <= 0 ) { //----(SA)	added
345 		return;
346 	}
347 
348 	overdraw &= ~REF_FORCE_DLIGHT;
349 	overdraw &= ~REF_JUNIOR_DLIGHT;
350 
351 	dl = &backEndData->dlights[r_numdlights++];
352 	VectorCopy( org, dl->origin );
353 
354 	dl->radius = intensity * r_dlightScale->value;  //----(SA)	modified
355 	dl->color[0] = r;
356 	dl->color[1] = g;
357 	dl->color[2] = b;
358 	dl->dlshader = NULL;
359 	dl->overdraw = 0;
360 
361 	if ( overdraw == 10 ) { // sorry, hijacking 10 for a quick hack (SA)
362 		dl->dlshader = R_GetShaderByHandle( RE_RegisterShader( "negdlightshader" ) );
363 	} else if ( overdraw == 11 ) { // 11 is flames
364 		dl->dlshader = R_GetShaderByHandle( RE_RegisterShader( "flamedlightshader" ) );
365 	} else {
366 		dl->overdraw = overdraw;
367 	}
368 }
369 // done.
370 
371 
372 /*
373 ==============
374 RE_AddCoronaToScene
375 ==============
376 */
RE_AddCoronaToScene(const vec3_t org,float r,float g,float b,float scale,int id,int flags)377 void RE_AddCoronaToScene( const vec3_t org, float r, float g, float b, float scale, int id, int flags ) {
378 	corona_t    *cor;
379 
380 	if ( !tr.registered ) {
381 		return;
382 	}
383 	if ( r_numcoronas >= MAX_CORONAS ) {
384 		return;
385 	}
386 
387 	cor = &backEndData->coronas[r_numcoronas++];
388 	VectorCopy( org, cor->origin );
389 	cor->color[0] = r;
390 	cor->color[1] = g;
391 	cor->color[2] = b;
392 	cor->scale = scale;
393 	cor->id = id;
394 	cor->flags = flags;
395 }
396 
397 /*
398 @@@@@@@@@@@@@@@@@@@@@
399 RE_RenderScene
400 
401 Draw a 3D view into a part of the window, then return
402 to 2D drawing.
403 
404 Rendering a scene may require multiple views to be rendered
405 to handle mirrors,
406 @@@@@@@@@@@@@@@@@@@@@
407 */
RE_RenderScene(const refdef_t * fd)408 void RE_RenderScene( const refdef_t *fd ) {
409 	viewParms_t parms;
410 	int startTime;
411 
412 	if ( !tr.registered ) {
413 		return;
414 	}
415 	GLimp_LogComment( "====== RE_RenderScene =====\n" );
416 
417 	if ( r_norefresh->integer ) {
418 		return;
419 	}
420 
421 	startTime = ri.Milliseconds();
422 
423 	if ( !tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) {
424 		ri.Error( ERR_DROP, "R_RenderScene: NULL worldmodel" );
425 	}
426 
427 	memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
428 
429 	tr.refdef.x = fd->x;
430 	tr.refdef.y = fd->y;
431 	tr.refdef.width = fd->width;
432 	tr.refdef.height = fd->height;
433 	tr.refdef.fov_x = fd->fov_x;
434 	tr.refdef.fov_y = fd->fov_y;
435 
436 	VectorCopy( fd->vieworg, tr.refdef.vieworg );
437 	VectorCopy( fd->viewaxis[0], tr.refdef.viewaxis[0] );
438 	VectorCopy( fd->viewaxis[1], tr.refdef.viewaxis[1] );
439 	VectorCopy( fd->viewaxis[2], tr.refdef.viewaxis[2] );
440 
441 	tr.refdef.time = fd->time;
442 	tr.refdef.rdflags = fd->rdflags;
443 
444 	if ( fd->rdflags & RDF_SKYBOXPORTAL ) {
445 		skyboxportal = 1;
446 	}
447 
448 	if ( fd->rdflags & RDF_DRAWSKYBOX ) {
449 		drawskyboxportal = 1;
450 	} else {
451 		drawskyboxportal = 0;
452 	}
453 
454 	// copy the areamask data over and note if it has changed, which
455 	// will force a reset of the visible leafs even if the view hasn't moved
456 	tr.refdef.areamaskModified = qfalse;
457 	if ( !( tr.refdef.rdflags & RDF_NOWORLDMODEL ) ) {
458 		int areaDiff;
459 		int i;
460 
461 		// compare the area bits
462 		areaDiff = 0;
463 		for ( i = 0 ; i < MAX_MAP_AREA_BYTES / 4 ; i++ ) {
464 			areaDiff |= ( (int *)tr.refdef.areamask )[i] ^ ( (int *)fd->areamask )[i];
465 			( (int *)tr.refdef.areamask )[i] = ( (int *)fd->areamask )[i];
466 		}
467 
468 		if ( areaDiff ) {
469 			// a door just opened or something
470 			tr.refdef.areamaskModified = qtrue;
471 		}
472 	}
473 
474 
475 	// derived info
476 
477 	tr.refdef.floatTime = tr.refdef.time * 0.001;
478 
479 	tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
480 	tr.refdef.drawSurfs = backEndData->drawSurfs;
481 
482 	tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
483 	tr.refdef.entities = &backEndData->entities[r_firstSceneEntity];
484 
485 	tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
486 	tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight];
487 
488 	tr.refdef.num_coronas = r_numcoronas - r_firstSceneCorona;
489 	tr.refdef.coronas = &backEndData->coronas[r_firstSceneCorona];
490 
491 	tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
492 	tr.refdef.polys = &backEndData->polys[r_firstScenePoly];
493 
494 	// turn off dynamic lighting globally by clearing all the
495 	// dlights if it needs to be disabled or if vertex lighting is enabled
496 	if ( /*r_dynamiclight->integer == 0 ||*/    // RF, disabled so we can force things like lightning dlights
497 		r_vertexLight->integer == 1 ||
498 		glConfig.hardwareType == GLHW_PERMEDIA2 ) {
499 		tr.refdef.num_dlights = 0;
500 	}
501 
502 	// a single frame may have multiple scenes draw inside it --
503 	// a 3D game view, 3D status bar renderings, 3D menus, etc.
504 	// They need to be distinguished by the light flare code, because
505 	// the visibility state for a given surface may be different in
506 	// each scene / view.
507 	tr.frameSceneNum++;
508 	tr.sceneCount++;
509 
510 	// setup view parms for the initial view
511 	//
512 	// set up viewport
513 	// The refdef takes 0-at-the-top y coordinates, so
514 	// convert to GL's 0-at-the-bottom space
515 	//
516 	memset( &parms, 0, sizeof( parms ) );
517 	parms.viewportX = tr.refdef.x;
518 	parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height );
519 	parms.viewportWidth = tr.refdef.width;
520 	parms.viewportHeight = tr.refdef.height;
521 	parms.isPortal = qfalse;
522 
523 	parms.fovX = tr.refdef.fov_x;
524 	parms.fovY = tr.refdef.fov_y;
525 
526 	parms.stereoFrame = tr.refdef.stereoFrame;
527 
528 	VectorCopy( fd->vieworg, parms.or.origin );
529 	VectorCopy( fd->viewaxis[0], parms.or.axis[0] );
530 	VectorCopy( fd->viewaxis[1], parms.or.axis[1] );
531 	VectorCopy( fd->viewaxis[2], parms.or.axis[2] );
532 
533 	VectorCopy( fd->vieworg, parms.pvsOrigin );
534 
535 	R_RenderView( &parms );
536 
537 	// the next scene rendered in this frame will tack on after this one
538 	r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
539 	r_firstSceneEntity = r_numentities;
540 	r_firstSceneDlight = r_numdlights;
541 	r_firstScenePoly = r_numpolys;
542 
543 	tr.frontEndMsec += ri.Milliseconds() - startTime;
544 }
545