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

Revision 435, 19.4 KB checked in by bittner, 19 years ago (diff)

default.env cleanup

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#include "Ray.h"
32
33// --------------------------------------------------------------
34// Static statistics for kd-tree search
35// --------------------------------------------------------------
36class VssStatistics :
37  public StatisticsBase
38{
39public: 
40  // total number of nodes
41  int nodes;
42  // number of splits along each of the axes
43  int splits[7];
44  // totals number of rays
45  int rays;
46        // initial size of the pvs
47  int initialPvsSize;
48        // total number of query domains
49  int queryDomains;
50  // total number of ray references
51  int rayRefs;
52
53        // max depth nodes
54  int maxDepthNodes;
55  // max depth nodes
56  int minPvsNodes;
57  int minRaysNodes;
58        // max ray contribution nodes
59  int maxRayContribNodes;
60        // max depth nodes
61  int minSizeNodes;
62  int maxCostRatioNodes;
63
64  // max number of rays per node
65  int maxRayRefs;
66  // number of dynamically added ray refs
67  int addedRayRefs;
68  // number of dynamically removed ray refs
69  int removedRayRefs;
70 
71  // Constructor
72  VssStatistics() {
73    Reset();
74  }
75
76  int Nodes() const {return nodes;}
77  int Interior() const { return nodes/2; }
78  int Leaves() const { return (nodes/2) + 1; }
79
80  void Reset() {
81    nodes = 0;
82    for (int i=0; i<7; i++)
83      splits[i] = 0;
84    rays = queryDomains = 0;
85    rayRefs = 0;
86    maxDepthNodes = 0;
87    minPvsNodes = 0;
88    minRaysNodes = 0;
89    maxRayRefs = 0;
90    addedRayRefs = removedRayRefs = 0;
91                initialPvsSize = 0;
92                maxRayContribNodes = 0;
93                minSizeNodes = 0;
94                maxCostRatioNodes = 0;
95  }
96
97 
98  void
99  Print(ostream &app) const;
100
101  friend ostream &operator<<(ostream &s, const VssStatistics &stat) {
102    stat.Print(s);
103    return s;
104  }
105 
106};
107
108
109// --------------------------------------------------------------
110// For sorting rays
111// --------------------------------------------------------------
112struct  SortableEntry
113{
114  enum EType {
115    ERayMin,
116    ERayMax
117  };
118
119  int type;
120  float value;
121  void *data;
122 
123  SortableEntry() {}
124  SortableEntry(const int t, const float v, void *d):type(t),
125                                                                                                                                                                                                                 value(v),
126                                                                                                                                                                                                                 data(d) {}
127       
128  friend bool operator<(const SortableEntry &a, const SortableEntry &b) {
129    return a.value < b.value;
130  }
131};
132
133
134class VssTreeInterior;
135
136
137// --------------------------------------------------------------
138// KD-tree node - abstract class
139// --------------------------------------------------------------
140class VssTreeNode
141{
142public:
143
144#define USE_FIXEDPOINT_T 0
145
146struct RayInfo
147{
148        // pointer to the actual ray
149        VssRay *mRay;
150       
151        // endpoints  - do we need them?
152#if USE_FIXEDPOINT_T
153        short mMinT, mMaxT;
154#else
155        float mMinT, mMaxT;
156#endif
157       
158        RayInfo():mRay(NULL) {}
159       
160        RayInfo(VssRay *r):mRay(r), mMinT(0),
161#if USE_FIXEDPOINT_T
162#define FIXEDPOINT_ONE 0x7FFE
163                                                                                 //                       mMaxT(0xFFFF)
164                                                                                 mMaxT(FIXEDPOINT_ONE)
165#else
166                mMaxT(1.0f)
167#endif
168        {}
169       
170        RayInfo(VssRay *r,
171                                        const float _min,
172                                        const float _max
173                                        ):mRay(r) {
174                SetMinT(_min);
175                SetMaxT(_max);
176        }
177       
178        RayInfo(VssRay *r,
179                                        const short _min,
180                                        const float _max
181                                        ):mRay(r), mMinT(_min) {
182                SetMaxT(_max);
183        }
184       
185        RayInfo(VssRay *r,
186                                                                                const float _min,
187                                                                                const short _max
188                                                                                ):mRay(r), mMaxT(_max) {
189                SetMinT(_min);
190        }
191
192        enum {
193                                SOURCE_RAY = 0,
194                                TERMINATION_RAY,
195                                PASSING_RAY,
196                                CONTAINED_RAY
197        };
198       
199        int GetRayClass() const {
200               
201                bool startsBefore = GetMinT() > 0.0f;
202                bool terminatesAfter = GetMaxT() < 1.0f;
203               
204                if (startsBefore && terminatesAfter)
205                        return PASSING_RAY;
206
207                if (!startsBefore && !terminatesAfter)
208                        return CONTAINED_RAY;
209               
210                if (!startsBefore)
211                        return SOURCE_RAY;
212               
213                return TERMINATION_RAY;
214        }
215       
216        friend bool operator<(const RayInfo &a, const RayInfo &b) {
217                return a.mRay < b.mRay;
218        }
219 
220       
221        float ExtrapOrigin(const int axis) const {
222                return mRay->GetOrigin(axis) + GetMinT()*mRay->GetDir(axis);
223        }
224       
225        float ExtrapTermination(const int axis) const {
226                return mRay->GetOrigin(axis) + GetMaxT()*mRay->GetDir(axis);
227        }
228
229        Vector3 Extrap(const float t) const {
230                return mRay->Extrap(t);
231        }
232       
233#if USE_FIXEDPOINT_T
234        float GetMinT () const { return mMinT/(float)(FIXEDPOINT_ONE); }
235        float GetMaxT () const { return mMaxT/(float)(FIXEDPOINT_ONE); }
236       
237        void SetMinT (const float t) {
238                mMinT = (short) (t*(float)(FIXEDPOINT_ONE));
239        }
240       
241        void SetMaxT (const float t) {
242                mMaxT = (short) (t*(float)(FIXEDPOINT_ONE));
243                mMaxT++;
244                //      if (mMaxT!=0xFFFF)
245                //      mMaxT++;
246        }
247#else
248        float GetMinT () const { return mMinT; }
249        float GetMaxT () const { return mMaxT; }
250       
251        void SetMinT (const float t) { mMinT = t; }
252        void SetMaxT (const float t) { mMaxT = t; }
253#endif
254
255
256  int ComputeRayIntersection(const int axis,
257                                                                                                                 const float position,
258                                                                                                                 float &t
259                                                                                                                 ) const {
260               
261                // intersect the ray with the plane
262    float denom = mRay->GetDir(axis);
263   
264    if (fabs(denom) < 1e-20)
265      //if (denom == 0.0f)
266      return (mRay->GetOrigin(axis) > position) ? 1 : -1;
267   
268    t = (position - mRay->GetOrigin(axis))/denom;
269
270    if (t < GetMinT())
271      return (denom > 0) ? 1 : -1;
272
273    if (t > GetMaxT())
274      return (denom > 0) ? -1 : 1;
275
276                return 0;
277        }
278
279
280};
281
282
283        typedef vector<RayInfo> RayInfoContainer;
284       
285  enum { EInterior, ELeaf };
286
287  /////////////////////////////////
288  // The actual data goes here
289 
290  // link to the parent
291  VssTreeInterior *parent;
292
293  enum {SPLIT_X=0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ};
294 
295  // splitting axis
296  char axis;
297       
298  // depth
299  unsigned char depth;
300 
301  //  short depth;
302  //
303  /////////////////////////////////
304 
305  inline VssTreeNode(VssTreeInterior *p);
306
307 
308  virtual ~VssTreeNode() {};
309  virtual int Type() const  = 0;
310 
311
312  bool IsLeaf() const { return axis == -1; }
313 
314  virtual void Print(ostream &s) const = 0;
315
316  virtual int GetAccessTime() {
317    return 0x7FFFFFF;
318  }
319
320 
321       
322};
323
324// --------------------------------------------------------------
325// KD-tree node - interior node
326// --------------------------------------------------------------
327class VssTreeInterior :
328  public VssTreeNode
329{
330public:
331  // plane in local modelling coordinates
332  float position;
333
334  // pointers to children
335  VssTreeNode *back, *front;
336
337  // the bbox of the node
338  AxisAlignedBox3 bbox;
339
340  // the bbox of the node
341  AxisAlignedBox3 dirBBox;
342 
343  // data for caching
344  long accesses;
345  long lastAccessTime;
346 
347  VssTreeInterior(VssTreeInterior *p):VssTreeNode(p),
348                                        back(NULL),
349                                        front(NULL),
350                                        accesses(0),
351                                        lastAccessTime(-1)
352  { }
353
354  virtual int GetAccessTime() {
355    return lastAccessTime;
356  }
357
358  void SetupChildLinks(VssTreeNode *b, VssTreeNode *f) {
359    back = b;
360    front = f;
361    b->parent = f->parent = this;
362  }
363
364  void ReplaceChildLink(VssTreeNode *oldChild, VssTreeNode *newChild) {
365    if (back == oldChild)
366      back = newChild;
367    else
368      front = newChild;
369  }
370
371  virtual int Type() const  { return EInterior; }
372 
373  virtual ~VssTreeInterior() {
374    if (back)
375      delete back;
376    if (front)
377      delete front;
378  }
379 
380  virtual void Print(ostream &s) const {
381    if (axis == 0)
382      s<<"x ";
383    else
384      if (axis == 1)
385        s<<"y ";
386      else
387        s<<"z ";
388    s<<position<<" ";
389    back->Print(s);
390    front->Print(s);
391  }
392
393 
394       
395  int ComputeRayIntersection(const RayInfo &rayData,
396                                                                                                                 float &t
397                                                                                                                 ) {
398                return rayData.ComputeRayIntersection(axis, position, t);
399  }
400
401};
402
403
404// --------------------------------------------------------------
405// KD-tree node - leaf node
406// --------------------------------------------------------------
407class VssTreeLeaf :
408  public VssTreeNode
409{
410private:
411        int mPvsSize;
412public:
413  static int mailID;
414  int mailbox;
415 
416  RayInfoContainer rays;
417        int mPassingRays;
418       
419        bool mValidPvs;
420       
421       
422       
423  VssTreeLeaf(VssTreeInterior *p,
424                                                        const int nRays
425                                                        ):VssTreeNode(p), rays(), mPvsSize(0), mPassingRays(0), mValidPvs(false) {
426    rays.reserve(nRays);
427  }
428 
429  virtual ~VssTreeLeaf() { }
430
431  virtual int Type() const  { return ELeaf; }
432
433  virtual void Print(ostream &s) const {
434    s<<endl<<"L: r="<<rays.size()<<endl;
435  };
436 
437  void AddRay(const RayInfo &data) {
438                mValidPvs = false;
439    rays.push_back(data);
440    data.mRay->Ref();
441                if (data.GetRayClass() == RayInfo::PASSING_RAY)
442                        mPassingRays++;
443  }
444       
445        int GetPvsSize() const {
446                return mPvsSize;
447        }
448        void SetPvsSize(const int s) {
449                mPvsSize = s;
450                mValidPvs = true;
451        }
452
453        void
454        UpdatePvsSize();
455
456  void Mail() { mailbox = mailID; }
457  static void NewMail() { mailID++; }
458  bool Mailed() const { return mailbox == mailID; }
459 
460  bool Mailed(const int mail) {
461    return mailbox >= mailID + mail;
462  }
463
464        float GetAvgRayContribution() const {
465                return GetPvsSize()/((float)rays.size() + Limits::Small);
466        }
467
468  float GetImportance() const;
469
470        float GetSqrRayContribution() const {
471                return sqr(GetPvsSize()/((float)rays.size() + Limits::Small));
472        }
473
474        // comparator for the
475        struct less_contribution : public
476        binary_function<const VssTreeLeaf *, const VssTreeLeaf *, bool> {
477               
478                bool operator()(const VssTreeLeaf * a, const VssTreeLeaf *b) {
479                        return a->GetAvgRayContribution() < b->GetAvgRayContribution();
480                }
481        };
482
483        struct greater_contribution : public
484        binary_function<const VssTreeLeaf *, const VssTreeLeaf *, bool> {
485               
486                bool operator()(const VssTreeLeaf * a, const VssTreeLeaf *b) {
487                        return a->GetAvgRayContribution() > b->GetAvgRayContribution();
488                }
489        };
490       
491        friend bool GreaterContribution(const VssTreeLeaf * a, const VssTreeLeaf *b) {
492                return a->GetAvgRayContribution() > b->GetAvgRayContribution();
493        }
494       
495};
496
497// Inline functions
498inline
499VssTreeNode::VssTreeNode(VssTreeInterior *p):
500  parent(p), axis(-1), depth(p ? p->depth + 1 : 0) {}
501
502
503
504// ---------------------------------------------------------------
505// Main LSDS search class
506// ---------------------------------------------------------------
507class VssTree
508{
509  struct TraversalData
510  { 
511    VssTreeNode *node;
512    AxisAlignedBox3 bbox;
513    int depth;
514    float priority;
515   
516    TraversalData() {}
517
518    TraversalData(VssTreeNode *n, const float p):
519      node(n), priority(p)
520    {}
521
522    TraversalData(VssTreeNode *n,
523                   const AxisAlignedBox3 &b,
524                   const int d):
525      node(n), bbox(b), depth(d) {}
526   
527               
528    // comparator for the
529    struct less_priority : public
530    binary_function<const TraversalData, const TraversalData, bool> {
531                       
532      bool operator()(const TraversalData a, const TraversalData b) {
533                                return a.priority < b.priority;
534      }
535     
536    };
537
538    //    ~TraversalData() {}
539    //    TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {}
540   
541    friend bool operator<(const TraversalData &a,
542                                                                                                        const TraversalData &b) {
543      //      return a.node->queries.size() < b.node->queries.size();
544      VssTreeLeaf *leafa = (VssTreeLeaf *) a.node;
545      VssTreeLeaf *leafb = (VssTreeLeaf *) b.node;
546#if 0
547                        return
548                                leafa->rays.size()*a.bbox.GetVolume()
549                                <
550                                leafb->rays.size()*b.bbox.GetVolume();
551#endif
552#if 0
553                        return
554                                leafa->GetPvsSize()*a.bbox.GetVolume()
555                                <
556                                leafb->GetPvsSize()*b.bbox.GetVolume();
557#endif
558#if 0
559                        return
560                                leafa->GetPvsSize()
561                                <
562                                leafb->GetPvsSize();
563#endif
564#if 0
565                        return
566                                leafa->GetPvsSize()/(leafa->rays.size()+1)
567                                >
568                                leafb->GetPvsSize()/(leafb->rays.size()+1);
569#endif
570#if 1
571                        return
572                                leafa->GetPvsSize()*leafa->rays.size()
573                                <
574                                leafb->GetPvsSize()*leafb->rays.size();
575#endif
576    }
577  };
578 
579  // simplified data for ray traversal only...
580
581  struct RayTraversalData {
582   
583    VssTreeNode::RayInfo rayData;
584    VssTreeNode *node;
585   
586    RayTraversalData() {}
587    RayTraversalData(VssTreeNode *n,
588                                                                                 const VssTreeNode::RayInfo &data):
589      rayData(data), node(n) {}
590  };
591       
592public:
593  /////////////////////////////
594  // The core pointer
595  VssTreeNode *root;
596 
597  /////////////////////////////
598  // Basic properties
599
600  // total number of nodes of the tree
601  int nodes;
602  // axis aligned bounding box of the scene
603  AxisAlignedBox3 bbox;
604
605  // axis aligned bounding box of directions
606  AxisAlignedBox3 dirBBox;
607 
608  /////////////////////////////
609  // Construction parameters
610
611  // epsilon used for the construction
612  float epsilon;
613
614  // ratio between traversal and intersection costs
615  float ct_div_ci;
616  // max depth of the tree
617  int termMaxDepth;
618  // minimal ratio of the volume of the cell and the query volume
619  float termMinSize;
620
621        // minimal pvs per node to still get subdivided
622  int termMinPvs;
623
624        // minimal ray number per node to still get subdivided
625  int termMinRays;
626       
627  // maximal cost ration to subdivide a node
628  float termMaxCostRatio;
629       
630        // maximal contribution per ray to subdivide the node
631        float termMaxRayContribution;
632
633       
634  // randomized construction
635  bool randomize;
636
637  // type of the splitting to use fo rthe tree construction
638  enum {ESplitRegular, ESplitHeuristic, ESplitHybrid };
639  int splitType;
640
641        bool mSplitUseOnlyDrivingAxis;
642
643        // use ray space subdivision instead of view space subdivision
644        bool mUseRss;
645       
646  // maximal size of the box on which the refdir splitting can be performed
647  // (relative to the scene bbox
648  float refDirBoxMaxSize;
649 
650  // maximum alovable memory in MB
651  float maxTotalMemory;
652
653  // maximum alovable memory for static kd tree in MB
654  float maxStaticMemory;
655
656  // this is used during the construction depending
657  // on the type of the tree and queries...
658  float maxMemory;
659
660
661  // minimal acess time for collapse
662  int accessTimeThreshold;
663
664        // minimal depth at which to perform collapse
665  int minCollapseDepth;
666
667 
668  // reusable array of split candidates
669  vector<SortableEntry> *splitCandidates;
670  /////////////////////////////
671
672        VssStatistics stat;
673       
674 
675  VssTree();
676  virtual ~VssTree();
677
678  virtual void
679  Construct(
680                                                VssRayContainer &rays,
681                                                AxisAlignedBox3 *forcedBoundingBox = NULL
682                                                );
683       
684  // incemental construction
685  virtual void UpdateRays(VssRayContainer &remove,
686                                                                                                        VssRayContainer &add
687                                                                                                        );
688
689        virtual void AddRays(
690                                                                                         VssRayContainer &add
691                                                                                         )
692        {
693                VssRayContainer remove;
694                UpdateRays(remove, add);
695        }
696
697 
698       
699  VssTreeNode *
700  Locate(const Vector3 &v);
701       
702  VssTreeNode *
703  SubdivideNode(VssTreeLeaf *leaf,
704                                                                const AxisAlignedBox3 &box,
705                                                                AxisAlignedBox3 &backBox,
706                                                                AxisAlignedBox3 &frontBox
707                                                                );
708       
709  VssTreeNode *
710  Subdivide(const TraversalData &tdata);
711       
712  int
713  SelectPlane(VssTreeLeaf *leaf,
714                                                        const AxisAlignedBox3 &box,
715                                                        float &position,
716                                                        int &raysBack,
717                                                        int &raysFront,
718                                                        int &pvsBack,
719                                                        int &pvsFront
720                                                        );
721
722  void
723  SortSplitCandidates(
724                                                                                        VssTreeLeaf *node,
725                                                                                        const int axis
726                                                                                        );
727       
728 
729  // return memory usage in MB
730  float GetMemUsage() const {
731    return
732      (sizeof(VssTree) +
733       stat.Leaves()*sizeof(VssTreeLeaf) +
734       stat.Interior()*sizeof(VssTreeInterior) +
735       stat.rayRefs*sizeof(VssTreeNode::RayInfo))/(1024.0f*1024.0f);
736  }
737       
738  float GetRayMemUsage() const {
739    return
740      stat.rays*(sizeof(VssRay))/(1024.0f*1024.0f);
741  }
742 
743
744        float
745        BestCostRatio(
746                                                                VssTreeLeaf *node,
747                                                                int &axis,
748                                                                float &position,
749                                                                int &raysBack,
750                                                                int &raysFront,
751                                                                int &pvsBack,
752                                                                int &pvsFront
753                                                                );
754       
755        float
756        EvalCostRatio(
757                                                                VssTreeLeaf *node,
758                                                                const int axis,
759                                                                const float position,
760                                                                int &raysBack,
761                                                                int &raysFront,
762                                                                int &pvsBack,
763                                                                int &pvsFront
764                                                                );
765
766        float
767        EvalCostRatioHeuristic(
768                                                                                                 VssTreeLeaf *node,
769                                                                                                 const int axis,
770                                                                                                 float &position,
771                                                                                                 int &raysBack,
772                                                                                                 int &raysFront,
773                                                                                                 int &pvsBack,
774                                                                                                 int &pvsFront
775                                                                                                 );
776
777        float
778        GetCostRatio(
779                                                         VssTreeLeaf *leaf,
780                                                         const int axis,
781                                                         const float position,
782                                                         const int raysBack,
783                                                         const int raysFront,
784                                                         const int pvsBack,
785                                                         const int pvsFront
786                                                         );
787
788  AxisAlignedBox3 GetBBox(const VssTreeNode *node) const {
789    if (node->parent == NULL)
790      return bbox;
791
792    if (!node->IsLeaf())
793      return ((VssTreeInterior *)node)->bbox;
794
795    if (node->parent->axis >= 3)
796      return node->parent->bbox;
797     
798    AxisAlignedBox3 box(node->parent->bbox);
799    if (node->parent->front == node)
800      box.SetMin(node->parent->axis, node->parent->position);
801    else
802      box.SetMax(node->parent->axis, node->parent->position);
803    return box;
804  }
805
806  AxisAlignedBox3 GetDirBBox(const VssTreeNode *node) const {
807
808    if (node->parent == NULL)
809      return dirBBox;
810   
811    if (!node->IsLeaf() )
812      return ((VssTreeInterior *)node)->dirBBox;
813
814    if (node->parent->axis < 3)
815      return node->parent->dirBBox;
816   
817    AxisAlignedBox3 dBBox(node->parent->dirBBox);
818
819    if (node->parent->front == node)
820      dBBox.SetMin(node->parent->axis - 3, node->parent->position);
821    else
822      dBBox.SetMax(node->parent->axis - 3, node->parent->position);
823    return dBBox;
824  }
825 
826  int
827  ReleaseMemory(const int time);
828
829  int
830  CollapseSubtree(VssTreeNode *node, const int time);
831
832  void
833  CountAccess(VssTreeInterior *node, const long time) {
834    node->accesses++;
835    node->lastAccessTime = time;
836  }
837
838  VssTreeNode *
839  SubdivideLeaf(
840                                                                VssTreeLeaf *leaf
841                                                                );
842
843  void
844  RemoveRay(VssRay *ray,
845                                                vector<VssTreeLeaf *> *affectedLeaves,
846                                                const bool removeAllScheduledRays
847                                                );
848
849        //  void
850        //  AddRay(VssRay *ray);
851        void
852        AddRay(VssTreeNode::RayInfo &info);
853
854  void
855  TraverseInternalNode(
856                                                                                         RayTraversalData &data,
857                                                                                         stack<RayTraversalData> &tstack);
858
859        void
860  EvaluateLeafStats(const TraversalData &data);
861
862
863        int
864        GetRootPvsSize() const {
865                return GetPvsSize(bbox);
866        }
867       
868        int
869        GetPvsSize(const AxisAlignedBox3 &box) const;
870
871        void
872        GetRayContributionStatistics(
873                                                                                                                         float &minRayContribution,
874                                                                                                                         float &maxRayContribution,
875                                                                                                                         float &avgRayContribution
876                                                                                                                         );
877
878        int
879        GenerateRays(const float ratioPerLeaf,
880                                                         SimpleRayContainer &rays);
881
882        int
883        GenerateRays(const int numberOfRays,
884                                                         const int numberOfLeaves,
885                                                         SimpleRayContainer &rays);
886               
887        float
888        GetAvgPvsSize();
889
890        int
891        UpdateSubdivision();
892
893        bool
894        TerminationCriteriaSatisfied(VssTreeLeaf *leaf);
895
896        void
897        CollectLeaves(vector<VssTreeLeaf *> &leaves);
898
899        bool
900        ClipRay(
901                                        VssTreeNode::RayInfo &rayInfo,
902                                        const AxisAlignedBox3 &box
903                                        );
904
905        VssTreeNode *GetRoot() const { return root; }
906
907        bool
908        ValidLeaf(VssTreeLeaf *leaf) const;
909
910        void
911        GenerateLeafRays(VssTreeLeaf *leaf,
912                                                                         const int numberOfRays,
913                                                                         SimpleRayContainer &rays);
914
915
916};
917
918
919#endif // __LSDS_KDTREE_H__
920
Note: See TracBrowser for help on using the repository browser.