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

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

skip cast line segment for consequent line segments with oposite dirs

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
[2618]764int KdTree::CastLineSegment2(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
[2618]866int KdTree::CastLineSegment(const Vector3 &origin,
867                            const Vector3 &termination,
868                            ViewCellContainer &viewcells)
869{
870  int hits = 0;
871
872  float mint = 0.0f, maxt = 1.0f;
873  const Vector3 dir = termination - origin;
874 
875  stack<RayTraversalData> tStack;
876 
877  Intersectable::NewMail();
878 
879  //maxt += Limits::Threshold;
880 
881  Vector3 entp = origin;
882  Vector3 extp = termination;
883 
884  KdNode *node = mRoot;
885  KdNode *farChild;
886 
887  float position;
888  float tdist;
889
890  while (1)
891  {
892    if (!node->IsLeaf())
893    {
894      KdInterior *in = static_cast<KdInterior *>(node);
895      position = in->mPosition;
896      switch (in->mAxis) {
897          case 0:
898                if (entp.x <= position)
899                  {
900                        if (extp.x <= position)
901                          {
902                                node = in->mBack;
903                                // cases N1,N2,N3,P5,Z2,Z3
904                                continue;
905                          }
906                        else
907                          {
908                                // case N4
909                                node = in->mBack;
910                                farChild = in->mFront;
911                          }
912                  }
913                else
914                  {
915                        if (position <= extp.x)
916                          {
917                                node = in->mFront;
918                                // cases P1,P2,P3,N5,Z1
919                                continue;
920                          }
921                        else
922                          {
923                                node = in->mFront;
924                                farChild = in->mBack;
925                                // case P4
926                          }
927                  }
928               
929                // $$ modification 3.5.2004 - hints from Kamil Ghais
930                // case N4 or P4
931                tdist = (position - origin.x) / dir.x;
932                //tStack.push(RayTraversalData(farChild, extp, maxt)); //TODO
933                extp = origin + dir * tdist;
934                maxt = tdist;
935         
936          break;
937        case 1:
938       
939                if (entp.y <= position)
940                  {
941                        if (extp.y <= position)
942                          {
943                                node = in->mBack;
944                                // cases N1,N2,N3,P5,Z2,Z3
945                                continue;
946                          }
947                        else
948                          {
949                                // case N4
950                                node = in->mBack;
951                                farChild = in->mFront;
952                          }
953                  }
954                else
955                  {
956                        if (position <= extp.y)
957                          {
958                                node = in->mFront;
959                                // cases P1,P2,P3,N5,Z1
960                                continue;
961                          }
962                        else
963                          {
964                                node = in->mFront;
965                                farChild = in->mBack;
966                                // case P4
967                          }
968                  }
969               
970                // $$ modification 3.5.2004 - hints from Kamil Ghais
971                // case N4 or P4
972                tdist = (position - origin.y) / dir.y;
973                //tStack.push(RayTraversalData(farChild, extp, maxt)); //TODO
974                extp = origin + dir * tdist;
975                maxt = tdist;
976               
977                break;
978          case 2:
979                if (entp.z <= position)
980                  {
981                        if (extp.z <= position)
982                          {
983                                node = in->mBack;
984                                // cases N1,N2,N3,P5,Z2,Z3
985                                continue;
986                          }
987                        else
988                          {
989                                // case N4
990                                node = in->mBack;
991                                farChild = in->mFront;
992                          }
993                  }
994                else
995                  {
996                        if (position <= extp.z)
997                          {
998                                node = in->mFront;
999                                // cases P1,P2,P3,N5,Z1
1000                                continue;
1001                          }
1002                        else
1003                          {
1004                                node = in->mFront;
1005                                farChild = in->mBack;
1006                                // case P4
1007                          }
1008                  }
1009               
1010                // $$ modification 3.5.2004 - hints from Kamil Ghais
1011                // case N4 or P4
1012                tdist = (position - origin.z) / dir.z;
1013                //tStack.push(RayTraversalData(farChild, extp, maxt)); //TODO
1014                extp = origin + dir * tdist;
1015                maxt = tdist;
1016         
1017          break;
1018         
1019          }
1020         
1021        }
1022    else
1023          {
1024      // compute intersection with all objects in this leaf
1025      KdLeaf *leaf = static_cast<KdLeaf *>(node);
1026     
1027      // add view cell to intersections
1028      ViewCell *vc = leaf->mViewCell;
1029     
1030      if (!vc->Mailed())
1031      {
1032        vc->Mail();
1033        viewcells.push_back(vc);
1034        ++ hits;
1035      }
1036     
1037      // get the next node from the stack
1038      if (tStack.empty())
1039                break;
1040     
1041      entp = extp;
1042      mint = maxt;
1043     
1044      RayTraversalData &s  = tStack.top();
1045      node = s.mNode;
1046      extp = s.mExitPoint;
1047      maxt = s.mMaxT;
1048      tStack.pop();
1049    }
1050  }
1051  return hits;
1052}
1053
[1974]1054void
1055KdTree::CollectKdObjects(const AxisAlignedBox3 &box,
[2575]1056                         ObjectContainer &objects
1057                        )
[1974]1058{
1059  stack<KdNode *> nodeStack;
1060 
1061  nodeStack.push(mRoot);
[469]1062
[1974]1063  while (!nodeStack.empty()) {
1064    KdNode *node = nodeStack.top();
1065    nodeStack.pop();
[2575]1066    if (node->IsLeaf() || node->mPvsTermination == 1)  {
1067      Intersectable *object = GetOrCreateKdIntersectable(node);
1068      if (!node->Mailed()) {
1069        node->Mail();
1070        objects.push_back(object);
1071      }
1072    }
1073    else {
[1974]1074      KdInterior *interior = (KdInterior *)node;
1075         
[2575]1076      if ( box.Max()[interior->mAxis] > interior->mPosition )
1077        nodeStack.push(interior->mFront);
1078     
1079      if (box.Min()[interior->mAxis] < interior->mPosition)
1080        nodeStack.push(interior->mBack);
[1974]1081    }
[2575]1082  } // while
[1974]1083}
1084
[372]1085void
[2606]1086KdTree::CollectSmallKdObjects(const AxisAlignedBox3 &box,
1087                                                          ObjectContainer &objects,
1088                                                          const float maxAreaFrac
1089                                                          )
1090{
1091  stack<KdNode *> nodeStack;
1092 
1093  nodeStack.push(mRoot);
1094  float maxArea = GetPvsArea()*maxAreaFrac;
1095 
1096  while (!nodeStack.empty()) {
1097    KdNode *node = nodeStack.top();
1098    nodeStack.pop();
1099        if (!node->Mailed()) {
1100          node->Mail();
1101          if (node->IsLeaf() || GetSurfaceArea(node) <= maxArea)  {
1102                Intersectable *object = GetOrCreateKdIntersectable(node);
1103                if (!node->Mailed()) {
1104                  objects.push_back(object);
1105                }
1106          }
1107          else {
1108                KdInterior *interior = (KdInterior *)node;
1109               
1110                if ( box.Max()[interior->mAxis] > interior->mPosition )
1111                  nodeStack.push(interior->mFront);
1112               
1113                if (box.Min()[interior->mAxis] < interior->mPosition)
1114                  nodeStack.push(interior->mBack);
1115          }
1116        }
1117  } // while
1118}
1119
1120
1121void
[859]1122KdTree::CollectObjects(const AxisAlignedBox3 &box,
[2575]1123                       ObjectContainer &objects)
[859]1124{
1125  stack<KdNode *> nodeStack;
1126
1127  nodeStack.push(mRoot);
1128
1129  while (!nodeStack.empty()) {
1130    KdNode *node = nodeStack.top();
1131    nodeStack.pop();
1132    if (node->IsLeaf()) {
1133      KdLeaf *leaf = (KdLeaf *)node;
1134      for (int j=0; j < leaf->mObjects.size(); j++) {
[2575]1135        Intersectable *object = leaf->mObjects[j];
1136        if (!object->Mailed() && Overlap(box, object->GetBox())) {
1137          object->Mail();
1138          objects.push_back(object);
1139        }
[859]1140      }
1141    } else {
1142      KdInterior *interior = (KdInterior *)node;
1143
[2575]1144      if ( box.Max()[interior->mAxis] > interior->mPosition )
1145        nodeStack.push(interior->mFront);
1146     
1147      if (box.Min()[interior->mAxis] < interior->mPosition)
1148        nodeStack.push(interior->mBack);
[859]1149    }
1150  }
1151}
1152
1153void
[372]1154KdTree::CollectObjects(KdNode *n, ObjectContainer &objects)
1155{
1156  stack<KdNode *> nodeStack;
1157
1158  nodeStack.push(n);
1159
1160  while (!nodeStack.empty()) {
1161    KdNode *node = nodeStack.top();
1162    nodeStack.pop();
1163    if (node->IsLeaf()) {
1164      KdLeaf *leaf = (KdLeaf *)node;
1165      for (int j=0; j < leaf->mObjects.size(); j++) {
[2575]1166        Intersectable *object = leaf->mObjects[j];
1167        if (!object->Mailed()) {
1168          object->Mail();
1169          objects.push_back(object);
1170        }
[372]1171      }
1172    } else {
1173      KdInterior *interior = (KdInterior *)node;
1174      nodeStack.push(interior->mFront);
1175      nodeStack.push(interior->mBack);
1176    }
1177  }
1178}
1179
1180// Find random neighbor which was not mailed
1181KdNode *
1182KdTree::FindRandomNeighbor(KdNode *n,
[2575]1183                           bool onlyUnmailed
1184                           )
[372]1185{
1186  stack<KdNode *> nodeStack;
1187 
1188  nodeStack.push(mRoot);
1189
1190  AxisAlignedBox3 box = GetBox(n);
1191  int mask = rand();
1192
1193  while (!nodeStack.empty()) {
1194    KdNode *node = nodeStack.top();
1195    nodeStack.pop();
1196    if (node->IsLeaf()) {
1197      if ( node != n && (!onlyUnmailed || !node->Mailed()) )
1198        return node;
1199    } else {
1200      KdInterior *interior = (KdInterior *)node;
1201      if (interior->mPosition > box.Max(interior->mAxis))
1202        nodeStack.push(interior->mBack);
1203      else
1204        if (interior->mPosition < box.Min(interior->mAxis))
1205          nodeStack.push(interior->mFront);
1206        else {
1207          // random decision
1208          if (mask&1)
1209            nodeStack.push(interior->mBack);
1210          else
1211            nodeStack.push(interior->mFront);
1212          mask = mask>>1;
1213        }
1214    }
1215  }
1216 
1217  return NULL;
1218}
1219
1220int
1221KdTree::FindNeighbors(KdNode *n,
1222                      vector<KdNode *> &neighbors,
1223                      bool onlyUnmailed
1224                      )
1225{
1226  stack<KdNode *> nodeStack;
1227 
1228  nodeStack.push(mRoot);
1229
1230  AxisAlignedBox3 box = GetBox(n);
1231
1232  while (!nodeStack.empty()) {
1233    KdNode *node = nodeStack.top();
1234    nodeStack.pop();
1235    if (node->IsLeaf()) {
1236      if ( node != n && (!onlyUnmailed || !node->Mailed()) )
1237        neighbors.push_back(node);
[2575]1238    }
1239    else {
[372]1240      KdInterior *interior = (KdInterior *)node;
1241      if (interior->mPosition > box.Max(interior->mAxis))
[2575]1242        nodeStack.push(interior->mBack);
1243      else {
1244        if (interior->mPosition < box.Min(interior->mAxis))
1245          nodeStack.push(interior->mFront);
1246        else {
1247          // random decision
1248          nodeStack.push(interior->mBack);
1249          nodeStack.push(interior->mFront);
1250        }
1251      }
[372]1252    }
1253  }
1254 
[469]1255  return (int)neighbors.size();
[372]1256}
1257
1258// Find random neighbor which was not mailed
1259KdNode *
1260KdTree::GetRandomLeaf(const Plane3 &plane)
1261{
1262  stack<KdNode *> nodeStack;
1263 
1264  nodeStack.push(mRoot);
1265 
1266  int mask = rand();
1267 
1268  while (!nodeStack.empty()) {
1269    KdNode *node = nodeStack.top();
1270    nodeStack.pop();
1271    if (node->IsLeaf()) {
1272      return node;
1273    } else {
1274      KdInterior *interior = (KdInterior *)node;
1275      KdNode *next;
1276        if (GetBox(interior->mBack).Side(plane) < 0)
1277          next = interior->mFront;
1278        else
1279          if (GetBox(interior->mFront).Side(plane) < 0)
1280            next = interior->mBack;
1281          else {
1282            // random decision
1283            if (mask&1)
1284              next = interior->mBack;
1285            else
1286              next = interior->mFront;
1287            mask = mask>>1;
1288          }
1289        nodeStack.push(next);
1290    }
1291  }
1292 
1293 
1294  return NULL;
1295}
1296
1297void
1298KdTree::CollectLeaves(vector<KdLeaf *> &leaves)
1299{
1300  stack<KdNode *> nodeStack;
1301  nodeStack.push(mRoot);
1302
1303  while (!nodeStack.empty()) {
1304    KdNode *node = nodeStack.top();
1305    nodeStack.pop();
1306    if (node->IsLeaf()) {
1307      KdLeaf *leaf = (KdLeaf *)node;
1308      leaves.push_back(leaf);
1309    } else {
1310      KdInterior *interior = (KdInterior *)node;
1311      nodeStack.push(interior->mBack);
1312      nodeStack.push(interior->mFront);
1313    }
1314  }
1315}
1316
[469]1317void
1318KdTree::CreateAndCollectViewCells(ViewCellContainer &vc) const
1319{
1320  stack<KdNode *> nodeStack;
1321  nodeStack.push(mRoot);
[372]1322
[469]1323  while (!nodeStack.empty()) {
1324    KdNode *node = nodeStack.top();
1325    nodeStack.pop();
1326    if (node->IsLeaf()) {
1327      KdLeaf *leaf = (KdLeaf *)node;
1328          // kdtree used as view cell container => create view cell
[471]1329          KdViewCell *viewCell = new KdViewCell();
1330          leaf->mViewCell = viewCell;
1331          // push back pointer to this leaf
[1551]1332          viewCell->mLeaves[0] = leaf;
[471]1333      vc.push_back(viewCell);
[469]1334    } else {
1335      KdInterior *interior = (KdInterior *)node;
1336      nodeStack.push(interior->mBack);
1337      nodeStack.push(interior->mFront);
1338    }
1339  }
1340}
1341
[1736]1342
[372]1343KdNode *
1344KdTree::GetRandomLeaf(const bool onlyUnmailed)
1345{
[507]1346  stack<KdNode *> nodeStack;
[372]1347  nodeStack.push(mRoot);
[507]1348 
1349  int mask = rand();
[372]1350       
1351  while (!nodeStack.empty()) {
1352    KdNode *node = nodeStack.top();
1353    nodeStack.pop();
1354    if (node->IsLeaf()) {
1355      if ( (!onlyUnmailed || !node->Mailed()) )
1356                                return node;
1357    } else {
1358      KdInterior *interior = (KdInterior *)node;
1359                        // random decision
1360                        if (mask&1)
1361                                nodeStack.push(interior->mBack);
1362                        else
1363                                nodeStack.push(interior->mFront);
1364                        mask = mask>>1;
1365                }
1366        }
1367  return NULL;
1368}
[504]1369
1370
[2539]1371int KdTree::CastBeam(Beam &beam)
[504]1372{
[507]1373  stack<KdNode *> nodeStack;
1374  nodeStack.push(mRoot);
[504]1375 
[507]1376  while (!nodeStack.empty()) {
1377    KdNode *node = nodeStack.top();
1378    nodeStack.pop();
1379       
1380        int side = beam.ComputeIntersection(GetBox(node));
1381        switch (side) {
1382        case -1:
1383          beam.mKdNodes.push_back(node);
1384          break;
1385        case 0:
1386          if (node->IsLeaf())
1387                beam.mKdNodes.push_back(node);
1388          else {
1389                KdInterior *interior = (KdInterior *)node;
1390                KdNode *first = interior->mBack;
1391                KdNode *second = interior->mFront;
1392               
1393                if (interior->mAxis < 3) {
1394                  // spatial split -> decide on the order of the nodes
1395                  if (beam.mPlanes[0].mNormal[interior->mAxis] > 0)
1396                        swap(first, second);
1397                }
[504]1398
[507]1399                nodeStack.push(first);
1400                nodeStack.push(second);
1401          }
1402          break;
1403          // default: cull
1404        }
1405  }
1406
[532]1407  if (beam.mFlags & Beam::STORE_OBJECTS)
1408  {
1409          vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
[535]1410       
[532]1411          Intersectable::NewMail();
1412          for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
1413          {
1414                  CollectObjects(*it, beam.mObjects);
1415          }
1416  }
1417
[837]1418  return (int)beam.mKdNodes.size();
[504]1419}
[860]1420
[1074]1421
[1201]1422void KdTree::ExportBinLeaf(OUT_STREAM &stream, KdLeaf *leaf)
[1194]1423{
[2575]1424  ObjectContainer::const_iterator it, it_end = leaf->mObjects.end();
1425 
1426  int type = TYPE_LEAF;
1427  int size = (int)leaf->mObjects.size();
1428 
1429  stream.write(reinterpret_cast<char *>(&type), sizeof(int));
1430  stream.write(reinterpret_cast<char *>(&size), sizeof(int));
1431 
1432  for (it = leaf->mObjects.begin(); it != it_end; ++ it)
1433    {   
1434      Intersectable *obj = *it;
1435      int id = obj->mId;               
1436     
1437      //stream.write(reinterpret_cast<char *>(&origin), sizeof(Vector3));
1438      stream.write(reinterpret_cast<char *>(&id), sizeof(int));
[1194]1439    }
[878]1440}
[1194]1441
1442
[1201]1443KdLeaf *KdTree::ImportBinLeaf(IN_STREAM &stream,
[2575]1444                              KdInterior *parent,
1445                              const ObjectContainer &objects)
[1194]1446{
[2575]1447  int leafId = TYPE_LEAF;
1448  int objId = leafId;
1449  int size;
1450 
1451  stream.read(reinterpret_cast<char *>(&size), sizeof(int));
1452  KdLeaf *leaf = new KdLeaf(parent, size);
[1196]1453
[2575]1454  MeshInstance dummyInst(NULL);
[1633]1455       
[2575]1456  // read object ids
1457  // note: this can also be done geometrically
1458  for (int i = 0; i < size; ++ i)
1459    {   
1460      stream.read(reinterpret_cast<char *>(&objId), sizeof(int));
1461      dummyInst.SetId(objId);
1462     
1463      ObjectContainer::const_iterator oit =
1464        lower_bound(objects.begin(), objects.end(), (Intersectable *)&dummyInst, ilt);
1465     
1466      if ((oit != objects.end()) && ((*oit)->GetId() == objId))
1467        leaf->mObjects.push_back(*oit);
1468      else
1469        Debug << "error: object with id " << objId << " does not exist" << endl;
1470    }
1471 
1472  return leaf;
[1194]1473}
1474
1475
[1201]1476void KdTree::ExportBinInterior(OUT_STREAM &stream, KdInterior *interior)
[1194]1477{
[1196]1478        int interiorid = TYPE_INTERIOR;
[1194]1479        stream.write(reinterpret_cast<char *>(&interiorid), sizeof(int));
1480
1481        int axis = interior->mAxis;
[1196]1482        float pos = interior->mPosition;
[1194]1483
1484        stream.write(reinterpret_cast<char *>(&axis), sizeof(int));
[1196]1485        stream.write(reinterpret_cast<char *>(&pos), sizeof(float));
[1194]1486}
1487
1488
[1201]1489KdInterior *KdTree::ImportBinInterior(IN_STREAM  &stream, KdInterior *parent)
[1194]1490{
[1196]1491        KdInterior *interior = new KdInterior(parent);
[1194]1492
[2539]1493        int axis;
1494        float pos;
[1194]1495
1496        stream.read(reinterpret_cast<char *>(&axis), sizeof(int));
[1196]1497        stream.read(reinterpret_cast<char *>(&pos), sizeof(float));
1498
1499        interior->mAxis = axis;
1500        interior->mPosition = pos;
1501
1502        return interior;
[1194]1503}
1504
1505
1506bool KdTree::ExportBinTree(const string &filename)
1507{
[1201]1508        OUT_STREAM stream(filename.c_str(), OUT_BIN_MODE);
[1194]1509       
[2332]1510        if (!stream.is_open()) return false;
[1194]1511
1512        // export binary version of mesh
[1197]1513        queue<KdNode *> tStack;
[1194]1514        tStack.push(mRoot);
1515
1516        while(!tStack.empty())
1517        {
[1197]1518                KdNode *node = tStack.front();
[1196]1519                tStack.pop();
1520               
1521                if (node->IsLeaf())
1522                {
[1197]1523                        //Debug << "l";
[2017]1524                        ExportBinLeaf(stream, static_cast<KdLeaf *>(node));
[1196]1525                }
1526                else
1527                {
[1197]1528                        //Debug << "i";
[2017]1529                        KdInterior *interior = static_cast<KdInterior *>(node);
[1194]1530
[1196]1531                        ExportBinInterior(stream, interior);
1532                       
1533                        tStack.push(interior->mFront);
1534                        tStack.push(interior->mBack);
[1194]1535                }
1536        }
1537
1538        return true;
1539}
1540
1541
[2539]1542KdNode *KdTree::ImportNextNode(IN_STREAM &stream,
1543                                                           KdInterior *parent,
1544                                                           const ObjectContainer &objects)
[1194]1545{
[1196]1546        int nodeType;
1547        stream.read(reinterpret_cast<char *>(&nodeType), sizeof(int));
1548
1549        if (nodeType == TYPE_LEAF)
[2017]1550                return ImportBinLeaf(stream, static_cast<KdInterior *>(parent), objects);
[1196]1551
1552        if (nodeType == TYPE_INTERIOR)
[2017]1553                return ImportBinInterior(stream, static_cast<KdInterior *>(parent));
[1196]1554
1555        Debug << "error! loading failed!" << endl;
1556        return NULL;
1557}
1558
1559
[2539]1560bool KdTree::ImportBinTree(const string &filename, ObjectContainer &objects)
[1196]1561{
[2615]1562        // export binary version of mesh
1563        queue<TraversalData> tStack;
1564        IN_STREAM stream(filename.c_str(), IN_BIN_MODE);
[1197]1565
[2615]1566        if (!stream.is_open()) return false;
1567
1568        // sort objects by their id
1569        //      if (!is_sorted(objects.begin(), objects.end(), ilt))
1570        sort(objects.begin(), objects.end(), ilt);
1571
1572        mBox.Initialize();
1573        ObjectContainer::const_iterator oit, oit_end = objects.end();
1574
1575        ///////////////////////////
1576        //-- compute bounding box of object space
1577
1578        for (oit = objects.begin(); oit != oit_end; ++ oit)
1579        {
1580                const AxisAlignedBox3 box = (*oit)->GetBox();
1581                mBox.Include(box);
1582        }
1583
1584        // hack: we make a new root
1585        DEL_PTR(mRoot);
1586
1587        mRoot = ImportNextNode(stream, NULL, objects);
1588
1589        tStack.push(TraversalData(mRoot, mBox, 0));
1590        mStat.Reset();
1591        mStat.nodes = 1;
1592
1593        while(!tStack.empty())
1594        {
1595                TraversalData tData = tStack.front();
1596                tStack.pop();
1597
1598                KdNode *node = tData.mNode;
1599
1600                if (!node->IsLeaf())
1601                {
1602                        mStat.nodes += 2;
1603
1604                        //Debug << "i" ;
1605                        KdInterior *interior = static_cast<KdInterior *>(node);
1606                        interior->mBox = tData.mBox;
1607
1608                        KdNode *front = ImportNextNode(stream, interior, objects);
1609                        KdNode *back = ImportNextNode(stream, interior, objects);
1610
1611                        interior->SetupChildLinks(back, front);
1612
1613                        ++ mStat.splits[interior->mAxis];
1614
1615                        // compute new bounding box
1616                        AxisAlignedBox3 frontBox, backBox;
1617
1618                        tData.mBox.Split(interior->mAxis,
1619                                interior->mPosition,
1620                                frontBox,
1621                                backBox);
1622
1623                        tStack.push(TraversalData(front, frontBox, tData.mDepth + 1));                 
1624                        tStack.push(TraversalData(back, backBox, tData.mDepth + 1));
1625                }
1626                else
1627                {
1628                        EvaluateLeafStats(tData);
1629                        //cout << "l";
1630                }
1631        }
1632
1633        float area = GetBox().SurfaceArea()*mKdPvsArea;
1634
1635        SetPvsTerminationNodes(area);
1636
1637        Debug << mStat << endl;
1638
1639        return true;
[1194]1640}
1641
[1999]1642
[1594]1643KdIntersectable *
1644KdTree::GetOrCreateKdIntersectable(KdNode *node)
1645{
[2615]1646        if (node == NULL)
1647                return NULL;
[1194]1648
[2116]1649        if (node->mIntersectable == NULL)
1650        {
1651                // not in map => create new entry
[2117]1652                const int id = (int)mKdIntersectables.size();
[2571]1653                KdIntersectable *kdObj = new KdIntersectable(node, GetBox(node));
[2117]1654                node->mIntersectable = kdObj;
[2615]1655
[2117]1656                mKdIntersectables.push_back(kdObj);
1657                kdObj->SetId(id);
1658#ifdef USE_BIT_PVS
[2615]1659                // hack: for kd pvs the kd intersecables are the pvs objects
1660                ObjectPvsIterator::sObjects.push_back(kdObj);
[2117]1661#endif
[2615]1662        }
[1761]1663
[2615]1664        return node->mIntersectable;
[1387]1665}
[1594]1666
[1989]1667
1668void
[2575]1669KdTree::SetPvsTerminationNodes(const float maxArea)
[1989]1670{
1671  stack<KdNode *> nodeStack;
1672 
1673  nodeStack.push(mRoot);
1674
[1995]1675  float area = 0.0f;
1676  float radius = 0.0f;
1677  int nodes = 0;
1678 
[1989]1679  while (!nodeStack.empty()) {
1680    KdNode *node = nodeStack.top();
[2575]1681    nodeStack.pop();
[2606]1682       
[2575]1683    node->mPvsTermination = 0;
1684    if (node->IsLeaf() || (GetSurfaceArea(node) <= maxArea) ) {
1685      area += GetSurfaceArea(node);
1686      radius += GetBox(node).Radius();
1687      nodes++;
1688      node->mPvsTermination = 1;
1689      // create dummy kd intersectable
1690      Intersectable *object = GetOrCreateKdIntersectable(node);
1691    } else {
1692      KdInterior *interior = (KdInterior *)node;
1693      nodeStack.push(interior->mFront);
1694      nodeStack.push(interior->mBack);
[1989]1695    }
1696  }
[2575]1697 
[1995]1698  if (nodes) {
[2575]1699    area /= nodes;
1700    radius /= nodes;
1701    cout<<"Number of nodes for storing in the PVS = "<<nodes<<endl;
1702    cout<<"Average rel. node area = "<<area/GetSurfaceArea(mRoot)<<endl;
1703    cout<<"Average rel. node radius = "<<radius/GetBox(mRoot).Radius()<<endl;
1704    cout<<"Avg node radius = "<<radius<<endl;
[1995]1705  }
1706 
[1989]1707}
1708
[2615]1709
1710/*KdNode *
1711KdTree::GetPvsNode(const Triangle3 &tri) const
1712{
1713  KdNode *node = mRoot;
1714 
1715  while (node->mPvsTermination == 0 )
1716  {
1717          KdInterior *inter = (KdInterior *)node;
1718          if (point[inter->mAxis] < inter->mPosition)
1719                  node = inter->mBack;
1720          else
1721                  node = inter->mFront;
1722  }
1723
1724  return node;
1725}*/
1726
1727
1728
[1594]1729KdNode *
[1989]1730KdTree::GetPvsNode(const Vector3 &point) const
1731{
1732  KdNode *node = mRoot;
1733 
1734  while (node->mPvsTermination == 0 ) {
[2575]1735    KdInterior *inter = (KdInterior *)node;
1736    if (point[inter->mAxis] < inter->mPosition)
1737      node = inter->mBack;
1738    else
1739      node = inter->mFront;
[1989]1740  }
1741 
1742  return node;
1743}
1744
1745KdNode *
[1594]1746KdTree::GetNode(const Vector3 &point,
1747                                const float maxArea) const
1748{
1749  KdNode *node = mRoot;
1750 
1751  while (!node->IsLeaf() && (GetSurfaceArea(node) > maxArea) ) {
[2575]1752    KdInterior *inter = (KdInterior *)node;
1753    if (point[inter->mAxis] < inter->mPosition)
1754      node = inter->mBack;
1755    else
1756      node = inter->mFront;
[1594]1757  }
1758 
1759  return node;
1760}
1761
1762
[1999]1763void KdTree::GetBoxIntersections(const AxisAlignedBox3 &box,
[2575]1764                                 vector<KdLeaf *> &leaves)
[1999]1765{
[2575]1766  stack<KdNode *> tStack;
1767 
1768  tStack.push(mRoot);
1769 
1770  while (!tStack.empty())
[2615]1771  {
1772          KdNode *node = tStack.top();
1773          tStack.pop();
1774
1775          if (node->IsLeaf())
1776          {
1777                  leaves.push_back(static_cast<KdLeaf *>(node));
1778          }
1779          else // interior
1780          {
1781                  KdInterior *interior = static_cast<KdInterior *>(node);
1782
1783                  if (box.Max(interior->mAxis) >= interior->mPosition)
1784                  {
1785                          tStack.push(interior->mFront);
1786                  }
1787
1788                  if (box.Min(interior->mAxis) < interior->mPosition)
1789                  {
1790                          tStack.push(interior->mBack);
1791                  }
1792          }
1793  }
[1594]1794}
[1633]1795
[1999]1796
1797
[1633]1798}
Note: See TracBrowser for help on using the repository browser.