Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

tr_scene.c (10706B)


      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 Foobar; 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 */
     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 */
     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 */
     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 */
    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 */
    207 void RE_AddRefEntityToScene( const refEntity_t *ent ) {
    208 	if ( !tr.registered ) {
    209 		return;
    210 	}
    211   // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=402
    212 	if ( r_numentities >= ENTITYNUM_WORLD ) {
    213 		return;
    214 	}
    215 	if ( ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) {
    216 		ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
    217 	}
    218 
    219 	backEndData[tr.smpFrame]->entities[r_numentities].e = *ent;
    220 	backEndData[tr.smpFrame]->entities[r_numentities].lightingCalculated = qfalse;
    221 
    222 	r_numentities++;
    223 }
    224 
    225 
    226 /*
    227 =====================
    228 RE_AddDynamicLightToScene
    229 
    230 =====================
    231 */
    232 void RE_AddDynamicLightToScene( const vec3_t org, float intensity, float r, float g, float b, int additive ) {
    233 	dlight_t	*dl;
    234 
    235 	if ( !tr.registered ) {
    236 		return;
    237 	}
    238 	if ( r_numdlights >= MAX_DLIGHTS ) {
    239 		return;
    240 	}
    241 	if ( intensity <= 0 ) {
    242 		return;
    243 	}
    244 	// these cards don't have the correct blend mode
    245 	if ( glConfig.hardwareType == GLHW_RIVA128 || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
    246 		return;
    247 	}
    248 	dl = &backEndData[tr.smpFrame]->dlights[r_numdlights++];
    249 	VectorCopy (org, dl->origin);
    250 	dl->radius = intensity;
    251 	dl->color[0] = r;
    252 	dl->color[1] = g;
    253 	dl->color[2] = b;
    254 	dl->additive = additive;
    255 }
    256 
    257 /*
    258 =====================
    259 RE_AddLightToScene
    260 
    261 =====================
    262 */
    263 void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
    264 	RE_AddDynamicLightToScene( org, intensity, r, g, b, qfalse );
    265 }
    266 
    267 /*
    268 =====================
    269 RE_AddAdditiveLightToScene
    270 
    271 =====================
    272 */
    273 void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
    274 	RE_AddDynamicLightToScene( org, intensity, r, g, b, qtrue );
    275 }
    276 
    277 /*
    278 @@@@@@@@@@@@@@@@@@@@@
    279 RE_RenderScene
    280 
    281 Draw a 3D view into a part of the window, then return
    282 to 2D drawing.
    283 
    284 Rendering a scene may require multiple views to be rendered
    285 to handle mirrors,
    286 @@@@@@@@@@@@@@@@@@@@@
    287 */
    288 void RE_RenderScene( const refdef_t *fd ) {
    289 	viewParms_t		parms;
    290 	int				startTime;
    291 
    292 	if ( !tr.registered ) {
    293 		return;
    294 	}
    295 	GLimp_LogComment( "====== RE_RenderScene =====\n" );
    296 
    297 	if ( r_norefresh->integer ) {
    298 		return;
    299 	}
    300 
    301 	startTime = ri.Milliseconds();
    302 
    303 	if (!tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) {
    304 		ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
    305 	}
    306 
    307 	Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
    308 
    309 	tr.refdef.x = fd->x;
    310 	tr.refdef.y = fd->y;
    311 	tr.refdef.width = fd->width;
    312 	tr.refdef.height = fd->height;
    313 	tr.refdef.fov_x = fd->fov_x;
    314 	tr.refdef.fov_y = fd->fov_y;
    315 
    316 	VectorCopy( fd->vieworg, tr.refdef.vieworg );
    317 	VectorCopy( fd->viewaxis[0], tr.refdef.viewaxis[0] );
    318 	VectorCopy( fd->viewaxis[1], tr.refdef.viewaxis[1] );
    319 	VectorCopy( fd->viewaxis[2], tr.refdef.viewaxis[2] );
    320 
    321 	tr.refdef.time = fd->time;
    322 	tr.refdef.rdflags = fd->rdflags;
    323 
    324 	// copy the areamask data over and note if it has changed, which
    325 	// will force a reset of the visible leafs even if the view hasn't moved
    326 	tr.refdef.areamaskModified = qfalse;
    327 	if ( ! (tr.refdef.rdflags & RDF_NOWORLDMODEL) ) {
    328 		int		areaDiff;
    329 		int		i;
    330 
    331 		// compare the area bits
    332 		areaDiff = 0;
    333 		for (i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++) {
    334 			areaDiff |= ((int *)tr.refdef.areamask)[i] ^ ((int *)fd->areamask)[i];
    335 			((int *)tr.refdef.areamask)[i] = ((int *)fd->areamask)[i];
    336 		}
    337 
    338 		if ( areaDiff ) {
    339 			// a door just opened or something
    340 			tr.refdef.areamaskModified = qtrue;
    341 		}
    342 	}
    343 
    344 
    345 	// derived info
    346 
    347 	tr.refdef.floatTime = tr.refdef.time * 0.001f;
    348 
    349 	tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
    350 	tr.refdef.drawSurfs = backEndData[tr.smpFrame]->drawSurfs;
    351 
    352 	tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
    353 	tr.refdef.entities = &backEndData[tr.smpFrame]->entities[r_firstSceneEntity];
    354 
    355 	tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
    356 	tr.refdef.dlights = &backEndData[tr.smpFrame]->dlights[r_firstSceneDlight];
    357 
    358 	tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
    359 	tr.refdef.polys = &backEndData[tr.smpFrame]->polys[r_firstScenePoly];
    360 
    361 	// turn off dynamic lighting globally by clearing all the
    362 	// dlights if it needs to be disabled or if vertex lighting is enabled
    363 	if ( r_dynamiclight->integer == 0 ||
    364 		 r_vertexLight->integer == 1 ||
    365 		 glConfig.hardwareType == GLHW_PERMEDIA2 ) {
    366 		tr.refdef.num_dlights = 0;
    367 	}
    368 
    369 	// a single frame may have multiple scenes draw inside it --
    370 	// a 3D game view, 3D status bar renderings, 3D menus, etc.
    371 	// They need to be distinguished by the light flare code, because
    372 	// the visibility state for a given surface may be different in
    373 	// each scene / view.
    374 	tr.frameSceneNum++;
    375 	tr.sceneCount++;
    376 
    377 	// setup view parms for the initial view
    378 	//
    379 	// set up viewport
    380 	// The refdef takes 0-at-the-top y coordinates, so
    381 	// convert to GL's 0-at-the-bottom space
    382 	//
    383 	Com_Memset( &parms, 0, sizeof( parms ) );
    384 	parms.viewportX = tr.refdef.x;
    385 	parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height );
    386 	parms.viewportWidth = tr.refdef.width;
    387 	parms.viewportHeight = tr.refdef.height;
    388 	parms.isPortal = qfalse;
    389 
    390 	parms.fovX = tr.refdef.fov_x;
    391 	parms.fovY = tr.refdef.fov_y;
    392 
    393 	VectorCopy( fd->vieworg, parms.or.origin );
    394 	VectorCopy( fd->viewaxis[0], parms.or.axis[0] );
    395 	VectorCopy( fd->viewaxis[1], parms.or.axis[1] );
    396 	VectorCopy( fd->viewaxis[2], parms.or.axis[2] );
    397 
    398 	VectorCopy( fd->vieworg, parms.pvsOrigin );
    399 
    400 	R_RenderView( &parms );
    401 
    402 	// the next scene rendered in this frame will tack on after this one
    403 	r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
    404 	r_firstSceneEntity = r_numentities;
    405 	r_firstSceneDlight = r_numdlights;
    406 	r_firstScenePoly = r_numpolys;
    407 
    408 	tr.frontEndMsec += ri.Milliseconds() - startTime;
    409 }