source: GTP/trunk/Lib/Vis/Preprocessing/src/KdTree.cpp @ 2615

Revision 2615, 36.4 KB checked in by mattausch, 16 years ago (diff)

did some stuff for the visualization

RevLine 
[372]1#include <stack>
2#include <algorithm>
3#include <queue>
4#include "Environment.h"
5#include "Mesh.h"
6#include "KdTree.h"
[469]7#include "ViewCell.h"
[505]8#include "Beam.h"
[2116]9#include "ViewCell.h"
10#include "IntersectableWrapper.h"
[372]11
12
[2176]13using namespace std;
14
[372]15
[2332]16#define TYPE_INTERIOR -2
17#define TYPE_LEAF -3
18
19
[863]20namespace GtpVisibilityPreprocessor {
[860]21
[1176]22int KdNode::sMailId = 1;
23int KdNode::sReservedMailboxes = 1;
[863]24
[2066]25
[1197]26inline static bool ilt(Intersectable *obj1, Intersectable *obj2)
27{
[2575]28  return obj1->mId < obj2->mId;
[1197]29}
30
31
[2539]32KdNode::KdNode(KdInterior *parent):
33mParent(parent), mMailbox(0), mIntersectable(NULL)
[372]34{
[2575]35  if (parent)
36    mDepth = parent->mDepth+1;
37  else
38    mDepth = 0;
[372]39}
40
[1002]41
42KdInterior::~KdInterior()
43{
[2575]44  // recursivly destroy children
45  DEL_PTR(mFront);
46  DEL_PTR(mBack);
[1002]47}
48
49
[1999]50KdLeaf::~KdLeaf()
51{
[2575]52  DEL_PTR(mViewCell); 
[1999]53}
54
55
[372]56KdTree::KdTree()
[2539]57{
[372]58  mRoot = new KdLeaf(NULL, 0);
[2575]59  Environment::GetSingleton()->GetIntValue("KdTree.Termination.maxNodes",
60                                           mTermMaxNodes);
61  Environment::GetSingleton()->GetIntValue("KdTree.Termination.maxDepth",
62                                           mTermMaxDepth);
63  Environment::GetSingleton()->GetIntValue("KdTree.Termination.minCost",
64                                           mTermMinCost);
65  Environment::GetSingleton()->GetFloatValue("KdTree.Termination.maxCostRatio",
66                                             mMaxCostRatio);
67  Environment::GetSingleton()->GetFloatValue("KdTree.Termination.ct_div_ci",
68                                             mCt_div_ci);
69  Environment::GetSingleton()->GetFloatValue("KdTree.splitBorder",
70                                             mSplitBorder);
71  Environment::GetSingleton()->GetFloatValue("KdTree.pvsArea",
72                                             mKdPvsArea);
[372]73
[2575]74  Environment::GetSingleton()->GetBoolValue("KdTree.sahUseFaces",
75                                            mSahUseFaces);
[372]76
77  char splitType[64];
[1004]78  Environment::GetSingleton()->GetStringValue("KdTree.splitMethod", splitType);
[372]79 
80  mSplitMethod = SPLIT_SPATIAL_MEDIAN;
81  if (strcmp(splitType, "spatialMedian") == 0)
82    mSplitMethod = SPLIT_SPATIAL_MEDIAN;
83  else
84    if (strcmp(splitType, "objectMedian") == 0)
85      mSplitMethod = SPLIT_OBJECT_MEDIAN;
86    else
87      if (strcmp(splitType, "SAH") == 0)
88        mSplitMethod = SPLIT_SAH;
89      else {
90        cerr<<"Wrong kd split type "<<splitType<<endl;
91        exit(1);
92      }
93  splitCandidates = NULL;
94}
95
[1002]96
97KdTree::~KdTree()
98{
[1999]99    DEL_PTR(mRoot);
100        CLEAR_CONTAINER(mKdIntersectables);
[1002]101}
102
103
[372]104bool
105KdTree::Construct()
106{
107  if (!splitCandidates)
[2003]108    splitCandidates = new vector<SortableEntry *>;
[372]109
110  // first construct a leaf that will get subdivide
111  KdLeaf *leaf = (KdLeaf *) mRoot;
112
113  mStat.nodes = 1;
114
115  mBox.Initialize();
116  ObjectContainer::const_iterator mi;
117  for ( mi = leaf->mObjects.begin();
118        mi != leaf->mObjects.end();
119        mi++) {
[752]120        //      cout<<(*mi)->GetBox()<<endl;
121        mBox.Include((*mi)->GetBox());
[372]122  }
123
[752]124  cout <<"KdTree Root Box:"<<mBox<<endl;
[372]125  mRoot = Subdivide(TraversalData(leaf, mBox, 0));
126
127  // remove the allocated array
[2003]128  CLEAR_CONTAINER(*splitCandidates);
[372]129  delete splitCandidates;
130
[2606]131  float area = GetPvsArea();
132 
[1989]133  SetPvsTerminationNodes(area);
134 
[372]135  return true;
136}
137
[2606]138float
139KdTree::GetPvsArea() const {
140  return GetBox().SurfaceArea() * mKdPvsArea;
141}
142
[372]143KdNode *
144KdTree::Subdivide(const TraversalData &tdata)
145{
146
147  KdNode *result = NULL;
148
149  priority_queue<TraversalData> tStack;
150  //  stack<STraversalData> tStack;
151 
152  tStack.push(tdata);
153  AxisAlignedBox3 backBox, frontBox;
154
155  while (!tStack.empty()) {
[752]156        //      cout<<mStat.Nodes()<<" "<<mTermMaxNodes<<endl;
157        if (mStat.Nodes() > mTermMaxNodes) {
158          //    if ( GetMemUsage() > maxMemory ) {
[372]159      // count statistics on unprocessed leafs
160      while (!tStack.empty()) {
[752]161                EvaluateLeafStats(tStack.top());
162                tStack.pop();
[372]163      }
164      break;
165    }
[752]166         
167       
[372]168    TraversalData data = tStack.top();
169    tStack.pop();
170   
171    KdNode *node = SubdivideNode((KdLeaf *) data.mNode,
[2575]172                                 data.mBox,
173                                 backBox,
174                                 frontBox
175                                 );
[752]176
[2575]177    if (result == NULL)
[372]178      result = node;
179   
180    if (!node->IsLeaf()) {
181      KdInterior *interior = (KdInterior *) node;
182      // push the children on the stack
183      tStack.push(TraversalData(interior->mBack, backBox, data.mDepth+1));
184      tStack.push(TraversalData(interior->mFront, frontBox, data.mDepth+1));
185     
[2575]186    }
187    else {
[372]188      EvaluateLeafStats(data);
189    }
190  }
191 
192  return result;
193
194}
195
196
197bool
198KdTree::TerminationCriteriaMet(const KdLeaf *leaf)
199{
[2575]200  const bool criteriaMet =
201    ((int)leaf->mObjects.size() <= mTermMinCost) ||
202    (leaf->mDepth >= mTermMaxDepth);
203 
204  if (0 && criteriaMet)
205    cerr<<"\n OBJECTS="<<(int)leaf->mObjects.size()<<endl;
206 
207  return criteriaMet;
[372]208}
209
210
211int
212KdTree::SelectPlane(KdLeaf *leaf,
[2575]213                    const AxisAlignedBox3 &box,
214                    float &position
215                    )
[372]216{
217  int axis = -1;
218 
219  switch (mSplitMethod)
220    {
221    case SPLIT_SPATIAL_MEDIAN: {
222      axis = box.Size().DrivingAxis();
223      position = (box.Min()[axis] + box.Max()[axis])*0.5f;
224      break;
225    }
226    case SPLIT_SAH: {
227      int objectsBack, objectsFront;
228      float costRatio;
[1584]229      bool mOnlyDrivingAxis = true;
[1387]230
[2575]231      if (mOnlyDrivingAxis) {
232        axis = box.Size().DrivingAxis();
233        costRatio = BestCostRatio(leaf,
234                                  box,
235                                  axis,
236                                  position,
237                                  objectsBack,
238                                  objectsFront);
[372]239      }
[2575]240      else {
241        // for all 3 axes
242        costRatio = MAX_FLOAT;
243        for (int i=0; i < 3; i++) {
244          float p;
245          float r = BestCostRatio(leaf,
246                                  box,
247                                  i,
248                                  p,
249                                  objectsBack,
250                                  objectsFront);
251          if (r < costRatio) {
252            costRatio = r;
253            axis = i;
254            position = p;
255          }
256        }
257      }
[372]258     
259      if (costRatio > mMaxCostRatio) {
[2575]260        //cout<<"Too big cost ratio "<<costRatio<<endl;
261        axis = -1;
[372]262      }
263      break;
264    }
265   
266    }
267  return axis;
268}
269
[2575]270KdNode*
[372]271KdTree::SubdivideNode(
272                      KdLeaf *leaf,
273                      const AxisAlignedBox3 &box,
274                      AxisAlignedBox3 &backBBox,
275                      AxisAlignedBox3 &frontBBox
276                      )
[2575]277
[372]278  if (TerminationCriteriaMet(leaf))
[2575]279    return leaf;
[469]280
[372]281  float position;
282 
283  // select subdivision axis
284  int axis = SelectPlane( leaf, box, position );
285
286  if (axis == -1) {
287    return leaf;
288  }
289 
[2575]290  mStat.nodes += 2;
[372]291  mStat.splits[axis]++;
292 
293  // add the new nodes to the tree
294  KdInterior *node = new KdInterior(leaf->mParent);
295
296  node->mAxis = axis;
297  node->mPosition = position;
298  node->mBox = box;
299 
300  backBBox = box;
301  frontBBox = box;
302 
303  // first count ray sides
304  int objectsBack = 0;
305  int objectsFront = 0;
306 
307  backBBox.SetMax(axis, position);
308  frontBBox.SetMin(axis, position);
309
310  ObjectContainer::const_iterator mi;
311
312  for ( mi = leaf->mObjects.begin();
313        mi != leaf->mObjects.end();
314        mi++) {
315    // determine the side of this ray with respect to the plane
316    AxisAlignedBox3 box = (*mi)->GetBox();
317    if (box.Max(axis) > position )
318      objectsFront++;
319   
320    if (box.Min(axis) < position )
321      objectsBack++;
322  }
323
324  KdLeaf *back = new KdLeaf(node, objectsBack);
325  KdLeaf *front = new KdLeaf(node, objectsFront);
[1074]326 
[372]327  // replace a link from node's parent
328  if (  leaf->mParent )
329    leaf->mParent->ReplaceChildLink(leaf, node);
330
331  // and setup child links
332  node->SetupChildLinks(back, front);
333 
334  for (mi = leaf->mObjects.begin();
335       mi != leaf->mObjects.end();
336       mi++) {
337    // determine the side of this ray with respect to the plane
338    AxisAlignedBox3 box = (*mi)->GetBox();
[1736]339       
340        // matt: no more ref
[1143]341        // for handling multiple objects: keep track of references
[1736]342        //if (leaf->IsRoot())
343        //      (*mi)->mReferences = 1; // initialise references at root
[1143]344       
[1736]345        // matt: no more ref
346        //-- (*mi)->mReferences; // remove parent ref
[372]347
[1143]348
[2575]349    if (box.Max(axis) >= position )
350    {
[372]351      front->mObjects.push_back(*mi);
[2575]352      //++ (*mi)->mReferences;
353    }
[1143]354       
[372]355    if (box.Min(axis) < position )
[2575]356    {
[372]357      back->mObjects.push_back(*mi);
[2575]358      // matt: no more ref
359      //  ++ (*mi)->mReferences;
360    }
[1143]361
[1144]362    mStat.objectRefs -= (int)leaf->mObjects.size();
363    mStat.objectRefs += objectsBack + objectsFront;
364  }
365
[2575]366  // store objects referenced in more than one leaf
367  // for easy access
368  ProcessMultipleRefs(back);
369  ProcessMultipleRefs(front);
370 
371  delete leaf;
372  return node;
[372]373}
374
375
[1143]376void KdTree::ProcessMultipleRefs(KdLeaf *leaf) const
377{
[2575]378  // find objects from multiple kd-leaves
379  ObjectContainer::const_iterator oit, oit_end = leaf->mObjects.end();
[1143]380
[2575]381  for (oit = leaf->mObjects.begin(); oit != oit_end; ++ oit)
382  {
383    Intersectable *object = *oit;
[1143]384               
[2575]385    // matt: no more ref
386    /*
387      if (object->mReferences > 1) {
388        leaf->mMultipleObjects.push_back(object);
389      }
390    */
391  }
[1143]392}
393
394
[372]395void
396KdTreeStatistics::Print(ostream &app) const
397{
398  app << "===== KdTree statistics ===============\n";
399
400  app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
401
402  app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
403
[667]404  app << "#N_SPLITS ( Number of splits in axes x y z dx dy dz)\n";
[372]405  for (int i=0; i<7; i++)
406    app << splits[i] <<" ";
407  app <<endl;
408
409  app << "#N_RAYREFS ( Number of rayRefs )\n" <<
410    rayRefs << "\n";
411
412  app << "#N_RAYRAYREFS  ( Number of rayRefs / ray )\n" <<
413    rayRefs/(double)rays << "\n";
414
415  app << "#N_LEAFRAYREFS  ( Number of rayRefs / leaf )\n" <<
416    rayRefs/(double)Leaves() << "\n";
417
[1184]418  app << "#N_MAXOBJECTREFS  ( Max number of object refs / leaf )\n" <<
[372]419    maxObjectRefs << "\n";
420
421  app << "#N_NONEMPTYRAYREFS  ( Number of rayRefs in nonEmpty leaves / non empty leaf )\n" <<
422    rayRefsNonZeroQuery/(double)(Leaves() - zeroQueryNodes) << "\n";
423
424  app << "#N_LEAFDOMAINREFS  ( Number of query domain Refs / leaf )\n" <<
425    objectRefs/(double)Leaves() << "\n";
426
427  //  app << setprecision(4);
428
429  app << "#N_PEMPTYLEAVES  ( Percentage of leaves with zero query domains )\n"<<
430    zeroQueryNodes*100/(double)Leaves()<<endl;
431
432  app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maxdepth )\n"<<
433    maxDepthNodes*100/(double)Leaves()<<endl;
434
435  app << "#N_PMINCOSTLEAVES  ( Percentage of leaves with minCost )\n"<<
436    minCostNodes*100/(double)Leaves()<<endl;
437
438  app << "#N_ADDED_RAYREFS  (Number of dynamically added ray references )\n"<<
439    addedRayRefs<<endl;
440
441  app << "#N_REMOVED_RAYREFS  (Number of dynamically removed ray references )\n"<<
442    removedRayRefs<<endl;
443
444  //  app << setprecision(4);
445
446  //  app << "#N_CTIME  ( Construction time [s] )\n"
447  //      << Time() << " \n";
448
449  app << "===== END OF KdTree statistics ==========\n";
450
451}
452
453
454
455void
456KdTree::EvaluateLeafStats(const TraversalData &data)
457{
458
459  // the node became a leaf -> evaluate stats for leafs
460  KdLeaf *leaf = (KdLeaf *)data.mNode;
461
462  if (data.mDepth > mTermMaxDepth)
463    mStat.maxDepthNodes++;
464 
465  if ( (int)(leaf->mObjects.size()) < mTermMinCost)
466    mStat.minCostNodes++;
467 
468 
469  if ( (int)(leaf->mObjects.size()) > mStat.maxObjectRefs)
[469]470    mStat.maxObjectRefs = (int)leaf->mObjects.size();
[372]471 
472}
473
474
475
476void
[1233]477KdTree::SortSubdivisionCandidates(
[2575]478                                  KdLeaf *node,
479                                  const int axis
480                                  )
[372]481{
[2575]482  CLEAR_CONTAINER(*splitCandidates);
483  //splitCandidates->clear();
484 
485  int requestedSize = 2*(int)node->mObjects.size();
486 
487  // creates a sorted split candidates array
488  if (splitCandidates->capacity() > 500000 &&
489      requestedSize < (int)(splitCandidates->capacity()/10) ) {         
490    delete splitCandidates;
491    splitCandidates = new vector<SortableEntry *>;
[372]492  }
493 
494  splitCandidates->reserve(requestedSize);
495 
496  // insert all queries
497  for(ObjectContainer::const_iterator mi = node->mObjects.begin();
498      mi != node->mObjects.end();
[2066]499      mi++)
500  {
[2575]501    AxisAlignedBox3 box = (*mi)->GetBox();
[372]502
[2575]503    splitCandidates->push_back(new SortableEntry(SortableEntry::BOX_MIN,
504                                                 box.Min(axis),
505                                                 *mi)
506                               );
[372]507   
[2575]508    splitCandidates->push_back(new SortableEntry(SortableEntry::BOX_MAX,
509                                                 box.Max(axis),
510                                                 *mi)
511                               );
[372]512  }
513 
[2066]514  stable_sort(splitCandidates->begin(), splitCandidates->end(), iltS);
[372]515}
516
517
518float
519KdTree::BestCostRatio(
[2575]520                      KdLeaf *node,
521                      const AxisAlignedBox3 &box,
522                      const int axis,
523                      float &position,
524                      int &objectsBack,
525                      int &objectsFront
526                      )
[372]527{
528
[1387]529#define DEBUG_COST 0
530
531#if DEBUG_COST
532  static int nodeId = -1;
533  char filename[256];
534 
535  static int lastAxis = 100;
536  if (axis <= lastAxis)
537        nodeId++;
538
539  lastAxis = axis;
540 
541  sprintf(filename, "sah-cost%d-%d.log", nodeId, axis);
542  ofstream costStream;
543 
544  if (nodeId < 100)
[2575]545    costStream.open(filename);
[1387]546
547#endif
548 
[1233]549  SortSubdivisionCandidates(node, axis);
[372]550 
551  // go through the lists, count the number of objects left and right
552  // and evaluate the following cost funcion:
553  // C = ct_div_ci  + (ol + or)/queries
554
555  float totalIntersections = 0.0f;
[2003]556  vector<SortableEntry *>::const_iterator ci;
[372]557
558  for(ci = splitCandidates->begin();
559      ci < splitCandidates->end();
560      ci++)
[2003]561    if ((*ci)->type == SortableEntry::BOX_MIN) {
562      totalIntersections += (*ci)->intersectable->IntersectionComplexity();
[372]563    }
564       
565  float intersectionsLeft = 0;
566  float intersectionsRight = totalIntersections;
567       
[469]568  int objectsLeft = 0, objectsRight = (int)node->mObjects.size();
[372]569 
570  float minBox = box.Min(axis);
571  float maxBox = box.Max(axis);
572  float boxArea = box.SurfaceArea();
573 
574  float minBand = minBox + mSplitBorder*(maxBox - minBox);
575  float maxBand = minBox + (1.0f - mSplitBorder)*(maxBox - minBox);
576 
[469]577  float minSum = 1e20f;
[372]578 
579  for(ci = splitCandidates->begin();
580      ci < splitCandidates->end();
581      ci++) {
[2003]582    switch ((*ci)->type) {
[372]583    case SortableEntry::BOX_MIN:
584      objectsLeft++;
[2003]585      intersectionsLeft += (*ci)->intersectable->IntersectionComplexity();
[372]586      break;
587    case SortableEntry::BOX_MAX:
588      objectsRight--;
[2003]589      intersectionsRight -= (*ci)->intersectable->IntersectionComplexity();
[372]590      break;
[2575]591    } // switch
[372]592
[2003]593    if ((*ci)->value > minBand && (*ci)->value < maxBand) {
[372]594      AxisAlignedBox3 lbox = box;
595      AxisAlignedBox3 rbox = box;
[2003]596      lbox.SetMax(axis, (*ci)->value);
597      rbox.SetMin(axis, (*ci)->value);
[372]598
599      float sum;
600      if (mSahUseFaces)
[2575]601        sum = intersectionsLeft*lbox.SurfaceArea() + intersectionsRight*rbox.SurfaceArea();
[372]602      else
[2575]603        sum = objectsLeft*lbox.SurfaceArea() + objectsRight*rbox.SurfaceArea();
[372]604     
605      //      cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl;
606      //      cout<<"cost= "<<sum<<endl;
[1387]607
608#if DEBUG_COST
[2575]609      if (nodeId < 100) {
[1387]610        float oldCost = mSahUseFaces ? totalIntersections : node->mObjects.size();
611        float newCost = mCt_div_ci + sum/boxArea;
612        float ratio = newCost/oldCost;
[2003]613        costStream<<(*ci)->value<<" "<<ratio<<endl;
[2575]614      }
[1387]615#endif
[2575]616     
[372]617      if (sum < minSum) {
[2575]618        minSum = sum;
619        position = (*ci)->value;
620       
621        objectsBack = objectsLeft;
622        objectsFront = objectsRight;
[372]623      }
624    }
[2575]625  } // for ci
[372]626 
627  float oldCost = mSahUseFaces ? totalIntersections : node->mObjects.size();
628  float newCost = mCt_div_ci + minSum/boxArea;
629  float ratio = newCost/oldCost;
630 
631#if 0
632  cout<<"===================="<<endl;
633  cout<<"costRatio="<<ratio<<" pos="<<position<<" t="<<(position - minBox)/(maxBox - minBox)
634      <<"\t o=("<<objectsBack<<","<<objectsFront<<")"<<endl;
635#endif
636  return ratio;
637}
638
639int
640KdTree::CastRay(
[2575]641                Ray &ray
642                )
[372]643{
[1984]644 
[372]645  int hits = 0;
646 
647  stack<RayTraversalData> tStack;
648 
649  float maxt = 1e6;
650  float mint = 0;
[1583]651
[1584]652  //  ray.ComputeInvertedDir();
[372]653  Intersectable::NewMail();
654
655  if (!mBox.GetMinMaxT(ray, &mint, &maxt))
656    return 0;
657
658  if (mint < 0)
659    mint = 0;
[1584]660
[372]661 
662  maxt += Limits::Threshold;
663 
664  Vector3 entp = ray.Extrap(mint);
665  Vector3 extp = ray.Extrap(maxt);
666 
667  KdNode *node = mRoot;
668  KdNode *farChild;
669  float position;
670  int axis;
[752]671
[372]672 
673  while (1) {
674    if (!node->IsLeaf()) {
675      KdInterior *in = (KdInterior *) node;
676      position = in->mPosition;
677      axis = in->mAxis;
678
679      if (entp[axis] <= position) {
[2575]680        if (extp[axis] <= position) {
681          node = in->mBack;
682          // cases N1,N2,N3,P5,Z2,Z3
683          continue;
684        }
685        else {
686          // case N4
687          node = in->mBack;
688          farChild = in->mFront;
689        }
[372]690      }
691      else {
[2575]692        if (position <= extp[axis]) {
693          node = in->mFront;
694          // cases P1,P2,P3,N5,Z1
695          continue;
696        }
697        else {
698          node = in->mFront;
699          farChild = in->mBack;
700          // case P4
701        }
702      }
[372]703      // $$ modification 3.5.2004 - hints from Kamil Ghais
704      // case N4 or P4
705      float tdist = (position - ray.GetLoc(axis)) / ray.GetDir(axis);
706      tStack.push(RayTraversalData(farChild, extp, maxt));
707      extp = ray.GetLoc() + ray.GetDir()*tdist;
708      maxt = tdist;
[2575]709    }
710    else {
711      // compute intersection with all objects in this leaf
712      KdLeaf *leaf = (KdLeaf *) node;
713      if (ray.mFlags & Ray::STORE_KDLEAVES)
714        ray.kdLeaves.push_back(leaf);
[752]715         
[2575]716      ObjectContainer::const_iterator mi;
717      for ( mi = leaf->mObjects.begin();
718            mi != leaf->mObjects.end();
719            mi++) {
720        Intersectable *object = *mi;
721        if (!object->Mailed() ) {
722          object->Mail();
723          if (ray.mFlags & Ray::STORE_TESTED_OBJECTS)
[1867]724                        ray.testedObjects.push_back(object);
725                 
[2575]726          static int oi=1;
727          if (MeshDebug)
728            cout<<"Object "<<oi++;
[752]729         
[2575]730          hits += object->CastRay(ray);
[752]731         
[2575]732          if (MeshDebug) {
733            if (!ray.intersections.empty())
734              cout<<"nearest t="<<ray.intersections[0].mT<<endl;
735            else
736              cout<<"nearest t=-INF"<<endl;
737          }       
738        }
739      }
[752]740         
[2575]741      if (hits && ray.GetType() == Ray::LOCAL_RAY)
742        if (ray.intersections[0].mT <= maxt)
743          break;
744     
745      // get the next node from the stack
746      if (tStack.empty())
747        break;
748     
749      entp = extp;
750      mint = maxt;
751      if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f)
752        break;
753     
754      RayTraversalData &s  = tStack.top();
755      node = s.mNode;
756      extp = s.mExitPoint;
757      maxt = s.mMaxT;
758      tStack.pop();
759    }
[372]760  }
761  return hits;
762}
763
[469]764int KdTree::CastLineSegment(const Vector3 &origin,
[2575]765                            const Vector3 &termination,
766                            ViewCellContainer &viewcells)
[469]767{
[2575]768  int hits = 0;
[2017]769
[2575]770  float mint = 0.0f, maxt = 1.0f;
771  const Vector3 dir = termination - origin;
772 
773  stack<RayTraversalData> tStack;
774 
775  Intersectable::NewMail();
776 
777  //maxt += Limits::Threshold;
778 
779  Vector3 entp = origin;
780  Vector3 extp = termination;
781 
782  KdNode *node = mRoot;
783  KdNode *farChild;
784 
785  float position;
786  int axis;
[469]787
[2575]788  while (1)
789  {
790    if (!node->IsLeaf())
791    {
792      KdInterior *in = static_cast<KdInterior *>(node);
793      position = in->mPosition;
794      axis = in->mAxis;
795     
796      if (entp[axis] <= position)
797      {
798        if (extp[axis] <= position)
[469]799        {
[2575]800          node = in->mBack;
801          // cases N1,N2,N3,P5,Z2,Z3
802          continue;
803        }
804        else
805        {
806          // case N4
807          node = in->mBack;
808          farChild = in->mFront;
[469]809        }
[2575]810      }
811      else
812      {
813        if (position <= extp[axis])
814        {
815          node = in->mFront;
816          // cases P1,P2,P3,N5,Z1
817          continue;
818        }
819        else
820        {
821          node = in->mFront;
822          farChild = in->mBack;
823          // case P4
824        }
825      }
826     
827      // $$ modification 3.5.2004 - hints from Kamil Ghais
828      // case N4 or P4
829      float tdist = (position - origin[axis]) / dir[axis];
830      //tStack.push(RayTraversalData(farChild, extp, maxt)); //TODO
831      extp = origin + dir * tdist;
832      maxt = tdist;
833    }
834    else
835    {
836      // compute intersection with all objects in this leaf
837      KdLeaf *leaf = static_cast<KdLeaf *>(node);
838     
839      // add view cell to intersections
840      ViewCell *vc = leaf->mViewCell;
841     
842      if (!vc->Mailed())
843      {
844        vc->Mail();
845        viewcells.push_back(vc);
846        ++ hits;
847      }
848     
849      // get the next node from the stack
850      if (tStack.empty())
851        break;
852     
853      entp = extp;
854      mint = maxt;
855     
856      RayTraversalData &s  = tStack.top();
857      node = s.mNode;
858      extp = s.mExitPoint;
859      maxt = s.mMaxT;
860      tStack.pop();
861    }
862  }
863  return hits;
[469]864}
865
[1974]866void
867KdTree::CollectKdObjects(const AxisAlignedBox3 &box,
[2575]868                         ObjectContainer &objects
869                        )
[1974]870{
871  stack<KdNode *> nodeStack;
872 
873  nodeStack.push(mRoot);
[469]874
[1974]875  while (!nodeStack.empty()) {
876    KdNode *node = nodeStack.top();
877    nodeStack.pop();
[2575]878    if (node->IsLeaf() || node->mPvsTermination == 1)  {
879      Intersectable *object = GetOrCreateKdIntersectable(node);
880      if (!node->Mailed()) {
881        node->Mail();
882        objects.push_back(object);
883      }
884    }
885    else {
[1974]886      KdInterior *interior = (KdInterior *)node;
887         
[2575]888      if ( box.Max()[interior->mAxis] > interior->mPosition )
889        nodeStack.push(interior->mFront);
890     
891      if (box.Min()[interior->mAxis] < interior->mPosition)
892        nodeStack.push(interior->mBack);
[1974]893    }
[2575]894  } // while
[1974]895}
896
[372]897void
[2606]898KdTree::CollectSmallKdObjects(const AxisAlignedBox3 &box,
899                                                          ObjectContainer &objects,
900                                                          const float maxAreaFrac
901                                                          )
902{
903  stack<KdNode *> nodeStack;
904 
905  nodeStack.push(mRoot);
906  float maxArea = GetPvsArea()*maxAreaFrac;
907 
908  while (!nodeStack.empty()) {
909    KdNode *node = nodeStack.top();
910    nodeStack.pop();
911        if (!node->Mailed()) {
912          node->Mail();
913          if (node->IsLeaf() || GetSurfaceArea(node) <= maxArea)  {
914                Intersectable *object = GetOrCreateKdIntersectable(node);
915                if (!node->Mailed()) {
916                  objects.push_back(object);
917                }
918          }
919          else {
920                KdInterior *interior = (KdInterior *)node;
921               
922                if ( box.Max()[interior->mAxis] > interior->mPosition )
923                  nodeStack.push(interior->mFront);
924               
925                if (box.Min()[interior->mAxis] < interior->mPosition)
926                  nodeStack.push(interior->mBack);
927          }
928        }
929  } // while
930}
931
932
933void
[859]934KdTree::CollectObjects(const AxisAlignedBox3 &box,
[2575]935                       ObjectContainer &objects)
[859]936{
937  stack<KdNode *> nodeStack;
938
939  nodeStack.push(mRoot);
940
941  while (!nodeStack.empty()) {
942    KdNode *node = nodeStack.top();
943    nodeStack.pop();
944    if (node->IsLeaf()) {
945      KdLeaf *leaf = (KdLeaf *)node;
946      for (int j=0; j < leaf->mObjects.size(); j++) {
[2575]947        Intersectable *object = leaf->mObjects[j];
948        if (!object->Mailed() && Overlap(box, object->GetBox())) {
949          object->Mail();
950          objects.push_back(object);
951        }
[859]952      }
953    } else {
954      KdInterior *interior = (KdInterior *)node;
955
[2575]956      if ( box.Max()[interior->mAxis] > interior->mPosition )
957        nodeStack.push(interior->mFront);
958     
959      if (box.Min()[interior->mAxis] < interior->mPosition)
960        nodeStack.push(interior->mBack);
[859]961    }
962  }
963}
964
965void
[372]966KdTree::CollectObjects(KdNode *n, ObjectContainer &objects)
967{
968  stack<KdNode *> nodeStack;
969
970  nodeStack.push(n);
971
972  while (!nodeStack.empty()) {
973    KdNode *node = nodeStack.top();
974    nodeStack.pop();
975    if (node->IsLeaf()) {
976      KdLeaf *leaf = (KdLeaf *)node;
977      for (int j=0; j < leaf->mObjects.size(); j++) {
[2575]978        Intersectable *object = leaf->mObjects[j];
979        if (!object->Mailed()) {
980          object->Mail();
981          objects.push_back(object);
982        }
[372]983      }
984    } else {
985      KdInterior *interior = (KdInterior *)node;
986      nodeStack.push(interior->mFront);
987      nodeStack.push(interior->mBack);
988    }
989  }
990}
991
992// Find random neighbor which was not mailed
993KdNode *
994KdTree::FindRandomNeighbor(KdNode *n,
[2575]995                           bool onlyUnmailed
996                           )
[372]997{
998  stack<KdNode *> nodeStack;
999 
1000  nodeStack.push(mRoot);
1001
1002  AxisAlignedBox3 box = GetBox(n);
1003  int mask = rand();
1004
1005  while (!nodeStack.empty()) {
1006    KdNode *node = nodeStack.top();
1007    nodeStack.pop();
1008    if (node->IsLeaf()) {
1009      if ( node != n && (!onlyUnmailed || !node->Mailed()) )
1010        return node;
1011    } else {
1012      KdInterior *interior = (KdInterior *)node;
1013      if (interior->mPosition > box.Max(interior->mAxis))
1014        nodeStack.push(interior->mBack);
1015      else
1016        if (interior->mPosition < box.Min(interior->mAxis))
1017          nodeStack.push(interior->mFront);
1018        else {
1019          // random decision
1020          if (mask&1)
1021            nodeStack.push(interior->mBack);
1022          else
1023            nodeStack.push(interior->mFront);
1024          mask = mask>>1;
1025        }
1026    }
1027  }
1028 
1029  return NULL;
1030}
1031
1032int
1033KdTree::FindNeighbors(KdNode *n,
1034                      vector<KdNode *> &neighbors,
1035                      bool onlyUnmailed
1036                      )
1037{
1038  stack<KdNode *> nodeStack;
1039 
1040  nodeStack.push(mRoot);
1041
1042  AxisAlignedBox3 box = GetBox(n);
1043
1044  while (!nodeStack.empty()) {
1045    KdNode *node = nodeStack.top();
1046    nodeStack.pop();
1047    if (node->IsLeaf()) {
1048      if ( node != n && (!onlyUnmailed || !node->Mailed()) )
1049        neighbors.push_back(node);
[2575]1050    }
1051    else {
[372]1052      KdInterior *interior = (KdInterior *)node;
1053      if (interior->mPosition > box.Max(interior->mAxis))
[2575]1054        nodeStack.push(interior->mBack);
1055      else {
1056        if (interior->mPosition < box.Min(interior->mAxis))
1057          nodeStack.push(interior->mFront);
1058        else {
1059          // random decision
1060          nodeStack.push(interior->mBack);
1061          nodeStack.push(interior->mFront);
1062        }
1063      }
[372]1064    }
1065  }
1066 
[469]1067  return (int)neighbors.size();
[372]1068}
1069
1070// Find random neighbor which was not mailed
1071KdNode *
1072KdTree::GetRandomLeaf(const Plane3 &plane)
1073{
1074  stack<KdNode *> nodeStack;
1075 
1076  nodeStack.push(mRoot);
1077 
1078  int mask = rand();
1079 
1080  while (!nodeStack.empty()) {
1081    KdNode *node = nodeStack.top();
1082    nodeStack.pop();
1083    if (node->IsLeaf()) {
1084      return node;
1085    } else {
1086      KdInterior *interior = (KdInterior *)node;
1087      KdNode *next;
1088        if (GetBox(interior->mBack).Side(plane) < 0)
1089          next = interior->mFront;
1090        else
1091          if (GetBox(interior->mFront).Side(plane) < 0)
1092            next = interior->mBack;
1093          else {
1094            // random decision
1095            if (mask&1)
1096              next = interior->mBack;
1097            else
1098              next = interior->mFront;
1099            mask = mask>>1;
1100          }
1101        nodeStack.push(next);
1102    }
1103  }
1104 
1105 
1106  return NULL;
1107}
1108
1109void
1110KdTree::CollectLeaves(vector<KdLeaf *> &leaves)
1111{
1112  stack<KdNode *> nodeStack;
1113  nodeStack.push(mRoot);
1114
1115  while (!nodeStack.empty()) {
1116    KdNode *node = nodeStack.top();
1117    nodeStack.pop();
1118    if (node->IsLeaf()) {
1119      KdLeaf *leaf = (KdLeaf *)node;
1120      leaves.push_back(leaf);
1121    } else {
1122      KdInterior *interior = (KdInterior *)node;
1123      nodeStack.push(interior->mBack);
1124      nodeStack.push(interior->mFront);
1125    }
1126  }
1127}
1128
[469]1129void
1130KdTree::CreateAndCollectViewCells(ViewCellContainer &vc) const
1131{
1132  stack<KdNode *> nodeStack;
1133  nodeStack.push(mRoot);
[372]1134
[469]1135  while (!nodeStack.empty()) {
1136    KdNode *node = nodeStack.top();
1137    nodeStack.pop();
1138    if (node->IsLeaf()) {
1139      KdLeaf *leaf = (KdLeaf *)node;
1140          // kdtree used as view cell container => create view cell
[471]1141          KdViewCell *viewCell = new KdViewCell();
1142          leaf->mViewCell = viewCell;
1143          // push back pointer to this leaf
[1551]1144          viewCell->mLeaves[0] = leaf;
[471]1145      vc.push_back(viewCell);
[469]1146    } else {
1147      KdInterior *interior = (KdInterior *)node;
1148      nodeStack.push(interior->mBack);
1149      nodeStack.push(interior->mFront);
1150    }
1151  }
1152}
1153
[1736]1154
[372]1155KdNode *
1156KdTree::GetRandomLeaf(const bool onlyUnmailed)
1157{
[507]1158  stack<KdNode *> nodeStack;
[372]1159  nodeStack.push(mRoot);
[507]1160 
1161  int mask = rand();
[372]1162       
1163  while (!nodeStack.empty()) {
1164    KdNode *node = nodeStack.top();
1165    nodeStack.pop();
1166    if (node->IsLeaf()) {
1167      if ( (!onlyUnmailed || !node->Mailed()) )
1168                                return node;
1169    } else {
1170      KdInterior *interior = (KdInterior *)node;
1171                        // random decision
1172                        if (mask&1)
1173                                nodeStack.push(interior->mBack);
1174                        else
1175                                nodeStack.push(interior->mFront);
1176                        mask = mask>>1;
1177                }
1178        }
1179  return NULL;
1180}
[504]1181
1182
[2539]1183int KdTree::CastBeam(Beam &beam)
[504]1184{
[507]1185  stack<KdNode *> nodeStack;
1186  nodeStack.push(mRoot);
[504]1187 
[507]1188  while (!nodeStack.empty()) {
1189    KdNode *node = nodeStack.top();
1190    nodeStack.pop();
1191       
1192        int side = beam.ComputeIntersection(GetBox(node));
1193        switch (side) {
1194        case -1:
1195          beam.mKdNodes.push_back(node);
1196          break;
1197        case 0:
1198          if (node->IsLeaf())
1199                beam.mKdNodes.push_back(node);
1200          else {
1201                KdInterior *interior = (KdInterior *)node;
1202                KdNode *first = interior->mBack;
1203                KdNode *second = interior->mFront;
1204               
1205                if (interior->mAxis < 3) {
1206                  // spatial split -> decide on the order of the nodes
1207                  if (beam.mPlanes[0].mNormal[interior->mAxis] > 0)
1208                        swap(first, second);
1209                }
[504]1210
[507]1211                nodeStack.push(first);
1212                nodeStack.push(second);
1213          }
1214          break;
1215          // default: cull
1216        }
1217  }
1218
[532]1219  if (beam.mFlags & Beam::STORE_OBJECTS)
1220  {
1221          vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
[535]1222       
[532]1223          Intersectable::NewMail();
1224          for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
1225          {
1226                  CollectObjects(*it, beam.mObjects);
1227          }
1228  }
1229
[837]1230  return (int)beam.mKdNodes.size();
[504]1231}
[860]1232
[1074]1233
[1201]1234void KdTree::ExportBinLeaf(OUT_STREAM &stream, KdLeaf *leaf)
[1194]1235{
[2575]1236  ObjectContainer::const_iterator it, it_end = leaf->mObjects.end();
1237 
1238  int type = TYPE_LEAF;
1239  int size = (int)leaf->mObjects.size();
1240 
1241  stream.write(reinterpret_cast<char *>(&type), sizeof(int));
1242  stream.write(reinterpret_cast<char *>(&size), sizeof(int));
1243 
1244  for (it = leaf->mObjects.begin(); it != it_end; ++ it)
1245    {   
1246      Intersectable *obj = *it;
1247      int id = obj->mId;               
1248     
1249      //stream.write(reinterpret_cast<char *>(&origin), sizeof(Vector3));
1250      stream.write(reinterpret_cast<char *>(&id), sizeof(int));
[1194]1251    }
[878]1252}
[1194]1253
1254
[1201]1255KdLeaf *KdTree::ImportBinLeaf(IN_STREAM &stream,
[2575]1256                              KdInterior *parent,
1257                              const ObjectContainer &objects)
[1194]1258{
[2575]1259  int leafId = TYPE_LEAF;
1260  int objId = leafId;
1261  int size;
1262 
1263  stream.read(reinterpret_cast<char *>(&size), sizeof(int));
1264  KdLeaf *leaf = new KdLeaf(parent, size);
[1196]1265
[2575]1266  MeshInstance dummyInst(NULL);
[1633]1267       
[2575]1268  // read object ids
1269  // note: this can also be done geometrically
1270  for (int i = 0; i < size; ++ i)
1271    {   
1272      stream.read(reinterpret_cast<char *>(&objId), sizeof(int));
1273      dummyInst.SetId(objId);
1274     
1275      ObjectContainer::const_iterator oit =
1276        lower_bound(objects.begin(), objects.end(), (Intersectable *)&dummyInst, ilt);
1277     
1278      if ((oit != objects.end()) && ((*oit)->GetId() == objId))
1279        leaf->mObjects.push_back(*oit);
1280      else
1281        Debug << "error: object with id " << objId << " does not exist" << endl;
1282    }
1283 
1284  return leaf;
[1194]1285}
1286
1287
[1201]1288void KdTree::ExportBinInterior(OUT_STREAM &stream, KdInterior *interior)
[1194]1289{
[1196]1290        int interiorid = TYPE_INTERIOR;
[1194]1291        stream.write(reinterpret_cast<char *>(&interiorid), sizeof(int));
1292
1293        int axis = interior->mAxis;
[1196]1294        float pos = interior->mPosition;
[1194]1295
1296        stream.write(reinterpret_cast<char *>(&axis), sizeof(int));
[1196]1297        stream.write(reinterpret_cast<char *>(&pos), sizeof(float));
[1194]1298}
1299
1300
[1201]1301KdInterior *KdTree::ImportBinInterior(IN_STREAM  &stream, KdInterior *parent)
[1194]1302{
[1196]1303        KdInterior *interior = new KdInterior(parent);
[1194]1304
[2539]1305        int axis;
1306        float pos;
[1194]1307
1308        stream.read(reinterpret_cast<char *>(&axis), sizeof(int));
[1196]1309        stream.read(reinterpret_cast<char *>(&pos), sizeof(float));
1310
1311        interior->mAxis = axis;
1312        interior->mPosition = pos;
1313
1314        return interior;
[1194]1315}
1316
1317
1318bool KdTree::ExportBinTree(const string &filename)
1319{
[1201]1320        OUT_STREAM stream(filename.c_str(), OUT_BIN_MODE);
[1194]1321       
[2332]1322        if (!stream.is_open()) return false;
[1194]1323
1324        // export binary version of mesh
[1197]1325        queue<KdNode *> tStack;
[1194]1326        tStack.push(mRoot);
1327
1328        while(!tStack.empty())
1329        {
[1197]1330                KdNode *node = tStack.front();
[1196]1331                tStack.pop();
1332               
1333                if (node->IsLeaf())
1334                {
[1197]1335                        //Debug << "l";
[2017]1336                        ExportBinLeaf(stream, static_cast<KdLeaf *>(node));
[1196]1337                }
1338                else
1339                {
[1197]1340                        //Debug << "i";
[2017]1341                        KdInterior *interior = static_cast<KdInterior *>(node);
[1194]1342
[1196]1343                        ExportBinInterior(stream, interior);
1344                       
1345                        tStack.push(interior->mFront);
1346                        tStack.push(interior->mBack);
[1194]1347                }
1348        }
1349
1350        return true;
1351}
1352
1353
[2539]1354KdNode *KdTree::ImportNextNode(IN_STREAM &stream,
1355                                                           KdInterior *parent,
1356                                                           const ObjectContainer &objects)
[1194]1357{
[1196]1358        int nodeType;
1359        stream.read(reinterpret_cast<char *>(&nodeType), sizeof(int));
1360
1361        if (nodeType == TYPE_LEAF)
[2017]1362                return ImportBinLeaf(stream, static_cast<KdInterior *>(parent), objects);
[1196]1363
1364        if (nodeType == TYPE_INTERIOR)
[2017]1365                return ImportBinInterior(stream, static_cast<KdInterior *>(parent));
[1196]1366
1367        Debug << "error! loading failed!" << endl;
1368        return NULL;
1369}
1370
1371
[2539]1372bool KdTree::ImportBinTree(const string &filename, ObjectContainer &objects)
[1196]1373{
[2615]1374        // export binary version of mesh
1375        queue<TraversalData> tStack;
1376        IN_STREAM stream(filename.c_str(), IN_BIN_MODE);
[1197]1377
[2615]1378        if (!stream.is_open()) return false;
1379
1380        // sort objects by their id
1381        //      if (!is_sorted(objects.begin(), objects.end(), ilt))
1382        sort(objects.begin(), objects.end(), ilt);
1383
1384        mBox.Initialize();
1385        ObjectContainer::const_iterator oit, oit_end = objects.end();
1386
1387        ///////////////////////////
1388        //-- compute bounding box of object space
1389
1390        for (oit = objects.begin(); oit != oit_end; ++ oit)
1391        {
1392                const AxisAlignedBox3 box = (*oit)->GetBox();
1393                mBox.Include(box);
1394        }
1395
1396        // hack: we make a new root
1397        DEL_PTR(mRoot);
1398
1399        mRoot = ImportNextNode(stream, NULL, objects);
1400
1401        tStack.push(TraversalData(mRoot, mBox, 0));
1402        mStat.Reset();
1403        mStat.nodes = 1;
1404
1405        while(!tStack.empty())
1406        {
1407                TraversalData tData = tStack.front();
1408                tStack.pop();
1409
1410                KdNode *node = tData.mNode;
1411
1412                if (!node->IsLeaf())
1413                {
1414                        mStat.nodes += 2;
1415
1416                        //Debug << "i" ;
1417                        KdInterior *interior = static_cast<KdInterior *>(node);
1418                        interior->mBox = tData.mBox;
1419
1420                        KdNode *front = ImportNextNode(stream, interior, objects);
1421                        KdNode *back = ImportNextNode(stream, interior, objects);
1422
1423                        interior->SetupChildLinks(back, front);
1424
1425                        ++ mStat.splits[interior->mAxis];
1426
1427                        // compute new bounding box
1428                        AxisAlignedBox3 frontBox, backBox;
1429
1430                        tData.mBox.Split(interior->mAxis,
1431                                interior->mPosition,
1432                                frontBox,
1433                                backBox);
1434
1435                        tStack.push(TraversalData(front, frontBox, tData.mDepth + 1));                 
1436                        tStack.push(TraversalData(back, backBox, tData.mDepth + 1));
1437                }
1438                else
1439                {
1440                        EvaluateLeafStats(tData);
1441                        //cout << "l";
1442                }
1443        }
1444
1445        float area = GetBox().SurfaceArea()*mKdPvsArea;
1446
1447        SetPvsTerminationNodes(area);
1448
1449        Debug << mStat << endl;
1450
1451        return true;
[1194]1452}
1453
[1999]1454
[1594]1455KdIntersectable *
1456KdTree::GetOrCreateKdIntersectable(KdNode *node)
1457{
[2615]1458        if (node == NULL)
1459                return NULL;
[1194]1460
[2116]1461        if (node->mIntersectable == NULL)
1462        {
1463                // not in map => create new entry
[2117]1464                const int id = (int)mKdIntersectables.size();
[2571]1465                KdIntersectable *kdObj = new KdIntersectable(node, GetBox(node));
[2117]1466                node->mIntersectable = kdObj;
[2615]1467
[2117]1468                mKdIntersectables.push_back(kdObj);
1469                kdObj->SetId(id);
1470#ifdef USE_BIT_PVS
[2615]1471                // hack: for kd pvs the kd intersecables are the pvs objects
1472                ObjectPvsIterator::sObjects.push_back(kdObj);
[2117]1473#endif
[2615]1474        }
[1761]1475
[2615]1476        return node->mIntersectable;
[1387]1477}
[1594]1478
[1989]1479
1480void
[2575]1481KdTree::SetPvsTerminationNodes(const float maxArea)
[1989]1482{
1483  stack<KdNode *> nodeStack;
1484 
1485  nodeStack.push(mRoot);
1486
[1995]1487  float area = 0.0f;
1488  float radius = 0.0f;
1489  int nodes = 0;
1490 
[1989]1491  while (!nodeStack.empty()) {
1492    KdNode *node = nodeStack.top();
[2575]1493    nodeStack.pop();
[2606]1494       
[2575]1495    node->mPvsTermination = 0;
1496    if (node->IsLeaf() || (GetSurfaceArea(node) <= maxArea) ) {
1497      area += GetSurfaceArea(node);
1498      radius += GetBox(node).Radius();
1499      nodes++;
1500      node->mPvsTermination = 1;
1501      // create dummy kd intersectable
1502      Intersectable *object = GetOrCreateKdIntersectable(node);
1503    } else {
1504      KdInterior *interior = (KdInterior *)node;
1505      nodeStack.push(interior->mFront);
1506      nodeStack.push(interior->mBack);
[1989]1507    }
1508  }
[2575]1509 
[1995]1510  if (nodes) {
[2575]1511    area /= nodes;
1512    radius /= nodes;
1513    cout<<"Number of nodes for storing in the PVS = "<<nodes<<endl;
1514    cout<<"Average rel. node area = "<<area/GetSurfaceArea(mRoot)<<endl;
1515    cout<<"Average rel. node radius = "<<radius/GetBox(mRoot).Radius()<<endl;
1516    cout<<"Avg node radius = "<<radius<<endl;
[1995]1517  }
1518 
[1989]1519}
1520
[2615]1521
1522/*KdNode *
1523KdTree::GetPvsNode(const Triangle3 &tri) const
1524{
1525  KdNode *node = mRoot;
1526 
1527  while (node->mPvsTermination == 0 )
1528  {
1529          KdInterior *inter = (KdInterior *)node;
1530          if (point[inter->mAxis] < inter->mPosition)
1531                  node = inter->mBack;
1532          else
1533                  node = inter->mFront;
1534  }
1535
1536  return node;
1537}*/
1538
1539
1540
[1594]1541KdNode *
[1989]1542KdTree::GetPvsNode(const Vector3 &point) const
1543{
1544  KdNode *node = mRoot;
1545 
1546  while (node->mPvsTermination == 0 ) {
[2575]1547    KdInterior *inter = (KdInterior *)node;
1548    if (point[inter->mAxis] < inter->mPosition)
1549      node = inter->mBack;
1550    else
1551      node = inter->mFront;
[1989]1552  }
1553 
1554  return node;
1555}
1556
1557KdNode *
[1594]1558KdTree::GetNode(const Vector3 &point,
1559                                const float maxArea) const
1560{
1561  KdNode *node = mRoot;
1562 
1563  while (!node->IsLeaf() && (GetSurfaceArea(node) > maxArea) ) {
[2575]1564    KdInterior *inter = (KdInterior *)node;
1565    if (point[inter->mAxis] < inter->mPosition)
1566      node = inter->mBack;
1567    else
1568      node = inter->mFront;
[1594]1569  }
1570 
1571  return node;
1572}
1573
1574
[1999]1575void KdTree::GetBoxIntersections(const AxisAlignedBox3 &box,
[2575]1576                                 vector<KdLeaf *> &leaves)
[1999]1577{
[2575]1578  stack<KdNode *> tStack;
1579 
1580  tStack.push(mRoot);
1581 
1582  while (!tStack.empty())
[2615]1583  {
1584          KdNode *node = tStack.top();
1585          tStack.pop();
1586
1587          if (node->IsLeaf())
1588          {
1589                  leaves.push_back(static_cast<KdLeaf *>(node));
1590          }
1591          else // interior
1592          {
1593                  KdInterior *interior = static_cast<KdInterior *>(node);
1594
1595                  if (box.Max(interior->mAxis) >= interior->mPosition)
1596                  {
1597                          tStack.push(interior->mFront);
1598                  }
1599
1600                  if (box.Min(interior->mAxis) < interior->mPosition)
1601                  {
1602                          tStack.push(interior->mBack);
1603                  }
1604          }
1605  }
[1594]1606}
[1633]1607
[1999]1608
1609
[1633]1610}
Note: See TracBrowser for help on using the repository browser.