UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
tree.cpp
Go to the documentation of this file.
1 
5 /*
6 Copyright (C) 1997-2001 Id Software, Inc.
7 
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 
17 See the GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23 */
24 
25 #include "bsp.h"
26 
27 int c_nodes;
29 
35 {
36  return Mem_AllocType(node_t);
37 }
38 
39 static void FreeTreePortals_r (node_t* node)
40 {
41  portal_t* p, *nextp;
42 
43  /* free children */
44  if (node->planenum != PLANENUM_LEAF) {
45  FreeTreePortals_r(node->children[0]);
46  FreeTreePortals_r(node->children[1]);
47  }
48 
49  /* free portals */
50  for (p = node->portals; p; p = nextp) {
51  const int s = (p->nodes[1] == node);
52  nextp = p->next[s];
53 
54  RemovePortalFromNode(p, p->nodes[!s]);
55  FreePortal(p);
56  }
57  node->portals = nullptr;
58 }
59 
60 static void FreeTree_r (node_t* node)
61 {
62  face_t* f, *nextf;
63 
64  /* free children */
65  if (node->planenum != PLANENUM_LEAF) {
66  FreeTree_r(node->children[0]);
67  FreeTree_r(node->children[1]);
68  }
69 
70  /* free bspbrushes */
71  FreeBrushList(node->brushlist);
72 
73  /* free faces */
74  for (f = node->faces; f; f = nextf) {
75  nextf = f->next;
76  FreeFace(f);
77  }
78 
79  /* free the node */
80  if (node->volume)
81  FreeBrush(node->volume);
82 
83  if (threadstate.numthreads == 1)
84  c_nodes--;
85  Mem_Free(node);
86 }
87 
88 
93 {
94  tree_t* tree = Mem_AllocType(tree_t);
95 
96  tree->aabb.setNegativeVolume();
97 
98  return tree;
99 }
100 
101 
102 void FreeTree (tree_t* tree)
103 {
105  FreeTree_r(tree->headnode);
106  Mem_Free(tree);
107 }
108 
109 
110 static void CheckPlaneAgainstParents (uint16_t pnum, const node_t* node)
111 {
112  node_t* p;
113 
114  for (p = node->parent; p; p = p->parent) {
115  if (p->planenum == pnum)
116  Sys_Error("Tried parent");
117  }
118 }
119 
120 static void LeafNode (node_t* node, bspbrush_t* brushes)
121 {
122  node->side = nullptr;
123  node->planenum = PLANENUM_LEAF;
124 
125  Verb_Printf(VERB_DUMP, "LeafNode: scanning brushes.\n");
126 
127  node->contentFlags = BrushListCalcContents(brushes);
128  node->brushlist = brushes;
129 }
130 
131 static node_t* BuildTree_r (node_t* node, bspbrush_t* brushes)
132 {
133  node_t* newnode;
134  side_t* bestside;
135  int i;
136  bspbrush_t* children[2];
137 
138  if (threadstate.numthreads == 1)
139  c_nodes++;
140 
141  /* find the best plane to use as a splitter */
142  bestside = SelectSplitSide(brushes, node->volume);
143  if (!bestside) {
144  /* leaf node */
145  LeafNode(node, brushes);
146  Verb_Printf(VERB_DUMP, "BuildTree_r: Created a leaf node.\n");
147  return node;
148  }
149  /* make sure the selected plane hasn't been used before. */
150  CheckPlaneAgainstParents(bestside->planenum, node);
151 
152  Verb_Printf(VERB_DUMP, "BuildTree_r: splitting along plane %i\n", (int)bestside->planenum);
153 
154  /* this is a splitplane node */
155  node->side = bestside;
156  node->planenum = bestside->planenum & ~1; /* always use front facing */
157 
158  SplitBrushList(brushes, node->planenum, &children[0], &children[1]);
159  FreeBrushList(brushes);
160 
161  /* allocate children before recursing */
162  for (i = 0; i < 2; i++) {
163  newnode = AllocNode();
164  newnode->parent = node;
165  node->children[i] = newnode;
166  }
167 
168  SplitBrush(node->volume, node->planenum, &node->children[0]->volume,
169  &node->children[1]->volume);
170 
171  /* recursively process children */
172  for (i = 0; i < 2; i++) {
173  node->children[i] = BuildTree_r(node->children[i], children[i]);
174  }
175 
176  return node;
177 }
178 
182 tree_t* BuildTree (bspbrush_t* brushlist, const vec3_t mins, const vec3_t maxs)
183 {
184  node_t* node;
185  tree_t* tree;
186  AABB blBox;
187 
188  Verb_Printf(VERB_EXTRA, "--- BrushBSP ---\n");
189 
190  tree = AllocTree();
191 
192  blBox.setNegativeVolume();
193  BrushlistCalcStats(brushlist, blBox);
194  tree->aabb.add(blBox);
195 
196  c_nodes = 0;
197  c_nonvis = 0;
198  node = AllocNode();
199 
200  node->volume = BrushFromBounds(mins, maxs);
201 
202  tree->headnode = node;
203 
204  node = BuildTree_r(node, brushlist);
205 
206  Verb_Printf(VERB_EXTRA, "%5i visible nodes\n", c_nodes / 2 - c_nonvis);
207  Verb_Printf(VERB_EXTRA, "%5i nonvis nodes\n", c_nonvis);
208  Verb_Printf(VERB_EXTRA, "%5i leafs\n", (c_nodes + 1) / 2);
209  return tree;
210 }
211 
212 /*=========================================================
213 NODES THAT DON'T SEPERATE DIFFERENT CONTENTS CAN BE PRUNED
214 =========================================================*/
215 
216 static int c_pruned;
217 
222 static void PruneNodes_r (node_t* node)
223 {
224  bspbrush_t* b, *next;
225 
226  if (node->planenum == PLANENUM_LEAF)
227  return;
228  PruneNodes_r(node->children[0]);
229  PruneNodes_r(node->children[1]);
230 
231  if ((node->children[0]->contentFlags & CONTENTS_SOLID)
232  && (node->children[1]->contentFlags & CONTENTS_SOLID)) {
233  if (node->faces)
234  Sys_Error("node->faces seperating CONTENTS_SOLID");
235  if (node->children[0]->faces || node->children[1]->faces)
236  Sys_Error("!node->faces with children");
237 
239  node->planenum = PLANENUM_LEAF;
241 
242  if (node->brushlist)
243  Sys_Error("PruneNodes: node->brushlist");
244 
245  /* combine brush lists */
246  node->brushlist = node->children[1]->brushlist;
247 
248  for (b = node->children[0]->brushlist; b; b = next) {
249  next = b->next;
250  b->next = node->brushlist;
251  node->brushlist = b;
252  }
253 
254  c_pruned++;
255  }
256 }
257 
261 void PruneNodes (node_t* node)
262 {
263  Verb_Printf(VERB_EXTRA, "--- PruneNodes ---\n");
264  c_pruned = 0;
265  PruneNodes_r(node);
266  Verb_Printf(VERB_EXTRA, "%5i pruned nodes\n", c_pruned);
267 }
int32_t contentFlags
Definition: bsp.h:56
void setNegativeVolume()
Sets mins and maxs to their starting points before using addPoint.
Definition: aabb.h:98
void Sys_Error(const char *error,...)
Definition: g_main.cpp:421
tree_t * BuildTree(bspbrush_t *brushlist, const vec3_t mins, const vec3_t maxs)
The incoming list will be freed before exiting.
Definition: tree.cpp:182
void SplitBrushList(bspbrush_t *brushes, uint16_t planenum, bspbrush_t **front, bspbrush_t **back)
Definition: bspbrush.cpp:700
Definition: map.h:42
struct face_s * next
Definition: map.h:43
#define CONTENTS_SOLID
Definition: defines.h:223
bspbrush_t * BrushFromBounds(const vec3_t mins, const vec3_t maxs)
Creates a new axial brush.
Definition: bspbrush.cpp:87
static void LeafNode(node_t *node, bspbrush_t *brushes)
Definition: tree.cpp:120
Definition: aabb.h:42
Definition: bsp.h:61
static node_t * BuildTree_r(node_t *node, bspbrush_t *brushes)
Definition: tree.cpp:131
struct portal_s * next[2]
Definition: map.h:114
void FreePortal(portal_t *p)
Definition: portals.cpp:52
void FreeBrushList(bspbrush_t *brushes)
Definition: bspbrush.cpp:193
static void FreeTreePortals_r(node_t *node)
Definition: tree.cpp:39
static int c_pruned
Definition: tree.cpp:216
int32_t planenum
Definition: bsp.h:44
void BrushlistCalcStats(bspbrush_t *brushlist, AABB &blBox)
Counts the faces and calculate the aabb.
Definition: bspbrush.cpp:759
uint32_t BrushListCalcContents(bspbrush_t *brushlist)
Collects the contentsflags of the brushes in the given list.
Definition: bspbrush.cpp:300
side_t * side
Definition: bsp.h:50
side_t * SelectSplitSide(bspbrush_t *brushes, bspbrush_t *volume)
Using a heuristic, choses one of the sides out of the brushlist to partition the brushes with...
Definition: bspbrush.cpp:416
void FreeFace(face_t *f)
Definition: faces.cpp:133
void add(const vec3_t point)
If the point is outside the box, expand the box to accommodate it.
Definition: aabb.cpp:57
static void CheckPlaneAgainstParents(uint16_t pnum, const node_t *node)
Definition: tree.cpp:110
int c_nonvis
Definition: tree.cpp:28
struct node_s * children[2]
Definition: bsp.h:51
bspbrush_t * volume
Definition: bsp.h:47
void FreeBrush(bspbrush_t *brushes)
Definition: bspbrush.cpp:179
struct node_s * nodes[2]
Definition: map.h:113
uint16_t planenum
Definition: map.h:61
threadstate_t threadstate
Definition: threads.cpp:32
void Verb_Printf(const verbosityLevel_t importance, const char *format,...) __attribute__((format(__printf__
tree_t * AllocTree(void)
Allocates a tree and initializes it.
Definition: tree.cpp:92
Definition: map.h:60
struct portal_s * portals
Definition: bsp.h:58
struct bspbrush_s * next
Definition: bspbrush.h:36
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
void SplitBrush(const bspbrush_t *brush, uint16_t planenum, bspbrush_t **front, bspbrush_t **back)
Generates two new brushes, leaving the original unchanged.
Definition: bspbrush.cpp:544
struct node_s * headnode
Definition: bsp.h:62
#define PLANENUM_LEAF
Definition: defines.h:45
QGL_EXTERN GLint i
Definition: r_gl.h:113
struct node_s * parent
Definition: bsp.h:45
int c_nodes
Definition: tree.cpp:27
bspbrush_t * brushlist
Definition: bsp.h:55
void RemovePortalFromNode(portal_t *portal, node_t *l)
Removes references to the given portal from the given node.
Definition: portals.cpp:102
void PruneNodes(node_t *node)
Definition: tree.cpp:261
AABB aabb
Definition: bsp.h:64
#define Mem_Free(ptr)
Definition: mem.h:35
static void FreeTree_r(node_t *node)
Definition: tree.cpp:60
vec_t vec3_t[3]
Definition: ufotypes.h:39
void FreeTree(tree_t *tree)
Definition: tree.cpp:102
#define Mem_AllocType(type)
Definition: mem.h:39
Definition: map.h:110
face_t * faces
Definition: bsp.h:52
Definition: bsp.h:42
node_t * AllocNode(void)
Definition: tree.cpp:34
static void PruneNodes_r(node_t *node)
Will cut solid nodes by recursing down the bsp tree.
Definition: tree.cpp:222