doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RenderWorld.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 R_ListRenderLightDefs_f
37 ===================
38 */
39 void R_ListRenderLightDefs_f( const idCmdArgs &args ) {
40  int i;
41  idRenderLightLocal *ldef;
42 
43  if ( !tr.primaryWorld ) {
44  return;
45  }
46  int active = 0;
47  int totalRef = 0;
48  int totalIntr = 0;
49 
50  for ( i = 0 ; i < tr.primaryWorld->lightDefs.Num() ; i++ ) {
51  ldef = tr.primaryWorld->lightDefs[i];
52  if ( !ldef ) {
53  common->Printf( "%4i: FREED\n", i );
54  continue;
55  }
56 
57  // count up the interactions
58  int iCount = 0;
59  for ( idInteraction *inter = ldef->firstInteraction; inter != NULL; inter = inter->lightNext ) {
60  iCount++;
61  }
62  totalIntr += iCount;
63 
64  // count up the references
65  int rCount = 0;
66  for ( areaReference_t *ref = ldef->references ; ref ; ref = ref->ownerNext ) {
67  rCount++;
68  }
69  totalRef += rCount;
70 
71  common->Printf( "%4i: %3i intr %2i refs %s\n", i, iCount, rCount, ldef->lightShader->GetName());
72  active++;
73  }
74 
75  common->Printf( "%i lightDefs, %i interactions, %i areaRefs\n", active, totalIntr, totalRef );
76 }
77 
78 /*
79 ===================
80 R_ListRenderEntityDefs_f
81 ===================
82 */
83 void R_ListRenderEntityDefs_f( const idCmdArgs &args ) {
84  int i;
85  idRenderEntityLocal *mdef;
86 
87  if ( !tr.primaryWorld ) {
88  return;
89  }
90  int active = 0;
91  int totalRef = 0;
92  int totalIntr = 0;
93 
94  for ( i = 0 ; i < tr.primaryWorld->entityDefs.Num() ; i++ ) {
95  mdef = tr.primaryWorld->entityDefs[i];
96  if ( !mdef ) {
97  common->Printf( "%4i: FREED\n", i );
98  continue;
99  }
100 
101  // count up the interactions
102  int iCount = 0;
103  for ( idInteraction *inter = mdef->firstInteraction; inter != NULL; inter = inter->entityNext ) {
104  iCount++;
105  }
106  totalIntr += iCount;
107 
108  // count up the references
109  int rCount = 0;
110  for ( areaReference_t *ref = mdef->entityRefs ; ref ; ref = ref->ownerNext ) {
111  rCount++;
112  }
113  totalRef += rCount;
114 
115  common->Printf( "%4i: %3i intr %2i refs %s\n", i, iCount, rCount, mdef->parms.hModel->Name());
116  active++;
117  }
118 
119  common->Printf( "total active: %i\n", active );
120 }
121 
122 /*
123 ===================
124 idRenderWorldLocal::idRenderWorldLocal
125 ===================
126 */
128  mapName.Clear();
129  mapTimeStamp = FILE_NOT_FOUND_TIMESTAMP;
130 
132 
133  areaNodes = NULL;
134  numAreaNodes = 0;
135 
136  portalAreas = NULL;
137  numPortalAreas = 0;
138 
141 
142  interactionTable = 0;
145 }
146 
147 /*
148 ===================
149 idRenderWorldLocal::~idRenderWorldLocal
150 ===================
151 */
153  // free all the entityDefs, lightDefs, portals, etc
154  FreeWorld();
155 
156  // free up the debug lines, polys, and text
158  RB_ClearDebugLines( 0 );
159  RB_ClearDebugText( 0 );
160 }
161 
162 /*
163 ===================
164 ResizeInteractionTable
165 ===================
166 */
168  // we overflowed the interaction table, so dump it
169  // we may want to resize this in the future if it turns out to be common
170  common->Printf( "idRenderWorldLocal::ResizeInteractionTable: overflowed interactionTableWidth, dumping\n" );
173 }
174 
175 /*
176 ===================
177 AddEntityDef
178 ===================
179 */
181  // try and reuse a free spot
182  int entityHandle = entityDefs.FindNull();
183  if ( entityHandle == -1 ) {
184  entityHandle = entityDefs.Append( NULL );
187  }
188  }
189 
190  UpdateEntityDef( entityHandle, re );
191 
192  return entityHandle;
193 }
194 
195 /*
196 ==============
197 UpdateEntityDef
198 
199 Does not write to the demo file, which will only be updated for
200 visible entities
201 ==============
202 */
204 
206  if ( r_skipUpdates.GetBool() ) {
207  return;
208  }
209 
211 
212  if ( !re->hModel && !re->callback ) {
213  common->Error( "idRenderWorld::UpdateEntityDef: NULL hModel" );
214  }
215 
216  // create new slots if needed
217  if ( entityHandle < 0 || entityHandle > LUDICROUS_INDEX ) {
218  common->Error( "idRenderWorld::UpdateEntityDef: index = %i", entityHandle );
219  }
220  while ( entityHandle >= entityDefs.Num() ) {
222  }
223 
224  idRenderEntityLocal *def = entityDefs[entityHandle];
225  if ( def ) {
226 
227  if ( !re->forceUpdate ) {
228 
229  // check for exact match (OPTIMIZE: check through pointers more)
230  if ( !re->joints && !re->callbackData && !def->dynamicModel && !memcmp( re, &def->parms, sizeof( *re ) ) ) {
231  return;
232  }
233 
234  // if the only thing that changed was shaderparms, we can just leave things as they are
235  // after updating parms
236 
237  // if we have a callback function and the bounds, origin, axis and model match,
238  // then we can leave the references as they are
239  if ( re->callback ) {
240 
241  bool axisMatch = ( re->axis == def->parms.axis );
242  bool originMatch = ( re->origin == def->parms.origin );
243  bool boundsMatch = ( re->bounds == def->referenceBounds );
244  bool modelMatch = ( re->hModel == def->parms.hModel );
245 
246  if ( boundsMatch && originMatch && axisMatch && modelMatch ) {
247  // only clear the dynamic model and interaction surfaces if they exist
250  def->parms = *re;
251  return;
252  }
253  }
254  }
255 
256  // save any decals if the model is the same, allowing marks to move with entities
257  if ( def->parms.hModel == re->hModel ) {
258  R_FreeEntityDefDerivedData( def, true, true );
259  } else {
260  R_FreeEntityDefDerivedData( def, false, false );
261  }
262  } else {
263  // creating a new one
264  def = new idRenderEntityLocal;
265  entityDefs[entityHandle] = def;
266 
267  def->world = this;
268  def->index = entityHandle;
269  }
270 
271  def->parms = *re;
272 
274 
276  if ( session->writeDemo && def->archived ) {
277  WriteFreeEntity( entityHandle );
278  def->archived = false;
279  }
280 
281  // optionally immediately issue any callbacks
282  if ( !r_useEntityCallbacks.GetBool() && def->parms.callback ) {
284  }
285 
286  // based on the model bounds, add references in each area
287  // that may contain the updated surface
288  R_CreateEntityRefs( def );
289 }
290 
291 /*
292 ===================
293 FreeEntityDef
294 
295 Frees all references and lit surfaces from the model, and
296 NULL's out it's entry in the world list
297 ===================
298 */
300  idRenderEntityLocal *def;
301 
302  if ( entityHandle < 0 || entityHandle >= entityDefs.Num() ) {
303  common->Printf( "idRenderWorld::FreeEntityDef: handle %i > %i\n", entityHandle, entityDefs.Num() );
304  return;
305  }
306 
307  def = entityDefs[entityHandle];
308  if ( !def ) {
309  common->Printf( "idRenderWorld::FreeEntityDef: handle %i is NULL\n", entityHandle );
310  return;
311  }
312 
313  R_FreeEntityDefDerivedData( def, false, false );
314 
315  if ( session->writeDemo && def->archived ) {
316  WriteFreeEntity( entityHandle );
317  }
318 
319  // if we are playing a demo, these will have been freed
320  // in R_FreeEntityDefDerivedData(), otherwise the gui
321  // object still exists in the game
322 
323  def->parms.gui[ 0 ] = NULL;
324  def->parms.gui[ 1 ] = NULL;
325  def->parms.gui[ 2 ] = NULL;
326 
327  delete def;
328  entityDefs[ entityHandle ] = NULL;
329 }
330 
331 /*
332 ==================
333 GetRenderEntity
334 ==================
335 */
337  idRenderEntityLocal *def;
338 
339  if ( entityHandle < 0 || entityHandle >= entityDefs.Num() ) {
340  common->Printf( "idRenderWorld::GetRenderEntity: invalid handle %i [0, %i]\n", entityHandle, entityDefs.Num() );
341  return NULL;
342  }
343 
344  def = entityDefs[entityHandle];
345  if ( !def ) {
346  common->Printf( "idRenderWorld::GetRenderEntity: handle %i is NULL\n", entityHandle );
347  return NULL;
348  }
349 
350  return &def->parms;
351 }
352 
353 /*
354 ==================
355 AddLightDef
356 ==================
357 */
359  // try and reuse a free spot
360  int lightHandle = lightDefs.FindNull();
361 
362  if ( lightHandle == -1 ) {
363  lightHandle = lightDefs.Append( NULL );
366  }
367  }
368  UpdateLightDef( lightHandle, rlight );
369 
370  return lightHandle;
371 }
372 
373 /*
374 =================
375 UpdateLightDef
376 
377 The generation of all the derived interaction data will
378 usually be deferred until it is visible in a scene
379 
380 Does not write to the demo file, which will only be done for visible lights
381 =================
382 */
383 void idRenderWorldLocal::UpdateLightDef( qhandle_t lightHandle, const renderLight_t *rlight ) {
384  if ( r_skipUpdates.GetBool() ) {
385  return;
386  }
387 
388  tr.pc.c_lightUpdates++;
389 
390  // create new slots if needed
391  if ( lightHandle < 0 || lightHandle > LUDICROUS_INDEX ) {
392  common->Error( "idRenderWorld::UpdateLightDef: index = %i", lightHandle );
393  }
394  while ( lightHandle >= lightDefs.Num() ) {
395  lightDefs.Append( NULL );
396  }
397 
398  bool justUpdate = false;
399  idRenderLightLocal *light = lightDefs[lightHandle];
400  if ( light ) {
401  // if the shape of the light stays the same, we don't need to dump
402  // any of our derived data, because shader parms are calculated every frame
403  if ( rlight->axis == light->parms.axis && rlight->end == light->parms.end &&
404  rlight->lightCenter == light->parms.lightCenter && rlight->lightRadius == light->parms.lightRadius &&
405  rlight->noShadows == light->parms.noShadows && rlight->origin == light->parms.origin &&
406  rlight->parallel == light->parms.parallel && rlight->pointLight == light->parms.pointLight &&
407  rlight->right == light->parms.right && rlight->start == light->parms.start &&
408  rlight->target == light->parms.target && rlight->up == light->parms.up &&
409  rlight->shader == light->lightShader && rlight->prelightModel == light->parms.prelightModel ) {
410  justUpdate = true;
411  } else {
412  // if we are updating shadows, the prelight model is no longer valid
413  light->lightHasMoved = true;
414  R_FreeLightDefDerivedData( light );
415  }
416  } else {
417  // create a new one
418  light = new idRenderLightLocal;
419  lightDefs[lightHandle] = light;
420 
421  light->world = this;
422  light->index = lightHandle;
423  }
424 
425  light->parms = *rlight;
427  if ( session->writeDemo && light->archived ) {
428  WriteFreeLight( lightHandle );
429  light->archived = false;
430  }
431 
432  if ( light->lightHasMoved ) {
433  light->parms.prelightModel = NULL;
434  }
435 
436  if (!justUpdate) {
437  R_DeriveLightData( light );
438  R_CreateLightRefs( light );
440  }
441 }
442 
443 /*
444 ====================
445 FreeLightDef
446 
447 Frees all references and lit surfaces from the light, and
448 NULL's out it's entry in the world list
449 ====================
450 */
452  idRenderLightLocal *light;
453 
454  if ( lightHandle < 0 || lightHandle >= lightDefs.Num() ) {
455  common->Printf( "idRenderWorld::FreeLightDef: invalid handle %i [0, %i]\n", lightHandle, lightDefs.Num() );
456  return;
457  }
458 
459  light = lightDefs[lightHandle];
460  if ( !light ) {
461  common->Printf( "idRenderWorld::FreeLightDef: handle %i is NULL\n", lightHandle );
462  return;
463  }
464 
465  R_FreeLightDefDerivedData( light );
466 
467  if ( session->writeDemo && light->archived ) {
468  WriteFreeLight( lightHandle );
469  }
470 
471  delete light;
472  lightDefs[lightHandle] = NULL;
473 }
474 
475 /*
476 ==================
477 GetRenderLight
478 ==================
479 */
481  idRenderLightLocal *def;
482 
483  if ( lightHandle < 0 || lightHandle >= lightDefs.Num() ) {
484  common->Printf( "idRenderWorld::GetRenderLight: handle %i > %i\n", lightHandle, lightDefs.Num() );
485  return NULL;
486  }
487 
488  def = lightDefs[lightHandle];
489  if ( !def ) {
490  common->Printf( "idRenderWorld::GetRenderLight: handle %i is NULL\n", lightHandle );
491  return NULL;
492  }
493 
494  return &def->parms;
495 }
496 
497 /*
498 ================
499 idRenderWorldLocal::ProjectDecalOntoWorld
500 ================
501 */
502 void idRenderWorldLocal::ProjectDecalOntoWorld( const idFixedWinding &winding, const idVec3 &projectionOrigin, const bool parallel, const float fadeDepth, const idMaterial *material, const int startTime ) {
503  int i, areas[10], numAreas;
504  const areaReference_t *ref;
505  const portalArea_t *area;
506  const idRenderModel *model;
507  idRenderEntityLocal *def;
508  decalProjectionInfo_t info, localInfo;
509 
510  if ( !idRenderModelDecal::CreateProjectionInfo( info, winding, projectionOrigin, parallel, fadeDepth, material, startTime ) ) {
511  return;
512  }
513 
514  // get the world areas touched by the projection volume
515  numAreas = BoundsInAreas( info.projectionBounds, areas, 10 );
516 
517  // check all areas for models
518  for ( i = 0; i < numAreas; i++ ) {
519 
520  area = &portalAreas[ areas[i] ];
521 
522  // check all models in this area
523  for ( ref = area->entityRefs.areaNext; ref != &area->entityRefs; ref = ref->areaNext ) {
524  def = ref->entity;
525 
526  // completely ignore any dynamic or callback models
527  model = def->parms.hModel;
528  if ( model == NULL || model->IsDynamicModel() != DM_STATIC || def->parms.callback ) {
529  continue;
530  }
531 
532  if ( def->parms.customShader != NULL && !def->parms.customShader->AllowOverlays() ) {
533  continue;
534  }
535 
536  idBounds bounds;
537  bounds.FromTransformedBounds( model->Bounds( &def->parms ), def->parms.origin, def->parms.axis );
538 
539  // if the model bounds do not overlap with the projection bounds
540  if ( !info.projectionBounds.IntersectsBounds( bounds ) ) {
541  continue;
542  }
543 
544  // transform the bounding planes, fade planes and texture axis into local space
546  localInfo.force = ( def->parms.customShader != NULL );
547 
548  if ( !def->decals ) {
550  }
551  def->decals->CreateDecal( model, localInfo );
552  }
553  }
554 }
555 
556 /*
557 ====================
558 idRenderWorldLocal::ProjectDecal
559 ====================
560 */
561 void idRenderWorldLocal::ProjectDecal( qhandle_t entityHandle, const idFixedWinding &winding, const idVec3 &projectionOrigin, const bool parallel, const float fadeDepth, const idMaterial *material, const int startTime ) {
562  decalProjectionInfo_t info, localInfo;
563 
564  if ( entityHandle < 0 || entityHandle >= entityDefs.Num() ) {
565  common->Error( "idRenderWorld::ProjectOverlay: index = %i", entityHandle );
566  return;
567  }
568 
569  idRenderEntityLocal *def = entityDefs[ entityHandle ];
570  if ( !def ) {
571  return;
572  }
573 
574  const idRenderModel *model = def->parms.hModel;
575 
576  if ( model == NULL || model->IsDynamicModel() != DM_STATIC || def->parms.callback ) {
577  return;
578  }
579 
580  if ( !idRenderModelDecal::CreateProjectionInfo( info, winding, projectionOrigin, parallel, fadeDepth, material, startTime ) ) {
581  return;
582  }
583 
584  idBounds bounds;
585  bounds.FromTransformedBounds( model->Bounds( &def->parms ), def->parms.origin, def->parms.axis );
586 
587  // if the model bounds do not overlap with the projection bounds
588  if ( !info.projectionBounds.IntersectsBounds( bounds ) ) {
589  return;
590  }
591 
592  // transform the bounding planes, fade planes and texture axis into local space
594  localInfo.force = ( def->parms.customShader != NULL );
595 
596  if ( def->decals == NULL ) {
598  }
599  def->decals->CreateDecal( model, localInfo );
600 }
601 
602 /*
603 ====================
604 idRenderWorldLocal::ProjectOverlay
605 ====================
606 */
607 void idRenderWorldLocal::ProjectOverlay( qhandle_t entityHandle, const idPlane localTextureAxis[2], const idMaterial *material ) {
608 
609  if ( entityHandle < 0 || entityHandle >= entityDefs.Num() ) {
610  common->Error( "idRenderWorld::ProjectOverlay: index = %i", entityHandle );
611  return;
612  }
613 
614  idRenderEntityLocal *def = entityDefs[ entityHandle ];
615  if ( !def ) {
616  return;
617  }
618 
619  const renderEntity_t *refEnt = &def->parms;
620 
621  idRenderModel *model = refEnt->hModel;
622  if ( model->IsDynamicModel() != DM_CACHED ) { // FIXME: probably should be MD5 only
623  return;
624  }
625  model = R_EntityDefDynamicModel( def );
626 
627  if ( def->overlay == NULL ) {
629  }
630  def->overlay->CreateOverlay( model, localTextureAxis, material );
631 }
632 
633 /*
634 ====================
635 idRenderWorldLocal::RemoveDecals
636 ====================
637 */
639  if ( entityHandle < 0 || entityHandle >= entityDefs.Num() ) {
640  common->Error( "idRenderWorld::ProjectOverlay: index = %i", entityHandle );
641  return;
642  }
643 
644  idRenderEntityLocal *def = entityDefs[ entityHandle ];
645  if ( !def ) {
646  return;
647  }
648 
649  R_FreeEntityDefDecals( def );
650  R_FreeEntityDefOverlay( def );
651 }
652 
653 /*
654 ====================
655 SetRenderView
656 
657 Sets the current view so any calls to the render world will use the correct parms.
658 ====================
659 */
661  tr.primaryRenderView = *renderView;
662 }
663 
664 /*
665 ====================
666 RenderScene
667 
668 Draw a 3D view into a part of the window, then return
669 to 2D drawing.
670 
671 Rendering a scene may require multiple views to be rendered
672 to handle mirrors,
673 ====================
674 */
676 #ifndef ID_DEDICATED
677  renderView_t copy;
678 
679  if ( !glConfig.isInitialized ) {
680  return;
681  }
682 
683  copy = *renderView;
684 
685  // skip front end rendering work, which will result
686  // in only gui drawing
687  if ( r_skipFrontEnd.GetBool() ) {
688  return;
689  }
690 
691  if ( renderView->fov_x <= 0 || renderView->fov_y <= 0 ) {
692  common->Error( "idRenderWorld::RenderScene: bad FOVs: %f, %f", renderView->fov_x, renderView->fov_y );
693  }
694 
695  // close any gui drawing
697  tr.guiModel->Clear();
698 
699  int startTime = Sys_Milliseconds();
700 
701  // setup view parms for the initial view
702  //
703  viewDef_t *parms = (viewDef_t *)R_ClearedFrameAlloc( sizeof( *parms ) );
704  parms->renderView = *renderView;
705 
706  if ( tr.takingScreenshot ) {
707  parms->renderView.forceUpdate = true;
708  }
709 
710  // set up viewport, adjusted for resolution and OpenGL style 0 at the bottom
711  tr.RenderViewToViewport( &parms->renderView, &parms->viewport );
712 
713  // the scissor bounds may be shrunk in subviews even if
714  // the viewport stays the same
715  // this scissor range is local inside the viewport
716  parms->scissor.x1 = 0;
717  parms->scissor.y1 = 0;
718  parms->scissor.x2 = parms->viewport.x2 - parms->viewport.x1;
719  parms->scissor.y2 = parms->viewport.y2 - parms->viewport.y1;
720 
721 
722  parms->isSubview = false;
723  parms->initialViewAreaOrigin = renderView->vieworg;
724  parms->floatTime = parms->renderView.time * 0.001f;
725  parms->renderWorld = this;
726 
727  // use this time for any subsequent 2D rendering, so damage blobs/etc
728  // can use level time
729  tr.frameShaderTime = parms->floatTime;
730 
731  // see if the view needs to reverse the culling sense in mirrors
732  // or environment cube sides
733  idVec3 cross;
734  cross = parms->renderView.viewaxis[1].Cross( parms->renderView.viewaxis[2] );
735  if ( cross * parms->renderView.viewaxis[0] > 0 ) {
736  parms->isMirror = false;
737  } else {
738  parms->isMirror = true;
739  }
740 
741  if ( r_lockSurfaces.GetBool() ) {
742  R_LockSurfaceScene( parms );
743  return;
744  }
745 
746  // save this world for use by some console commands
747  tr.primaryWorld = this;
748  tr.primaryRenderView = *renderView;
749  tr.primaryView = parms;
750 
751  // rendering this view may cause other views to be rendered
752  // for mirrors / portals / shadows / environment maps
753  // this will also cause any necessary entities and lights to be
754  // updated to the demo file
755  R_RenderView( parms );
756 
757  // now write delete commands for any modified-but-not-visible entities, and
758  // add the renderView command to the demo
759  if ( session->writeDemo ) {
760  WriteRenderView( renderView );
761  }
762 
763 #if 0
764  for ( int i = 0 ; i < entityDefs.Num() ; i++ ) {
766  if ( !def ) {
767  continue;
768  }
769  if ( def->parms.callback ) {
770  continue;
771  }
772  if ( def->parms.hModel->IsDynamicModel() == DM_CONTINUOUS ) {
773  }
774  }
775 #endif
776 
777  int endTime = Sys_Milliseconds();
778 
779  tr.pc.frontEndMsec += endTime - startTime;
780 
781  // prepare for any 2D drawing after this
782  tr.guiModel->Clear();
783 #endif
784 }
785 
786 /*
787 ===================
788 NumAreas
789 ===================
790 */
791 int idRenderWorldLocal::NumAreas( void ) const {
792  return numPortalAreas;
793 }
794 
795 /*
796 ===================
797 NumPortalsInArea
798 ===================
799 */
801  portalArea_t *area;
802  int count;
803  portal_t *portal;
804 
805  if ( areaNum >= numPortalAreas || areaNum < 0 ) {
806  common->Error( "idRenderWorld::NumPortalsInArea: bad areanum %i", areaNum );
807  }
808  area = &portalAreas[areaNum];
809 
810  count = 0;
811  for ( portal = area->portals ; portal ; portal = portal->next ) {
812  count++;
813  }
814  return count;
815 }
816 
817 /*
818 ===================
819 GetPortal
820 ===================
821 */
822 exitPortal_t idRenderWorldLocal::GetPortal( int areaNum, int portalNum ) {
823  portalArea_t *area;
824  int count;
825  portal_t *portal;
826  exitPortal_t ret;
827 
828  if ( areaNum > numPortalAreas ) {
829  common->Error( "idRenderWorld::GetPortal: areaNum > numAreas" );
830  }
831  area = &portalAreas[areaNum];
832 
833  count = 0;
834  for ( portal = area->portals ; portal ; portal = portal->next ) {
835  if ( count == portalNum ) {
836  ret.areas[0] = areaNum;
837  ret.areas[1] = portal->intoArea;
838  ret.w = portal->w;
839  ret.blockingBits = portal->doublePortal->blockingBits;
840  ret.portalHandle = portal->doublePortal - doublePortals + 1;
841  return ret;
842  }
843  count++;
844  }
845 
846  common->Error( "idRenderWorld::GetPortal: portalNum > numPortals" );
847 
848  memset( &ret, 0, sizeof( ret ) );
849  return ret;
850 }
851 
852 /*
853 ===============
854 PointInAreaNum
855 
856 Will return -1 if the point is not in an area, otherwise
857 it will return 0 <= value < tr.world->numPortalAreas
858 ===============
859 */
860 int idRenderWorldLocal::PointInArea( const idVec3 &point ) const {
861  areaNode_t *node;
862  int nodeNum;
863  float d;
864 
865  node = areaNodes;
866  if ( !node ) {
867  return -1;
868  }
869  while( 1 ) {
870  d = point * node->plane.Normal() + node->plane[3];
871  if (d > 0) {
872  nodeNum = node->children[0];
873  } else {
874  nodeNum = node->children[1];
875  }
876  if ( nodeNum == 0 ) {
877  return -1; // in solid
878  }
879  if ( nodeNum < 0 ) {
880  nodeNum = -1 - nodeNum;
881  if ( nodeNum >= numPortalAreas ) {
882  common->Error( "idRenderWorld::PointInArea: area out of range" );
883  }
884  return nodeNum;
885  }
886  node = areaNodes + nodeNum;
887  }
888 
889  return -1;
890 }
891 
892 /*
893 ===================
894 BoundsInAreas_r
895 ===================
896 */
897 void idRenderWorldLocal::BoundsInAreas_r( int nodeNum, const idBounds &bounds, int *areas, int *numAreas, int maxAreas ) const {
898  int side, i;
899  areaNode_t *node;
900 
901  do {
902  if ( nodeNum < 0 ) {
903  nodeNum = -1 - nodeNum;
904 
905  for ( i = 0; i < (*numAreas); i++ ) {
906  if ( areas[i] == nodeNum ) {
907  break;
908  }
909  }
910  if ( i >= (*numAreas) && (*numAreas) < maxAreas ) {
911  areas[(*numAreas)++] = nodeNum;
912  }
913  return;
914  }
915 
916  node = areaNodes + nodeNum;
917 
918  side = bounds.PlaneSide( node->plane );
919  if ( side == PLANESIDE_FRONT ) {
920  nodeNum = node->children[0];
921  }
922  else if ( side == PLANESIDE_BACK ) {
923  nodeNum = node->children[1];
924  }
925  else {
926  if ( node->children[1] != 0 ) {
927  BoundsInAreas_r( node->children[1], bounds, areas, numAreas, maxAreas );
928  if ( (*numAreas) >= maxAreas ) {
929  return;
930  }
931  }
932  nodeNum = node->children[0];
933  }
934  } while( nodeNum != 0 );
935 
936  return;
937 }
938 
939 /*
940 ===================
941 BoundsInAreas
942 
943  fills the *areas array with the number of the areas the bounds are in
944  returns the total number of areas the bounds are in
945 ===================
946 */
947 int idRenderWorldLocal::BoundsInAreas( const idBounds &bounds, int *areas, int maxAreas ) const {
948  int numAreas = 0;
949 
950  assert( areas );
951  assert( bounds[0][0] <= bounds[1][0] && bounds[0][1] <= bounds[1][1] && bounds[0][2] <= bounds[1][2] );
952  assert( bounds[1][0] - bounds[0][0] < 1e4f && bounds[1][1] - bounds[0][1] < 1e4f && bounds[1][2] - bounds[0][2] < 1e4f );
953 
954  if ( !areaNodes ) {
955  return numAreas;
956  }
957  BoundsInAreas_r( 0, bounds, areas, &numAreas, maxAreas );
958  return numAreas;
959 }
960 
961 /*
962 ================
963 GuiTrace
964 
965 checks a ray trace against any gui surfaces in an entity, returning the
966 fraction location of the trace on the gui surface, or -1,-1 if no hit.
967 this doesn't do any occlusion testing, simply ignoring non-gui surfaces.
968 start / end are in global world coordinates.
969 ================
970 */
972  localTrace_t local;
973  idVec3 localStart, localEnd, bestPoint;
974  int j;
975  idRenderModel *model;
976  srfTriangles_t *tri;
977  const idMaterial *shader;
978  guiPoint_t pt;
979 
980  pt.x = pt.y = -1;
981  pt.guiId = 0;
982 
983  if ( ( entityHandle < 0 ) || ( entityHandle >= entityDefs.Num() ) ) {
984  common->Printf( "idRenderWorld::GuiTrace: invalid handle %i\n", entityHandle );
985  return pt;
986  }
987 
988  idRenderEntityLocal *def = entityDefs[entityHandle];
989  if ( !def ) {
990  common->Printf( "idRenderWorld::GuiTrace: handle %i is NULL\n", entityHandle );
991  return pt;
992  }
993 
994  model = def->parms.hModel;
995  if ( def->parms.callback || !def->parms.hModel || def->parms.hModel->IsDynamicModel() != DM_STATIC ) {
996  return pt;
997  }
998 
999  // transform the points into local space
1000  R_GlobalPointToLocal( def->modelMatrix, start, localStart );
1001  R_GlobalPointToLocal( def->modelMatrix, end, localEnd );
1002 
1003 
1004  float best = 99999.0;
1005  const modelSurface_t *bestSurf = NULL;
1006 
1007  for ( j = 0 ; j < model->NumSurfaces() ; j++ ) {
1008  const modelSurface_t *surf = model->Surface( j );
1009 
1010  tri = surf->geometry;
1011  if ( !tri ) {
1012  continue;
1013  }
1014 
1015  shader = R_RemapShaderBySkin( surf->shader, def->parms.customSkin, def->parms.customShader );
1016  if ( !shader ) {
1017  continue;
1018  }
1019  // only trace against gui surfaces
1020  if (!shader->HasGui()) {
1021  continue;
1022  }
1023 
1024  local = R_LocalTrace( localStart, localEnd, 0.0f, tri );
1025  if ( local.fraction < 1.0 ) {
1026  idVec3 origin, axis[3];
1027  idVec3 cursor;
1028  float axisLen[2];
1029 
1030  R_SurfaceToTextureAxis( tri, origin, axis );
1031  cursor = local.point - origin;
1032 
1033  axisLen[0] = axis[0].Length();
1034  axisLen[1] = axis[1].Length();
1035 
1036  pt.x = ( cursor * axis[0] ) / ( axisLen[0] * axisLen[0] );
1037  pt.y = ( cursor * axis[1] ) / ( axisLen[1] * axisLen[1] );
1038  pt.guiId = shader->GetEntityGui();
1039 
1040  return pt;
1041  }
1042  }
1043 
1044  return pt;
1045 }
1046 
1047 /*
1048 ===================
1049 idRenderWorldLocal::ModelTrace
1050 ===================
1051 */
1052 bool idRenderWorldLocal::ModelTrace( modelTrace_t &trace, qhandle_t entityHandle, const idVec3 &start, const idVec3 &end, const float radius ) const {
1053  int i;
1054  bool collisionSurface;
1055  const modelSurface_t *surf;
1056  localTrace_t localTrace;
1057  idRenderModel *model;
1058  float modelMatrix[16];
1059  idVec3 localStart, localEnd;
1060  const idMaterial *shader;
1061 
1062  trace.fraction = 1.0f;
1063 
1064  if ( entityHandle < 0 || entityHandle >= entityDefs.Num() ) {
1065 // common->Error( "idRenderWorld::ModelTrace: index = %i", entityHandle );
1066  return false;
1067  }
1068 
1069  idRenderEntityLocal *def = entityDefs[entityHandle];
1070  if ( !def ) {
1071  return false;
1072  }
1073 
1074  renderEntity_t *refEnt = &def->parms;
1075 
1076  model = R_EntityDefDynamicModel( def );
1077  if ( !model ) {
1078  return false;
1079  }
1080 
1081  // transform the points into local space
1082  R_AxisToModelMatrix( refEnt->axis, refEnt->origin, modelMatrix );
1083  R_GlobalPointToLocal( modelMatrix, start, localStart );
1084  R_GlobalPointToLocal( modelMatrix, end, localEnd );
1085 
1086  // if we have explicit collision surfaces, only collide against them
1087  // (FIXME, should probably have a parm to control this)
1088  collisionSurface = false;
1089  for ( i = 0; i < model->NumBaseSurfaces(); i++ ) {
1090  surf = model->Surface( i );
1091 
1092  shader = R_RemapShaderBySkin( surf->shader, def->parms.customSkin, def->parms.customShader );
1093 
1094  if ( shader->GetSurfaceFlags() & SURF_COLLISION ) {
1095  collisionSurface = true;
1096  break;
1097  }
1098  }
1099 
1100  // only use baseSurfaces, not any overlays
1101  for ( i = 0; i < model->NumBaseSurfaces(); i++ ) {
1102  surf = model->Surface( i );
1103 
1104  shader = R_RemapShaderBySkin( surf->shader, def->parms.customSkin, def->parms.customShader );
1105 
1106  if ( !surf->geometry || !shader ) {
1107  continue;
1108  }
1109 
1110  if ( collisionSurface ) {
1111  // only trace vs collision surfaces
1112  if ( !( shader->GetSurfaceFlags() & SURF_COLLISION ) ) {
1113  continue;
1114  }
1115  } else {
1116  // skip if not drawn or translucent
1117  if ( !shader->IsDrawn() || ( shader->Coverage() != MC_OPAQUE && shader->Coverage() != MC_PERFORATED ) ) {
1118  continue;
1119  }
1120  }
1121 
1122  localTrace = R_LocalTrace( localStart, localEnd, radius, surf->geometry );
1123 
1124  if ( localTrace.fraction < trace.fraction ) {
1125  trace.fraction = localTrace.fraction;
1126  R_LocalPointToGlobal( modelMatrix, localTrace.point, trace.point );
1127  trace.normal = localTrace.normal * refEnt->axis;
1128  trace.material = shader;
1129  trace.entity = &def->parms;
1130  trace.jointNumber = refEnt->hModel->NearestJoint( i, localTrace.indexes[0], localTrace.indexes[1], localTrace.indexes[2] );
1131  }
1132  }
1133 
1134  return ( trace.fraction < 1.0f );
1135 }
1136 
1137 /*
1138 ===================
1139 idRenderWorldLocal::Trace
1140 ===================
1141 */
1142 // FIXME: _D3XP added those.
1143 const char* playerModelExcludeList[] = {
1144  "models/md5/characters/player/d3xp_spplayer.md5mesh",
1145  "models/md5/characters/player/head/d3xp_head.md5mesh",
1146  "models/md5/weapons/pistol_world/worldpistol.md5mesh",
1147  NULL
1148 };
1149 
1150 const char* playerMaterialExcludeList[] = {
1151  "muzzlesmokepuff",
1152  NULL
1153 };
1154 
1155 bool idRenderWorldLocal::Trace( modelTrace_t &trace, const idVec3 &start, const idVec3 &end, const float radius, bool skipDynamic, bool skipPlayer /*_D3XP*/ ) const {
1156  areaReference_t * ref;
1157  idRenderEntityLocal *def;
1158  portalArea_t * area;
1159  idRenderModel * model;
1160  srfTriangles_t * tri;
1161  localTrace_t localTrace;
1162  int areas[128], numAreas, i, j, numSurfaces;
1163  idBounds traceBounds, bounds;
1164  float modelMatrix[16];
1165  idVec3 localStart, localEnd;
1166  const idMaterial *shader;
1167 
1168  trace.fraction = 1.0f;
1169  trace.point = end;
1170 
1171  // bounds for the whole trace
1172  traceBounds.Clear();
1173  traceBounds.AddPoint( start );
1174  traceBounds.AddPoint( end );
1175 
1176  // get the world areas the trace is in
1177  numAreas = BoundsInAreas( traceBounds, areas, 128 );
1178 
1179  numSurfaces = 0;
1180 
1181  // check all areas for models
1182  for ( i = 0; i < numAreas; i++ ) {
1183 
1184  area = &portalAreas[ areas[i] ];
1185 
1186  // check all models in this area
1187  for ( ref = area->entityRefs.areaNext; ref != &area->entityRefs; ref = ref->areaNext ) {
1188  def = ref->entity;
1189 
1190  model = def->parms.hModel;
1191  if ( !model ) {
1192  continue;
1193  }
1194 
1195  if ( model->IsDynamicModel() != DM_STATIC ) {
1196  if ( skipDynamic ) {
1197  continue;
1198  }
1199 
1200 #if 1 /* _D3XP addition. could use a cleaner approach */
1201  if ( skipPlayer ) {
1202  idStr name = model->Name();
1203  const char *exclude;
1204  int k;
1205 
1206  for ( k = 0; playerModelExcludeList[k]; k++ ) {
1207  exclude = playerModelExcludeList[k];
1208  if ( name == exclude ) {
1209  break;
1210  }
1211  }
1212 
1213  if ( playerModelExcludeList[k] ) {
1214  continue;
1215  }
1216  }
1217 #endif
1218 
1219  model = R_EntityDefDynamicModel( def );
1220  if ( !model ) {
1221  continue; // can happen with particle systems, which don't instantiate without a valid view
1222  }
1223  }
1224 
1225  bounds.FromTransformedBounds( model->Bounds( &def->parms ), def->parms.origin, def->parms.axis );
1226 
1227  // if the model bounds do not overlap with the trace bounds
1228  if ( !traceBounds.IntersectsBounds( bounds ) || !bounds.LineIntersection( start, trace.point ) ) {
1229  continue;
1230  }
1231 
1232  // check all model surfaces
1233  for ( j = 0; j < model->NumSurfaces(); j++ ) {
1234  const modelSurface_t *surf = model->Surface( j );
1235 
1236  shader = R_RemapShaderBySkin( surf->shader, def->parms.customSkin, def->parms.customShader );
1237 
1238  // if no geometry or no shader
1239  if ( !surf->geometry || !shader ) {
1240  continue;
1241  }
1242 
1243 #if 1 /* _D3XP addition. could use a cleaner approach */
1244  if ( skipPlayer ) {
1245  idStr name = shader->GetName();
1246  const char *exclude;
1247  int k;
1248 
1249  for ( k = 0; playerMaterialExcludeList[k]; k++ ) {
1250  exclude = playerMaterialExcludeList[k];
1251  if ( name == exclude ) {
1252  break;
1253  }
1254  }
1255 
1256  if ( playerMaterialExcludeList[k] ) {
1257  continue;
1258  }
1259  }
1260 #endif
1261 
1262  tri = surf->geometry;
1263 
1264  bounds.FromTransformedBounds( tri->bounds, def->parms.origin, def->parms.axis );
1265 
1266  // if triangle bounds do not overlap with the trace bounds
1267  if ( !traceBounds.IntersectsBounds( bounds ) || !bounds.LineIntersection( start, trace.point ) ) {
1268  continue;
1269  }
1270 
1271  numSurfaces++;
1272 
1273  // transform the points into local space
1274  R_AxisToModelMatrix( def->parms.axis, def->parms.origin, modelMatrix );
1275  R_GlobalPointToLocal( modelMatrix, start, localStart );
1276  R_GlobalPointToLocal( modelMatrix, end, localEnd );
1277 
1278  localTrace = R_LocalTrace( localStart, localEnd, radius, surf->geometry );
1279 
1280  if ( localTrace.fraction < trace.fraction ) {
1281  trace.fraction = localTrace.fraction;
1282  R_LocalPointToGlobal( modelMatrix, localTrace.point, trace.point );
1283  trace.normal = localTrace.normal * def->parms.axis;
1284  trace.material = shader;
1285  trace.entity = &def->parms;
1286  trace.jointNumber = model->NearestJoint( j, localTrace.indexes[0], localTrace.indexes[1], localTrace.indexes[2] );
1287 
1288  traceBounds.Clear();
1289  traceBounds.AddPoint( start );
1290  traceBounds.AddPoint( start + trace.fraction * (end - start) );
1291  }
1292  }
1293  }
1294  }
1295  return ( trace.fraction < 1.0f );
1296 }
1297 
1298 /*
1299 ==================
1300 idRenderWorldLocal::RecurseProcBSP
1301 ==================
1302 */
1303 void idRenderWorldLocal::RecurseProcBSP_r( modelTrace_t *results, int parentNodeNum, int nodeNum, float p1f, float p2f, const idVec3 &p1, const idVec3 &p2 ) const {
1304  float t1, t2;
1305  float frac;
1306  idVec3 mid;
1307  int side;
1308  float midf;
1309  areaNode_t *node;
1310 
1311  if ( results->fraction <= p1f) {
1312  return; // already hit something nearer
1313  }
1314  // empty leaf
1315  if ( nodeNum < 0 ) {
1316  return;
1317  }
1318  // if solid leaf node
1319  if ( nodeNum == 0 ) {
1320  if ( parentNodeNum != -1 ) {
1321 
1322  results->fraction = p1f;
1323  results->point = p1;
1324  node = &areaNodes[parentNodeNum];
1325  results->normal = node->plane.Normal();
1326  return;
1327  }
1328  }
1329  node = &areaNodes[nodeNum];
1330 
1331  // distance from plane for trace start and end
1332  t1 = node->plane.Normal() * p1 + node->plane[3];
1333  t2 = node->plane.Normal() * p2 + node->plane[3];
1334 
1335  if ( t1 >= 0.0f && t2 >= 0.0f ) {
1336  RecurseProcBSP_r( results, nodeNum, node->children[0], p1f, p2f, p1, p2 );
1337  return;
1338  }
1339  if ( t1 < 0.0f && t2 < 0.0f ) {
1340  RecurseProcBSP_r( results, nodeNum, node->children[1], p1f, p2f, p1, p2 );
1341  return;
1342  }
1343  side = t1 < t2;
1344  frac = t1 / (t1 - t2);
1345  midf = p1f + frac*(p2f - p1f);
1346  mid[0] = p1[0] + frac*(p2[0] - p1[0]);
1347  mid[1] = p1[1] + frac*(p2[1] - p1[1]);
1348  mid[2] = p1[2] + frac*(p2[2] - p1[2]);
1349  RecurseProcBSP_r( results, nodeNum, node->children[side], p1f, midf, p1, mid );
1350  RecurseProcBSP_r( results, nodeNum, node->children[side^1], midf, p2f, mid, p2 );
1351 }
1352 
1353 /*
1354 ==================
1355 idRenderWorldLocal::FastWorldTrace
1356 ==================
1357 */
1358 bool idRenderWorldLocal::FastWorldTrace( modelTrace_t &results, const idVec3 &start, const idVec3 &end ) const {
1359  memset( &results, 0, sizeof( modelTrace_t ) );
1360  results.fraction = 1.0f;
1361  if ( areaNodes != NULL ) {
1362  RecurseProcBSP_r( &results, -1, 0, 0.0f, 1.0f, start, end );
1363  return ( results.fraction < 1.0f );
1364  }
1365  return false;
1366 }
1367 
1368 /*
1369 =================================================================================
1370 
1371 CREATE MODEL REFS
1372 
1373 =================================================================================
1374 */
1375 
1376 /*
1377 =================
1378 AddEntityRefToArea
1379 
1380 This is called by R_PushVolumeIntoTree and also directly
1381 for the world model references that are precalculated.
1382 =================
1383 */
1386 
1387  if ( !def ) {
1388  common->Error( "idRenderWorldLocal::AddEntityRefToArea: NULL def" );
1389  }
1390 
1391  ref = areaReferenceAllocator.Alloc();
1392 
1394 
1395  ref->entity = def;
1396 
1397  // link to entityDef
1398  ref->ownerNext = def->entityRefs;
1399  def->entityRefs = ref;
1400 
1401  // link to end of area list
1402  ref->area = area;
1403  ref->areaNext = &area->entityRefs;
1404  ref->areaPrev = area->entityRefs.areaPrev;
1405  ref->areaNext->areaPrev = ref;
1406  ref->areaPrev->areaNext = ref;
1407 }
1408 
1409 /*
1410 ===================
1411 AddLightRefToArea
1412 
1413 ===================
1414 */
1416  areaReference_t *lref;
1417 
1418  // add a lightref to this area
1419  lref = areaReferenceAllocator.Alloc();
1420  lref->light = light;
1421  lref->area = area;
1422  lref->ownerNext = light->references;
1423  light->references = lref;
1425 
1426  // doubly linked list so we can free them easily later
1427  area->lightRefs.areaNext->areaPrev = lref;
1428  lref->areaNext = area->lightRefs.areaNext;
1429  lref->areaPrev = &area->lightRefs;
1430  area->lightRefs.areaNext = lref;
1431 }
1432 
1433 /*
1434 ===================
1435 GenerateAllInteractions
1436 
1437 Force the generation of all light / surface interactions at the start of a level
1438 If this isn't called, they will all be dynamically generated
1439 
1440 This really isn't all that helpful anymore, because the calculation of shadows
1441 and light interactions is deferred from idRenderWorldLocal::CreateLightDefInteractions(), but we
1442 use it as an oportunity to size the interactionTable
1443 ===================
1444 */
1446  if ( !glConfig.isInitialized ) {
1447  return;
1448  }
1449 
1450  int start = Sys_Milliseconds();
1451 
1453 
1454  // watch how much memory we allocate
1455  tr.staticAllocCount = 0;
1456 
1457  // let idRenderWorldLocal::CreateLightDefInteractions() know that it shouldn't
1458  // try and do any view specific optimizations
1459  tr.viewDef = NULL;
1460 
1461  for ( int i = 0 ; i < this->lightDefs.Num() ; i++ ) {
1462  idRenderLightLocal *ldef = this->lightDefs[i];
1463  if ( !ldef ) {
1464  continue;
1465  }
1466  this->CreateLightDefInteractions( ldef );
1467  }
1468 
1469  int end = Sys_Milliseconds();
1470  int msec = end - start;
1471 
1472  common->Printf( "idRenderWorld::GenerateAllInteractions, msec = %i, staticAllocCount = %i.\n", msec, tr.staticAllocCount );
1473 
1474 
1475  // build the interaction table
1476  if ( r_useInteractionTable.GetBool() ) {
1479  int size = interactionTableWidth * interactionTableHeight * sizeof( *interactionTable );
1480  interactionTable = (idInteraction **)R_ClearedStaticAlloc( size );
1481 
1482  int count = 0;
1483  for ( int i = 0 ; i < this->lightDefs.Num() ; i++ ) {
1484  idRenderLightLocal *ldef = this->lightDefs[i];
1485  if ( !ldef ) {
1486  continue;
1487  }
1488  idInteraction *inter;
1489  for ( inter = ldef->firstInteraction; inter != NULL; inter = inter->lightNext ) {
1490  idRenderEntityLocal *edef = inter->entityDef;
1491  int index = ldef->index * interactionTableWidth + edef->index;
1492 
1493  interactionTable[ index ] = inter;
1494  count++;
1495  }
1496  }
1497 
1498  common->Printf( "interactionTable size: %i bytes\n", size );
1499  common->Printf( "%i interaction take %i bytes\n", count, count * sizeof( idInteraction ) );
1500  }
1501 
1502  // entities flagged as noDynamicInteractions will no longer make any
1504 }
1505 
1506 /*
1507 ===================
1508 idRenderWorldLocal::FreeInteractions
1509 ===================
1510 */
1512  int i;
1513  idRenderEntityLocal *def;
1514 
1515  for ( i = 0 ; i < entityDefs.Num(); i++ ) {
1516  def = entityDefs[i];
1517  if ( !def ) {
1518  continue;
1519  }
1520  // free all the interactions
1521  while ( def->firstInteraction != NULL ) {
1523  }
1524  }
1525 }
1526 
1527 /*
1528 ==================
1529 PushVolumeIntoTree
1530 
1531 Used for both light volumes and model volumes.
1532 
1533 This does not clip the points by the planes, so some slop
1534 occurs.
1535 
1536 tr.viewCount should be bumped before calling, allowing it
1537 to prevent double checking areas.
1538 
1539 We might alternatively choose to do this with an area flow.
1540 ==================
1541 */
1542 void idRenderWorldLocal::PushVolumeIntoTree_r( idRenderEntityLocal *def, idRenderLightLocal *light, const idSphere *sphere, int numPoints, const idVec3 (*points),
1543  int nodeNum ) {
1544  int i;
1545  areaNode_t *node;
1546  bool front, back;
1547 
1548  if ( nodeNum < 0 ) {
1549  portalArea_t *area;
1550  int areaNum = -1 - nodeNum;
1551 
1552  area = &portalAreas[ areaNum ];
1553  if ( area->viewCount == tr.viewCount ) {
1554  return; // already added a reference here
1555  }
1556  area->viewCount = tr.viewCount;
1557 
1558  if ( def ) {
1559  AddEntityRefToArea( def, area );
1560  }
1561  if ( light ) {
1562  AddLightRefToArea( light, area );
1563  }
1564 
1565  return;
1566  }
1567 
1568  node = areaNodes + nodeNum;
1569 
1570  // if we know that all possible children nodes only touch an area
1571  // we have already marked, we can early out
1573  node->commonChildrenArea != CHILDREN_HAVE_MULTIPLE_AREAS ) {
1574  // note that we do NOT try to set a reference in this area
1575  // yet, because the test volume may yet wind up being in the
1576  // solid part, which would cause bounds slightly poked into
1577  // a wall to show up in the next room
1578  if ( portalAreas[ node->commonChildrenArea ].viewCount == tr.viewCount ) {
1579  return;
1580  }
1581  }
1582 
1583  // if the bounding sphere is completely on one side, don't
1584  // bother checking the individual points
1585  float sd = node->plane.Distance( sphere->GetOrigin() );
1586  if ( sd >= sphere->GetRadius() ) {
1587  nodeNum = node->children[0];
1588  if ( nodeNum ) { // 0 = solid
1589  PushVolumeIntoTree_r( def, light, sphere, numPoints, points, nodeNum );
1590  }
1591  return;
1592  }
1593  if ( sd <= -sphere->GetRadius() ) {
1594  nodeNum = node->children[1];
1595  if ( nodeNum ) { // 0 = solid
1596  PushVolumeIntoTree_r( def, light, sphere, numPoints, points, nodeNum );
1597  }
1598  return;
1599  }
1600 
1601  // exact check all the points against the node plane
1602  front = back = false;
1603 #ifdef MACOS_X //loop unrolling & pre-fetching for performance
1604  const idVec3 norm = node->plane.Normal();
1605  const float plane3 = node->plane[3];
1606  float D0, D1, D2, D3;
1607 
1608  for ( i = 0 ; i < numPoints - 4; i+=4 ) {
1609  D0 = points[i+0] * norm + plane3;
1610  D1 = points[i+1] * norm + plane3;
1611  if ( !front && D0 >= 0.0f ) {
1612  front = true;
1613  } else if ( !back && D0 <= 0.0f ) {
1614  back = true;
1615  }
1616  D2 = points[i+1] * norm + plane3;
1617  if ( !front && D1 >= 0.0f ) {
1618  front = true;
1619  } else if ( !back && D1 <= 0.0f ) {
1620  back = true;
1621  }
1622  D3 = points[i+1] * norm + plane3;
1623  if ( !front && D2 >= 0.0f ) {
1624  front = true;
1625  } else if ( !back && D2 <= 0.0f ) {
1626  back = true;
1627  }
1628 
1629  if ( !front && D3 >= 0.0f ) {
1630  front = true;
1631  } else if ( !back && D3 <= 0.0f ) {
1632  back = true;
1633  }
1634  if ( back && front ) {
1635  break;
1636  }
1637  }
1638  if(!(back && front)) {
1639  for (; i < numPoints ; i++ ) {
1640  float d;
1641  d = points[i] * node->plane.Normal() + node->plane[3];
1642  if ( d >= 0.0f ) {
1643  front = true;
1644  } else if ( d <= 0.0f ) {
1645  back = true;
1646  }
1647  if ( back && front ) {
1648  break;
1649  }
1650  }
1651  }
1652 #else
1653  for ( i = 0 ; i < numPoints ; i++ ) {
1654  float d;
1655 
1656  d = points[i] * node->plane.Normal() + node->plane[3];
1657  if ( d >= 0.0f ) {
1658  front = true;
1659  } else if ( d <= 0.0f ) {
1660  back = true;
1661  }
1662  if ( back && front ) {
1663  break;
1664  }
1665  }
1666 #endif
1667  if ( front ) {
1668  nodeNum = node->children[0];
1669  if ( nodeNum ) { // 0 = solid
1670  PushVolumeIntoTree_r( def, light, sphere, numPoints, points, nodeNum );
1671  }
1672  }
1673  if ( back ) {
1674  nodeNum = node->children[1];
1675  if ( nodeNum ) { // 0 = solid
1676  PushVolumeIntoTree_r( def, light, sphere, numPoints, points, nodeNum );
1677  }
1678  }
1679 }
1680 
1681 /*
1682 ==============
1683 PushVolumeIntoTree
1684 ==============
1685 */
1687  int i;
1688  float radSquared, lr;
1689  idVec3 mid, dir;
1690 
1691  if ( areaNodes == NULL ) {
1692  return;
1693  }
1694 
1695  // calculate a bounding sphere for the points
1696  mid.Zero();
1697  for ( i = 0; i < numPoints; i++ ) {
1698  mid += points[i];
1699  }
1700  mid *= ( 1.0f / numPoints );
1701 
1702  radSquared = 0;
1703 
1704  for ( i = 0; i < numPoints; i++ ) {
1705  dir = points[i] - mid;
1706  lr = dir * dir;
1707  if ( lr > radSquared ) {
1708  radSquared = lr;
1709  }
1710  }
1711 
1712  idSphere sphere( mid, sqrt( radSquared ) );
1713 
1714  PushVolumeIntoTree_r( def, light, &sphere, numPoints, points, 0 );
1715 }
1716 
1717 //===================================================================
1718 
1719 /*
1720 ====================
1721 idRenderWorldLocal::DebugClearLines
1722 ====================
1723 */
1725  RB_ClearDebugLines( time );
1726  RB_ClearDebugText( time );
1727 }
1728 
1729 /*
1730 ====================
1731 idRenderWorldLocal::DebugLine
1732 ====================
1733 */
1734 void idRenderWorldLocal::DebugLine( const idVec4 &color, const idVec3 &start, const idVec3 &end, const int lifetime, const bool depthTest ) {
1735  RB_AddDebugLine( color, start, end, lifetime, depthTest );
1736 }
1737 
1738 /*
1739 ================
1740 idRenderWorldLocal::DebugArrow
1741 ================
1742 */
1743 void idRenderWorldLocal::DebugArrow( const idVec4 &color, const idVec3 &start, const idVec3 &end, int size, const int lifetime ) {
1744  idVec3 forward, right, up, v1, v2;
1745  float a, s;
1746  int i;
1747  static float arrowCos[40];
1748  static float arrowSin[40];
1749  static int arrowStep;
1750 
1751  DebugLine( color, start, end, lifetime );
1752 
1753  if ( r_debugArrowStep.GetInteger() <= 10 ) {
1754  return;
1755  }
1756  // calculate sine and cosine when step size changes
1757  if ( arrowStep != r_debugArrowStep.GetInteger() ) {
1758  arrowStep = r_debugArrowStep.GetInteger();
1759  for (i = 0, a = 0; a < 360.0f; a += arrowStep, i++) {
1760  arrowCos[i] = idMath::Cos16( DEG2RAD( a ) );
1761  arrowSin[i] = idMath::Sin16( DEG2RAD( a ) );
1762  }
1763  arrowCos[i] = arrowCos[0];
1764  arrowSin[i] = arrowSin[0];
1765  }
1766  // draw a nice arrow
1767  forward = end - start;
1768  forward.Normalize();
1769  forward.NormalVectors( right, up);
1770  for (i = 0, a = 0; a < 360.0f; a += arrowStep, i++) {
1771  s = 0.5f * size * arrowCos[i];
1772  v1 = end - size * forward;
1773  v1 = v1 + s * right;
1774  s = 0.5f * size * arrowSin[i];
1775  v1 = v1 + s * up;
1776 
1777  s = 0.5f * size * arrowCos[i+1];
1778  v2 = end - size * forward;
1779  v2 = v2 + s * right;
1780  s = 0.5f * size * arrowSin[i+1];
1781  v2 = v2 + s * up;
1782 
1783  DebugLine( color, v1, end, lifetime );
1784  DebugLine( color, v1, v2, lifetime );
1785  }
1786 }
1787 
1788 /*
1789 ====================
1790 idRenderWorldLocal::DebugWinding
1791 ====================
1792 */
1793 void idRenderWorldLocal::DebugWinding( const idVec4 &color, const idWinding &w, const idVec3 &origin, const idMat3 &axis, const int lifetime, const bool depthTest ) {
1794  int i;
1795  idVec3 point, lastPoint;
1796 
1797  if ( w.GetNumPoints() < 2 ) {
1798  return;
1799  }
1800 
1801  lastPoint = origin + w[w.GetNumPoints()-1].ToVec3() * axis;
1802  for ( i = 0; i < w.GetNumPoints(); i++ ) {
1803  point = origin + w[i].ToVec3() * axis;
1804  DebugLine( color, lastPoint, point, lifetime, depthTest );
1805  lastPoint = point;
1806  }
1807 }
1808 
1809 /*
1810 ====================
1811 idRenderWorldLocal::DebugCircle
1812 ====================
1813 */
1814 void idRenderWorldLocal::DebugCircle( const idVec4 &color, const idVec3 &origin, const idVec3 &dir, const float radius, const int numSteps, const int lifetime, const bool depthTest ) {
1815  int i;
1816  float a;
1817  idVec3 left, up, point, lastPoint;
1818 
1819  dir.OrthogonalBasis( left, up );
1820  left *= radius;
1821  up *= radius;
1822  lastPoint = origin + up;
1823  for ( i = 1; i <= numSteps; i++ ) {
1824  a = idMath::TWO_PI * i / numSteps;
1825  point = origin + idMath::Sin16( a ) * left + idMath::Cos16( a ) * up;
1826  DebugLine( color, lastPoint, point, lifetime, depthTest );
1827  lastPoint = point;
1828  }
1829 }
1830 
1831 /*
1832 ============
1833 idRenderWorldLocal::DebugSphere
1834 ============
1835 */
1836 void idRenderWorldLocal::DebugSphere( const idVec4 &color, const idSphere &sphere, const int lifetime, const bool depthTest /*_D3XP*/ ) {
1837  int i, j, n, num;
1838  float s, c;
1839  idVec3 p, lastp, *lastArray;
1840 
1841  num = 360 / 15;
1842  lastArray = (idVec3 *) _alloca16( num * sizeof( idVec3 ) );
1843  lastArray[0] = sphere.GetOrigin() + idVec3( 0, 0, sphere.GetRadius() );
1844  for ( n = 1; n < num; n++ ) {
1845  lastArray[n] = lastArray[0];
1846  }
1847 
1848  for ( i = 15; i <= 360; i += 15 ) {
1849  s = idMath::Sin16( DEG2RAD(i) );
1850  c = idMath::Cos16( DEG2RAD(i) );
1851  lastp[0] = sphere.GetOrigin()[0];
1852  lastp[1] = sphere.GetOrigin()[1] + sphere.GetRadius() * s;
1853  lastp[2] = sphere.GetOrigin()[2] + sphere.GetRadius() * c;
1854  for ( n = 0, j = 15; j <= 360; j += 15, n++ ) {
1855  p[0] = sphere.GetOrigin()[0] + idMath::Sin16( DEG2RAD(j) ) * sphere.GetRadius() * s;
1856  p[1] = sphere.GetOrigin()[1] + idMath::Cos16( DEG2RAD(j) ) * sphere.GetRadius() * s;
1857  p[2] = lastp[2];
1858 
1859  DebugLine( color, lastp, p, lifetime,depthTest );
1860  DebugLine( color, lastp, lastArray[n], lifetime, depthTest );
1861 
1862  lastArray[n] = lastp;
1863  lastp = p;
1864  }
1865  }
1866 }
1867 
1868 /*
1869 ====================
1870 idRenderWorldLocal::DebugBounds
1871 ====================
1872 */
1873 void idRenderWorldLocal::DebugBounds( const idVec4 &color, const idBounds &bounds, const idVec3 &org, const int lifetime ) {
1874  int i;
1875  idVec3 v[8];
1876 
1877  if ( bounds.IsCleared() ) {
1878  return;
1879  }
1880 
1881  for ( i = 0; i < 8; i++ ) {
1882  v[i][0] = org[0] + bounds[(i^(i>>1))&1][0];
1883  v[i][1] = org[1] + bounds[(i>>1)&1][1];
1884  v[i][2] = org[2] + bounds[(i>>2)&1][2];
1885  }
1886  for ( i = 0; i < 4; i++ ) {
1887  DebugLine( color, v[i], v[(i+1)&3], lifetime );
1888  DebugLine( color, v[4+i], v[4+((i+1)&3)], lifetime );
1889  DebugLine( color, v[i], v[4+i], lifetime );
1890  }
1891 }
1892 
1893 /*
1894 ====================
1895 idRenderWorldLocal::DebugBox
1896 ====================
1897 */
1898 void idRenderWorldLocal::DebugBox( const idVec4 &color, const idBox &box, const int lifetime ) {
1899  int i;
1900  idVec3 v[8];
1901 
1902  box.ToPoints( v );
1903  for ( i = 0; i < 4; i++ ) {
1904  DebugLine( color, v[i], v[(i+1)&3], lifetime );
1905  DebugLine( color, v[4+i], v[4+((i+1)&3)], lifetime );
1906  DebugLine( color, v[i], v[4+i], lifetime );
1907  }
1908 }
1909 
1910 /*
1911 ================
1912 idRenderWorldLocal::DebugFrustum
1913 ================
1914 */
1915 void idRenderWorldLocal::DebugFrustum( const idVec4 &color, const idFrustum &frustum, const bool showFromOrigin, const int lifetime ) {
1916  int i;
1917  idVec3 v[8];
1918 
1919  frustum.ToPoints( v );
1920 
1921  if ( frustum.GetNearDistance() > 0.0f ) {
1922  for ( i = 0; i < 4; i++ ) {
1923  DebugLine( color, v[i], v[(i+1)&3], lifetime );
1924  }
1925  if ( showFromOrigin ) {
1926  for ( i = 0; i < 4; i++ ) {
1927  DebugLine( color, frustum.GetOrigin(), v[i], lifetime );
1928  }
1929  }
1930  }
1931  for ( i = 0; i < 4; i++ ) {
1932  DebugLine( color, v[4+i], v[4+((i+1)&3)], lifetime );
1933  DebugLine( color, v[i], v[4+i], lifetime );
1934  }
1935 }
1936 
1937 /*
1938 ============
1939 idRenderWorldLocal::DebugCone
1940 
1941  dir is the cone axis
1942  radius1 is the radius at the apex
1943  radius2 is the radius at apex+dir
1944 ============
1945 */
1946 void idRenderWorldLocal::DebugCone( const idVec4 &color, const idVec3 &apex, const idVec3 &dir, float radius1, float radius2, const int lifetime ) {
1947  int i;
1948  idMat3 axis;
1949  idVec3 top, p1, p2, lastp1, lastp2, d;
1950 
1951  axis[2] = dir;
1952  axis[2].Normalize();
1953  axis[2].NormalVectors( axis[0], axis[1] );
1954  axis[1] = -axis[1];
1955 
1956  top = apex + dir;
1957  lastp2 = top + radius2 * axis[1];
1958 
1959  if ( radius1 == 0.0f ) {
1960  for ( i = 20; i <= 360; i += 20 ) {
1961  d = idMath::Sin16( DEG2RAD(i) ) * axis[0] + idMath::Cos16( DEG2RAD(i) ) * axis[1];
1962  p2 = top + d * radius2;
1963  DebugLine( color, lastp2, p2, lifetime );
1964  DebugLine( color, p2, apex, lifetime );
1965  lastp2 = p2;
1966  }
1967  } else {
1968  lastp1 = apex + radius1 * axis[1];
1969  for ( i = 20; i <= 360; i += 20 ) {
1970  d = idMath::Sin16( DEG2RAD(i) ) * axis[0] + idMath::Cos16( DEG2RAD(i) ) * axis[1];
1971  p1 = apex + d * radius1;
1972  p2 = top + d * radius2;
1973  DebugLine( color, lastp1, p1, lifetime );
1974  DebugLine( color, lastp2, p2, lifetime );
1975  DebugLine( color, p1, p2, lifetime );
1976  lastp1 = p1;
1977  lastp2 = p2;
1978  }
1979  }
1980 }
1981 
1982 /*
1983 ================
1984 idRenderWorldLocal::DebugAxis
1985 ================
1986 */
1987 void idRenderWorldLocal::DebugAxis( const idVec3 &origin, const idMat3 &axis ) {
1988  idVec3 start = origin;
1989  idVec3 end = start + axis[0] * 20.0f;
1990  DebugArrow( colorWhite, start, end, 2 );
1991  end = start + axis[0] * -20.0f;
1992  DebugArrow( colorWhite, start, end, 2 );
1993  end = start + axis[1] * +20.0f;
1994  DebugArrow( colorGreen, start, end, 2 );
1995  end = start + axis[1] * -20.0f;
1996  DebugArrow( colorGreen, start, end, 2 );
1997  end = start + axis[2] * +20.0f;
1998  DebugArrow( colorBlue, start, end, 2 );
1999  end = start + axis[2] * -20.0f;
2000  DebugArrow( colorBlue, start, end, 2 );
2001 }
2002 
2003 /*
2004 ====================
2005 idRenderWorldLocal::DebugClearPolygons
2006 ====================
2007 */
2009  RB_ClearDebugPolygons( time );
2010 }
2011 
2012 /*
2013 ====================
2014 idRenderWorldLocal::DebugPolygon
2015 ====================
2016 */
2017 void idRenderWorldLocal::DebugPolygon( const idVec4 &color, const idWinding &winding, const int lifeTime, const bool depthTest ) {
2018  RB_AddDebugPolygon( color, winding, lifeTime, depthTest );
2019 }
2020 
2021 /*
2022 ================
2023 idRenderWorldLocal::DebugScreenRect
2024 ================
2025 */
2026 void idRenderWorldLocal::DebugScreenRect( const idVec4 &color, const idScreenRect &rect, const viewDef_t *viewDef, const int lifetime ) {
2027  int i;
2028  float centerx, centery, dScale, hScale, vScale;
2029  idBounds bounds;
2030  idVec3 p[4];
2031 
2032  centerx = ( viewDef->viewport.x2 - viewDef->viewport.x1 ) * 0.5f;
2033  centery = ( viewDef->viewport.y2 - viewDef->viewport.y1 ) * 0.5f;
2034 
2035  dScale = r_znear.GetFloat() + 1.0f;
2036  hScale = dScale * idMath::Tan16( DEG2RAD( viewDef->renderView.fov_x * 0.5f ) );
2037  vScale = dScale * idMath::Tan16( DEG2RAD( viewDef->renderView.fov_y * 0.5f ) );
2038 
2039  bounds[0][0] = bounds[1][0] = dScale;
2040  bounds[0][1] = -( rect.x1 - centerx ) / centerx * hScale;
2041  bounds[1][1] = -( rect.x2 - centerx ) / centerx * hScale;
2042  bounds[0][2] = ( rect.y1 - centery ) / centery * vScale;
2043  bounds[1][2] = ( rect.y2 - centery ) / centery * vScale;
2044 
2045  for ( i = 0; i < 4; i++ ) {
2046  p[i].x = bounds[0][0];
2047  p[i].y = bounds[(i^(i>>1))&1].y;
2048  p[i].z = bounds[(i>>1)&1].z;
2049  p[i] = viewDef->renderView.vieworg + p[i] * viewDef->renderView.viewaxis;
2050  }
2051  for ( i = 0; i < 4; i++ ) {
2052  DebugLine( color, p[i], p[(i+1)&3], false );
2053  }
2054 }
2055 
2056 /*
2057 ================
2058 idRenderWorldLocal::DrawTextLength
2059 
2060  returns the length of the given text
2061 ================
2062 */
2063 float idRenderWorldLocal::DrawTextLength( const char *text, float scale, int len ) {
2064  return RB_DrawTextLength( text, scale, len );
2065 }
2066 
2067 /*
2068 ================
2069 idRenderWorldLocal::DrawText
2070 
2071  oriented on the viewaxis
2072  align can be 0-left, 1-center (default), 2-right
2073 ================
2074 */
2075 void idRenderWorldLocal::DrawText( const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align, const int lifetime, const bool depthTest ) {
2076  RB_AddDebugText( text, origin, scale, color, viewAxis, align, lifetime, depthTest );
2077 }
2078 
2079 /*
2080 ===============
2081 idRenderWorldLocal::RegenerateWorld
2082 ===============
2083 */
2086 }
2087 
2088 /*
2089 ===============
2090 R_GlobalShaderOverride
2091 ===============
2092 */
2093 bool R_GlobalShaderOverride( const idMaterial **shader ) {
2094 
2095  if ( !(*shader)->IsDrawn() ) {
2096  return false;
2097  }
2098 
2101  return true;
2102  }
2103 
2104  if ( r_materialOverride.GetString()[0] != '\0' ) {
2106  return true;
2107  }
2108 
2109  return false;
2110 }
2111 
2112 /*
2113 ===============
2114 R_RemapShaderBySkin
2115 ===============
2116 */
2117 const idMaterial *R_RemapShaderBySkin( const idMaterial *shader, const idDeclSkin *skin, const idMaterial *customShader ) {
2118 
2119  if ( !shader ) {
2120  return NULL;
2121  }
2122 
2123  // never remap surfaces that were originally nodraw, like collision hulls
2124  if ( !shader->IsDrawn() ) {
2125  return shader;
2126  }
2127 
2128  if ( customShader ) {
2129  // this is sort of a hack, but cause deformed surfaces to map to empty surfaces,
2130  // so the item highlight overlay doesn't highlight the autosprite surface
2131  if ( shader->Deform() ) {
2132  return NULL;
2133  }
2134  return const_cast<idMaterial *>(customShader);
2135  }
2136 
2137  if ( !skin || !shader ) {
2138  return const_cast<idMaterial *>(shader);
2139  }
2140 
2141  return skin->RemapShaderBySkin( shader );
2142 }
idRenderWorldLocal * world
Definition: tr_local.h:255
const idMaterial * lightShader
Definition: tr_local.h:213
void AddEntityRefToArea(idRenderEntityLocal *def, portalArea_t *area)
virtual qhandle_t AddEntityDef(const renderEntity_t *re)
byte color[4]
Definition: MegaTexture.cpp:54
idRenderModel * dynamicModel
Definition: tr_local.h:263
int indexes[3]
Definition: tr_local.h:1664
bool HasGui(void) const
Definition: Material.h:384
void R_LockSurfaceScene(viewDef_t *parms)
virtual void RegenerateWorld()
GLsizei const GLfloat * points
Definition: glext.h:3884
const idVec3 & GetOrigin(void) const
Definition: Sphere.h:165
virtual void DebugCircle(const idVec4 &color, const idVec3 &origin, const idVec3 &dir, const float radius, const int numSteps, const int lifetime=0, const bool depthTest=false)
void UnlinkAndFree(void)
void RB_ClearDebugPolygons(int time)
float Normalize(void)
Definition: Vector.h:646
idVec4 colorGreen
Definition: Lib.cpp:118
const idVec3 & GetOrigin(void) const
Definition: Frustum.h:192
int qhandle_t
Definition: Lib.h:81
idVec3 lightCenter
Definition: RenderWorld.h:179
void cross(float a[], float b[], float c[])
Definition: Model_lwo.cpp:3889
assert(prefInfo.fullscreenBtn)
virtual const renderLight_t * GetRenderLight(qhandle_t lightHandle) const
void EmitFullScreen()
Definition: GuiModel.cpp:226
const idVec3 & Normal(void) const
Definition: Plane.h:239
virtual exitPortal_t GetPortal(int areaNum, int portalNum)
idBounds projectionBounds
Definition: ModelDecal.h:51
areaReference_t lightRefs
virtual void DebugPolygon(const idVec4 &color, const idWinding &winding, const int lifeTime=0, const bool depthTest=false)
virtual void UpdateEntityDef(qhandle_t entityHandle, const renderEntity_t *re)
idVec4 colorWhite
Definition: Lib.cpp:116
void ToPoints(idVec3 points[8]) const
Definition: Frustum.cpp:1523
static bool CreateProjectionInfo(decalProjectionInfo_t &info, const idFixedWinding &winding, const idVec3 &projectionOrigin, const bool parallel, const float fadeDepth, const idMaterial *material, const int startTime)
Definition: ModelDecal.cpp:88
void R_FreeEntityDefOverlay(idRenderEntityLocal *def)
idInteraction * lightNext
Definition: Interaction.h:108
short x2
Definition: tr_local.h:55
void R_CreateLightRefs(idRenderLightLocal *light)
static float Tan16(float a)
Definition: Math.h:463
float GetFloat(void) const
Definition: CVarSystem.h:144
const GLdouble * v
Definition: glext.h:2936
class idGuiModel * guiModel
Definition: tr_local.h:802
virtual void RemoveDecals(qhandle_t entityHandle)
virtual qhandle_t AddLightDef(const renderLight_t *rlight)
virtual void UpdateLightDef(qhandle_t lightHandle, const renderLight_t *rlight)
const idWinding * w
Definition: RenderWorld.h:231
idRenderModel * R_EntityDefDynamicModel(idRenderEntityLocal *def)
Definition: tr_light.cpp:1104
float floatTime
Definition: tr_local.h:377
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:4804
areaReference_t * entityRefs
Definition: tr_local.h:285
float Distance(const idVec3 &v) const
Definition: Plane.h:324
bool R_GlobalShaderOverride(const idMaterial **shader)
void RB_AddDebugPolygon(const idVec4 &color, const idWinding &winding, const int lifeTime, const bool depthTest)
void R_SurfaceToTextureAxis(const srfTriangles_t *tri, idVec3 &origin, idVec3 axis[3])
Definition: tr_guisurf.cpp:49
idVec3 normal
Definition: tr_local.h:1663
idList< idRenderEntityLocal * > entityDefs
const idMaterial * material
Definition: RenderWorld.h:249
idCVar r_useEntityCallbacks("r_useEntityCallbacks","1", CVAR_RENDERER|CVAR_BOOL,"if 0, issue the callback immediately at update time, rather than defering")
GLenum GLsizei n
Definition: glext.h:3705
float z
Definition: Vector.h:320
virtual void DebugSphere(const idVec4 &color, const idSphere &sphere, const int lifetime=0, bool depthTest=false)
int Sys_Milliseconds(void)
virtual void RenderScene(const renderView_t *renderView)
qhandle_t portalHandle
Definition: RenderWorld.h:233
virtual void DebugClearPolygons(int time)
const idMaterial * RemapShaderBySkin(const idMaterial *shader) const
Definition: DeclSkin.cpp:162
GLclampf ref
Definition: glext.h:4237
const idMaterial * shader
Definition: Model.h:146
renderLight_t parms
Definition: tr_local.h:191
deform_t Deform(void) const
Definition: Material.h:516
int GetEntityGui(void) const
Definition: Material.h:535
idCVar r_useNodeCommonChildren("r_useNodeCommonChildren","1", CVAR_RENDERER|CVAR_BOOL,"stop pushing reference bounds early when possible")
const char * GetName(void) const
Definition: DeclManager.h:140
Definition: Vector.h:316
idScreenRect viewport
Definition: tr_local.h:398
performanceCounters_t pc
Definition: tr_local.h:788
bool forceUpdate
Definition: RenderWorld.h:219
virtual void DebugArrow(const idVec4 &color, const idVec3 &start, const idVec3 &end, int size, const int lifetime=0)
void PushVolumeIntoTree_r(idRenderEntityLocal *def, idRenderLightLocal *light, const idSphere *sphere, int numPoints, const idVec3(*points), int nodeNum)
idRenderWorldLocal * primaryWorld
Definition: tr_local.h:774
virtual const char * Name() const =0
void ToPoints(idVec3 points[8]) const
Definition: Box.cpp:761
float modelMatrix[16]
Definition: tr_local.h:253
void Clear(void)
Definition: Bounds.h:201
short x1
Definition: tr_local.h:55
void R_RegenerateWorld_f(const idCmdArgs &args)
virtual const idMaterial * FindMaterial(const char *name, bool makeDefault=true)=0
virtual void DebugBox(const idVec4 &color, const idBox &box, const int lifetime=0)
GLdouble s
Definition: glext.h:2935
GLenum GLsizei len
Definition: glext.h:3472
idCVar r_lockSurfaces("r_lockSurfaces","0", CVAR_RENDERER|CVAR_BOOL,"allow moving the view point without changing the composition of the scene, including culling")
GLdouble right
Definition: qgl.h:273
float x
Definition: Vector.h:318
int c_callbackUpdate
virtual void DebugBounds(const idVec4 &color, const idBounds &bounds, const idVec3 &org=vec3_origin, const int lifetime=0)
virtual bool Trace(modelTrace_t &trace, const idVec3 &start, const idVec3 &end, const float radius, bool skipDynamic=true, bool skipPlayer=false) const
int i
Definition: process.py:33
void OrthogonalBasis(idVec3 &left, idVec3 &up) const
Definition: Vector.h:744
deferredEntityCallback_t callback
Definition: RenderWorld.h:96
GLuint GLuint num
Definition: glext.h:5390
idCVar r_skipUpdates("r_skipUpdates","0", CVAR_RENDERER|CVAR_BOOL,"1 = don't accept any entity or light updates, making everything static")
bool IsDrawn(void) const
Definition: Material.h:378
const idMaterial * customShader
Definition: RenderWorld.h:123
void * R_ClearedFrameAlloc(int bytes)
Definition: tr_main.cpp:417
idDemoFile * writeDemo
Definition: Session.h:159
float GetNearDistance(void) const
Definition: Frustum.h:208
static float Cos16(float a)
Definition: Math.h:350
void WriteFreeEntity(qhandle_t handle)
virtual dynamicModel_t IsDynamicModel() const =0
idList< idRenderLightLocal * > lightDefs
void WriteRenderView(const renderView_t *renderView)
void ResizeInteractionTable()
static float Sin16(float a)
Definition: Math.h:314
static idRenderModelOverlay * Alloc(void)
virtual void DebugLine(const idVec4 &color, const idVec3 &start, const idVec3 &end, const int lifetime=0, const bool depthTest=false)
idCVar r_debugArrowStep("r_debugArrowStep","120", CVAR_RENDERER|CVAR_ARCHIVE|CVAR_INTEGER,"step size of arrow cone line rotation in degrees", 0, 120)
idBounds referenceBounds
Definition: tr_local.h:268
bool AllowOverlays(void) const
Definition: Material.h:422
#define PLANESIDE_FRONT
Definition: Plane.h:53
void R_CreateEntityRefs(idRenderEntityLocal *def)
materialCoverage_t Coverage(void) const
Definition: Material.h:428
doublePortal_t * doublePortals
bool AddPoint(const idVec3 &v)
Definition: Bounds.h:226
GLfloat GLfloat GLfloat v2
Definition: glext.h:3608
idInteraction ** interactionTable
virtual void DrawText(const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align=1, const int lifetime=0, bool depthTest=false)
GLuint GLuint GLsizei count
Definition: glext.h:2845
void WriteFreeLight(qhandle_t handle)
virtual void FreeLightDef(qhandle_t lightHandle)
virtual const renderEntity_t * GetRenderEntity(qhandle_t entityHandle) const
int GetNumPoints(void) const
Definition: Winding.h:238
idRenderModelDecal * decals
Definition: tr_local.h:282
GLuint index
Definition: glext.h:3476
const GLubyte * c
Definition: glext.h:4677
virtual bool FastWorldTrace(modelTrace_t &trace, const idVec3 &start, const idVec3 &end) const
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3454
Definition: Vector.h:808
idVec3 lightRadius
Definition: RenderWorld.h:178
float Length(void) const
Definition: Vector.h:631
const int LUDICROUS_INDEX
idRenderWorldLocal * world
Definition: tr_local.h:198
void CreateOverlay(const idRenderModel *model, const idPlane localTextureAxis[2], const idMaterial *material)
viewDef_t * primaryView
Definition: tr_local.h:776
GLuint GLuint end
Definition: glext.h:2845
void Clear()
Definition: GuiModel.cpp:52
areaReference_t * references
Definition: tr_local.h:229
localTrace_t R_LocalTrace(const idVec3 &start, const idVec3 &end, const float radius, const srfTriangles_t *tri)
Definition: tr_trace.cpp:43
idBounds bounds
Definition: Model.h:87
bool R_IssueEntityDefCallback(idRenderEntityLocal *def)
Definition: tr_light.cpp:1060
int lastModifiedFrameNum
Definition: tr_local.h:204
float GetRadius(void) const
Definition: Sphere.h:169
renderView_t renderView
Definition: tr_local.h:370
idCommon * common
Definition: Common.cpp:206
idJointMat * joints
Definition: RenderWorld.h:135
#define PLANESIDE_BACK
Definition: Plane.h:54
virtual bool ModelTrace(modelTrace_t &trace, qhandle_t entityHandle, const idVec3 &start, const idVec3 &end, const float radius) const
void R_FreeEntityDefDerivedData(idRenderEntityLocal *def, bool keepDecals, bool keepCachedDynamicModel)
#define NULL
Definition: Lib.h:88
struct portal_s * next
srfTriangles_t * geometry
Definition: Model.h:147
const idDeclSkin * customSkin
Definition: RenderWorld.h:125
float fraction
Definition: tr_local.h:1660
const idMaterial * globalMaterial
Definition: RenderWorld.h:224
float y
Definition: Vector.h:319
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
struct areaReference_s * ownerNext
Definition: tr_local.h:144
void * callbackData
Definition: RenderWorld.h:98
virtual const modelSurface_t * Surface(int surfaceNum) const =0
Definition: Plane.h:71
virtual void DebugScreenRect(const idVec4 &color, const idScreenRect &rect, const viewDef_t *viewDef, const int lifetime=0)
const int GetSurfaceFlags(void) const
Definition: Material.h:500
idBlockAlloc< areaReference_t, 1024 > areaReferenceAllocator
virtual void ProjectDecalOntoWorld(const idFixedWinding &winding, const idVec3 &projectionOrigin, const bool parallel, const float fadeDepth, const idMaterial *material, const int startTime)
virtual ~idRenderWorldLocal()
void Clear(void)
Definition: Str.h:724
bool isMirror
Definition: tr_local.h:390
void FromTransformedBounds(const idBounds &bounds, const idVec3 &origin, const idMat3 &axis)
Definition: Bounds.cpp:232
void BoundsInAreas_r(int nodeNum, const idBounds &bounds, int *areas, int *numAreas, int maxAreas) const
virtual int NearestJoint(int surfaceNum, int a, int c, int b) const =0
void RenderViewToViewport(const renderView_t *renderView, idScreenRect *viewport)
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)
#define DEG2RAD(a)
Definition: Math.h:56
float RB_DrawTextLength(const char *text, float scale, int len)
idCVar r_useInteractionTable("r_useInteractionTable","1", CVAR_RENDERER|CVAR_BOOL,"create a full entityDefs * lightDefs table to make finding interactions faster")
virtual idBounds Bounds(const struct renderEntity_s *ent=NULL) const =0
virtual void DebugWinding(const idVec4 &color, const idWinding &w, const idVec3 &origin, const idMat3 &axis, const int lifetime=0, const bool depthTest=false)
void R_ListRenderLightDefs_f(const idCmdArgs &args)
Definition: RenderWorld.cpp:39
GLfloat GLfloat v1
Definition: glext.h:3607
GLdouble GLdouble GLdouble top
Definition: qgl.h:273
idVec3 point
Definition: tr_local.h:1662
void RecurseProcBSP_r(modelTrace_t *results, int parentNodeNum, int nodeNum, float p1f, float p2f, const idVec3 &p1, const idVec3 &p2) const
idDeclManager * declManager
virtual int NumPortalsInArea(int areaNum)
virtual int NumAreas(void) const
virtual void DebugClearLines(int time)
void R_ListRenderEntityDefs_f(const idCmdArgs &args)
Definition: RenderWorld.cpp:83
static const float TWO_PI
Definition: Math.h:206
virtual guiPoint_t GuiTrace(qhandle_t entityHandle, const idVec3 start, const idVec3 end) const
idCVar r_skipFrontEnd("r_skipFrontEnd","0", CVAR_RENDERER|CVAR_BOOL,"bypasses all front end work, but 2D gui rendering still draws")
const char * GetString(void) const
Definition: CVarSystem.h:141
idWinding * w
void R_CreateLightDefFogPortals(idRenderLightLocal *ldef)
void R_GlobalPointToLocal(const float modelMatrix[16], const idVec3 &in, idVec3 &out)
Definition: tr_main.cpp:522
virtual void GenerateAllInteractions()
void R_RenderView(viewDef_t *parms)
Definition: tr_main.cpp:1095
idVec3 vieworg
Definition: RenderWorld.h:215
viewDef_t * viewDef
Definition: tr_local.h:786
idVec3 normal
Definition: RenderWorld.h:248
int Append(const type &obj)
Definition: List.h:646
bool isSubview
Definition: tr_local.h:389
void R_FreeEntityDefDecals(idRenderEntityLocal *def)
const char * playerModelExcludeList[]
float DrawTextLength(const char *text, float scale, int len=0)
idRenderModel * prelightModel
Definition: RenderWorld.h:194
Definition: Matrix.h:333
idVec3 point
Definition: RenderWorld.h:247
bool LineIntersection(const idVec3 &start, const idVec3 &end) const
Definition: Bounds.cpp:135
void CreateLightDefInteractions(idRenderLightLocal *ldef)
Definition: tr_light.cpp:541
virtual void SetRenderView(const renderView_t *renderView)
bool GetBool(void) const
Definition: CVarSystem.h:142
glconfig_t glConfig
tuple f
Definition: idal.py:89
void * R_ClearedStaticAlloc(int bytes)
Definition: tr_main.cpp:322
bool IsCleared(void) const
Definition: Bounds.h:222
void R_DeriveLightData(idRenderLightLocal *light)
int Num(void) const
Definition: List.h:265
int FindNull(void) const
Definition: List.h:804
bool IntersectsBounds(const idBounds &a) const
Definition: Bounds.h:361
Definition: quaddefs.h:113
portalArea_t * portalAreas
virtual void DebugCone(const idVec4 &color, const idVec3 &apex, const idVec3 &dir, float radius1, float radius2, const int lifetime=0)
const GLcharARB * name
Definition: glext.h:3629
GLsizeiptr size
Definition: glext.h:3112
virtual void DebugAxis(const idVec3 &origin, const idMat3 &axis)
virtual int PointInArea(const idVec3 &point) const
idScreenRect scissor
Definition: tr_local.h:400
void CreateDecal(const idRenderModel *model, const decalProjectionInfo_t &localInfo)
Definition: ModelDecal.cpp:295
Definition: Str.h:116
idBounds bounds
Definition: RenderWorld.h:95
idRenderModelOverlay * overlay
Definition: tr_local.h:283
int areas[2]
Definition: RenderWorld.h:230
struct portalArea_s * area
Definition: tr_local.h:147
virtual int NumBaseSurfaces() const =0
idRenderEntityLocal * entity
Definition: tr_local.h:145
class idUserInterface * gui[MAX_RENDERENTITY_GUI]
Definition: RenderWorld.h:130
portal_t * portals
areaReference_t entityRefs
idRenderSystemLocal tr
void AddLightRefToArea(idRenderLightLocal *light, portalArea_t *area)
static idRenderModelDecal * Alloc(void)
Definition: ModelDecal.cpp:70
struct areaReference_s * areaNext
Definition: tr_local.h:142
const renderEntity_t * entity
Definition: RenderWorld.h:250
static void GlobalProjectionInfoToLocal(decalProjectionInfo_t &localInfo, const decalProjectionInfo_t &info, const idVec3 &origin, const idMat3 &axis)
Definition: ModelDecal.cpp:181
idRenderLightLocal * light
Definition: tr_local.h:146
idVec3 initialViewAreaOrigin
Definition: tr_local.h:379
float fraction
Definition: RenderWorld.h:246
void PushVolumeIntoTree(idRenderEntityLocal *def, idRenderLightLocal *light, int numPoints, const idVec3(*points))
short y1
Definition: tr_local.h:55
GLint j
Definition: qgl.h:264
bool isInitialized
Definition: RenderSystem.h:98
struct doublePortal_s * doublePortal
idSession * session
Definition: Session.cpp:48
idInteraction * firstInteraction
Definition: tr_local.h:286
idRenderWorldLocal * renderWorld
Definition: tr_local.h:375
void RB_AddDebugLine(const idVec4 &color, const idVec3 &start, const idVec3 &end, const int lifeTime, const bool depthTest)
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
Definition: Bounds.cpp:108
virtual void ProjectDecal(qhandle_t entityHandle, const idFixedWinding &winding, const idVec3 &projectionOrigin, const bool parallel, const float fadeDepth, const idMaterial *material, const int startTime)
void R_StaticFree(void *data)
Definition: tr_main.cpp:335
renderEntity_t parms
Definition: tr_local.h:251
short y2
Definition: tr_local.h:55
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
GLfloat GLfloat p
Definition: glext.h:4674
const idMaterial * shader
Definition: RenderWorld.h:200
idRenderEntityLocal * entityDef
Definition: Interaction.h:105
idMat3 viewaxis
Definition: RenderWorld.h:216
virtual void ProjectOverlay(qhandle_t entityHandle, const idPlane localTextureAxis[2], const idMaterial *material)
void R_AxisToModelMatrix(const idMat3 &axis, const idVec3 &origin, float modelMatrix[16])
Definition: tr_main.cpp:445
void R_FreeLightDefDerivedData(idRenderLightLocal *ldef)
GLdouble GLdouble z
Definition: glext.h:3067
virtual void FreeEntityDef(qhandle_t entityHandle)
void Zero(void)
Definition: Vector.h:415
idCVar r_materialOverride("r_materialOverride","", CVAR_RENDERER,"overrides all materials", idCmdSystem::ArgCompletion_Decl< DECL_MATERIAL >)
void RB_ClearDebugLines(int time)
void NormalVectors(idVec3 &left, idVec3 &down) const
Definition: Vector.h:727
Definition: Box.h:40
renderView_t primaryRenderView
Definition: tr_local.h:775
void R_ClearEntityDefDynamicModel(idRenderEntityLocal *def)
GLuint start
Definition: glext.h:2845
idVec4 colorBlue
Definition: Lib.cpp:119
struct areaReference_s * areaPrev
Definition: tr_local.h:143
virtual void DebugFrustum(const idVec4 &color, const idFrustum &frustum, const bool showFromOrigin=false, const int lifetime=0)
const char * playerMaterialExcludeList[]
void RB_ClearDebugText(int time)
virtual int BoundsInAreas(const idBounds &bounds, int *areas, int maxAreas) const
void RB_AddDebugText(const char *text, const idVec3 &origin, float scale, const idVec4 &color, const idMat3 &viewAxis, const int align, const int lifetime, const bool depthTest)
virtual int NumSurfaces() const =0