source: trunk/VUT/GtpVisibilityPreprocessor/src/VssTree.h @ 372

Revision 372, 14.6 KB checked in by bittner, 19 years ago (diff)

preparation for vss preprocessor. converted all .cpp and .h to dos new line format

Line 
1// ================================================================
2// $Id$
3// ****************************************************************
4//
5// Initial coding by
6/**
7   @author Jiri Bittner
8*/
9
10#ifndef __VSSTREE_H__
11#define __VSSTREE_H__
12
13// Standard headers
14#include <iomanip>
15#include <vector>
16#include <functional>
17#include <stack>
18
19
20// User headers
21#include "VssRay.h"
22#include "AxisAlignedBox3.h"
23
24
25#define USE_KDNODE_VECTORS 1
26#define _RSS_STATISTICS
27#define _RSS_TRAVERSAL_STATISTICS
28
29
30#include "Statistics.h"
31
32// --------------------------------------------------------------
33// Static statistics for kd-tree search
34// --------------------------------------------------------------
35class VssStatistics :
36  public StatisticsBase
37{
38public: 
39  // total number of nodes
40  int nodes;
41  // number of splits along each of the axes
42  int splits[7];
43  // totals number of rays
44  int rays;
45  // total number of query domains
46  int queryDomains;
47  // total number of ray references
48  int rayRefs;
49  // refs in non empty leafs
50  int rayRefsNonZeroQuery;
51  // total number of query references
52  int queryDomainRefs;
53  // nodes with zero queries
54  int zeroQueryNodes;
55  // max depth nodes
56  int maxDepthNodes;
57  // max depth nodes
58  int minCostNodes;
59  // max number of rays per node
60  int maxRayRefs;
61  // number of dynamically added ray refs
62  int addedRayRefs;
63  // number of dynamically removed ray refs
64  int removedRayRefs;
65 
66  // Constructor
67  VssStatistics() {
68    Reset();
69  }
70
71  int Nodes() const {return nodes;}
72  int Interior() const { return nodes/2; }
73  int Leaves() const { return (nodes/2) + 1; }
74
75  void Reset() {
76    nodes = 0;
77    for (int i=0; i<7; i++)
78      splits[i] = 0;
79    rays = queryDomains = 0;
80    rayRefs = rayRefsNonZeroQuery = queryDomainRefs = 0;
81    zeroQueryNodes = 0;
82    maxDepthNodes = 0;
83    minCostNodes = 0;
84    maxRayRefs = 0;
85    addedRayRefs = removedRayRefs = 0;
86  }
87
88 
89  void
90  Print(ostream &app) const;
91
92  friend ostream &operator<<(ostream &s, const VssStatistics &stat) {
93    stat.Print(s);
94    return s;
95  }
96 
97};
98
99
100// --------------------------------------------------------------
101// For sorting rays
102// --------------------------------------------------------------
103struct  SSortableEntry
104{
105  enum EType {
106    ERayMin,
107    ERayMax
108  };
109
110  int type;
111  float value;
112  void *data;
113 
114  SSortableEntry() {}
115  SSortableEntry(const int t, const float v, void *d):type(t),
116                                                                                                                                                                                                                        value(v),
117                                                      data(d) {}
118       
119  friend bool operator<(const SSortableEntry &a, const SSortableEntry &b) {
120    return a.value < b.value;
121  }
122};
123
124
125class VssTreeInterior;
126
127
128// --------------------------------------------------------------
129// KD-tree node - abstract class
130// --------------------------------------------------------------
131class VssTreeNode
132{
133public:
134
135#define USE_FIXEDPOINT_T 1
136
137struct RayInfo
138{
139        // pointer to the actual ray
140        VssRay *mRay;
141       
142        // endpoints  - do we need them?
143#if USE_FIXEDPOINT_T
144        short mMinT, mMaxT;
145#else
146        float mMinT, mMaxT;
147#endif
148       
149        RayInfo():mRay(NULL) {}
150       
151        RayInfo(VssRay *r):mRay(r), mMinT(0),
152#if USE_FIXEDPOINT_T
153#define FIXEDPOINT_ONE 0x7FFE
154                                                                                                //                        mMaxT(0xFFFF)
155                                                                                                                                                        mMaxT(FIXEDPOINT_ONE)
156#else
157                mMaxT(1.0f)
158#endif
159        {}
160       
161        RayInfo(VssRay *r,
162                                                                                const float _min,
163                                                                                const float _max
164                                                                                ):mRay(r) {
165                SetMinT(_min);
166                SetMaxT(_max);
167        }
168       
169        RayInfo(VssRay *r,
170                                                                                const short _min,
171                                                                                const float _max
172                                                                                ):mRay(r), mMinT(_min) {
173                SetMaxT(_max);
174        }
175       
176        RayInfo(VssRay *r,
177                                                                                const float _min,
178                                                                                const short _max
179                                                                                ):mRay(r), mMaxT(_max) {
180                SetMinT(_min);
181        }
182       
183        friend bool operator<(const RayInfo &a, const RayInfo &b) {
184                return a.mRay < b.mRay;
185        }
186 
187       
188        float ExtrapOrigin(const int axis) const {
189                return mRay->GetOrigin(axis) + GetMinT()*mRay->GetDir(axis);
190        }
191       
192        float ExtrapTermination(const int axis) const {
193                return mRay->GetOrigin(axis) + GetMaxT()*mRay->GetDir(axis);
194        }
195       
196#if USE_FIXEDPOINT_T
197        float GetMinT () const { return mMinT/(float)(FIXEDPOINT_ONE); }
198        float GetMaxT () const { return mMaxT/(float)(FIXEDPOINT_ONE); }
199       
200        void SetMinT (const float t) {
201                mMinT = (short) (t*(float)(FIXEDPOINT_ONE));
202        }
203       
204        void SetMaxT (const float t) {
205                mMaxT = (short) (t*(float)(FIXEDPOINT_ONE));
206                mMaxT++;
207                //      if (mMaxT!=0xFFFF)
208                //      mMaxT++;
209        }
210#else
211        float GetMinT () const { return mMinT; }
212        float GetMaxT () const { return mMaxT; }
213       
214        void SetMinT (const float t) { mMinT = t; }
215        void SetMaxT (const float t) { mMaxT = t; }
216#endif
217};
218
219
220        typedef vector<RayInfo> RayInfoContainer;
221       
222  enum { EInterior, ELeaf };
223
224  /////////////////////////////////
225  // The actual data goes here
226 
227  // link to the parent
228  VssTreeInterior *parent;
229
230  enum {SPLIT_X=0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
231 
232  // splitting axis
233  char axis;
234       
235  // depth
236  unsigned char depth;
237 
238  //  short depth;
239  //
240  /////////////////////////////////
241 
242  inline VssTreeNode(VssTreeInterior *p);
243
244 
245  virtual ~VssTreeNode() {};
246  virtual int Type() const  = 0;
247 
248
249  bool IsLeaf() const { return axis == -1; }
250 
251  virtual void Print(ostream &s) const = 0;
252
253  virtual int GetAccessTime() {
254    return 0x7FFFFFF;
255  }
256
257 
258       
259};
260
261// --------------------------------------------------------------
262// KD-tree node - interior node
263// --------------------------------------------------------------
264class VssTreeInterior :
265  public VssTreeNode
266{
267public:
268  // plane in local modelling coordinates
269  float position;
270
271  // pointers to children
272  VssTreeNode *back, *front;
273
274  // the bbox of the node
275  AxisAlignedBox3 bbox;
276
277  // the bbox of the node
278  AxisAlignedBox3 dirBBox;
279 
280  // data for caching
281  long accesses;
282  long lastAccessTime;
283 
284  VssTreeInterior(VssTreeInterior *p):VssTreeNode(p),
285                                        back(NULL),
286                                        front(NULL),
287                                        accesses(0),
288                                        lastAccessTime(-1)
289  { }
290
291  virtual int GetAccessTime() {
292    return lastAccessTime;
293  }
294
295  void SetupChildLinks(VssTreeNode *b, VssTreeNode *f) {
296    back = b;
297    front = f;
298    b->parent = f->parent = this;
299  }
300
301  void ReplaceChildLink(VssTreeNode *oldChild, VssTreeNode *newChild) {
302    if (back == oldChild)
303      back = newChild;
304    else
305      front = newChild;
306  }
307
308  virtual int Type() const  { return EInterior; }
309 
310  virtual ~VssTreeInterior() {
311    if (back)
312      delete back;
313    if (front)
314      delete front;
315  }
316 
317  virtual void Print(ostream &s) const {
318    if (axis == 0)
319      s<<"x ";
320    else
321      if (axis == 1)
322        s<<"y ";
323      else
324        s<<"z ";
325    s<<position<<" ";
326    back->Print(s);
327    front->Print(s);
328  }
329
330 
331  int ComputeRayIntersection(const RayInfo &rayData,
332                                                                                                                 float &t
333                                                                                                                 ) {
334               
335    // intersect the ray with the plane
336    float denom = rayData.mRay->GetDir(axis);
337   
338    if (fabs(denom) < 1e-20)
339      //if (denom == 0.0f)
340      return (rayData.mRay->GetOrigin(axis) > position) ? 1 : -1;
341   
342    t = (position - rayData.mRay->GetOrigin(axis))/denom;
343
344    if (t < rayData.GetMinT())
345      return (denom > 0) ? 1 : -1;
346
347    if (t > rayData.GetMaxT())
348      return (denom > 0) ? -1 : 1;
349   
350    return 0;
351  }
352
353};
354
355
356// --------------------------------------------------------------
357// KD-tree node - leaf node
358// --------------------------------------------------------------
359class VssTreeLeaf :
360  public VssTreeNode
361{
362public:
363  static int mailID;
364  int mailbox;
365 
366  RayInfoContainer rays;
367
368 
369  VssTreeLeaf(VssTreeInterior *p, const int n):VssTreeNode(p), rays() {
370    rays.reserve(n);
371  }
372 
373  virtual ~VssTreeLeaf() { }
374
375  virtual int Type() const  { return ELeaf; }
376
377  virtual void Print(ostream &s) const {
378    s<<endl<<"L: r="<<rays.size()<<endl;
379  };
380 
381  void AddRay(const RayInfo &data) {
382    rays.push_back(data);
383    data.mRay->Ref();
384  }
385
386  void Mail() { mailbox = mailID; }
387  static void NewMail() { mailID++; }
388  bool Mailed() const { return mailbox == mailID; }
389 
390  bool Mailed(const int mail) {
391    return mailbox >= mailID + mail;
392  }
393
394};
395
396// Inline functions
397inline
398VssTreeNode::VssTreeNode(VssTreeInterior *p):
399  parent(p), axis(-1), depth(p ? p->depth + 1 : 0) {}
400
401
402
403// ---------------------------------------------------------------
404// Main LSDS search class
405// ---------------------------------------------------------------
406class VssTree
407{
408  struct TraversalData
409  { 
410    VssTreeNode *node;
411    AxisAlignedBox3 bbox;
412    int depth;
413    float priority;
414   
415    TraversalData() {}
416
417    TraversalData(VssTreeNode *n, const float p):
418      node(n), priority(p)
419    {}
420
421    TraversalData(VssTreeNode *n,
422                   const AxisAlignedBox3 &b,
423                   const int d):
424      node(n), bbox(b), depth(d) {}
425   
426               
427    // comparator for the
428    struct less_priority : public
429    binary_function<const TraversalData, const TraversalData, bool> {
430                       
431      bool operator()(const TraversalData a, const TraversalData b) {
432                                return a.priority < b.priority;
433      }
434     
435    };
436
437    //    ~TraversalData() {}
438    //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
439   
440    friend bool operator<(const TraversalData &a,
441                                                                                                        const TraversalData &b) {
442      //      return a.node->queries.size() < b.node->queries.size();
443      VssTreeLeaf *leafa = (VssTreeLeaf *) a.node;
444      VssTreeLeaf *leafb = (VssTreeLeaf *) b.node;
445      //      return leafa->rays.size()*a.bbox.GetVolume() < leafb->rays.size()*b.bbox.GetVolume();
446      return
447                                leafa->rays.size()*a.bbox.GetVolume()
448                                <
449                                leafb->rays.size()*b.bbox.GetVolume();
450    }
451  };
452 
453  // simplified data for ray traversal only...
454
455  struct RayTraversalData {
456   
457    VssTreeNode::RayInfo rayData;
458    VssTreeNode *node;
459   
460    RayTraversalData() {}
461    RayTraversalData(VssTreeNode *n,
462                                                                                 const VssTreeNode::RayInfo &data):
463      rayData(data), node(n) {}
464  };
465       
466public:
467  /////////////////////////////
468  // The core pointer
469  VssTreeNode *root;
470 
471  /////////////////////////////
472  // Basic properties
473
474  // total number of nodes of the tree
475  int nodes;
476  // axis aligned bounding box of the scene
477  AxisAlignedBox3 bbox;
478
479  // axis aligned bounding box of directions
480  AxisAlignedBox3 dirBBox;
481 
482  /////////////////////////////
483  // Construction parameters
484
485  // epsilon used for the construction
486  float epsilon;
487
488  // ratio between traversal and intersection costs
489  float ct_div_ci;
490  // max depth of the tree
491  int termMaxDepth;
492  // minimal cost of the node to still get subdivided
493  int termMinCost;
494  // minimal ratio of the volume of the cell and the query volume
495  float termMinSize;
496
497  // minimal cost imporvement to subdivide a node
498  float maxCostRatio;
499 
500  // randomized construction
501  bool randomize;
502
503  // type of the splitting to use fo rthe tree construction
504  enum {ESplitRegular, ESplitVolume, ESplitQueries };
505  int splitType;
506       
507  // maximal size of the box on which the refdir splitting can be performed
508  // (relative to the scene bbox
509  float refDirBoxMaxSize;
510 
511  // maximum alovable memory in MB
512  float maxTotalMemory;
513
514  // maximum alovable memory for static kd tree in MB
515  float maxStaticMemory;
516
517  // this is used during the construction depending
518  // on the type of the tree and queries...
519  float maxMemory;
520
521
522  // minimal acess time for collapse
523  int accessTimeThreshold;
524
525        // minimal depth at which to perform collapse
526  int minCollapseDepth;
527
528 
529  // reusable array of split candidates
530  vector<SSortableEntry> *splitCandidates;
531  /////////////////////////////
532
533        VssStatistics stat;
534       
535 
536  VssTree();
537  virtual ~VssTree();
538
539  virtual void
540  Construct(
541                                                VssRayContainer &rays,
542                                                const bool onlyStaticPart
543                                                );
544       
545  // incemental construction
546  virtual void UpdateRays(VssRayContainer &remove,
547                                                                                                        VssRayContainer &add
548                                                                                                        );
549       
550 
551       
552  VssTreeNode *
553  Locate(const Vector3 &v);
554       
555  VssTreeNode *
556  SubdivideNode(VssTreeLeaf *leaf,
557                                                                const AxisAlignedBox3 &box,
558                                                                AxisAlignedBox3 &backBox,
559                                                                AxisAlignedBox3 &frontBox
560                                                                );
561       
562  VssTreeNode *
563  Subdivide(const TraversalData &tdata);
564       
565  int
566  SelectPlane(VssTreeLeaf *leaf,
567              const AxisAlignedBox3 &box,
568              float &position
569              );
570
571  void
572  SortSplitCandidates(
573                                                                                        VssTreeLeaf *node,
574                                                                                        const int axis
575                                                                                        );
576       
577 
578  // return memory usage in MB
579  float GetMemUsage() const {
580    return
581      (sizeof(VssTree) +
582       stat.Leaves()*sizeof(VssTreeLeaf) +
583       stat.Interior()*sizeof(VssTreeInterior) +
584       stat.rayRefs*sizeof(VssTreeNode::RayInfo))/(1024.0f*1024.0f);
585  }
586       
587  float GetRayMemUsage() const {
588    return
589      stat.rays*(sizeof(VssRay))/(1024.0f*1024.0f);
590  }
591 
592
593  AxisAlignedBox3 GetBBox(const VssTreeNode *node) {
594    if (node->parent == NULL)
595      return bbox;
596
597    if (!node->IsLeaf())
598      return ((VssTreeInterior *)node)->bbox;
599
600    if (node->parent->axis >= 3)
601      return node->parent->bbox;
602     
603    AxisAlignedBox3 box(node->parent->bbox);
604    if (node->parent->front == node)
605      box.SetMin(node->parent->axis, node->parent->position);
606    else
607      box.SetMax(node->parent->axis, node->parent->position);
608    return box;
609  }
610
611  AxisAlignedBox3 GetDirBBox(const VssTreeNode *node) {
612
613    if (node->parent == NULL)
614      return dirBBox;
615   
616    if (!node->IsLeaf() )
617      return ((VssTreeInterior *)node)->dirBBox;
618
619    if (node->parent->axis < 3)
620      return node->parent->dirBBox;
621   
622    AxisAlignedBox3 dBBox(node->parent->dirBBox);
623
624    if (node->parent->front == node)
625      dBBox.SetMin(node->parent->axis - 3, node->parent->position);
626    else
627      dBBox.SetMax(node->parent->axis - 3, node->parent->position);
628    return dBBox;
629  }
630 
631  int
632  ReleaseMemory(const int time);
633
634  int
635  CollapseSubtree(VssTreeNode *node, const int time);
636
637  void
638  CountAccess(VssTreeInterior *node, const long time) {
639    node->accesses++;
640    node->lastAccessTime = time;
641  }
642
643  VssTreeNode *
644  SubdivideLeaf(
645                                                                VssTreeLeaf *leaf,
646                                                                const float SAThreshold
647                                                                );
648
649  void
650  RemoveRay(VssRay *ray,
651                                                vector<VssTreeLeaf *> *affectedLeaves,
652                                                const bool removeAllScheduledRays
653                                                );
654
655  void
656  AddRay(VssRay *ray);
657       
658  void
659  TraverseInternalNode(
660                                                                                         RayTraversalData &data,
661                                                                                         stack<RayTraversalData> &tstack);
662
663        void
664  EvaluateLeafStats(const TraversalData &data);
665
666};
667
668
669#endif // __LSDS_KDTREE_H__
670
Note: See TracBrowser for help on using the repository browser.