doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Brush.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 
34 #define BRUSH_EPSILON 0.1f
35 #define BRUSH_PLANE_NORMAL_EPSILON 0.00001f
36 #define BRUSH_PLANE_DIST_EPSILON 0.01f
37 
38 #define OUTPUT_UPDATE_TIME 500 // update every 500 msec
39 
40 //#define OUTPUT_CHOP_STATS
41 
42 /*
43 ============
44 DisplayRealTimeString
45 ============
46 */
47 void DisplayRealTimeString( char *string, ... ) {
48  va_list argPtr;
49  char buf[MAX_STRING_CHARS];
50  static int lastUpdateTime;
51  int time;
52 
53  time = Sys_Milliseconds();
54  if ( time > lastUpdateTime + OUTPUT_UPDATE_TIME ) {
55  va_start( argPtr, string );
56  vsprintf( buf, string, argPtr );
57  va_end( argPtr );
58  common->Printf( buf );
59  lastUpdateTime = time;
60  }
61 }
62 
63 
64 //===============================================================
65 //
66 // idBrushSide
67 //
68 //===============================================================
69 
70 /*
71 ============
72 idBrushSide::idBrushSide
73 ============
74 */
76  flags = 0;
77  planeNum = -1;
78  winding = NULL;
79 }
80 
81 /*
82 ============
83 idBrushSide::idBrushSide
84 ============
85 */
86 idBrushSide::idBrushSide( const idPlane &plane, int planeNum ) {
87  this->flags = 0;
88  this->plane = plane;
89  this->planeNum = planeNum;
90  this->winding = NULL;
91 }
92 
93 /*
94 ============
95 idBrushSide::~idBrushSide
96 ============
97 */
99  if ( winding ) {
100  delete winding;
101  }
102 }
103 
104 /*
105 ============
106 idBrushSide::Copy
107 ============
108 */
110  idBrushSide *side;
111 
112  side = new idBrushSide( plane, planeNum );
113  side->flags = flags;
114  if ( winding ) {
115  side->winding = winding->Copy();
116  }
117  else {
118  side->winding = NULL;
119  }
120  return side;
121 }
122 
123 /*
124 ============
125 idBrushSide::Split
126 ============
127 */
128 int idBrushSide::Split( const idPlane &splitPlane, idBrushSide **front, idBrushSide **back ) const {
129  idWinding *frontWinding, *backWinding;
130 
131  assert( winding );
132 
133  *front = *back = NULL;
134 
135  winding->Split( splitPlane, 0.0f, &frontWinding, &backWinding );
136 
137  if ( frontWinding ) {
138  (*front) = new idBrushSide( plane, planeNum );
139  (*front)->winding = frontWinding;
140  (*front)->flags = flags;
141  }
142 
143  if ( backWinding ) {
144  (*back) = new idBrushSide( plane, planeNum );
145  (*back)->winding = backWinding;
146  (*back)->flags = flags;
147  }
148 
149  if ( frontWinding && backWinding ) {
150  return PLANESIDE_CROSS;
151  }
152  else if ( frontWinding ) {
153  return PLANESIDE_FRONT;
154  }
155  else {
156  return PLANESIDE_BACK;
157  }
158 }
159 
160 
161 //===============================================================
162 //
163 // idBrushSide
164 //
165 //===============================================================
166 
167 /*
168 ============
169 idBrush::idBrush
170 ============
171 */
173  contents = flags = 0;
174  bounds.Clear();
175  sides.Clear();
176  windingsValid = false;
177 }
178 
179 
180 /*
181 ============
182 idBrush::~idBrush
183 ============
184 */
186  for ( int i = 0; i < sides.Num(); i++ ) {
187  delete sides[i];
188  }
189 }
190 
191 /*
192 ============
193 idBrush::RemoveSidesWithoutWinding
194 ============
195 */
197  int i;
198 
199  for ( i = 0; i < sides.Num(); i++ ) {
200 
201  if ( sides[i]->winding ) {
202  continue;
203  }
204 
205  sides.RemoveIndex( i );
206  i--;
207  }
208 
209  return ( sides.Num() >= 4 );
210 }
211 
212 /*
213 ============
214 idBrush::CreateWindings
215 ============
216 */
218  int i, j;
219  idBrushSide *side;
220 
221  bounds.Clear();
222  for ( i = 0; i < sides.Num(); i++ ) {
223  side = sides[i];
224 
225  if ( side->winding ) {
226  delete side->winding;
227  }
228 
229  side->winding = new idWinding( side->plane.Normal(), side->plane.Dist() );
230 
231  for ( j = 0; j < sides.Num() && side->winding; j++ ) {
232  if ( i == j ) {
233  continue;
234  }
235  // keep the winding if on the clip plane
236  side->winding = side->winding->Clip( -sides[j]->plane, BRUSH_EPSILON, true );
237  }
238 
239  if ( side->winding ) {
240  for ( j = 0; j < side->winding->GetNumPoints(); j++ ) {
241  bounds.AddPoint( (*side->winding)[j].ToVec3() );
242  }
243  }
244  }
245 
246  if ( bounds[0][0] > bounds[1][0] ) {
247  return false;
248  }
249  for ( i = 0; i < 3; i++ ) {
250  if ( bounds[0][i] < MIN_WORLD_COORD || bounds[1][i] > MAX_WORLD_COORD ) {
251  return false;
252  }
253  }
254 
255  windingsValid = true;
256 
257  return true;
258 }
259 
260 /*
261 ============
262 idBrush::BoundBrush
263 ============
264 */
265 void idBrush::BoundBrush( const idBrush *original ) {
266  int i, j;
267  idBrushSide *side;
268  idWinding *w;
269 
271 
272  bounds.Clear();
273  for ( i = 0; i < sides.Num(); i++ ) {
274  side = sides[i];
275 
276  w = side->winding;
277 
278  if ( !w ) {
279  continue;
280  }
281 
282  for ( j = 0; j < w->GetNumPoints(); j++ ) {
283  bounds.AddPoint( (*w)[j].ToVec3() );
284  }
285  }
286 
287  if ( bounds[0][0] > bounds[1][0] ) {
288  if ( original ) {
289  idBrushMap *bm = new idBrushMap( "error_brush", "_original" );
290  bm->WriteBrush( original );
291  delete bm;
292  }
293  common->Error( "idBrush::BoundBrush: brush %d on entity %d without windings", primitiveNum, entityNum );
294  }
295 
296  for ( i = 0; i < 3; i++ ) {
297  if ( bounds[0][i] < MIN_WORLD_COORD || bounds[1][i] > MAX_WORLD_COORD ) {
298  if ( original ) {
299  idBrushMap *bm = new idBrushMap( "error_brush", "_original" );
300  bm->WriteBrush( original );
301  delete bm;
302  }
303  common->Error( "idBrush::BoundBrush: brush %d on entity %d is unbounded", primitiveNum, entityNum );
304  }
305  }
306 }
307 
308 /*
309 ============
310 idBrush::FromSides
311 ============
312 */
314  int i;
315 
316  for ( i = 0; i < sideList.Num(); i++ ) {
317  sides.Append( sideList[i] );
318  }
319 
320  sideList.Clear();
321 
322  return CreateWindings();
323 }
324 
325 /*
326 ============
327 idBrush::FromWinding
328 ============
329 */
330 bool idBrush::FromWinding( const idWinding &w, const idPlane &windingPlane ) {
331  int i, j, bestAxis;
332  idPlane plane;
333  idVec3 normal, axialNormal;
334 
335  sides.Append( new idBrushSide( windingPlane, -1 ) );
336  sides.Append( new idBrushSide( -windingPlane, -1 ) );
337 
338  bestAxis = 0;
339  for ( i = 1; i < 3; i++ ) {
340  if ( idMath::Fabs( windingPlane.Normal()[i] ) > idMath::Fabs( windingPlane.Normal()[bestAxis] ) ) {
341  bestAxis = i;
342  }
343  }
344  axialNormal = vec3_origin;
345  if ( windingPlane.Normal()[bestAxis] > 0.0f ) {
346  axialNormal[bestAxis] = 1.0f;
347  }
348  else {
349  axialNormal[bestAxis] = -1.0f;
350  }
351 
352  for ( i = 0; i < w.GetNumPoints(); i++ ) {
353  j = (i+1) % w.GetNumPoints();
354  normal = ( w[j].ToVec3() - w[i].ToVec3() ).Cross( axialNormal );
355  if ( normal.Normalize() < 0.5f ) {
356  continue;
357  }
358  plane.SetNormal( normal );
359  plane.FitThroughPoint( w[j].ToVec3() );
360  sides.Append( new idBrushSide( plane, -1 ) );
361  }
362 
363  if ( sides.Num() < 4 ) {
364  for ( i = 0; i < sides.Num(); i++ ) {
365  delete sides[i];
366  }
367  sides.Clear();
368  return false;
369  }
370 
371  sides[0]->winding = w.Copy();
372  windingsValid = true;
373  BoundBrush();
374 
375  return true;
376 }
377 
378 /*
379 ============
380 idBrush::FromBounds
381 ============
382 */
383 bool idBrush::FromBounds( const idBounds &bounds ) {
384  int axis, dir;
385  idVec3 normal;
386  idPlane plane;
387 
388  for ( axis = 0; axis < 3; axis++ ) {
389  for ( dir = -1; dir <= 1; dir += 2 ) {
390  normal = vec3_origin;
391  normal[axis] = dir;
392  plane.SetNormal( normal );
393  plane.SetDist( dir * bounds[(dir == 1)][axis] );
394  sides.Append( new idBrushSide( plane, -1 ) );
395  }
396  }
397 
398  return CreateWindings();
399 }
400 
401 /*
402 ============
403 idBrush::Transform
404 ============
405 */
406 void idBrush::Transform( const idVec3 &origin, const idMat3 &axis ) {
407  int i;
408  bool transformed = false;
409 
410  if ( axis.IsRotated() ) {
411  for ( i = 0; i < sides.Num(); i++ ) {
412  sides[i]->plane.RotateSelf( vec3_origin, axis );
413  }
414  transformed = true;
415  }
416  if ( origin != vec3_origin ) {
417  for ( i = 0; i < sides.Num(); i++ ) {
418  sides[i]->plane.TranslateSelf( origin );
419  }
420  transformed = true;
421  }
422  if ( transformed ) {
423  CreateWindings();
424  }
425 }
426 
427 /*
428 ============
429 idBrush::GetVolume
430 ============
431 */
432 float idBrush::GetVolume( void ) const {
433  int i;
434  idWinding *w;
435  idVec3 corner;
436  float d, area, volume;
437 
438  // grab the first valid point as a corner
439  w = NULL;
440  for ( i = 0; i < sides.Num(); i++ ) {
441  w = sides[i]->winding;
442  if ( w ) {
443  break;
444  }
445  }
446  if ( !w ) {
447  return 0.0f;
448  }
449  corner = (*w)[0].ToVec3();
450 
451  // create tetrahedrons to all other sides
452  volume = 0.0f;
453  for ( ; i < sides.Num(); i++) {
454  w = sides[i]->winding;
455  if ( !w ) {
456  continue;
457  }
458  d = -( corner * sides[i]->plane.Normal() - sides[i]->plane.Dist() );
459  area = w->GetArea();
460  volume += d * area;
461  }
462 
463  return ( volume * ( 1.0f / 3.0f ) );
464 }
465 
466 /*
467 ============
468 idBrush::Subtract
469 ============
470 */
471 bool idBrush::Subtract( const idBrush *b, idBrushList &list ) const {
472  int i;
473  idBrush *front, *back;
474  const idBrush *in;
475 
476  list.Clear();
477  in = this;
478  for ( i = 0; i < b->sides.Num() && in; i++ ) {
479 
480  in->Split( b->sides[i]->plane, b->sides[i]->planeNum, &front, &back );
481 
482  if ( in != this ) {
483  delete in;
484  }
485  if ( front ) {
486  list.AddToTail( front );
487  }
488  in = back;
489  }
490  // if didn't really intersect
491  if ( !in ) {
492  list.Free();
493  return false;
494  }
495 
496  delete in;
497  return true;
498 }
499 
500 /*
501 ============
502 idBrush::TryMerge
503 ============
504 */
505 bool idBrush::TryMerge( const idBrush *brush, const idPlaneSet &planeList ) {
506  int i, j, k, l, m, seperatingPlane;
507  const idBrush *brushes[2];
508  const idWinding *w;
509  const idPlane *plane;
510 
511  // brush bounds should overlap
512  for ( i = 0; i < 3; i++ ) {
513  if ( bounds[0][i] > brush->bounds[1][i] + 0.1f ) {
514  return false;
515  }
516  if ( bounds[1][i] < brush->bounds[0][i] - 0.1f ) {
517  return false;
518  }
519  }
520 
521  // the brushes should share an opposite plane
522  seperatingPlane = -1;
523  for ( i = 0; i < GetNumSides(); i++ ) {
524  for ( j = 0; j < brush->GetNumSides(); j++ ) {
525  if ( GetSide(i)->GetPlaneNum() == (brush->GetSide(j)->GetPlaneNum() ^ 1) ) {
526  // may only have one seperating plane
527  if ( seperatingPlane != -1 ) {
528  return false;
529  }
530  seperatingPlane = GetSide(i)->GetPlaneNum();
531  break;
532  }
533  }
534  }
535  if ( seperatingPlane == -1 ) {
536  return false;
537  }
538 
539  brushes[0] = this;
540  brushes[1] = brush;
541 
542  for ( i = 0; i < 2; i++ ) {
543 
544  j = !i;
545 
546  for ( k = 0; k < brushes[i]->GetNumSides(); k++ ) {
547 
548  // if the brush side plane is the seprating plane
549  if ( !( ( brushes[i]->GetSide(k)->GetPlaneNum() ^ seperatingPlane ) >> 1 ) ) {
550  continue;
551  }
552 
553  plane = &brushes[i]->GetSide(k)->GetPlane();
554 
555  // all the non seperating brush sides of the other brush should be at the back or on the plane
556  for ( l = 0; l < brushes[j]->GetNumSides(); l++ ) {
557 
558  w = brushes[j]->GetSide(l)->GetWinding();
559  if ( !w ) {
560  continue;
561  }
562 
563  if ( !( ( brushes[j]->GetSide(l)->GetPlaneNum() ^ seperatingPlane ) >> 1 ) ) {
564  continue;
565  }
566 
567  for ( m = 0; m < w->GetNumPoints(); m++ ) {
568  if ( plane->Distance( (*w)[m].ToVec3() ) > 0.1f ) {
569  return false;
570  }
571  }
572  }
573  }
574  }
575 
576  // add any sides from the other brush to this brush
577  for ( i = 0; i < brush->GetNumSides(); i++ ) {
578  for ( j = 0; j < GetNumSides(); j++ ) {
579  if ( !( ( brush->GetSide(i)->GetPlaneNum() ^ GetSide(j)->GetPlaneNum() ) >> 1 ) ) {
580  break;
581  }
582  }
583  if ( j < GetNumSides() ) {
584  sides[j]->flags &= brush->GetSide(i)->GetFlags();
585  continue;
586  }
587  sides.Append( brush->GetSide(i)->Copy() );
588  }
589 
590  // remove any side from this brush that is the opposite of a side of the other brush
591  for ( i = 0; i < GetNumSides(); i++ ) {
592  for ( j = 0; j < brush->GetNumSides(); j++ ) {
593  if ( GetSide(i)->GetPlaneNum() == ( brush->GetSide(j)->GetPlaneNum() ^ 1 ) ) {
594  break;
595  }
596  }
597  if ( j < brush->GetNumSides() ) {
598  delete sides[i];
599  sides.RemoveIndex(i);
600  i--;
601  continue;
602  }
603  }
604 
605  contents |= brush->contents;
606 
607  CreateWindings();
608  BoundBrush();
609 
610  return true;
611 }
612 
613 /*
614 ============
615 idBrush::Split
616 ============
617 */
618 int idBrush::Split( const idPlane &plane, int planeNum, idBrush **front, idBrush **back ) const {
619  int res, i, j;
620  idBrushSide *side, *frontSide, *backSide;
621  float dist, maxBack, maxFront, *maxBackWinding, *maxFrontWinding;
622  idWinding *w, *mid;
623 
625 
626  if ( front ) {
627  *front = NULL;
628  }
629  if ( back ) {
630  *back = NULL;
631  }
632 
633  res = bounds.PlaneSide( plane, -BRUSH_EPSILON );
634  if ( res == PLANESIDE_FRONT ) {
635  if ( front ) {
636  *front = Copy();
637  }
638  return res;
639  }
640  if ( res == PLANESIDE_BACK ) {
641  if ( back ) {
642  *back = Copy();
643  }
644  return res;
645  }
646 
647  maxBackWinding = (float *) _alloca16( sides.Num() * sizeof(float) );
648  maxFrontWinding = (float *) _alloca16( sides.Num() * sizeof(float) );
649 
650  maxFront = maxBack = 0.0f;
651  for ( i = 0; i < sides.Num(); i++ ) {
652  side = sides[i];
653 
654  w = side->winding;
655 
656  if ( !w ) {
657  continue;
658  }
659 
660  maxBackWinding[i] = 10.0f;
661  maxFrontWinding[i] = -10.0f;
662 
663  for ( j = 0; j < w->GetNumPoints(); j++ ) {
664 
665  dist = plane.Distance( (*w)[j].ToVec3() );
666  if ( dist > maxFrontWinding[i] ) {
667  maxFrontWinding[i] = dist;
668  }
669  if ( dist < maxBackWinding[i] ) {
670  maxBackWinding[i] = dist;
671  }
672  }
673 
674  if ( maxFrontWinding[i] > maxFront ) {
675  maxFront = maxFrontWinding[i];
676  }
677  if ( maxBackWinding[i] < maxBack ) {
678  maxBack = maxBackWinding[i];
679  }
680  }
681 
682  if ( maxFront < BRUSH_EPSILON ) {
683  if ( back ) {
684  *back = Copy();
685  }
686  return PLANESIDE_BACK;
687  }
688 
689  if ( maxBack > -BRUSH_EPSILON ) {
690  if ( front ) {
691  *front = Copy();
692  }
693  return PLANESIDE_FRONT;
694  }
695 
696  mid = new idWinding( plane.Normal(), plane.Dist() );
697 
698  for ( i = 0; i < sides.Num() && mid; i++ ) {
699  mid = mid->Clip( -sides[i]->plane, BRUSH_EPSILON, false );
700  }
701 
702  if ( mid ) {
703  if ( mid->IsTiny() ) {
704  delete mid;
705  mid = NULL;
706  }
707  else if ( mid->IsHuge() ) {
708  // if the winding is huge then the brush is unbounded
709  common->Warning( "brush %d on entity %d is unbounded"
710  "( %1.2f %1.2f %1.2f )-( %1.2f %1.2f %1.2f )-( %1.2f %1.2f %1.2f )", primitiveNum, entityNum,
711  bounds[0][0], bounds[0][1], bounds[0][2], bounds[1][0], bounds[1][1], bounds[1][2],
712  bounds[1][0]-bounds[0][0], bounds[1][1]-bounds[0][1], bounds[1][2]-bounds[0][2] );
713  delete mid;
714  mid = NULL;
715  }
716  }
717 
718  if ( !mid ) {
719  if ( maxFront > - maxBack ) {
720  if ( front ) {
721  *front = Copy();
722  }
723  return PLANESIDE_FRONT;
724  }
725  else {
726  if ( back ) {
727  *back = Copy();
728  }
729  return PLANESIDE_BACK;
730  }
731  }
732 
733  if ( !front && !back ) {
734  delete mid;
735  return PLANESIDE_CROSS;
736  }
737 
738  *front = new idBrush();
739  (*front)->SetContents( contents );
740  (*front)->SetEntityNum( entityNum );
741  (*front)->SetPrimitiveNum( primitiveNum );
742  *back = new idBrush();
743  (*back)->SetContents( contents );
744  (*back)->SetEntityNum( entityNum );
745  (*back)->SetPrimitiveNum( primitiveNum );
746 
747  for ( i = 0; i < sides.Num(); i++ ) {
748  side = sides[i];
749 
750  if ( !side->winding ) {
751  continue;
752  }
753 
754  // if completely at the front
755  if ( maxBackWinding[i] >= BRUSH_EPSILON ) {
756  (*front)->sides.Append( side->Copy() );
757  }
758  // if completely at the back
759  else if ( maxFrontWinding[i] <= -BRUSH_EPSILON ) {
760  (*back)->sides.Append( side->Copy() );
761  }
762  else {
763  // split the side
764  side->Split( plane, &frontSide, &backSide );
765  if ( frontSide ) {
766  (*front)->sides.Append( frontSide );
767  }
768  else if ( maxFrontWinding[i] > -BRUSH_EPSILON ) {
769  // favor an overconstrained brush
770  side = side->Copy();
771  side->winding = side->winding->Clip( idPlane( plane.Normal(), (plane.Dist() - (BRUSH_EPSILON+0.02f)) ), 0.01f, true );
772  assert( side->winding );
773  (*front)->sides.Append( side );
774  }
775  if ( backSide ) {
776  (*back)->sides.Append( backSide );
777  }
778  else if ( maxBackWinding[i] < BRUSH_EPSILON ) {
779  // favor an overconstrained brush
780  side = side->Copy();
781  side->winding = side->winding->Clip( idPlane( -plane.Normal(), -(plane.Dist() + (BRUSH_EPSILON+0.02f)) ), 0.01f, true );
782  assert( side->winding );
783  (*back)->sides.Append( side );
784  }
785  }
786  }
787 
788  side = new idBrushSide( -plane, planeNum^1 );
789  side->winding = mid->Reverse();
790  side->flags |= SFL_SPLIT;
791  (*front)->sides.Append( side );
792  (*front)->windingsValid = true;
793  (*front)->BoundBrush( this );
794 
795  side = new idBrushSide( plane, planeNum );
796  side->winding = mid;
797  side->flags |= SFL_SPLIT;
798  (*back)->sides.Append( side );
799  (*back)->windingsValid = true;
800  (*back)->BoundBrush( this );
801 
802  return PLANESIDE_CROSS;
803 }
804 
805 /*
806 ============
807 idBrush::AddBevelsForAxialBox
808 ============
809 */
810 #define BRUSH_BEVEL_EPSILON 0.1f
811 
813  int axis, dir, i, j, k, l, order;
814  idBrushSide *side, *newSide;
815  idPlane plane;
816  idVec3 normal, vec;
817  idWinding *w, *w2;
818  float d, minBack;
819 
821 
822  // add the axial planes
823  order = 0;
824  for ( axis = 0; axis < 3; axis++ ) {
825 
826  for ( dir = -1; dir <= 1; dir += 2, order++ ) {
827 
828  // see if the plane is already present
829  for ( i = 0; i < sides.Num(); i++ ) {
830  if ( dir > 0 ) {
831  if ( sides[i]->plane.Normal()[axis] >= 0.9999f ) {
832  break;
833  }
834  }
835  else {
836  if ( sides[i]->plane.Normal()[axis] <= -0.9999f ) {
837  break;
838  }
839  }
840  }
841 
842  if ( i >= sides.Num() ) {
843  normal = vec3_origin;
844  normal[axis] = dir;
845  plane.SetNormal( normal );
846  plane.SetDist( dir * bounds[(dir == 1)][axis] );
847  newSide = new idBrushSide( plane, -1 );
848  newSide->SetFlag( SFL_BEVEL );
849  sides.Append( newSide );
850  }
851  }
852  }
853 
854  // if the brush is pure axial we're done
855  if ( sides.Num() == 6 ) {
856  return;
857  }
858 
859  // test the non-axial plane edges
860  for ( i = 0; i < sides.Num(); i++ ) {
861  side = sides[i];
862  w = side->winding;
863  if ( !w ) {
864  continue;
865  }
866 
867  for ( j = 0; j < w->GetNumPoints(); j++) {
868  k = (j+1) % w->GetNumPoints();
869  vec = (*w)[j].ToVec3() - (*w)[k].ToVec3();
870  if ( vec.Normalize() < 0.5f ) {
871  continue;
872  }
873  for ( k = 0; k < 3; k++ ) {
874  if ( vec[k] == 1.0f || vec[k] == -1.0f || (vec[k] == 0.0f && vec[(k+1)%3] == 0.0f) ) {
875  break; // axial
876  }
877  }
878  if ( k < 3 ) {
879  continue; // only test non-axial edges
880  }
881 
882  // try the six possible slanted axials from this edge
883  for ( axis = 0; axis < 3; axis++ ) {
884 
885  for ( dir = -1; dir <= 1; dir += 2 ) {
886 
887  // construct a plane
888  normal = vec3_origin;
889  normal[axis] = dir;
890  normal = vec.Cross( normal );
891  if ( normal.Normalize() < 0.5f ) {
892  continue;
893  }
894  plane.SetNormal( normal );
895  plane.FitThroughPoint( (*w)[j].ToVec3() );
896 
897  // if all the points on all the sides are
898  // behind this plane, it is a proper edge bevel
899  for ( k = 0; k < sides.Num(); k++ ) {
900 
901  // if this plane has allready been used, skip it
902  if ( plane.Compare( sides[k]->plane, 0.001f, 0.1f ) ) {
903  break;
904  }
905 
906  w2 = sides[k]->winding;
907  if ( !w2 ) {
908  continue;
909  }
910  minBack = 0.0f;
911  for ( l = 0; l < w2->GetNumPoints(); l++ ) {
912  d = plane.Distance( (*w2)[l].ToVec3() );
913  if ( d > BRUSH_BEVEL_EPSILON ) {
914  break; // point at the front
915  }
916  if ( d < minBack ) {
917  minBack = d;
918  }
919  }
920  // if some point was at the front
921  if ( l < w2->GetNumPoints() ) {
922  break;
923  }
924  // if no points at the back then the winding is on the bevel plane
925  if ( minBack > -BRUSH_BEVEL_EPSILON ) {
926  break;
927  }
928  }
929 
930  if ( k < sides.Num() ) {
931  continue; // wasn't part of the outer hull
932  }
933 
934  // add this plane
935  newSide = new idBrushSide( plane, -1 );
936  newSide->SetFlag( SFL_BEVEL );
937  sides.Append( newSide );
938  }
939  }
940  }
941  }
942 }
943 
944 /*
945 ============
946 idBrush::ExpandForAxialBox
947 ============
948 */
949 void idBrush::ExpandForAxialBox( const idBounds &bounds ) {
950  int i, j;
951  idBrushSide *side;
952  idVec3 v;
953 
955 
956  for ( i = 0; i < sides.Num(); i++ ) {
957  side = sides[i];
958 
959  for ( j = 0; j < 3; j++ ) {
960  if ( side->plane.Normal()[j] > 0.0f ) {
961  v[j] = bounds[0][j];
962  }
963  else {
964  v[j] = bounds[1][j];
965  }
966  }
967 
968  side->plane.SetDist( side->plane.Dist() + v * -side->plane.Normal() );
969  }
970 
971  if ( !CreateWindings() ) {
972  common->Error( "idBrush::ExpandForAxialBox: brush %d on entity %d imploded", primitiveNum, entityNum );
973  }
974 
975  /*
976  // after expansion at least all non bevel sides should have a winding
977  for ( i = 0; i < sides.Num(); i++ ) {
978  side = sides[i];
979  if ( !side->winding ) {
980  if ( !( side->flags & SFL_BEVEL ) ) {
981  int shit = 1;
982  }
983  }
984  }
985  */
986 }
987 
988 /*
989 ============
990 idBrush::Copy
991 ============
992 */
993 idBrush *idBrush::Copy( void ) const {
994  int i;
995  idBrush *b;
996 
997  b = new idBrush();
998  b->entityNum = entityNum;
1000  b->contents = contents;
1002  b->bounds = bounds;
1003  for ( i = 0; i < sides.Num(); i++ ) {
1004  b->sides.Append( sides[i]->Copy() );
1005  }
1006  return b;
1007 }
1008 
1009 
1010 //===============================================================
1011 //
1012 // idBrushList
1013 //
1014 //===============================================================
1015 
1016 /*
1017 ============
1018 idBrushList::idBrushList
1019 ============
1020 */
1022  numBrushes = numBrushSides = 0;
1023  head = tail = NULL;
1024 }
1025 
1026 /*
1027 ============
1028 idBrushList::~idBrushList
1029 ============
1030 */
1032 }
1033 
1034 /*
1035 ============
1036 idBrushList::GetBounds
1037 ============
1038 */
1040  idBounds bounds;
1041  idBrush *b;
1042 
1043  bounds.Clear();
1044  for ( b = Head(); b; b = b->Next() ) {
1045  bounds += b->GetBounds();
1046  }
1047  return bounds;
1048 }
1049 
1050 /*
1051 ============
1052 idBrushList::AddToTail
1053 ============
1054 */
1056  brush->next = NULL;
1057  if ( tail ) {
1058  tail->next = brush;
1059  }
1060  tail = brush;
1061  if ( !head ) {
1062  head = brush;
1063  }
1064  numBrushes++;
1065  numBrushSides += brush->sides.Num();
1066 }
1067 
1068 /*
1069 ============
1070 idBrushList::AddToTail
1071 ============
1072 */
1074  idBrush *brush, *next;
1075 
1076  for ( brush = list.head; brush; brush = next ) {
1077  next = brush->next;
1078  brush->next = NULL;
1079  if ( tail ) {
1080  tail->next = brush;
1081  }
1082  tail = brush;
1083  if ( !head ) {
1084  head = brush;
1085  }
1086  numBrushes++;
1087  numBrushSides += brush->sides.Num();
1088  }
1089  list.head = list.tail = NULL;
1090  list.numBrushes = 0;
1091 }
1092 
1093 /*
1094 ============
1095 idBrushList::AddToFront
1096 ============
1097 */
1099  brush->next = head;
1100  head = brush;
1101  if ( !tail ) {
1102  tail = brush;
1103  }
1104  numBrushes++;
1105  numBrushSides += brush->sides.Num();
1106 }
1107 
1108 /*
1109 ============
1110 idBrushList::AddToFront
1111 ============
1112 */
1114  idBrush *brush, *next;
1115 
1116  for ( brush = list.head; brush; brush = next ) {
1117  next = brush->next;
1118  brush->next = head;
1119  head = brush;
1120  if ( !tail ) {
1121  tail = brush;
1122  }
1123  numBrushes++;
1124  numBrushSides += brush->sides.Num();
1125  }
1126  list.head = list.tail = NULL;
1127  list.numBrushes = 0;
1128 }
1129 
1130 /*
1131 ============
1132 idBrushList::Remove
1133 ============
1134 */
1136  idBrush *b, *last;
1137 
1138  last = NULL;
1139  for ( b = head; b; b = b->next ) {
1140  if ( b == brush ) {
1141  if ( last ) {
1142  last->next = b->next;
1143  }
1144  else {
1145  head = b->next;
1146  }
1147  if ( b == tail ) {
1148  tail = last;
1149  }
1150  numBrushes--;
1151  numBrushSides -= brush->sides.Num();
1152  return;
1153  }
1154  last = b;
1155  }
1156 }
1157 
1158 /*
1159 ============
1160 idBrushList::Delete
1161 ============
1162 */
1164  idBrush *b, *last;
1165 
1166  last = NULL;
1167  for ( b = head; b; b = b->next ) {
1168  if ( b == brush ) {
1169  if ( last ) {
1170  last->next = b->next;
1171  }
1172  else {
1173  head = b->next;
1174  }
1175  if ( b == tail ) {
1176  tail = last;
1177  }
1178  numBrushes--;
1179  numBrushSides -= b->sides.Num();
1180  delete b;
1181  return;
1182  }
1183  last = b;
1184  }
1185 }
1186 
1187 /*
1188 ============
1189 idBrushList::Copy
1190 ============
1191 */
1193  idBrush *brush;
1194  idBrushList *list;
1195 
1196  list = new idBrushList;
1197 
1198  for ( brush = head; brush; brush = brush->next ) {
1199  list->AddToTail( brush->Copy() );
1200  }
1201  return list;
1202 }
1203 
1204 /*
1205 ============
1206 idBrushList::Free
1207 ============
1208 */
1209 void idBrushList::Free( void ) {
1210  idBrush *brush, *next;
1211 
1212  for ( brush = head; brush; brush = next ) {
1213  next = brush->next;
1214  delete brush;
1215  }
1216  head = tail = NULL;
1217  numBrushes = numBrushSides = 0;
1218 }
1219 
1220 /*
1221 ============
1222 idBrushList::Split
1223 ============
1224 */
1225 void idBrushList::Split( const idPlane &plane, int planeNum, idBrushList &frontList, idBrushList &backList, bool useBrushSavedPlaneSide ) {
1226  idBrush *b, *front, *back;
1227 
1228  frontList.Clear();
1229  backList.Clear();
1230 
1231  if ( !useBrushSavedPlaneSide ) {
1232  for ( b = head; b; b = b->next ) {
1233  b->Split( plane, planeNum, &front, &back );
1234  if ( front ) {
1235  frontList.AddToTail( front );
1236  }
1237  if ( back ) {
1238  backList.AddToTail( back );
1239  }
1240  }
1241  return;
1242  }
1243 
1244  for ( b = head; b; b = b->next ) {
1245  if ( b->savedPlaneSide & BRUSH_PLANESIDE_BOTH ) {
1246  b->Split( plane, planeNum, &front, &back );
1247  if ( front ) {
1248  frontList.AddToTail( front );
1249  }
1250  if ( back ) {
1251  backList.AddToTail( back );
1252  }
1253  }
1254  else if ( b->savedPlaneSide & BRUSH_PLANESIDE_FRONT ) {
1255  frontList.AddToTail( b->Copy() );
1256  }
1257  else {
1258  backList.AddToTail( b->Copy() );
1259  }
1260  }
1261 }
1262 
1263 /*
1264 ============
1265 idBrushList::Chop
1266 ============
1267 */
1268 void idBrushList::Chop( bool (*ChopAllowed)( idBrush *b1, idBrush *b2 ) ) {
1269  idBrush *b1, *b2, *next;
1270  idBrushList sub1, sub2, keep;
1271  int i, j, c1, c2;
1272  idPlaneSet planeList;
1273 
1274 #ifdef OUTPUT_CHOP_STATS
1275  common->Printf( "[Brush CSG]\n");
1276  common->Printf( "%6d original brushes\n", this->Num() );
1277 #endif
1278 
1279  CreatePlaneList( planeList );
1280 
1281  for ( b1 = this->Head(); b1; b1 = this->Head() ) {
1282 
1283  for ( b2 = b1->next; b2; b2 = next ) {
1284 
1285  next = b2->next;
1286 
1287  for ( i = 0; i < 3; i++ ) {
1288  if ( b1->bounds[0][i] >= b2->bounds[1][i] ) {
1289  break;
1290  }
1291  if ( b1->bounds[1][i] <= b2->bounds[0][i] ) {
1292  break;
1293  }
1294  }
1295  if ( i < 3 ) {
1296  continue;
1297  }
1298 
1299  for ( i = 0; i < b1->GetNumSides(); i++ ) {
1300  for ( j = 0; j < b2->GetNumSides(); j++ ) {
1301  if ( b1->GetSide(i)->GetPlaneNum() == ( b2->GetSide(j)->GetPlaneNum() ^ 1 ) ) {
1302  // opposite planes, so not touching
1303  break;
1304  }
1305  }
1306  if ( j < b2->GetNumSides() ) {
1307  break;
1308  }
1309  }
1310  if ( i < b1->GetNumSides() ) {
1311  continue;
1312  }
1313 
1314  sub1.Clear();
1315  sub2.Clear();
1316 
1317  c1 = 999999;
1318  c2 = 999999;
1319 
1320  // if b2 may chop up b1
1321  if ( !ChopAllowed || ChopAllowed( b2, b1 ) ) {
1322  if ( !b1->Subtract( b2, sub1 ) ) {
1323  // didn't really intersect
1324  continue;
1325  }
1326  if ( sub1.IsEmpty() ) {
1327  // b1 is swallowed by b2
1328  this->Delete( b1 );
1329  break;
1330  }
1331  c1 = sub1.Num();
1332  }
1333 
1334  // if b1 may chop up b2
1335  if ( !ChopAllowed || ChopAllowed( b1, b2 ) ) {
1336  if ( !b2->Subtract( b1, sub2 ) ) {
1337  // didn't really intersect
1338  continue;
1339  }
1340  if ( sub2.IsEmpty() ) {
1341  // b2 is swallowed by b1
1342  sub1.Free();
1343  this->Delete( b2 );
1344  continue;
1345  }
1346  c2 = sub2.Num();
1347  }
1348 
1349  if ( sub1.IsEmpty() && sub2.IsEmpty() ) {
1350  continue;
1351  }
1352 
1353  // don't allow too much fragmentation
1354  if ( c1 > 2 && c2 > 2 ) {
1355  sub1.Free();
1356  sub2.Free();
1357  continue;
1358  }
1359 
1360  if ( c1 < c2 ) {
1361  sub2.Free();
1362  this->AddToTail( sub1 );
1363  this->Delete( b1 );
1364  break;
1365  }
1366  else {
1367  sub1.Free();
1368  this->AddToTail( sub2 );
1369  this->Delete( b2 );
1370  continue;
1371  }
1372  }
1373 
1374  if ( !b2 ) {
1375  // b1 is no longer intersecting anything, so keep it
1376  this->Remove( b1 );
1377  keep.AddToTail( b1 );
1378 #ifdef OUTPUT_CHOP_STATS
1379  DisplayRealTimeString( "\r%6d", keep.numBrushes );
1380 #endif
1381  }
1382  }
1383 
1384  *this = keep;
1385 
1386 #ifdef OUTPUT_CHOP_STATS
1387  common->Printf( "\r%6d output brushes\n", Num() );
1388 #endif
1389 }
1390 
1391 
1392 /*
1393 ============
1394 idBrushList::Merge
1395 ============
1396 */
1397 void idBrushList::Merge( bool (*MergeAllowed)( idBrush *b1, idBrush *b2 ) ) {
1398  idPlaneSet planeList;
1399  idBrush *b1, *b2, *nextb2;
1400  int numMerges;
1401 
1402  common->Printf( "[Brush Merge]\n");
1403  common->Printf( "%6d original brushes\n", Num() );
1404 
1405  CreatePlaneList( planeList );
1406 
1407  numMerges = 0;
1408  for ( b1 = Head(); b1; b1 = b1->next ) {
1409 
1410  for ( b2 = Head(); b2; b2 = nextb2 ) {
1411  nextb2 = b2->Next();
1412 
1413  if ( b2 == b1 ) {
1414  continue;
1415  }
1416 
1417  if ( MergeAllowed && !MergeAllowed( b1, b2 ) ) {
1418  continue;
1419  }
1420 
1421  if ( b1->TryMerge( b2, planeList ) ) {
1422  Delete( b2 );
1423  DisplayRealTimeString( "\r%6d", ++numMerges );
1424  nextb2 = Head();
1425  }
1426  }
1427  }
1428 
1429  common->Printf( "\r%6d brushes merged\n", numMerges );
1430 }
1431 
1432 /*
1433 ============
1434 idBrushList::SetFlagOnFacingBrushSides
1435 ============
1436 */
1437 void idBrushList::SetFlagOnFacingBrushSides( const idPlane &plane, int flag ) {
1438  int i;
1439  idBrush *b;
1440  const idWinding *w;
1441 
1442  for ( b = head; b; b = b->next ) {
1443  if ( idMath::Fabs( b->GetBounds().PlaneDistance( plane ) ) > 0.1f ) {
1444  continue;
1445  }
1446  for ( i = 0; i < b->GetNumSides(); i++ ) {
1447  w = b->GetSide(i)->GetWinding();
1448  if ( !w ) {
1450  b->GetSide(i)->SetFlag( flag );
1451  }
1452  continue;
1453  }
1454  if ( w->PlaneSide( plane ) == SIDE_ON ) {
1455  b->GetSide(i)->SetFlag( flag );
1456  }
1457  }
1458  }
1459 }
1460 
1461 /*
1462 ============
1463 idBrushList::CreatePlaneList
1464 ============
1465 */
1466 void idBrushList::CreatePlaneList( idPlaneSet &planeList ) const {
1467  int i;
1468  idBrush *b;
1469  idBrushSide *side;
1470 
1471  planeList.Resize( 512, 128 );
1472  for ( b = Head(); b; b = b->Next() ) {
1473  for ( i = 0; i < b->GetNumSides(); i++ ) {
1474  side = b->GetSide( i );
1476  }
1477  }
1478 }
1479 
1480 /*
1481 ============
1482 idBrushList::CreatePlaneList
1483 ============
1484 */
1485 void idBrushList::WriteBrushMap( const idStr &fileName, const idStr &ext ) const {
1486  idBrushMap *map;
1487 
1488  map = new idBrushMap( fileName, ext );
1489  map->WriteBrushList( *this );
1490  delete map;
1491 }
1492 
1493 
1494 //===============================================================
1495 //
1496 // idBrushMap
1497 //
1498 //===============================================================
1499 
1500 /*
1501 ============
1502 idBrushMap::idBrushMap
1503 ============
1504 */
1505 idBrushMap::idBrushMap( const idStr &fileName, const idStr &ext ) {
1506  idStr qpath;
1507 
1508  qpath = fileName;
1509  qpath.StripFileExtension();
1510  qpath += ext;
1511  qpath.SetFileExtension( "map" );
1512 
1513  common->Printf( "writing %s...\n", qpath.c_str() );
1514 
1515  fp = fileSystem->OpenFileWrite( qpath, "fs_devpath" );
1516  if ( !fp ) {
1517  common->Error( "Couldn't open %s\n", qpath.c_str() );
1518  return;
1519  }
1520 
1521  texture = "textures/washroom/btile01";
1522 
1523  fp->WriteFloatString( "Version %1.2f\n", (float) CURRENT_MAP_VERSION );
1524  fp->WriteFloatString( "{\n" );
1525  fp->WriteFloatString( "\"classname\" \"worldspawn\"\n" );
1526 
1527  brushCount = 0;
1528 }
1529 
1530 /*
1531 ============
1532 idBrushMap::~idBrushMap
1533 ============
1534 */
1536  if ( !fp ) {
1537  return;
1538  }
1539  fp->WriteFloatString( "}\n" );
1540  fileSystem->CloseFile( fp );
1541 }
1542 
1543 /*
1544 ============
1545 idBrushMap::WriteBrush
1546 ============
1547 */
1548 void idBrushMap::WriteBrush( const idBrush *brush ) {
1549  int i;
1550  idBrushSide *side;
1551 
1552  if ( !fp ) {
1553  return;
1554  }
1555 
1556  fp->WriteFloatString( "// primitive %d\n{\nbrushDef3\n{\n", brushCount++ );
1557 
1558  for ( i = 0; i < brush->GetNumSides(); i++ ) {
1559  side = brush->GetSide( i );
1560  fp->WriteFloatString( " ( %f %f %f %f ) ", side->GetPlane()[0], side->GetPlane()[1], side->GetPlane()[2], -side->GetPlane().Dist() );
1561  fp->WriteFloatString( "( ( 0.031250 0 0 ) ( 0 0.031250 0 ) ) %s 0 0 0\n", texture.c_str() );
1562 
1563  }
1564  fp->WriteFloatString( "}\n}\n" );
1565 }
1566 
1567 /*
1568 ============
1569 idBrushMap::WriteBrushList
1570 ============
1571 */
1572 void idBrushMap::WriteBrushList( const idBrushList &brushList ) {
1573  idBrush *b;
1574 
1575  if ( !fp ) {
1576  return;
1577  }
1578 
1579  for ( b = brushList.Head(); b; b = b->Next() ) {
1580  WriteBrush( b );
1581  }
1582 }
idBrushMap(const idStr &fileName, const idStr &ext)
Definition: Brush.cpp:1505
void Clear(void)
Definition: Brush.h:170
int GetFlags(void) const
Definition: Brush.h:72
idBrush * next
Definition: Brush.h:136
#define BRUSH_PLANE_DIST_EPSILON
Definition: Brush.cpp:36
#define BRUSH_PLANESIDE_BOTH
Definition: Brush.h:43
float Normalize(void)
Definition: Vector.h:646
int contents
Definition: Brush.h:141
void AddBevelsForAxialBox(void)
Definition: Brush.cpp:812
idStr & SetFileExtension(const char *extension)
Definition: Str.cpp:743
float GetArea(void) const
Definition: Winding.cpp:598
assert(prefInfo.fullscreenBtn)
const idVec3 & Normal(void) const
Definition: Plane.h:239
bool Compare(const idPlane &p) const
Definition: Plane.h:187
#define BRUSH_BEVEL_EPSILON
Definition: Brush.cpp:810
void Transform(const idVec3 &origin, const idMat3 &axis)
Definition: Brush.cpp:406
#define BRUSH_PLANE_NORMAL_EPSILON
Definition: Brush.cpp:35
idBrush * tail
Definition: Brush.h:204
idBrushList(void)
Definition: Brush.cpp:1021
idList< idBrushSide * > sides
Definition: Brush.h:145
const GLdouble * v
Definition: glext.h:2936
#define BRUSH_EPSILON
Definition: Brush.cpp:34
int numBrushSides
Definition: Brush.h:206
float Distance(const idVec3 &v) const
Definition: Plane.h:324
void CreatePlaneList(idPlaneSet &planeList) const
Definition: Brush.cpp:1466
idBounds bounds
Definition: Brush.h:144
const idWinding * GetWinding(void) const
Definition: Brush.h:78
bool Subtract(const idBrush *b, idBrushList &list) const
Definition: Brush.cpp:471
idBrush * head
Definition: Brush.h:203
bool RemoveSidesWithoutWinding(void)
Definition: Brush.cpp:196
float GetVolume(void) const
Definition: Brush.cpp:432
int Sys_Milliseconds(void)
void ExpandForAxialBox(const idBounds &bounds)
Definition: Brush.cpp:949
idBrush * Copy(void) const
Definition: Brush.cpp:993
idFileSystem * fileSystem
Definition: FileSystem.cpp:500
#define MAX_WORLD_COORD
Definition: Lib.h:98
int primitiveNum
Definition: Brush.h:138
void Split(const idPlane &plane, int planeNum, idBrushList &frontList, idBrushList &backList, bool useBrushSavedPlaneSide=false)
Definition: Brush.cpp:1225
Definition: Vector.h:316
case const float
Definition: Callbacks.cpp:62
int Split(const idPlane &splitPlane, idBrushSide **front, idBrushSide **back) const
Definition: Brush.cpp:128
void Chop(bool(*ChopAllowed)(idBrush *b1, idBrush *b2))
Definition: Brush.cpp:1268
idBrushSide * Copy(void) const
Definition: Brush.cpp:109
void Clear(void)
Definition: Bounds.h:201
int entityNum
Definition: Brush.h:137
idBrushSide * GetSide(int i) const
Definition: Brush.h:116
idWinding * Reverse(void) const
Definition: Winding.cpp:478
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
idVec3 Cross(const idVec3 &a) const
Definition: Vector.h:619
bool IsRotated(void) const
Definition: Matrix.h:624
void Free(void)
Definition: Brush.cpp:1209
bool windingsValid
Definition: Brush.h:140
int i
Definition: process.py:33
const int CURRENT_MAP_VERSION
Definition: MapFile.h:47
int FindPlane(const idPlane &plane, const float normalEps, const float distEps)
Definition: PlaneSet.h:51
~idBrushList(void)
Definition: Brush.cpp:1031
#define MIN_WORLD_COORD
Definition: Lib.h:99
list l
Definition: prepare.py:17
~idBrushSide(void)
Definition: Brush.cpp:98
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
Definition: Winding.cpp:1292
int flags
Definition: Brush.h:83
~idBrushMap(void)
Definition: Brush.cpp:1535
#define PLANESIDE_FRONT
Definition: Plane.h:53
bool AddPoint(const idVec3 &v)
Definition: Bounds.h:226
int brushCount
Definition: Brush.h:228
void Delete(idBrush *brush)
Definition: Brush.cpp:1163
idBrush * Head(void) const
Definition: Brush.h:168
bool FromWinding(const idWinding &w, const idPlane &windingPlane)
Definition: Brush.cpp:330
bool CreateWindings(void)
Definition: Brush.cpp:217
GLdouble GLdouble GLint GLint order
Definition: qgl.h:339
int GetNumPoints(void) const
Definition: Winding.h:238
idBrush(void)
Definition: Brush.cpp:172
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3454
void SetDist(const float dist)
Definition: Plane.h:275
idStr & StripFileExtension(void)
Definition: Str.cpp:757
void Remove(idBrush *brush)
Definition: Brush.cpp:1135
#define MAX_STRING_CHARS
Definition: Lib.h:95
idVec3 vec3_origin(0.0f, 0.0f, 0.0f)
bool IsHuge(void) const
Definition: Winding.cpp:1226
void AddToTail(idBrush *brush)
Definition: Brush.cpp:1055
static float Fabs(float f)
Definition: Math.h:779
idCommon * common
Definition: Common.cpp:206
#define PLANESIDE_BACK
Definition: Plane.h:54
float PlaneDistance(const idPlane &plane) const
Definition: Bounds.cpp:83
#define NULL
Definition: Lib.h:88
const idBounds & GetBounds(void) const
Definition: Brush.h:113
int savedPlaneSide
Definition: Brush.h:143
virtual idFile * OpenFileWrite(const char *relativePath, const char *basePath="fs_savepath")=0
Definition: Plane.h:71
virtual int WriteFloatString(const char *fmt,...) id_attribute((format(printf
Definition: File.cpp:294
#define OUTPUT_UPDATE_TIME
Definition: Brush.cpp:38
void SetFlag(int flag)
Definition: Brush.h:73
void WriteBrushList(const idBrushList &brushList)
Definition: Brush.cpp:1572
virtual void Printf(const char *fmt,...) id_attribute((format(printf
idWinding * winding
Definition: Brush.h:86
void WriteBrushMap(const idStr &fileName, const idStr &ext) const
Definition: Brush.cpp:1485
void AddToFront(idBrush *brush)
Definition: Brush.cpp:1098
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: glext.h:4080
GLubyte GLubyte b
Definition: glext.h:4662
bool IsTiny(void) const
Definition: Winding.cpp:1202
void BoundBrush(const idBrush *original=NULL)
Definition: Brush.cpp:265
idBrush * Next(void) const
Definition: Brush.h:133
idBrushSide(void)
Definition: Brush.cpp:75
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
Definition: Matrix.h:333
#define SFL_BEVEL
Definition: Brush.h:59
tuple f
Definition: idal.py:89
GLuint in
Definition: glext.h:5388
void SetPlaneNum(int num)
Definition: Brush.h:76
int Num(void) const
Definition: List.h:265
bool IsEmpty(void) const
Definition: Brush.h:171
bool RemoveIndex(int index)
Definition: List.h:849
idBrushList * Copy(void) const
Definition: Brush.cpp:1192
GLuint texture
Definition: glext.h:3871
idWinding * Copy(void) const
Definition: Winding.cpp:464
Definition: Str.h:116
const idPlane & GetPlane(void) const
Definition: Brush.h:75
#define SFL_SPLIT
Definition: Brush.h:58
int GetPlaneNum(void)
Definition: Brush.h:77
int vsprintf(idStr &string, const char *fmt, va_list argptr)
Definition: Str.cpp:1549
const char * c_str(void) const
Definition: Str.h:487
int numBrushes
Definition: Brush.h:205
void SetFlagOnFacingBrushSides(const idPlane &plane, int flag)
Definition: Brush.cpp:1437
void Merge(bool(*MergeAllowed)(idBrush *b1, idBrush *b2))
Definition: Brush.cpp:1397
GLuint res
Definition: glext.h:5385
void DisplayRealTimeString(char *string,...)
Definition: Brush.cpp:47
#define PLANESIDE_CROSS
Definition: Plane.h:56
GLint j
Definition: qgl.h:264
int planeNum
Definition: Brush.h:84
bool FromBounds(const idBounds &bounds)
Definition: Brush.cpp:383
int GetNumSides(void) const
Definition: Brush.h:115
virtual void CloseFile(idFile *f)=0
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
Definition: Bounds.cpp:108
bool MergeAllowed(idBrush *b1, idBrush *b2)
Definition: AASBuild.cpp:597
virtual void Error(const char *fmt,...) id_attribute((format(printf
void WriteBrush(const idBrush *brush)
Definition: Brush.cpp:1548
idPlane plane
Definition: Brush.h:85
idBounds GetBounds(void) const
Definition: Brush.cpp:1039
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
Definition: Brush.h:98
void Resize(int newsize)
Definition: List.h:360
int flags
Definition: Brush.h:139
bool FromSides(idList< idBrushSide * > &sideList)
Definition: Brush.cpp:313
float Dist(void) const
Definition: Plane.h:271
bool TryMerge(const idBrush *brush, const idPlaneSet &planeList)
Definition: Brush.cpp:505
#define BRUSH_PLANESIDE_FRONT
Definition: Brush.h:41
idFile * fp
Definition: Brush.h:226
int Num(void) const
Definition: Brush.h:166
void FitThroughPoint(const idVec3 &p)
Definition: Plane.h:297
int Split(const idPlane &plane, int planeNum, idBrush **front, idBrush **back) const
Definition: Brush.cpp:618
~idBrush(void)
Definition: Brush.cpp:185
void Clear(void)
Definition: List.h:184