doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
facebsp.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 "dmap.h"
33 
35 
36 
37 extern int c_nodes;
38 
39 void RemovePortalFromNode( uPortal_t *portal, node_t *l );
40 
41 node_t *NodeForPoint( node_t *node, idVec3 origin ) {
42  float d;
43 
44  while( node->planenum != PLANENUM_LEAF ) {
45  idPlane &plane = dmapGlobals.mapPlanes[node->planenum];
46  d = plane.Distance( origin );
47  if ( d >= 0 ) {
48  node = node->children[0];
49  } else {
50  node = node->children[1];
51  }
52  }
53 
54  return node;
55 }
56 
57 
58 
59 /*
60 =============
61 FreeTreePortals_r
62 =============
63 */
65 {
66  uPortal_t *p, *nextp;
67  int s;
68 
69  // free children
70  if (node->planenum != PLANENUM_LEAF)
71  {
72  FreeTreePortals_r (node->children[0]);
73  FreeTreePortals_r (node->children[1]);
74  }
75 
76  // free portals
77  for (p=node->portals ; p ; p=nextp)
78  {
79  s = (p->nodes[1] == node);
80  nextp = p->next[s];
81 
82  RemovePortalFromNode (p, p->nodes[!s]);
83  FreePortal (p);
84  }
85  node->portals = NULL;
86 }
87 
88 /*
89 =============
90 FreeTree_r
91 =============
92 */
93 void FreeTree_r (node_t *node)
94 {
95  // free children
96  if (node->planenum != PLANENUM_LEAF)
97  {
98  FreeTree_r (node->children[0]);
99  FreeTree_r (node->children[1]);
100  }
101 
102  // free brushes
103  FreeBrushList (node->brushlist);
104 
105  // free the node
106  c_nodes--;
107  Mem_Free (node);
108 }
109 
110 
111 /*
112 =============
113 FreeTree
114 =============
115 */
116 void FreeTree( tree_t *tree ) {
117  if ( !tree ) {
118  return;
119  }
120  FreeTreePortals_r (tree->headnode);
121  FreeTree_r (tree->headnode);
122  Mem_Free (tree);
123 }
124 
125 //===============================================================
126 
127 void PrintTree_r (node_t *node, int depth)
128 {
129  int i;
130  uBrush_t *bb;
131 
132  for (i=0 ; i<depth ; i++)
133  common->Printf(" ");
134  if (node->planenum == PLANENUM_LEAF)
135  {
136  if (!node->brushlist)
137  common->Printf("NULL\n");
138  else
139  {
140  for (bb=node->brushlist ; bb ; bb=bb->next)
141  common->Printf("%i ", bb->original->brushnum);
142  common->Printf("\n");
143  }
144  return;
145  }
146 
147  idPlane &plane = dmapGlobals.mapPlanes[node->planenum];
148  common->Printf( "#%i (%5.2f %5.2f %5.2f %5.2f)\n", node->planenum,
149  plane[0], plane[1], plane[2], plane[3] );
150  PrintTree_r( node->children[0], depth+1 );
151  PrintTree_r( node->children[1], depth+1 );
152 }
153 
154 /*
155 ================
156 AllocBspFace
157 ================
158 */
160  bspface_t *f;
161 
162  f = (bspface_t *)Mem_Alloc(sizeof(*f));
163  memset( f, 0, sizeof(*f) );
164 
165  return f;
166 }
167 
168 /*
169 ================
170 FreeBspFace
171 ================
172 */
174  if ( f->w ) {
175  delete f->w;
176  }
177  Mem_Free( f );
178 }
179 
180 
181 /*
182 ================
183 SelectSplitPlaneNum
184 ================
185 */
186 #define BLOCK_SIZE 1024
187 int SelectSplitPlaneNum( node_t *node, bspface_t *list ) {
188  bspface_t *split;
189  bspface_t *check;
190  bspface_t *bestSplit;
191  int splits, facing, front, back;
192  int side;
193  idPlane *mapPlane;
194  int value, bestValue;
195  idPlane plane;
196  int planenum;
197  bool havePortals;
198  float dist;
199  idVec3 halfSize;
200 
201  // if it is crossing a 1k block boundary, force a split
202  // this prevents epsilon problems from extending an
203  // arbitrary distance across the map
204 
205  halfSize = ( node->bounds[1] - node->bounds[0] ) * 0.5f;
206  for ( int axis = 0; axis < 3; axis++ ) {
207  if ( halfSize[axis] > BLOCK_SIZE ) {
208  dist = BLOCK_SIZE * ( floor( ( node->bounds[0][axis] + halfSize[axis] ) / BLOCK_SIZE ) + 1.0f );
209  } else {
210  dist = BLOCK_SIZE * ( floor( node->bounds[0][axis] / BLOCK_SIZE ) + 1.0f );
211  }
212  if ( dist > node->bounds[0][axis] + 1.0f && dist < node->bounds[1][axis] - 1.0f ) {
213  plane[0] = plane[1] = plane[2] = 0.0f;
214  plane[axis] = 1.0f;
215  plane[3] = -dist;
216  planenum = FindFloatPlane( plane );
217  return planenum;
218  }
219  }
220 
221  // pick one of the face planes
222  // if we have any portal faces at all, only
223  // select from them, otherwise select from
224  // all faces
225  bestValue = -999999;
226  bestSplit = list;
227 
228  havePortals = false;
229  for ( split = list ; split ; split = split->next ) {
230  split->checked = false;
231  if ( split->portal ) {
232  havePortals = true;
233  }
234  }
235 
236  for ( split = list ; split ; split = split->next ) {
237  if ( split->checked ) {
238  continue;
239  }
240  if ( havePortals != split->portal ) {
241  continue;
242  }
243  mapPlane = &dmapGlobals.mapPlanes[ split->planenum ];
244  splits = 0;
245  facing = 0;
246  front = 0;
247  back = 0;
248  for ( check = list ; check ; check = check->next ) {
249  if ( check->planenum == split->planenum ) {
250  facing++;
251  check->checked = true; // won't need to test this plane again
252  continue;
253  }
254  side = check->w->PlaneSide( *mapPlane );
255  if ( side == SIDE_CROSS ) {
256  splits++;
257  } else if ( side == SIDE_FRONT ) {
258  front++;
259  } else if ( side == SIDE_BACK ) {
260  back++;
261  }
262  }
263  value = 5*facing - 5*splits; // - abs(front-back);
264  if ( mapPlane->Type() < PLANETYPE_TRUEAXIAL ) {
265  value+=5; // axial is better
266  }
267 
268  if ( value > bestValue ) {
269  bestValue = value;
270  bestSplit = split;
271  }
272  }
273 
274  if ( bestValue == -999999 ) {
275  return -1;
276  }
277 
278  return bestSplit->planenum;
279 }
280 
281 /*
282 ================
283 BuildFaceTree_r
284 ================
285 */
286 void BuildFaceTree_r( node_t *node, bspface_t *list ) {
287  bspface_t *split;
288  bspface_t *next;
289  int side;
290  bspface_t *newFace;
291  bspface_t *childLists[2];
292  idWinding *frontWinding, *backWinding;
293  int i;
294  int splitPlaneNum;
295 
296  splitPlaneNum = SelectSplitPlaneNum( node, list );
297  // if we don't have any more faces, this is a node
298  if ( splitPlaneNum == -1 ) {
299  node->planenum = PLANENUM_LEAF;
300  c_faceLeafs++;
301  return;
302  }
303 
304  // partition the list
305  node->planenum = splitPlaneNum;
306  idPlane &plane = dmapGlobals.mapPlanes[ splitPlaneNum ];
307  childLists[0] = NULL;
308  childLists[1] = NULL;
309  for ( split = list ; split ; split = next ) {
310  next = split->next;
311 
312  if ( split->planenum == node->planenum ) {
313  FreeBspFace( split );
314  continue;
315  }
316 
317  side = split->w->PlaneSide( plane );
318 
319  if ( side == SIDE_CROSS ) {
320  split->w->Split( plane, CLIP_EPSILON * 2, &frontWinding, &backWinding );
321  if ( frontWinding ) {
322  newFace = AllocBspFace();
323  newFace->w = frontWinding;
324  newFace->next = childLists[0];
325  newFace->planenum = split->planenum;
326  childLists[0] = newFace;
327  }
328  if ( backWinding ) {
329  newFace = AllocBspFace();
330  newFace->w = backWinding;
331  newFace->next = childLists[1];
332  newFace->planenum = split->planenum;
333  childLists[1] = newFace;
334  }
335  FreeBspFace( split );
336  } else if ( side == SIDE_FRONT ) {
337  split->next = childLists[0];
338  childLists[0] = split;
339  } else if ( side == SIDE_BACK ) {
340  split->next = childLists[1];
341  childLists[1] = split;
342  }
343  }
344 
345 
346  // recursively process children
347  for ( i = 0 ; i < 2 ; i++ ) {
348  node->children[i] = AllocNode();
349  node->children[i]->parent = node;
350  node->children[i]->bounds = node->bounds;
351  }
352 
353  // split the bounds if we have a nice axial plane
354  for ( i = 0 ; i < 3 ; i++ ) {
355  if ( idMath::Fabs( plane[i] - 1.0 ) < 0.001 ) {
356  node->children[0]->bounds[0][i] = plane.Dist();
357  node->children[1]->bounds[1][i] = plane.Dist();
358  break;
359  }
360  }
361 
362  for ( i = 0 ; i < 2 ; i++ ) {
363  BuildFaceTree_r ( node->children[i], childLists[i]);
364  }
365 }
366 
367 
368 /*
369 ================
370 FaceBSP
371 
372 List will be freed before returning
373 ================
374 */
376  tree_t *tree;
377  bspface_t *face;
378  int i;
379  int count;
380  int start, end;
381 
382  start = Sys_Milliseconds();
383 
384  common->Printf( "--- FaceBSP ---\n" );
385 
386  tree = AllocTree ();
387 
388  count = 0;
389  tree->bounds.Clear();
390  for ( face = list ; face ; face = face->next ) {
391  count++;
392  for ( i = 0 ; i < face->w->GetNumPoints() ; i++ ) {
393  tree->bounds.AddPoint( (*face->w)[i].ToVec3() );
394  }
395  }
396  common->Printf( "%5i faces\n", count );
397 
398  tree->headnode = AllocNode();
399  tree->headnode->bounds = tree->bounds;
400  c_faceLeafs = 0;
401 
402  BuildFaceTree_r ( tree->headnode, list );
403 
404  common->Printf( "%5i leafs\n", c_faceLeafs );
405 
406  end = Sys_Milliseconds();
407 
408  common->Printf( "%5.1f seconds faceBsp\n", ( end - start ) / 1000.0 );
409 
410  return tree;
411 }
412 
413 //==========================================================================
414 
415 /*
416 =================
417 MakeStructuralBspFaceList
418 =================
419 */
421  uBrush_t *b;
422  int i;
423  side_t *s;
424  idWinding *w;
425  bspface_t *f, *flist;
426 
427  flist = NULL;
428  for ( ; list ; list = list->next ) {
429  b = list->brush;
430  if ( !b ) {
431  continue;
432  }
433  if ( !b->opaque && !( b->contents & CONTENTS_AREAPORTAL ) ) {
434  continue;
435  }
436  for ( i = 0 ; i < b->numsides ; i++ ) {
437  s = &b->sides[i];
438  w = s->winding;
439  if ( !w ) {
440  continue;
441  }
442  if ( ( b->contents & CONTENTS_AREAPORTAL ) && ! ( s->material->GetContentFlags() & CONTENTS_AREAPORTAL ) ) {
443  continue;
444  }
445  f = AllocBspFace();
447  f->portal = true;
448  }
449  f->w = w->Copy();
450  f->planenum = s->planenum & ~1;
451  f->next = flist;
452  flist = f;
453  }
454  }
455 
456  return flist;
457 }
458 
459 /*
460 =================
461 MakeVisibleBspFaceList
462 =================
463 */
465  uBrush_t *b;
466  int i;
467  side_t *s;
468  idWinding *w;
469  bspface_t *f, *flist;
470 
471  flist = NULL;
472  for ( ; list ; list = list->next ) {
473  b = list->brush;
474  if ( !b ) {
475  continue;
476  }
477  if ( !b->opaque && !( b->contents & CONTENTS_AREAPORTAL ) ) {
478  continue;
479  }
480  for ( i = 0 ; i < b->numsides ; i++ ) {
481  s = &b->sides[i];
482  w = s->visibleHull;
483  if ( !w ) {
484  continue;
485  }
486  f = AllocBspFace();
488  f->portal = true;
489  }
490  f->w = w->Copy();
491  f->planenum = s->planenum & ~1;
492  f->next = flist;
493  flist = f;
494  }
495  }
496 
497  return flist;
498 }
499 
GLsizei const GLfloat * value
Definition: glext.h:3614
void PrintTree_r(node_t *node, int depth)
Definition: facebsp.cpp:127
node_t * headnode
Definition: dmap.h:173
#define SIDE_CROSS
Definition: Plane.h:50
int contents
Definition: dmap.h:122
tree_t * FaceBSP(bspface_t *list)
Definition: facebsp.cpp:375
tree_t * AllocTree(void)
Definition: ubrush.cpp:471
idWinding * winding
Definition: dmap.h:108
node_t * nodes[2]
Definition: dmap.h:166
#define SIDE_BACK
Definition: Plane.h:48
idBounds bounds
Definition: dmap.h:175
float Distance(const idVec3 &v) const
Definition: Plane.h:324
void BuildFaceTree_r(node_t *node, bspface_t *list)
Definition: facebsp.cpp:286
Definition: dmap.h:172
int Sys_Milliseconds(void)
int planenum
Definition: dmap.h:103
int FindFloatPlane(const idPlane &plane, bool *fixedDegeneracies=NULL)
Definition: map.cpp:75
Definition: Vector.h:316
struct uPortal_s * next[2]
Definition: dmap.h:167
struct bspface_s * next
Definition: dmap.h:90
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glext.h:2878
void RemovePortalFromNode(uPortal_t *portal, node_t *l)
Definition: portals.cpp:126
void Clear(void)
Definition: Bounds.h:201
GLdouble s
Definition: glext.h:2935
bspface_t * MakeVisibleBspFaceList(primitive_t *list)
Definition: facebsp.cpp:464
int i
Definition: process.py:33
int planenum
Definition: dmap.h:140
idPlaneSet mapPlanes
Definition: dmap.h:239
int planenum
Definition: dmap.h:91
int Type(void) const
Definition: Plane.cpp:39
list l
Definition: prepare.py:17
int PlaneSide(const idPlane &plane, const float epsilon=ON_EPSILON) const
Definition: Winding.cpp:1292
const idMaterial * material
Definition: dmap.h:105
bool AddPoint(const idVec3 &v)
Definition: Bounds.h:226
void FreeTree_r(node_t *node)
Definition: facebsp.cpp:93
Definition: dmap.h:89
GLuint GLuint GLsizei count
Definition: glext.h:2845
int GetNumPoints(void) const
Definition: Winding.h:238
struct node_s * children[2]
Definition: dmap.h:146
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:3454
#define BLOCK_SIZE
Definition: facebsp.cpp:186
int SelectSplitPlaneNum(node_t *node, bspface_t *list)
Definition: facebsp.cpp:187
GLuint GLuint end
Definition: glext.h:2845
static float Fabs(float f)
Definition: Math.h:779
idCommon * common
Definition: Common.cpp:206
idWinding * visibleHull
Definition: dmap.h:109
#define NULL
Definition: Lib.h:88
struct uPortal_s * portals
Definition: dmap.h:159
#define CLIP_EPSILON
Definition: dmap.h:281
const int GetContentFlags(void) const
Definition: Material.h:497
Definition: Plane.h:71
side_t sides[6]
Definition: dmap.h:128
void Mem_Free(void *ptr)
Definition: Heap.cpp:1087
bool portal
Definition: dmap.h:92
void FreeTreePortals_r(node_t *node)
Definition: facebsp.cpp:64
uBrush_t * brushlist
Definition: dmap.h:152
Definition: dmap.h:102
idBounds bounds
Definition: dmap.h:142
virtual void Printf(const char *fmt,...) id_attribute((format(printf
bool checked
Definition: dmap.h:94
void FreeBspFace(bspface_t *f)
Definition: facebsp.cpp:173
int c_nodes
Definition: ubrush.cpp:36
struct bspbrush_s * next
Definition: dmap.h:114
int numsides
Definition: dmap.h:127
GLubyte GLubyte b
Definition: glext.h:4662
idWinding * w
Definition: dmap.h:95
#define PLANENUM_LEAF
Definition: dmap.h:81
int Split(const idPlane &plane, const float epsilon, idWinding **front, idWinding **back) const
Definition: Winding.cpp:92
struct primitive_s * next
Definition: dmap.h:33
struct bspbrush_s * original
Definition: dmap.h:115
void FreeBrushList(uBrush_t *brushes)
Definition: ubrush.cpp:117
struct node_s * parent
Definition: dmap.h:141
tuple f
Definition: idal.py:89
node_t * NodeForPoint(node_t *node, idVec3 origin)
Definition: facebsp.cpp:41
node_t * AllocNode(void)
Definition: ubrush.cpp:487
void FreePortal(uPortal_t *p)
Definition: portals.cpp:62
void FreeTree(tree_t *tree)
Definition: facebsp.cpp:116
idWinding * Copy(void) const
Definition: Winding.cpp:464
bool opaque
Definition: dmap.h:123
#define PLANETYPE_TRUEAXIAL
Definition: Plane.h:65
int brushnum
Definition: dmap.h:118
Definition: dmap.h:138
void * Mem_Alloc(const int size)
Definition: Heap.cpp:1067
bspface_t * AllocBspFace(void)
Definition: facebsp.cpp:159
struct bspbrush_s * brush
Definition: dmap.h:36
dmapGlobals_t dmapGlobals
Definition: dmap.cpp:34
GLfloat GLfloat p
Definition: glext.h:4674
#define SIDE_FRONT
Definition: Plane.h:47
int c_faceLeafs
Definition: facebsp.cpp:34
GLuint start
Definition: glext.h:2845
float Dist(void) const
Definition: Plane.h:271
bspface_t * MakeStructuralBspFaceList(primitive_t *list)
Definition: facebsp.cpp:420