source: GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktball.cpp @ 2582

Revision 2582, 27.7 KB checked in by bittner, 16 years ago (diff)

Havran Ray Caster compiles and links, but still does not work

Line 
1// ===================================================================
2// $Id: $
3//
4// ktball.cpp
5//     Implementation of interface functions for CKTB trees
6//
7// REPLACEMENT_STRING
8//
9// Copyright by Vlastimil Havran, 2007 - email to "vhavran AT seznam.cz"
10// Initial coding by Vlastimil Havran, February 2007
11
12// GOLEM library
13#include "ktb.h"
14#include "ktbai.h"
15#include "ktball.h"
16#include "ktbtrav.h"
17#include "Environment.h"
18#include "raypack.h"
19#include "Mesh.h"
20
21// standard headers
22#include <fstream>
23#include <iomanip>
24
25namespace GtpVisibilityPreprocessor {
26
27// Static data structures fo CKTBTraversal class
28GALIGN16 CKTBTraversal::SStackElem
29CKTBTraversal::stack[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
30
31CKTBTraversal::SStackElem2
32CKTBTraversal::stack2[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
33
34CKTBTraversal::SStackElem3
35CKTBTraversal::stack3[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
36
37CKTBTraversal::SStackElem4
38CKTBTraversal::stack4[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
39
40 
41// ------------------------------------------------------------------
42// CKTB class
43//
44// Binary Space Partitioning Tree, that handles bounded objects only
45// during intersection computation other way
46
47// default constructor
48CKTB::CKTB():
49  builtUp(false),
50  buildClass(NULL), traversalClass(NULL), sizeBuffer(0),buffer(0),
51  indexRead(0), indexWrite(0)
52{
53
54}
55
56// only for creating building class of CKTB tree
57CKTBAllocManPredecessor*
58CKTB::AllocBuildClass()
59{
60  CKTBAllocManPredecessor *bc = 0;
61  bool useArray = true;
62 
63  // this should be already initialised, but we want to be sure
64  if (useArray) {
65    // the implementation based on arrays
66    bc = new CKTBABuildUp(); // file ktbai.cpp
67  }
68  else {
69    // the implementation based on lists
70    // bc = new CKTBBuildUp(); // file ktbi.cpp
71  }
72   
73  if (bc == NULL) {
74    cerr << "The building class for KTB cannot be allocated"<< endl;
75    exit(3);
76  }
77
78  return bc;
79}
80
81void
82CKTB::AllocTraversalClass()
83{
84  if (traversalClass != NULL)
85    delete traversalClass;
86
87  traversalClass = NULL;
88
89  // if we use min boxes idea in the tree
90
91  Environment::GetSingleton()->GetBoolValue("BSP.minBoxes.use",
92                                            makeMinBoxes);
93  Environment::GetSingleton()->GetBoolValue("BSP.minBoxes.tight",
94                                            makeTightMinBoxes);
95  // the number of cells along ray path
96  const int size1D = 150;
97
98  cerr<<"th1"<<endl;
99  // $$JB tmp
100  size2D = 1;
101  cerr<<"size2d="<<size2D<<endl;
102  // initial index
103  index2D = 0;
104  AllocBuffer(size2D, size1D);
105  cerr<<"th2"<<endl;
106
107#if 0 
108  // -------------------------------------------------------------------
109  if (makeMinBoxes) {
110    // This class uses information about the box
111    // inside from which the ray starts from
112    traversalClass = new CKTBMinBoxesTraversal(size1D);
113  }
114  else {
115    // normal traversal always from root
116    traversalClass = new CKTBTraversal;
117  }
118#else
119  cerr<<"th3"<<endl;
120
121  traversalClass = new CKTBTraversal;
122#endif
123
124  assert(traversalClass);
125
126  return;
127}
128
129// default destructor
130CKTB::~CKTB()
131{
132  // Print the statistics
133  PrintStats();
134 
135  Remove();
136}
137
138void
139CKTB::Remove()
140{
141  if (buildClass) {
142    // DEBUG << "Deleting build class from CKTB" << endl;
143    buildClass->Remove();
144    delete buildClass;
145    buildClass = NULL;
146  }
147
148  if (traversalClass) {
149    delete traversalClass;
150    traversalClass = NULL;
151  }
152
153  return;
154}
155
156void
157CKTB::ProvideID(ostream& app)
158{
159  app << "#CASDS = CKTB - KD-tree for only bounded objects\n";
160  //app << (int)GetID() << "\n";
161 
162  //app << "#ActMaxDepth (Dreach)\tActual maximal depth of the KD-tree"
163  //    << " reached\n";
164  //app << world->_statistics->actMaxDepth << "\n";
165
166  ProvidePars(app);
167}
168
169void
170CKTB::ProvidePars(ostream& app)
171{
172  app << "#NumberOfObjects\t\tNumber of objects inside kd-tree\n";
173  app << countObjects << "\n";
174 
175  app << "#BBox\t\t\tSize of axis-aligned box of the whole scene\n"
176      << bbox.Max().x - bbox.Min().x << ","
177      << bbox.Max().y - bbox.Min().y << ","
178      << bbox.Max().z - bbox.Min().z << "\n";
179
180#if 0 
181  bool tempvar;
182  Environment::GetSingleton()->GetBoolValue("BSP.pruning", tempvar);
183  if (tempvar) {
184    app << "#BSP.pruning \t\tPruning of CKTB disabled/enabled\n";
185    app << tempvar << "\n";
186  }
187  app << "#BSP.constrMethod \tBuilding up method for KD-tree\n";
188#endif 
189
190  if (buildClass)
191    buildClass->ProvideID(app);
192
193  return;
194}
195
196void
197CKTB::PrintStats()
198{
199  if (traversalClass)
200    traversalClass->PrintStatsTR(cout);
201}
202
203// builds up CKTB tree
204void
205CKTB::BuildUp(const ObjectContainer &alist)
206{
207  cerr<<"KTB buildup\n";
208  Remove();
209
210  // Create the list of objects to be processed.
211  ObjectContainer *objlist = new ObjectContainer;
212
213  // The minimum size
214  bbox.Initialize();
215 
216  // Copy only finite (not invisible and bounded) objects from
217  // the original list to 'objlist'
218   
219  // copy the pointers to objects to the array
220  int i = 0;
221  AxisAlignedBox3 objbox; 
222  bool hasUnboundeds = false;
223  countObjects = 0;
224  for (ObjectContainer::iterator it = ((ObjectContainer*)&alist)->begin();
225       it != alist.end(); it++, i++) {
226    Intersectable* obj = *it;
227    objbox = (*it)->GetBox();
228    // invisible objects are not added - lights etc.
229    bbox.Include(objbox);
230    // This is a regular object, add it to the list
231    objlist->push_back(obj);
232  } // for
233   
234  // prepare building up for CKTB tree
235  //  BuildingUp(*objlist);
236  BuildingUp(*objlist, NULL, NULL, true);
237
238  cerr<<"KTB buildup3\n";
239
240  delete objlist;
241
242  return;
243}
244
245bool
246CKTB::CheckBoxes(ObjectContainer &objlist)
247{
248  // the minimum size of the box at any dimension
249  const float epsilon = Limits::Small * 5.0f;
250
251  for (ObjectContainer::iterator oi = objlist.begin();
252       oi != objlist.end(); oi++) {
253    AxisAlignedBox3 box = (*oi)->GetBox();
254    Vector3 diff = box.Diagonal();
255    for (int i = 0; i < 3; i++) {
256      float d = fabs(diff[i]);
257#if 0
258      if (d < epsilon) {
259        CObject3D &obj = **(oi);
260        cerr << "CKTB::CheckBoxes - the scene incorrectly prepared, "
261              << " the size of the box = " << d << " in dimension "
262              << i << " is" << " below threshold = " << epsilon << endl;
263        cerr << "object = " << (void*)(*oi) << " uniqueID = " <<
264          (*oi)->GetUniqueID() << " description = " << endl;
265        obj.Describe(cout, 1);
266        cerr << "----------" << endl;
267        abort();
268        return true; // error
269      }
270#else
271      if (d < epsilon) {
272        int size = objlist.size();
273        *oi = objlist[size-1];
274        objlist.resize(size-1);
275        oi--; // check this object as well
276      }     
277#endif
278    } // for i   
279  } // for all objecs
280
281  return false;
282}
283
284// builds up CKTB tree without unbounded objects. The 'boxToInclude
285// is a box that can be optionally given and the kd-tree constructed
286// must contain such a box. The 'boxToBoundObjects' when given, is
287// a box to which the objects boxes are bounded. This is used for special
288// cases such a multilevel kd-trees.
289void
290CKTB::BuildingUp(ObjectContainer& objlist,
291                 const AxisAlignedBox3 *boxToInclude,
292                 const AxisAlignedBox3 *boxToBoundObjects,
293                 bool verbose)
294{
295  // the number of objects for statistics purposes - it can be different
296  // from objlist->size() since objlist need not be initialized at all!
297  countObjects = objlist.size();
298
299  // compute the estimate for the kd-tree constructed this way
300  _expectedIntersectionCost = log((float)countObjects) / log(2.0f) + 2.0;
301 
302#ifdef _DEBUG
303  // check the flatness of the boxes for all objects
304  if (CheckBoxes(objlist)) {
305    cerr << "Problem with the size of the box for some object" << endl;
306    return;
307  }
308#endif // _DEBUG
309
310  cerr<<"hh2"<<endl;
311  // possibly remove the old building class
312  // and allocate the class for CKTB building up
313  if (buildClass)
314    delete buildClass; 
315  buildClass = AllocBuildClass();
316
317  cerr<<"hh3"<<endl;
318
319  // and for traversal
320  AllocTraversalClass();
321  cerr<<"hh4"<<endl;
322
323  if (boxToBoundObjects) {
324    // maximum box of the scene is given in advance
325    bbox = Intersect(bbox, *boxToBoundObjects);
326  }
327
328  // we can additionally include the user box
329  if (boxToInclude)
330    bbox.Include(*boxToInclude); 
331
332  cerr<<"hh5"<<endl;
333
334  // build up the CKTB tree and make setup for traversal
335  SKTBNodeT *rootNode =
336    buildClass->BuildUp(objlist, bbox, verbose);
337  cerr<<"hh6"<<endl;
338
339  traversalClass->Setup(bbox, rootNode);
340  cerr<<"hh7"<<endl;
341
342#ifdef _DEBUG
343  //traversalClass->AssignIDs();
344#endif
345  builtUp = true;
346
347#if 0 
348  // if to clean up the whole structure
349  bool pruning;
350  Environment::GetSingleton()->GetBoolValue("BSP.pruning", pruning);
351  if (pruning)
352    // only the objects whose surfaces intersects with the subdivision
353    PruneLeaves(); // cells are not pruned from the CKTB tree
354#endif
355}
356
357// functions that allows correctly traverse recursively allowing to have
358// the same traversal stack
359void
360CKTB::TraversalReset()
361{
362  assert(traversalClass);
363  traversalClass->ResetTraversalDepth();
364}
365
366// Allocate 2D buffer of pointers to the interior nodes
367void
368CKTB::AllocBuffer(int size2D, int size1Dv)
369{
370  int i, j;
371 
372  if (buffer) {
373    for (i=0; i < sizeBuffer; i++) {
374      delete [] buffer[i];
375    } // for
376    delete [] buffer;
377    buffer = 0;
378  }
379
380  sizeBuffer = size2D;
381  this->size1D = size1Dv;
382  buffer = new SKTBNodeT ** [sizeBuffer];
383  assert(buffer);
384  for (i=0; i < sizeBuffer; i++) {
385    buffer[i] = new SKTBNodeT* [size1D];
386    assert(buffer[i]);
387    // reset the array content
388    for (j = 0; j < size1D; j++) {
389      buffer[i][j] = 0;
390    }
391  } // for
392
393  return;
394}
395
396int
397CKTB::FindNearestI(const SimpleRay &ray)
398{
399  return traversalClass->FindNearestI(ray);     
400}
401
402#ifdef __SSE__
403// --------------------------------------------------------------
404// Ray packets
405void
406CKTB::FindNearestI(RayPacket2x2 &raypack)
407{
408  if (!makeMinBoxes)
409    raypack.SetOrigin(0); // min boxes are not used, we cannot use them here !
410  traversalClass->FindNearestI(raypack);
411}
412
413void
414CKTB::FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax)
415{
416  if (!makeMinBoxes)
417    raypack.SetOrigin(0); // min boxes are not used, we cannot use them here !
418  traversalClass->FindNearestI(raypack, boxmin, boxmax);
419}
420
421#endif // __SSE__
422 
423void
424CKTB::DeleteBuildClass()
425{
426  if (buildClass)
427    delete buildClass;
428  buildClass = NULL;
429}
430
431void
432CKTB::GatherStats(bool itself)
433{
434  // DEBUG << "CKTB::GatherStats called" << endl;
435  struct EDir {
436    SKTBNodeT *node;
437    int depth;
438    AxisAlignedBox3 bbox;
439  };
440  EDir stack[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
441  int stackTop = 0; // pointer to the stack
442  stack[stackTop].node = 0;
443  stack[stackTop].depth = 0;
444  stack[stackTop].bbox = bbox;
445  int tmpdir;
446#ifdef __TAGGED_KDR
447  int taggedLists = 0;
448#endif // __TAGGED_KDR
449 
450  /*
451  if (!BuiltUp) {
452    cerr << "Internal error: CASDS not built up. Giving up.\n" << flush;
453    abort();
454  }
455  */
456 
457  // average depth for all leaves
458  long avgLeafDepth = 0;
459  // for full leaves
460  long avgFullLeafDepth = 0;
461  // for empty leaves
462  long avgEmptyLeafDepth = 0;
463
464  // Surface areas  (divided by the area of the box)
465  // Surface area of leaves (empty + full)
466  double saLeaves = 0.f;
467  // Surface area of interior nodes
468  double saInteriorNodes = 0.f;
469  // Sum of surface area of (full) leaves multiplied by
470  // the number of objects in leaves
471  double sa_cntLeaves = 0.f;
472  // number of boxes enclosing tightly the objects
473  long int boxesMin = 0;
474  long int boxesMinX = 0;
475  long int boxesMinY = 0;
476  long int boxesMinZ = 0;
477  // the sum of depth of tight boxes
478  long int boxesMinDepth = 0;
479
480  // start from the root node
481  SKTBNodeT *curr = buildClass->GetRootNode();
482  // copy the box over the scene objects
483  AxisAlignedBox3 wbox = this->bbox;
484  int currDepth = 0;
485
486  if (buildClass->IsLeaf_(curr)) {
487    this->numElemCells++;
488    if (buildClass->IsEmptyLeaf_(curr)) {
489      this->numEmptyElemCells++;
490      AxisAlignedBox3 bwbox = this->bbox;
491      // Surface area for empty leaf
492      this->emptyVolume += bwbox.GetVolume();
493      saLeaves += bwbox.SurfaceArea();
494    }
495    else { // CKTB tree is single non-empty leaf
496      AxisAlignedBox3 bwbox = this->bbox;
497      this->nonEmptyVolume += bwbox.GetVolume();
498      ObjectContainer *olist = curr->objlist;
499      saLeaves += bwbox.SurfaceArea();
500      if (!olist) {
501        this->numSolidsInElemCells += olist->size();
502        this->actMaxListLen = olist->size();
503        // surface area for full leaf
504        sa_cntLeaves = bwbox.SurfaceArea() * (float)(olist->size());
505      }
506    }
507  }
508  else { // CKTB tree is not a single leaf
509    // now we access the interior node
510
511    // surface area for interior node
512    AxisAlignedBox3 bwbox = this->bbox;
513    // surface area for interior node
514    saInteriorNodes += bwbox.SurfaceArea();
515    this->numHierCells++;
516       
517    // traverse through whole CKTB tree
518    do {
519      CKTBAxes::Axes nodeType = buildClass->GetNodeType(curr);
520      if (nodeType == CKTBAxes::EE_Link) {
521        // just relink
522        curr = buildClass->GetLinkNode(curr);
523        // cout << "Link node was accessed" << endl;
524        continue;       
525      }
526     
527      if ( (nodeType == CKTBAxes::EE_X_axis)||
528           (nodeType == CKTBAxes::EE_Y_axis)||
529           (nodeType == CKTBAxes::EE_Z_axis)||
530           (nodeType == CKTBAxes::EE_X_axisBox)||
531           (nodeType == CKTBAxes::EE_Y_axisBox)||
532           (nodeType == CKTBAxes::EE_Z_axisBox)
533         ) {
534
535        // push onto the stack
536        AxisAlignedBox3 rightBox = bwbox;
537        float value = curr->splitPlane;
538        switch(nodeType) {
539          case CKTBAxes:: EE_X_axisBox: {
540            rightBox.SetMin(0, value);
541            bwbox.SetMax(0, value);
542            boxesMin++;
543            boxesMinX++;
544            boxesMinDepth += currDepth;
545            break;       
546          }
547          case CKTBAxes:: EE_X_axis: {
548            rightBox.SetMin(0, value);
549            bwbox.SetMax(0, value);
550            break;       
551          }
552          case CKTBAxes:: EE_Y_axisBox: {
553            rightBox.SetMin(0, value);
554            bwbox.SetMax(0, value);
555            boxesMin++;
556            boxesMinY++;
557            boxesMinDepth += currDepth;
558            break;       
559          }
560          case CKTBAxes:: EE_Y_axis: {
561            rightBox.SetMin(1, value);
562            bwbox.SetMax(1, value);
563            break;       
564          }
565          case CKTBAxes:: EE_Z_axisBox: {
566            rightBox.SetMin(0, value);
567            bwbox.SetMax(0, value);
568            boxesMin++;
569            boxesMinZ++;
570            boxesMinDepth += currDepth;
571            break;       
572          }
573          case CKTBAxes:: EE_Z_axis: {
574            rightBox.SetMin(2, value);
575            bwbox.SetMax(2, value);
576            break;       
577          }
578        } // switch
579     
580        stack[stackTop].node = buildClass->GetRight(curr);
581        stack[stackTop].depth = currDepth+1;
582        stack[stackTop].bbox = rightBox;
583        stackTop++;
584        // where to go
585        if ( (nodeType == CKTBAxes:: EE_X_axisBox)||
586             (nodeType == CKTBAxes:: EE_Y_axisBox)||
587             (nodeType == CKTBAxes:: EE_Z_axisBox) )
588          curr = buildClass->GetLeftMinBox(curr);
589        else
590          curr = buildClass->GetLeft(curr);
591        // the box was already set     
592        currDepth++;
593     
594        if (this->actMaxDepth < currDepth)
595          this->actMaxDepth = currDepth;
596
597        // surface area for interior node
598        saInteriorNodes += bwbox.SurfaceArea();
599        this->numHierCells++;
600
601        continue;
602      } // interior nodes
603
604      assert(nodeType == CKTBAxes::EE_Leaf);
605     
606      while ( (nodeType == CKTBAxes::EE_Leaf) && currDepth) {
607        this->numElemCells++;
608        avgLeafDepth += currDepth;
609
610        ObjectContainer *olist = buildClass->GetObjList(curr);
611       
612        // test to empty leaf
613        if (!olist) {
614          this->numEmptyElemCells++;
615          avgEmptyLeafDepth += currDepth;
616          this->emptyVolume += bwbox.GetVolume();
617          // Surface area for empty leaf
618          saLeaves += bwbox.SurfaceArea();
619        }
620        else {
621          // full leaf
622          this->nonEmptyVolume += bwbox.GetVolume();
623          avgFullLeafDepth += currDepth;
624          int length = olist->size();
625          this->numSolidsInElemCells += length;
626          // surface area for full leaf
627          saLeaves += bwbox.SurfaceArea();
628          sa_cntLeaves += bwbox.SurfaceArea() * (float)(olist->size());
629          if (this->actMaxListLen < length)
630            this->actMaxListLen = length;
631        }
632       
633        // traverse up the tree
634        stackTop--;
635        if (stackTop < 0)
636          goto FINISH;
637        // pop the node from the stack
638        curr = stack[stackTop].node;
639        currDepth = stack[stackTop].depth;
640
641        nodeType = buildClass->GetNodeType(curr);
642       
643      } // while is a leaf
644    }
645    while (stackTop >= 0);
646  } // either single leaf or tree
647
648FINISH:
649
650  cout << "BBox " << this->bbox << "\n";
651 
652#ifdef __TAGGED_KDR
653  DEBUGW << "Tagged lists = " << taggedLists << "\n";
654#endif // __TAGGED_KDR
655
656  cout << "#CntLeaves = \n" << this->numElemCells << "\n";
657  cout << "#AverageLeafDepth = \n"
658       << (float)avgLeafDepth/(float)this->numElemCells << "\n";
659  cout << "#CntFullLeaves = \n" << (this->numElemCells-this->numEmptyElemCells)
660        << "\n";
661  cout << "#AverageFullLeafDepth = \n"
662        << (float)avgFullLeafDepth/
663            (float)(this->numElemCells - this->numEmptyElemCells) << "\n";
664  cout << "#AverageEmptyLeafDepth = \n";
665  if (this->numEmptyElemCells)
666    cout << (float)avgEmptyLeafDepth / (float)this->numEmptyElemCells<<"\n";
667  else
668    cout << "undefined\n";
669
670  // Normalized the surface area
671  this->sumSurfaceAreaLeaves = saLeaves / wbox.SurfaceArea();
672  this->sumSurfaceAreaMULcntLeaves = sa_cntLeaves / wbox.SurfaceArea();
673  this->sumSurfaceAreaInteriorNodes = saInteriorNodes / wbox.SurfaceArea();
674
675  cout << "#SumSurfaceLeafArea = \n" << saLeaves << "\n";
676  cout << "#SumSurfaceLeafAreaMulCNT = \n" << sa_cntLeaves << "\n";
677  cout << "#NormSurfaceLeafArea = \n" << this->sumSurfaceAreaLeaves << "\n";
678  cout << "#NormSurfaceLeafAreaMulCNT = \n" << this->sumSurfaceAreaMULcntLeaves << "\n";
679  cout << "#SurfaceAreaInteriorNodes = \n" << this->sumSurfaceAreaInteriorNodes<<"\n"; 
680  cout << "#MinBoxesCount = \n" << boxesMin << "\n";
681  cout << "#MinBoxesXCount = \n" << boxesMinX << "\n";
682  cout << "#MinBoxesYCount = \n" << boxesMinY << "\n";
683  cout << "#MinBoxesZCount = \n" << boxesMinZ << "\n";
684  if (boxesMin)
685    cout << "#AverageMinBoxesDepth = \n"
686          << (float)boxesMinDepth/(float)boxesMin << "\n";
687
688  long int memUsed = 0;
689#ifdef _KTB8Bytes
690  memUsed += this->numHierCells*8;
691  memUsed += (this->numElemCells-this->numEmptyElemCells)*8;
692#ifdef _SHORT_FORM_MINBOX
693  memUsed += boxesMin * (sizeof(SBBox) + 2*8);
694#else
695  memUsed += boxesMin * (5*8);
696#endif
697#else // _KTB8Bytes
698  memUsed += this->numHierCells*12;
699  memUsed += (this->numElemCells-this->numEmptyElemCells)*12;
700#ifdef _SHORT_FORM_MINBOX
701  memUsed += boxesMin * (sizeof(SBBox) + 2*12);
702#else
703  memUsed += boxesMin * (4*12);
704#endif
705#endif // _KTB8Bytes
706
707  // The references to objects
708  memUsed += this->numSolidsInElemCells * sizeof(Intersectable*);
709  memUsed += (this->numElemCells-this->numEmptyElemCells) *
710    sizeof(ObjectContainer);
711  cout << "#MemUsedKBB = \n" << memUsed << "\n";
712   
713  return;
714}
715
716
717void CKTB::ExportBinLeaf(OUT_STREAM &stream, SKTBNodeT *leaf)
718{
719#define TYPE_LEAF -3
720  int type = TYPE_LEAF;
721  if (leaf->objlist == 0) {
722    // empty leaf
723    int size = 0;
724    stream.write(reinterpret_cast<char *>(&type), sizeof(int));
725    stream.write(reinterpret_cast<char *>(&size), sizeof(int));   
726    return;
727  }
728 
729  ObjectContainer::const_iterator it, it_end = leaf->objlist->end(); 
730  int size = (int)leaf->objlist->size();
731 
732  stream.write(reinterpret_cast<char *>(&type), sizeof(int));
733  stream.write(reinterpret_cast<char *>(&size), sizeof(int));
734 
735  for (it = leaf->objlist->begin(); it != it_end; ++ it)
736  {     
737    Intersectable *obj = *it;
738    int id = obj->mId;         
739     
740    //stream.write(reinterpret_cast<char *>(&origin), sizeof(Vector3));
741    stream.write(reinterpret_cast<char *>(&id), sizeof(int));
742  }
743}
744
745
746inline static bool ilt(Intersectable *obj1, Intersectable *obj2)
747{
748  return obj1->mId < obj2->mId;
749}
750
751 
752SKTBNodeT*
753CKTB::ImportBinLeaf(IN_STREAM &stream,
754                    SKTBNodeT *parent,
755                    const ObjectContainer &objects)
756{
757  int leafId = TYPE_LEAF;
758  int objId = leafId;
759  int size;
760 
761  stream.read(reinterpret_cast<char *>(&size), sizeof(int));
762  if (size == 0) {
763    // alloc empty leaf -- ?????????? I am not sure if this works !!!
764    // since for
765    SKTBNodeT* leaf = buildClass->AllocLeaf(0);
766    return leaf;
767  }
768 
769  MeshInstance dummyInst(NULL);
770  SKTBNodeT* leaf = buildClass->AllocLeaf(size);
771
772  ObjectContainer *newobjlist = new ObjectContainer;
773 
774  // read object ids
775  // note: this can also be done geometrically
776  for (int i = 0; i < size; ++ i)
777  {     
778    stream.read(reinterpret_cast<char *>(&objId), sizeof(int));
779    dummyInst.SetId(objId);
780     
781    ObjectContainer::const_iterator oit =
782      lower_bound(objects.begin(), objects.end(), (Intersectable *)&dummyInst, ilt);
783     
784    if ((oit != objects.end()) && ((*oit)->GetId() == objId))
785      newobjlist->push_back(*oit);
786    else
787      Debug << "error: object with id " << objId << " does not exist" << endl;
788  } // for
789
790  buildClass->SetFullLeaf(leaf, newobjlist);
791 
792  return leaf;
793}
794
795
796void CKTB::ExportBinInterior(OUT_STREAM &stream, SKTBNodeT *interior)
797{
798#define TYPE_INTERIOR -2
799  int interiorid = TYPE_INTERIOR;
800  stream.write(reinterpret_cast<char *>(&interiorid), sizeof(int));
801
802  int axis = (int)(buildClass->GetNodeType(interior));
803  float pos = buildClass->GetSplitValue(interior);
804
805  stream.write(reinterpret_cast<char *>(&axis), sizeof(int));
806  stream.write(reinterpret_cast<char *>(&pos), sizeof(float));
807}
808
809
810SKTBNodeT *
811CKTB::ImportBinInterior(IN_STREAM  &stream, SKTBNodeT *parent)
812{
813  int axis;
814  float pos;
815
816  stream.read(reinterpret_cast<char *>(&axis), sizeof(int));
817  stream.read(reinterpret_cast<char *>(&pos), sizeof(float));
818
819  SKTBNodeT *interiorNode =
820    buildClass->AllocInteriorNode(axis, pos, 0, 0);
821       
822  return interiorNode;
823}
824
825
826bool CKTB::ExportBinTree(const string &filename)
827{
828  OUT_STREAM stream(filename.c_str(), OUT_BIN_MODE);
829       
830  if (!stream.is_open()) return false;
831
832  // DEBUG << "CKTB::GatherStats called" << endl;
833  struct EDir {
834    SKTBNodeT *node;
835    int depth;
836    AxisAlignedBox3 bbox;
837  };
838  EDir stack[CKTBTraversal::MAX_TRAVERSAL_HEIGHT];
839  int stackTop = 0; // pointer to the stack
840  stack[stackTop].node = 0;
841  stack[stackTop].depth = 0;
842  stack[stackTop].bbox = bbox;
843  int tmpdir;
844 
845  // export binary version of mesh
846  queue<SKTBNodeT *> tStack;
847  // start from the root node
848  SKTBNodeT *currNode = buildClass->GetRootNode();
849
850  // copy the box over the scene objects
851  AxisAlignedBox3 bwbox = this->bbox;
852  int currDepth = 0; 
853
854  // traverse through whole CKTB tree
855  do {
856    CKTBAxes::Axes nodeType = buildClass->GetNodeType(currNode);
857    if (nodeType == CKTBAxes::EE_Link) {
858      // just relink
859      currNode = buildClass->GetLinkNode(currNode);
860      // cout << "Link node was accessed" << endl;
861      continue;
862    }
863     
864    if ( (nodeType == CKTBAxes::EE_X_axis)||
865         (nodeType == CKTBAxes::EE_Y_axis)||
866         (nodeType == CKTBAxes::EE_Z_axis)||
867         (nodeType == CKTBAxes::EE_X_axisBox)||
868         (nodeType == CKTBAxes::EE_Y_axisBox)||
869         (nodeType == CKTBAxes::EE_Z_axisBox)
870       ) {
871     
872      // push onto the stack
873      AxisAlignedBox3 rightBox = bwbox;
874      float value = currNode->splitPlane;
875      switch(nodeType) {
876        case CKTBAxes:: EE_X_axisBox: {
877          rightBox.SetMin(0, value);
878          bwbox.SetMax(0, value);
879          break;         
880        }
881        case CKTBAxes:: EE_X_axis: {
882          rightBox.SetMin(0, value);
883          bwbox.SetMax(0, value);
884          break;         
885        }
886        case CKTBAxes:: EE_Y_axisBox: {
887          rightBox.SetMin(0, value);
888          bwbox.SetMax(0, value);
889          break;         
890        }
891        case CKTBAxes:: EE_Y_axis: {
892          rightBox.SetMin(1, value);
893          bwbox.SetMax(1, value);
894          break;         
895        }
896        case CKTBAxes:: EE_Z_axisBox: {
897          rightBox.SetMin(0, value);
898          bwbox.SetMax(0, value);
899          break;         
900        }
901        case CKTBAxes:: EE_Z_axis: {
902          rightBox.SetMin(2, value);
903          bwbox.SetMax(2, value);
904          break;         
905        }
906      } // switch
907
908      // Exporting interior node
909      ExportBinInterior(stream, currNode);
910     
911      stack[stackTop].node = buildClass->GetRight(currNode);
912      stack[stackTop].depth = currDepth + 1;
913      stack[stackTop].bbox = rightBox;
914      stackTop++;
915      // where to go
916      if ( (nodeType == CKTBAxes:: EE_X_axisBox)||
917           (nodeType == CKTBAxes:: EE_Y_axisBox)||
918           (nodeType == CKTBAxes:: EE_Z_axisBox) )
919        currNode = buildClass->GetLeftMinBox(currNode);
920      else
921        currNode = buildClass->GetLeft(currNode);
922      // the box was already set
923      currDepth++;
924     
925      continue;
926    } // interior nodes
927
928    assert(nodeType == CKTBAxes::EE_Leaf);
929     
930    while ( (nodeType == CKTBAxes::EE_Leaf) && currDepth) {
931      ObjectContainer *olist = buildClass->GetObjList(currNode);
932      // Exporting leaf node
933      ExportBinLeaf(stream, static_cast<SKTBNodeT *>(currNode));
934       
935      // traverse up the tree
936      stackTop--;
937      if (stackTop < 0)
938        goto FINISH;
939      // pop the node from the stack
940      currNode = stack[stackTop].node;
941      currDepth = stack[stackTop].depth;
942      bwbox = stack[stackTop].bbox;
943     
944      nodeType = buildClass->GetNodeType(currNode);
945       
946    } // while is a leaf
947  }
948  while (stackTop >= 0);
949
950FINISH:
951  // close the stream
952  stream.close();
953 
954  return true;
955}
956
957#if 0
958KdNode *KdTree::ImportNextNode(IN_STREAM &stream,
959                               KdInterior *parent,
960                               const ObjectContainer &objects)
961{
962        int nodeType;
963        stream.read(reinterpret_cast<char *>(&nodeType), sizeof(int));
964
965        if (nodeType == TYPE_LEAF)
966                return ImportBinLeaf(stream, static_cast<KdInterior *>(parent), objects);
967
968        if (nodeType == TYPE_INTERIOR)
969                return ImportBinInterior(stream, static_cast<KdInterior *>(parent));
970
971        Debug << "error! loading failed!" << endl;
972        return NULL;
973}
974
975
976bool KdTree::ImportBinTree(const string &filename, ObjectContainer &objects)
977{
978  // export binary version of mesh
979  queue<TraversalData> tStack;
980  IN_STREAM stream(filename.c_str(), IN_BIN_MODE);
981 
982  if (!stream.is_open()) return false;
983 
984  // sort objects by their id
985  //    if (!is_sorted(objects.begin(), objects.end(), ilt))
986  sort(objects.begin(), objects.end(), ilt);
987 
988  mBox.Initialize();
989  ObjectContainer::const_iterator oit, oit_end = objects.end();
990 
991  ///////////////////////////
992  //-- compute bounding box of object space
993 
994  for (oit = objects.begin(); oit != oit_end; ++ oit)
995  {
996    const AxisAlignedBox3 box = (*oit)->GetBox();
997    mBox.Include(box);
998  }
999 
1000  // hack: we make a new root
1001  DEL_PTR(mRoot);
1002 
1003  mRoot = ImportNextNode(stream, NULL, objects);
1004 
1005  tStack.push(TraversalData(mRoot, mBox, 0));
1006  mStat.Reset();
1007  mStat.nodes = 1;
1008 
1009  while(!tStack.empty())
1010  {
1011    TraversalData tData = tStack.front();
1012    tStack.pop();
1013   
1014    KdNode *node = tData.mNode;
1015   
1016    if (!node->IsLeaf())
1017    {
1018      mStat.nodes += 2;
1019     
1020      //Debug << "i" ;
1021      KdInterior *interior = static_cast<KdInterior *>(node);
1022      interior->mBox = tData.mBox;
1023     
1024      KdNode *front = ImportNextNode(stream, interior, objects);
1025      KdNode *back = ImportNextNode(stream, interior, objects);
1026     
1027      interior->SetupChildLinks(back, front);
1028     
1029      ++ mStat.splits[interior->mAxis];
1030     
1031      // compute new bounding box
1032      AxisAlignedBox3 frontBox, backBox;
1033     
1034      tData.mBox.Split(interior->mAxis,
1035                       interior->mPosition,
1036                       frontBox,
1037                       backBox);
1038     
1039      tStack.push(TraversalData(front, frontBox, tData.mDepth + 1));                   
1040      tStack.push(TraversalData(back, backBox, tData.mDepth + 1));
1041    }
1042    else
1043    {
1044      EvaluateLeafStats(tData);
1045      //cout << "l";
1046    }
1047  }
1048
1049  float area = GetBox().SurfaceArea()*mKdPvsArea;
1050 
1051  SetPvsTerminationNodes(area);
1052 
1053  Debug << mStat << endl;
1054 
1055  return true;
1056}
1057#endif
1058
1059
1060void
1061CKTB::GatherPostStats()
1062{
1063
1064}
1065
1066void*
1067CKTB::Locate(const Vector3 &loc)
1068{
1069  return (void*)(traversalClass->Locate(loc));
1070}
1071
1072
1073} // namespace
Note: See TracBrowser for help on using the repository browser.