src/kdtree.cc
branchpyrit
changeset 21 79b516a3803d
parent 20 f22952603f29
child 22 76b7bd51d64a
--- 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;