kd-tree generalizations
parent
fee7a12934
commit
701af0aa4b
|
@ -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) {
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue