AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
BIH Class Reference

#include "BoundingIntervalHierarchy.h"

Classes

struct  buildData
 
class  BuildStats
 
struct  StackNode
 

Public Member Functions

 BIH ()
 
template<class BoundsFunc , class PrimArray >
void build (const PrimArray &primitives, BoundsFunc &GetBounds, uint32 leafSize=3, bool printStats=false)
 
uint32 primCount () const
 
G3D::AABox const & bound () const
 
template<typename RayCallback >
void intersectRay (const G3D::Ray &r, RayCallback &intersectCallback, float &maxDist, bool stopAtFirstHit) const
 
template<typename IsectCallback >
void intersectPoint (const G3D::Vector3 &p, IsectCallback &intersectCallback) const
 
bool writeToFile (FILE *wf) const
 
bool readFromFile (FILE *rf)
 

Protected Member Functions

void buildHierarchy (std::vector< uint32 > &tempTree, buildData &dat, BuildStats &stats)
 
void createNode (std::vector< uint32 > &tempTree, int nodeIndex, uint32 left, uint32 right) const
 
void subdivide (int left, int right, std::vector< uint32 > &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats)
 

Protected Attributes

std::vector< uint32tree
 
std::vector< uint32objects
 
G3D::AABox bounds
 

Private Member Functions

void init_empty ()
 

Detailed Description

Bounding Interval Hierarchy Class. Building and Ray-Intersection functions based on BIH from Sunflow, a Java Raytracer, released under MIT/X11 License http://sunflow.sourceforge.net/ Copyright (c) 2003-2007 Christopher Kulla

Constructor & Destructor Documentation

◆ BIH()

BIH::BIH ( )
inline
79{ init_empty(); }
void init_empty()
Definition BoundingIntervalHierarchy.h:69

References init_empty().

Member Function Documentation

◆ bound()

G3D::AABox const & BIH::bound ( ) const
inline
120{ return bounds; }
G3D::AABox bounds
Definition BoundingIntervalHierarchy.h:383

References bounds.

Referenced by VMAP::WorldModel::GetLocationInfo(), VMAP::GroupModel::GetMeshTreeBound(), and VMAP::GroupModel::IsInsideObject().

◆ build()

template<class BoundsFunc , class PrimArray >
void BIH::build ( const PrimArray &  primitives,
BoundsFunc &  GetBounds,
uint32  leafSize = 3,
bool  printStats = false 
)
inline
82 {
83 if (primitives.size() == 0)
84 {
85 init_empty();
86 return;
87 }
88
89 buildData dat;
90 dat.maxPrims = leafSize;
91 dat.numPrims = primitives.size();
92 dat.indices = new uint32[dat.numPrims];
93 dat.primBound = new G3D::AABox[dat.numPrims];
94 GetBounds(primitives[0], bounds);
95 for (uint32 i = 0; i < dat.numPrims; ++i)
96 {
97 dat.indices[i] = i;
98 GetBounds(primitives[i], dat.primBound[i]);
99 bounds.merge(dat.primBound[i]);
100 }
101 std::vector<uint32> tempTree;
102 BuildStats stats;
103 buildHierarchy(tempTree, dat, stats);
104 if (printStats)
105 {
106 stats.printStats();
107 }
108
109 objects.resize(dat.numPrims);
110 for (uint32 i = 0; i < dat.numPrims; ++i)
111 {
112 objects[i] = dat.indices[i];
113 }
114 //nObjects = dat.numPrims;
115 tree = tempTree;
116 delete[] dat.primBound;
117 delete[] dat.indices;
118 }
std::uint32_t uint32
Definition Define.h:107
std::vector< uint32 > objects
Definition BoundingIntervalHierarchy.h:382
void buildHierarchy(std::vector< uint32 > &tempTree, buildData &dat, BuildStats &stats)
Definition BoundingIntervalHierarchy.cpp:26
std::vector< uint32 > tree
Definition BoundingIntervalHierarchy.h:381

References bounds, buildHierarchy(), BIH::buildData::indices, init_empty(), BIH::buildData::maxPrims, BIH::buildData::numPrims, objects, BIH::buildData::primBound, BIH::BuildStats::printStats(), and tree.

Referenced by BIHWrap< T, BoundsFunc >::balance(), VMAP::TileAssembler::convertWorld2(), VMAP::WorldModel::setGroupModels(), and VMAP::GroupModel::setMeshData().

◆ buildHierarchy()

void BIH::buildHierarchy ( std::vector< uint32 > &  tempTree,
buildData dat,
BuildStats stats 
)
protected
27{
28 // create space for the first node
29 // cppcheck-suppress integerOverflow
30 tempTree.push_back(uint32(3 << 30)); // dummy leaf
31 tempTree.insert(tempTree.end(), 2, 0);
32 //tempTree.add(0);
33
34 // seed bbox
35 AABound gridBox = { bounds.low(), bounds.high() };
36 AABound nodeBox = gridBox;
37 // seed subdivide function
38 subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats);
39}
void subdivide(int left, int right, std::vector< uint32 > &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats)
Definition BoundingIntervalHierarchy.cpp:41
Definition BoundingIntervalHierarchy.h:55

References bounds, BIH::buildData::numPrims, and subdivide().

Referenced by build().

◆ createNode()

void BIH::createNode ( std::vector< uint32 > &  tempTree,
int  nodeIndex,
uint32  left,
uint32  right 
) const
inlineprotected
428 {
429 // write leaf node
430 tempTree[nodeIndex + 0] = (3 << 30) | left; // cppcheck-suppress integerOverflow
431 tempTree[nodeIndex + 1] = right - left + 1;
432 }

Referenced by subdivide().

◆ init_empty()

void BIH::init_empty ( )
inlineprivate
70 {
71 tree.clear();
72 objects.clear();
73 bounds = G3D::AABox::empty();
74 // create space for the first node
75 tree.push_back(3u << 30u); // dummy leaf
76 tree.insert(tree.end(), 2, 0);
77 }

References bounds, objects, and tree.

Referenced by BIH(), and build().

◆ intersectPoint()

template<typename IsectCallback >
void BIH::intersectPoint ( const G3D::Vector3 &  p,
IsectCallback &  intersectCallback 
) const
inline
287 {
288 if (!bounds.contains(p))
289 {
290 return;
291 }
292
293 StackNode stack[MAX_STACK_SIZE];
294 int stackPos = 0;
295 int node = 0;
296
297 while (true)
298 {
299 while (true)
300 {
301 uint32 tn = tree[node];
302 uint32 axis = (tn & (3 << 30)) >> 30; // cppcheck-suppress integerOverflow
303 bool BVH2 = tn & (1 << 29); // cppcheck-suppress integerOverflow
304 int offset = tn & ~(7 << 29); // cppcheck-suppress integerOverflow
305 if (!BVH2)
306 {
307 if (axis < 3)
308 {
309 // "normal" interior node
310 float tl = intBitsToFloat(tree[node + 1]);
311 float tr = intBitsToFloat(tree[node + 2]);
312 // point is between clip zones
313 if (tl < p[axis] && tr > p[axis])
314 {
315 break;
316 }
317 int right = offset + 3;
318 node = right;
319 // point is in right node only
320 if (tl < p[axis])
321 {
322 continue;
323 }
324 node = offset; // left
325 // point is in left node only
326 if (tr > p[axis])
327 {
328 continue;
329 }
330 // point is in both nodes
331 // push back right node
332 stack[stackPos].node = right;
333 stackPos++;
334 continue;
335 }
336 else
337 {
338 // leaf - test some objects
339 int n = tree[node + 1];
340 while (n > 0)
341 {
342 intersectCallback(p, objects[offset]); // !!!
343 --n;
344 ++offset;
345 }
346 break;
347 }
348 }
349 else // BVH2 node (empty space cut off left and right)
350 {
351 if (axis > 2)
352 {
353 return; // should not happen
354 }
355 float tl = intBitsToFloat(tree[node + 1]);
356 float tr = intBitsToFloat(tree[node + 2]);
357 node = offset;
358 if (tl > p[axis] || tr < p[axis])
359 {
360 break;
361 }
362 continue;
363 }
364 } // traversal loop
365
366 // stack is empty?
367 if (stackPos == 0)
368 {
369 return;
370 }
371 // move back up the stack
372 stackPos--;
373 node = stack[stackPos].node;
374 }
375 }
static float intBitsToFloat(uint32 i)
Definition BoundingIntervalHierarchy.h:46
#define MAX_STACK_SIZE
Definition BoundingIntervalHierarchy.h:34

References bounds, intBitsToFloat(), MAX_STACK_SIZE, BIH::StackNode::node, objects, and tree.

Referenced by VMAP::StaticMapTree::GetLocationInfo(), and BIHWrap< T, BoundsFunc >::intersectPoint().

◆ intersectRay()

template<typename RayCallback >
void BIH::intersectRay ( const G3D::Ray &  r,
RayCallback &  intersectCallback,
float &  maxDist,
bool  stopAtFirstHit 
) const
inline
124 {
125 float intervalMin = -1.f;
126 float intervalMax = -1.f;
127 G3D::Vector3 org = r.origin();
128 G3D::Vector3 dir = r.direction();
129 G3D::Vector3 invDir;
130 for (int i = 0; i < 3; ++i)
131 {
132 invDir[i] = 1.f / dir[i];
133 if (G3D::fuzzyNe(dir[i], 0.0f))
134 {
135 float t1 = (bounds.low()[i] - org[i]) * invDir[i];
136 float t2 = (bounds.high()[i] - org[i]) * invDir[i];
137 if (t1 > t2)
138 {
139 std::swap(t1, t2);
140 }
141 if (t1 > intervalMin)
142 {
143 intervalMin = t1;
144 }
145 if (t2 < intervalMax || intervalMax < 0.f)
146 {
147 intervalMax = t2;
148 }
149 // intervalMax can only become smaller for other axis,
150 // and intervalMin only larger respectively, so stop early
151 if (intervalMax <= 0 || intervalMin >= maxDist)
152 {
153 return;
154 }
155 }
156 }
157
158 if (intervalMin > intervalMax)
159 {
160 return;
161 }
162 intervalMin = std::max(intervalMin, 0.f);
163 intervalMax = std::min(intervalMax, maxDist);
164
165 uint32 offsetFront[3];
166 uint32 offsetBack[3];
167 uint32 offsetFront3[3];
168 uint32 offsetBack3[3];
169 // compute custom offsets from direction sign bit
170
171 for (int i = 0; i < 3; ++i)
172 {
173 offsetFront[i] = floatToRawIntBits(dir[i]) >> 31;
174 offsetBack[i] = offsetFront[i] ^ 1;
175 offsetFront3[i] = offsetFront[i] * 3;
176 offsetBack3[i] = offsetBack[i] * 3;
177
178 // avoid always adding 1 during the inner loop
179 ++offsetFront[i];
180 ++offsetBack[i];
181 }
182
183 StackNode stack[MAX_STACK_SIZE];
184 int stackPos = 0;
185 int node = 0;
186
187 while (true)
188 {
189 while (true)
190 {
191 uint32 tn = tree[node];
192 uint32 axis = (tn & (3 << 30)) >> 30; // cppcheck-suppress integerOverflow
193 bool BVH2 = tn & (1 << 29); // cppcheck-suppress integerOverflow
194 int offset = tn & ~(7 << 29); // cppcheck-suppress integerOverflow
195 if (!BVH2)
196 {
197 if (axis < 3)
198 {
199 // "normal" interior node
200 float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
201 float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
202 // ray passes between clip zones
203 if (tf < intervalMin && tb > intervalMax)
204 {
205 break;
206 }
207 int back = offset + offsetBack3[axis];
208 node = back;
209 // ray passes through far node only
210 if (tf < intervalMin)
211 {
212 intervalMin = (tb >= intervalMin) ? tb : intervalMin;
213 continue;
214 }
215 node = offset + offsetFront3[axis]; // front
216 // ray passes through near node only
217 if (tb > intervalMax)
218 {
219 intervalMax = (tf <= intervalMax) ? tf : intervalMax;
220 continue;
221 }
222 // ray passes through both nodes
223 // push back node
224 stack[stackPos].node = back;
225 stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin;
226 stack[stackPos].tfar = intervalMax;
227 stackPos++;
228 // update ray interval for front node
229 intervalMax = (tf <= intervalMax) ? tf : intervalMax;
230 continue;
231 }
232 else
233 {
234 // leaf - test some objects
235 int n = tree[node + 1];
236 while (n > 0)
237 {
238 bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirstHit);
239 if (stopAtFirstHit && hit) { return; }
240 --n;
241 ++offset;
242 }
243 break;
244 }
245 }
246 else
247 {
248 if (axis > 2)
249 {
250 return; // should not happen
251 }
252 float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
253 float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
254 node = offset;
255 intervalMin = (tf >= intervalMin) ? tf : intervalMin;
256 intervalMax = (tb <= intervalMax) ? tb : intervalMax;
257 if (intervalMin > intervalMax)
258 {
259 break;
260 }
261 continue;
262 }
263 } // traversal loop
264 do
265 {
266 // stack is empty?
267 if (stackPos == 0)
268 {
269 return;
270 }
271 // move back up the stack
272 stackPos--;
273 intervalMin = stack[stackPos].tnear;
274 if (maxDist < intervalMin)
275 {
276 continue;
277 }
278 node = stack[stackPos].node;
279 intervalMax = stack[stackPos].tfar;
280 break;
281 } while (true);
282 }
283 }
static uint32 floatToRawIntBits(float f)
Definition BoundingIntervalHierarchy.h:38

References bounds, floatToRawIntBits(), intBitsToFloat(), MAX_STACK_SIZE, BIH::StackNode::node, objects, BIH::StackNode::tfar, BIH::StackNode::tnear, and tree.

Referenced by VMAP::StaticMapTree::GetIntersectionTime(), VMAP::WorldModel::GetLocationInfo(), VMAP::GroupModel::IntersectRay(), VMAP::WorldModel::IntersectRay(), and BIHWrap< T, BoundsFunc >::intersectRay().

◆ primCount()

uint32 BIH::primCount ( ) const
inline
119{ return objects.size(); }

References objects.

Referenced by VMAP::StaticMapTree::InitMap().

◆ readFromFile()

bool BIH::readFromFile ( FILE *  rf)
288{
289 uint32 treeSize;
290 G3D::Vector3 lo, hi;
291 uint32 check = 0, count = 0;
292 check += fread(&lo, sizeof(float), 3, rf);
293 check += fread(&hi, sizeof(float), 3, rf);
294 bounds = G3D::AABox(lo, hi);
295 check += fread(&treeSize, sizeof(uint32), 1, rf);
296 tree.resize(treeSize);
297 check += fread(&tree[0], sizeof(uint32), treeSize, rf);
298 check += fread(&count, sizeof(uint32), 1, rf);
299 objects.resize(count); // = new uint32[nObjects];
300 check += fread(&objects[0], sizeof(uint32), count, rf);
301 return uint64(check) == uint64(3 + 3 + 1 + 1 + uint64(treeSize) + uint64(count));
302}
std::uint64_t uint64
Definition Define.h:106

References bounds, objects, and tree.

Referenced by VMAP::StaticMapTree::InitMap(), VMAP::WorldModel::readFile(), and VMAP::GroupModel::readFromFile().

◆ subdivide()

void BIH::subdivide ( int  left,
int  right,
std::vector< uint32 > &  tempTree,
buildData dat,
AABound gridBox,
AABound nodeBox,
int  nodeIndex,
int  depth,
BuildStats stats 
)
protected
42{
43 if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE)
44 {
45 // write leaf node
46 stats.updateLeaf(depth, right - left + 1);
47 createNode(tempTree, nodeIndex, left, right);
48 return;
49 }
50 // calculate extents
51 int axis = -1, prevAxis, rightOrig;
52 float clipL = G3D::fnan(), clipR = G3D::fnan(), prevClip = G3D::fnan();
53 float split = G3D::fnan(), prevSplit;
54 bool wasLeft = true;
55 while (true)
56 {
57 prevAxis = axis;
58 prevSplit = split;
59 // perform quick consistency checks
60 G3D::Vector3 d( gridBox.hi - gridBox.lo );
61 if (d.x < 0 || d.y < 0 || d.z < 0)
62 {
63 throw std::logic_error("negative node extents");
64 }
65 for (int i = 0; i < 3; i++)
66 {
67 if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i])
68 {
69 //UI.printError(Module.ACCEL, "Reached tree area in error - discarding node with: %d objects", right - left + 1);
70 throw std::logic_error("invalid node overlap");
71 }
72 }
73 // find longest axis
74 axis = d.primaryAxis();
75 split = 0.5f * (gridBox.lo[axis] + gridBox.hi[axis]);
76 // partition L/R subsets
77 clipL = -G3D::inf();
78 clipR = G3D::inf();
79 rightOrig = right; // save this for later
80 float nodeL = G3D::inf();
81 float nodeR = -G3D::inf();
82 for (int i = left; i <= right;)
83 {
84 int obj = dat.indices[i];
85 float minb = dat.primBound[obj].low()[axis];
86 float maxb = dat.primBound[obj].high()[axis];
87 float center = (minb + maxb) * 0.5f;
88 if (center <= split)
89 {
90 // stay left
91 i++;
92 if (clipL < maxb)
93 {
94 clipL = maxb;
95 }
96 }
97 else
98 {
99 // move to the right most
100 int t = dat.indices[i];
101 dat.indices[i] = dat.indices[right];
102 dat.indices[right] = t;
103 right--;
104 if (clipR > minb)
105 {
106 clipR = minb;
107 }
108 }
109 nodeL = std::min(nodeL, minb);
110 nodeR = std::max(nodeR, maxb);
111 }
112 // check for empty space
113 if (nodeL > nodeBox.lo[axis] && nodeR < nodeBox.hi[axis])
114 {
115 float nodeBoxW = nodeBox.hi[axis] - nodeBox.lo[axis];
116 float nodeNewW = nodeR - nodeL;
117 // node box is too big compare to space occupied by primitives?
118 if (1.3f * nodeNewW < nodeBoxW)
119 {
120 stats.updateBVH2();
121 int nextIndex = tempTree.size();
122 // allocate child
123 tempTree.push_back(0);
124 tempTree.push_back(0);
125 tempTree.push_back(0);
126 // write bvh2 clip node
127 stats.updateInner();
128 tempTree[nodeIndex + 0] = (axis << 30) | (1 << 29) | nextIndex;
129 tempTree[nodeIndex + 1] = floatToRawIntBits(nodeL);
130 tempTree[nodeIndex + 2] = floatToRawIntBits(nodeR);
131 // update nodebox and recurse
132 nodeBox.lo[axis] = nodeL;
133 nodeBox.hi[axis] = nodeR;
134 subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex, depth + 1, stats);
135 return;
136 }
137 }
138 // ensure we are making progress in the subdivision
139 if (right == rightOrig)
140 {
141 // all left
142 if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split))
143 {
144 // we are stuck here - create a leaf
145 stats.updateLeaf(depth, right - left + 1);
146 createNode(tempTree, nodeIndex, left, right);
147 return;
148 }
149 if (clipL <= split)
150 {
151 // keep looping on left half
152 gridBox.hi[axis] = split;
153 prevClip = clipL;
154 wasLeft = true;
155 continue;
156 }
157 gridBox.hi[axis] = split;
158 prevClip = G3D::fnan();
159 }
160 else if (left > right)
161 {
162 // all right
163 right = rightOrig;
164 if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split))
165 {
166 // we are stuck here - create a leaf
167 stats.updateLeaf(depth, right - left + 1);
168 createNode(tempTree, nodeIndex, left, right);
169 return;
170 }
171 if (clipR >= split)
172 {
173 // keep looping on right half
174 gridBox.lo[axis] = split;
175 prevClip = clipR;
176 wasLeft = false;
177 continue;
178 }
179 gridBox.lo[axis] = split;
180 prevClip = G3D::fnan();
181 }
182 else
183 {
184 // we are actually splitting stuff
185 if (prevAxis != -1 && !isnan(prevClip))
186 {
187 // second time through - lets create the previous split
188 // since it produced empty space
189 int nextIndex = tempTree.size();
190 // allocate child node
191 tempTree.push_back(0);
192 tempTree.push_back(0);
193 tempTree.push_back(0);
194 if (wasLeft)
195 {
196 // create a node with a left child
197 // write leaf node
198 stats.updateInner();
199 tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex;
200 tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip);
201 tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::inf());
202 }
203 else
204 {
205 // create a node with a right child
206 // write leaf node
207 stats.updateInner();
208 tempTree[nodeIndex + 0] = (prevAxis << 30) | (nextIndex - 3);
209 tempTree[nodeIndex + 1] = floatToRawIntBits(-G3D::inf());
210 tempTree[nodeIndex + 2] = floatToRawIntBits(prevClip);
211 }
212 // count stats for the unused leaf
213 depth++;
214 stats.updateLeaf(depth, 0);
215 // now we keep going as we are, with a new nodeIndex:
216 nodeIndex = nextIndex;
217 }
218 break;
219 }
220 }
221 // compute index of child nodes
222 int nextIndex = tempTree.size();
223 // allocate left node
224 int nl = right - left + 1;
225 int nr = rightOrig - (right + 1) + 1;
226 if (nl > 0)
227 {
228 tempTree.push_back(0);
229 tempTree.push_back(0);
230 tempTree.push_back(0);
231 }
232 else
233 {
234 nextIndex -= 3;
235 }
236 // allocate right node
237 if (nr > 0)
238 {
239 tempTree.push_back(0);
240 tempTree.push_back(0);
241 tempTree.push_back(0);
242 }
243 // write leaf node
244 stats.updateInner();
245 tempTree[nodeIndex + 0] = (axis << 30) | nextIndex;
246 tempTree[nodeIndex + 1] = floatToRawIntBits(clipL);
247 tempTree[nodeIndex + 2] = floatToRawIntBits(clipR);
248 // prepare L/R child boxes
249 AABound gridBoxL(gridBox), gridBoxR(gridBox);
250 AABound nodeBoxL(nodeBox), nodeBoxR(nodeBox);
251 gridBoxL.hi[axis] = gridBoxR.lo[axis] = split;
252 nodeBoxL.hi[axis] = clipL;
253 nodeBoxR.lo[axis] = clipR;
254 // recurse
255 if (nl > 0)
256 {
257 subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats);
258 }
259 else
260 {
261 stats.updateLeaf(depth + 1, 0);
262 }
263 if (nr > 0)
264 {
265 subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats);
266 }
267 else
268 {
269 stats.updateLeaf(depth + 1, 0);
270 }
271}
#define isnan
Definition BoundingIntervalHierarchy.cpp:23
void createNode(std::vector< uint32 > &tempTree, int nodeIndex, uint32 left, uint32 right) const
Definition BoundingIntervalHierarchy.h:427
G3D::Vector3 hi
Definition BoundingIntervalHierarchy.h:56
G3D::Vector3 lo
Definition BoundingIntervalHierarchy.h:56

References createNode(), floatToRawIntBits(), AABound::hi, BIH::buildData::indices, isnan, AABound::lo, MAX_STACK_SIZE, BIH::buildData::maxPrims, BIH::buildData::primBound, subdivide(), BIH::BuildStats::updateBVH2(), BIH::BuildStats::updateInner(), and BIH::BuildStats::updateLeaf().

Referenced by buildHierarchy(), and subdivide().

◆ writeToFile()

bool BIH::writeToFile ( FILE *  wf) const
274{
275 uint32 treeSize = tree.size();
276 uint32 check = 0, count;
277 check += fwrite(&bounds.low(), sizeof(float), 3, wf);
278 check += fwrite(&bounds.high(), sizeof(float), 3, wf);
279 check += fwrite(&treeSize, sizeof(uint32), 1, wf);
280 check += fwrite(&tree[0], sizeof(uint32), treeSize, wf);
281 count = objects.size();
282 check += fwrite(&count, sizeof(uint32), 1, wf);
283 check += fwrite(&objects[0], sizeof(uint32), count, wf);
284 return check == (3 + 3 + 2 + treeSize + count);
285}

References bounds, objects, and tree.

Referenced by VMAP::TileAssembler::convertWorld2(), VMAP::WorldModel::writeFile(), and VMAP::GroupModel::writeToFile().

Member Data Documentation

◆ bounds

G3D::AABox BIH::bounds
protected

◆ objects

std::vector<uint32> BIH::objects
protected

◆ tree

std::vector<uint32> BIH::tree
protected

The documentation for this class was generated from the following files: