1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4 
5 This file is part of Quake III Arena source code.
6 
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11 
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22 
23 #include "tr_local.h"
24 
25 int			r_firstSceneDrawSurf;
26 
27 int			r_numdlights;
28 int			r_firstSceneDlight;
29 
30 int			r_numentities;
31 int			r_firstSceneEntity;
32 
33 int			r_numpolys;
34 int			r_firstScenePoly;
35 
36 int			r_numpolyverts;
37 
38 
39 /*
40 ====================
41 R_ToggleSmpFrame
42 
43 ====================
44 */
R_ToggleSmpFrame(void)45 void R_ToggleSmpFrame( void ) {
46 	if ( r_smp->integer ) {
47 		// use the other buffers next frame, because another CPU
48 		// may still be rendering into the current ones
49 		tr.smpFrame ^= 1;
50 	} else {
51 		tr.smpFrame = 0;
52 	}
53 
54 	backEndData[tr.smpFrame]->commands.used = 0;
55 
56 	r_firstSceneDrawSurf = 0;
57 
58 	r_numdlights = 0;
59 	r_firstSceneDlight = 0;
60 
61 	r_numentities = 0;
62 	r_firstSceneEntity = 0;
63 
64 	r_numpolys = 0;
65 	r_firstScenePoly = 0;
66 
67 	r_numpolyverts = 0;
68 }
69 
70 
71 /*
72 ====================
73 RE_ClearScene
74 
75 ====================
76 */
RE_ClearScene(void)77 void RE_ClearScene( void ) {
78 	r_firstSceneDlight = r_numdlights;
79 	r_firstSceneEntity = r_numentities;
80 	r_firstScenePoly = r_numpolys;
81 }
82 
83 /*
84 ===========================================================================
85 
86 DISCRETE POLYS
87 
88 ===========================================================================
89 */
90 
91 /*
92 =====================
93 R_AddPolygonSurfaces
94 
95 Adds all the scene's polys into this view's drawsurf list
96 =====================
97 */
R_AddPolygonSurfaces(void)98 void R_AddPolygonSurfaces( void ) {
99 	int			i;
100 	shader_t	*sh;
101 	srfPoly_t	*poly;
102 
103 	tr.currentEntityNum = ENTITYNUM_WORLD;
104 	tr.shiftedEntityNum = tr.currentEntityNum << QSORT_ENTITYNUM_SHIFT;
105 
106 	for ( i = 0, poly = tr.refdef.polys; i < tr.refdef.numPolys ; i++, poly++ ) {
107 		sh = R_GetShaderByHandle( poly->hShader );
108 		R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex, qfalse );
109 	}
110 }
111 
112 /*
113 =====================
114 RE_AddPolyToScene
115 
116 =====================
117 */
RE_AddPolyToScene(qhandle_t hShader,int numVerts,const polyVert_t * verts,int numPolys)118 void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) {
119 	srfPoly_t	*poly;
120 	int			i, j;
121 	int			fogIndex;
122 	fog_t		*fog;
123 	vec3_t		bounds[2];
124 
125 	if ( !tr.registered ) {
126 		return;
127 	}
128 
129 	if ( !hShader ) {
130 		ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n");
131 		return;
132 	}
133 
134 	for ( j = 0; j < numPolys; j++ ) {
135 		if ( r_numpolyverts + numVerts > max_polyverts || r_numpolys >= max_polys ) {
136       /*
137       NOTE TTimo this was initially a PRINT_WARNING
138       but it happens a lot with high fighting scenes and particles
139       since we don't plan on changing the const and making for room for those effects
140       simply cut this message to developer only
141       */
142 			ri.Printf( PRINT_DEVELOPER, "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n");
143 			return;
144 		}
145 
146 		poly = &backEndData[tr.smpFrame]->polys[r_numpolys];
147 		poly->surfaceType = SF_POLY;
148 		poly->hShader = hShader;
149 		poly->numVerts = numVerts;
150 		poly->verts = &backEndData[tr.smpFrame]->polyVerts[r_numpolyverts];
151 
152 		Com_Memcpy( poly->verts, &verts[numVerts*j], numVerts * sizeof( *verts ) );
153 
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 		// if no world is loaded
165 		if ( tr.world == NULL ) {
166 			fogIndex = 0;
167 		}
168 		// see if it is in a fog volume
169 		else if ( tr.world->numfogs == 1 ) {
170 			fogIndex = 0;
171 		} else {
172 			// find which fog volume the poly is in
173 			VectorCopy( poly->verts[0].xyz, bounds[0] );
174 			VectorCopy( poly->verts[0].xyz, bounds[1] );
175 			for ( i = 1 ; i < poly->numVerts ; i++ ) {
176 				AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
177 			}
178 			for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
179 				fog = &tr.world->fogs[fogIndex];
180 				if ( bounds[1][0] >= fog->bounds[0][0]
181 					&& bounds[1][1] >= fog->bounds[0][1]
182 					&& bounds[1][2] >= fog->bounds[0][2]
183 					&& bounds[0][0] <= fog->bounds[1][0]
184 					&& bounds[0][1] <= fog->bounds[1][1]
185 					&& bounds[0][2] <= fog->bounds[1][2] ) {
186 					break;
187 				}
188 			}
189 			if ( fogIndex == tr.world->numfogs ) {
190 				fogIndex = 0;
191 			}
192 		}
193 		poly->fogIndex = fogIndex;
194 	}
195 }
196 
197 
198 //=================================================================================
199 
200 
201 /*
202 =====================
203 RE_AddRefEntityToScene
204 
205 =====================
206 */
RE_AddRefEntityToScene(const refEntity_t * ent)207 void RE_AddRefEntityToScene( const refEntity_t *ent ) {
208 	if ( !tr.registered ) {
209 		return;
210 	}
211 	if ( r_numentities >= MAX_ENTITIES ) {
212 		return;
213 	}
214 	if ( ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) {
215 		ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
216 	}
217 
218 	backEndData[tr.smpFrame]->entities[r_numentities].e = *ent;
219 	backEndData[tr.smpFrame]->entities[r_numentities].lightingCalculated = qfalse;
220 
221 	r_numentities++;
222 }
223 
224 
225 /*
226 =====================
227 RE_AddDynamicLightToScene
228 
229 =====================
230 */
RE_AddDynamicLightToScene(const vec3_t org,float intensity,float r,float g,float b,int additive)231 void RE_AddDynamicLightToScene( const vec3_t org, float intensity, float r, float g, float b, int additive ) {
232 	dlight_t	*dl;
233 
234 	if ( !tr.registered ) {
235 		return;
236 	}
237 	if ( r_numdlights >= MAX_DLIGHTS ) {
238 		return;
239 	}
240 	if ( intensity <= 0 ) {
241 		return;
242 	}
243 	// these cards don't have the correct blend mode
244 	if ( glConfig.hardwareType == GLHW_RIVA128 || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
245 		return;
246 	}
247 	dl = &backEndData[tr.smpFrame]->dlights[r_numdlights++];
248 	VectorCopy (org, dl->origin);
249 	dl->radius = intensity;
250 	dl->color[0] = r;
251 	dl->color[1] = g;
252 	dl->color[2] = b;
253 	dl->additive = additive;
254 }
255 
256 /*
257 =====================
258 RE_AddLightToScene
259 
260 =====================
261 */
RE_AddLightToScene(const vec3_t org,float intensity,float r,float g,float b)262 void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
263 	RE_AddDynamicLightToScene( org, intensity, r, g, b, qfalse );
264 }
265 
266 /*
267 =====================
268 RE_AddAdditiveLightToScene
269 
270 =====================
271 */
RE_AddAdditiveLightToScene(const vec3_t org,float intensity,float r,float g,float b)272 void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
273 	RE_AddDynamicLightToScene( org, intensity, r, g, b, qtrue );
274 }
275 
276 /*
277 @@@@@@@@@@@@@@@@@@@@@
278 RE_RenderScene
279 
280 Draw a 3D view into a part of the window, then return
281 to 2D drawing.
282 
283 Rendering a scene may require multiple views to be rendered
284 to handle mirrors,
285 @@@@@@@@@@@@@@@@@@@@@
286 */
RE_RenderScene(const refdef_t * fd)287 void RE_RenderScene( const refdef_t *fd ) {
288 	viewParms_t		parms;
289 	int				startTime;
290 
291 	if ( !tr.registered ) {
292 		return;
293 	}
294 	GLimp_LogComment( "====== RE_RenderScene =====\n" );
295 
296 	if ( r_norefresh->integer ) {
297 		return;
298 	}
299 
300 	startTime = ri.Milliseconds();
301 
302 	if (!tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) {
303 		ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
304 	}
305 
306 	Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
307 
308 	tr.refdef.x = fd->x;
309 	tr.refdef.y = fd->y;
310 	tr.refdef.width = fd->width;
311 	tr.refdef.height = fd->height;
312 	tr.refdef.fov_x = fd->fov_x;
313 	tr.refdef.fov_y = fd->fov_y;
314 
315 	VectorCopy( fd->vieworg, tr.refdef.vieworg );
316 	VectorCopy( fd->viewaxis[0], tr.refdef.viewaxis[0] );
317 	VectorCopy( fd->viewaxis[1], tr.refdef.viewaxis[1] );
318 	VectorCopy( fd->viewaxis[2], tr.refdef.viewaxis[2] );
319 
320 	tr.refdef.time = fd->time;
321 	tr.refdef.rdflags = fd->rdflags;
322 
323 	// copy the areamask data over and note if it has changed, which
324 	// will force a reset of the visible leafs even if the view hasn't moved
325 	tr.refdef.areamaskModified = qfalse;
326 	if ( ! (tr.refdef.rdflags & RDF_NOWORLDMODEL) ) {
327 		int		areaDiff;
328 		int		i;
329 
330 		// compare the area bits
331 		areaDiff = 0;
332 		for (i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++) {
333 			areaDiff |= ((int *)tr.refdef.areamask)[i] ^ ((int *)fd->areamask)[i];
334 			((int *)tr.refdef.areamask)[i] = ((int *)fd->areamask)[i];
335 		}
336 
337 		if ( areaDiff ) {
338 			// a door just opened or something
339 			tr.refdef.areamaskModified = qtrue;
340 		}
341 	}
342 
343 
344 	// derived info
345 
346 	tr.refdef.floatTime = tr.refdef.time * 0.001f;
347 
348 	tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
349 	tr.refdef.drawSurfs = backEndData[tr.smpFrame]->drawSurfs;
350 
351 	tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
352 	tr.refdef.entities = &backEndData[tr.smpFrame]->entities[r_firstSceneEntity];
353 
354 	tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
355 	tr.refdef.dlights = &backEndData[tr.smpFrame]->dlights[r_firstSceneDlight];
356 
357 	tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
358 	tr.refdef.polys = &backEndData[tr.smpFrame]->polys[r_firstScenePoly];
359 
360 	// turn off dynamic lighting globally by clearing all the
361 	// dlights if it needs to be disabled or if vertex lighting is enabled
362 	if ( r_dynamiclight->integer == 0 ||
363 		 r_vertexLight->integer == 1 ||
364 		 glConfig.hardwareType == GLHW_PERMEDIA2 ) {
365 		tr.refdef.num_dlights = 0;
366 	}
367 
368 	// a single frame may have multiple scenes draw inside it --
369 	// a 3D game view, 3D status bar renderings, 3D menus, etc.
370 	// They need to be distinguished by the light flare code, because
371 	// the visibility state for a given surface may be different in
372 	// each scene / view.
373 	tr.frameSceneNum++;
374 	tr.sceneCount++;
375 
376 	// setup view parms for the initial view
377 	//
378 	// set up viewport
379 	// The refdef takes 0-at-the-top y coordinates, so
380 	// convert to GL's 0-at-the-bottom space
381 	//
382 	Com_Memset( &parms, 0, sizeof( parms ) );
383 	parms.viewportX = tr.refdef.x;
384 	parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height );
385 	parms.viewportWidth = tr.refdef.width;
386 	parms.viewportHeight = tr.refdef.height;
387 	parms.isPortal = qfalse;
388 
389 	parms.fovX = tr.refdef.fov_x;
390 	parms.fovY = tr.refdef.fov_y;
391 
392 	parms.stereoFrame = tr.refdef.stereoFrame;
393 
394 	VectorCopy( fd->vieworg, parms.or.origin );
395 	VectorCopy( fd->viewaxis[0], parms.or.axis[0] );
396 	VectorCopy( fd->viewaxis[1], parms.or.axis[1] );
397 	VectorCopy( fd->viewaxis[2], parms.or.axis[2] );
398 
399 	VectorCopy( fd->vieworg, parms.pvsOrigin );
400 
401 	R_RenderView( &parms );
402 
403 	// the next scene rendered in this frame will tack on after this one
404 	r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
405 	r_firstSceneEntity = r_numentities;
406 	r_firstSceneDlight = r_numdlights;
407 	r_firstScenePoly = r_numpolys;
408 
409 	tr.frontEndMsec += ri.Milliseconds() - startTime;
410 }
411