48 class SplitList: public vector<SplitPos> |
48 class SplitList: public vector<SplitPos> |
49 { |
49 { |
50 }; |
50 }; |
51 |
51 |
52 // stack element for kd-tree traversal |
52 // stack element for kd-tree traversal |
53 struct StackElem |
53 class StackElem |
54 { |
54 { |
|
55 public: |
55 KdNode* node; /* pointer to far child */ |
56 KdNode* node; /* pointer to far child */ |
56 float t; /* the entry/exit signed distance */ |
57 float t; /* the entry/exit signed distance */ |
57 Vector3 pb; /* the coordinates of entry/exit point */ |
58 Vector3 pb; /* the coordinates of entry/exit point */ |
|
59 StackElem(KdNode *anode, const float &at, const Vector3 &apb): |
|
60 node(anode), t(at), pb(apb) {}; |
58 }; |
61 }; |
59 |
62 |
60 // ---------------------------------------- |
63 // ---------------------------------------- |
61 |
64 |
62 void Container::addShape(Shape* aShape) |
65 void Container::addShape(Shape* aShape) |
293 } |
296 } |
294 |
297 |
295 lbb.H.cell[axis] = split; |
298 lbb.H.cell[axis] = split; |
296 rbb.L.cell[axis] = split; |
299 rbb.L.cell[axis] = split; |
297 |
300 |
298 children[0].subdivide(lbb, depth+1); |
301 children[0].subdivide(lbb, maxdepth-1); |
299 children[1].subdivide(rbb, depth+1); |
302 children[1].subdivide(rbb, maxdepth-1); |
300 } |
303 } |
301 |
304 |
302 void KdTree::build() |
305 void KdTree::build() |
303 { |
306 { |
304 infomsg("* building kd-tree\n"); |
307 infomsg("* building kd-tree\n"); |
305 root = new KdNode(); |
308 root = new KdNode(); |
306 ShapeList::iterator shape; |
309 ShapeList::iterator shape; |
307 for (shape = shapes.begin(); shape != shapes.end(); shape++) |
310 for (shape = shapes.begin(); shape != shapes.end(); shape++) |
308 root->addShape(*shape); |
311 root->addShape(*shape); |
309 root->subdivide(bbox, 0); |
312 root->subdivide(bbox, max_depth); |
310 built = true; |
313 built = true; |
311 } |
314 } |
312 |
315 |
313 /* algorithm by Vlastimil Havran, Heuristic Ray Shooting Algorithms, appendix C */ |
316 /* algorithm by Vlastimil Havran, Heuristic Ray Shooting Algorithms, appendix C */ |
314 Shape *KdTree::nearest_intersection(const Shape *origin_shape, const Ray &ray, |
317 Shape *KdTree::nearest_intersection(const Shape *origin_shape, const Ray &ray, |
326 |
329 |
327 /* pointers to the far child node and current node */ |
330 /* pointers to the far child node and current node */ |
328 KdNode *farchild, *node; |
331 KdNode *farchild, *node; |
329 node = root; /* start from the kd-tree root node */ |
332 node = root; /* start from the kd-tree root node */ |
330 |
333 |
331 stack<StackElem*> st; |
334 /* std vector is much faster than stack */ |
332 |
335 vector<StackElem*> st; |
333 StackElem *enPt = new StackElem(); |
336 |
334 enPt->t = a; /* set the signed distance */ |
337 StackElem *enPt = new StackElem(NULL, a, |
335 enPt->node = NULL; |
338 /* distinguish between internal and external origin of a ray*/ |
336 |
339 a >= 0.0 ? |
337 /* distinguish between internal and external origin */ |
340 ray.o + ray.dir * a : /* external */ |
338 if (a >= 0.0) /* a ray with external origin */ |
341 ray.o); /* internal */ |
339 enPt->pb = ray.o + ray.dir * a; |
|
340 else /* a ray with internal origin */ |
|
341 enPt->pb = ray.o; |
|
342 |
342 |
343 /* setup initial exit point in the stack */ |
343 /* setup initial exit point in the stack */ |
344 StackElem *exPt = new StackElem(); |
344 StackElem *exPt = new StackElem(NULL, b, ray.o + ray.dir * b); |
345 exPt->t = b; |
345 st.push_back(exPt); |
346 exPt->pb = ray.o + ray.dir * b; |
|
347 exPt->node = NULL; /* set termination flag */ |
|
348 st.push(exPt); |
|
349 |
346 |
350 /* loop, traverse through the whole kd-tree, until an object is intersected or ray leaves the scene */ |
347 /* loop, traverse through the whole kd-tree, until an object is intersected or ray leaves the scene */ |
351 while (node) |
348 while (node) |
352 { |
349 { |
353 exPt = st.top(); |
350 exPt = st.back(); |
354 /* loop until a leaf is found */ |
351 /* loop until a leaf is found */ |
355 while (!node->isLeaf()) |
352 while (!node->isLeaf()) |
356 { |
353 { |
357 /* retrieve position of splitting plane */ |
354 /* retrieve position of splitting plane */ |
358 float splitVal = node->getSplit(); |
355 float splitVal = node->getSplit(); |
391 |
388 |
392 /* signed distance to the splitting plane */ |
389 /* signed distance to the splitting plane */ |
393 t = (splitVal - ray.o.cell[axis]) / ray.dir.cell[axis]; |
390 t = (splitVal - ray.o.cell[axis]) / ray.dir.cell[axis]; |
394 |
391 |
395 /* setup the new exit point and push it onto stack */ |
392 /* setup the new exit point and push it onto stack */ |
396 exPt = new StackElem(); |
393 exPt = new StackElem(farchild, t, Vector3()); |
397 exPt->t = t; |
|
398 exPt->node = farchild; |
|
399 exPt->pb[axis] = splitVal; |
394 exPt->pb[axis] = splitVal; |
400 exPt->pb[(axis+1)%3] = ray.o.cell[(axis+1)%3] + t * ray.dir.cell[(axis+1)%3]; |
395 exPt->pb[(axis+1)%3] = ray.o.cell[(axis+1)%3] + t * ray.dir.cell[(axis+1)%3]; |
401 exPt->pb[(axis+2)%3] = ray.o.cell[(axis+2)%3] + t * ray.dir.cell[(axis+2)%3]; |
396 exPt->pb[(axis+2)%3] = ray.o.cell[(axis+2)%3] + t * ray.dir.cell[(axis+2)%3]; |
402 st.push(exPt); |
397 st.push_back(exPt); |
403 } /* while */ |
398 } /* while */ |
404 |
399 |
405 /* current node is the leaf . . . empty or full */ |
400 /* current node is the leaf . . . empty or full */ |
406 /* "intersect ray with each object in the object list, discarding " |
401 /* "intersect ray with each object in the object list, discarding " |
407 "those lying before stack[enPt].t or farther than stack[exPt].t" */ |
402 "those lying before stack[enPt].t or farther than stack[exPt].t" */ |