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

Revision 2638, 39.9 KB checked in by bittner, 16 years ago (diff)

siggraph submission

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