diff -r f22952603f29 -r 79b516a3803d src/kdtree.cc --- 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 st; - - StackElem *enPt = new StackElem(); - enPt->t = a; /* set the signed distance */ - enPt->node = NULL; + /* std vector is much faster than stack */ + vector 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;