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 }