--- a/src/kdtree.cc Thu Nov 29 18:30:16 2007 +0100
+++ b/src/kdtree.cc Fri Nov 30 00:44:51 2007 +0100
@@ -50,11 +50,14 @@
};
// stack element for kd-tree traversal
-struct StackElem
+class StackElem
{
+public:
KdNode* node; /* pointer to far child */
float t; /* the entry/exit signed distance */
Vector3 pb; /* the coordinates of entry/exit point */
+ StackElem(KdNode *anode, const float &at, const Vector3 &apb):
+ node(anode), t(at), pb(apb) {};
};
// ----------------------------------------
@@ -96,9 +99,9 @@
delete[] children;
}
-void KdNode::subdivide(BBox bbox, int depth)
+void KdNode::subdivide(BBox bbox, int maxdepth)
{
- if (depth >= 20 || shapes->size() <= 4)
+ if (maxdepth <= 0 || shapes->size() <= 2)
{
setLeaf();
return;
@@ -295,8 +298,8 @@
lbb.H.cell[axis] = split;
rbb.L.cell[axis] = split;
- children[0].subdivide(lbb, depth+1);
- children[1].subdivide(rbb, depth+1);
+ children[0].subdivide(lbb, maxdepth-1);
+ children[1].subdivide(rbb, maxdepth-1);
}
void KdTree::build()
@@ -306,7 +309,7 @@
ShapeList::iterator shape;
for (shape = shapes.begin(); shape != shapes.end(); shape++)
root->addShape(*shape);
- root->subdivide(bbox, 0);
+ root->subdivide(bbox, max_depth);
built = true;
}
@@ -328,29 +331,23 @@
KdNode *farchild, *node;
node = root; /* start from the kd-tree root node */
- stack<StackElem*> st;
-
- StackElem *enPt = new StackElem();
- enPt->t = a; /* set the signed distance */
- enPt->node = NULL;
+ /* std vector is much faster than stack */
+ vector<StackElem*> st;
- /* distinguish between internal and external origin */
- if (a >= 0.0) /* a ray with external origin */
- enPt->pb = ray.o + ray.dir * a;
- else /* a ray with internal origin */
- enPt->pb = ray.o;
+ StackElem *enPt = new StackElem(NULL, a,
+ /* distinguish between internal and external origin of a ray*/
+ a >= 0.0 ?
+ ray.o + ray.dir * a : /* external */
+ ray.o); /* internal */
/* setup initial exit point in the stack */
- StackElem *exPt = new StackElem();
- exPt->t = b;
- exPt->pb = ray.o + ray.dir * b;
- exPt->node = NULL; /* set termination flag */
- st.push(exPt);
+ StackElem *exPt = new StackElem(NULL, b, ray.o + ray.dir * b);
+ st.push_back(exPt);
/* loop, traverse through the whole kd-tree, until an object is intersected or ray leaves the scene */
while (node)
{
- exPt = st.top();
+ exPt = st.back();
/* loop until a leaf is found */
while (!node->isLeaf())
{
@@ -393,13 +390,11 @@
t = (splitVal - ray.o.cell[axis]) / ray.dir.cell[axis];
/* setup the new exit point and push it onto stack */
- exPt = new StackElem();
- exPt->t = t;
- exPt->node = farchild;
+ exPt = new StackElem(farchild, t, Vector3());
exPt->pb[axis] = splitVal;
exPt->pb[(axis+1)%3] = ray.o.cell[(axis+1)%3] + t * ray.dir.cell[(axis+1)%3];
exPt->pb[(axis+2)%3] = ray.o.cell[(axis+2)%3] + t * ray.dir.cell[(axis+2)%3];
- st.push(exPt);
+ st.push_back(exPt);
} /* while */
/* current node is the leaf . . . empty or full */
@@ -419,8 +414,8 @@
{
while (!st.empty())
{
- delete st.top();
- st.pop();
+ delete st.back();
+ st.pop_back();
}
nearest_distance = dist;
return nearest_shape;
@@ -430,7 +425,7 @@
/* retrieve the pointer to the next node, it is possible that ray traversal terminates */
node = enPt->node;
- st.pop();
+ st.pop_back();
} /* while */
delete enPt;