source: GTP/trunk/Lib/Vis/Preprocessing/src/HierarchyManager.cpp @ 1264

Revision 1264, 11.1 KB checked in by mattausch, 18 years ago (diff)
Line 
1#include <stack>
2#include <time.h>
3#include <iomanip>
4
5#include "ViewCell.h"
6#include "Plane3.h"
7#include "HierarchyManager.h"
8#include "Mesh.h"
9#include "common.h"
10#include "Environment.h"
11#include "Polygon3.h"
12#include "Ray.h"
13#include "AxisAlignedBox3.h"
14#include "Exporter.h"
15#include "Plane3.h"
16#include "ViewCellsManager.h"
17#include "Beam.h"
18#include "KdTree.h"
19#include "KdIntersectable.h"
20#include "VspTree.h"
21#include "OspTree.h"
22#include "BvHierarchy.h"
23
24
25namespace GtpVisibilityPreprocessor {
26
27
28#define USE_FIXEDPOINT_T 0
29
30
31/*******************************************************************/
32/*              class HierarchyManager implementation              */
33/*******************************************************************/
34
35
36HierarchyManager::HierarchyManager(VspTree &vspTree, OspTree &ospTree)
37//:mVspTree(vspTree), mOspTree(ospTree)
38{
39        char subdivisionStatsLog[100];
40        Environment::GetSingleton()->GetStringValue("Hierarchy.subdivisionStats",
41                subdivisionStatsLog);
42        mSubdivisionStats.open(subdivisionStatsLog);
43}
44
45
46SubdivisionCandidate *HierarchyManager::NextSubdivisionCandidate()
47{
48        SubdivisionCandidate *splitCandidate = mTQueue.Top();
49        mTQueue.Pop();
50
51        return splitCandidate;
52}
53
54
55void HierarchyManager::PrepareConstruction(const VssRayContainer &sampleRays,
56                                                                                   const ObjectContainer &objects,
57                                                                                   AxisAlignedBox3 *forcedViewSpace,
58                                                                                   RayInfoContainer &viewSpaceRays,
59                                                                                   RayInfoContainer &objectSpaceRays)
60{
61        SubdivisionCandidate *vsc =
62                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, viewSpaceRays);
63        mTQueue.Push(vsc);
64
65        SubdivisionCandidate *osc =
66                mOspTree->PrepareConstruction(sampleRays, objects, forcedViewSpace, objectSpaceRays);
67
68        mTQueue.Push(osc);
69}
70
71
72void HierarchyManager::EvalSubdivisionStats(const SubdivisionCandidate &tData)
73{
74        const float costDecr = tData.GetRenderCostDecrease();
75
76        //mTotalCost -= costDecr;
77        //mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs;
78
79        AddSubdivisionStats(mOspTree->mOspStats.Leaves() + mVspTree->mVspStats.Leaves(),
80                                                costDecr,
81                                                mTotalCost
82                                                );
83}
84
85
86void HierarchyManager::AddSubdivisionStats(const int splits,
87                                                                                   const float renderCostDecr,
88                                                                                   const float totalRenderCost)
89{
90        mSubdivisionStats
91                        << "#Splits\n" << splits << endl
92                        << "#RenderCostDecrease\n" << renderCostDecr << endl
93                        << "#TotalRenderCost\n" << totalRenderCost << endl;
94                        //<< "#AvgRenderCost\n" << avgRenderCost << endl;
95}
96
97
98bool HierarchyManager::GlobalTerminationCriteriaMet(SubdivisionCandidate *candidate) const
99{
100        // TODO matt: make virtual by creating superclasss for traveral data
101        return candidate->GlobalTerminationCriteriaMet();
102}
103
104
105void HierarchyManager::Construct(const VssRayContainer &sampleRays,
106                                                                 const ObjectContainer &objects,
107                                                                 AxisAlignedBox3 *forcedViewSpace)
108{
109        RayInfoContainer *objectSpaceRays = new RayInfoContainer();
110        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
111
112        // prepare vsp and osp trees for traversal
113        PrepareConstruction(sampleRays, objects, forcedViewSpace, *viewSpaceRays, *objectSpaceRays);
114
115        mVspTree->mVspStats.Reset();
116        mVspTree->mVspStats.Start();
117
118        cout << "Constructing view space / object space tree ... \n";
119        const long startTime = GetTime();       
120       
121        RunConstruction(true);
122
123        cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
124
125        mVspTree->mVspStats.Stop();
126}
127
128
129bool HierarchyManager::SubdivideSubdivisionCandidate(SubdivisionCandidate *sc)
130{
131        const bool globalTerminationCriteriaMet =
132                        GlobalTerminationCriteriaMet(sc);
133
134        const bool vspSplit = (sc->Type() == SubdivisionCandidate::VIEW_SPACE);
135
136        if (vspSplit)
137        {
138                VspNode *n = mVspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
139        }
140        else
141        {
142                KdNode *n = mOspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
143        }
144       
145        return !globalTerminationCriteriaMet;
146}
147
148
149void HierarchyManager::RunConstruction(const bool repair)
150{
151        int numNodes = 0;
152
153        while (!FinishedConstruction())
154        {
155                SubdivisionCandidate *splitCandidate = NextSubdivisionCandidate();
156           
157                mTotalCost -= splitCandidate->GetRenderCostDecrease();
158
159                // cost ratio of cost decrease / totalCost
160                const float costRatio = splitCandidate->GetRenderCostDecrease() / mTotalCost;
161
162                if (costRatio < mTermMinGlobalCostRatio)
163                        ++ mGlobalCostMisses;
164       
165                /*Debug << "\n**********" << endl
166                          << "total cost: " << mTotalCost << " render cost decr: "
167                          << splitCandidate->GetRenderCostDecrease()
168                          << " cost ratio: " << costRatio << endl << endl;*/
169
170                //-- subdivide leaf node
171
172                if (SubdivideSubdivisionCandidate(splitCandidate))
173                {
174                        // subdivision successful
175                        EvalSubdivisionStats(*splitCandidate);
176               
177                        // reevaluate candidates affected by the split
178                        // for view space splits, this would be object space splits
179                        // and other way round
180                        if (repair)
181                                RepairQueue();
182
183                        cout << "candidate: " << splitCandidate->Type() << ", priority: " << splitCandidate->GetPriority() << endl;
184                }
185
186                DEL_PTR(splitCandidate);
187        }
188}
189
190
191void HierarchyManager::Construct2(const VssRayContainer &sampleRays,
192                                                                  const ObjectContainer &objects,
193                                                                  AxisAlignedBox3 *forcedViewSpace)
194{
195        // rays clipped in view space and in object space
196        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
197        RayInfoContainer *objectSpaceRays = new RayInfoContainer();
198
199
200        /////////////////////////////////////////////////////////////
201        // view space space partition
202        /////////////////////////////////////////////////////////////
203
204#if 0
205        // makes no sense otherwise because only one kd cell available
206        // during view space partition
207        const bool savedCountMethod = mVspTree.mUseKdPvsForHeuristics;
208        const bool savedStoreMethod = mVspTree.mStoreObjectPvs;
209       
210        mVspTree.mUseKdPvsForHeuristics = false;
211        mVspTree.mStoreObjectPvs = false;
212#endif
213
214        SubdivisionCandidate *vsc =
215                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, *viewSpaceRays);
216
217        // add to queue
218        mTQueue.Push(vsc);
219
220        long startTime = GetTime();
221        cout << "starting vsp contruction ... " << endl;
222
223        mVspTree->mVspStats.Reset();
224        mVspTree->mVspStats.Start();
225
226        int i = 0;
227
228        // all objects can be seen from everywhere
229        mTotalCost = (float)dynamic_cast<VspTree::VspSubdivisionCandidate *>(vsc)->mParentData.mPvs;
230
231        const bool repairQueue = false;
232
233        // process view space candidates
234        RunConstruction(repairQueue);
235
236        cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
237        mVspTree->mVspStats.Stop();
238
239
240        /////////////////////////////////////////////////////////////
241        // object space partition
242        /////////////////////////////////////////////////////////////
243
244
245        Debug << "\n$$$$$$$$$ osp tree construction $$$$$$$$$$\n" << endl;
246        cout << "starting osp contruction ... " << endl;
247
248        // start with one big kd cell - all objects can be seen from everywhere
249        // note: only true for view space = object space
250
251        // compute first candidate
252        SubdivisionCandidate *osc =
253                mOspTree->PrepareConstruction(sampleRays, objects, forcedViewSpace, *objectSpaceRays);
254
255        Debug << "reseting cost, new total cost: " << mTotalCost << endl;
256        mTotalCost = mOspTree->mTotalCost;
257
258    mTQueue.Push(osc);
259
260        mOspTree->mOspStats.Reset();
261        mOspTree->mOspStats.Start();
262
263        startTime = GetTime();
264       
265        // process object space candidates
266        RunConstruction(repairQueue);
267       
268        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
269
270        mOspTree->mOspStats.Stop();
271
272        //////////////////////////
273        // matt: only for debugging purpose
274
275        const float rc = mOspTree->EvalRenderCost(sampleRays);
276
277        Debug << "My render cost evalulation: " << rc << endl;
278
279#if 0
280        // reset parameters
281        mVspTree->mUseKdPvsForHeuristics = savedCountMethod;
282        mVspTree->mStoreObjectPvs = savedStoreMethod;
283#endif
284}
285
286
287void HierarchyManager::Construct3(const VssRayContainer &sampleRays,
288                                                                  const ObjectContainer &objects,
289                                                                  AxisAlignedBox3 *forcedViewSpace)
290{
291        // construct only view space partition
292        // object kd tree is taken for osp
293
294        mVspTree->mVspStats.Reset();
295        mVspTree->mVspStats.Start();
296
297        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
298       
299        SubdivisionCandidate *sc =
300                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, *viewSpaceRays);
301
302        mTQueue.Push(sc);
303
304        cout << "starting vsp contruction ... " << endl;
305
306        long startTime = GetTime();
307
308        RunConstruction(false);
309
310        cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
311        mVspTree->mVspStats.Stop();
312}
313
314
315bool HierarchyManager::FinishedConstruction() const
316{
317        return mTQueue.Empty();
318}
319
320
321void HierarchyManager::CollectObjectSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
322{
323        switch (mObjectSpaceSubdivisonType)
324        {
325        case KD_BASED_OBJ_SUBDIV:
326                {
327                        OspTree::OspSubdivisionCandidate *sc =
328                                dynamic_cast<OspTree::OspSubdivisionCandidate *>(mCurrentCandidate);
329
330                        mOspTree->CollectDirtyCandidates(sc, dirtyList);
331                        break;
332                }
333        case BV_BASED_OBJ_SUBDIV:
334                {
335                        BvHierarchy::BvhSubdivisionCandidate *sc =
336                                dynamic_cast<BvHierarchy::BvhSubdivisionCandidate *>(mCurrentCandidate);
337
338                        mBvHierarchy->CollectDirtyCandidates(sc, dirtyList);
339                        break;
340                }
341        default:
342                break;
343        }
344}
345
346
347void HierarchyManager::CollectViewSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
348{
349        VspTree::VspSubdivisionCandidate *sc =
350                dynamic_cast<VspTree::VspSubdivisionCandidate *>(mCurrentCandidate);
351
352        mVspTree->CollectDirtyCandidates(sc, dirtyList);
353}
354
355
356void HierarchyManager::CollectDirtyCandidates(SubdivisionCandidateContainer &dirtyList)
357{       
358        // we have either a object space or view space split
359        if (mCurrentCandidate->Type() == SubdivisionCandidate::VIEW_SPACE)
360        {
361                CollectViewSpaceDirtyList(dirtyList);
362        }
363        else // object space split
364        {       
365                CollectObjectSpaceDirtyList(dirtyList);
366        }
367}
368
369
370void HierarchyManager::RepairQueue()
371{
372        // TODO
373        // for each update of the view space partition:
374        // the candidates from object space partition which
375        // have been afected by the view space split (the kd split candidates
376        // which saw the view cell which was split) must be reevaluated
377        // (maybe not locally, just reinsert them into the queue)
378        //
379        // vice versa for the view cells
380        // for each update of the object space partition
381        // reevaluate split candidate for view cells which saw the split kd cell
382        //
383        // the priority queue update can be solved by implementing a binary heap
384        // (explicit data structure, binary tree)
385        // *) inserting and removal is efficient
386        // *) search is not efficient => store queue position with each
387        // split candidate
388
389        // collect list of "dirty" candidates
390        vector<SubdivisionCandidate *> dirtyList;
391        CollectDirtyCandidates(dirtyList);
392       
393        //-- reevaluate the dirty list
394        vector<SubdivisionCandidate *>::const_iterator sit, sit_end = dirtyList.end();
395
396        for (sit = dirtyList.begin(); sit != sit_end; ++ sit)
397        {
398                SubdivisionCandidate* sc = *sit;
399
400                mTQueue.Erase(sc);
401
402                // reevaluate
403                sc->EvalPriority();
404
405                // reinsert
406                mTQueue.Push(sc);
407        }
408}
409
410
411}
Note: See TracBrowser for help on using the repository browser.