doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
BrushBSP.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 "Brush.h"
33 #include "BrushBSP.h"
34 
35 
36 #define BSP_GRID_SIZE 512.0f
37 #define SPLITTER_EPSILON 0.1f
38 #define VERTEX_MELT_EPSILON 0.1f
39 #define VERTEX_MELT_HASH_SIZE 32
40 
41 #define PORTAL_PLANE_NORMAL_EPSILON 0.00001f
42 #define PORTAL_PLANE_DIST_EPSILON 0.01f
43 
44 //#define OUPUT_BSP_STATS_PER_GRID_CELL
45 
46 
47 //===============================================================
48 //
49 // idBrushBSPPortal
50 //
51 //===============================================================
52 
53 /*
54 ============
55 idBrushBSPPortal::idBrushBSPPortal
56 ============
57 */
59  planeNum = -1;
60  winding = NULL;
61  nodes[0] = nodes[1] = NULL;
62  next[0] = next[1] = NULL;
63  faceNum = 0;
64  flags = 0;
65 }
66 
67 /*
68 ============
69 idBrushBSPPortal::~idBrushBSPPortal
70 ============
71 */
73  if ( winding ) {
74  delete winding;
75  }
76 }
77 
78 /*
79 ============
80 idBrushBSPPortal::AddToNodes
81 ============
82 */
84  if ( nodes[0] || nodes[1] ) {
85  common->Error( "AddToNode: allready included" );
86  }
87 
88  assert( front && back );
89 
90  nodes[0] = front;
91  next[0] = front->portals;
92  front->portals = this;
93 
94  nodes[1] = back;
95  next[1] = back->portals;
96  back->portals = this;
97 }
98 
99 /*
100 ============
101 idBrushBSPPortal::RemoveFromNode
102 ============
103 */
105  idBrushBSPPortal **pp, *t;
106 
107  // remove reference to the current portal
108  pp = &l->portals;
109  while (1)
110  {
111  t = *pp;
112  if ( !t ) {
113  common->Error( "idBrushBSPPortal::RemoveFromNode: portal not in node" );
114  }
115 
116  if ( t == this ) {
117  break;
118  }
119 
120  if ( t->nodes[0] == l ) {
121  pp = &t->next[0];
122  }
123  else if ( t->nodes[1] == l ) {
124  pp = &t->next[1];
125  }
126  else {
127  common->Error( "idBrushBSPPortal::RemoveFromNode: portal not bounding node" );
128  }
129  }
130 
131  if ( nodes[0] == l ) {
132  *pp = next[0];
133  nodes[0] = NULL;
134  }
135  else if ( nodes[1] == l ) {
136  *pp = next[1];
137  nodes[1] = NULL;
138  }
139  else {
140  common->Error( "idBrushBSPPortal::RemoveFromNode: mislinked portal" );
141  }
142 }
143 
144 /*
145 ============
146 idBrushBSPPortal::Flip
147 ============
148 */
150  idBrushBSPNode *frontNode, *backNode;
151 
152  frontNode = nodes[0];
153  backNode = nodes[1];
154 
155  if ( frontNode ) {
156  RemoveFromNode( frontNode );
157  }
158  if ( backNode ) {
159  RemoveFromNode( backNode );
160  }
161  AddToNodes( frontNode, backNode );
162 
163  plane = -plane;
164  planeNum ^= 1;
165  winding->ReverseSelf();
166 }
167 
168 /*
169 ============
170 idBrushBSPPortal::Split
171 ============
172 */
173 int idBrushBSPPortal::Split( const idPlane &splitPlane, idBrushBSPPortal **front, idBrushBSPPortal **back ) {
174  idWinding *frontWinding, *backWinding;
175 
176  (*front) = (*back) = NULL;
177  winding->Split( splitPlane, 0.1f, &frontWinding, &backWinding );
178  if ( frontWinding ) {
179  (*front) = new idBrushBSPPortal();
180  (*front)->plane = plane;
181  (*front)->planeNum = planeNum;
182  (*front)->flags = flags;
183  (*front)->winding = frontWinding;
184  }
185  if ( backWinding ) {
186  (*back) = new idBrushBSPPortal();
187  (*back)->plane = plane;
188  (*back)->planeNum = planeNum;
189  (*back)->flags = flags;
190  (*back)->winding = backWinding;
191  }
192 
193  if ( frontWinding && backWinding ) {
194  return PLANESIDE_CROSS;
195  }
196  else if ( frontWinding ) {
197  return PLANESIDE_FRONT;
198  }
199  else {
200  return PLANESIDE_BACK;
201  }
202 }
203 
204 
205 //===============================================================
206 //
207 // idBrushBSPNode
208 //
209 //===============================================================
210 
211 /*
212 ============
213 idBrushBSPNode::idBrushBSPNode
214 ============
215 */
217  brushList.Clear();
218  contents = 0;
219  flags = 0;
220  volume = NULL;
221  portals = NULL;
222  children[0] = children[1] = NULL;
223  areaNum = 0;
224  occupied = 0;
225 }
226 
227 /*
228 ============
229 idBrushBSPNode::~idBrushBSPNode
230 ============
231 */
234 
235  // delete brushes
236  brushList.Free();
237 
238  // delete volume brush
239  if ( volume ) {
240  delete volume;
241  }
242 
243  // delete portals
244  for ( p = portals; p; p = portals ) {
245  p->RemoveFromNode( this );
246  if ( !p->nodes[0] && !p->nodes[1] ) {
247  delete p;
248  }
249  }
250 }
251 
252 /*
253 ============
254 idBrushBSPNode::SetContentsFromBrushes
255 ============
256 */
258  idBrush *brush;
259 
260  contents = 0;
261  for ( brush = brushList.Head(); brush; brush = brush->Next() ) {
262  contents |= brush->GetContents();
263  }
264 }
265 
266 /*
267 ============
268 idBrushBSPNode::GetPortalBounds
269 ============
270 */
272  int s, i;
274  idBounds bounds;
275 
276  bounds.Clear();
277  for ( p = portals; p; p = p->next[s] ) {
278  s = (p->nodes[1] == this);
279 
280  for ( i = 0; i < p->winding->GetNumPoints(); i++ ) {
281  bounds.AddPoint( (*p->winding)[i].ToVec3() );
282  }
283  }
284  return bounds;
285 }
286 
287 /*
288 ============
289 idBrushBSPNode::TestLeafNode
290 ============
291 */
293  int s, n;
294  float d;
296  idVec3 center;
297  idPlane plane;
298 
299  n = 0;
300  center = vec3_origin;
301  for ( p = portals; p; p = p->next[s] ) {
302  s = (p->nodes[1] == this);
303  center += p->winding->GetCenter();
304  n++;
305  }
306 
307  center /= n;
308 
309  for ( p = portals; p; p = p->next[s] ) {
310  s = (p->nodes[1] == this);
311  if ( s ) {
312  plane = -p->GetPlane();
313  }
314  else {
315  plane = p->GetPlane();
316  }
317  d = plane.Distance( center );
318  if ( d < 0.0f ) {
319  return false;
320  }
321  }
322  return true;
323 }
324 
325 /*
326 ============
327 idBrushBSPNode::Split
328 ============
329 */
330 bool idBrushBSPNode::Split( const idPlane &splitPlane, int splitPlaneNum ) {
331  int s, i;
332  idWinding *mid;
333  idBrushBSPPortal *p, *midPortal, *newPortals[2];
334  idBrushBSPNode *newNodes[2];
335 
336  mid = new idWinding( splitPlane.Normal(), splitPlane.Dist() );
337 
338  for ( p = portals; p && mid; p = p->next[s] ) {
339  s = (p->nodes[1] == this);
340  if ( s ) {
341  mid = mid->Clip( -p->plane, 0.1f, false );
342  }
343  else {
344  mid = mid->Clip( p->plane, 0.1f, false );
345  }
346  }
347 
348  if ( !mid ) {
349  return false;
350  }
351 
352  // allocate two new nodes
353  for ( i = 0; i < 2; i++ ) {
354  newNodes[i] = new idBrushBSPNode();
355  newNodes[i]->flags = flags;
356  newNodes[i]->contents = contents;
357  newNodes[i]->parent = this;
358  }
359 
360  // split all portals of the node
361  for ( p = portals; p; p = portals ) {
362  s = (p->nodes[1] == this);
363  p->Split( splitPlane, &newPortals[0], &newPortals[1] );
364  for ( i = 0; i < 2; i++ ) {
365  if ( newPortals[i] ) {
366  if ( s ) {
367  newPortals[i]->AddToNodes( p->nodes[0], newNodes[i] );
368  }
369  else {
370  newPortals[i]->AddToNodes( newNodes[i], p->nodes[1] );
371  }
372  }
373  }
374  p->RemoveFromNode( p->nodes[0] );
375  p->RemoveFromNode( p->nodes[1] );
376  delete p;
377  }
378 
379  // add seperating portal
380  midPortal = new idBrushBSPPortal();
381  midPortal->plane = splitPlane;
382  midPortal->planeNum = splitPlaneNum;
383  midPortal->winding = mid;
384  midPortal->AddToNodes( newNodes[0], newNodes[1] );
385 
386  // set new child nodes
387  children[0] = newNodes[0];
388  children[1] = newNodes[1];
389  plane = splitPlane;
390 
391  return true;
392 }
393 
394 /*
395 ============
396 idBrushBSPNode::PlaneSide
397 ============
398 */
399 int idBrushBSPNode::PlaneSide( const idPlane &plane, float epsilon ) const {
400  int s, side;
402  bool front, back;
403 
404  front = back = false;
405  for ( p = portals; p; p = p->next[s] ) {
406  s = (p->nodes[1] == this);
407 
408  side = p->winding->PlaneSide( plane, epsilon );
409  if ( side == SIDE_CROSS || side == SIDE_ON) {
410  return side;
411  }
412  if ( side == SIDE_FRONT ) {
413  if ( back ) {
414  return SIDE_CROSS;
415  }
416  front = true;
417  }
418  if ( side == SIDE_BACK ) {
419  if ( front ) {
420  return SIDE_CROSS;
421  }
422  back = true;
423  }
424  }
425 
426  if ( front ) {
427  return SIDE_FRONT;
428  }
429  return SIDE_BACK;
430 }
431 
432 /*
433 ============
434 idBrushBSPNode::RemoveFlagFlood
435 ============
436 */
438  int s;
440 
441  RemoveFlag( flag );
442 
443  for ( p = GetPortals(); p; p = p->Next(s) ) {
444  s = (p->GetNode(1) == this);
445 
446  if ( !(p->GetNode( !s )->GetFlags() & flag ) ) {
447  continue;
448  }
449 
450  p->GetNode( !s )->RemoveFlagFlood( flag );
451  }
452 }
453 
454 /*
455 ============
456 idBrushBSPNode::RemoveFlagRecurse
457 ============
458 */
460  RemoveFlag( flag );
461  if ( children[0] ) {
462  children[0]->RemoveFlagRecurse( flag );
463  }
464  if ( children[1] ) {
465  children[1]->RemoveFlagRecurse( flag );
466  }
467 }
468 
469 /*
470 ============
471 idBrushBSPNode::RemoveFlagRecurseFlood
472 ============
473 */
475  RemoveFlag( flag );
476  if ( !children[0] && !children[1] ) {
477  RemoveFlagFlood( flag );
478  }
479  else {
480  if ( children[0] ) {
481  children[0]->RemoveFlagRecurseFlood( flag );
482  }
483  if ( children[1] ) {
484  children[1]->RemoveFlagRecurseFlood( flag );
485  }
486  }
487 }
488 
489 
490 //===============================================================
491 //
492 // idBrushBSP
493 //
494 //===============================================================
495 
496 /*
497 ============
498 idBrushBSP::idBrushBSP
499 ============
500 */
502  root = outside = NULL;
504  brushMapContents = 0;
505  brushMap = NULL;
506 }
507 
508 /*
509 ============
510 idBrushBSP::~idBrushBSP
511 ============
512 */
514 
516  Free_r( root );
517 
518  if ( outside ) {
519  delete outside;
520  }
521 }
522 
523 /*
524 ============
525 idBrushBSP::RemoveMultipleLeafNodeReferences_r
526 ============
527 */
529  if ( !node ) {
530  return;
531  }
532 
533  if ( node->children[0] ) {
534  if ( node->children[0]->parent != node ) {
535  node->children[0] = NULL;
536  }
537  else {
539  }
540  }
541  if ( node->children[1] ) {
542  if ( node->children[1]->parent != node ) {
543  node->children[1] = NULL;
544  }
545  else {
547  }
548  }
549 }
550 
551 /*
552 ============
553 idBrushBSP::Free_r
554 ============
555 */
557  if ( !node ) {
558  return;
559  }
560 
561  Free_r( node->children[0] );
562  Free_r( node->children[1] );
563 
564  delete node;
565 }
566 
567 /*
568 ============
569 idBrushBSP::IsValidSplitter
570 ============
571 */
572 ID_INLINE bool idBrushBSP::IsValidSplitter( const idBrushSide *side ) {
573  return !( side->GetFlags() & ( SFL_SPLIT | SFL_USED_SPLITTER ) );
574 }
575 
576 /*
577 ============
578 idBrushBSP::BrushSplitterStats
579 ============
580 */
581 typedef struct splitterStats_s {
582  int numFront; // number of brushes at the front of the splitter
583  int numBack; // number of brushes at the back of the splitter
584  int numSplits; // number of brush sides split by the splitter
585  int numFacing; // number of brushes facing this splitter
586  int epsilonBrushes; // number of tiny brushes this splitter would create
588 
589 int idBrushBSP::BrushSplitterStats( const idBrush *brush, int planeNum, const idPlaneSet &planeList, bool *testedPlanes, struct splitterStats_s &stats ) {
590  int i, j, num, s, lastNumSplits;
591  const idPlane *plane;
592  const idWinding *w;
593  float d, d_front, d_back, brush_front, brush_back;
594 
595  plane = &planeList[planeNum];
596 
597  // get the plane side for the brush bounds
598  s = brush->GetBounds().PlaneSide( *plane, SPLITTER_EPSILON );
599  if ( s == PLANESIDE_FRONT ) {
600  stats.numFront++;
601  return BRUSH_PLANESIDE_FRONT;
602  }
603  if ( s == PLANESIDE_BACK ) {
604  stats.numBack++;
605  return BRUSH_PLANESIDE_BACK;
606  }
607 
608  // if the brush actually uses the planenum, we can tell the side for sure
609  for ( i = 0; i < brush->GetNumSides(); i++ ) {
610  num = brush->GetSide( i )->GetPlaneNum();
611 
612  if ( !(( num ^ planeNum ) >> 1) ) {
613  if ( num == planeNum ) {
614  stats.numBack++;
615  stats.numFacing++;
617  }
618  if ( num == ( planeNum ^ 1 ) ) {
619  stats.numFront++;
620  stats.numFacing++;
622  }
623  }
624  }
625 
626  lastNumSplits = stats.numSplits;
627  brush_front = brush_back = 0.0f;
628  for ( i = 0; i < brush->GetNumSides(); i++ ) {
629 
630  if ( !IsValidSplitter( brush->GetSide( i ) ) ) {
631  continue;
632  }
633 
634  j = brush->GetSide( i )->GetPlaneNum();
635  if ( testedPlanes[j] || testedPlanes[j^1] ) {
636  continue;
637  }
638 
639  w = brush->GetSide(i)->GetWinding();
640  if ( !w ) {
641  continue;
642  }
643  d_front = d_back = 0.0f;
644  for ( j = 0; j < w->GetNumPoints(); j++ ) {
645  d = plane->Distance( (*w)[j].ToVec3() );
646  if ( d > d_front ) {
647  d_front = d;
648  }
649  else if ( d < d_back ) {
650  d_back = d;
651  }
652  }
653  if ( d_front > SPLITTER_EPSILON && d_back < -SPLITTER_EPSILON ) {
654  stats.numSplits++;
655  }
656  if ( d_front > brush_front ) {
657  brush_front = d_front;
658  }
659  else if ( d_back < brush_back ) {
660  brush_back = d_back;
661  }
662  }
663 
664  // if brush sides are split and the brush only pokes one unit through the plane
665  if ( stats.numSplits > lastNumSplits && (brush_front < 1.0f || brush_back > -1.0f) ) {
666  stats.epsilonBrushes++;
667  }
668 
669  return BRUSH_PLANESIDE_BOTH;
670 }
671 
672 /*
673 ============
674 idBrushBSP::FindSplitter
675 ============
676 */
677 int idBrushBSP::FindSplitter( idBrushBSPNode *node, const idPlaneSet &planeList, bool *testedPlanes, struct splitterStats_s &bestStats ) {
678  int i, planeNum, bestSplitter, value, bestValue, f, numBrushSides;
679  idBrush *brush, *b;
680  splitterStats_t stats;
681 
682  memset( testedPlanes, 0, planeList.Num() * sizeof( bool ) );
683 
684  bestSplitter = -1;
685  bestValue = -99999999;
686  for ( brush = node->brushList.Head(); brush; brush = brush->Next() ) {
687 
688  if ( brush->GetFlags() & BFL_NO_VALID_SPLITTERS ) {
689  continue;
690  }
691 
692  for ( i = 0; i < brush->GetNumSides(); i++ ) {
693 
694  if ( !IsValidSplitter( brush->GetSide(i) ) ) {
695  continue;
696  }
697 
698  planeNum = brush->GetSide(i)->GetPlaneNum();
699 
700  if ( testedPlanes[planeNum] || testedPlanes[planeNum^1] ) {
701  continue;
702  }
703 
704  testedPlanes[planeNum] = testedPlanes[planeNum^1] = true;
705 
706  if ( node->volume->Split( planeList[planeNum], planeNum, NULL, NULL ) != PLANESIDE_CROSS ) {
707  continue;
708  }
709 
710  memset( &stats, 0, sizeof( stats ) );
711 
712  f = 15 + 5 * (brush->GetSide(i)->GetPlane().Type() < PLANETYPE_TRUEAXIAL);
713  numBrushSides = node->brushList.NumSides();
714 
715  for ( b = node->brushList.Head(); b; b = b->Next() ) {
716 
717  // if the brush has no valid splitters left
718  if ( b->GetFlags() & BFL_NO_VALID_SPLITTERS ) {
720  }
721  else {
722  b->SetPlaneSide( BrushSplitterStats( b, planeNum, planeList, testedPlanes, stats ) );
723  }
724 
725  numBrushSides -= b->GetNumSides();
726  // best value we can get using this plane as a splitter
727  value = f * (stats.numFacing + numBrushSides) - 10 * stats.numSplits - stats.epsilonBrushes * 1000;
728  // if the best value for this plane can't get any better than the best value we have
729  if ( value < bestValue ) {
730  break;
731  }
732  }
733 
734  if ( b ) {
735  continue;
736  }
737 
738  value = f * stats.numFacing - 10 * stats.numSplits - abs(stats.numFront - stats.numBack) - stats.epsilonBrushes * 1000;
739 
740  if ( value > bestValue ) {
741  bestValue = value;
742  bestSplitter = planeNum;
743  bestStats = stats;
744 
745  for ( b = node->brushList.Head(); b; b = b->Next() ) {
746  b->SavePlaneSide();
747  }
748  }
749  }
750  }
751 
752  return bestSplitter;
753 }
754 
755 /*
756 ============
757 idBrushBSP::SetSplitterUsed
758 ============
759 */
760 void idBrushBSP::SetSplitterUsed( idBrushBSPNode *node, int planeNum ) {
761  int i, numValidBrushSplitters;
762  idBrush *brush;
763 
764  for ( brush = node->brushList.Head(); brush; brush = brush->Next() ) {
765  if ( !( brush->GetSavedPlaneSide() & BRUSH_PLANESIDE_FACING ) ) {
766  continue;
767  }
768  numValidBrushSplitters = 0;
769  for ( i = 0; i < brush->GetNumSides(); i++ ) {
770 
771  if ( !(( brush->GetSide(i)->GetPlaneNum() ^ planeNum ) >> 1) ) {
772  brush->GetSide(i)->SetFlag( SFL_USED_SPLITTER );
773  }
774  else if ( IsValidSplitter( brush->GetSide(i) ) ) {
775  numValidBrushSplitters++;
776  }
777  }
778  if ( numValidBrushSplitters == 0 ) {
780  }
781  }
782 }
783 
784 /*
785 ============
786 idBrushBSP::BuildBrushBSP_r
787 ============
788 */
789 idBrushBSPNode *idBrushBSP::BuildBrushBSP_r( idBrushBSPNode *node, const idPlaneSet &planeList, bool *testedPlanes, int skipContents ) {
790  int planeNum;
791  splitterStats_t bestStats;
792 
793  planeNum = FindSplitter( node, planeList, testedPlanes, bestStats );
794 
795  // if no split plane found this is a leaf node
796  if ( planeNum == -1 ) {
797 
798  node->SetContentsFromBrushes();
799 
800  if ( brushMap && ( node->contents & brushMapContents ) ) {
801  brushMap->WriteBrush( node->volume );
802  }
803 
804  // free node memory
805  node->brushList.Free();
806  delete node->volume;
807  node->volume = NULL;
808 
809  node->children[0] = node->children[1] = NULL;
810  return node;
811  }
812 
813  numSplits++;
815 
816  // mark all brush sides on the split plane as used
817  SetSplitterUsed( node, planeNum );
818 
819  // set node split plane
820  node->plane = planeList[planeNum];
821 
822  // allocate children
823  node->children[0] = new idBrushBSPNode();
824  node->children[1] = new idBrushBSPNode();
825 
826  // split node volume and brush list for children
827  node->volume->Split( node->plane, -1, &node->children[0]->volume, &node->children[1]->volume );
828  node->brushList.Split( node->plane, -1, node->children[0]->brushList, node->children[1]->brushList, true );
829  node->children[0]->parent = node->children[1]->parent = node;
830 
831  // free node memory
832  node->brushList.Free();
833  delete node->volume;
834  node->volume = NULL;
835 
836  // process children
837  node->children[0] = BuildBrushBSP_r( node->children[0], planeList, testedPlanes, skipContents );
838  node->children[1] = BuildBrushBSP_r( node->children[1], planeList, testedPlanes, skipContents );
839 
840  // if both children contain the skip contents
841  if ( node->children[0]->contents & node->children[1]->contents & skipContents ) {
842  node->contents = node->children[0]->contents | node->children[1]->contents;
843  delete node->children[0];
844  delete node->children[1];
845  node->children[0] = node->children[1] = NULL;
846  numSplits--;
848  }
849 
850  return node;
851 }
852 
853 /*
854 ============
855 idBrushBSP::ProcessGridCell
856 ============
857 */
859  idPlaneSet planeList;
860  bool *testedPlanes;
861 
862 #ifdef OUPUT_BSP_STATS_PER_GRID_CELL
863  common->Printf( "[Grid Cell %d]\n", ++numGridCells );
864  common->Printf( "%6d brushes\n", node->brushList.Num() );
865 #endif
866 
867  numGridCellSplits = 0;
868 
869  // chop away all brush overlap
871 
872  // merge brushes if possible
873  //node->brushList.Merge( BrushMergeAllowed );
874 
875  // create a list with planes for this grid cell
876  node->brushList.CreatePlaneList( planeList );
877 
878 #ifdef OUPUT_BSP_STATS_PER_GRID_CELL
879  common->Printf( "[Grid Cell BSP]\n" );
880 #endif
881 
882  testedPlanes = new bool[planeList.Num()];
883 
884  BuildBrushBSP_r( node, planeList, testedPlanes, skipContents );
885 
886  delete testedPlanes;
887 
888 #ifdef OUPUT_BSP_STATS_PER_GRID_CELL
889  common->Printf( "\r%6d splits\n", numGridCellSplits );
890 #endif
891 
892  return node;
893 }
894 
895 /*
896 ============
897 idBrushBSP::BuildGrid_r
898 ============
899 */
901  int axis;
902  float dist;
903  idBounds bounds;
904  idVec3 normal, halfSize;
905 
906  if ( !node->brushList.Num() ) {
907  delete node->volume;
908  node->volume = NULL;
909  node->children[0] = node->children[1] = NULL;
910  return;
911  }
912 
913  bounds = node->volume->GetBounds();
914  halfSize = (bounds[1] - bounds[0]) * 0.5f;
915  for ( axis = 0; axis < 3; axis++ ) {
916  if ( halfSize[axis] > BSP_GRID_SIZE ) {
917  dist = BSP_GRID_SIZE * ( floor( (bounds[0][axis] + halfSize[axis]) / BSP_GRID_SIZE ) + 1 );
918  }
919  else {
920  dist = BSP_GRID_SIZE * ( floor( bounds[0][axis] / BSP_GRID_SIZE ) + 1 );
921  }
922  if ( dist > bounds[0][axis] + 1.0f && dist < bounds[1][axis] - 1.0f ) {
923  break;
924  }
925  }
926  if ( axis >= 3 ) {
927  gridCells.Append( node );
928  return;
929  }
930 
931  numSplits++;
932 
933  normal = vec3_origin;
934  normal[axis] = 1.0f;
935  node->plane.SetNormal( normal );
936  node->plane.SetDist( (int) dist );
937 
938  // allocate children
939  node->children[0] = new idBrushBSPNode();
940  node->children[1] = new idBrushBSPNode();
941 
942  // split volume and brush list for children
943  node->volume->Split( node->plane, -1, &node->children[0]->volume, &node->children[1]->volume );
944  node->brushList.Split( node->plane, -1, node->children[0]->brushList, node->children[1]->brushList );
947  node->children[0]->parent = node->children[1]->parent = node;
948 
949  // free node memory
950  node->brushList.Free();
951  delete node->volume;
952  node->volume = NULL;
953 
954  // process children
955  BuildGrid_r( gridCells, node->children[0] );
956  BuildGrid_r( gridCells, node->children[1] );
957 }
958 
959 /*
960 ============
961 idBrushBSP::Build
962 ============
963 */
964 void idBrushBSP::Build( idBrushList brushList, int skipContents,
965  bool (*ChopAllowed)( idBrush *b1, idBrush *b2 ),
966  bool (*MergeAllowed)( idBrush *b1, idBrush *b2 ) ) {
967 
968  int i;
969  idList<idBrushBSPNode *> gridCells;
970 
971  common->Printf( "[Brush BSP]\n" );
972  common->Printf( "%6d brushes\n", brushList.Num() );
973 
974  BrushChopAllowed = ChopAllowed;
976 
977  numGridCells = 0;
978  treeBounds = brushList.GetBounds();
979  root = new idBrushBSPNode();
980  root->brushList = brushList;
981  root->volume = new idBrush();
983  root->parent = NULL;
984 
985  BuildGrid_r( gridCells, root );
986 
987  common->Printf( "\r%6d grid cells\n", gridCells.Num() );
988 
989 #ifdef OUPUT_BSP_STATS_PER_GRID_CELL
990  for ( i = 0; i < gridCells.Num(); i++ ) {
991  ProcessGridCell( gridCells[i], skipContents );
992  }
993 #else
994  common->Printf( "\r%6d %%", 0 );
995  for ( i = 0; i < gridCells.Num(); i++ ) {
996  DisplayRealTimeString( "\r%6d", i * 100 / gridCells.Num() );
997  ProcessGridCell( gridCells[i], skipContents );
998  }
999  common->Printf( "\r%6d %%\n", 100 );
1000 #endif
1001 
1002  common->Printf( "\r%6d splits\n", numSplits );
1003 
1004  if ( brushMap ) {
1005  delete brushMap;
1006  }
1007 }
1008 
1009 /*
1010 ============
1011 idBrushBSP::WriteBrushMap
1012 ============
1013 */
1014 void idBrushBSP::WriteBrushMap( const idStr &fileName, const idStr &ext, int contents ) {
1015  brushMap = new idBrushMap( fileName, ext );
1016  brushMapContents = contents;
1017 }
1018 
1019 /*
1020 ============
1021 idBrushBSP::PruneTree_r
1022 ============
1023 */
1024 void idBrushBSP::PruneTree_r( idBrushBSPNode *node, int contents ) {
1025  int i, s;
1026  idBrushBSPNode *nodes[2];
1027  idBrushBSPPortal *p, *nextp;
1028 
1029  if ( !node->children[0] || !node->children[1] ) {
1030  return;
1031  }
1032 
1033  PruneTree_r( node->children[0], contents );
1034  PruneTree_r( node->children[1], contents );
1035 
1036  if ( ( node->children[0]->contents & node->children[1]->contents & contents ) ) {
1037 
1038  node->contents = node->children[0]->contents | node->children[1]->contents;
1039  // move all child portals to parent
1040  for ( i = 0; i < 2; i++ ) {
1041  for ( p = node->children[i]->portals; p; p = nextp ) {
1042  s = ( p->nodes[1] == node->children[i] );
1043  nextp = p->next[s];
1044  nodes[s] = node;
1045  nodes[!s] = p->nodes[!s];
1046  p->RemoveFromNode( p->nodes[0] );
1047  p->RemoveFromNode( p->nodes[1] );
1048  if ( nodes[!s] == node->children[!i] ) {
1049  delete p; // portal seperates both children
1050  }
1051  else {
1052  p->AddToNodes( nodes[0], nodes[1] );
1053  }
1054  }
1055  }
1056 
1057  delete node->children[0];
1058  delete node->children[1];
1059  node->children[0] = NULL;
1060  node->children[1] = NULL;
1061 
1062  numPrunedSplits++;
1063  }
1064 }
1065 
1066 /*
1067 ============
1068 idBrushBSP::PruneTree
1069 ============
1070 */
1071 void idBrushBSP::PruneTree( int contents ) {
1072  numPrunedSplits = 0;
1073  common->Printf( "[Prune BSP]\n" );
1074  PruneTree_r( root, contents );
1075  common->Printf( "%6d splits pruned\n", numPrunedSplits );
1076 }
1077 
1078 /*
1079 ============
1080 idBrushBSP::BaseWindingForNode
1081 ============
1082 */
1083 #define BASE_WINDING_EPSILON 0.001f
1084 
1086  idWinding *w;
1087  idBrushBSPNode *n;
1088 
1089  w = new idWinding( node->plane.Normal(), node->plane.Dist() );
1090 
1091  // clip by all the parents
1092  for ( n = node->parent; n && w; n = n->parent ) {
1093 
1094  if ( n->children[0] == node ) {
1095  // take front
1096  w = w->Clip( n->plane, BASE_WINDING_EPSILON );
1097  }
1098  else {
1099  // take back
1100  w = w->Clip( -n->plane, BASE_WINDING_EPSILON );
1101  }
1102  node = n;
1103  }
1104 
1105  return w;
1106 }
1107 
1108 /*
1109 ============
1110 idBrushBSP::MakeNodePortal
1111 
1112  create the new portal by taking the full plane winding for the cutting
1113  plane and clipping it by all of parents of this node
1114 ============
1115 */
1117  idBrushBSPPortal *newPortal, *p;
1118  idWinding *w;
1119  int side;
1120 
1121  w = BaseWindingForNode( node );
1122 
1123  // clip the portal by all the other portals in the node
1124  for ( p = node->portals; p && w; p = p->next[side] ) {
1125  if ( p->nodes[0] == node ) {
1126  side = 0;
1127  w = w->Clip( p->plane, 0.1f );
1128  }
1129  else if ( p->nodes[1] == node ) {
1130  side = 1;
1131  w = w->Clip( -p->plane, 0.1f );
1132  }
1133  else {
1134  common->Error( "MakeNodePortal: mislinked portal" );
1135  }
1136  }
1137 
1138  if ( !w ) {
1139  return;
1140  }
1141 
1142  if ( w->IsTiny() ) {
1143  delete w;
1144  return;
1145  }
1146 
1147  newPortal = new idBrushBSPPortal();
1148  newPortal->plane = node->plane;
1149  newPortal->winding = w;
1150  newPortal->AddToNodes( node->children[0], node->children[1] );
1151 }
1152 
1153 /*
1154 ============
1155 idBrushBSP::SplitNodePortals
1156 
1157  Move or split the portals that bound the node so that the node's children have portals instead of node.
1158 ============
1159 */
1160 #define SPLIT_WINDING_EPSILON 0.001f
1161 
1163  int side;
1164  idBrushBSPPortal *p, *nextPortal, *newPortal;
1165  idBrushBSPNode *f, *b, *otherNode;
1166  idPlane *plane;
1167  idWinding *frontWinding, *backWinding;
1168 
1169  plane = &node->plane;
1170  f = node->children[0];
1171  b = node->children[1];
1172 
1173  for ( p = node->portals; p; p = nextPortal ) {
1174  if (p->nodes[0] == node) {
1175  side = 0;
1176  }
1177  else if (p->nodes[1] == node) {
1178  side = 1;
1179  }
1180  else {
1181  common->Error( "idBrushBSP::SplitNodePortals: mislinked portal" );
1182  }
1183  nextPortal = p->next[side];
1184 
1185  otherNode = p->nodes[!side];
1186  p->RemoveFromNode( p->nodes[0] );
1187  p->RemoveFromNode( p->nodes[1] );
1188 
1189  // cut the portal into two portals, one on each side of the cut plane
1190  p->winding->Split( *plane, SPLIT_WINDING_EPSILON, &frontWinding, &backWinding );
1191 
1192  if ( frontWinding && frontWinding->IsTiny() ) {
1193  delete frontWinding;
1194  frontWinding = NULL;
1195  //tinyportals++;
1196  }
1197 
1198  if ( backWinding && backWinding->IsTiny() ) {
1199  delete backWinding;
1200  backWinding = NULL;
1201  //tinyportals++;
1202  }
1203 
1204  if ( !frontWinding && !backWinding ) {
1205  // tiny windings on both sides
1206  continue;
1207  }
1208 
1209  if ( !frontWinding ) {
1210  delete backWinding;
1211  if ( side == 0 ) {
1212  p->AddToNodes( b, otherNode );
1213  }
1214  else {
1215  p->AddToNodes( otherNode, b );
1216  }
1217  continue;
1218  }
1219  if ( !backWinding ) {
1220  delete frontWinding;
1221  if ( side == 0 ) {
1222  p->AddToNodes( f, otherNode );
1223  }
1224  else {
1225  p->AddToNodes( otherNode, f );
1226  }
1227  continue;
1228  }
1229 
1230  // the winding is split
1231  newPortal = new idBrushBSPPortal();
1232  *newPortal = *p;
1233  newPortal->winding = backWinding;
1234  delete p->winding;
1235  p->winding = frontWinding;
1236 
1237  if ( side == 0 ) {
1238  p->AddToNodes( f, otherNode );
1239  newPortal->AddToNodes( b, otherNode );
1240  }
1241  else {
1242  p->AddToNodes( otherNode, f );
1243  newPortal->AddToNodes( otherNode, b );
1244  }
1245  }
1246 
1247  node->portals = NULL;
1248 }
1249 
1250 /*
1251 ============
1252 idBrushBSP::MakeTreePortals_r
1253 ============
1254 */
1256  int i;
1257  idBounds bounds;
1258 
1259  numPortals++;
1260  DisplayRealTimeString( "\r%6d", numPortals );
1261 
1262  bounds = node->GetPortalBounds();
1263 
1264  if ( bounds[0][0] >= bounds[1][0] ) {
1265  //common->Warning( "node without volume" );
1266  }
1267 
1268  for ( i = 0; i < 3; i++ ) {
1269  if ( bounds[0][i] < MIN_WORLD_COORD || bounds[1][i] > MAX_WORLD_COORD ) {
1270  common->Warning( "node with unbounded volume" );
1271  break;
1272  }
1273  }
1274 
1275  if ( !node->children[0] || !node->children[1] ) {
1276  return;
1277  }
1278 
1279  MakeNodePortal( node );
1280  SplitNodePortals( node );
1281 
1282  MakeTreePortals_r( node->children[0] );
1283  MakeTreePortals_r( node->children[1] );
1284 }
1285 
1286 /*
1287 ============
1288 idBrushBSP::MakeOutsidePortals
1289 ============
1290 */
1292  int i, j, n;
1293  idBounds bounds;
1294  idBrushBSPPortal *p, *portals[6];
1295  idVec3 normal;
1296  idPlane planes[6];
1297 
1298  // pad with some space so there will never be null volume leaves
1299  bounds = treeBounds.Expand( 32 );
1300 
1301  for ( i = 0; i < 3; i++ ) {
1302  if ( bounds[0][i] > bounds[1][i] ) {
1303  common->Error( "empty BSP tree" );
1304  }
1305  }
1306 
1307  outside = new idBrushBSPNode();
1308  outside->parent = NULL;
1309  outside->children[0] = outside->children[1] = NULL;
1310  outside->brushList.Clear();
1311  outside->portals = NULL;
1312  outside->contents = 0;
1313 
1314  for ( i = 0; i < 3; i++ ) {
1315  for ( j = 0; j < 2; j++ ) {
1316 
1317  p = new idBrushBSPPortal();
1318  normal = vec3_origin;
1319  normal[i] = j ? -1 : 1;
1320  p->plane.SetNormal( normal );
1321  p->plane.SetDist( j ? -bounds[j][i] : bounds[j][i] );
1322  p->winding = new idWinding( p->plane.Normal(), p->plane.Dist() );
1323  p->AddToNodes( root, outside );
1324 
1325  n = j * 3 + i;
1326  portals[n] = p;
1327  }
1328  }
1329 
1330  // clip the base windings with all the other planes
1331  for ( i = 0; i < 6; i++ ) {
1332  for ( j = 0; j < 6; j++ ) {
1333  if (j == i) {
1334  continue;
1335  }
1336  portals[i]->winding = portals[i]->winding->Clip( portals[j]->plane, ON_EPSILON );
1337  }
1338  }
1339 }
1340 
1341 /*
1342 ============
1343 idBrushBSP::Portalize
1344 ============
1345 */
1347  common->Printf( "[Portalize BSP]\n" );
1348  common->Printf( "%6d nodes\n", (numSplits - numPrunedSplits) * 2 + 1 );
1349  numPortals = 0;
1352  common->Printf( "\r%6d nodes portalized\n", numPortals );
1353 }
1354 
1355 /*
1356 =============
1357 LeakFile
1358 
1359 Finds the shortest possible chain of portals that
1360 leads from the outside leaf to a specific occupied leaf.
1361 =============
1362 */
1363 void idBrushBSP::LeakFile( const idStr &fileName ) {
1364  int count, next, s;
1365  idVec3 mid;
1366  idFile *lineFile;
1367  idBrushBSPNode *node, *nextNode;
1368  idBrushBSPPortal *p, *nextPortal;
1369  idStr qpath, name;
1370 
1371  if ( !outside->occupied ) {
1372  return;
1373  }
1374 
1375  qpath = fileName;
1376  qpath.SetFileExtension( "lin" );
1377 
1378  common->Printf( "writing %s...\n", qpath.c_str() );
1379 
1380  lineFile = fileSystem->OpenFileWrite( qpath, "fs_devpath" );
1381  if ( !lineFile ) {
1382  common->Error( "Couldn't open %s\n", qpath.c_str() );
1383  return;
1384  }
1385 
1386  count = 0;
1387  node = outside;
1388  while( node->occupied > 1 ) {
1389 
1390  // find the best portal exit
1391  next = node->occupied;
1392  for (p = node->portals; p; p = p->next[!s] ) {
1393  s = (p->nodes[0] == node);
1394  if ( p->nodes[s]->occupied && p->nodes[s]->occupied < next ) {
1395  nextPortal = p;
1396  nextNode = p->nodes[s];
1397  next = nextNode->occupied;
1398  }
1399  }
1400  node = nextNode;
1401  mid = nextPortal->winding->GetCenter();
1402  lineFile->Printf( "%f %f %f\n", mid[0], mid[1], mid[2] );
1403  count++;
1404  }
1405 
1406  // add the origin of the entity from which the leak was found
1407  lineFile->Printf( "%f %f %f\n", leakOrigin[0], leakOrigin[1], leakOrigin[2] );
1408 
1409  fileSystem->CloseFile( lineFile );
1410 }
1411 
1412 /*
1413 ============
1414 idBrushBSP::FloodThroughPortals_r
1415 ============
1416 */
1417 void idBrushBSP::FloodThroughPortals_r( idBrushBSPNode *node, int contents, int depth ) {
1419  int s;
1420 
1421  if ( node->occupied ) {
1422  common->Error( "FloodThroughPortals_r: node already occupied\n" );
1423  }
1424  if ( !node ) {
1425  common->Error( "FloodThroughPortals_r: NULL node\n" );
1426  }
1427 
1428  node->occupied = depth;
1429 
1430  for ( p = node->portals; p; p = p->next[s] ) {
1431  s = (p->nodes[1] == node);
1432 
1433  // if the node at the other side of the portal is removed
1434  if ( !p->nodes[!s] ) {
1435  continue;
1436  }
1437 
1438  // if the node at the other side of the portal is occupied already
1439  if ( p->nodes[!s]->occupied ) {
1440  continue;
1441  }
1442 
1443  // can't flood through the portal if it has the seperating contents at the other side
1444  if ( p->nodes[!s]->contents & contents ) {
1445  continue;
1446  }
1447 
1448  // flood recursively through the current portal
1449  FloodThroughPortals_r( p->nodes[!s], contents, depth+1 );
1450  }
1451 }
1452 
1453 /*
1454 ============
1455 idBrushBSP::FloodFromOrigin
1456 ============
1457 */
1458 bool idBrushBSP::FloodFromOrigin( const idVec3 &origin, int contents ) {
1459  idBrushBSPNode *node;
1460 
1461  //find the leaf to start in
1462  node = root;
1463  while( node->children[0] && node->children[1] ) {
1464 
1465  if ( node->plane.Side( origin ) == PLANESIDE_BACK ) {
1466  node = node->children[1];
1467  }
1468  else {
1469  node = node->children[0];
1470  }
1471  }
1472 
1473  if ( !node ) {
1474  return false;
1475  }
1476 
1477  // if inside the inside/outside seperating contents
1478  if ( node->contents & contents ) {
1479  return false;
1480  }
1481 
1482  // if the node is already occupied
1483  if ( node->occupied ) {
1484  return false;
1485  }
1486 
1487  FloodThroughPortals_r( node, contents, 1 );
1488 
1489  return true;
1490 }
1491 
1492 /*
1493 ============
1494 idBrushBSP::FloodFromEntities
1495 
1496  Marks all nodes that can be reached by entites.
1497 ============
1498 */
1499 bool idBrushBSP::FloodFromEntities( const idMapFile *mapFile, int contents, const idStrList &classNames ) {
1500  int i, j;
1501  bool inside;
1502  idVec3 origin;
1503  idMapEntity *mapEnt;
1504  idStr classname;
1505 
1506  inside = false;
1507  outside->occupied = 0;
1508 
1509  // skip the first entity which is assumed to be the worldspawn
1510  for ( i = 1; i < mapFile->GetNumEntities(); i++ ) {
1511 
1512  mapEnt = mapFile->GetEntity( i );
1513 
1514  if ( !mapEnt->epairs.GetVector( "origin", "", origin ) ) {
1515  continue;
1516  }
1517 
1518  if ( !mapEnt->epairs.GetString( "classname", "", classname ) ) {
1519  continue;
1520  }
1521 
1522  for ( j = 0; j < classNames.Num(); j++ ) {
1523  if ( classname.Icmp( classNames[j] ) == 0 ) {
1524  break;
1525  }
1526  }
1527 
1528  if ( j >= classNames.Num() ) {
1529  continue;
1530  }
1531 
1532  origin[2] += 1;
1533 
1534  // nudge around a little
1535  if ( FloodFromOrigin( origin, contents ) ) {
1536  inside = true;
1537  }
1538 
1539  if ( outside->occupied ) {
1540  leakOrigin = origin;
1541  break;
1542  }
1543  }
1544 
1545  if ( !inside ) {
1546  common->Warning( "no entities inside" );
1547  }
1548  else if ( outside->occupied ) {
1549  common->Warning( "reached outside from entity %d (%s)", i, classname.c_str() );
1550  }
1551 
1552  return ( inside && !outside->occupied );
1553 }
1554 
1555 /*
1556 ============
1557 idBrushBSP::RemoveOutside_r
1558 ============
1559 */
1560 void idBrushBSP::RemoveOutside_r( idBrushBSPNode *node, int contents ) {
1561 
1562  if ( !node ) {
1563  return;
1564  }
1565 
1566  if ( node->children[0] || node->children[1] ) {
1567  RemoveOutside_r( node->children[0], contents );
1568  RemoveOutside_r( node->children[1], contents );
1569  return;
1570  }
1571 
1572  if ( !node->occupied ) {
1573  if ( !( node->contents & contents ) ) {
1574  outsideLeafNodes++;
1575  node->contents |= contents;
1576  }
1577  else {
1578  solidLeafNodes++;
1579  }
1580  }
1581  else {
1582  insideLeafNodes++;
1583  }
1584 }
1585 
1586 /*
1587 ============
1588 idBrushBSP::RemoveOutside
1589 ============
1590 */
1591 bool idBrushBSP::RemoveOutside( const idMapFile *mapFile, int contents, const idStrList &classNames ) {
1592  common->Printf( "[Remove Outside]\n" );
1593 
1595 
1596  if ( !FloodFromEntities( mapFile, contents, classNames ) ) {
1597  return false;
1598  }
1599 
1600  RemoveOutside_r( root, contents );
1601 
1602  common->Printf( "%6d solid leaf nodes\n", solidLeafNodes );
1603  common->Printf( "%6d outside leaf nodes\n", outsideLeafNodes );
1604  common->Printf( "%6d inside leaf nodes\n", insideLeafNodes );
1605 
1606  //PruneTree( contents );
1607 
1608  return true;
1609 }
1610 
1611 /*
1612 ============
1613 idBrushBSP::SetPortalPlanes_r
1614 ============
1615 */
1617  int s;
1619 
1620  if ( !node ) {
1621  return;
1622  }
1623 
1624  for ( p = node->portals; p; p = p->next[s] ) {
1625  s = (p->nodes[1] == node);
1626  if ( p->planeNum == -1 ) {
1628  }
1629  }
1630  SetPortalPlanes_r( node->children[0], planeList );
1631  SetPortalPlanes_r( node->children[1], planeList );
1632 }
1633 
1634 /*
1635 ============
1636 idBrushBSP::SetPortalPlanes
1637 
1638  give all portals a plane number
1639 ============
1640 */
1643 }
1644 
1645 /*
1646 ============
1647 idBrushBSP::MergeLeafNodePortals
1648 ============
1649 */
1650 void idBrushBSP::MergeLeafNodePortals( idBrushBSPNode *node, int skipContents ) {
1651  int s1, s2;
1652  bool foundPortal;
1653  idBrushBSPPortal *p1, *p2, *nextp1, *nextp2;
1654  idWinding *newWinding, *reverse;
1655 
1656  // pass 1: merge all portals that seperate the same leaf nodes
1657  for ( p1 = node->GetPortals(); p1; p1 = nextp1 ) {
1658  s1 = (p1->GetNode(1) == node);
1659  nextp1 = p1->Next(s1);
1660 
1661  for ( p2 = nextp1; p2; p2 = nextp2 ) {
1662  s2 = (p2->GetNode(1) == node);
1663  nextp2 = p2->Next(s2);
1664 
1665  // if both portals seperate the same leaf nodes
1666  if ( p1->nodes[!s1] == p2->nodes[!s2] ) {
1667 
1668  // add the winding of p2 to the winding of p1
1669  p1->winding->AddToConvexHull( p2->winding, p1->plane.Normal() );
1670 
1671  // delete p2
1672  p2->RemoveFromNode( p2->nodes[0] );
1673  p2->RemoveFromNode( p2->nodes[1] );
1674  delete p2;
1675 
1676  numMergedPortals++;
1677 
1678  nextp1 = node->GetPortals();
1679  break;
1680  }
1681  }
1682  }
1683 
1684  // pass 2: merge all portals in the same plane if they all have the skip contents at the other side
1685  for ( p1 = node->GetPortals(); p1; p1 = nextp1 ) {
1686  s1 = (p1->GetNode(1) == node);
1687  nextp1 = p1->Next(s1);
1688 
1689  if ( !(p1->nodes[!s1]->contents & skipContents) ) {
1690  continue;
1691  }
1692 
1693  // test if all portals in this plane have the skip contents at the other side
1694  foundPortal = false;
1695  for ( p2 = node->GetPortals(); p2; p2 = nextp2 ) {
1696  s2 = (p2->GetNode(1) == node);
1697  nextp2 = p2->Next(s2);
1698 
1699  if ( p2 == p1 || (p2->planeNum & ~1) != (p1->planeNum & ~1) ) {
1700  continue;
1701  }
1702  foundPortal = true;
1703  if ( !(p2->nodes[!s2]->contents & skipContents) ) {
1704  break;
1705  }
1706  }
1707 
1708  // if all portals in this plane have the skip contents at the other side
1709  if ( !p2 && foundPortal ) {
1710  for ( p2 = node->GetPortals(); p2; p2 = nextp2 ) {
1711  s2 = (p2->GetNode(1) == node);
1712  nextp2 = p2->Next(s2);
1713 
1714  if ( p2 == p1 || (p2->planeNum & ~1) != (p1->planeNum & ~1) ) {
1715  continue;
1716  }
1717 
1718  // add the winding of p2 to the winding of p1
1719  p1->winding->AddToConvexHull( p2->winding, p1->plane.Normal() );
1720 
1721  // delete p2
1722  p2->RemoveFromNode( p2->nodes[0] );
1723  p2->RemoveFromNode( p2->nodes[1] );
1724  delete p2;
1725 
1726  numMergedPortals++;
1727  }
1728  nextp1 = node->GetPortals();
1729  }
1730  }
1731 
1732  // pass 3: try to merge portals in the same plane that have the skip contents at the other side
1733  for ( p1 = node->GetPortals(); p1; p1 = nextp1 ) {
1734  s1 = (p1->GetNode(1) == node);
1735  nextp1 = p1->Next(s1);
1736 
1737  if ( !(p1->nodes[!s1]->contents & skipContents) ) {
1738  continue;
1739  }
1740 
1741  for ( p2 = nextp1; p2; p2 = nextp2 ) {
1742  s2 = (p2->GetNode(1) == node);
1743  nextp2 = p2->Next(s2);
1744 
1745  if ( !(p2->nodes[!s2]->contents & skipContents) ) {
1746  continue;
1747  }
1748 
1749  if ( (p2->planeNum & ~1) != (p1->planeNum & ~1) ) {
1750  continue;
1751  }
1752 
1753  // try to merge the two portal windings
1754  if ( p2->planeNum == p1->planeNum ) {
1755  newWinding = p1->winding->TryMerge( *p2->winding, p1->plane.Normal() );
1756  }
1757  else {
1758  reverse = p2->winding->Reverse();
1759  newWinding = p1->winding->TryMerge( *reverse, p1->plane.Normal() );
1760  delete reverse;
1761  }
1762 
1763  // if successfully merged
1764  if ( newWinding ) {
1765 
1766  // replace the winding of the first portal
1767  delete p1->winding;
1768  p1->winding = newWinding;
1769 
1770  // delete p2
1771  p2->RemoveFromNode( p2->nodes[0] );
1772  p2->RemoveFromNode( p2->nodes[1] );
1773  delete p2;
1774 
1775  numMergedPortals++;
1776 
1777  nextp1 = node->GetPortals();
1778  break;
1779  }
1780  }
1781  }
1782 }
1783 
1784 /*
1785 ============
1786 idBrushBSP::MergePortals_r
1787 ============
1788 */
1789 void idBrushBSP::MergePortals_r( idBrushBSPNode *node, int skipContents ) {
1790 
1791  if ( !node ) {
1792  return;
1793  }
1794 
1795  if ( node->contents & skipContents ) {
1796  return;
1797  }
1798 
1799  if ( !node->children[0] && !node->children[1] ) {
1800  MergeLeafNodePortals( node, skipContents );
1801  return;
1802  }
1803 
1804  MergePortals_r( node->children[0], skipContents );
1805  MergePortals_r( node->children[1], skipContents );
1806 }
1807 
1808 /*
1809 ============
1810 idBrushBSP::MergePortals
1811 ============
1812 */
1813 void idBrushBSP::MergePortals( int skipContents ) {
1814  numMergedPortals = 0;
1815  common->Printf( "[Merge Portals]\n" );
1816  SetPortalPlanes();
1817  MergePortals_r( root, skipContents );
1818  common->Printf( "%6d portals merged\n", numMergedPortals );
1819 }
1820 
1821 /*
1822 ============
1823 idBrushBSP::PruneMergedTree_r
1824 ============
1825 */
1827  int i;
1828  idBrushBSPNode *leafNode;
1829 
1830  if ( !node ) {
1831  return;
1832  }
1833 
1834  PruneMergedTree_r( node->children[0] );
1835  PruneMergedTree_r( node->children[1] );
1836 
1837  for ( i = 0; i < 2; i++ ) {
1838  if ( node->children[i] ) {
1839  leafNode = node->children[i]->children[0];
1840  if ( leafNode && leafNode == node->children[i]->children[1] ) {
1841  if ( leafNode->parent == node->children[i] ) {
1842  leafNode->parent = node;
1843  }
1844  delete node->children[i];
1845  node->children[i] = leafNode;
1846  }
1847  }
1848  }
1849 }
1850 
1851 /*
1852 ============
1853 idBrushBSP::UpdateTreeAfterMerge_r
1854 ============
1855 */
1857 
1858  if ( !node ) {
1859  return;
1860  }
1861 
1862  if ( !node->children[0] && !node->children[1] ) {
1863  return;
1864  }
1865 
1866  if ( node->children[0] == oldNode ) {
1867  node->children[0] = newNode;
1868  }
1869  if ( node->children[1] == oldNode ) {
1870  node->children[1] = newNode;
1871  }
1872 
1873  switch( bounds.PlaneSide( node->plane, 2.0f ) ) {
1874  case PLANESIDE_FRONT:
1875  UpdateTreeAfterMerge_r( node->children[0], bounds, oldNode, newNode );
1876  break;
1877  case PLANESIDE_BACK:
1878  UpdateTreeAfterMerge_r( node->children[1], bounds, oldNode, newNode );
1879  break;
1880  default:
1881  UpdateTreeAfterMerge_r( node->children[0], bounds, oldNode, newNode );
1882  UpdateTreeAfterMerge_r( node->children[1], bounds, oldNode, newNode );
1883  break;
1884  }
1885 }
1886 
1887 /*
1888 ============
1889 idBrushBSP::TryMergeLeafNodes
1890 
1891  NOTE: multiple brances of the BSP tree might point to the same leaf node after merging
1892 ============
1893 */
1895  int i, j, k, s1, s2, s;
1896  idBrushBSPNode *nodes[2], *node1, *node2;
1897  idBrushBSPPortal *p1, *p2, *p, *nextp;
1898  idPlane plane;
1899  idWinding *w;
1900  idBounds bounds, b;
1901 
1902  nodes[0] = node1 = portal->nodes[side];
1903  nodes[1] = node2 = portal->nodes[!side];
1904 
1905  // check if the merged node would still be convex
1906  for ( i = 0; i < 2; i++ ) {
1907 
1908  j = !i;
1909 
1910  for ( p1 = nodes[i]->portals; p1; p1 = p1->next[s1] ) {
1911  s1 = (p1->nodes[1] == nodes[i]);
1912 
1913  if ( p1->nodes[!s1] == nodes[j] ) {
1914  continue;
1915  }
1916 
1917  if ( s1 ) {
1918  plane = -p1->plane;
1919  }
1920  else {
1921  plane = p1->plane;
1922  }
1923 
1924  // all the non seperating portals of the other node should be at the front or on the plane
1925  for ( p2 = nodes[j]->portals; p2; p2 = p2->next[s2] ) {
1926  s2 = (p2->nodes[1] == nodes[j]);
1927 
1928  if ( p2->nodes[!s2] == nodes[i] ) {
1929  continue;
1930  }
1931 
1932  w = p2->winding;
1933  for ( k = 0; k < w->GetNumPoints(); k++ ) {
1934  if ( plane.Distance( (*w)[k].ToVec3() ) < -0.1f ) {
1935  return false;
1936  }
1937  }
1938  }
1939  }
1940  }
1941 
1942  // remove all portals that seperate the two nodes
1943  for ( p = node1->portals; p; p = nextp ) {
1944  s = (p->nodes[1] == node1);
1945  nextp = p->next[s];
1946 
1947  if ( p->nodes[!s] == node2 ) {
1948  p->RemoveFromNode( p->nodes[0] );
1949  p->RemoveFromNode( p->nodes[1] );
1950  delete p;
1951  }
1952  }
1953 
1954  // move all portals of node2 to node1
1955  for ( p = node2->portals; p; p = node2->portals ) {
1956  s = (p->nodes[1] == node2);
1957 
1958  nodes[s] = node1;
1959  nodes[!s] = p->nodes[!s];
1960  p->RemoveFromNode( p->nodes[0] );
1961  p->RemoveFromNode( p->nodes[1] );
1962  p->AddToNodes( nodes[0], nodes[1] );
1963  }
1964 
1965  // get bounds for the new node
1966  bounds.Clear();
1967  for ( p = node1->portals; p; p = p->next[s] ) {
1968  s = (p->nodes[1] == node1);
1969  p->GetWinding()->GetBounds( b );
1970  bounds += b;
1971  }
1972 
1973  // replace every reference to node2 by a reference to node1
1974  UpdateTreeAfterMerge_r( root, bounds, node2, node1 );
1975 
1976  delete node2;
1977 
1978  return true;
1979 }
1980 
1981 /*
1982 ============
1983 idBrushBSP::MeltFloor_r
1984 
1985  flood through portals touching the bounds to find all vertices that might be inside the bounds
1986 ============
1987 */
1988 void idBrushBSP::MeltFlood_r( idBrushBSPNode *node, int skipContents, idBounds &bounds, idVectorSet<idVec3,3> &vertexList ) {
1989  int s1, i;
1990  idBrushBSPPortal *p1;
1991  idBounds b;
1992  const idWinding *w;
1993 
1994  node->SetFlag( NODE_VISITED );
1995 
1996  for ( p1 = node->GetPortals(); p1; p1 = p1->Next(s1) ) {
1997  s1 = (p1->GetNode(1) == node);
1998 
1999  if ( p1->GetNode( !s1 )->GetFlags() & NODE_VISITED ) {
2000  continue;
2001  }
2002 
2003  w = p1->GetWinding();
2004 
2005  for ( i = 0; i < w->GetNumPoints(); i++ ) {
2006  if ( bounds.ContainsPoint( (*w)[i].ToVec3() ) ) {
2007  vertexList.FindVector( (*w)[i].ToVec3(), VERTEX_MELT_EPSILON );
2008  }
2009  }
2010  }
2011 
2012  for ( p1 = node->GetPortals(); p1; p1 = p1->Next(s1) ) {
2013  s1 = (p1->GetNode(1) == node);
2014 
2015  if ( p1->GetNode( !s1 )->GetFlags() & NODE_VISITED ) {
2016  continue;
2017  }
2018 
2019  if ( p1->GetNode( !s1 )->GetContents() & skipContents ) {
2020  continue;
2021  }
2022 
2023  w = p1->GetWinding();
2024  w->GetBounds( b );
2025 
2026  if ( !bounds.IntersectsBounds( b ) ) {
2027  continue;
2028  }
2029 
2030  MeltFlood_r( p1->GetNode( !s1 ), skipContents, bounds, vertexList );
2031  }
2032 }
2033 
2034 /*
2035 ============
2036 idBrushBSP::MeltLeafNodePortals
2037 ============
2038 */
2039 void idBrushBSP::MeltLeafNodePortals( idBrushBSPNode *node, int skipContents, idVectorSet<idVec3,3> &vertexList ) {
2040  int s1, i;
2041  idBrushBSPPortal *p1;
2042  idBounds bounds;
2043 
2044  if ( node->GetFlags() & NODE_DONE ) {
2045  return;
2046  }
2047 
2048  node->SetFlag( NODE_DONE );
2049 
2050  // melt things together
2051  for ( p1 = node->GetPortals(); p1; p1 = p1->Next(s1) ) {
2052  s1 = (p1->GetNode(1) == node);
2053 
2054  if ( p1->GetNode( !s1 )->GetFlags() & NODE_DONE ) {
2055  continue;
2056  }
2057 
2058  p1->winding->GetBounds( bounds );
2060  vertexList.Init( bounds[0], bounds[1], VERTEX_MELT_HASH_SIZE, 128 );
2061 
2062  // get all vertices to be considered
2063  MeltFlood_r( node, skipContents, bounds, vertexList );
2064  node->RemoveFlagFlood( NODE_VISITED );
2065 
2066  for ( i = 0; i < vertexList.Num(); i++ ) {
2067  if ( p1->winding->InsertPointIfOnEdge( vertexList[i], p1->plane, 0.1f ) ) {
2069  }
2070  }
2071  }
2073 }
2074 
2075 /*
2076 ============
2077 idBrushBSP::MeltPortals_r
2078 ============
2079 */
2080 void idBrushBSP::MeltPortals_r( idBrushBSPNode *node, int skipContents, idVectorSet<idVec3,3> &vertexList ) {
2081  if ( !node ) {
2082  return;
2083  }
2084 
2085  if ( node->contents & skipContents ) {
2086  return;
2087  }
2088 
2089  if ( !node->children[0] && !node->children[1] ) {
2090  MeltLeafNodePortals( node, skipContents, vertexList );
2091  return;
2092  }
2093 
2094  MeltPortals_r( node->children[0], skipContents, vertexList );
2095  MeltPortals_r( node->children[1], skipContents, vertexList );
2096 }
2097 
2098 /*
2099 ============
2100 idBrushBSP::RemoveLeafNodeColinearPoints
2101 ============
2102 */
2104  int s1;
2105  idBrushBSPPortal *p1;
2106 
2107  // remove colinear points
2108  for ( p1 = node->GetPortals(); p1; p1 = p1->Next(s1) ) {
2109  s1 = (p1->GetNode(1) == node);
2110  p1->winding->RemoveColinearPoints( p1->plane.Normal(), 0.1f );
2111  }
2112 }
2113 
2114 /*
2115 ============
2116 idBrushBSP::RemoveColinearPoints_r
2117 ============
2118 */
2119 void idBrushBSP::RemoveColinearPoints_r( idBrushBSPNode *node, int skipContents ) {
2120  if ( !node ) {
2121  return;
2122  }
2123 
2124  if ( node->contents & skipContents ) {
2125  return;
2126  }
2127 
2128  if ( !node->children[0] && !node->children[1] ) {
2130  return;
2131  }
2132 
2133  RemoveColinearPoints_r( node->children[0], skipContents );
2134  RemoveColinearPoints_r( node->children[1], skipContents );
2135 }
2136 
2137 /*
2138 ============
2139 idBrushBSP::MeltPortals
2140 ============
2141 */
2142 void idBrushBSP::MeltPortals( int skipContents ) {
2143  idVectorSet<idVec3,3> vertexList;
2144 
2145  numInsertedPoints = 0;
2146  common->Printf( "[Melt Portals]\n" );
2147  RemoveColinearPoints_r( root, skipContents );
2148  MeltPortals_r( root, skipContents, vertexList );
2150  common->Printf( "\r%6d points inserted\n", numInsertedPoints );
2151 }
bool(* BrushChopAllowed)(idBrush *b1, idBrush *b2)
Definition: BrushBSP.h:197
void GetBounds(idBounds &bounds) const
Definition: Winding.cpp:700
void Init(const type &mins, const type &maxs, const int boxHashSize, const int initialSize)
Definition: VectorSet.h:82
void MergePortals(int skipContents)
Definition: BrushBSP.cpp:1813
void Clear(void)
Definition: Brush.h:170
int GetFlags(void) const
Definition: Brush.h:72
void SavePlaneSide(void)
Definition: Brush.h:118
#define VERTEX_MELT_HASH_SIZE
Definition: BrushBSP.cpp:39
#define BRUSH_PLANESIDE_BOTH
Definition: Brush.h:43
idMapEntity * GetEntity(int i) const
Definition: MapFile.h:198
GLsizei const GLfloat * value
Definition: glext.h:3614
idStr & SetFileExtension(const char *extension)
Definition: Str.cpp:743
assert(prefInfo.fullscreenBtn)
const idVec3 & Normal(void) const
Definition: Plane.h:239
#define SIDE_CROSS
Definition: Plane.h:50
bool(* BrushMergeAllowed)(idBrush *b1, idBrush *b2)
Definition: BrushBSP.h:198
int GetContents(void) const
Definition: BrushBSP.h:106
idVec3 leakOrigin
Definition: BrushBSP.h:193
void MeltPortals(int skipContents)
Definition: BrushBSP.cpp:2142
void AddToConvexHull(const idWinding *winding, const idVec3 &normal, const float epsilon=ON_EPSILON)
Definition: Winding.cpp:789
bool RemoveOutside(const idMapFile *mapFile, int contents, const idStrList &classNames)
Definition: BrushBSP.cpp:1591
#define SIDE_BACK
Definition: Plane.h:48
float Distance(const idVec3 &v) const
Definition: Plane.h:324
void FloodThroughPortals_r(idBrushBSPNode *node, int contents, int depth)
Definition: BrushBSP.cpp:1417
void CreatePlaneList(idPlaneSet &planeList) const
Definition: Brush.cpp:1466
int numMergedPortals
Definition: BrushBSP.h:191
int GetSavedPlaneSide(void) const
Definition: Brush.h:119
const idWinding * GetWinding(void) const
Definition: Brush.h:78
idWinding * TryMerge(const idWinding &w, const idVec3 &normal, int keep=false) const
Definition: Winding.cpp:998
int FindSplitter(idBrushBSPNode *node, const idPlaneSet &planeList, bool *testedPlanes, struct splitterStats_s &bestStats)
Definition: BrushBSP.cpp:677
void MergePortals_r(idBrushBSPNode *node, int skipContents)
Definition: BrushBSP.cpp:1789
GLenum GLsizei n
Definition: glext.h:3705
idBrushList brushList
Definition: BrushBSP.h:131
const idPlane & GetPlane(void) const
Definition: BrushBSP.h:64
idFileSystem * fileSystem
Definition: FileSystem.cpp:500
idWinding * winding
Definition: BrushBSP.h:76
#define MAX_WORLD_COORD
Definition: Lib.h:98
#define BRUSH_PLANESIDE_BACK
Definition: Brush.h:42
void MakeTreePortals_r(idBrushBSPNode *node)
Definition: BrushBSP.cpp:1255
void SetSplitterUsed(idBrushBSPNode *node, int planeNum)
Definition: BrushBSP.cpp:760
int GetFlags(void) const
Definition: Brush.h:106
void Split(const idPlane &plane, int planeNum, idBrushList &frontList, idBrushList &backList, bool useBrushSavedPlaneSide=false)
Definition: Brush.cpp:1225
Definition: Vector.h:316
int BrushSplitterStats(const idBrush *brush, int planeNum, const idPlaneSet &planeList, bool *testedPlanes, struct splitterStats_s &stats)
Definition: BrushBSP.cpp:589
int NumSides(void) const
Definition: Brush.h:167
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glext.h:2878
#define VERTEX_MELT_EPSILON
Definition: BrushBSP.cpp:38
int PlaneSide(const idPlane &plane, float epsilon=ON_EPSILON) const
Definition: BrushBSP.cpp:399
#define BSP_GRID_SIZE
Definition: BrushBSP.cpp:36
void Chop(bool(*ChopAllowed)(idBrush *b1, idBrush *b2))
Definition: Brush.cpp:1268
bool TryMergeLeafNodes(idBrushBSPPortal *portal, int side)
Definition: BrushBSP.cpp:1894
idBrushBSPPortal * next[2]
Definition: BrushBSP.h:78
void ReverseSelf(void)
Definition: Winding.cpp:495
void Clear(void)
Definition: Bounds.h:201
void SetFlag(int flag)
Definition: Brush.h:107
idBrushSide * GetSide(int i) const
Definition: Brush.h:116
idWinding * Reverse(void) const
Definition: Winding.cpp:478
idBrushBSP(void)
Definition: BrushBSP.cpp:501
GLdouble s
Definition: glext.h:2935
void SetNormal(const idVec3 &normal)
Definition: Plane.h:233
idWinding * Clip(const idPlane &plane, const float epsilon=ON_EPSILON, const bool keepOn=false)
Definition: Winding.cpp:234
void WriteBrushMap(const idStr &fileName, const idStr &ext, int contents)
Definition: BrushBSP.cpp:1014
void SplitNodePortals(idBrushBSPNode *node)
Definition: BrushBSP.cpp:1162
void Free(void)
Definition: Brush.cpp:1209
void SetPortalPlanes(void)
Definition: BrushBSP.cpp:1641
idPlaneSet portalPlanes
Definition: BrushBSP.h:182
int i
Definition: process.py:33
int GetFlags(void) const
Definition: BrushBSP.h:111
void SetPlaneSide(int s)
Definition: Brush.h:117
GLuint GLuint num
Definition: glext.h:5390
friend class idBrushBSPPortal
Definition: BrushBSP.h:96
void RemoveFlagRecurse(int flag)
Definition: BrushBSP.cpp:459
bool InsertPointIfOnEdge(const idVec3 &point, const idPlane &plane, const float epsilon=ON_EPSILON)
Definition: Winding.cpp:1145
int Icmp(const char *text) const
Definition: Str.h:667
int FindPlane(const idPlane &plane, const float normalEps, const float distEps)
Definition: PlaneSet.h:51
idBrushBSPNode * nodes[2]
Definition: BrushBSP.h:77
int Type(void) const
Definition: Plane.cpp:39
#define MIN_WORLD_COORD
Definition: Lib.h:99
list l
Definition: prepare.py:17
idDict epairs
Definition: MapFile.h:166
idBrushBSPNode * root
Definition: BrushBSP.h:179
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
Definition: Winding.cpp:1292
idBrushBSPPortal * portals
Definition: BrushBSP.h:134
void MergeLeafNodePortals(idBrushBSPNode *node, int skipContents)
Definition: BrushBSP.cpp:1650
Definition: File.h:50
#define PORTAL_PLANE_DIST_EPSILON
Definition: BrushBSP.cpp:42
int solidLeafNodes
Definition: BrushBSP.h:188
#define PLANESIDE_FRONT
Definition: Plane.h:53
bool AddPoint(const idVec3 &v)
Definition: Bounds.h:226
idBrush * volume
Definition: BrushBSP.h:129
int outsideLeafNodes
Definition: BrushBSP.h:189
bool FloodFromEntities(const idMapFile *mapFile, int contents, const idStrList &classNames)
Definition: BrushBSP.cpp:1499
int numPortals
Definition: BrushBSP.h:187
idBrush * Head(void) const
Definition: Brush.h:168
GLuint GLuint GLsizei count
Definition: glext.h:2845
#define BRUSH_PLANESIDE_FACING
Definition: Brush.h:44
int numPrunedSplits
Definition: BrushBSP.h:186
int GetNumPoints(void) const
Definition: Winding.h:238
const char * GetString(const char *key, const char *defaultString="") const
Definition: Dict.h:240
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3454
void SetDist(const float dist)
Definition: Plane.h:275
idBrushBSPNode * GetNode(int side) const
Definition: BrushBSP.h:71
int GetNumEntities(void) const
Definition: MapFile.h:196
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
bool TestLeafNode(void)
Definition: BrushBSP.cpp:292
bool IsValidSplitter(const idBrushSide *side)
Definition: BrushBSP.cpp:572
void RemoveColinearPoints_r(idBrushBSPNode *node, int skipContents)
Definition: BrushBSP.cpp:2119
idCommon * common
Definition: Common.cpp:206
#define SFL_USED_SPLITTER
Definition: Brush.h:60
#define PLANESIDE_BACK
Definition: Plane.h:54
int numSplits
Definition: BrushBSP.h:184
void Portalize(void)
Definition: BrushBSP.cpp:1346
#define NULL
Definition: Lib.h:88
void MeltFlood_r(idBrushBSPNode *node, int skipContents, idBounds &bounds, idVectorSet< idVec3, 3 > &vertexList)
Definition: BrushBSP.cpp:1988
const idBounds & GetBounds(void) const
Definition: Brush.h:113
int FindVector(const type &v, const float epsilon)
Definition: VectorSet.h:115
int insideLeafNodes
Definition: BrushBSP.h:190
idVec3 GetVector(const char *key, const char *defaultString=NULL) const
Definition: Dict.h:260
~idBrushBSPPortal(void)
Definition: BrushBSP.cpp:72
#define NODE_DONE
Definition: BrushBSP.h:91
virtual idFile * OpenFileWrite(const char *relativePath, const char *basePath="fs_savepath")=0
Definition: Plane.h:71
idBrushBSPNode(void)
Definition: BrushBSP.cpp:216
#define BASE_WINDING_EPSILON
Definition: BrushBSP.cpp:1083
void UpdateTreeAfterMerge_r(idBrushBSPNode *node, const idBounds &bounds, idBrushBSPNode *oldNode, idBrushBSPNode *newNode)
Definition: BrushBSP.cpp:1856
void SetFlag(int flag)
Definition: Brush.h:73
virtual void Printf(const char *fmt,...) id_attribute((format(printf
void RemoveOutside_r(idBrushBSPNode *node, int contents)
Definition: BrushBSP.cpp:1560
int GetContents(void) const
Definition: Brush.h:112
idBounds Expand(const float d) const
Definition: Bounds.h:317
void SetPortalPlanes_r(idBrushBSPNode *node, idPlaneSet &planeList)
Definition: BrushBSP.cpp:1616
~idBrushBSPNode(void)
Definition: BrushBSP.cpp:232
int Side(const idVec3 &v, const float epsilon=0.0f) const
Definition: Plane.h:328
#define BFL_NO_VALID_SPLITTERS
Definition: Brush.h:96
GLubyte GLubyte b
Definition: glext.h:4662
void RemoveFlagFlood(int flag)
Definition: BrushBSP.cpp:437
bool IsTiny(void) const
Definition: Winding.cpp:1202
idBrush * Next(void) const
Definition: Brush.h:133
void LeakFile(const idStr &fileName)
Definition: BrushBSP.cpp:1363
int brushMapContents
Definition: BrushBSP.h:194
int numGridCellSplits
Definition: BrushBSP.h:185
idBrushBSPNode * children[2]
Definition: BrushBSP.h:133
int Split(const idPlane &plane, const float epsilon, idWinding **front, idWinding **back) const
Definition: Winding.cpp:92
int Append(const type &obj)
Definition: List.h:646
#define SIDE_ON
Definition: Plane.h:49
void MakeNodePortal(idBrushBSPNode *node)
Definition: BrushBSP.cpp:1116
void Flip(void)
Definition: BrushBSP.cpp:149
#define NODE_VISITED
Definition: BrushBSP.h:90
void RemoveLeafNodeColinearPoints(idBrushBSPNode *node)
Definition: BrushBSP.cpp:2103
idBrushMap * brushMap
Definition: BrushBSP.h:195
bool FloodFromOrigin(const idVec3 &origin, int contents)
Definition: BrushBSP.cpp:1458
tuple f
Definition: idal.py:89
void BuildGrid_r(idList< idBrushBSPNode * > &gridCells, idBrushBSPNode *node)
Definition: BrushBSP.cpp:900
#define ON_EPSILON
Definition: Plane.h:44
int numInsertedPoints
Definition: BrushBSP.h:192
idBrushBSPNode * outside
Definition: BrushBSP.h:180
struct splitterStats_s splitterStats_t
int Num(void) const
Definition: List.h:265
bool IntersectsBounds(const idBounds &a) const
Definition: Bounds.h:361
const GLcharARB * name
Definition: glext.h:3629
idWinding * BaseWindingForNode(idBrushBSPNode *node)
Definition: BrushBSP.cpp:1085
idVec3 GetCenter(void) const
Definition: Winding.cpp:639
idBrushBSPNode * parent
Definition: BrushBSP.h:132
#define PORTAL_PLANE_NORMAL_EPSILON
Definition: BrushBSP.cpp:41
Definition: Str.h:116
idBrushBSPPortal * GetPortals(void) const
Definition: BrushBSP.h:108
idBounds GetPortalBounds(void)
Definition: BrushBSP.cpp:271
const idPlane & GetPlane(void) const
Definition: Brush.h:75
#define SPLIT_WINDING_EPSILON
Definition: BrushBSP.cpp:1160
#define SFL_SPLIT
Definition: Brush.h:58
idBrushBSPNode * ProcessGridCell(idBrushBSPNode *node, int skipContents)
Definition: BrushBSP.cpp:858
void SetFlag(int flag)
Definition: BrushBSP.h:112
int GetPlaneNum(void)
Definition: Brush.h:77
#define PLANETYPE_TRUEAXIAL
Definition: Plane.h:65
const char * c_str(void) const
Definition: Str.h:487
idPlane plane
Definition: BrushBSP.h:128
idWinding * GetWinding(void) const
Definition: BrushBSP.h:63
void Build(idBrushList brushList, int skipContents, bool(*ChopAllowed)(idBrush *b1, idBrush *b2), bool(*MergeAllowed)(idBrush *b1, idBrush *b2))
Definition: BrushBSP.cpp:964
void SetFlagOnFacingBrushSides(const idPlane &plane, int flag)
Definition: Brush.cpp:1437
unsigned char bool
Definition: setup.h:74
idBrushBSPPortal * Next(int side) const
Definition: BrushBSP.h:70
void DisplayRealTimeString(char *string,...)
Definition: Brush.cpp:47
void RemoveFlagRecurseFlood(int flag)
Definition: BrushBSP.cpp:474
#define PLANESIDE_CROSS
Definition: Plane.h:56
GLint j
Definition: qgl.h:264
idBounds & ExpandSelf(const float d)
Definition: Bounds.h:322
void SetContentsFromBrushes(void)
Definition: BrushBSP.cpp:257
idPlane plane
Definition: BrushBSP.h:74
int Split(const idPlane &splitPlane, idBrushBSPPortal **front, idBrushBSPPortal **back)
Definition: BrushBSP.cpp:173
idBrushBSPPortal(void)
Definition: BrushBSP.cpp:58
if(!ValidDisplayID(prefInfo.prefDisplayID)) prefInfo.prefDisplayID
void RemoveMultipleLeafNodeReferences_r(idBrushBSPNode *node)
Definition: BrushBSP.cpp:528
bool FromBounds(const idBounds &bounds)
Definition: Brush.cpp:383
int GetNumSides(void) const
Definition: Brush.h:115
void MeltPortals_r(idBrushBSPNode *node, int skipContents, idVectorSet< idVec3, 3 > &vertexList)
Definition: BrushBSP.cpp:2080
virtual void CloseFile(idFile *f)=0
idBrushBSPNode * BuildBrushBSP_r(idBrushBSPNode *node, const idPlaneSet &planeList, bool *testedPlanes, int skipContents)
Definition: BrushBSP.cpp:789
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
Definition: Bounds.cpp:108
#define SPLITTER_EPSILON
Definition: BrushBSP.cpp:37
bool MergeAllowed(idBrush *b1, idBrush *b2)
Definition: AASBuild.cpp:597
void RemoveFromNode(idBrushBSPNode *l)
Definition: BrushBSP.cpp:104
virtual void Error(const char *fmt,...) id_attribute((format(printf
GLfloat GLfloat p
Definition: glext.h:4674
Definition: List.h:84
#define SIDE_FRONT
Definition: Plane.h:47
void WriteBrush(const idBrush *brush)
Definition: Brush.cpp:1548
idBounds GetBounds(void) const
Definition: Brush.cpp:1039
void MakeOutsidePortals(void)
Definition: BrushBSP.cpp:1291
bool ContainsPoint(const idVec3 &p) const
Definition: Bounds.h:353
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
Definition: Brush.h:98
idBounds treeBounds
Definition: BrushBSP.h:181
void AddToNodes(idBrushBSPNode *front, idBrushBSPNode *back)
Definition: BrushBSP.cpp:83
void PruneTree(int contents)
Definition: BrushBSP.cpp:1071
void RemoveFlag(int flag)
Definition: BrushBSP.h:113
virtual int Printf(const char *fmt,...) id_attribute((format(printf
Definition: File.cpp:260
float Dist(void) const
Definition: Plane.h:271
void RemoveColinearPoints(const idVec3 &normal, const float epsilon=ON_EPSILON)
Definition: Winding.cpp:753
#define BRUSH_PLANESIDE_FRONT
Definition: Brush.h:41
~idBrushBSP(void)
Definition: BrushBSP.cpp:513
void Free_r(idBrushBSPNode *node)
Definition: BrushBSP.cpp:556
void MeltLeafNodePortals(idBrushBSPNode *node, int skipContents, idVectorSet< idVec3, 3 > &vertexList)
Definition: BrushBSP.cpp:2039
int Num(void) const
Definition: Brush.h:166
bool Split(const idPlane &splitPlane, int splitPlaneNum)
Definition: BrushBSP.cpp:330
int numGridCells
Definition: BrushBSP.h:183
GLdouble GLdouble t
Definition: glext.h:2943
void PruneTree_r(idBrushBSPNode *node, int contents)
Definition: BrushBSP.cpp:1024
int Split(const idPlane &plane, int planeNum, idBrush **front, idBrush **back) const
Definition: Brush.cpp:618
void PruneMergedTree_r(idBrushBSPNode *node)
Definition: BrushBSP.cpp:1826