00001 #ifndef SAHKDTREE_HPP_
00002 #define SAHKDTREE_HPP_
00003
00004 #include "Traceable.h"
00005 #include <vector>
00006 #include <stack>
00007 #include <list>
00008 #include <limits>
00009 #include <iostream>
00010
00011
00012
00013 namespace rcrt
00014 {
00015
00019 enum Side
00020 {
00021 BOTH_SIDES = 0,
00022 LEFT_ONLY = 1,
00023 RIGHT_ONLY = 2,
00024 };
00025
00029 enum OptimalCostSide
00030 {
00031 NOT_SET = 0,
00032 LEFT = 1,
00033 RIGHT = 2,
00034 };
00035
00039 enum EventType
00040 {
00041 END = 0,
00042 IN_PLANE = 1,
00043 START = 2,
00044
00045 };
00046
00050 template <class T>
00051 class KDNode {
00052 public:
00053 KDNode<T>() {
00054 prim = 0;
00055 children[0] = 0;
00056 children[1] = 0;
00057 };
00058
00059 ~KDNode() {
00060 if (children[0]) delete children[0];
00061 if (children[1]) delete children[1];
00062 if (prim) delete prim;
00063 }
00064
00065 bool leaf, empty;
00066 KDNode<T>* children[2];
00067 Axis splitAxis;
00068 float plane;
00069 std::vector<T*>* prim;
00070
00071 };
00072
00073 template <class T> struct TraceableEntry;
00074
00078 template <class T>
00079 struct PlanarEvent {
00080 TraceableEntry<T>* traceable;
00081 Axis axis;
00082 float plane;
00083 EventType type;
00084 OptimalCostSide optSide;
00085 };
00086
00090 template <class T>
00091 struct TraceableEntry {
00092 T* t;
00093 Side side;
00094 };
00095
00096
00100 template <class T>
00101 class SAHKDtree : public rcrt::Traceable
00102 {
00103 private:
00104 KDNode<T>* root;
00105 AABB bbox;
00106 unsigned int maxDepth, leafSize;
00107 public:
00108 SAHKDtree<T>() : root(0)
00109 {
00110 maxDepth = 40;
00111 leafSize = 2;
00112 }
00113
00114 SAHKDtree<T>(std::vector<T*>* trList, int depth = 40, int lSize = 2) : root(0), maxDepth(depth), leafSize(lSize)
00115 {
00116 buildTree(trList);
00117 }
00118
00119 virtual ~SAHKDtree() {
00120
00121 }
00122
00123 typedef typename std::vector< T* >::iterator vecTIter;
00124 typedef typename std::vector<TraceableEntry<T>* >::iterator vecTEIter;
00125 typedef typename std::list<PlanarEvent<T> >::iterator listPEIter;
00126
00133 Intersection intersect(Ray& r) const
00134 {
00135 Intersection is = bbox.intersect(r);
00136
00137 if (!is.isValid()) {
00138 return is;
00139 }
00140
00141 return intersectNode(root, r);
00142 }
00143
00151 Intersection intersectNode(KDNode<T>* n, Ray& r) const {
00152
00153 Intersection is;
00154
00155 if (n->empty) {
00156 return is;
00157 }
00158 if (n->leaf) {
00159 for (vecTIter i = n->prim->begin(); i != n->prim->end(); ++i) {
00160 Intersection currentIs = (*i)->intersect(r);
00161 if (currentIs.isValid() && currentIs.getDistance() < is.getDistance()) {
00162 is = currentIs;
00163 }
00164 }
00165 return is;
00166 }
00167
00168 float rayAxisDir = r.dir()[n->splitAxis];
00169 float rayAxisOrg = r.org()[n->splitAxis];
00170 float splitDist = (n->plane-rayAxisOrg)/rayAxisDir;
00171
00172 int near = rayAxisDir < 0;
00173
00174 if (r.minDist() - splitDist > 100 * std::numeric_limits<float>::epsilon() ) {
00175 return intersectNode(n->children[!near],r);
00176 }
00177
00178 if (splitDist - r.maxDist() > 100 * std::numeric_limits<float>::epsilon() ) {
00179 return intersectNode(n->children[near],r);
00180 }
00181
00182 float maxDist = r.maxDist();
00183 r.setMaxDist(std::min(splitDist + 100 * std::numeric_limits<float>::epsilon(),maxDist));
00184 Intersection nearIS = intersectNode(n->children[near],r);
00185 r.setMaxDist(maxDist);
00186
00187 float minDist = r.minDist();
00188 r.setMinDist(std::max(splitDist - 100 * std::numeric_limits<float>::epsilon(),minDist));
00189 Intersection farIS = intersectNode(n->children[!near],r);
00190 r.setMinDist(minDist);
00191
00192 if (nearIS.isValid() && nearIS.getDistance() < farIS.getDistance()) {
00193 return nearIS;
00194 }
00195 else {
00196 return farIS;
00197 }
00198
00199 }
00200
00201 const AABB& getBoundingBox() const
00202 {
00203 return bbox;
00204 }
00205
00206 const Point3D& getCentroid() const
00207 {
00208 return bbox.getCentroid();
00209 }
00210
00211 void setTraceables(std::vector<T*>* trList) {
00212 buildTree(trList);
00213 }
00214
00220 void buildTree(std::vector<T*>* trList) {
00221
00222 std::cout << "[SAHKDtree]: building tree size = "<< trList->size() << std::endl;
00223
00224 if (root) delete root;
00225
00226 bbox = calcBoundingBox(trList);
00227
00228
00229 std::vector<TraceableEntry<T>* > trEList;
00230 std::list<PlanarEvent<T> >* eventList = new std::list<PlanarEvent<T> >();
00231
00232 for( vecTIter i = trList->begin(); i != trList->end(); ++i ) {
00233 TraceableEntry<T>* trEntry = new TraceableEntry<T>();
00234 trEntry->side = BOTH_SIDES;
00235 trEntry->t = *i;
00236
00237 trEList.push_back(trEntry);
00238 createPlanarEvents(trEntry, eventList);
00239 }
00240
00241
00242 eventList->sort(planarEventCompare);
00243
00244
00245 root = buildNode(bbox, trEList, eventList, 0);
00246 std::cout << " built tree" << std::endl;
00247 }
00248
00258 KDNode<T>* buildNode(AABB& nbox, std::vector<TraceableEntry<T>* > trList, std::list<PlanarEvent<T> >* eventList, unsigned int depth) {
00259
00260
00261
00262
00263 if (trList.size() <= leafSize || depth >= maxDepth || nbox.getSurfaceArea() < 0.00001 || eventList->size() == 0) {
00264 return buildLeaf(trList);
00265 }
00266
00267
00268
00269 int N = trList.size();
00270
00271 int Nl[3], Np[3], Nr[3];
00272
00273 for (int i = 0; i < 3; ++i) {
00274 Nl[i] = 0; Np[i] = 0; Nr[i] = N;
00275 }
00276
00277
00278
00279 PlanarEvent<T>* bestSplit = 0;
00280 float minCost = std::numeric_limits<float>::infinity();
00281
00282 for (int k = 0; k < 3; ++k) {
00283 listPEIter i = eventList->begin();
00284
00285 while (i != eventList->end()) {
00286
00287
00288
00289 while (i != eventList->end() && (*i).axis != intToAxis(k)) {
00290 ++i;
00291 }
00292
00293 if (i == eventList->end()) break;
00294
00295 PlanarEvent<T>* candidate = &(*i);
00296
00297
00298 int p[3] = {0};
00299
00300 ++p[(*i).type];
00301
00302 ++i;
00303
00304 while (i != eventList->end() && (*i).plane == candidate->plane) {
00305 if ((*i).axis == intToAxis(k)) {
00306 ++p[(*i).type];
00307 }
00308 ++i;
00309 }
00310
00311
00312
00313
00314
00315 Np[k] = p[IN_PLANE]; Nr[k] -= p[IN_PLANE]; Nr[k] -= p[END];
00316
00317 float cost = SAH(candidate, nbox, Nl[k], Nr[k], Np[k]);
00318
00319
00320
00321 if (cost < minCost) {
00322 minCost = cost;
00323 bestSplit = candidate;
00324 }
00325
00326 Nl[k] += p[START]; Nl[k] += p[IN_PLANE]; Np[k] = 0;
00327 }
00328 }
00329
00330 if (minCost >= 10 * trList.size()) {
00331 return buildLeaf(trList);
00332 }
00333
00334
00335
00336 for (vecTEIter i = trList.begin(); i != trList.end(); ++i) {
00337 (*i)->side = BOTH_SIDES;
00338 }
00339
00340
00341
00342 for (listPEIter i = eventList->begin(); i != eventList->end(); ++i) {
00343
00344 if ((*i).type == END && (*i).axis == bestSplit->axis && (*i).plane <= bestSplit->plane) {
00345
00346 (*i).traceable->side = LEFT_ONLY;
00347 }
00348 else if ((*i).type == START && (*i).axis == bestSplit->axis && (*i).plane >= bestSplit->plane) {
00349
00350 (*i).traceable->side = RIGHT_ONLY;
00351 }
00352 else if ((*i).type == IN_PLANE && (*i).axis == bestSplit->axis) {
00353
00354 if ((*i).plane < bestSplit->plane || ((*i).plane == bestSplit->plane && bestSplit->optSide == LEFT)) {
00355
00356 (*i).traceable->side = LEFT_ONLY;
00357 }
00358 if ((*i).plane > bestSplit->plane || ((*i).plane == bestSplit->plane && bestSplit->optSide == RIGHT)) {
00359
00360 (*i).traceable->side = RIGHT_ONLY;
00361 }
00362 }
00363 }
00364
00365
00366
00367 std::list<PlanarEvent<T> >* El = new std::list<PlanarEvent<T> >();
00368 std::list<PlanarEvent<T> >* Er = new std::list<PlanarEvent<T> >();
00369 std::vector<TraceableEntry<T>* > ltrs;
00370 std::vector<TraceableEntry<T>* > rtrs;
00371
00372 for (vecTEIter i = trList.begin(); i != trList.end(); ++i) {
00373 if ((*i)->side == LEFT_ONLY) {
00374 ltrs.push_back(*i);
00375 }
00376 else if ((*i)->side == RIGHT_ONLY) {
00377 rtrs.push_back(*i);
00378 }
00379 else {
00380 ltrs.push_back(*i);
00381 rtrs.push_back(*i);
00382 }
00383 }
00384
00385
00386
00387 for (listPEIter i = eventList->begin(); i != eventList->end(); ++i) {
00388 if ((*i).traceable->side == LEFT_ONLY) {
00389 El->push_back(*i);
00390 }
00391 else if ((*i).traceable->side == RIGHT_ONLY) {
00392 Er->push_back(*i);
00393 }
00394 }
00395
00396
00397
00398
00399
00400 std::list<PlanarEvent<T> > Ebl;
00401 std::list<PlanarEvent<T> > Ebr;
00402
00403 Point3D minP = nbox.getMinP();
00404 Point3D maxP = nbox.getMaxP();
00405 Point3D maxLP = maxP; maxLP[bestSplit->axis] = bestSplit->plane;
00406 Point3D minRP = minP; minRP[bestSplit->axis] = bestSplit->plane;
00407
00408 AABB lBox(minP,maxLP);
00409 AABB rBox(minRP, maxP);
00410
00411
00412
00413 for (vecTEIter i = trList.begin(); i != trList.end(); ++i) {
00414 if ((*i)->side == BOTH_SIDES) {
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 AABB lclipBox;
00430 AABB rclipBox;
00431
00432 (*i)->t->clipPlane(bestSplit->axis, bestSplit->plane, lclipBox, rclipBox);
00433 lclipBox.contract(lBox);
00434 rclipBox.contract(rBox);
00435
00436 createPlanarEvents(*i, &Ebl, lclipBox);
00437
00438 createPlanarEvents(*i, &Ebr, rclipBox);
00439
00440 }
00441 }
00442
00443
00444
00445
00446
00447 Ebl.sort(planarEventCompare);
00448 Ebr.sort(planarEventCompare);
00449
00450
00451
00452 El->merge(Ebl,planarEventCompare);
00453 Er->merge(Ebr,planarEventCompare);
00454
00455
00456
00457
00458
00459 KDNode<T>* newNode = new KDNode<T>();
00460 newNode->plane = bestSplit->plane;
00461 newNode->splitAxis = bestSplit->axis;
00462 newNode->leaf = false;
00463 newNode->empty = false;
00464 newNode->children[0] = buildNode(lBox, ltrs, El, depth+1);
00465 newNode->children[1] = buildNode(rBox, rtrs, Er, depth+1);
00466
00467
00468
00469 delete eventList;
00470
00471 return newNode;
00472 }
00473
00480 KDNode<T>* buildLeaf(std::vector<TraceableEntry<T>* > trList) {
00481
00482
00483
00484 KDNode<T>* leaf = new KDNode<T>();
00485
00486 leaf->leaf =true;
00487
00488
00489 if (trList.size() == 0) {
00490 leaf->empty = true;
00491 return leaf;
00492 }
00493
00494 leaf->empty = false;
00495
00496 leaf->prim = new std::vector<T*>();
00497
00498
00499 for (vecTEIter i = trList.begin(); i != trList.end(); ++i) {
00500 leaf->prim->push_back((*i)->t);
00501 }
00502
00503 return leaf;
00504 }
00505
00513 static bool planarEventCompare(PlanarEvent<T>& a, PlanarEvent<T>& b)
00514 {
00515 return a.plane < b.plane || (a.plane == b.plane && a.type < b.type);
00516 }
00517
00518
00526 void createPlanarEvents(TraceableEntry<T>* trEntry, std::list<PlanarEvent<T> >* eventList, AABB tbbox)
00527 {
00528
00529 for (int axis = 0; axis < 3; ++axis) {
00530 if (tbbox.getMin(intToAxis(axis)) == tbbox.getMax(intToAxis(axis))) {
00531
00532 PlanarEvent<T> planeEvent;
00533 planeEvent.axis = intToAxis(axis);
00534 planeEvent.plane = tbbox.getMin(intToAxis(axis));
00535 planeEvent.traceable = trEntry;
00536 planeEvent.type = IN_PLANE;
00537 planeEvent.optSide = NOT_SET;
00538
00539 eventList->push_back(planeEvent);
00540 }
00541 else {
00542
00543 PlanarEvent<T> startEvent;
00544 startEvent.axis = intToAxis(axis);
00545 startEvent.plane = tbbox.getMin(intToAxis(axis));
00546 startEvent.traceable = trEntry;
00547 startEvent.type = START;
00548 startEvent.optSide = NOT_SET;
00549
00550 eventList->push_back(startEvent);
00551
00552 PlanarEvent<T> endEvent;
00553 endEvent.axis = intToAxis(axis);
00554 endEvent.plane = tbbox.getMax(intToAxis(axis));
00555 endEvent.traceable = trEntry;
00556 endEvent.type = END;
00557 endEvent.optSide = NOT_SET;
00558
00559 eventList->push_back(endEvent);
00560 }
00561 }
00562 }
00563
00564 void createPlanarEvents(TraceableEntry<T>* trEntry, std::list<PlanarEvent<T> >* eventList)
00565 {
00566 const AABB& tbbox = trEntry->t->getBoundingBox();
00567 createPlanarEvents(trEntry, eventList, tbbox);
00568
00569 }
00570
00580 float C(float& Pl, float& Pr, int Nl, int Nr)
00581 {
00582 float tCost = 1;
00583 float iCost = 10;
00584 float lambda = (Nl == 0 || Nr == 0) ? 0.8 : 1;
00585 return lambda * (tCost + iCost * (Pl * Nl + Pr * Nr));
00586 }
00587
00597 float SAH(PlanarEvent<T>* p, AABB& V, int& Nl, int& Nr, int& Np) {
00598 Point3D minP = V.getMinP();
00599 Point3D maxP = V.getMaxP();
00600 Point3D maxLP = maxP; maxLP[p->axis] = p->plane;
00601 Point3D minRP = minP; minRP[p->axis] = p->plane;
00602
00603 AABB Vl(minP,maxLP);
00604 AABB Vr(minRP, maxP);
00605
00606 float vol = V.getSurfaceArea();
00607
00608
00609
00610 float Pl = Vl.getSurfaceArea()/vol;
00611 float Pr = Vr.getSurfaceArea()/vol;
00612
00613 float Cl = C(Pl,Pr,Nl+Np,Nr);
00614 float Cr = C(Pl,Pr,Nl,Np+Nr);
00615
00616
00617
00618 p->optSide = (Cl<Cr) ? LEFT : RIGHT;
00619
00620 return (Cl<Cr) ? Cl : Cr;
00621 }
00622
00629 static AABB calcBoundingBox(std::vector<T*>* trList)
00630 {
00631 AABB box;
00632 for(unsigned int i = 0; i < trList->size(); i++){
00633 box.extend(trList->at(i)->getBoundingBox());
00634 }
00635 return box;
00636 }
00637
00638 AABB clipBox(AABB& cbox) const {
00639 return getBoundingBox();
00640 }
00641
00648 static Axis intToAxis(int i)
00649 {
00650 if (i==0) return X_AXIS;
00651 if (i==1) return Y_AXIS;
00652 if (i==2) return Z_AXIS;
00653 return X_AXIS;
00654 }
00655 };
00656
00657 }
00658
00659 #endif