kd-tree generalizations

metadata
Wenzel Jakob 2010-11-09 15:35:27 +01:00
parent fee7a12934
commit 701af0aa4b
12 changed files with 130 additions and 109 deletions

View File

@ -33,9 +33,9 @@ MTS_NAMESPACE_BEGIN
* \tparam T Underlying point data type (e.g. \ref TPoint3<float>)
*/
template <typename T> struct TAABB {
typedef T PointType;
typedef typename T::ValueType ValueType;
typedef typename T::VectorType VectorType;
typedef T point_type;
typedef typename T::value_type value_type;
typedef typename T::vector_type vector_type;
/**
* \brief Create a new invalid bounding box
@ -50,19 +50,19 @@ template <typename T> struct TAABB {
/// Unserialize a bounding box from a binary data stream
inline TAABB(Stream *stream) {
min = PointType(stream);
max = PointType(stream);
min = point_type(stream);
max = point_type(stream);
}
/// Create a collapsed AABB from a single point
inline TAABB(const PointType &p)
inline TAABB(const point_type &p)
: min(p), max(p) { }
/// Create a bounding box from two positions
inline TAABB(const PointType &min, const PointType &max)
inline TAABB(const point_type &min, const point_type &max)
: min(min), max(max) {
#if defined(MTS_DEBUG)
for (int i=0; i<PointType::dim(); ++i)
for (int i=0; i<point_type::dim(); ++i)
SAssert(min[i] <= max[i]);
#endif
}
@ -79,7 +79,7 @@ template <typename T> struct TAABB {
/// Clip to another bounding box
inline void clip(const TAABB &aabb) {
for (int i=0; i<PointType::dim(); ++i) {
for (int i=0; i<point_type::dim(); ++i) {
min[i] = std::max(min[i], aabb.min[i]);
max[i] = std::min(max[i], aabb.max[i]);
}
@ -93,28 +93,28 @@ template <typename T> struct TAABB {
* respectively.
*/
inline void reset() {
min = PointType( std::numeric_limits<ValueType>::infinity());
max = PointType(-std::numeric_limits<ValueType>::infinity());
min = point_type( std::numeric_limits<value_type>::infinity());
max = point_type(-std::numeric_limits<value_type>::infinity());
}
/// Calculate the n-dimensional volume of the bounding box
inline ValueType getVolume() const {
ValueType result = 0;
inline value_type getVolume() const {
value_type result = 0;
for (int i=0; i<3; ++i) {
ValueType tmp = max[i] - min[i];
value_type tmp = max[i] - min[i];
result += tmp*tmp;
}
return result;
}
/// Return the center point
inline PointType getCenter() const {
return (max + min) * (ValueType) 0.5;
inline point_type getCenter() const {
return (max + min) * (value_type) 0.5;
}
/// Check whether a point lies on or inside the bounding box
inline bool contains(const PointType &vec) const {
for (int i=0; i<PointType::dim(); ++i)
inline bool contains(const point_type &vec) const {
for (int i=0; i<point_type::dim(); ++i)
if (vec[i] < min[i] || vec[i] > max[i])
return false;
return true;
@ -124,7 +124,7 @@ template <typename T> struct TAABB {
inline bool contains(const TAABB &aabb) const {
if (!isValid())
return false;
for (int i=0; i<PointType::dim(); ++i)
for (int i=0; i<point_type::dim(); ++i)
if (aabb.min[i] < min[i] || aabb.max[i] > max[i])
return false;
return true;
@ -132,15 +132,15 @@ template <typename T> struct TAABB {
/// Axis-aligned bounding box overlap test
inline bool overlaps(const TAABB &aabb) const {
for (int i=0; i<PointType::dim(); ++i)
for (int i=0; i<point_type::dim(); ++i)
if (max[i] < aabb.min[i] || min[i] > aabb.max[i])
return false;
return true;
}
/// Expand the bounding box to contain another point
inline void expandBy(const PointType &p) {
for (int i=0; i<PointType::dim(); ++i) {
inline void expandBy(const point_type &p) {
for (int i=0; i<point_type::dim(); ++i) {
min[i] = std::min(min[i], p[i]);
max[i] = std::max(max[i], p[i]);
}
@ -148,17 +148,17 @@ template <typename T> struct TAABB {
/// Expand the bounding box to contain another bounding box
inline void expandBy(const TAABB &aabb) {
for (int i=0; i<PointType::dim(); ++i) {
for (int i=0; i<point_type::dim(); ++i) {
min[i] = std::min(min[i], aabb.min[i]);
max[i] = std::max(max[i], aabb.max[i]);
}
}
/// Calculate the point-AABB distance
inline ValueType distanceTo(const PointType &p) const {
ValueType result = 0;
for (int i=0; i<PointType::dim(); ++i) {
ValueType value = 0;
inline value_type distanceTo(const point_type &p) const {
value_type result = 0;
for (int i=0; i<point_type::dim(); ++i) {
value_type value = 0;
if (p[i] < min[i])
value = min[i] - p[i];
if (p[i] > max[i])
@ -170,7 +170,7 @@ template <typename T> struct TAABB {
/// Return whether this bounding box is valid
inline bool isValid() const {
for (int i=0; i<PointType::dim(); ++i)
for (int i=0; i<point_type::dim(); ++i)
if (max[i] < min[i])
return false;
return true;
@ -184,7 +184,7 @@ template <typename T> struct TAABB {
* is considered nonempty.
*/
inline bool isEmpty() const {
for (int i=0; i<PointType::dim(); ++i) {
for (int i=0; i<point_type::dim(); ++i) {
if (max[i] > min[i])
return false;
}
@ -196,7 +196,7 @@ template <typename T> struct TAABB {
Vector d = max - min;
int largest = 0;
for (int i=1; i<PointType::dim(); ++i)
for (int i=1; i<point_type::dim(); ++i)
if (d[i] > d[largest])
largest = i;
return largest;
@ -207,7 +207,7 @@ template <typename T> struct TAABB {
Vector d = max - min;
int shortest = 0;
for (int i=1; i<PointType::dim(); ++i)
for (int i=1; i<point_type::dim(); ++i)
if (d[i] < d[shortest])
shortest = i;
return shortest;
@ -217,7 +217,7 @@ template <typename T> struct TAABB {
* \brief Calculate the bounding box extents
* \return max-min
*/
inline VectorType getExtents() const {
inline vector_type getExtents() const {
return max - min;
}
@ -241,8 +241,8 @@ template <typename T> struct TAABB {
return oss.str();
}
PointType min; ///< Component-wise minimum
PointType max; ///< Component-wise maximum
point_type min; ///< Component-wise minimum
point_type max; ///< Component-wise maximum
};
@ -270,7 +270,7 @@ public:
inline AABB(const Point &p) : TAABB<Point>(p) { }
/// Create a bounding box from two positions
inline AABB(const PointType &min, const PointType &max)
inline AABB(const point_type &min, const point_type &max)
: TAABB<Point>(min, max) {
}

View File

@ -28,8 +28,8 @@ MTS_NAMESPACE_BEGIN
* \brief Parameterizable two-dimensional point data structure
*/
template <typename T> struct TPoint2 {
typedef T ValueType;
typedef TVector2<T> VectorType;
typedef T value_type;
typedef TVector2<T> vector_type;
T x, y;
@ -220,8 +220,8 @@ template <> inline TPoint2<int> &TPoint2<int>::operator/=(int s) {
* \brief Parameterizable three-dimensional point data structure
*/
template <typename T> struct TPoint3 {
typedef T ValueType;
typedef TVector3<T> VectorType;
typedef T value_type;
typedef TVector3<T> vector_type;
T x, y, z;
@ -415,8 +415,8 @@ template <> inline TPoint3<int> &TPoint3<int>::operator/=(int s) {
* \brief Parameterizable four-dimensional point data structure
*/
template <typename T> struct TPoint4 {
typedef T ValueType;
typedef TVector4<T> VectorType;
typedef T value_type;
typedef TVector4<T> vector_type;
T x, y, z, w;

View File

@ -28,8 +28,8 @@ MTS_NAMESPACE_BEGIN
* \brief Parameterizable two-dimensional vector data structure
*/
template <typename T> struct TVector2 {
typedef T ValueType;
typedef TPoint2<T> PointType;
typedef T value_type;
typedef TPoint2<T> point_type;
T x, y;
@ -219,8 +219,8 @@ template <> inline TVector2<int> &TVector2<int>::operator/=(int s) {
* \brief Parameterizable three-dimensional vector data structure
*/
template <typename T> struct TVector3 {
typedef T ValueType;
typedef TPoint3<T> PointType;
typedef T value_type;
typedef TPoint3<T> point_type;
T x, y, z;
@ -423,8 +423,8 @@ template <> inline TVector3<int> &TVector3<int>::operator/=(int s) {
* \brief Parameterizable four-dimensional vector data structure
*/
template <typename T> struct TVector4 {
typedef T ValueType;
typedef TPoint4<T> PointType;
typedef T value_type;
typedef TPoint4<T> point_type;
T x, y, z, w;

View File

@ -37,8 +37,8 @@ class ImageBlock;
class Integrator;
struct Intersection;
class IrradianceCache;
class AbstractKDTree;
template <typename Derived> class GenericKDTree;
template <typename AABBType> class AbstractKDTree;
template <typename AABBType, typename Derived> class GenericKDTree;
class KDTree;
class LocalWorker;
class Luminaire;

View File

@ -433,7 +433,7 @@ private:
* This class defines the byte layout for KD-tree nodes and
* provides methods for querying the tree structure.
*/
class MTS_EXPORT_RENDER AbstractKDTree : public Object {
template <typename AABBType> class AbstractKDTree : public Object {
public:
/// Index number format (max 2^32 prims)
typedef uint32_t index_type;
@ -606,10 +606,10 @@ public:
}
/// Return a (slightly enlarged) axis-aligned bounding box containing all primitives
inline const AABB &getAABB() const { return m_aabb; }
inline const AABBType &getAABB() const { return m_aabb; }
/// Return a tight axis-aligned bounding box containing all primitives
inline const AABB &getTightAABB() const { return m_tightAABB;}
inline const AABBType &getTightAABB() const { return m_tightAABB;}
/// Return an bounding sphere containing all primitives
inline const BSphere &getBSphere() const { return m_bsphere; }
@ -619,7 +619,7 @@ protected:
virtual ~AbstractKDTree() { }
protected:
KDNode *m_nodes;
AABB m_aabb, m_tightAABB;
AABBType m_aabb, m_tightAABB;
BSphere m_bsphere;
};
@ -679,7 +679,8 @@ protected:
*
* \author Wenzel Jakob
*/
template <typename Derived> class GenericKDTree : public AbstractKDTree {
template <typename AABBType, typename Derived>
class GenericKDTree : public AbstractKDTree<AABBType> {
protected:
// Some forward declarations
struct MinMaxBins;
@ -687,6 +688,13 @@ protected:
struct EdgeEventOrdering;
public:
typedef typename AbstractKDTree<AABBType>::size_type size_type;
typedef typename AbstractKDTree<AABBType>::index_type index_type;
typedef typename AbstractKDTree<AABBType>::KDNode KDNode;
typedef typename AABBType::value_type value_type;
typedef typename AABBType::point_type point_type;
typedef typename AABBType::vector_type vector_type;
/**
* \brief Documents the possible outcomes of a single
* ray-primitive intersection computation
@ -709,7 +717,7 @@ public:
* the default parameters.
*/
GenericKDTree() : m_indices(NULL) {
m_nodes = NULL;
this->m_nodes = NULL;
m_traversalCost = 15;
m_intersectionCost = 20;
m_emptySpaceBonus = 0.9f;
@ -729,8 +737,8 @@ public:
virtual ~GenericKDTree() {
if (m_indices)
delete[] m_indices;
if (m_nodes)
freeAligned(m_nodes-1); // undo alignment shift
if (this->m_nodes)
freeAligned(this->m_nodes-1); // undo alignment shift
}
/**
@ -920,7 +928,7 @@ protected:
*/
void buildInternal() {
/* Some samity checks */
if (isBuilt())
if (this->isBuilt())
Log(EError, "The kd-tree has already been built!");
if (m_traversalCost <= 0)
Log(EError, "The traveral cost must be > 0");
@ -939,8 +947,8 @@ protected:
if (primCount == 0) {
Log(EWarn, "kd-tree contains no geometry!");
// +1 shift is for alignment purposes (see KDNode::getSibling)
m_nodes = static_cast<KDNode *>(allocAligned(sizeof(KDNode) * 2))+1;
m_nodes[0].initLeafNode(0, 0);
this->m_nodes = static_cast<KDNode *>(allocAligned(sizeof(KDNode) * 2))+1;
this->m_nodes[0].initLeafNode(0, 0);
return;
}
@ -958,9 +966,10 @@ protected:
index_type *indices = leftAlloc.allocate<index_type>(primCount);
ref<Timer> timer = new Timer();
m_aabb.reset();
AABB &aabb = this->m_aabb;
aabb.reset();
for (index_type i=0; i<primCount; ++i) {
m_aabb.expandBy(cast()->getAABB(i));
aabb.expandBy(cast()->getAABB(i));
indices[i] = i;
}
@ -974,9 +983,9 @@ protected:
Log(EDebug, " Empty space bonus : %.2f", m_emptySpaceBonus);
Log(EDebug, " Max. tree depth : %i", m_maxDepth);
Log(EDebug, " Scene bounding box (min) : %s",
m_aabb.min.toString().c_str());
aabb.min.toString().c_str());
Log(EDebug, " Scene bounding box (max) : %s",
m_aabb.max.toString().c_str());
aabb.max.toString().c_str());
Log(EDebug, " Min-max bins : %i", m_minMaxBins);
Log(EDebug, " Greedy SAH optimization : use for <= %i primitives",
m_exactPrimThreshold);
@ -1005,7 +1014,7 @@ protected:
m_indirectionLock = new Mutex();
KDNode *prelimRoot = ctx.nodes.allocate(1);
buildTreeMinMax(ctx, 1, prelimRoot, m_aabb, m_aabb,
buildTreeMinMax(ctx, 1, prelimRoot, aabb, aabb,
indices, primCount, true, 0);
ctx.leftAlloc.release(indices);
@ -1055,7 +1064,7 @@ protected:
Log(EDebug, "Optimizing memory layout ..");
std::stack<boost::tuple<const KDNode *, KDNode *,
const BuildContext *, AABB> > stack;
const BuildContext *, AABBType> > stack;
Float expTraversalSteps = 0;
Float expLeavesVisited = 0;
@ -1070,17 +1079,17 @@ protected:
m_indexCount = ctx.primIndexCount;
// +1 shift is for alignment purposes (see KDNode::getSibling)
m_nodes = static_cast<KDNode *> (allocAligned(
this->m_nodes = static_cast<KDNode *> (allocAligned(
sizeof(KDNode) * (m_nodeCount+1)))+1;
m_indices = new index_type[m_indexCount];
stack.push(boost::make_tuple(prelimRoot, &m_nodes[nodePtr++],
&ctx, m_aabb));
stack.push(boost::make_tuple(prelimRoot, &this->m_nodes[nodePtr++],
&ctx, aabb));
while (!stack.empty()) {
const KDNode *node = boost::get<0>(stack.top());
KDNode *target = boost::get<1>(stack.top());
const BuildContext *context = boost::get<2>(stack.top());
AABB aabb = boost::get<3>(stack.top());
AABBType aabb = boost::get<3>(stack.top());
stack.pop();
typename std::map<const KDNode *, index_type>::const_iterator it
= m_interface.threadMap.find(node);
@ -1118,7 +1127,7 @@ protected:
else
left = m_indirections[node->getIndirectionIndex()];
KDNode *children = &m_nodes[nodePtr];
KDNode *children = &this->m_nodes[nodePtr];
nodePtr += 2;
int axis = node->getAxis();
float split = node->getSplit();
@ -1160,7 +1169,7 @@ protected:
Log(EDebug, "");
Float rootSA = m_aabb.getSurfaceArea();
Float rootSA = aabb.getSurfaceArea();
expTraversalSteps /= rootSA;
expLeavesVisited /= rootSA;
expPrimitivesIntersected /= rootSA;
@ -1168,12 +1177,12 @@ protected:
/* Slightly enlarge the bounding box
(necessary e.g. when the scene is planar) */
m_tightAABB = m_aabb;
m_aabb.min -= (m_aabb.max-m_aabb.min) * Epsilon
this->m_tightAABB = aabb;
aabb.min -= (aabb.max-aabb.min) * Epsilon
+ Vector(Epsilon, Epsilon, Epsilon);
m_aabb.max += (m_aabb.max-m_aabb.min) * Epsilon
aabb.max += (aabb.max-aabb.min) * Epsilon
+ Vector(Epsilon, Epsilon, Epsilon);
m_bsphere = m_aabb.getBSphere();
this->m_bsphere = aabb.getBSphere();
Log(EDebug, "Structural kd-tree statistics:");
Log(EDebug, " Parallel work units : " SIZE_T_FMT,
@ -1527,7 +1536,7 @@ protected:
aabb = cast()->getAABB(index);
}
for (int axis=0; axis<3; ++axis) {
for (int axis=0; axis<point_type::dim(); ++axis) {
float min = (float) aabb.min[axis], max = (float) aabb.max[axis];
if (min == max) {
@ -2686,9 +2695,9 @@ protected:
/**
* \brief Internal kd-tree traversal implementation (Havran variant)
*/
template<typename Derived> template<bool shadowRay> FINLINE bool
GenericKDTree<Derived>::rayIntersectHavran(const Ray &ray,
Float mint, Float maxt, Float &t, void *temp) const {
template<typename AABBType, typename Derived> template<bool shadowRay>
FINLINE bool GenericKDTree<AABBType, Derived>::rayIntersectHavran(
const Ray &ray, Float mint, Float maxt, Float &t, void *temp) const {
KDStackEntryHavran stack[MTS_KD_MAXDEPTH];
#if 0
static const int prevAxisTable[] = { 2, 0, 1 };
@ -2710,7 +2719,7 @@ template<typename Derived> template<bool shadowRay> FINLINE bool
stack[exPt].p = ray(maxt);
stack[exPt].node = NULL;
const KDNode * __restrict currNode = m_nodes;
const KDNode * __restrict currNode = this->m_nodes;
while (currNode != NULL) {
while (EXPECT_TAKEN(!currNode->isLeaf())) {
const Float splitVal = (Float) currNode->getSplit();
@ -2835,8 +2844,9 @@ template<typename Derived> template<bool shadowRay> FINLINE bool
return false;
}
template <typename Derived> FINLINE boost::tuple<bool, uint32_t, uint32_t, uint64_t>
GenericKDTree<Derived>::rayIntersectHavranCollectStatistics(
template <typename AABBType, typename Derived>
FINLINE boost::tuple<bool, uint32_t, uint32_t, uint64_t>
GenericKDTree<AABBType, Derived>::rayIntersectHavranCollectStatistics(
const Ray &ray, Float mint, Float maxt, Float &t, void *temp) const {
KDStackEntryHavran stack[MTS_KD_MAXDEPTH];
@ -2855,7 +2865,7 @@ template <typename Derived> FINLINE boost::tuple<bool, uint32_t, uint32_t, uint6
uint32_t numIntersections = 0;
uint64_t timer = rdtsc();
const KDNode * __restrict currNode = m_nodes;
const KDNode * __restrict currNode = this->m_nodes;
while (currNode != NULL) {
while (EXPECT_TAKEN(!currNode->isLeaf())) {
const Float splitVal = (Float) currNode->getSplit();
@ -2952,13 +2962,14 @@ template <typename Derived> FINLINE boost::tuple<bool, uint32_t, uint32_t, uint6
numIntersections, rdtsc() - timer);
}
template<typename Derived> template <bool shadowRay> FINLINE bool
GenericKDTree<Derived>::rayIntersectPlain(const Ray &ray,
template<typename AABBType, typename Derived>
template <bool shadowRay> FINLINE bool
GenericKDTree<AABBType, Derived>::rayIntersectPlain(const Ray &ray,
Float mint_, Float maxt_, Float &t, void *temp) const {
KDStackEntry stack[MTS_KD_MAXDEPTH];
int stackPos = 0;
Float mint = mint_, maxt = maxt_;
const KDNode *node = m_nodes;
const KDNode *node = this->m_nodes;
#if defined(MTS_KD_MAILBOX_ENABLED)
HashedMailbox mailbox;
@ -3044,13 +3055,14 @@ template<typename Derived> template <bool shadowRay> FINLINE bool
return false;
}
template<typename Derived> template <bool shadowRay> FINLINE bool
GenericKDTree<Derived>::rayIntersectPBRT(const Ray &ray,
template<typename AABBType, typename Derived>
template <bool shadowRay> FINLINE bool
GenericKDTree<AABBType, Derived>::rayIntersectPBRT(const Ray &ray,
Float mint_, Float maxt_, Float &t, void *temp) const {
KDStackEntry stack[MTS_KD_MAXDEPTH];
int stackPos = 0;
Float mint = mint_, maxt=maxt_;
const KDNode *node = m_nodes;
const KDNode *node = this->m_nodes;
bool foundIntersection = false;
#if defined(MTS_KD_MAILBOX_ENABLED)
@ -3129,11 +3141,12 @@ template<typename Derived> template <bool shadowRay> FINLINE bool
}
template <typename Derived> void GenericKDTree<Derived>::findCosts(
template <typename AABBType, typename Derived>
void GenericKDTree<AABBType, Derived>::findCosts(
Float &traversalCost, Float &intersectionCost) {
ref<Random> random = new Random();
uint8_t temp[128];
BSphere bsphere = m_aabb.getBSphere();
BSphere bsphere = this->m_aabb.getBSphere();
int nRays = 10000000, warmup = nRays/4;
Vector *A = new Vector[nRays-warmup];
Float *b = new Float[nRays-warmup];
@ -3146,7 +3159,7 @@ template <typename Derived> void GenericKDTree<Derived>::findCosts(
Point p2 = bsphere.center + squareToSphere(sample2) * bsphere.radius;
Ray ray(p1, normalize(p2-p1));
Float mint, maxt, t;
if (m_aabb.rayIntersect(ray, mint, maxt)) {
if (this->m_aabb.rayIntersect(ray, mint, maxt)) {
if (ray.mint > mint) mint = ray.mint;
if (ray.maxt < maxt) maxt = ray.maxt;
if (EXPECT_TAKEN(maxt > mint)) {
@ -3216,13 +3229,23 @@ template <typename Derived> void GenericKDTree<Derived>::findCosts(
intersectionCost = x[2];
}
template <typename Derived> Class *GenericKDTree<Derived>::m_theClass
= new Class("GenericKDTree", true, "AbstractKDTree");
template <typename AABBType>
Class *AbstractKDTree<AABBType>::m_theClass
= new Class("AbstractKDTree", true, "Object");
template <typename Derived> const Class *GenericKDTree<Derived>::getClass() const {
template <typename AABBType>
const Class *AbstractKDTree<AABBType>::getClass() const {
return m_theClass;
}
template <typename AABBType, typename Derived>
Class *GenericKDTree<AABBType, Derived>::m_theClass
= new Class("GenericKDTree", true, "AbstractKDTree");
template <typename AABBType, typename Derived>
const Class *GenericKDTree<AABBType, Derived>::getClass() const {
return m_theClass;
}
MTS_NAMESPACE_END

View File

@ -61,8 +61,8 @@ MTS_NAMESPACE_BEGIN
*
* \sa GenericKDTree
*/
class MTS_EXPORT_RENDER KDTree : public GenericKDTree<KDTree> {
friend class GenericKDTree<KDTree>;
class MTS_EXPORT_RENDER KDTree : public GenericKDTree<AABB, KDTree> {
friend class GenericKDTree<AABB, KDTree>;
public:
/// Create an empty kd-tree
KDTree();

View File

@ -249,7 +249,7 @@ public:
* the interactive walkthrough. The default implementation
* simply returns NULL.
*/
virtual const AbstractKDTree *getKDTree() const;
virtual const AbstractKDTree<AABB> *getKDTree() const;
/**
* \brief Create a triangle mesh approximation of this shape

View File

@ -374,6 +374,5 @@ void KDTree::rayIntersectPacketIncoherent(const RayPacket4 &packet,
#endif
MTS_IMPLEMENT_CLASS(AbstractKDTree, true, Object)
MTS_IMPLEMENT_CLASS(KDTree, false, GenericKDTree)
MTS_NAMESPACE_END

View File

@ -101,7 +101,7 @@ void Shape::addChild(const std::string &name, ConfigurableObject *child) {
}
}
const AbstractKDTree *Shape::getKDTree() const {
const AbstractKDTree<AABB> *Shape::getKDTree() const {
return NULL;
}

View File

@ -541,14 +541,14 @@ void PreviewThread::oglRenderVPL(PreviewQueueEntry &target, const VPL &vpl) {
}
}
void PreviewThread::oglRenderKDTree(const AbstractKDTree *kdtree) {
std::stack<boost::tuple<const AbstractKDTree::KDNode *, AABB, uint32_t> > stack;
void PreviewThread::oglRenderKDTree(const AbstractKDTree<AABB> *kdtree) {
std::stack<boost::tuple<const AbstractKDTree<AABB>::KDNode *, AABB, uint32_t> > stack;
stack.push(boost::make_tuple(kdtree->getRoot(), kdtree->getTightAABB(), 0));
Float brightness = 10.0f;
while (!stack.empty()) {
const AbstractKDTree::KDNode *node = boost::get<0>(stack.top());
const AbstractKDTree<AABB>::KDNode *node = boost::get<0>(stack.top());
AABB aabb = boost::get<1>(stack.top());
int level = boost::get<2>(stack.top());
stack.pop();

View File

@ -75,7 +75,7 @@ protected:
/// Render a single VPL using OpenGL
void oglRenderVPL(PreviewQueueEntry &target, const VPL &vpl);
/// Render a wireframe visualization of a kd-tree
void oglRenderKDTree(const AbstractKDTree *kdtree);
void oglRenderKDTree(const AbstractKDTree<AABB> *kdtree);
/// Render a single VPL using real-time coherent ray tracing
void rtrtRenderVPL(PreviewQueueEntry &target, const VPL &vpl);
private:

View File

@ -34,8 +34,8 @@ MTS_NAMESPACE_BEGIN
* \brief Space-efficient acceleration structure for cylindrical hair
* segments with miter joints.
*/
class HairKDTree : public GenericKDTree<HairKDTree> {
friend class GenericKDTree<HairKDTree>;
class HairKDTree : public GenericKDTree<AABB, HairKDTree> {
friend class GenericKDTree<AABB, HairKDTree>;
public:
HairKDTree(std::vector<Point> &vertices,
std::vector<bool> &vertexStartsFiber, Float radius)
@ -210,7 +210,6 @@ public:
return true;
}
/**
* \brief Intersect an infinite cylinder with an
* AABB face and bound the resulting clipped ellipse
@ -706,7 +705,7 @@ public:
return mesh.get();
}
const AbstractKDTree *getKDTree() const {
const AbstractKDTree<AABB> *getKDTree() const {
return m_kdtree.get();
}