doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
tr_lightrun.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
9 Doom 3 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 Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 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 Doom 3 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 #include "../idlib/precompiled.h"
30 #pragma hdrstop
31 
32 #include "tr_local.h"
33 
34 /*
35 
36 
37 Prelight models
38 
39 "_prelight_<lightname>", ie "_prelight_light1"
40 
41 Static surfaces available to dmap will be processed to optimized
42 shadow and lit surface geometry
43 
44 Entity models are never prelighted.
45 
46 Light entity can have a "noPrelight 1" key set to avoid the preprocessing
47 and carving of the world. A light that will move should usually have this
48 set.
49 
50 Prelight models will usually have multiple surfaces
51 
52 Shadow volume surfaces will have the material "_shadowVolume"
53 
54 The exact same vertexes as the ambient surfaces will be used for the
55 non-shadow surfaces, so there is opportunity to share
56 
57 
58 Reference their parent surfaces?
59 Reference their parent area?
60 
61 
62 If we don't track parts that are in different areas, there will be huge
63 losses when an areaportal closed door has a light poking slightly
64 through it.
65 
66 There is potential benefit to splitting even the shadow volumes
67 at area boundaries, but it would involve the possibility of an
68 extra plane of shadow drawing at the area boundary.
69 
70 
71 interaction lightName numIndexes
72 
73 Shadow volume surface
74 
75 Surfaces in the world cannot have "no self shadow" properties, because all
76 the surfaces are considered together for the optimized shadow volume. If
77 you want no self shadow on a static surface, you must still make it into an
78 entity so it isn't considered in the prelight.
79 
80 
81 r_hidePrelights
82 r_hideNonPrelights
83 
84 
85 
86 each surface could include prelight indexes
87 
88 generation procedure in dmap:
89 
90 carve original surfaces into areas
91 
92 for each light
93  build shadow volume and beam tree
94  cut all potentially lit surfaces into the beam tree
95  move lit fragments into a new optimize group
96 
97 optimize groups
98 
99 build light models
100 
101 
102 
103 
104 */
105 
106 /*
107 =================================================================================
108 
109 LIGHT TESTING
110 
111 =================================================================================
112 */
113 
114 
115 /*
116 ====================
117 R_ModulateLights_f
118 
119 Modifies the shaderParms on all the lights so the level
120 designers can easily test different color schemes
121 ====================
122 */
123 void R_ModulateLights_f( const idCmdArgs &args ) {
124  if ( !tr.primaryWorld ) {
125  return;
126  }
127  if ( args.Argc() != 4 ) {
128  common->Printf( "usage: modulateLights <redFloat> <greenFloat> <blueFloat>\n" );
129  return;
130  }
131 
132  float modulate[3];
133  int i;
134  for ( i = 0 ; i < 3 ; i++ ) {
135  modulate[i] = atof( args.Argv( i+1 ) );
136  }
137 
138  int count = 0;
139  for ( i = 0 ; i < tr.primaryWorld->lightDefs.Num() ; i++ ) {
140  idRenderLightLocal *light;
141 
142  light = tr.primaryWorld->lightDefs[i];
143  if ( light ) {
144  count++;
145  for ( int j = 0 ; j < 3 ; j++ ) {
146  light->parms.shaderParms[j] *= modulate[j];
147  }
148  }
149  }
150  common->Printf( "modulated %i lights\n", count );
151 }
152 
153 
154 
155 //======================================================================================
156 
157 
158 /*
159 ===============
160 R_CreateEntityRefs
161 
162 Creates all needed model references in portal areas,
163 chaining them to both the area and the entityDef.
164 
165 Bumps tr.viewCount.
166 ===============
167 */
169  int i;
170  idVec3 transformed[8];
171  idVec3 v;
172 
173  if ( !def->parms.hModel ) {
175  }
176 
177  // if the entity hasn't been fully specified due to expensive animation calcs
178  // for md5 and particles, use the provided conservative bounds.
179  if ( def->parms.callback ) {
180  def->referenceBounds = def->parms.bounds;
181  } else {
182  def->referenceBounds = def->parms.hModel->Bounds( &def->parms );
183  }
184 
185  // some models, like empty particles, may not need to be added at all
186  if ( def->referenceBounds.IsCleared() ) {
187  return;
188  }
189 
190  if ( r_showUpdates.GetBool() &&
191  ( def->referenceBounds[1][0] - def->referenceBounds[0][0] > 1024 ||
192  def->referenceBounds[1][1] - def->referenceBounds[0][1] > 1024 ) ) {
193  common->Printf( "big entityRef: %f,%f\n", def->referenceBounds[1][0] - def->referenceBounds[0][0],
194  def->referenceBounds[1][1] - def->referenceBounds[0][1] );
195  }
196 
197  for (i = 0 ; i < 8 ; i++) {
198  v[0] = def->referenceBounds[i&1][0];
199  v[1] = def->referenceBounds[(i>>1)&1][1];
200  v[2] = def->referenceBounds[(i>>2)&1][2];
201 
202  R_LocalPointToGlobal( def->modelMatrix, v, transformed[i] );
203  }
204 
205  // bump the view count so we can tell if an
206  // area already has a reference
207  tr.viewCount++;
208 
209  // push these points down the BSP tree into areas
210  def->world->PushVolumeIntoTree( def, NULL, 8, transformed );
211 }
212 
213 
214 /*
215 =================================================================================
216 
217 CREATE LIGHT REFS
218 
219 =================================================================================
220 */
221 
222 /*
223 =====================
224 R_SetLightProject
225 
226 All values are reletive to the origin
227 Assumes that right and up are not normalized
228 This is also called by dmap during map processing.
229 =====================
230 */
231 void R_SetLightProject( idPlane lightProject[4], const idVec3 origin, const idVec3 target,
232  const idVec3 rightVector, const idVec3 upVector, const idVec3 start, const idVec3 stop ) {
233  float dist;
234  float scale;
235  float rLen, uLen;
236  idVec3 normal;
237  float ofs;
238  idVec3 right, up;
239  idVec3 startGlobal;
240  idVec4 targetGlobal;
241 
242  right = rightVector;
243  rLen = right.Normalize();
244  up = upVector;
245  uLen = up.Normalize();
246  normal = up.Cross( right );
247 //normal = right.Cross( up );
248  normal.Normalize();
249 
250  dist = target * normal; // - ( origin * normal );
251  if ( dist < 0 ) {
252  dist = -dist;
253  normal = -normal;
254  }
255 
256  scale = ( 0.5f * dist ) / rLen;
257  right *= scale;
258  scale = -( 0.5f * dist ) / uLen;
259  up *= scale;
260 
261  lightProject[2] = normal;
262  lightProject[2][3] = -( origin * lightProject[2].Normal() );
263 
264  lightProject[0] = right;
265  lightProject[0][3] = -( origin * lightProject[0].Normal() );
266 
267  lightProject[1] = up;
268  lightProject[1][3] = -( origin * lightProject[1].Normal() );
269 
270  // now offset to center
271  targetGlobal.ToVec3() = target + origin;
272  targetGlobal[3] = 1;
273  ofs = 0.5f - ( targetGlobal * lightProject[0].ToVec4() ) / ( targetGlobal * lightProject[2].ToVec4() );
274  lightProject[0].ToVec4() += ofs * lightProject[2].ToVec4();
275  ofs = 0.5f - ( targetGlobal * lightProject[1].ToVec4() ) / ( targetGlobal * lightProject[2].ToVec4() );
276  lightProject[1].ToVec4() += ofs * lightProject[2].ToVec4();
277 
278  // set the falloff vector
279  normal = stop - start;
280  dist = normal.Normalize();
281  if ( dist <= 0 ) {
282  dist = 1;
283  }
284  lightProject[3] = normal * ( 1.0f / dist );
285  startGlobal = start + origin;
286  lightProject[3][3] = -( startGlobal * lightProject[3].Normal() );
287 }
288 
289 /*
290 ===================
291 R_SetLightFrustum
292 
293 Creates plane equations from the light projection, positive sides
294 face out of the light
295 ===================
296 */
297 void R_SetLightFrustum( const idPlane lightProject[4], idPlane frustum[6] ) {
298  int i;
299 
300  // we want the planes of s=0, s=q, t=0, and t=q
301  frustum[0] = lightProject[0];
302  frustum[1] = lightProject[1];
303  frustum[2] = lightProject[2] - lightProject[0];
304  frustum[3] = lightProject[2] - lightProject[1];
305 
306  // we want the planes of s=0 and s=1 for front and rear clipping planes
307  frustum[4] = lightProject[3];
308 
309  frustum[5] = lightProject[3];
310  frustum[5][3] -= 1.0f;
311  frustum[5] = -frustum[5];
312 
313  for ( i = 0 ; i < 6 ; i++ ) {
314  float l;
315 
316  frustum[i] = -frustum[i];
317  l = frustum[i].Normalize();
318  frustum[i][3] /= l;
319  }
320 }
321 
322 /*
323 ====================
324 R_FreeLightDefFrustum
325 ====================
326 */
328  int i;
329 
330  // free the frustum tris
331  if ( ldef->frustumTris ) {
333  ldef->frustumTris = NULL;
334  }
335  // free frustum windings
336  for ( i = 0; i < 6; i++ ) {
337  if ( ldef->frustumWindings[i] ) {
338  delete ldef->frustumWindings[i];
339  ldef->frustumWindings[i] = NULL;
340  }
341  }
342 }
343 
344 /*
345 =================
346 R_DeriveLightData
347 
348 Fills everything in based on light->parms
349 =================
350 */
352  int i;
353 
354  // decide which light shader we are going to use
355  if ( light->parms.shader ) {
356  light->lightShader = light->parms.shader;
357  }
358  if ( !light->lightShader ) {
359  if ( light->parms.pointLight ) {
360  light->lightShader = declManager->FindMaterial( "lights/defaultPointLight" );
361  } else {
362  light->lightShader = declManager->FindMaterial( "lights/defaultProjectedLight" );
363  }
364  }
365 
366  // get the falloff image
367  light->falloffImage = light->lightShader->LightFalloffImage();
368  if ( !light->falloffImage ) {
369  // use the falloff from the default shader of the correct type
370  const idMaterial *defaultShader;
371 
372  if ( light->parms.pointLight ) {
373  defaultShader = declManager->FindMaterial( "lights/defaultPointLight" );
374  light->falloffImage = defaultShader->LightFalloffImage();
375  } else {
376  // projected lights by default don't diminish with distance
377  defaultShader = declManager->FindMaterial( "lights/defaultProjectedLight" );
378  light->falloffImage = defaultShader->LightFalloffImage();
379  }
380  }
381 
382  // set the projection
383  if ( !light->parms.pointLight ) {
384  // projected light
385 
386  R_SetLightProject( light->lightProject, vec3_origin /* light->parms.origin */, light->parms.target,
387  light->parms.right, light->parms.up, light->parms.start, light->parms.end);
388  } else {
389  // point light
390  memset( light->lightProject, 0, sizeof( light->lightProject ) );
391  light->lightProject[0][0] = 0.5f / light->parms.lightRadius[0];
392  light->lightProject[1][1] = 0.5f / light->parms.lightRadius[1];
393  light->lightProject[3][2] = 0.5f / light->parms.lightRadius[2];
394  light->lightProject[0][3] = 0.5f;
395  light->lightProject[1][3] = 0.5f;
396  light->lightProject[2][3] = 1.0f;
397  light->lightProject[3][3] = 0.5f;
398  }
399 
400  // set the frustum planes
401  R_SetLightFrustum( light->lightProject, light->frustum );
402 
403  // rotate the light planes and projections by the axis
404  R_AxisToModelMatrix( light->parms.axis, light->parms.origin, light->modelMatrix );
405 
406  for ( i = 0 ; i < 6 ; i++ ) {
407  idPlane temp;
408  temp = light->frustum[i];
409  R_LocalPlaneToGlobal( light->modelMatrix, temp, light->frustum[i] );
410  }
411  for ( i = 0 ; i < 4 ; i++ ) {
412  idPlane temp;
413  temp = light->lightProject[i];
414  R_LocalPlaneToGlobal( light->modelMatrix, temp, light->lightProject[i] );
415  }
416 
417  // adjust global light origin for off center projections and parallel projections
418  // we are just faking parallel by making it a very far off center for now
419  if ( light->parms.parallel ) {
420  idVec3 dir;
421 
422  dir = light->parms.lightCenter;
423  if ( !dir.Normalize() ) {
424  // make point straight up if not specified
425  dir[2] = 1;
426  }
427  light->globalLightOrigin = light->parms.origin + dir * 100000;
428  } else {
429  light->globalLightOrigin = light->parms.origin + light->parms.axis * light->parms.lightCenter;
430  }
431 
432  R_FreeLightDefFrustum( light );
433 
434  light->frustumTris = R_PolytopeSurface( 6, light->frustum, light->frustumWindings );
435 
436  // a projected light will have one shadowFrustum, a point light will have
437  // six unless the light center is outside the box
438  R_MakeShadowFrustums( light );
439 }
440 
441 /*
442 =================
443 R_CreateLightRefs
444 =================
445 */
446 #define MAX_LIGHT_VERTS 40
449  int i;
450  srfTriangles_t *tri;
451 
452  tri = light->frustumTris;
453 
454  // because a light frustum is made of only six intersecting planes,
455  // we should never be able to get a stupid number of points...
456  if ( tri->numVerts > MAX_LIGHT_VERTS ) {
457  common->Error( "R_CreateLightRefs: %i points in frustumTris!", tri->numVerts );
458  }
459  for ( i = 0 ; i < tri->numVerts ; i++ ) {
460  points[i] = tri->verts[i].xyz;
461  }
462 
463  if ( r_showUpdates.GetBool() && ( tri->bounds[1][0] - tri->bounds[0][0] > 1024 ||
464  tri->bounds[1][1] - tri->bounds[0][1] > 1024 ) ) {
465  common->Printf( "big lightRef: %f,%f\n", tri->bounds[1][0] - tri->bounds[0][0]
466  ,tri->bounds[1][1] - tri->bounds[0][1] );
467  }
468 
469  // determine the areaNum for the light origin, which may let us
470  // cull the light if it is behind a closed door
471  // it is debatable if we want to use the entity origin or the center offset origin,
472  // but we definitely don't want to use a parallel offset origin
473  light->areaNum = light->world->PointInArea( light->globalLightOrigin );
474  if ( light->areaNum == -1 ) {
475  light->areaNum = light->world->PointInArea( light->parms.origin );
476  }
477 
478  // bump the view count so we can tell if an
479  // area already has a reference
480  tr.viewCount++;
481 
482  // if we have a prelight model that includes all the shadows for the major world occluders,
483  // we can limit the area references to those visible through the portals from the light center.
484  // We can't do this in the normal case, because shadows are cast from back facing triangles, which
485  // may be in areas not directly visible to the light projection center.
487  light->world->FlowLightThroughPortals( light );
488  } else {
489  // push these points down the BSP tree into areas
490  light->world->PushVolumeIntoTree( NULL, light, tri->numVerts, points );
491  }
492 }
493 
494 /*
495 ===============
496 R_RenderLightFrustum
497 
498 Called by the editor and dmap to operate on light volumes
499 ===============
500 */
501 void R_RenderLightFrustum( const renderLight_t &renderLight, idPlane lightFrustum[6] ) {
502  idRenderLightLocal fakeLight;
503 
504  memset( &fakeLight, 0, sizeof( fakeLight ) );
505  fakeLight.parms = renderLight;
506 
507  R_DeriveLightData( &fakeLight );
508 
509  R_FreeStaticTriSurf( fakeLight.frustumTris );
510 
511  for ( int i = 0 ; i < 6 ; i++ ) {
512  lightFrustum[i] = fakeLight.frustum[i];
513  }
514 }
515 
516 
517 //=================================================================================
518 
519 /*
520 ===============
521 WindingCompletelyInsideLight
522 ===============
523 */
525  int i, j;
526 
527  for ( i = 0 ; i < w->GetNumPoints() ; i++ ) {
528  for ( j = 0 ; j < 6 ; j++ ) {
529  float d;
530 
531  d = (*w)[i].ToVec3() * ldef->frustum[j].Normal() + ldef->frustum[j][3];
532  if ( d > 0 ) {
533  return false;
534  }
535  }
536  }
537  return true;
538 }
539 
540 /*
541 ======================
542 R_CreateLightDefFogPortals
543 
544 When a fog light is created or moved, see if it completely
545 encloses any portals, which may allow them to be fogged closed.
546 ======================
547 */
549  areaReference_t *lref;
550  portalArea_t *area;
551 
552  ldef->foggedPortals = NULL;
553 
554  if ( !ldef->lightShader->IsFogLight() ) {
555  return;
556  }
557 
558  // some fog lights will explicitly disallow portal fogging
559  if ( ldef->lightShader->TestMaterialFlag( MF_NOPORTALFOG ) ) {
560  return;
561  }
562 
563  for ( lref = ldef->references ; lref ; lref = lref->ownerNext ) {
564  // check all the models in this area
565  area = lref->area;
566 
567  portal_t *prt;
569 
570  for ( prt = area->portals ; prt ; prt = prt->next ) {
571  dp = prt->doublePortal;
572 
573  // we only handle a single fog volume covering a portal
574  // this will never cause incorrect drawing, but it may
575  // fail to cull a portal
576  if ( dp->fogLight ) {
577  continue;
578  }
579 
580  if ( WindingCompletelyInsideLight( prt->w, ldef ) ) {
581  dp->fogLight = ldef;
582  dp->nextFoggedPortal = ldef->foggedPortals;
583  ldef->foggedPortals = dp;
584  }
585  }
586  }
587 }
588 
589 /*
590 ====================
591 R_FreeLightDefDerivedData
592 
593 Frees all references and lit surfaces from the light
594 ====================
595 */
597  areaReference_t *lref, *nextRef;
598 
599  // rmove any portal fog references
600  for ( doublePortal_t *dp = ldef->foggedPortals ; dp ; dp = dp->nextFoggedPortal ) {
601  dp->fogLight = NULL;
602  }
603 
604  // free all the interactions
605  while ( ldef->firstInteraction != NULL ) {
607  }
608 
609  // free all the references to the light
610  for ( lref = ldef->references ; lref ; lref = nextRef ) {
611  nextRef = lref->ownerNext;
612 
613  // unlink from the area
614  lref->areaNext->areaPrev = lref->areaPrev;
615  lref->areaPrev->areaNext = lref->areaNext;
616 
617  // put it back on the free list for reuse
618  ldef->world->areaReferenceAllocator.Free( lref );
619  }
620  ldef->references = NULL;
621 
622  R_FreeLightDefFrustum( ldef );
623 }
624 
625 /*
626 ===================
627 R_FreeEntityDefDerivedData
628 
629 Used by both RE_FreeEntityDef and RE_UpdateEntityDef
630 Does not actually free the entityDef.
631 ===================
632 */
633 void R_FreeEntityDefDerivedData( idRenderEntityLocal *def, bool keepDecals, bool keepCachedDynamicModel ) {
634  int i;
635  areaReference_t *ref, *next;
636 
637  // demo playback needs to free the joints, while normal play
638  // leaves them in the control of the game
639  if ( session->readDemo ) {
640  if ( def->parms.joints ) {
641  Mem_Free16( def->parms.joints );
642  def->parms.joints = NULL;
643  }
644  if ( def->parms.callbackData ) {
645  Mem_Free( def->parms.callbackData );
646  def->parms.callbackData = NULL;
647  }
648  for ( i = 0; i < MAX_RENDERENTITY_GUI; i++ ) {
649  if ( def->parms.gui[ i ] ) {
650  delete def->parms.gui[ i ];
651  def->parms.gui[ i ] = NULL;
652  }
653  }
654  }
655 
656  // free all the interactions
657  while ( def->firstInteraction != NULL ) {
659  }
660 
661  // clear the dynamic model if present
662  if ( def->dynamicModel ) {
663  def->dynamicModel = NULL;
664  }
665 
666  if ( !keepDecals ) {
667  R_FreeEntityDefDecals( def );
668  R_FreeEntityDefOverlay( def );
669  }
670 
671  if ( !keepCachedDynamicModel ) {
672  delete def->cachedDynamicModel;
673  def->cachedDynamicModel = NULL;
674  }
675 
676  // free the entityRefs from the areas
677  for ( ref = def->entityRefs ; ref ; ref = next ) {
678  next = ref->ownerNext;
679 
680  // unlink from the area
681  ref->areaNext->areaPrev = ref->areaPrev;
682  ref->areaPrev->areaNext = ref->areaNext;
683 
684  // put it back on the free list for reuse
685  def->world->areaReferenceAllocator.Free( ref );
686  }
687  def->entityRefs = NULL;
688 }
689 
690 /*
691 ==================
692 R_ClearEntityDefDynamicModel
693 
694 If we know the reference bounds stays the same, we
695 only need to do this on entity update, not the full
696 R_FreeEntityDefDerivedData
697 ==================
698 */
700  // free all the interaction surfaces
701  for( idInteraction *inter = def->firstInteraction; inter != NULL && !inter->IsEmpty(); inter = inter->entityNext ) {
702  inter->FreeSurfaces();
703  }
704 
705  // clear the dynamic model if present
706  if ( def->dynamicModel ) {
707  def->dynamicModel = NULL;
708  }
709 }
710 
711 /*
712 ===================
713 R_FreeEntityDefDecals
714 ===================
715 */
717  while( def->decals ) {
718  idRenderModelDecal *next = def->decals->Next();
720  def->decals = next;
721  }
722 }
723 
724 /*
725 ===================
726 R_FreeEntityDefFadedDecals
727 ===================
728 */
731 }
732 
733 /*
734 ===================
735 R_FreeEntityDefOverlay
736 ===================
737 */
739  if ( def->overlay ) {
741  def->overlay = NULL;
742  }
743 }
744 
745 /*
746 ===================
747 R_FreeDerivedData
748 
749 ReloadModels and RegenerateWorld call this
750 // FIXME: need to do this for all worlds
751 ===================
752 */
753 void R_FreeDerivedData( void ) {
754  int i, j;
755  idRenderWorldLocal *rw;
756  idRenderEntityLocal *def;
757  idRenderLightLocal *light;
758 
759  for ( j = 0; j < tr.worlds.Num(); j++ ) {
760  rw = tr.worlds[j];
761 
762  for ( i = 0; i < rw->entityDefs.Num(); i++ ) {
763  def = rw->entityDefs[i];
764  if ( !def ) {
765  continue;
766  }
767  R_FreeEntityDefDerivedData( def, false, false );
768  }
769 
770  for ( i = 0; i < rw->lightDefs.Num(); i++ ) {
771  light = rw->lightDefs[i];
772  if ( !light ) {
773  continue;
774  }
775  R_FreeLightDefDerivedData( light );
776  }
777  }
778 }
779 
780 /*
781 ===================
782 R_CheckForEntityDefsUsingModel
783 ===================
784 */
786  int i, j;
787  idRenderWorldLocal *rw;
788  idRenderEntityLocal *def;
789 
790  for ( j = 0; j < tr.worlds.Num(); j++ ) {
791  rw = tr.worlds[j];
792 
793  for ( i = 0 ; i < rw->entityDefs.Num(); i++ ) {
794  def = rw->entityDefs[i];
795  if ( !def ) {
796  continue;
797  }
798  if ( def->parms.hModel == model ) {
799  //assert( 0 );
800  // this should never happen but Radiant messes it up all the time so just free the derived data
801  R_FreeEntityDefDerivedData( def, false, false );
802  }
803  }
804  }
805 }
806 
807 /*
808 ===================
809 R_ReCreateWorldReferences
810 
811 ReloadModels and RegenerateWorld call this
812 // FIXME: need to do this for all worlds
813 ===================
814 */
816  int i, j;
817  idRenderWorldLocal *rw;
818  idRenderEntityLocal *def;
819  idRenderLightLocal *light;
820 
821  // let the interaction generation code know this shouldn't be optimized for
822  // a particular view
823  tr.viewDef = NULL;
824 
825  for ( j = 0; j < tr.worlds.Num(); j++ ) {
826  rw = tr.worlds[j];
827 
828  for ( i = 0 ; i < rw->entityDefs.Num() ; i++ ) {
829  def = rw->entityDefs[i];
830  if ( !def ) {
831  continue;
832  }
833  // the world model entities are put specifically in a single
834  // area, instead of just pushing their bounds into the tree
835  if ( i < rw->numPortalAreas ) {
836  rw->AddEntityRefToArea( def, &rw->portalAreas[i] );
837  } else {
838  R_CreateEntityRefs( def );
839  }
840  }
841 
842  for ( i = 0 ; i < rw->lightDefs.Num() ; i++ ) {
843  light = rw->lightDefs[i];
844  if ( !light ) {
845  continue;
846  }
847  renderLight_t parms = light->parms;
848 
849  light->world->FreeLightDef( i );
850  rw->UpdateLightDef( i, &parms );
851  }
852  }
853 }
854 
855 /*
856 ===================
857 R_RegenerateWorld_f
858 
859 Frees and regenerates all references and interactions, which
860 must be done when switching between display list mode and immediate mode
861 ===================
862 */
863 void R_RegenerateWorld_f( const idCmdArgs &args ) {
865 
866  // watch how much memory we allocate
867  tr.staticAllocCount = 0;
868 
870 
871  common->Printf( "Regenerated world, staticAllocCount = %i.\n", tr.staticAllocCount );
872 }
idRenderWorldLocal * world
Definition: tr_local.h:255
const idMaterial * lightShader
Definition: tr_local.h:213
void AddEntityRefToArea(idRenderEntityLocal *def, portalArea_t *area)
idRenderModel * dynamicModel
Definition: tr_local.h:263
GLsizei const GLfloat * points
Definition: glext.h:3884
void UnlinkAndFree(void)
virtual idRenderModel * DefaultModel()=0
void R_RenderLightFrustum(const renderLight_t &renderLight, idPlane lightFrustum[6])
float Normalize(void)
Definition: Vector.h:646
void R_SetLightFrustum(const idPlane lightProject[4], idPlane frustum[6])
struct doublePortal_s * foggedPortals
Definition: tr_local.h:233
void R_SetLightProject(idPlane lightProject[4], const idVec3 origin, const idVec3 target, const idVec3 rightVector, const idVec3 upVector, const idVec3 start, const idVec3 stop)
idDemoFile * readDemo
Definition: Session.h:158
idVec3 lightCenter
Definition: RenderWorld.h:179
const idVec3 & Normal(void) const
Definition: Plane.h:239
idPlane frustum[6]
Definition: tr_local.h:219
int numVerts
Definition: Model.h:98
void R_FreeEntityDefOverlay(idRenderEntityLocal *def)
void R_CreateLightRefs(idRenderLightLocal *light)
const GLdouble * v
Definition: glext.h:2936
idRenderLightLocal * fogLight
virtual void UpdateLightDef(qhandle_t lightHandle, const renderLight_t *rlight)
#define MAX_LIGHT_VERTS
srfTriangles_t * R_PolytopeSurface(int numPlanes, const idPlane *planes, idWinding **windings)
Definition: tr_polytope.cpp:44
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:4804
areaReference_t * entityRefs
Definition: tr_local.h:285
idVec3 xyz
Definition: DrawVert.h:42
idList< idRenderEntityLocal * > entityDefs
void FlowLightThroughPortals(idRenderLightLocal *light)
GLclampf ref
Definition: glext.h:4237
renderLight_t parms
Definition: tr_local.h:191
const idVec4 & ToVec4(void) const
Definition: Plane.h:375
Definition: Vector.h:316
idRenderWorldLocal * primaryWorld
Definition: tr_local.h:774
float modelMatrix[16]
Definition: tr_local.h:253
void R_RegenerateWorld_f(const idCmdArgs &args)
virtual const idMaterial * FindMaterial(const char *name, bool makeDefault=true)=0
idList< idRenderWorldLocal * > worlds
Definition: tr_local.h:772
GLdouble right
Definition: qgl.h:273
idVec3 Cross(const idVec3 &a) const
Definition: Vector.h:619
int i
Definition: process.py:33
deferredEntityCallback_t callback
Definition: RenderWorld.h:96
static void Free(idRenderModelOverlay *overlay)
void R_CheckForEntityDefsUsingModel(idRenderModel *model)
list l
Definition: prepare.py:17
idList< idRenderLightLocal * > lightDefs
float shaderParms[MAX_ENTITY_SHADER_PARMS]
Definition: RenderWorld.h:201
void R_ReCreateWorldReferences(void)
bool LightCastsShadows() const
Definition: Material.h:468
struct doublePortal_s * nextFoggedPortal
idBounds referenceBounds
Definition: tr_local.h:268
void R_CreateEntityRefs(idRenderEntityLocal *def)
idPlane lightProject[4]
Definition: tr_local.h:211
GLuint GLuint GLsizei count
Definition: glext.h:2845
void R_FreeLightDefFrustum(idRenderLightLocal *ldef)
virtual void FreeLightDef(qhandle_t lightHandle)
int GetNumPoints(void) const
Definition: Winding.h:238
idRenderModelDecal * decals
Definition: tr_local.h:282
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3454
Definition: Vector.h:808
idVec3 lightRadius
Definition: RenderWorld.h:178
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
idRenderWorldLocal * world
Definition: tr_local.h:198
areaReference_t * references
Definition: tr_local.h:229
idBounds bounds
Definition: Model.h:87
idCVar r_showUpdates("r_showUpdates","0", CVAR_RENDERER|CVAR_BOOL,"report entity and light updates and ref counts")
idCommon * common
Definition: Common.cpp:206
idJointMat * joints
Definition: RenderWorld.h:135
idImage * falloffImage
Definition: tr_local.h:214
void R_FreeEntityDefDerivedData(idRenderEntityLocal *def, bool keepDecals, bool keepCachedDynamicModel)
#define NULL
Definition: Lib.h:88
struct portal_s * next
idInteraction * firstInteraction
Definition: tr_local.h:230
struct areaReference_s * ownerNext
Definition: tr_local.h:144
const int MAX_RENDERENTITY_GUI
Definition: RenderWorld.h:74
void * callbackData
Definition: RenderWorld.h:98
Definition: Plane.h:71
void R_MakeShadowFrustums(idRenderLightLocal *def)
void R_FreeStaticTriSurf(srfTriangles_t *tri)
Definition: tr_trisurf.cpp:489
tuple dp
Definition: prepare.py:21
idBlockAlloc< areaReference_t, 1024 > areaReferenceAllocator
int Argc(void) const
Definition: CmdArgs.h:48
void Mem_Free(void *ptr)
Definition: Heap.cpp:1087
void R_ModulateLights_f(const idCmdArgs &args)
idRenderModel * hModel
Definition: RenderWorld.h:81
virtual void Printf(const char *fmt,...) id_attribute((format(printf
float Normalize(bool fixDegenerate=true)
Definition: Plane.h:247
virtual idBounds Bounds(const struct renderEntity_s *ent=NULL) const =0
float modelMatrix[16]
Definition: tr_local.h:196
idRenderModel * cachedDynamicModel
Definition: tr_local.h:266
idDeclManager * declManager
srfTriangles_t * frustumTris
Definition: tr_local.h:221
bool WindingCompletelyInsideLight(const idWinding *w, const idRenderLightLocal *ldef)
static idRenderModelDecal * RemoveFadedDecals(idRenderModelDecal *decals, int time)
Definition: ModelDecal.cpp:389
idWinding * w
void R_CreateLightDefFogPortals(idRenderLightLocal *ldef)
viewDef_t * viewDef
Definition: tr_local.h:786
void R_FreeEntityDefDecals(idRenderEntityLocal *def)
void R_FreeDerivedData(void)
idRenderModelManager * renderModelManager
idRenderModel * prelightModel
Definition: RenderWorld.h:194
bool GetBool(void) const
Definition: CVarSystem.h:142
bool IsCleared(void) const
Definition: Bounds.h:222
void R_DeriveLightData(idRenderLightLocal *light)
void R_FreeEntityDefFadedDecals(idRenderEntityLocal *def, int time)
int Num(void) const
Definition: List.h:265
void R_LocalPlaneToGlobal(const float modelMatrix[16], const idPlane &in, idPlane &out)
Definition: tr_main.cpp:554
portalArea_t * portalAreas
virtual int PointInArea(const idVec3 &point) const
void Mem_Free16(void *ptr)
Definition: Heap.cpp:1128
idRenderModelDecal * Next(void) const
Definition: ModelDecal.h:88
idBounds bounds
Definition: RenderWorld.h:95
idRenderModelOverlay * overlay
Definition: tr_local.h:283
idWinding * frustumWindings[6]
Definition: tr_local.h:220
struct portalArea_s * area
Definition: tr_local.h:147
class idUserInterface * gui[MAX_RENDERENTITY_GUI]
Definition: RenderWorld.h:130
bool IsFogLight() const
Definition: Material.h:458
portal_t * portals
bool TestMaterialFlag(const int flag) const
Definition: Material.h:494
idRenderSystemLocal tr
struct areaReference_s * areaNext
Definition: tr_local.h:142
const idVec3 & ToVec3(void) const
Definition: Vector.h:1043
const char * Argv(int arg) const
Definition: CmdArgs.h:50
void PushVolumeIntoTree(idRenderEntityLocal *def, idRenderLightLocal *light, int numPoints, const idVec3(*points))
GLint j
Definition: qgl.h:264
struct doublePortal_s * doublePortal
idSession * session
Definition: Session.cpp:48
idInteraction * firstInteraction
Definition: tr_local.h:286
renderEntity_t parms
Definition: tr_local.h:251
void R_LocalPointToGlobal(const float modelMatrix[16], const idVec3 &in, idVec3 &out)
Definition: tr_main.cpp:470
virtual void Error(const char *fmt,...) id_attribute((format(printf
const idMaterial * shader
Definition: RenderWorld.h:200
idImage * LightFalloffImage() const
Definition: Material.h:480
void R_AxisToModelMatrix(const idMat3 &axis, const idVec3 &origin, float modelMatrix[16])
Definition: tr_main.cpp:445
void R_FreeLightDefDerivedData(idRenderLightLocal *ldef)
idCVar r_useLightPortalFlow("r_useLightPortalFlow","1", CVAR_RENDERER|CVAR_BOOL,"use a more precise area reference determination")
void R_ClearEntityDefDynamicModel(idRenderEntityLocal *def)
GLuint start
Definition: glext.h:2845
idDrawVert * verts
Definition: Model.h:99
struct areaReference_s * areaPrev
Definition: tr_local.h:143
idVec3 globalLightOrigin
Definition: tr_local.h:216
static void Free(idRenderModelDecal *decal)
Definition: ModelDecal.cpp:79