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
 
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
78{ init_empty(); }
void init_empty()
Definition: BoundingIntervalHierarchy.h:69

References init_empty().

Member Function Documentation

◆ build()

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

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
426 {
427 // write leaf node
428 tempTree[nodeIndex + 0] = (3 << 30) | left; // cppcheck-suppress integerOverflow
429 tempTree[nodeIndex + 1] = right - left + 1;
430 }

Referenced by subdivide().

◆ init_empty()

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

References objects, and tree.

Referenced by BIH(), and build().

◆ intersectPoint()

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

◆ intersectRay()

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

◆ primCount()

uint32 BIH::primCount ( ) const
inline
118{ 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
G3D::Vector3 hi
Definition: BoundingIntervalHierarchy.h:56
G3D::Vector3 lo
Definition: BoundingIntervalHierarchy.h:56
void createNode(std::vector< uint32 > &tempTree, int nodeIndex, uint32 left, uint32 right) const
Definition: BoundingIntervalHierarchy.h:425

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