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

Revision 2603, 27.5 KB checked in by bittner, 17 years ago (diff)

sse disabled for hr

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