doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Interaction.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 idInteraction implementation
38 
39 ===========================================================================
40 */
41 
42 // FIXME: use private allocator for srfCullInfo_t
43 
44 /*
45 ================
46 R_CalcInteractionFacing
47 
48 Determines which triangles of the surface are facing towards the light origin.
49 
50 The facing array should be allocated with one extra index than
51 the number of surface triangles, which will be used to handle dangling
52 edge silhouettes.
53 ================
54 */
55 void R_CalcInteractionFacing( const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo ) {
56  idVec3 localLightOrigin;
57 
58  if ( cullInfo.facing != NULL ) {
59  return;
60  }
61 
62  R_GlobalPointToLocal( ent->modelMatrix, light->globalLightOrigin, localLightOrigin );
63 
64  int numFaces = tri->numIndexes / 3;
65 
66  if ( !tri->facePlanes || !tri->facePlanesCalculated ) {
67  R_DeriveFacePlanes( const_cast<srfTriangles_t *>(tri) );
68  }
69 
70  cullInfo.facing = (byte *) R_StaticAlloc( ( numFaces + 1 ) * sizeof( cullInfo.facing[0] ) );
71 
72  // calculate back face culling
73  float *planeSide = (float *) _alloca16( numFaces * sizeof( float ) );
74 
75  // exact geometric cull against face
76  SIMDProcessor->Dot( planeSide, localLightOrigin, tri->facePlanes, numFaces );
77  SIMDProcessor->CmpGE( cullInfo.facing, planeSide, 0.0f, numFaces );
78 
79  cullInfo.facing[ numFaces ] = 1; // for dangling edges to reference
80 }
81 
82 /*
83 =====================
84 R_CalcInteractionCullBits
85 
86 We want to cull a little on the sloppy side, because the pre-clipping
87 of geometry to the lights in dmap will give many cases that are right
88 at the border we throw things out on the border, because if any one
89 vertex is clearly inside, the entire triangle will be accepted.
90 =====================
91 */
92 void R_CalcInteractionCullBits( const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo ) {
93  int i, frontBits;
94 
95  if ( cullInfo.cullBits != NULL ) {
96  return;
97  }
98 
99  frontBits = 0;
100 
101  // cull the triangle surface bounding box
102  for ( i = 0; i < 6; i++ ) {
103 
104  R_GlobalPlaneToLocal( ent->modelMatrix, -light->frustum[i], cullInfo.localClipPlanes[i] );
105 
106  // get front bits for the whole surface
107  if ( tri->bounds.PlaneDistance( cullInfo.localClipPlanes[i] ) >= LIGHT_CLIP_EPSILON ) {
108  frontBits |= 1<<i;
109  }
110  }
111 
112  // if the surface is completely inside the light frustum
113  if ( frontBits == ( ( 1 << 6 ) - 1 ) ) {
114  cullInfo.cullBits = LIGHT_CULL_ALL_FRONT;
115  return;
116  }
117 
118  cullInfo.cullBits = (byte *) R_StaticAlloc( tri->numVerts * sizeof( cullInfo.cullBits[0] ) );
119  SIMDProcessor->Memset( cullInfo.cullBits, 0, tri->numVerts * sizeof( cullInfo.cullBits[0] ) );
120 
121  float *planeSide = (float *) _alloca16( tri->numVerts * sizeof( float ) );
122 
123  for ( i = 0; i < 6; i++ ) {
124  // if completely infront of this clipping plane
125  if ( frontBits & ( 1 << i ) ) {
126  continue;
127  }
128  SIMDProcessor->Dot( planeSide, cullInfo.localClipPlanes[i], tri->verts, tri->numVerts );
129  SIMDProcessor->CmpLT( cullInfo.cullBits, i, planeSide, LIGHT_CLIP_EPSILON, tri->numVerts );
130  }
131 }
132 
133 /*
134 ================
135 R_FreeInteractionCullInfo
136 ================
137 */
139  if ( cullInfo.facing != NULL ) {
140  R_StaticFree( cullInfo.facing );
141  cullInfo.facing = NULL;
142  }
143  if ( cullInfo.cullBits != NULL ) {
144  if ( cullInfo.cullBits != LIGHT_CULL_ALL_FRONT ) {
145  R_StaticFree( cullInfo.cullBits );
146  }
147  cullInfo.cullBits = NULL;
148  }
149 }
150 
151 #define MAX_CLIPPED_POINTS 20
152 typedef struct {
153  int numVerts;
155 } clipTri_t;
156 
157 /*
158 =============
159 R_ChopWinding
160 
161 Clips a triangle from one buffer to another, setting edge flags
162 The returned buffer may be the same as inNum if no clipping is done
163 If entirely clipped away, clipTris[returned].numVerts == 0
164 
165 I have some worries about edge flag cases when polygons are clipped
166 multiple times near the epsilon.
167 =============
168 */
169 static int R_ChopWinding( clipTri_t clipTris[2], int inNum, const idPlane plane ) {
170  clipTri_t *in, *out;
171  float dists[MAX_CLIPPED_POINTS];
172  int sides[MAX_CLIPPED_POINTS];
173  int counts[3];
174  float dot;
175  int i, j;
176  idVec3 mid;
177  bool front;
178 
179  in = &clipTris[inNum];
180  out = &clipTris[inNum^1];
181  counts[0] = counts[1] = counts[2] = 0;
182 
183  // determine sides for each point
184  front = false;
185  for ( i = 0; i < in->numVerts; i++ ) {
186  dot = in->verts[i] * plane.Normal() + plane[3];
187  dists[i] = dot;
188  if ( dot < LIGHT_CLIP_EPSILON ) { // slop onto the back
189  sides[i] = SIDE_BACK;
190  } else {
191  sides[i] = SIDE_FRONT;
192  if ( dot > LIGHT_CLIP_EPSILON ) {
193  front = true;
194  }
195  }
196  counts[sides[i]]++;
197  }
198 
199  // if none in front, it is completely clipped away
200  if ( !front ) {
201  in->numVerts = 0;
202  return inNum;
203  }
204  if ( !counts[SIDE_BACK] ) {
205  return inNum; // inout stays the same
206  }
207 
208  // avoid wrapping checks by duplicating first value to end
209  sides[i] = sides[0];
210  dists[i] = dists[0];
211  in->verts[in->numVerts] = in->verts[0];
212 
213  out->numVerts = 0;
214  for ( i = 0 ; i < in->numVerts ; i++ ) {
215  idVec3 &p1 = in->verts[i];
216 
217  if ( sides[i] == SIDE_FRONT ) {
218  out->verts[out->numVerts] = p1;
219  out->numVerts++;
220  }
221 
222  if ( sides[i+1] == sides[i] ) {
223  continue;
224  }
225 
226  // generate a split point
227  idVec3 &p2 = in->verts[i+1];
228 
229  dot = dists[i] / ( dists[i] - dists[i+1] );
230  for ( j = 0; j < 3; j++ ) {
231  mid[j] = p1[j] + dot * ( p2[j] - p1[j] );
232  }
233 
234  out->verts[out->numVerts] = mid;
235 
236  out->numVerts++;
237  }
238 
239  return inNum ^ 1;
240 }
241 
242 /*
243 ===================
244 R_ClipTriangleToLight
245 
246 Returns false if nothing is left after clipping
247 ===================
248 */
249 static bool R_ClipTriangleToLight( const idVec3 &a, const idVec3 &b, const idVec3 &c, int planeBits, const idPlane frustum[6] ) {
250  int i;
251  clipTri_t pingPong[2];
252  int p;
253 
254  pingPong[0].numVerts = 3;
255  pingPong[0].verts[0] = a;
256  pingPong[0].verts[1] = b;
257  pingPong[0].verts[2] = c;
258 
259  p = 0;
260  for ( i = 0 ; i < 6 ; i++ ) {
261  if ( planeBits & ( 1 << i ) ) {
262  p = R_ChopWinding( pingPong, p, frustum[i] );
263  if ( pingPong[p].numVerts < 1 ) {
264  return false;
265  }
266  }
267  }
268 
269  return true;
270 }
271 
272 /*
273 ====================
274 R_CreateLightTris
275 
276 The resulting surface will be a subset of the original triangles,
277 it will never clip triangles, but it may cull on a per-triangle basis.
278 ====================
279 */
280 static srfTriangles_t *R_CreateLightTris( const idRenderEntityLocal *ent,
281  const srfTriangles_t *tri, const idRenderLightLocal *light,
282  const idMaterial *shader, srfCullInfo_t &cullInfo ) {
283  int i;
284  int numIndexes;
285  glIndex_t *indexes;
286  srfTriangles_t *newTri;
287  int c_backfaced;
288  int c_distance;
289  idBounds bounds;
290  bool includeBackFaces;
291  int faceNum;
292 
294  c_backfaced = 0;
295  c_distance = 0;
296 
297  numIndexes = 0;
298  indexes = NULL;
299 
300  // it is debatable if non-shadowing lights should light back faces. we aren't at the moment
302  || shader->ReceivesLightingOnBackSides()
303  || ent->parms.noSelfShadow || ent->parms.noShadow ) {
304  includeBackFaces = true;
305  } else {
306  includeBackFaces = false;
307  }
308 
309  // allocate a new surface for the lit triangles
310  newTri = R_AllocStaticTriSurf();
311 
312  // save a reference to the original surface
313  newTri->ambientSurface = const_cast<srfTriangles_t *>(tri);
314 
315  // the light surface references the verts of the ambient surface
316  newTri->numVerts = tri->numVerts;
317  R_ReferenceStaticTriSurfVerts( newTri, tri );
318 
319  // calculate cull information
320  if ( !includeBackFaces ) {
321  R_CalcInteractionFacing( ent, tri, light, cullInfo );
322  }
323  R_CalcInteractionCullBits( ent, tri, light, cullInfo );
324 
325  // if the surface is completely inside the light frustum
326  if ( cullInfo.cullBits == LIGHT_CULL_ALL_FRONT ) {
327 
328  // if we aren't self shadowing, let back facing triangles get
329  // through so the smooth shaded bump maps light all the way around
330  if ( includeBackFaces ) {
331 
332  // the whole surface is lit so the light surface just references the indexes of the ambient surface
333  R_ReferenceStaticTriSurfIndexes( newTri, tri );
334  numIndexes = tri->numIndexes;
335  bounds = tri->bounds;
336 
337  } else {
338 
339  // the light tris indexes are going to be a subset of the original indexes so we generally
340  // allocate too much memory here but we decrease the memory block when the number of indexes is known
341  R_AllocStaticTriSurfIndexes( newTri, tri->numIndexes );
342 
343  // back face cull the individual triangles
344  indexes = newTri->indexes;
345  const byte *facing = cullInfo.facing;
346  for ( faceNum = i = 0; i < tri->numIndexes; i += 3, faceNum++ ) {
347  if ( !facing[ faceNum ] ) {
348  c_backfaced++;
349  continue;
350  }
351  indexes[numIndexes+0] = tri->indexes[i+0];
352  indexes[numIndexes+1] = tri->indexes[i+1];
353  indexes[numIndexes+2] = tri->indexes[i+2];
354  numIndexes += 3;
355  }
356 
357  // get bounds for the surface
358  SIMDProcessor->MinMax( bounds[0], bounds[1], tri->verts, indexes, numIndexes );
359 
360  // decrease the size of the memory block to the size of the number of used indexes
361  R_ResizeStaticTriSurfIndexes( newTri, numIndexes );
362  }
363 
364  } else {
365 
366  // the light tris indexes are going to be a subset of the original indexes so we generally
367  // allocate too much memory here but we decrease the memory block when the number of indexes is known
368  R_AllocStaticTriSurfIndexes( newTri, tri->numIndexes );
369 
370  // cull individual triangles
371  indexes = newTri->indexes;
372  const byte *facing = cullInfo.facing;
373  const byte *cullBits = cullInfo.cullBits;
374  for ( faceNum = i = 0; i < tri->numIndexes; i += 3, faceNum++ ) {
375  int i1, i2, i3;
376 
377  // if we aren't self shadowing, let back facing triangles get
378  // through so the smooth shaded bump maps light all the way around
379  if ( !includeBackFaces ) {
380  // back face cull
381  if ( !facing[ faceNum ] ) {
382  c_backfaced++;
383  continue;
384  }
385  }
386 
387  i1 = tri->indexes[i+0];
388  i2 = tri->indexes[i+1];
389  i3 = tri->indexes[i+2];
390 
391  // fast cull outside the frustum
392  // if all three points are off one plane side, it definately isn't visible
393  if ( cullBits[i1] & cullBits[i2] & cullBits[i3] ) {
394  c_distance++;
395  continue;
396  }
397 
399  // do a precise clipped cull if none of the points is completely inside the frustum
400  // note that we do not actually use the clipped triangle, which would have Z fighting issues.
401  if ( cullBits[i1] && cullBits[i2] && cullBits[i3] ) {
402  int cull = cullBits[i1] | cullBits[i2] | cullBits[i3];
403  if ( !R_ClipTriangleToLight( tri->verts[i1].xyz, tri->verts[i2].xyz, tri->verts[i3].xyz, cull, cullInfo.localClipPlanes ) ) {
404  continue;
405  }
406  }
407  }
408 
409  // add to the list
410  indexes[numIndexes+0] = i1;
411  indexes[numIndexes+1] = i2;
412  indexes[numIndexes+2] = i3;
413  numIndexes += 3;
414  }
415 
416  // get bounds for the surface
417  SIMDProcessor->MinMax( bounds[0], bounds[1], tri->verts, indexes, numIndexes );
418 
419  // decrease the size of the memory block to the size of the number of used indexes
420  R_ResizeStaticTriSurfIndexes( newTri, numIndexes );
421  }
422 
423  if ( !numIndexes ) {
424  R_ReallyFreeStaticTriSurf( newTri );
425  return NULL;
426  }
427 
428  newTri->numIndexes = numIndexes;
429 
430  newTri->bounds = bounds;
431 
432  return newTri;
433 }
434 
435 /*
436 ===============
437 idInteraction::idInteraction
438 ===============
439 */
441  numSurfaces = 0;
442  surfaces = NULL;
443  entityDef = NULL;
444  lightDef = NULL;
445  lightNext = NULL;
446  lightPrev = NULL;
447  entityNext = NULL;
448  entityPrev = NULL;
451  frustumAreas = NULL;
452 }
453 
454 /*
455 ===============
456 idInteraction::AllocAndLink
457 ===============
458 */
460  if ( !edef || !ldef ) {
461  common->Error( "idInteraction::AllocAndLink: NULL parm" );
462  }
463 
464  idRenderWorldLocal *renderWorld = edef->world;
465 
466  idInteraction *interaction = renderWorld->interactionAllocator.Alloc();
467 
468  // link and initialize
469  interaction->dynamicModelFrameCount = 0;
470 
471  interaction->lightDef = ldef;
472  interaction->entityDef = edef;
473 
474  interaction->numSurfaces = -1; // not checked yet
475  interaction->surfaces = NULL;
476 
478  interaction->frustumAreas = NULL;
479 
480  // link at the start of the entity's list
481  interaction->lightNext = ldef->firstInteraction;
482  interaction->lightPrev = NULL;
483  ldef->firstInteraction = interaction;
484  if ( interaction->lightNext != NULL ) {
485  interaction->lightNext->lightPrev = interaction;
486  } else {
487  ldef->lastInteraction = interaction;
488  }
489 
490  // link at the start of the light's list
491  interaction->entityNext = edef->firstInteraction;
492  interaction->entityPrev = NULL;
493  edef->firstInteraction = interaction;
494  if ( interaction->entityNext != NULL ) {
495  interaction->entityNext->entityPrev = interaction;
496  } else {
497  edef->lastInteraction = interaction;
498  }
499 
500  // update the interaction table
501  if ( renderWorld->interactionTable ) {
502  int index = ldef->index * renderWorld->interactionTableWidth + edef->index;
503  if ( renderWorld->interactionTable[index] != NULL ) {
504  common->Error( "idInteraction::AllocAndLink: non NULL table entry" );
505  }
506  renderWorld->interactionTable[ index ] = interaction;
507  }
508 
509  return interaction;
510 }
511 
512 /*
513 ===============
514 idInteraction::FreeSurfaces
515 
516 Frees the surfaces, but leaves the interaction linked in, so it
517 will be regenerated automatically
518 ===============
519 */
521  if ( this->surfaces ) {
522  for ( int i = 0 ; i < this->numSurfaces ; i++ ) {
523  surfaceInteraction_t *sint = &this->surfaces[i];
524 
525  if ( sint->lightTris ) {
526  if ( sint->lightTris != LIGHT_TRIS_DEFERRED ) {
528  }
529  sint->lightTris = NULL;
530  }
531  if ( sint->shadowTris ) {
532  // if it doesn't have an entityDef, it is part of a prelight
533  // model, not a generated interaction
534  if ( this->entityDef ) {
536  sint->shadowTris = NULL;
537  }
538  }
540  }
541 
542  R_StaticFree( this->surfaces );
543  this->surfaces = NULL;
544  }
545  this->numSurfaces = -1;
546 }
547 
548 /*
549 ===============
550 idInteraction::Unlink
551 ===============
552 */
553 void idInteraction::Unlink( void ) {
554 
555  // unlink from the entity's list
556  if ( this->entityPrev ) {
557  this->entityPrev->entityNext = this->entityNext;
558  } else {
559  this->entityDef->firstInteraction = this->entityNext;
560  }
561  if ( this->entityNext ) {
562  this->entityNext->entityPrev = this->entityPrev;
563  } else {
564  this->entityDef->lastInteraction = this->entityPrev;
565  }
566  this->entityNext = this->entityPrev = NULL;
567 
568  // unlink from the light's list
569  if ( this->lightPrev ) {
570  this->lightPrev->lightNext = this->lightNext;
571  } else {
572  this->lightDef->firstInteraction = this->lightNext;
573  }
574  if ( this->lightNext ) {
575  this->lightNext->lightPrev = this->lightPrev;
576  } else {
577  this->lightDef->lastInteraction = this->lightPrev;
578  }
579  this->lightNext = this->lightPrev = NULL;
580 }
581 
582 /*
583 ===============
584 idInteraction::UnlinkAndFree
585 
586 Removes links and puts it back on the free list.
587 ===============
588 */
590 
591  // clear the table pointer
592  idRenderWorldLocal *renderWorld = this->lightDef->world;
593  if ( renderWorld->interactionTable ) {
594  int index = this->lightDef->index * renderWorld->interactionTableWidth + this->entityDef->index;
595  if ( renderWorld->interactionTable[index] != this ) {
596  common->Error( "idInteraction::UnlinkAndFree: interactionTable wasn't set" );
597  }
598  renderWorld->interactionTable[index] = NULL;
599  }
600 
601  Unlink();
602 
603  FreeSurfaces();
604 
605  // free the interaction area references
606  areaNumRef_t *area, *nextArea;
607  for ( area = frustumAreas; area; area = nextArea ) {
608  nextArea = area->next;
609  renderWorld->areaNumRefAllocator.Free( area );
610  }
611 
612  // put it back on the free list
613  renderWorld->interactionAllocator.Free( this );
614 }
615 
616 /*
617 ===============
618 idInteraction::MakeEmpty
619 
620 Makes the interaction empty and links it at the end of the entity's and light's interaction lists.
621 ===============
622 */
624 
625  // an empty interaction has no surfaces
626  numSurfaces = 0;
627 
628  Unlink();
629 
630  // relink at the end of the entity's list
631  this->entityNext = NULL;
632  this->entityPrev = this->entityDef->lastInteraction;
633  this->entityDef->lastInteraction = this;
634  if ( this->entityPrev ) {
635  this->entityPrev->entityNext = this;
636  } else {
637  this->entityDef->firstInteraction = this;
638  }
639 
640  // relink at the end of the light's list
641  this->lightNext = NULL;
642  this->lightPrev = this->lightDef->lastInteraction;
643  this->lightDef->lastInteraction = this;
644  if ( this->lightPrev ) {
645  this->lightPrev->lightNext = this;
646  } else {
647  this->lightDef->firstInteraction = this;
648  }
649 }
650 
651 /*
652 ===============
653 idInteraction::HasShadows
654 ===============
655 */
656 ID_INLINE bool idInteraction::HasShadows( void ) const {
658 }
659 
660 /*
661 ===============
662 idInteraction::MemoryUsed
663 
664 Counts up the memory used by all the surfaceInteractions, which
665 will be used to determine when we need to start purging old interactions.
666 ===============
667 */
669  int total = 0;
670 
671  for ( int i = 0 ; i < numSurfaces ; i++ ) {
672  surfaceInteraction_t *inter = &surfaces[i];
673 
674  total += R_TriSurfMemory( inter->lightTris );
675  total += R_TriSurfMemory( inter->shadowTris );
676  }
677 
678  return total;
679 }
680 
681 /*
682 ==================
683 idInteraction::CalcInteractionScissorRectangle
684 ==================
685 */
687  idBounds projectionBounds;
688  idScreenRect portalRect;
689  idScreenRect scissorRect;
690 
691  if ( r_useInteractionScissors.GetInteger() == 0 ) {
692  return lightDef->viewLight->scissorRect;
693  }
694 
695  if ( r_useInteractionScissors.GetInteger() < 0 ) {
696  // this is the code from Cass at nvidia, it is more precise, but slower
698  }
699 
700  // the following is Mr.E's code
701 
702  // frustum must be initialized and valid
704  return lightDef->viewLight->scissorRect;
705  }
706 
707  // calculate scissors for the portals through which the interaction is visible
708  if ( r_useInteractionScissors.GetInteger() > 1 ) {
709  areaNumRef_t *area;
710 
712  // retrieve all the areas the interaction frustum touches
714  area = entityDef->world->areaNumRefAllocator.Alloc();
715  area->areaNum = ref->area->areaNum;
716  area->next = frustumAreas;
717  frustumAreas = area;
718  }
721  }
722 
723  portalRect.Clear();
724  for ( area = frustumAreas; area; area = area->next ) {
725  portalRect.Union( entityDef->world->GetAreaScreenRect( area->areaNum ) );
726  }
727  portalRect.Intersect( lightDef->viewLight->scissorRect );
728  } else {
729  portalRect = lightDef->viewLight->scissorRect;
730  }
731 
732  // early out if the interaction is not visible through any portals
733  if ( portalRect.IsEmpty() ) {
734  return portalRect;
735  }
736 
737  // calculate bounds of the interaction frustum projected into the view frustum
738  if ( lightDef->parms.pointLight ) {
739  viewFrustum.ClippedProjectionBounds( frustum, idBox( lightDef->parms.origin, lightDef->parms.lightRadius, lightDef->parms.axis ), projectionBounds );
740  } else {
741  viewFrustum.ClippedProjectionBounds( frustum, idBox( lightDef->frustumTris->bounds ), projectionBounds );
742  }
743 
744  if ( projectionBounds.IsCleared() ) {
745  return portalRect;
746  }
747 
748  // derive a scissor rectangle from the projection bounds
749  scissorRect = R_ScreenRectFromViewFrustumBounds( projectionBounds );
750 
751  // intersect with the portal crossing scissor rectangle
752  scissorRect.Intersect( portalRect );
753 
755  R_ShowColoredScreenRect( scissorRect, lightDef->index );
756  }
757 
758  return scissorRect;
759 }
760 
761 /*
762 ===================
763 idInteraction::CullInteractionByViewFrustum
764 ===================
765 */
767 
768  if ( !r_useInteractionCulling.GetBool() ) {
769  return false;
770  }
771 
773  return false;
774  }
775 
777 
779 
780  if ( !frustum.IsValid() ) {
782  return false;
783  }
784 
785  if ( lightDef->parms.pointLight ) {
786  frustum.ConstrainToBox( idBox( lightDef->parms.origin, lightDef->parms.lightRadius, lightDef->parms.axis ) );
787  } else {
788  frustum.ConstrainToBox( idBox( lightDef->frustumTris->bounds ) );
789  }
790 
792  }
793 
794  if ( !viewFrustum.IntersectsFrustum( frustum ) ) {
795  return true;
796  }
797 
803  }
804  }
805 
806  return false;
807 }
808 
809 /*
810 ====================
811 idInteraction::CreateInteraction
812 
813 Called when a entityDef and a lightDef are both present in a
814 portalArea, and might be visible. Performs cull checking before doing the expensive
815 computations.
816 
817 References tr.viewCount so lighting surfaces will only be created if the ambient surface is visible,
818 otherwise it will be marked as deferred.
819 
820 The results of this are cached and valid until the light or entity change.
821 ====================
822 */
824  const idMaterial * lightShader = lightDef->lightShader;
825  const idMaterial* shader;
826  bool interactionGenerated;
827  idBounds bounds;
828 
830 
831  bounds = model->Bounds( &entityDef->parms );
832 
833  // if it doesn't contact the light frustum, none of the surfaces will
834  if ( R_CullLocalBox( bounds, entityDef->modelMatrix, 6, lightDef->frustum ) ) {
835  MakeEmpty();
836  return;
837  }
838 
839  // use the turbo shadow path
840  shadowGen_t shadowGen = SG_DYNAMIC;
841 
842  // really large models, like outside terrain meshes, should use
843  // the more exactly culled static shadow path instead of the turbo shadow path.
844  // FIXME: this is a HACK, we should probably have a material flag.
845  if ( bounds[1][0] - bounds[0][0] > 3000 ) {
846  shadowGen = SG_STATIC;
847  }
848 
849  //
850  // create slots for each of the model's surfaces
851  //
852  numSurfaces = model->NumSurfaces();
854 
855  interactionGenerated = false;
856 
857  // check each surface in the model
858  for ( int c = 0 ; c < model->NumSurfaces() ; c++ ) {
859  const modelSurface_t *surf;
860  srfTriangles_t *tri;
861 
862  surf = model->Surface( c );
863 
864  tri = surf->geometry;
865  if ( !tri ) {
866  continue;
867  }
868 
869  // determine the shader for this surface, possibly by skinning
870  shader = surf->shader;
872 
873  if ( !shader ) {
874  continue;
875  }
876 
877  // try to cull each surface
879  continue;
880  }
881 
882  surfaceInteraction_t *sint = &surfaces[c];
883 
884  sint->shader = shader;
885 
886  // save the ambient tri pointer so we can reject lightTri interactions
887  // when the ambient surface isn't in view, and we can get shared vertex
888  // and shadow data from the source surface
889  sint->ambientTris = tri;
890 
891  // "invisible ink" lights and shaders
892  if ( shader->Spectrum() != lightShader->Spectrum() ) {
893  continue;
894  }
895 
896  // generate a lighted surface and add it
897  if ( shader->ReceivesLighting() ) {
898  if ( tri->ambientViewCount == tr.viewCount ) {
899  sint->lightTris = R_CreateLightTris( entityDef, tri, lightDef, shader, sint->cullInfo );
900  } else {
901  // this will be calculated when sint->ambientTris is actually in view
903  }
904  interactionGenerated = true;
905  }
906 
907  // if the interaction has shadows and this surface casts a shadow
908  if ( HasShadows() && shader->SurfaceCastsShadow() && tri->silEdges != NULL ) {
909 
910  // if the light has an optimized shadow volume, don't create shadows for any models that are part of the base areas
912 
913  // this is the only place during gameplay (outside the utilities) that R_CreateShadowVolume() is called
914  sint->shadowTris = R_CreateShadowVolume( entityDef, tri, lightDef, shadowGen, sint->cullInfo );
915  if ( sint->shadowTris ) {
917  // if any surface is a shadow-casting perforated or translucent surface, or the
918  // base surface is suppressed in the view (world weapon shadows) we can't use
919  // the external shadow optimizations because we can see through some of the faces
922  }
923  }
924  interactionGenerated = true;
925  }
926  }
927 
928  // free the cull information when it's no longer needed
929  if ( sint->lightTris != LIGHT_TRIS_DEFERRED ) {
931  }
932  }
933 
934  // if none of the surfaces generated anything, don't even bother checking?
935  if ( !interactionGenerated ) {
936  MakeEmpty();
937  }
938 }
939 
940 /*
941 ======================
942 R_PotentiallyInsideInfiniteShadow
943 
944 If we know that we are "off to the side" of an infinite shadow volume,
945 we can draw it without caps in zpass mode
946 ======================
947 */
948 static bool R_PotentiallyInsideInfiniteShadow( const srfTriangles_t *occluder,
949  const idVec3 &localView, const idVec3 &localLight ) {
950  idBounds exp;
951 
952  // expand the bounds to account for the near clip plane, because the
953  // view could be mathematically outside, but if the near clip plane
954  // chops a volume edge, the zpass rendering would fail.
955  float znear = r_znear.GetFloat();
956  if ( tr.viewDef->renderView.cramZNear ) {
957  znear *= 0.25f;
958  }
959  float stretch = znear * 2; // in theory, should vary with FOV
960  exp[0][0] = occluder->bounds[0][0] - stretch;
961  exp[0][1] = occluder->bounds[0][1] - stretch;
962  exp[0][2] = occluder->bounds[0][2] - stretch;
963  exp[1][0] = occluder->bounds[1][0] + stretch;
964  exp[1][1] = occluder->bounds[1][1] + stretch;
965  exp[1][2] = occluder->bounds[1][2] + stretch;
966 
967  if ( exp.ContainsPoint( localView ) ) {
968  return true;
969  }
970  if ( exp.ContainsPoint( localLight ) ) {
971  return true;
972  }
973 
974  // if the ray from localLight to localView intersects a face of the
975  // expanded bounds, we will be inside the projection
976 
977  idVec3 ray = localView - localLight;
978 
979  // intersect the ray from the view to the light with the near side of the bounds
980  for ( int axis = 0; axis < 3; axis++ ) {
981  float d, frac;
982  idVec3 hit;
983 
984  if ( localLight[axis] < exp[0][axis] ) {
985  if ( localView[axis] < exp[0][axis] ) {
986  continue;
987  }
988  d = exp[0][axis] - localLight[axis];
989  frac = d / ray[axis];
990  hit = localLight + frac * ray;
991  hit[axis] = exp[0][axis];
992  } else if ( localLight[axis] > exp[1][axis] ) {
993  if ( localView[axis] > exp[1][axis] ) {
994  continue;
995  }
996  d = exp[1][axis] - localLight[axis];
997  frac = d / ray[axis];
998  hit = localLight + frac * ray;
999  hit[axis] = exp[1][axis];
1000  } else {
1001  continue;
1002  }
1003 
1004  if ( exp.ContainsPoint( hit ) ) {
1005  return true;
1006  }
1007  }
1008 
1009  // the view is definitely not inside the projected shadow
1010  return false;
1011 }
1012 
1013 /*
1014 ==================
1015 idInteraction::AddActiveInteraction
1016 
1017 Create and add any necessary light and shadow triangles
1018 
1019 If the model doesn't have any surfaces that need interactions
1020 with this type of light, it can be skipped, but we might need to
1021 instantiate the dynamic model to find out
1022 ==================
1023 */
1025  viewLight_t * vLight;
1026  viewEntity_t * vEntity;
1027  idScreenRect shadowScissor;
1028  idScreenRect lightScissor;
1029  idVec3 localLightOrigin;
1030  idVec3 localViewOrigin;
1031 
1032  vLight = lightDef->viewLight;
1033  vEntity = entityDef->viewEntity;
1034 
1035  // do not waste time culling the interaction frustum if there will be no shadows
1036  if ( !HasShadows() ) {
1037 
1038  // use the entity scissor rectangle
1039  shadowScissor = vEntity->scissorRect;
1040 
1041  // culling does not seem to be worth it for static world models
1042  } else if ( entityDef->parms.hModel->IsStaticWorldModel() ) {
1043 
1044  // use the light scissor rectangle
1045  shadowScissor = vLight->scissorRect;
1046 
1047  } else {
1048 
1049  // try to cull the interaction
1050  // this will also cull the case where the light origin is inside the
1051  // view frustum and the entity bounds are outside the view frustum
1053  return;
1054  }
1055 
1056  // calculate the shadow scissor rectangle
1058  }
1059 
1060  // get out before making the dynamic model if the shadow scissor rectangle is empty
1061  if ( shadowScissor.IsEmpty() ) {
1062  return;
1063  }
1064 
1065  // We will need the dynamic surface created to make interactions, even if the
1066  // model itself wasn't visible. This just returns a cached value after it
1067  // has been generated once in the view.
1069  if ( model == NULL || model->NumSurfaces() <= 0 ) {
1070  return;
1071  }
1072 
1073  // the dynamic model may have changed since we built the surface list
1075  FreeSurfaces();
1076  }
1078 
1079  // actually create the interaction if needed, building light and shadow surfaces as needed
1080  if ( IsDeferred() ) {
1081  CreateInteraction( model );
1082  }
1083 
1084  R_GlobalPointToLocal( vEntity->modelMatrix, lightDef->globalLightOrigin, localLightOrigin );
1085  R_GlobalPointToLocal( vEntity->modelMatrix, tr.viewDef->renderView.vieworg, localViewOrigin );
1086 
1087  // calculate the scissor as the intersection of the light and model rects
1088  // this is used for light triangles, but not for shadow triangles
1089  lightScissor = vLight->scissorRect;
1090  lightScissor.Intersect( vEntity->scissorRect );
1091 
1092  bool lightScissorsEmpty = lightScissor.IsEmpty();
1093 
1094  // for each surface of this entity / light interaction
1095  for ( int i = 0; i < numSurfaces; i++ ) {
1096  surfaceInteraction_t *sint = &surfaces[i];
1097 
1098  // see if the base surface is visible, we may still need to add shadows even if empty
1099  if ( !lightScissorsEmpty && sint->ambientTris && sint->ambientTris->ambientViewCount == tr.viewCount ) {
1100 
1101  // make sure we have created this interaction, which may have been deferred
1102  // on a previous use that only needed the shadow
1103  if ( sint->lightTris == LIGHT_TRIS_DEFERRED ) {
1104  sint->lightTris = R_CreateLightTris( vEntity->entityDef, sint->ambientTris, vLight->lightDef, sint->shader, sint->cullInfo );
1106  }
1107 
1108  srfTriangles_t *lightTris = sint->lightTris;
1109 
1110  if ( lightTris ) {
1111 
1112  // try to cull before adding
1113  // FIXME: this may not be worthwhile. We have already done culling on the ambient,
1114  // but individual surfaces may still be cropped somewhat more
1115  if ( !R_CullLocalBox( lightTris->bounds, vEntity->modelMatrix, 5, tr.viewDef->frustum ) ) {
1116 
1117  // make sure the original surface has its ambient cache created
1118  srfTriangles_t *tri = sint->ambientTris;
1119  if ( !tri->ambientCache ) {
1120  if ( !R_CreateAmbientCache( tri, sint->shader->ReceivesLighting() ) ) {
1121  // skip if we were out of vertex memory
1122  continue;
1123  }
1124  }
1125 
1126  // reference the original surface's ambient cache
1127  lightTris->ambientCache = tri->ambientCache;
1128 
1129  // touch the ambient surface so it won't get purged
1130  vertexCache.Touch( lightTris->ambientCache );
1131 
1132  // regenerate the lighting cache (for non-vertex program cards) if it has been purged
1133  if ( !lightTris->lightingCache ) {
1134  if ( !R_CreateLightingCache( entityDef, lightDef, lightTris ) ) {
1135  // skip if we are out of vertex memory
1136  continue;
1137  }
1138  }
1139  // touch the light surface so it won't get purged
1140  // (vertex program cards won't have a light cache at all)
1141  if ( lightTris->lightingCache ) {
1142  vertexCache.Touch( lightTris->lightingCache );
1143  }
1144 
1145  if ( !lightTris->indexCache && r_useIndexBuffers.GetBool() ) {
1146  vertexCache.Alloc( lightTris->indexes, lightTris->numIndexes * sizeof( lightTris->indexes[0] ), &lightTris->indexCache, true );
1147  }
1148  if ( lightTris->indexCache ) {
1149  vertexCache.Touch( lightTris->indexCache );
1150  }
1151 
1152  // add the surface to the light list
1153 
1154  const idMaterial *shader = sint->shader;
1155  R_GlobalShaderOverride( &shader );
1156 
1157  // there will only be localSurfaces if the light casts shadows and
1158  // there are surfaces with NOSELFSHADOW
1159  if ( sint->shader->Coverage() == MC_TRANSLUCENT ) {
1160  R_LinkLightSurf( &vLight->translucentInteractions, lightTris,
1161  vEntity, lightDef, shader, lightScissor, false );
1162  } else if ( !lightDef->parms.noShadows && sint->shader->TestMaterialFlag(MF_NOSELFSHADOW) ) {
1163  R_LinkLightSurf( &vLight->localInteractions, lightTris,
1164  vEntity, lightDef, shader, lightScissor, false );
1165  } else {
1166  R_LinkLightSurf( &vLight->globalInteractions, lightTris,
1167  vEntity, lightDef, shader, lightScissor, false );
1168  }
1169  }
1170  }
1171  }
1172 
1173  srfTriangles_t *shadowTris = sint->shadowTris;
1174 
1175  // the shadows will always have to be added, unless we can tell they
1176  // are from a surface in an unconnected area
1177  if ( shadowTris ) {
1178 
1179  // check for view specific shadow suppression (player shadows, etc)
1180  if ( !r_skipSuppress.GetBool() ) {
1183  continue;
1184  }
1187  continue;
1188  }
1189  }
1190 
1191  // cull static shadows that have a non-empty bounds
1192  // dynamic shadows that use the turboshadow code will not have valid
1193  // bounds, because the perspective projection extends them to infinity
1194  if ( r_useShadowCulling.GetBool() && !shadowTris->bounds.IsCleared() ) {
1195  if ( R_CullLocalBox( shadowTris->bounds, vEntity->modelMatrix, 5, tr.viewDef->frustum ) ) {
1196  continue;
1197  }
1198  }
1199 
1200  // copy the shadow vertexes to the vertex cache if they have been purged
1201 
1202  // if we are using shared shadowVertexes and letting a vertex program fix them up,
1203  // get the shadowCache from the parent ambient surface
1204  if ( !shadowTris->shadowVertexes ) {
1205  // the data may have been purged, so get the latest from the "home position"
1206  shadowTris->shadowCache = sint->ambientTris->shadowCache;
1207  }
1208 
1209  // if we have been purged, re-upload the shadowVertexes
1210  if ( !shadowTris->shadowCache ) {
1211  if ( shadowTris->shadowVertexes ) {
1212  // each interaction has unique vertexes
1213  R_CreatePrivateShadowCache( shadowTris );
1214  } else {
1216  shadowTris->shadowCache = sint->ambientTris->shadowCache;
1217  }
1218  // if we are out of vertex cache space, skip the interaction
1219  if ( !shadowTris->shadowCache ) {
1220  continue;
1221  }
1222  }
1223 
1224  // touch the shadow surface so it won't get purged
1225  vertexCache.Touch( shadowTris->shadowCache );
1226 
1227  if ( !shadowTris->indexCache && r_useIndexBuffers.GetBool() ) {
1228  vertexCache.Alloc( shadowTris->indexes, shadowTris->numIndexes * sizeof( shadowTris->indexes[0] ), &shadowTris->indexCache, true );
1229  vertexCache.Touch( shadowTris->indexCache );
1230  }
1231 
1232  // see if we can avoid using the shadow volume caps
1233  bool inside = R_PotentiallyInsideInfiniteShadow( sint->ambientTris, localViewOrigin, localLightOrigin );
1234 
1235  if ( sint->shader->TestMaterialFlag( MF_NOSELFSHADOW ) ) {
1236  R_LinkLightSurf( &vLight->localShadows,
1237  shadowTris, vEntity, lightDef, NULL, shadowScissor, inside );
1238  } else {
1239  R_LinkLightSurf( &vLight->globalShadows,
1240  shadowTris, vEntity, lightDef, NULL, shadowScissor, inside );
1241  }
1242  }
1243  }
1244 }
1245 
1246 /*
1247 ===================
1248 R_ShowInteractionMemory_f
1249 ===================
1250 */
1252  int total = 0;
1253  int entities = 0;
1254  int interactions = 0;
1255  int deferredInteractions = 0;
1256  int emptyInteractions = 0;
1257  int lightTris = 0;
1258  int lightTriVerts = 0;
1259  int lightTriIndexes = 0;
1260  int shadowTris = 0;
1261  int shadowTriVerts = 0;
1262  int shadowTriIndexes = 0;
1263 
1264  for ( int i = 0; i < tr.primaryWorld->entityDefs.Num(); i++ ) {
1266  if ( !def ) {
1267  continue;
1268  }
1269  if ( def->firstInteraction == NULL ) {
1270  continue;
1271  }
1272  entities++;
1273 
1274  for ( idInteraction *inter = def->firstInteraction; inter != NULL; inter = inter->entityNext ) {
1275  interactions++;
1276  total += inter->MemoryUsed();
1277 
1278  if ( inter->IsDeferred() ) {
1279  deferredInteractions++;
1280  continue;
1281  }
1282  if ( inter->IsEmpty() ) {
1283  emptyInteractions++;
1284  continue;
1285  }
1286 
1287  for ( int j = 0; j < inter->numSurfaces; j++ ) {
1288  surfaceInteraction_t *srf = &inter->surfaces[j];
1289 
1290  if ( srf->lightTris && srf->lightTris != LIGHT_TRIS_DEFERRED ) {
1291  lightTris++;
1292  lightTriVerts += srf->lightTris->numVerts;
1293  lightTriIndexes += srf->lightTris->numIndexes;
1294  }
1295  if ( srf->shadowTris ) {
1296  shadowTris++;
1297  shadowTriVerts += srf->shadowTris->numVerts;
1298  shadowTriIndexes += srf->shadowTris->numIndexes;
1299  }
1300  }
1301  }
1302  }
1303 
1304  common->Printf( "%i entities with %i total interactions totalling %ik\n", entities, interactions, total / 1024 );
1305  common->Printf( "%i deferred interactions, %i empty interactions\n", deferredInteractions, emptyInteractions );
1306  common->Printf( "%5i indexes %5i verts in %5i light tris\n", lightTriIndexes, lightTriVerts, lightTris );
1307  common->Printf( "%5i indexes %5i verts in %5i shadow tris\n", shadowTriIndexes, shadowTriVerts, shadowTris );
1308 }
shadowGen_t
Definition: tr_local.h:1399
idPlane frustum[5]
Definition: tr_local.h:421
idRenderWorldLocal * world
Definition: tr_local.h:255
int numShadowIndexesNoFrontCaps
Definition: Model.h:119
bool SurfaceCastsShadow(void) const
Definition: Material.h:392
void R_CalcInteractionCullBits(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo)
Definition: Interaction.cpp:92
bool LightEffectsBackSides() const
Definition: Material.h:477
const idMaterial * lightShader
Definition: tr_local.h:213
const idMaterial * shader
Definition: Interaction.h:76
areaNumRef_t * frustumAreas
Definition: Interaction.h:157
void UnlinkAndFree(void)
byte * facing
Definition: Interaction.h:51
idVec4 colorGreen
Definition: Lib.cpp:118
idCVar r_useShadowCulling("r_useShadowCulling","1", CVAR_RENDERER|CVAR_BOOL,"try to cull shadows from partially visible lights")
void R_CreatePrivateShadowCache(srfTriangles_t *tri)
Definition: tr_light.cpp:140
const idVec3 & Normal(void) const
Definition: Plane.h:239
virtual bool IsStaticWorldModel() const =0
#define LIGHT_CULL_ALL_FRONT
Definition: Interaction.h:45
idScreenRect R_ScreenRectFromViewFrustumBounds(const idBounds &bounds)
Definition: tr_main.cpp:151
idPlane frustum[6]
Definition: tr_local.h:219
idInteraction * entityPrev
Definition: Interaction.h:111
idVec4 colorWhite
Definition: Lib.cpp:116
int numVerts
Definition: Model.h:98
struct viewEntity_s * viewEntity
Definition: tr_local.h:274
idCVar r_useIndexBuffers("r_useIndexBuffers","0", CVAR_RENDERER|CVAR_ARCHIVE|CVAR_INTEGER,"use ARB_vertex_buffer_object for indexes", 0, 1, idCmdSystem::ArgCompletion_Integer< 0, 1 >)
idInteraction * lightNext
Definition: Interaction.h:108
idCVar r_showInteractionFrustums("r_showInteractionFrustums","0", CVAR_RENDERER|CVAR_INTEGER,"1 = show a frustum for each interaction, 2 = also draw lines to light origin, 3 = also draw entity bbox", 0, 3, idCmdSystem::ArgCompletion_Integer< 0, 3 >)
bool ReceivesLighting(void) const
Definition: Material.h:401
void R_CalcInteractionFacing(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, srfCullInfo_t &cullInfo)
Definition: Interaction.cpp:55
float GetFloat(void) const
Definition: CVarSystem.h:144
idCVar r_useInteractionScissors("r_useInteractionScissors","2", CVAR_RENDERER|CVAR_INTEGER,"1 = use a custom scissor rectangle for each shadow interaction, 2 = also crop using portal scissors",-2, 2, idCmdSystem::ArgCompletion_Integer<-2, 2 >)
#define SIDE_BACK
Definition: Plane.h:48
#define MAX_WORLD_SIZE
Definition: Lib.h:100
idScreenRect & GetAreaScreenRect(int areaNum) const
#define MAX_CLIPPED_POINTS
idRenderModel * R_EntityDefDynamicModel(idRenderEntityLocal *def)
Definition: tr_light.cpp:1104
areaReference_t * entityRefs
Definition: tr_local.h:285
idScreenRect scissorRect
Definition: tr_local.h:307
bool R_GlobalShaderOverride(const idMaterial **shader)
idVec3 xyz
Definition: DrawVert.h:42
idList< idRenderEntityLocal * > entityDefs
bool HasShadows(void) const
virtual void VPCALL CmpGE(byte *dst, const float *src0, const float constant, const int count)=0
GLclampf ref
Definition: glext.h:4237
const idMaterial * shader
Definition: Model.h:146
renderLight_t parms
Definition: tr_local.h:191
bool IsDeferred(void) const
Definition: Interaction.h:136
int suppressShadowInViewID
Definition: RenderWorld.h:105
const struct drawSurf_s * localShadows
Definition: tr_local.h:332
void Union(const idScreenRect &rect)
Definition: tr_main.cpp:113
Definition: Vector.h:316
bool facePlanesCalculated
Definition: Model.h:93
performanceCounters_t pc
Definition: tr_local.h:788
srfCullInfo_t cullInfo
Definition: Interaction.h:80
silEdge_t * silEdges
Definition: Model.h:113
const struct drawSurf_s * globalInteractions
Definition: tr_local.h:333
idRenderWorldLocal * primaryWorld
Definition: tr_local.h:774
idPlane * facePlanes
Definition: Model.h:115
int ambientViewCount
Definition: Model.h:89
idRenderLightLocal * lightDef
Definition: Interaction.h:106
float modelMatrix[16]
Definition: tr_local.h:253
idRenderLightLocal * lightDef
Definition: tr_local.h:302
virtual void DebugBox(const idVec4 &color, const idBox &box, const int lifetime=0)
srfTriangles_t * R_AllocStaticTriSurf(void)
Definition: tr_trisurf.cpp:523
virtual void VPCALL Memset(void *dst, const int val, const int count)=0
idCVar r_useInteractionCulling("r_useInteractionCulling","1", CVAR_RENDERER|CVAR_BOOL,"1 = cull interactions")
int Spectrum(void) const
Definition: Material.h:541
struct vertCache_s * ambientCache
Definition: Model.h:137
int i
Definition: process.py:33
static idInteraction * AllocAndLink(idRenderEntityLocal *edef, idRenderLightLocal *ldef)
areaNumRef_t * FloodFrustumAreas(const idFrustum &frustum, areaNumRef_t *areas)
idInteraction * lightPrev
Definition: Interaction.h:109
const idMaterial * customShader
Definition: RenderWorld.h:123
idCVar r_skipSuppress("r_skipSuppress","0", CVAR_RENDERER|CVAR_BOOL,"ignore the per-view suppressions")
bool R_CullLocalBox(const idBounds &bounds, const float modelMatrix[16], int numPlanes, const idPlane *planes)
Definition: tr_main.cpp:675
byte * cullBits
Definition: Interaction.h:57
#define LIGHT_CLIP_EPSILON
Definition: Interaction.h:46
struct srfTriangles_s * ambientSurface
Definition: Model.h:130
void R_ReferenceStaticTriSurfVerts(srfTriangles_t *tri, const srfTriangles_t *reference)
Definition: tr_trisurf.cpp:636
idInteraction * lastInteraction
Definition: tr_local.h:287
idVec4 colorRed
Definition: Lib.cpp:117
bool IsEmpty() const
Definition: tr_main.cpp:142
idVec3 verts[MAX_CLIPPED_POINTS]
bool LightCastsShadows() const
Definition: Material.h:468
idBounds referenceBounds
Definition: tr_local.h:268
int suppressShadowInLightID
Definition: RenderWorld.h:109
materialCoverage_t Coverage(void) const
Definition: Material.h:428
void Unlink(void)
idScreenRect R_CalcIntersectionScissor(const idRenderLightLocal *lightDef, const idRenderEntityLocal *entityDef, const viewDef_t *viewDef)
struct areaNumRef_s * next
Definition: Interaction.h:85
idInteraction ** interactionTable
idFrustum viewFrustum
Definition: tr_local.h:422
int dynamicModelFrameCount
Definition: tr_local.h:264
idVec4 colorYellow
Definition: Lib.cpp:120
virtual void VPCALL MinMax(float &min, float &max, const float *src, const int count)=0
virtual void VPCALL CmpLT(byte *dst, const float *src0, const float constant, const int count)=0
void Clear()
Definition: tr_main.cpp:47
GLuint index
Definition: glext.h:3476
void R_CreateVertexProgramShadowCache(srfTriangles_t *tri)
Definition: tr_light.cpp:156
const GLubyte * c
Definition: glext.h:4677
Definition: Vector.h:808
idVec3 lightRadius
Definition: RenderWorld.h:178
srfTriangles_t * lightTris
Definition: Interaction.h:67
idRenderWorldLocal * world
Definition: tr_local.h:198
idBounds bounds
Definition: Model.h:87
type * Alloc(void)
Definition: Heap.h:197
renderView_t renderView
Definition: tr_local.h:370
idCommon * common
Definition: Common.cpp:206
float PlaneDistance(const idPlane &plane) const
Definition: Bounds.cpp:83
#define NULL
Definition: Lib.h:88
srfTriangles_t * geometry
Definition: Model.h:147
const idDeclSkin * customSkin
Definition: RenderWorld.h:125
void R_DeriveFacePlanes(srfTriangles_t *tri)
Definition: tr_trisurf.cpp:827
int glIndex_t
Definition: Model.h:52
const idMaterial * R_RemapShaderBySkin(const idMaterial *shader, const idDeclSkin *skin, const idMaterial *customShader)
idInteraction * firstInteraction
Definition: tr_local.h:230
int GetInteger(void) const
Definition: CVarSystem.h:143
idPlane localClipPlanes[6]
Definition: Interaction.h:60
struct areaReference_s * ownerNext
Definition: tr_local.h:144
virtual const modelSurface_t * Surface(int surfaceNum) const =0
Definition: Plane.h:71
virtual void VPCALL Dot(float *dst, const idVec3 &constant, const idVec3 *src, const int count)=0
void Intersect(const idScreenRect &rect)
Definition: tr_main.cpp:93
void R_FreeStaticTriSurf(srfTriangles_t *tri)
Definition: tr_trisurf.cpp:489
#define LIGHT_TRIS_DEFERRED
Definition: Interaction.h:44
idVec4 colorPurple
Definition: Lib.cpp:124
void AddActiveInteraction(void)
struct vertCache_s * lightingCache
Definition: Model.h:138
void Touch(vertCache_t *buffer)
const struct drawSurf_s * translucentInteractions
Definition: tr_local.h:334
shadowCache_t * shadowVertexes
Definition: Model.h:127
void R_LinkLightSurf(const drawSurf_t **link, const srfTriangles_t *tri, const viewEntity_t *space, const idRenderLightLocal *light, const idMaterial *shader, const idScreenRect &scissor, bool viewInsideShadow)
Definition: tr_light.cpp:658
idScreenRect scissorRect
Definition: tr_local.h:355
idRenderEntityLocal * entityDef
Definition: tr_local.h:348
struct vertCache_s * shadowCache
Definition: Model.h:139
idRenderModel * hModel
Definition: RenderWorld.h:81
GLubyte GLubyte GLubyte a
Definition: glext.h:4662
virtual void Printf(const char *fmt,...) id_attribute((format(printf
idCVar r_znear("r_znear","3", CVAR_RENDERER|CVAR_FLOAT,"near Z clip plane distance", 0.001f, 200.0f)
float modelMatrix[16]
Definition: tr_local.h:360
virtual idBounds Bounds(const struct renderEntity_s *ent=NULL) const =0
idBlockAlloc< areaNumRef_t, 1024 > areaNumRefAllocator
void MakeEmpty(void)
idCVar r_showInteractionScissors("r_showInteractionScissors","0", CVAR_RENDERER|CVAR_INTEGER,"1 = show screen rectangle which contains the interaction frustum, 2 = also draw construction lines", 0, 2, idCmdSystem::ArgCompletion_Integer< 0, 2 >)
srfTriangles_t * R_CreateShadowVolume(const idRenderEntityLocal *ent, const srfTriangles_t *tri, const idRenderLightLocal *light, shadowGen_t optimize, srfCullInfo_t &cullInfo)
srfTriangles_t * frustumTris
Definition: tr_local.h:221
GLubyte GLubyte b
Definition: glext.h:4662
void R_ReferenceStaticTriSurfIndexes(srfTriangles_t *tri, const srfTriangles_t *reference)
Definition: tr_trisurf.cpp:645
int numShadowIndexesNoCaps
Definition: Model.h:120
enum idInteraction::@87 frustumState
void R_GlobalPointToLocal(const float modelMatrix[16], const idVec3 &in, idVec3 &out)
Definition: tr_main.cpp:522
idVec3 vieworg
Definition: RenderWorld.h:215
idVec4 colorCyan
Definition: Lib.cpp:122
viewDef_t * viewDef
Definition: tr_local.h:786
bool ClippedProjectionBounds(const idFrustum &frustum, const idBox &clipBox, idBounds &projectionBounds) const
Definition: Frustum.cpp:2623
idRenderModel * prelightModel
Definition: RenderWorld.h:194
void R_ReallyFreeStaticTriSurf(srfTriangles_t *tri)
Definition: tr_trisurf.cpp:374
int dynamicModelFrameCount
Definition: Interaction.h:159
bool GetBool(void) const
Definition: CVarSystem.h:142
const struct drawSurf_s * globalShadows
Definition: tr_local.h:330
GLint GLint i2
Definition: qgl.h:261
void * R_ClearedStaticAlloc(int bytes)
Definition: tr_main.cpp:322
surfaceInteraction_t * surfaces
Definition: Interaction.h:102
bool IsCleared(void) const
Definition: Bounds.h:222
GLuint in
Definition: glext.h:5388
const struct drawSurf_s * localInteractions
Definition: tr_local.h:331
idScreenRect CalcInteractionScissorRectangle(const idFrustum &viewFrustum)
int Num(void) const
Definition: List.h:265
void Alloc(void *data, int bytes, vertCache_t **buffer, bool indexBuffer=false)
unsigned char byte
Definition: Lib.h:75
void * R_StaticAlloc(int bytes)
Definition: tr_main.cpp:301
bool CullInteractionByViewFrustum(const idFrustum &viewFrustum)
int MemoryUsed(void)
idInteraction * lastInteraction
Definition: tr_local.h:231
idInteraction * entityNext
Definition: Interaction.h:110
bool IntersectsFrustum(const idFrustum &frustum) const
Definition: Frustum.cpp:1055
bool R_CreateAmbientCache(srfTriangles_t *tri, bool needsLighting)
Definition: tr_light.cpp:52
entity_t entities
Definition: EditorMap.cpp:47
srfTriangles_t * ambientTris
Definition: Interaction.h:74
bool ReceivesLightingOnBackSides(void) const
Definition: Material.h:405
int suppressSurfaceInViewID
Definition: RenderWorld.h:104
GLint i1
Definition: qgl.h:261
void R_FreeInteractionCullInfo(srfCullInfo_t &cullInfo)
void R_ShowInteractionMemory_f(const idCmdArgs &args)
glIndex_t * indexes
Definition: Model.h:102
bool TestMaterialFlag(const int flag) const
Definition: Material.h:494
idVertexCache vertexCache
Definition: VertexCache.cpp:41
idRenderSystemLocal tr
void Free(type *element)
Definition: Heap.h:216
void R_AllocStaticTriSurfIndexes(srfTriangles_t *tri, int numIndexes)
Definition: tr_trisurf.cpp:565
idCVar r_usePreciseTriangleInteractions("r_usePreciseTriangleInteractions","0", CVAR_RENDERER|CVAR_BOOL,"1 = do winding clipping to determine if each ambiguous tri should be lit")
GLint j
Definition: qgl.h:264
float dot(float a[], float b[])
Definition: Model_lwo.cpp:3883
srfTriangles_t * shadowTris
Definition: Interaction.h:70
void FreeSurfaces(void)
int numIndexes
Definition: Model.h:101
idInteraction * firstInteraction
Definition: tr_local.h:286
idRenderWorldLocal * renderWorld
Definition: tr_local.h:375
struct vertCache_s * indexCache
Definition: Model.h:136
void R_StaticFree(void *data)
Definition: tr_main.cpp:335
void R_ResizeStaticTriSurfIndexes(srfTriangles_t *tri, int numIndexes)
Definition: tr_trisurf.cpp:610
renderEntity_t parms
Definition: tr_local.h:251
virtual void Error(const char *fmt,...) id_attribute((format(printf
GLfloat GLfloat p
Definition: glext.h:4674
idRenderEntityLocal * entityDef
Definition: Interaction.h:105
int R_TriSurfMemory(const srfTriangles_t *tri)
Definition: tr_trisurf.cpp:290
#define SIDE_FRONT
Definition: Plane.h:47
idCVar r_useOptimizedShadows("r_useOptimizedShadows","1", CVAR_RENDERER|CVAR_BOOL,"use the dmap generated static shadow volumes")
idVec4 colorMagenta
Definition: Lib.cpp:121
bool ContainsPoint(const idVec3 &p) const
Definition: Bounds.h:353
void R_ShowColoredScreenRect(const idScreenRect &rect, int colorIndex)
Definition: tr_main.cpp:172
idCVar r_lightAllBackFaces("r_lightAllBackFaces","0", CVAR_RENDERER|CVAR_BOOL,"light all the back faces, even when they would be shadowed")
idBlockAlloc< idInteraction, 256 > interactionAllocator
void R_GlobalPlaneToLocal(const float modelMatrix[16], const idPlane &in, idPlane &out)
Definition: tr_main.cpp:547
Definition: Box.h:40
idDrawVert * verts
Definition: Model.h:99
idVec4 colorBlue
Definition: Lib.cpp:119
void CreateInteraction(const idRenderModel *model)
struct viewLight_s * viewLight
Definition: tr_local.h:227
virtual void DebugFrustum(const idVec4 &color, const idFrustum &frustum, const bool showFromOrigin=false, const int lifetime=0)
bool R_CreateLightingCache(const idRenderEntityLocal *ent, const idRenderLightLocal *light, srfTriangles_t *tri)
Definition: tr_light.cpp:75
size_t MemoryUsed(void) const
Definition: List.h:252
idVec3 globalLightOrigin
Definition: tr_local.h:216
idSIMDProcessor * SIMDProcessor
Definition: Simd.cpp:43
virtual int NumSurfaces() const =0