diff -r d8d596d26f25 -r bf17f9f84c91 src/kdtree.cc --- a/src/kdtree.cc Sun Nov 18 11:20:56 2007 +0100 +++ b/src/kdtree.cc Thu Nov 22 17:53:34 2007 +0100 @@ -1,36 +1,129 @@ -#include "kdtree.cc" +#include + +#include "kdtree.h" -void KdTree::KdTree(ShapeList &shapelist): +void Container::addShape(Shape* aShape) +{ + shapes.push_back(aShape); + if (shapes.size() == 0) { + /* initialize bounding box */ + bbox = aShape->get_bbox(); + } else { + /* adjust bounding box */ + BBox shapebb = aShape->get_bbox(); + if (shapebb.L.x < bbox.L.x) bbox.L.x = shapebb.L.x; + if (shapebb.L.y < bbox.L.y) bbox.L.y = shapebb.L.y; + if (shapebb.L.z < bbox.L.z) bbox.L.z = shapebb.L.z; + if (shapebb.R.x > bbox.R.x) bbox.R.x = shapebb.R.x; + if (shapebb.R.y > bbox.R.y) bbox.R.y = shapebb.R.y; + if (shapebb.R.z > bbox.R.z) bbox.R.z = shapebb.R.z; + } +}; + +void KdNode::subdivide(BBox bbox, int depth, int count) { - root = new KdNode(); - shapes = new vector(); + int axis; + float pos; + + //if (stopcriterionmet()) return + + // choose split axis + axis = 0; + if (bbox.R.y - bbox.L.y > bbox.R.x - bbox.L.x) + axis = 1; + if (bbox.R.z - bbox.L.z > bbox.R.y - bbox.L.y) + axis = 2; + + // *** find optimal split position + SortableShapeList sslist(shapes, axis); + sort(sslist.begin(), sslist.end()); + + SplitList splitlist = SplitList(); + + SortableShapeList::iterator sh; + for (sh = sslist.begin(); sh != sslist.end(); sh++) + { + splitlist.push_back(SplitPos(sh->bbox.L.cell[axis])); + splitlist.push_back(SplitPos(sh->bbox.R.cell[axis])); + } + sort(splitlist.begin(), splitlist.end()); + + // find all posible splits + SplitList::iterator split; + int rest; + for (split = splitlist.begin(); split != splitlist.end(); split++) + { + for (sh = sslist.begin(), rest = sslist.size(); sh != sslist.end(); sh++, rest--) + { + if (sh->hasMark()) + continue; + // if shape is on left side of split plane + if (sh->bbox.R.cell[axis] <= split->pos) + { + sh->setMark(); + split->lnum++; + } + // if shape is completely contained in split plane + if (sh->bbox.L.cell[axis] == sh->bbox.R.cell[axis] == split->pos) + { + if (split->pos - bbox.L.cell[axis] < bbox.R.cell[axis] - split->pos) + { + // left subcell is smaller -> if not empty, put shape here + if (split->lnum) + split->lnum++; + else + split->rnum++; + } else { + // right subcell is smaller + if (split->rnum) + split->rnum++; + else + split->lnum++; + } + } + // if shape is on right side of split plane + if (sh->bbox.L.cell[axis] >= split->pos) + { + split->rnum += rest; + break; + } + // if shape occupies both sides of split plane + if (sh->bbox.L.cell[axis] < split->pos && sh->bbox.R.cell[axis] > split->pos) + { + split->lnum++; + split->rnum++; + } + } + } + + // choose best split pos + // ... // + + KdNode *children = new KdNode[2]; + ShapeList::iterator shape; - for (shape = shapelist.begin(); shape != shapes.end(); shape++) - addShape(*shape); + for (shape = shapes.begin(); shape != shapes.end(); shape++) + { + if (((Triangle*)*shape)->A.cell[axis-1] < pos + || ((Triangle*)*shape)->B.cell[axis-1] < pos + || ((Triangle*)*shape)->C.cell[axis-1] < pos) + children[0].addShape(*shape); + if (((Triangle*)*shape)->A.cell[axis-1] >= pos + || ((Triangle*)*shape)->B.cell[axis-1] >= pos + || ((Triangle*)*shape)->C.cell[axis-1] >= pos) + children[1].addShape(*shape); + } - rebuild(); + bbox.R[axis-1] = pos; + children[0].subdivide(bbox, depth+1, children[0].shapes.size()); + + bbox.L[axis-1] = pos; + children[1].subdivide(bbox, depth+1, children[1].shapes.size()); } -void KdTree::Subdivide(KdNode* node, AABB& bbox, int depth, int count) +void KdTree::build() { - - /*if (stopcriterionmet()) return - splitpos = findoptimalsplitposition() - leftnode = new Node() - rightnode = new Node() - for (all primitives in node) - { - if (node->intersectleftnode()) leftnode->addprimitive( primitive ) - if (node->intersectrightnode()) rightnode->addprimitive( primitive ) - } - buildkdtree( leftnode ) - buildkdtree( rightnode )*/ + root = new KdNode(); + root->shapes = shapes; + root->subdivide(bbox, 0, shapes.size()); } - -void KdTree::rebuild() -{ - int count = shapes->size(); - AABB bbox = shapes->extends(); - - Subdivide(root, bbox, 0, count); -} \ No newline at end of file