source: GTP/trunk/Lib/Vis/Preprocessing/src/VspBspTree.h @ 652

Revision 652, 21.7 KB checked in by mattausch, 18 years ago (diff)

started to implement split plane queue

Line 
1#ifndef _VspBspTree_H__
2#define _VspBspTree_H__
3
4#include "Mesh.h"
5#include "Containers.h"
6#include "Polygon3.h"
7#include <stack>
8#include "Statistics.h"
9#include "VssRay.h"
10#include "RayInfo.h"
11#include "ViewCellBsp.h"
12
13class ViewCell;
14//class BspViewCell;
15class Plane3;
16class VspBspTree; 
17class BspInterior;
18class BspNode;
19class AxisAlignedBox3;
20class Ray;
21class ViewCellsStatistics;
22class ViewCellsManager;
23class MergeCandidate;
24class Beam;
25class ViewCellsTree;
26
27
28struct BspRay;
29
30#define OCTREE_HACK 0
31/**
32        This is a view space partitioning specialised BSPtree. 
33        There are no polygon splits, but we split the sample rays.
34        The candidates for the next split plane are evaluated only
35        by checking the sampled visibility information.
36        The polygons are employed merely as candidates for the next split planes.
37*/
38class VspBspTree
39{
40        friend class ViewCellsParseHandlers;
41        friend class VspBspViewCellsManager;
42public:
43       
44        /** Additional data which is passed down the BSP tree during traversal.
45        */
46        struct VspBspTraversalData
47        { 
48                /// the current node
49                BspNode *mNode;
50                /// polygonal data for splitting
51                PolygonContainer *mPolygons;
52                /// current depth
53                int mDepth;
54                /// rays piercing this node
55                RayInfoContainer *mRays;
56                /// the probability that this node contains view point
57                float mProbability;
58                /// geometry of node as induced by planes
59                BspNodeGeometry *mGeometry;
60                /// pvs size
61                int mPvs;
62                /// how often this branch has missed the max-cost ratio
63                int mMaxCostMisses;
64                /// if this node is a kd-node (i.e., boundaries are axis aligned
65                bool mIsKdNode;
66#if OCTREE_HACK // OCTREE HACK
67                int mAxis;
68#endif
69                /// bounding box of current view space.
70                ///AxisAlignedBox3 mBbox;
71               
72                /** Returns average ray contribution.
73                */
74                float GetAvgRayContribution() const
75                {
76                        return (float)mPvs / ((float)mRays->size() + Limits::Small);
77                }
78
79
80                VspBspTraversalData():
81                mNode(NULL),
82                mPolygons(NULL),
83                mDepth(0),
84                mRays(NULL),
85                mPvs(0),
86                mProbability(0.0),
87                mGeometry(NULL),
88                mMaxCostMisses(0),
89                mIsKdNode(false)
90                {}
91               
92                VspBspTraversalData(BspNode *node,
93                                                        PolygonContainer *polys,
94                                                        const int depth,
95                                                        RayInfoContainer *rays,
96                                                        const int pvs,
97                                                        const float p,
98                                                        BspNodeGeometry *geom):
99                mNode(node),
100                mPolygons(polys),
101                mDepth(depth),
102                mRays(rays),
103                mPvs(pvs),
104                mProbability(p),
105                mGeometry(geom),
106                mMaxCostMisses(0),
107                mIsKdNode(false)
108                {}
109
110                VspBspTraversalData(PolygonContainer *polys,
111                                                        const int depth,
112                                                        RayInfoContainer *rays,
113                                                        BspNodeGeometry *geom):
114                mNode(NULL),
115                mPolygons(polys),
116                mDepth(depth),
117                mRays(rays),
118                mPvs(0),
119                mProbability(0),
120                mGeometry(geom),
121                mMaxCostMisses(0),
122                mIsKdNode(false)
123                {}
124
125                /** Returns cost of the traversal data.
126                */
127                float GetCost() const
128                {
129#if 1
130                        return mPvs * mProbability;
131#endif
132#if 0
133                        return (float) (-mDepth); // for regular grid
134#endif
135#if 0
136                        return (float)(mPvs * (int)mRays->size());
137#endif
138#if 0
139                        return (float)mPvs;
140#endif
141#if 0
142                        return mProbabiliy * (float)mRays->size();
143#endif
144                }
145
146                // deletes contents and sets them to NULL
147                void Clear()
148                {
149                        DEL_PTR(mPolygons);
150                        DEL_PTR(mRays);
151                        DEL_PTR(mGeometry);
152                }
153
154                friend bool operator<(const VspBspTraversalData &a, const VspBspTraversalData &b)
155                {
156                        return a.GetCost() < b.GetCost();
157                }
158    };
159       
160        typedef std::priority_queue<VspBspTraversalData> VspBspTraversalQueue;
161       
162       
163        struct VspBspSplitCandidate
164        { 
165                /// the current node
166                Plane3 mSplitPlane;
167               
168                // parent data
169                VspBspTraversalData mParentData;
170
171                float mRenderCost;
172
173                VspBspSplitCandidate(const Plane3 &plane, const VspBspTraversalData &tData):
174                mSplitPlane(plane), mParentData(tData)
175                {}
176
177                /** Returns cost of the traversal data.
178                */
179                float GetCost() const
180                {
181#if 1
182                        return mRenderCost;
183#endif
184#if 0
185                        return (float) (-mDepth); // for kd tree
186#endif
187                }
188
189                friend bool operator<(const VspBspSplitCandidate &a, const VspBspSplitCandidate &b)
190                {
191                        return a.GetCost() < b.GetCost();
192                }
193    };
194
195        typedef std::priority_queue<VspBspSplitCandidate> VspBspSplitQueue;
196
197        /** Default constructor creating an empty tree.
198        */
199        VspBspTree();
200
201        /** Default destructor.
202        */
203        ~VspBspTree();
204
205        /** Returns BSP Tree statistics.
206        */
207        const BspTreeStatistics &GetStatistics() const;
208 
209
210        /** Constructs the tree from a given set of rays.
211                @param sampleRays the set of sample rays the construction is based on
212                @param viewCells if not NULL, new view cells are
213                created in the leafs and stored in the container
214        */
215        void Construct(const VssRayContainer &sampleRays,
216                                   AxisAlignedBox3 *forcedBoundingBox);
217
218        /** Returns list of BSP leaves with pvs smaller than
219                a certain threshold.
220                @param onlyUnmailed if only the unmailed leaves should be considered
221                @param maxPvs the maximal pvs (-1 means unlimited)
222        */
223        void CollectLeaves(vector<BspLeaf *> &leaves,
224                                           const bool onlyUnmailed = false,
225                                           const int maxPvs = -1) const;
226
227        /** Returns box which bounds the whole tree.
228        */
229        AxisAlignedBox3 GetBoundingBox()const;
230
231        /** Returns root of BSP tree.
232        */
233        BspNode *GetRoot() const;
234
235        /** Collects the leaf view cells of the tree
236                @param viewCells returns the view cells
237        */
238        void CollectViewCells(ViewCellContainer &viewCells, bool onlyValid) const;
239
240        /** A ray is cast possible intersecting the tree.
241                @param the ray that is cast.
242                @returns the number of intersections with objects stored in the tree.
243        */
244        int CastRay(Ray &ray);
245
246        /// bsp tree construction types
247        enum {FROM_INPUT_VIEW_CELLS, FROM_SCENE_GEOMETRY, FROM_SAMPLES};
248
249        /** finds neighbouring leaves of this tree node.
250        */
251        int FindNeighbors(BspNode *n,
252                                          vector<BspLeaf *> &neighbors,
253                                          const bool onlyUnmailed) const;
254
255        /** Constructs geometry associated with the half space intersections
256                leading to this node.
257        */
258        void ConstructGeometry(BspNode *n, BspNodeGeometry &geom) const;
259       
260        /** Construct geometry of view cell.
261        */
262        void ConstructGeometry(ViewCell *vc, BspNodeGeometry &geom) const;
263
264        /** Returns random leaf of BSP tree.
265                @param halfspace defines the halfspace from which the leaf is taken.
266        */
267        BspLeaf *GetRandomLeaf(const Plane3 &halfspace);
268
269        /** Returns random leaf of BSP tree.
270                @param onlyUnmailed if only unmailed leaves should be returned.
271        */
272        BspLeaf *GetRandomLeaf(const bool onlyUnmailed = false);
273
274        /** Returns epsilon of this tree.
275        */
276        float GetEpsilon() const;
277
278        /** Casts line segment into the tree.
279                @param origin the origin of the line segment
280                @param termination the end point of the line segment
281                @returns view cells intersecting the line segment.
282        */
283    int CastLineSegment(const Vector3 &origin,
284                                                const Vector3 &termination,
285                                                ViewCellContainer &viewcells);
286
287               
288        /** Sets pointer to view cells manager.
289        */
290        void SetViewCellsManager(ViewCellsManager *vcm);
291
292        /** Returns distance from node 1 to node 2.
293        */
294        int TreeDistance(BspNode *n1, BspNode *n2) const;
295
296        /** Collapses the tree with respect to the view cell partition.
297                @returns number of collapsed nodes
298        */
299        int CollapseTree();
300
301        /** Returns view cell the current point is located in.
302        */
303        ViewCell *GetViewCell(const Vector3 &point);
304
305
306        /** Returns true if this view point is in a valid view space,
307                false otherwise.
308        */
309        bool ViewPointValid(const Vector3 &viewPoint) const;
310
311        /** Returns view cell corresponding to
312                the invalid view space.
313        */
314        BspViewCell *GetOutOfBoundsCell();
315
316        /** Writes tree to output stream
317        */
318        bool Export(ofstream &stream);
319
320        /** Casts beam, i.e. a 5D frustum of rays, into tree.
321                Tests conservative using the bounding box of the nodes.
322                @returns number of view cells it intersected
323        */
324        int CastBeam(Beam &beam);
325
326        void CollectViewCells(BspNode *root,
327                                                  bool onlyValid,
328                                                  ViewCellContainer &viewCells,
329                                                  bool onlyUnmailed = false) const;
330
331       
332        int FindApproximateNeighbors(BspNode *n,
333                                                             vector<BspLeaf *> &neighbors,
334                                                                 const bool onlyUnmailed) const;
335
336        /** Checks if tree validity-flags are right
337                with respect to view cell valitiy.
338                If not, marks subtree as invalid.
339        */
340        void ValidateTree();
341
342        /** Invalid view cells are added to the unbounded space
343        */
344        void CollapseViewCells();
345
346        /** Collects rays stored in the leaves.
347        */
348        void CollectRays(VssRayContainer &rays);
349
350
351        ViewCellsTree *mViewCellsTree;
352
353
354protected:
355
356        // --------------------------------------------------------------
357        // For sorting objects
358        // --------------------------------------------------------------
359        struct SortableEntry
360        {
361                enum EType
362                {
363                        ERayMin,
364                        ERayMax
365                };
366
367                int type;
368                float value;
369                VssRay *ray;
370 
371                SortableEntry() {}
372                SortableEntry(const int t, const float v, VssRay *r):type(t),
373                                          value(v), ray(r)
374                {
375                }
376               
377                friend bool operator<(const SortableEntry &a, const SortableEntry &b)
378                {
379                        return a.value < b.value;
380                }
381        };
382
383        /** faster evaluation of split plane cost for kd axis aligned cells.
384        */
385        float EvalAxisAlignedSplitCost(const VspBspTraversalData &data,
386                                                                   const AxisAlignedBox3 &box,
387                                                                   const int axis,
388                                                                   const float &position,
389                                                                   float &pFront,
390                                                                   float &pBack) const;
391
392        void EvalSplitCandidate(VspBspTraversalData &tData, VspBspSplitCandidate &splitData);
393
394        float EvalRenderCostDecrease(const Plane3 &candidatePlane,
395                                                                 const VspBspTraversalData &data) const;
396
397        /** Returns view cell corresponding to
398                the invalid view space. If it does not exist, it is created.
399        */
400        BspViewCell *GetOrCreateOutOfBoundsCell();
401
402        /** Collapses the tree with respect to the view cell partition,
403                i.e. leaves having the same view cell are collapsed.
404                @param node the root of the subtree to be collapsed
405                @param collapsed returns the number of collapsed nodes
406                @returns node of type leaf if the node could be collapsed,
407                this node otherwise
408        */
409        BspNode *CollapseTree(BspNode *node, int &collapsed);
410
411        /** Helper function revalidating the view cell leaf list after merge.
412        */
413        void RepairViewCellsLeafLists();
414
415        /** Evaluates tree stats in the BSP tree leafs.
416        */
417        void EvaluateLeafStats(const VspBspTraversalData &data);
418
419        /** Subdivides node with respect to the traversal data.
420            @param tStack current traversal stack
421                @param tData traversal data also holding node to be subdivided
422                @returns new root of the subtree
423        */
424        BspNode *Subdivide(VspBspTraversalQueue &tStack,
425                                           VspBspTraversalData &tData);
426
427        /** Constructs the tree from the given traversal data.
428                @param polys stores set of polygons on which subdivision may be based
429                @param rays storesset of rays on which subdivision may be based
430        */
431        void Construct(const PolygonContainer &polys, RayInfoContainer *rays);
432
433        /** Selects the best possible splitting plane.
434                @param plane returns the split plane
435                @param leaf the leaf to be split
436                @param polys the polygon list on which the split decition is based
437                @param rays ray container on which selection may be based
438                @note the polygons can be reordered in the process
439                @returns true if the cost of the split is under maxCostRatio
440
441        */
442        bool SelectPlane(Plane3 &plane,
443                                         BspLeaf *leaf,
444                                         VspBspTraversalData &data,
445                                         VspBspTraversalData &frontData,
446                                         VspBspTraversalData &backData,
447                                         int &splitAxis);
448       
449        /** Strategies where the effect of the split plane is tested
450            on all input rays.
451
452                @returns the cost of the candidate split plane
453        */
454        float EvalSplitPlaneCost(const Plane3 &candidatePlane,
455                                                         const VspBspTraversalData &data,
456                                                         BspNodeGeometry &geomFront,
457                                                         BspNodeGeometry &geomBack,
458                                                         float &pFront,
459                                                         float &pBack) const;
460
461        /** Subdivide leaf.
462                @param leaf the leaf to be subdivided
463               
464                @param polys the polygons to be split
465                @param frontPolys returns the polygons in front of the split plane
466                @param backPolys returns the polygons in the back of the split plane
467               
468                @param rays the polygons to be filtered
469                @param frontRays returns the polygons in front of the split plane
470                @param backRays returns the polygons in the back of the split plane
471
472                @returns the root of the subdivision
473        */
474
475        BspNode *SubdivideNode(VspBspTraversalData &tData,
476                                                   VspBspTraversalData &frontData,
477                                                   VspBspTraversalData &backData,
478                                                   PolygonContainer &coincident);
479
480        /** Extracts the meshes of the objects and adds them to polygons.
481                Adds object aabb to the aabb of the tree.
482                @param maxPolys the maximal number of objects to be stored as polygons
483                @returns the number of polygons
484        */
485        int AddToPolygonSoup(const ObjectContainer &objects,
486                                                 PolygonContainer &polys,
487                                                 int maxObjects = 0);
488
489        /** Extracts the meshes of the view cells and and adds them to polygons.
490                Adds view cell aabb to the aabb of the tree.
491                @param maxPolys the maximal number of objects to be stored as polygons
492                @returns the number of polygons
493        */
494        int AddToPolygonSoup(const ViewCellContainer &viewCells,
495                                                 PolygonContainer &polys,
496                                                 int maxObjects = 0);
497
498        /** Extract polygons of this mesh and add to polygon container.
499                @param mesh the mesh that drives the polygon construction
500                @param parent the parent intersectable this polygon is constructed from
501                @returns number of polygons
502        */
503        int AddMeshToPolygons(Mesh *mesh, PolygonContainer &polys, MeshInstance *parent);
504
505        /** Selects an axis aligned for the next split.
506                @returns cost for this split
507        */
508        float SelectAxisAlignedPlane(Plane3 &plane,
509                                                                 const VspBspTraversalData &tData,
510                                                                 int &axis,
511                                                                 BspNodeGeometry **frontGeom,
512                                                                 BspNodeGeometry **backGeom,
513                                                                 float &pFront,
514                                                                 float &pBack,
515                                                                 const bool useKdSplit);
516
517        /** Sorts split candidates for surface area heuristics for axis aligned splits.
518                @param polys the input for choosing split candidates
519                @param axis the current split axis
520                @param splitCandidates returns sorted list of split candidates
521        */
522        void SortSplitCandidates(const RayInfoContainer &rays, const int axis);
523
524        /** Computes best cost for axis aligned planes.
525        */
526        float BestCostRatioHeuristics(const RayInfoContainer &rays,
527                                                                  const AxisAlignedBox3 &box,
528                                                                  const int pvsSize,
529                                                                  const int &axis,
530                                                                  float &position);
531
532        /** Selects an axis aligned split plane.
533                @Returns true if split is valied
534        */
535        bool SelectAxisAlignedPlane(Plane3 &plane, const PolygonContainer &polys) const;
536
537        /** Subdivides the rays into front and back rays according to the split plane.
538               
539                @param plane the split plane
540                @param rays contains the rays to be split. The rays are
541                           distributed into front and back rays.
542                @param frontRays returns rays on the front side of the plane
543                @param backRays returns rays on the back side of the plane
544               
545                @returns the number of splits
546        */
547        int SplitRays(const Plane3 &plane,
548                                  RayInfoContainer &rays,
549                              RayInfoContainer &frontRays,
550                                  RayInfoContainer &backRays) const;
551
552
553        /** Extracts the split planes representing the space bounded by node n.
554        */
555        void ExtractHalfSpaces(BspNode *n, vector<Plane3> &halfSpaces) const;
556
557        /** Adds the object to the pvs of the front and back leaf with a given classification.
558
559                @param obj the object to be added
560                @param cf the ray classification regarding the split plane
561                @param frontPvs returns the PVS of the front partition
562                @param backPvs returns the PVS of the back partition
563       
564        */
565        void AddObjToPvs(Intersectable *obj,
566                                         const int cf,
567                                         int &frontPvs,
568                                         int &backPvs,
569                                         int &totalPvs) const;
570       
571        /** Computes PVS size induced by the rays.
572        */
573        int ComputePvsSize(const RayInfoContainer &rays) const;
574
575        /** Returns true if tree can be terminated.
576        */
577        inline bool TerminationCriteriaMet(const VspBspTraversalData &data) const;
578
579        /** Computes accumulated ray lenght of this rays.
580        */
581        float AccumulatedRayLength(const RayInfoContainer &rays) const;
582
583        /** Splits polygons with respect to the split plane.
584
585                @param plane the split plane
586                @param polys the polygons to be split. the polygons are consumed and
587                           distributed to the containers frontPolys, backPolys, coincident.
588                @param frontPolys returns the polygons in the front of the split plane
589                @param backPolys returns the polygons in the back of the split plane
590                @param coincident returns the polygons coincident to the split plane
591
592                @returns the number of splits   
593        */
594        int SplitPolygons(const Plane3 &plane,
595                                          PolygonContainer &polys,
596                                          PolygonContainer &frontPolys,
597                                          PolygonContainer &backPolys,
598                                          PolygonContainer &coincident) const;
599
600        /** Adds ray sample contributions to the PVS.
601                @param sampleContributions the number contributions of the samples
602                @param contributingSampels the number of contributing rays
603               
604        */
605        void AddToPvs(BspLeaf *leaf,
606                                  const RayInfoContainer &rays,
607                                  float &sampleContributions,
608                                  int &contributingSamples);
609
610
611
612
613
614       
615        /** Take 3 ray endpoints, where two are minimum and one a maximum
616                point or the other way round.
617        */
618        Plane3 ChooseCandidatePlane(const RayInfoContainer &rays) const;
619
620        /** Take plane normal as plane normal and the midpoint of the ray.
621                PROBLEM: does not resemble any point where visibility is
622                likely to change
623        */
624        Plane3 ChooseCandidatePlane2(const RayInfoContainer &rays) const;
625
626        /** Fit the plane between the two lines so that the plane
627                has equal shortest distance to both lines.
628        */
629        Plane3 ChooseCandidatePlane3(const RayInfoContainer &rays) const;
630 
631        /** Collects candidates for merging.
632                @param leaves the leaves to be merged
633                @returns number of leaves in queue
634        */
635        int CollectMergeCandidates(const vector<BspLeaf *> leaves, vector<MergeCandidate> &candidates);
636
637        /** Collects candidates for the merge in the merge queue.
638                @returns number of leaves in queue
639        */
640        int CollectMergeCandidates(const VssRayContainer &rays, vector<MergeCandidate> &candidates);
641       
642        /** Preprocesses polygons and throws out all polygons which are coincident to
643                the view space box faces (they can be problematic).
644        */
645        void PreprocessPolygons(PolygonContainer &polys);
646       
647        /** Propagates valid flag up the tree.
648        */
649        void PropagateUpValidity(BspNode *node);
650
651        /** Writes the node to disk
652                @note: should be implemented as visitor
653        */
654        void ExportNode(BspNode *node, ofstream &stream);
655
656        /** Returns estimated memory usage of tree.
657        */
658        //float GetMemUsage(const VspBspTraversalQueue &tstack) const;
659        float GetMemUsage() const;
660
661
662
663        /// Pointer to the root of the tree
664        BspNode *mRoot;
665               
666        BspTreeStatistics mBspStats;
667
668        /// Strategies for choosing next split plane.
669        enum {NO_STRATEGY = 0,
670                  RANDOM_POLYGON = 1,
671                  AXIS_ALIGNED = 2,
672                  LEAST_RAY_SPLITS = 256,
673                  BALANCED_RAYS = 512,
674                  PVS = 1024
675                };
676
677        /// box around the whole view domain
678        AxisAlignedBox3 mBox;
679
680        bool mUseCostHeuristics;
681
682        /// minimal number of rays before subdivision termination
683        int mTermMinRays;
684        /// maximal possible depth
685        int mTermMaxDepth;
686        /// mininum probability
687        float mTermMinProbability;
688        /// mininum PVS
689        int mTermMinPvs;
690        /// maximal contribution per ray
691        float mTermMaxRayContribution;
692        /// minimal accumulated ray length
693        float mTermMinAccRayLength;
694
695        //HACK
696        int mTermMinPolygons;
697
698        //-- termination criteria for axis aligned split
699
700        /// minimal number of rays for axis aligned split
701        int mTermMinRaysForAxisAligned;
702        // max ray contribution
703        float mTermMaxRayContriForAxisAligned;
704
705        /// strategy to get the best split plane
706        int mSplitPlaneStrategy;
707        /// number of candidates evaluated for the next split plane
708        int mMaxPolyCandidates;
709        /// number of candidates for split planes evaluated using the rays
710        int mMaxRayCandidates;
711        /// balancing factor for PVS criterium
712        float mCtDivCi;
713
714        //-- axis aligned split criteria
715        float mAxisAlignedCtDivCi;
716        /// spezifies the split border of the axis aligned split
717        float mAxisAlignedSplitBorder;
718
719        /// maximal acceptable cost ratio
720        float mTermMaxCostRatio;
721        /// tolerance value indicating how often the max cost ratio can be failed
722        int mTermMissTolerance;
723
724        //-- factors guiding the split plane heuristics
725        float mLeastRaySplitsFactor;
726        float mBalancedRaysFactor;
727        float mPvsFactor;
728
729        /// if area or volume should be used for PVS heuristics
730        bool mUseAreaForPvs;
731        /// tolerance for polygon split
732        float mEpsilon;
733        /// maximal number of test rays used to evaluate candidate split plane
734        int mMaxTests;
735        /// normalizes different bsp split plane criteria
736        float mCostNormalizer;
737        /// maximal number of view cells
738        int mMaxViewCells;
739       
740        ofstream  mSubdivisionStats;
741
742        // if rays should be stored in leaves
743        bool mStoreRays;
744       
745        /// if only driving axis should be used for split
746        bool mOnlyDrivingAxis;
747
748        ViewCellsManager *mViewCellsManager;
749
750        vector<SortableEntry> *mSplitCandidates;
751
752       
753        float mRenderCostWeight;
754        /// View cell corresponding to the space outside the valid view space
755        BspViewCell *mOutOfBoundsCell;
756
757        /// maximal tree memory
758        float mMaxMemory;
759        /// the tree is out of memory
760        bool mOutOfMemory;
761       
762        float mTotalCost;
763        int mTotalPvsSize;
764
765        //int mSplits;
766
767        ofstream mSubdivsionStats;
768
769        bool mUseRandomAxis;
770
771        bool mUsePolygonSplitIfAvailable;
772
773        int mTimeStamp;
774
775        int mCreatedViewCells;
776
777private:
778
779
780        static const float sLeastRaySplitsTable[5];
781        /** Evaluates split plane classification with respect to the plane's
782                contribution for balanced rays.
783        */
784        static const float sBalancedRaysTable[5];
785
786        /// Generates unique ids for PVS criterium
787        static void GenerateUniqueIdsForPvs();
788
789        //-- unique ids for PVS criterium
790        static int sFrontId;
791        static int sBackId;
792        static int sFrontAndBackId;
793};
794
795
796
797
798#endif
Note: See TracBrowser for help on using the repository browser.