src/rcrt/SAHKDtree.hpp

Go to the documentation of this file.
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                 // sort event list
00242                 eventList->sort(planarEventCompare);
00243                 //std::cout << "Events Sorted" << std::endl;
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                 //std::cout << "building Node - depth=" << depth << " size=" << trList.size() << " nbox=" << nbox << std::endl;
00261                 
00262                 // check wether to build a leaf
00263                 if (trList.size() <= leafSize || depth >= maxDepth || nbox.getSurfaceArea() < 0.00001 || eventList->size() == 0) {
00264                         return buildLeaf(trList);
00265                 }
00266                 
00267                 // determining best split
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                 //std::cout << "finding best split" << std::endl;
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                                 // get next split candidate
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                                 // initializing p
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                                 //moving plane on p
00312                                 
00313                                 //std::cout << "plane=" << p[IN_PLANE] << " start=" << p[START] << " end=" << p[END] << std::endl;
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                                 //std::cout << "cost=" << cost << std::endl;
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                 //std::cout << "classification " << eventList->size() << std::endl;
00335                 
00336                 for (vecTEIter i = trList.begin(); i != trList.end(); ++i) {
00337                         (*i)->side = BOTH_SIDES;
00338                 }
00339                 
00340                 //std::cout << "set both" << std::endl;
00341                 
00342                 for (listPEIter i = eventList->begin(); i != eventList->end(); ++i) {
00343                         //std::cout << "processing tri " << ((*i).axis) << " " << ((*i).traceable == 0) << " " << (bestSplit == 0) << std::endl;
00344                         if ((*i).type == END && (*i).axis == bestSplit->axis && (*i).plane <= bestSplit->plane) {
00345                                 //std::cout << "LO1" << std::endl;
00346                                 (*i).traceable->side = LEFT_ONLY;
00347                         }
00348                         else if ((*i).type == START && (*i).axis == bestSplit->axis && (*i).plane >= bestSplit->plane) {
00349                                 //std::cout << "RO1" << std::endl;
00350                                 (*i).traceable->side = RIGHT_ONLY;
00351                         }
00352                         else if ((*i).type == IN_PLANE && (*i).axis == bestSplit->axis) {
00353                                 //std::cout << "IP" << std::endl;
00354                                 if ((*i).plane < bestSplit->plane || ((*i).plane == bestSplit->plane && bestSplit->optSide == LEFT)) {
00355                                         //std::cout << "LO2" << std::endl;
00356                                         (*i).traceable->side = LEFT_ONLY;
00357                                 }
00358                                 if ((*i).plane > bestSplit->plane || ((*i).plane == bestSplit->plane && bestSplit->optSide == RIGHT)) {
00359                                         //std::cout << "RO2" << std::endl;
00360                                         (*i).traceable->side = RIGHT_ONLY;
00361                                 }
00362                         }
00363                 }
00364                 
00365                 //std::cout << "building tr lists" << std::endl;
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                 //std::cout << "building exclusive lists" << std::endl;
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                 // generating new Events for overlapping triangles
00397                 
00398                 //std::cout << "generate events for overlap" << std::endl;
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                 //std::cout << "enter for 1" << std::endl;
00412                 
00413                 for (vecTEIter i = trList.begin(); i != trList.end(); ++i) {
00414                         if ((*i)->side == BOTH_SIDES) {
00415                                 
00416 //                              createPlanarEvents(*i, &Ebl, lBox);
00417 //                              createPlanarEvents(*i, &Ebr, rBox);
00418 //                              AABB lclipBox =(*i)->t->clipBox(lBox);
00419 //                              AABB rclipBox =(*i)->t->clipBox(rBox);
00420 //                              //std::cout << "lclipBox: " << lclipBox << " rclipBox: " << rclipBox << std::endl;
00421 //                              if (!lclipBox.isEmpty()){
00422 //                                      //std::cout << "lclipBox: " << lclipBox << std::endl;
00423 //                                      createPlanarEvents(*i, &Ebl, lclipBox);
00424 //                              }
00425 //                              if (!rclipBox.isEmpty()) {
00426 //                                      //std::cout << "rclipBox: " << rclipBox << std::endl;
00427 //                                      createPlanarEvents(*i, &Ebr, rclipBox);
00428 //                              }
00429                                 AABB lclipBox;
00430                                 AABB rclipBox;
00431                                 //std::cout << "clip" << std::endl;
00432                                 (*i)->t->clipPlane(bestSplit->axis, bestSplit->plane, lclipBox, rclipBox);
00433                                 lclipBox.contract(lBox);
00434                                 rclipBox.contract(rBox);
00435                                 //std::cout << "lclipBox: " << lclipBox << " rclipBox: " << rclipBox << std::endl;
00436                                 createPlanarEvents(*i, &Ebl, lclipBox);
00437                                 //std::cout << "left events created" << std::endl;
00438                                 createPlanarEvents(*i, &Ebr, rclipBox);
00439                                 //std::cout << "right events created" << std::endl;
00440                         }
00441                 }
00442                 
00443                 //std::cout << "sort and merge lists" << std::endl;
00444                 
00445                 // sorting lists of newly generated events
00446                 
00447                 Ebl.sort(planarEventCompare);
00448                 Ebr.sort(planarEventCompare);
00449                 
00450                 // generate left and right event list
00451                 
00452                 El->merge(Ebl,planarEventCompare);
00453                 Er->merge(Ebr,planarEventCompare);
00454                 
00455                 // create new node
00456                 
00457                 //std::cout << "Create Node" << std::endl;
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                 //std::cout << "done" << std::endl;
00468                 
00469                 delete eventList;
00470                 
00471                 return newNode;
00472         }
00473         
00480         KDNode<T>* buildLeaf(std::vector<TraceableEntry<T>* > trList) {
00481                 
00482                 //std::cout << "building leaf" << std::endl;
00483                 
00484                 KDNode<T>* leaf = new KDNode<T>();
00485                 
00486                 leaf->leaf =true;
00487                 
00488                 // check if leaf is empty
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                 // adding primitives to node
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                 // creating planar events for every axis
00529                 for (int axis = 0; axis < 3; ++axis) {
00530                         if (tbbox.getMin(intToAxis(axis)) == tbbox.getMax(intToAxis(axis))) {
00531                                 // generating IN_PLANE event
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                                 // generating START and END events
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                 //std::cout << "vol:" << vol << std::endl;
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                 //std::cout << "SAH - Cl=" << Cl << " Cr=" << Cr <<" Pl=" << Pl << " Pr=" << Pr << " Nl=" << Nl << " Nr=" << Nr << " Np=" << Np << std::endl;
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 /*SAHKDTREE_HPP_*/

Generated on Thu Jan 31 19:26:19 2008 for RenderingCompetitionRayTracer by  doxygen 1.5.3