18#ifndef TRINITYCORE_BOUNDING_INTERVAL_HIERARCHY_H
19#define TRINITYCORE_BOUNDING_INTERVAL_HIERARCHY_H
25#include <G3D/Vector3.h>
31#define MAX_STACK_SIZE 64
52 bounds = G3D::AABox::empty();
54 tree = { 3u << 30u, 0u, 0u };
57 BIH() { init_empty(); }
58 template <
class BoundsFunc,
class PrimArray>
59 void build(PrimArray
const& primitives, BoundsFunc
const& getBounds,
uint32 leafSize = 3,
bool printStats =
false)
61 if (primitives.size() == 0)
71 dat.
primBound =
static_cast<G3D::AABox*
>(::operator
new[](dat.
numPrims *
sizeof(G3D::AABox)));
73 getBounds(primitives[0], bounds);
77 getBounds(primitives[i], dat.
primBound[i]);
80 std::vector<uint32> tempTree;
82 buildHierarchy(tempTree, dat, stats);
93 G3D::AABox
const&
bound()
const {
return bounds; }
95 template<
typename RayCallback>
96 void intersectRay(G3D::Ray
const& r, RayCallback& intersectCallback,
float& maxDist,
bool stopAtFirst =
false)
const
98 float intervalMin = -1.f;
99 float intervalMax = -1.f;
100 G3D::Vector3
const& org = r.origin();
101 G3D::Vector3
const& dir = r.direction();
102 G3D::Vector3
const& invDir = r.invDirection();
103 for (
int i = 0; i < 3; ++i)
105 if (G3D::fuzzyNe(dir[i], 0.0f))
107 float t1 = (bounds.low()[i] - org[i]) * invDir[i];
108 float t2 = (bounds.high()[i] - org[i]) * invDir[i];
111 if (t1 > intervalMin)
113 if (t2 < intervalMax || intervalMax < 0.f)
117 if (intervalMax <= 0 || intervalMin >= maxDist)
122 if (intervalMin > intervalMax)
124 intervalMin = std::max(intervalMin, 0.f);
125 intervalMax = std::min(intervalMax, maxDist);
133 for (
int i = 0; i < 3; ++i)
135 offsetFront[i] = advstd::bit_cast<uint32>(dir[i]) >> 31;
136 offsetBack[i] = offsetFront[i] ^ 1;
137 offsetFront3[i] = offsetFront[i] * 3;
138 offsetBack3[i] = offsetBack[i] * 3;
154 uint32 axis = (tn & (3 << 30)) >> 30;
155 bool BVH2 = (tn & (1 << 29)) != 0;
156 int offset = tn & ~(7 << 29);
162 float tf = (advstd::bit_cast<float>(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
163 float tb = (advstd::bit_cast<float>(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
165 if (tf < intervalMin && tb > intervalMax)
167 int back = offset + offsetBack3[axis];
170 if (tf < intervalMin)
172 intervalMin = (tb >= intervalMin) ? tb : intervalMin;
175 node = offset + offsetFront3[axis];
177 if (tb > intervalMax)
179 intervalMax = (tf <= intervalMax) ? tf : intervalMax;
184 stack[stackPos].
node = back;
185 stack[stackPos].
tnear = (tb >= intervalMin) ? tb : intervalMin;
186 stack[stackPos].
tfar = intervalMax;
189 intervalMax = (tf <= intervalMax) ? tf : intervalMax;
195 int n = tree[node + 1];
198 bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirst);
199 if (stopAtFirst && hit)
return;
210 float tf = (advstd::bit_cast<float>(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
211 float tb = (advstd::bit_cast<float>(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
213 intervalMin = (tf >= intervalMin) ? tf : intervalMin;
214 intervalMax = (tb <= intervalMax) ? tb : intervalMax;
215 if (intervalMin > intervalMax)
227 intervalMin = stack[stackPos].
tnear;
228 if (maxDist < intervalMin)
230 node = stack[stackPos].
node;
231 intervalMax = stack[stackPos].
tfar;
237 template<
typename IsectCallback>
238 void intersectPoint(G3D::Vector3
const& p, IsectCallback& intersectCallback)
const
240 if (!bounds.contains(p))
252 uint32 axis = (tn & (3 << 30)) >> 30;
253 bool BVH2 = (tn & (1 << 29)) != 0;
254 int offset = tn & ~(7 << 29);
260 float tl = advstd::bit_cast<float>(tree[node + 1]);
261 float tr = advstd::bit_cast<float>(tree[node + 2]);
263 if (tl < p[axis] && tr > p[axis])
265 int right = offset + 3;
280 stack[stackPos].
node = right;
287 int n = tree[node + 1];
290 intersectCallback(p, objects[offset]);
301 float tl = advstd::bit_cast<float>(tree[node + 1]);
302 float tr = advstd::bit_cast<float>(tree[node + 2]);
304 if (tl > p[axis] || tr < p[axis])
315 node = stack[stackPos].
node;
319 bool writeToFile(FILE* wf)
const;
320 bool readFromFile(FILE* rf);
357 numNodes(0), numLeaves(0), sumObjects(0), minObjects(0x0FFFFFFF),
358 maxObjects(0xFFFFFFFF), sumDepth(0), minDepth(0x0FFFFFFF),
359 maxDepth(0xFFFFFFFF), numBVH2(0)
361 for (
int i = 0; i < 6; ++i) numLeavesN[i] = 0;
366 void updateLeaf(
int depth,
int n);
367 void printStats()
const;
370 void buildHierarchy(std::vector<uint32>& tempTree, buildData& dat, BuildStats& stats)
const;
375 tempTree[nodeIndex + 0] = (3 << 30) | left;
376 tempTree[nodeIndex + 1] = right - left + 1;
379 static void subdivide(
int left,
int right, std::vector<uint32>& tempTree, buildData& dat,
AABound& gridBox,
AABound& nodeBox,
int nodeIndex,
int depth, BuildStats& stats);
void build(PrimArray const &primitives, BoundsFunc const &getBounds, uint32 leafSize=3, bool printStats=false)
static void createNode(std::vector< uint32 > &tempTree, int nodeIndex, uint32 left, uint32 right)
std::vector< uint32 > objects
std::vector< uint32 > tree
void intersectPoint(G3D::Vector3 const &p, IsectCallback &intersectCallback) const
G3D::AABox const & bound() const
void intersectRay(G3D::Ray const &r, RayCallback &intersectCallback, float &maxDist, bool stopAtFirst=false) const