SAH minimization sweep

metadata
Wenzel Jakob 2010-10-08 20:25:48 +02:00
parent 13ada869dd
commit fc01e4485e
1 changed files with 104 additions and 2 deletions

View File

@ -171,6 +171,10 @@ private:
template <typename Derived> class GenericKDTree : public Object {
protected:
struct KDNode;
struct EdgeEvent;
typedef EdgeEvent *EdgeEventPtr;
typedef EdgeEventPtr EdgeEventPtr3[3];
public:
/// Index number format (max 2^32 prims)
typedef uint32_t index_type;
@ -327,7 +331,7 @@ public:
}
/**
* \brief Build helper function
* \brief Build helper function (min-max binning)
*
* \param ctx
* Thread-specific build context containing allocators etc.
@ -366,10 +370,18 @@ public:
return leafCost;
}
/* ==================================================================== */
/* Binning */
/* ==================================================================== */
MinMaxBins<MTS_KD_MINMAX_BINS> bins(tightAABB);
bins.bin(downCast(), indices, primCount);
/* ==================================================================== */
/* Split candidate search */
/* ==================================================================== */
SplitCandidate bestSplit = bins.maximizeSAH(m_traversalCost,
m_intersectionCost, m_emptySpaceBonus);
m_intersectionCost);
/* "Bad refines" heuristic from PBRT */
if (bestSplit.sahCost >= leafCost) {
@ -382,6 +394,10 @@ public:
++badRefines;
}
/* ==================================================================== */
/* Partitioning */
/* ==================================================================== */
boost::tuple<AABB, index_type *, AABB, index_type *> partition =
bins.partition(ctx, downCast(), indices, bestSplit, isLeftChild,
m_traversalCost, m_intersectionCost);
@ -398,6 +414,10 @@ public:
m_indirectionTable.push_back(children);
}
/* ==================================================================== */
/* Recursion */
/* ==================================================================== */
AABB childAABB(nodeAABB);
childAABB.max[bestSplit.axis] = bestSplit.pos;
Float saLeft = childAABB.getSurfaceArea();
@ -442,6 +462,88 @@ public:
}
}
Float buildTreeSAH(BuildContext &ctx, unsigned int depth, const KDNode *node,
const AABB &nodeAABB, EdgeEventPtr3 firstEventByAxis,
EdgeEventPtr3 lastEventByAxis, size_type primCount, bool isLeftChild,
size_type badRefines) {
Float leafCost = primCount * m_intersectionCost;
if (primCount <= m_stopPrims || depth >= m_maxDepth) {
createLeaf(ctx, node, nodeAABB, primCount);
return leafCost;
}
/* ==================================================================== */
/* Split candidate search */
/* ==================================================================== */
/* First, find the optimal splitting plane according to the
surface area heuristic. To do this in O(n), the search is
implemented as a sweep over the edge events */
for (int axis=0; axis<3; axis++) {
/* Initially, the split plane is placed left of the scene
and thus all geometry is on its right side */
int numLeft = 0, numPlanar = 0, numRight = primCount;
const EdgeEvent *firstEvent = firstEventByAxis[axis];
const EdgeEvent *lastEvent = lastEventByAxis[axis];
/* Iterate over all events on the current axis */
for (EdgeEvent *event = firstEvent; event < lastEvent; ++event) {
/* Record the current position and count all
other events, which are also here */
Float t = event->t;
int numStart = 0, numEnd = 0;
/* Count "end" events */
while (event != lastEvent && event->t == t
&& event->type == EdgeEvent::EEdgeEnd) {
++numEnd; ++event;
}
/* Count "planar" events */
while (event != lastEvent && event->t == t
&& event->type == EdgeEvent::EEdgePlanar) {
++numPlanar; ++event;
}
/* Count "start" events */
while (event != lastEvent && event->t == t
&& event->type == EdgeEvent::EEdgeStart) {
++numStart; ++event;
}
/* The split plane can now be moved onto 't'.
Accordingly, all planar and ending primitives
are removed from the right side */
numRight -= numPlanar; numRight -= numEnd;
/* Calculate a score using the surface area heuristic */
if (t >= nodeAABB.min[axis] && t <= nodeAABB.max[axis]) {
/* Score score = SAH(axis, invSA, aabb, t, numLeft,
numRight, numPlanar);
if (score < bestSplit) {
bestSplit = score;
}*/
} else {
/* When primitive clipping is active, this should
never happen! */
AssertEx(!m_clip, "Internal error: edge event is out of bounds");
}
/* The split plane is moved past 't'. All prims,
which were planar on 't', are moved to the left
side. Also, starting prims are now also left of
the split plane. */
numLeft += numStart; numLeft += numPlanar;
numPlanar = 0;
}
/* Sanity checks. Everything should now be on the
left side of the split plane */
Assert(numRight == 0 && numLeft == primCount);
}
}
/**
* \brief Tear up a subtree after a split did not reduce the SAH cost
*/