source: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.h @ 1718

Revision 1718, 16.4 KB checked in by mattausch, 18 years ago (diff)
RevLine 
[1237]1#ifndef _HierarchyManager_H__
2#define _HierarchyManager_H__
3
4#include <stack>
5
6#include "Mesh.h"
7#include "Containers.h"
8#include "Statistics.h"
9#include "VssRay.h"
10#include "RayInfo.h"
11#include "gzstream.h"
[1239]12#include "SubdivisionCandidate.h"
[1237]13
14
15
16namespace GtpVisibilityPreprocessor {
17
18class ViewCellLeaf;
19class OspTree;
20class VspTree;
21class Plane3;
22class AxisAlignedBox3;
23class Ray;
24class ViewCellsStatistics;
25class ViewCellsManager;
26class MergeCandidate;
27class Beam;
28class ViewCellsTree;
29class Environment;
30class VspInterior;
31class VspLeaf;
32class VspNode;
33class KdNode;
34class KdInterior;
35class KdLeaf;
36class OspTree;
37class KdIntersectable;
38class KdTree;
39class VspTree;
40class KdTreeStatistics;
[1259]41class BvHierarchy;
[1287]42class Exporter;
[1667]43class ViewCellsParseHandlers;
[1237]44
[1667]45
[1649]46#define COUNT_ORIGIN_OBJECTS 1
[1237]47
[1551]48/** View space / object space hierarchy statistics.
[1288]49*/
50class HierarchyStatistics: public StatisticsBase
51{
52public:
[1576]53        /// total number of entries in the pvs
[1624]54        int mPvsEntries;
[1640]55        /// storage cost in MB
56        float mMemory;
[1288]57        /// total number of nodes
[1624]58        int mNodes;
[1288]59        /// maximal reached depth
[1624]60        int mMaxDepth;
[1288]61        /// accumulated depth
[1624]62        int mAccumDepth;
[1449]63        /// time spent for queue repair
[1624]64        float mRepairTime;
65
[1449]66        // global cost ratio violations
67        int mGlobalCostMisses;
[1624]68        /// total cost of subdivision
69        float mTotalCost;
70        /// render cost decrease of subdivision
71        float mRenderCostDecrease;
[1313]72
[1288]73        // Constructor
74        HierarchyStatistics()
75        {
76                Reset();
77        }
78
[1624]79        int Nodes() const {return mNodes;}
[1640]80        int Interior() const { return mNodes / 2 - 1; }
[1624]81        int Leaves() const { return (mNodes / 2) + 1; }
[1288]82       
83        // TODO: computation wrong
[1624]84        double AvgDepth() const { return mAccumDepth / (double)Leaves();}
[1288]85
[1449]86        void Reset()
[1288]87        {
[1449]88                mGlobalCostMisses = 0;
[1624]89                mTotalCost = 0;
90                mRenderCostDecrease = 0;
91
92                mNodes = 0;
93                mMaxDepth = 0;
94                mAccumDepth = 0;
95                mRepairTime = 0;
96                mMemory = 0;
97                mPvsEntries = 0;
[1288]98        }
99
100        void Print(ostream &app) const;
101
102        friend ostream &operator<<(ostream &s, const HierarchyStatistics &stat)
103        {
104                stat.Print(s);
105                return s;
106        }
107};
108
109
[1237]110/** This class implements a structure holding two different hierarchies,
111        one for object space partitioning and one for view space partitioning.
112
113        The object space and the view space are subdivided using a cost heuristics.
114        If an object space split or a view space split is chosen is also evaluated
115        based on the heuristics.
116       
117        The view space heuristics is evaluated by weighting and adding the pvss of the back and
118        front node of each specific split. unlike for the standalone method vspbsp tree,
119        the pvs of an object would not be the pvs of single object but that of all objects
120        which are contained in the same leaf of the object subdivision. This could be done
121        by storing the pointer to the object space partition parent, which would allow access to all children.
122        Another possibility is to include traced kd-cells in the ray casing process.
123
124        Accordingly, the object space heuristics is evaluated by storing a pvs of view cells with each object.
125        the contribution to an object to the pvs is the number of view cells it can be seen from.
126
127        @note
128        There is a potential efficiency problem involved in a sense that once a certain type
129        of split is chosen for view space / object space, the candidates for the next split of
130        object space / view space must be reevaluated.
131*/
132class HierarchyManager
133{
134public:
[1421]135        /** Constructor with the view space partition tree and
136                the object space hierarchy type as argument.
[1237]137        */
[1421]138        HierarchyManager(const int objectSpaceHierarchyType);
[1279]139        /** Hack: OspTree will copy the content from this kd tree.
140                Only view space hierarchy will be constructed.
141        */
[1421]142        HierarchyManager(KdTree *kdTree);
[1237]143
[1421]144        /** Deletes space partition and view space partition.
145        */
[1286]146        ~HierarchyManager();
147
[1237]148        /** Constructs the view space and object space subdivision from a given set of rays
149                and a set of objects.
150                @param sampleRays the set of sample rays the construction is based on
151                @param objects the set of objects
152        */
[1308]153        void Construct(
[1293]154                const VssRayContainer &sampleRays,
155                const ObjectContainer &objects,
156                AxisAlignedBox3 *forcedViewSpace);
[1237]157
[1259]158        enum
159        {
160                NO_OBJ_SUBDIV,
161                KD_BASED_OBJ_SUBDIV,
162                BV_BASED_OBJ_SUBDIV
163        };
[1237]164
[1370]165        enum
166        {
167                NO_VIEWSPACE_SUBDIV,
168                KD_BASED_VIEWSPACE_SUBDIV
169        };
170
[1259]171        /** The type of object space subdivison
172        */
[1370]173        int GetObjectSpaceSubdivisionType() const;     
174        /** The type of view space space subdivison
175        */
176        int GetViewSpaceSubdivisionType() const;
177        /** Sets a pointer to the view cells manager.
178        */             
[1279]179        void SetViewCellsManager(ViewCellsManager *vcm);
[1370]180        /** Sets a pointer to the view cells tree.
181        */
[1279]182        void SetViewCellsTree(ViewCellsTree *vcTree);
[1370]183        /** Exports the object hierarchy to disc.
184        */
[1279]185        void ExportObjectSpaceHierarchy(OUT_STREAM &stream);
[1370]186        /** Adds a sample to the pvs of the specified view cell.
187        */
[1279]188        bool AddSampleToPvs(
189                Intersectable *obj,
190                const Vector3 &hitPoint,
191                ViewCell *vc,
192                const float pdf,
193                float &contribution) const;
194
[1421]195        /** Print out statistics.
196        */
197        void PrintHierarchyStatistics(ostream &stream) const;
[1279]198
[1421]199        /** Returns the view space partition tree.
200        */
[1379]201        VspTree *GetVspTree();
[1279]202
[1421]203        /** Returns view space bounding box.
204        */
[1563]205        //AxisAlignedBox3 GetViewSpaceBox() const;
[1624]206
[1421]207        /** Returns object space bounding box.
208        */
[1416]209        AxisAlignedBox3 GetObjectSpaceBox() const;
[1379]210
[1421]211        /** Exports object space hierarchy for visualization.
212        */
[1626]213        void ExportObjectSpaceHierarchy(Exporter *exporter,
214                                                                        const ObjectContainer &objects,
215                                                                        const AxisAlignedBox3 *bbox,
216                                                                        const bool exportBounds = true) const;
[1279]217
[1421]218        /** Returns intersectable pierced by this ray.
219        */
[1626]220        Intersectable *GetIntersectable(const VssRay &ray, const bool isTermination) const;
[1418]221
[1626]222        /** Export object space partition bounding boxes.
223        */
224        void ExportBoundingBoxes(OUT_STREAM &stream, const ObjectContainer &objects);
225
[1419]226        friend ostream &operator<<(ostream &s, const HierarchyManager &hm)
227        {
[1421]228                hm.PrintHierarchyStatistics(s);
[1419]229                return s;
230        }
231
[1667]232        HierarchyStatistics &GetHierarchyStats() { return mHierarchyStats; };
233
234        inline bool ConsiderMemory() const { return mConsiderMemory; }
[1676]235        inline float GetMemoryConst() const { return mMemoryConst; }
[1667]236
[1686]237       
238        void EvaluateSubdivision(const VssRayContainer &sampleRays,                                                                                     
239                                                         const ObjectContainer &objects,
240                                                         const string &filename);
[1676]241
[1710]242        void EvaluateSubdivision2(ofstream &splitsStats,
[1713]243                                                          const int splitsStepSize);
[1709]244
245
[1718]246        void CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects);
247
[1686]248        float mInitialRenderCost;
249
250
[1237]251protected:
252
[1625]253        /** Returns true if the global termination criteria were met.
254        */
[1237]255        bool GlobalTerminationCriteriaMet(SubdivisionCandidate *candidate) const;
256
257        /** Prepare construction of the hierarchies, set parameters, compute
258                first split candidates.
259        */
[1625]260        SubdivisionCandidate *PrepareObjectSpaceSubdivision(const VssRayContainer &sampleRays,
261                                                                                                                const ObjectContainer &objects);
[1237]262
[1625]263
[1640]264        /** Create bounding box and root.
265        */
266        void InitialiseObjectSpaceSubdivision(const ObjectContainer &objects);
267
268        /** Returns memory usage of object space hierarchy.
269        */
270        float GetObjectSpaceMemUsage() const;
271
[1667]272
[1625]273        //////////////////////////////
274        // the main loop
275
276        /** This is for interleaved construction / sequential construction.
277        */
278        void RunConstruction(const bool repairQueue,
279                                                 const VssRayContainer &sampleRays,
280                                                 const ObjectContainer &objects,
[1640]281                                                 AxisAlignedBox3 *forcedViewSpace);
[1449]282       
[1625]283        /** This is for interleaved construction using some objects
284                and some view space splits.
285        */
286        int RunConstruction(SplitQueue &splitQueue,
287                                                SubdivisionCandidateContainer &chosenCandidates,
[1667]288                                                //const float minRenderCostDecr,
289                                                SubdivisionCandidate *oldCandidate,
[1676]290                                                const int minSteps,
291                                                const int maxSteps);
[1625]292
293        /** Default subdivision method.
294        */
[1449]295        void RunConstruction(const bool repairQueue);
296               
[1625]297        ////////////////////////////////////////////////
298
[1580]299        /** Evaluates the subdivision candidate and executes the split.
300        */
[1625]301        bool ApplySubdivisionCandidate(SubdivisionCandidate *sc,
302                                                                   SplitQueue &splitQueue,
303                                                                   const bool repairQueue);
[1237]304
[1625]305        /** Tests if hierarchy construction is finished.
306        */
[1237]307        bool FinishedConstruction() const;
308
[1625]309        /** Returns next subdivision candidate from the split queue.
310        */
311        SubdivisionCandidate *NextSubdivisionCandidate(SplitQueue &splitQueue);
[1237]312
[1625]313        /** Repairs the dirty entries of the subdivision candidate queue. The
314                list of entries is given in the dirty list.
[1580]315        */
[1633]316        void RepairQueue(const SubdivisionCandidateContainer &dirtyList,
317                                         SplitQueue &splitQueue,
318                                         const bool recomputeSplitPlaneOnRepair);
[1237]319
[1625]320        /** Collect subdivision candidates which were affected by the splits from the
321                chosenCandidates list.
322        */
323        void CollectDirtyCandidates(const SubdivisionCandidateContainer &chosenCandidates,
324                                                                SubdivisionCandidateContainer &dirtyList);
325
[1580]326        /** Evaluate subdivision stats for log.
327        */
[1624]328        void EvalSubdivisionStats();
[1237]329
[1625]330        void AddSubdivisionStats(const int splits,
331                                                         const float renderCostDecr,
332                                                         const float totalRenderCost,
333                                                         const int totalPvsEntries,
[1640]334                                                         const float memory,
[1654]335                                                         const float renderCostPerStorage,
336                                                         const float vspOspRatio);
[1237]337
[1625]338        bool AddSampleToPvs(Intersectable *obj,
339                                                const float pdf,
340                                                float &contribution) const;
[1237]341
[1625]342        /** Collect affected view space candidates.
343        */
344        void CollectViewSpaceDirtyList(SubdivisionCandidate *sc,
345                                                                   SubdivisionCandidateContainer &dirtyList);
[1259]346
[1625]347        /** Collect affected object space candidates.
348        */
349        void CollectObjectSpaceDirtyList(SubdivisionCandidate *sc,
350                                                                         SubdivisionCandidateContainer &dirtyList);
[1259]351               
[1625]352        /** Export object space partition tree.
353        */
354        void ExportOspTree(Exporter *exporter,
355                                           const ObjectContainer &objects) const;
[1259]356
[1625]357        /** Parse the environment variables.
358        */
[1418]359        void ParseEnvironment();
[1415]360
[1418]361        bool StartObjectSpaceSubdivision() const;
362        bool StartViewSpaceSubdivision() const;
363
[1667]364
[1625]365        ////////////////////////////
366        // Helper function for preparation of subdivision
[1286]367
[1625]368        /** Prepare bv hierarchy for subdivision
369        */
370        SubdivisionCandidate *PrepareBvHierarchy(const VssRayContainer &sampleRays,
371                                                                           const ObjectContainer &objects);
[1286]372
[1625]373        /** Prepare object space kd tree for subdivision.
374        */
375        SubdivisionCandidate *PrepareOspTree(const VssRayContainer &sampleRays,
376                                                                   const ObjectContainer &objects);
[1308]377
[1625]378        /** Prepare view space subdivision and add candidate to queue.
379        */
380        SubdivisionCandidate *PrepareViewSpaceSubdivision(const VssRayContainer &sampleRays,
381                                                                                                          const ObjectContainer &objects);
382
383        /** Was object space subdivision already constructed?
384        */
[1313]385        bool ObjectSpaceSubdivisionConstructed() const;
[1625]386       
387        /** Was view space subdivision already constructed?
388        */
[1329]389        bool ViewSpaceSubdivisionConstructed() const;
[1311]390
[1625]391        /** Reset the split queue, i.e., reevaluate the split candidates.
392        */
[1640]393    void ResetQueue(SplitQueue &splitQueue, const bool recomputeSplitPlane);
[1313]394
[1625]395        /** After the suddivision has ended, do some final tasks.
396        */
[1654]397        void FinishObjectSpaceSubdivision(const ObjectContainer &objects,
398                                                                          const bool removeRayRefs = true) const;
[1313]399
[1625]400        /** Returns depth of object space subdivision.
401        */
[1370]402        int GetObjectSpaceSubdivisionDepth() const;
403
[1640]404        /** Returns number of leaves in object space subdivision.
405        */
406        int GetObjectSpaceSubdivisionLeaves() const;
[1663]407        int GetObjectSpaceSubdivisionNodes() const;
[1640]408
[1625]409        /** Construct object space partition interleaved with view space partition.
410                Each time the best object or view space candidate is selected
411                for the next split.
412        */
[1626]413        void ConstructInterleaved(const VssRayContainer &sampleRays,
414                                                          const ObjectContainer &objects,
415                                                          AxisAlignedBox3 *forcedViewSpace);
[1449]416
[1625]417        /** Construct object space partition interleaved with view space partition.
418                The method chooses a number candidates of each type for subdivision.
419                The number is determined by the "gradient", i.e., the render cost decrease.
420                Once this render cost decrease is lower than the render cost decrease
421                for the splits of previous type, the method will stop current subdivision and
422                evaluate if view space or object space would be the beneficial for the
423                next number of split.
424        */
[1626]425        void ConstructInterleavedWithGradient(const VssRayContainer &sampleRays,
426                                                                                  const ObjectContainer &objects,
427                                                                                  AxisAlignedBox3 *forcedViewSpace);
[1624]428
[1548]429        /** Use iteration to construct the object space hierarchy.
430        */
[1626]431        void ConstructMultiLevel(const VssRayContainer &sampleRays,
432                                                         const ObjectContainer &objects,
433                                                         AxisAlignedBox3 *forcedViewSpace);
[1449]434
[1640]435        /** Based on a given subdivision, we try to optimize using an
436                multiple iteration over view and object space.
437        */
438        void OptimizeMultiLevel(const VssRayContainer &sampleRays,                                                                                       
439                                                        const ObjectContainer &objects,
440                                                        AxisAlignedBox3 *forcedViewSpace);
441
[1548]442        /** Reset the object space subdivision.
443                E.g., deletes hierarchy and resets stats.
444                so construction can be restarted.
445        */
[1625]446        SubdivisionCandidate *ResetObjectSpaceSubdivision(const VssRayContainer &rays,
447                                                                                                          const ObjectContainer &objects);
[1449]448
[1625]449        SubdivisionCandidate *ResetViewSpaceSubdivision(const VssRayContainer &rays,
[1642]450                                                                                                        const ObjectContainer &objects,
451                                                                                                        AxisAlignedBox3 *forcedViewSpace);
[1557]452
[1614]453
[1686]454        ///////////////////////////
[1680]455
[1686]456        void ExportStats(ofstream &stats, SplitQueue &tQueue, const ObjectContainer &objects);
457
[1706]458        void CollectBestSet(const int maxSplits,
459                                                const float maxMemoryCost,
[1707]460                                                ViewCellContainer &viewCells,
[1706]461                                                vector<BvhNode *> &bvhNodes);
462
[1713]463        int ExtractStatistics(const int maxSplits,
464                                                  const float maxMemoryCost,
465                                                  float &renderCost,
466                                                  float &memory,
[1718]467                                                  int &pvsEntries,
468                                                  int &viewSpaceSplits,
469                                                  int &objectSpaceSplits);
[1709]470
471
[1237]472protected:
473
[1627]474        /** construction types
475                sequential: construct first view space, then object space
476                interleaved: construct view space and object space fully interleaved
477                gradient: construct view space / object space until a threshold is reached
478                multilevel: iterate until subdivisions converge to the optimum.
479        */
480        enum {SEQUENTIAL, INTERLEAVED, GRADIENT, MULTILEVEL};
481
[1580]482        /// type of hierarchy construction
483        int mConstructionType;
484
485        /// Type of object space partition
[1308]486        int mObjectSpaceSubdivisionType;
[1580]487        /// Type of view space partition
[1329]488    int mViewSpaceSubdivisionType;
489
[1589]490        /// the traversal queue
491        SplitQueue mTQueue;
492       
[1580]493        ////////////
494        //-- helper variables
495       
496        // the original osp type
[1323]497        int mSavedObjectSpaceSubdivisionType;
[1580]498        // the original vsp type
[1329]499        int mSavedViewSpaceSubdivisionType;
[1580]500        /// the current subdivision candidate
[1624]501        //SubdivisionCandidate *mCurrentCandidate;
[1323]502
[1259]503
[1580]504        ///////////////////
505        // Hierarchies
506
507        /// view space hierarchy
[1259]508        VspTree *mVspTree;
[1580]509        /// object space partition kd tree
[1259]510        OspTree *mOspTree;
[1625]511
[1589]512        public:
[1580]513        /// bounding volume hierarchy
[1259]514        BvHierarchy *mBvHierarchy;
[1580]515       
[1589]516protected:
[1237]517
518
[1580]519        //////////
[1576]520        //-- global termination criteria
521
[1580]522        /// the mininal acceptable cost ratio for a split
[1237]523        float mTermMinGlobalCostRatio;
[1580]524        /// the threshold for global cost miss tolerance
[1237]525        int mTermGlobalCostMissTolerance;
[1580]526        /// maximum number of leaves
527        int mTermMaxLeaves;
[1649]528        /// Maximal allowed memory consumption.
529        float mTermMaxMemory;
[1580]530
[1667]531
[1576]532        ////////////////////
533
[1667]534        /// number of minimal steps of the same type
[1640]535        int mMinStepsOfSameType;
[1684]536        int mMaxStepsOfSameType;
[1640]537
[1580]538        /// statistics about the hierarchy
[1288]539        HierarchyStatistics mHierarchyStats;
540
[1308]541        int mMinDepthForObjectSpaceSubdivion;
[1370]542        int mMinDepthForViewSpaceSubdivion;
[1580]543       
[1625]544        //int mMinRenderCostDecrease;
[1624]545
[1237]546        ofstream mSubdivisionStats;
[1314]547
[1580]548        /// if the queue should be repaired after a subdivision steps
[1314]549        bool mRepairQueue;
[1370]550
551        bool mStartWithObjectSpace;
[1580]552        /** if multi level construction method should be used
553                where we iterate over both hierarchies until we
554                converge to the optimum.
555        */
[1449]556        bool mUseMultiLevelConstruction;
[1640]557
[1580]558        /// number of iteration steps for multilevel approach   
559        int mNumMultiLevels;
[1640]560
[1633]561        /** if split plane should be recomputed for the repair.
562                Otherwise only the priority is recomputed, the
563                split plane itself stays the same
564        */
565        bool mRecomputeSplitPlaneOnRepair;
[1662]566
567        /** If memory should be considered during choosing
568                of the next split type during gradient method.
569        */
570        bool mConsiderMemory;
[1666]571
[1673]572        /// constant value for driving the heuristics
[1666]573        float mMemoryConst;
[1673]574       
575        bool mConsiderMemory2;
[1667]576
[1679]577        int mTimeStamp;
[1667]578        friend VspTree;
579        friend OspTree;
580        friend BvHierarchy;
581        friend ViewCellsParseHandlers;
582
[1237]583};
584
585}
586
587#endif
Note: See TracBrowser for help on using the repository browser.