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

Revision 1284, 15.0 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,
37                                                                   const int objectSpaceSubdivisionType):
38mObjectSpaceSubdivisonType(objectSpaceSubdivisionType),
39mVspTree(vspTree),
40mOspTree(NULL),
41mBvHierarchy(NULL)
42{
43        switch(mObjectSpaceSubdivisonType)
44        {
45        case KD_BASED_OBJ_SUBDIV:
46                mOspTree = new OspTree();
47                mOspTree->mVspTree = mVspTree;
48                //mOspTree->mHierarchyManager = this;
49                Debug << "creating osp tree" << endl;
50                break;
51        case BV_BASED_OBJ_SUBDIV:
52        mBvHierarchy = new BvHierarchy();
53                mBvHierarchy->mVspTree = mVspTree;
54                //mBvHierarchy->mHierarchyManager = this;
55                Debug << "creating bv hierachy" << endl;
56                break;
57        default:
58                break;
59        }
60
61        if (mVspTree)
62                mVspTree->mHierarchyManager = this;
63
64        char subdivisionStatsLog[100];
65        Environment::GetSingleton()->GetStringValue("Hierarchy.subdivisionStats",
66                subdivisionStatsLog);
67        mSubdivisionStats.open(subdivisionStatsLog);
68}
69
70
71HierarchyManager::HierarchyManager(VspTree *vspTree, KdTree *kdTree):
72mObjectSpaceSubdivisonType(KD_BASED_OBJ_SUBDIV),
73mVspTree(vspTree),
74mBvHierarchy(NULL)
75{
76        mOspTree = new OspTree(*kdTree);
77        mOspTree->mVspTree = mVspTree;
78
79        //mOspTree->mHierarchyManager = this;
80        Debug << "creating osp tree" << endl;
81
82        if (mVspTree)
83                mVspTree->mHierarchyManager = this;
84
85        char subdivisionStatsLog[100];
86        Environment::GetSingleton()->GetStringValue("Hierarchy.subdivisionStats",
87                subdivisionStatsLog);
88        mSubdivisionStats.open(subdivisionStatsLog);
89}
90
91
92HierarchyManager::~HierarchyManager()
93{
94        DEL_PTR(mOspTree);
95        //DEL_PTR(mVspTree);
96        DEL_PTR(mBvHierarchy);
97}
98
99
100void HierarchyManager::SetViewCellsManager(ViewCellsManager *vcm)
101{
102        mVspTree->SetViewCellsManager(vcm);
103
104        if (mOspTree)
105                mOspTree->SetViewCellsManager(vcm);
106        if (mBvHierarchy)
107                mBvHierarchy->SetViewCellsManager(vcm);
108}
109
110
111void HierarchyManager::SetViewCellsTree(ViewCellsTree *vcTree)
112{
113        mVspTree->SetViewCellsTree(vcTree);
114}
115
116
117SubdivisionCandidate *HierarchyManager::NextSubdivisionCandidate()
118{
119        SubdivisionCandidate *splitCandidate = mTQueue.Top();
120        mTQueue.Pop();
121
122        return splitCandidate;
123}
124
125
126void HierarchyManager::PrepareConstruction(const VssRayContainer &sampleRays,
127                                                                                   const ObjectContainer &objects,
128                                                                                   AxisAlignedBox3 *forcedViewSpace,
129                                                                                   RayInfoContainer &viewSpaceRays,
130                                                                                   RayInfoContainer &objectSpaceRays)
131{
132        SubdivisionCandidate *vsc =
133                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, viewSpaceRays);
134        mTQueue.Push(vsc);
135
136        SubdivisionCandidate *osc =
137                mOspTree->PrepareConstruction(sampleRays, objects, forcedViewSpace, objectSpaceRays);
138
139        mTQueue.Push(osc);
140}
141
142
143void HierarchyManager::EvalSubdivisionStats(const SubdivisionCandidate &tData)
144{
145        const float costDecr = tData.GetRenderCostDecrease();
146
147        //mTotalCost -= costDecr;
148        //mTotalPvsSize += tFrontData.mPvs + tBackData.mPvs - tData.mPvs;
149
150        AddSubdivisionStats(mOspTree->mOspStats.Leaves() + mVspTree->mVspStats.Leaves(),
151                                                costDecr,
152                                                mTotalCost
153                                                );
154}
155
156
157void HierarchyManager::AddSubdivisionStats(const int splits,
158                                                                                   const float renderCostDecr,
159                                                                                   const float totalRenderCost)
160{
161        mSubdivisionStats
162                        << "#Splits\n" << splits << endl
163                        << "#RenderCostDecrease\n" << renderCostDecr << endl
164                        << "#TotalRenderCost\n" << totalRenderCost << endl;
165                        //<< "#AvgRenderCost\n" << avgRenderCost << endl;
166}
167
168
169bool HierarchyManager::GlobalTerminationCriteriaMet(SubdivisionCandidate *candidate) const
170{
171        // TODO matt: make virtual by creating superclasss for traveral data
172        return candidate->GlobalTerminationCriteriaMet();
173}
174
175
176void HierarchyManager::Construct(const VssRayContainer &sampleRays,
177                                                                 const ObjectContainer &objects,
178                                                                 AxisAlignedBox3 *forcedViewSpace)
179{
180        RayInfoContainer *objectSpaceRays = new RayInfoContainer();
181        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
182
183        // prepare vsp and osp trees for traversal
184        PrepareConstruction(sampleRays, objects, forcedViewSpace, *viewSpaceRays, *objectSpaceRays);
185
186        mVspTree->mVspStats.Reset();
187        mVspTree->mVspStats.Start();
188
189        cout << "Constructing view space / object space tree ... \n";
190        const long startTime = GetTime();       
191       
192        RunConstruction(true);
193
194        cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
195
196        mVspTree->mVspStats.Stop();
197}
198
199
200bool HierarchyManager::SubdivideSubdivisionCandidate(SubdivisionCandidate *sc)
201{
202        const bool globalTerminationCriteriaMet =
203                        GlobalTerminationCriteriaMet(sc);
204
205        const bool vspSplit = (sc->Type() == SubdivisionCandidate::VIEW_SPACE);
206
207        if (vspSplit)
208        {
209                VspNode *n = mVspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
210        }
211        else
212        {
213                KdNode *n = mOspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
214        }
215       
216        return !globalTerminationCriteriaMet;
217}
218
219
220void HierarchyManager::RunConstruction(const bool repair)
221{
222        int numNodes = 0;
223
224        while (!FinishedConstruction())
225        {
226                SubdivisionCandidate *splitCandidate = NextSubdivisionCandidate();
227           
228                mTotalCost -= splitCandidate->GetRenderCostDecrease();
229
230                // cost ratio of cost decrease / totalCost
231                const float costRatio = splitCandidate->GetRenderCostDecrease() / mTotalCost;
232
233                if (costRatio < mTermMinGlobalCostRatio)
234                        ++ mGlobalCostMisses;
235       
236                /*Debug << "\n**********" << endl
237                          << "total cost: " << mTotalCost << " render cost decr: "
238                          << splitCandidate->GetRenderCostDecrease()
239                          << " cost ratio: " << costRatio << endl << endl;*/
240
241                //-- subdivide leaf node
242
243                if (SubdivideSubdivisionCandidate(splitCandidate))
244                {
245                        // subdivision successful
246                        EvalSubdivisionStats(*splitCandidate);
247               
248                        // reevaluate candidates affected by the split
249                        // for view space splits, this would be object space splits
250                        // and other way round
251                        if (repair)
252                                RepairQueue();
253
254                        cout << "candidate: " << splitCandidate->Type() << ", priority: " << splitCandidate->GetPriority() << endl;
255                }
256
257                DEL_PTR(splitCandidate);
258        }
259}
260
261
262void HierarchyManager::Construct2(const VssRayContainer &sampleRays,
263                                                                  const ObjectContainer &objects,
264                                                                  AxisAlignedBox3 *forcedViewSpace)
265{
266        // rays clipped in view space and in object space
267        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
268        RayInfoContainer *objectSpaceRays = new RayInfoContainer();
269
270
271        /////////////////////////////////////////////////////////////
272        // view space space partition
273        /////////////////////////////////////////////////////////////
274
275#if 0
276        // makes no sense otherwise because only one kd cell available
277        // during view space partition
278        const bool savedCountMethod = mVspTree.mUseKdPvsForHeuristics;
279        const bool savedStoreMethod = mVspTree.mStoreObjectPvs;
280       
281        mVspTree.mUseKdPvsForHeuristics = false;
282        mVspTree.mStoreObjectPvs = false;
283#endif
284        SubdivisionCandidate *vsc =
285                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, *viewSpaceRays);
286       
287        // add to queue
288        mTQueue.Push(vsc);
289
290        long startTime = GetTime();
291        cout << "starting vsp contruction ... " << endl;
292
293        mVspTree->mVspStats.Reset();
294        mVspTree->mVspStats.Start();
295
296        int i = 0;
297
298        // all objects can be seen from everywhere
299        mTotalCost = (float)dynamic_cast<VspTree::VspSubdivisionCandidate *>(vsc)->mParentData.mPvs;
300
301        const bool repairQueue = false;
302
303        // process view space candidates
304        RunConstruction(repairQueue);
305
306        cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
307        mVspTree->mVspStats.Stop();
308
309
310        /////////////////////////////////////////////////////////////
311        // object space partition
312        /////////////////////////////////////////////////////////////
313
314
315        Debug << "\n$$$$$$$$$ osp tree construction $$$$$$$$$$\n" << endl;
316        cout << "starting osp contruction ... " << endl;
317
318        // start with one big kd cell - all objects can be seen from everywhere
319        // note: only true for view space = object space
320
321        // compute first candidate
322        SubdivisionCandidate *osc =
323                mOspTree->PrepareConstruction(sampleRays, objects, forcedViewSpace, *objectSpaceRays);
324
325        Debug << "reseting cost, new total cost: " << mTotalCost << endl;
326        mTotalCost = mOspTree->mTotalCost;
327
328    mTQueue.Push(osc);
329
330        mOspTree->mOspStats.Reset();
331        mOspTree->mOspStats.Start();
332
333        startTime = GetTime();
334       
335        // process object space candidates
336        RunConstruction(repairQueue);
337       
338        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
339
340        mOspTree->mOspStats.Stop();
341
342        //////////////////////////
343        // matt: only for debugging purpose
344
345        const float rc = mOspTree->EvalRenderCost(sampleRays);
346
347        Debug << "My render cost evalulation: " << rc << endl;
348
349#if 0
350        // reset parameters
351        mVspTree->mUseKdPvsForHeuristics = savedCountMethod;
352        mVspTree->mStoreObjectPvs = savedStoreMethod;
353#endif
354}
355
356
357void HierarchyManager::Construct3(const VssRayContainer &sampleRays,
358                                                                  const ObjectContainer &objects,
359                                                                  AxisAlignedBox3 *forcedViewSpace)
360{
361        // construct only view space partition
362        // object kd tree is taken for osp
363
364        mVspTree->mVspStats.Reset();
365        mVspTree->mVspStats.Start();
366
367        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
368       
369        SubdivisionCandidate *sc =
370                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, *viewSpaceRays);
371
372        mTQueue.Push(sc);
373
374        cout << "starting vsp contruction ... " << endl;
375
376        long startTime = GetTime();
377
378        RunConstruction(false);
379
380        cout << "finished in " << TimeDiff(startTime, GetTime())*1e-3 << " secs" << endl;
381        mVspTree->mVspStats.Stop();
382}
383
384
385bool HierarchyManager::FinishedConstruction() const
386{
387        return mTQueue.Empty();
388}
389
390
391void HierarchyManager::CollectObjectSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
392{
393        switch (mObjectSpaceSubdivisonType)
394        {
395        case KD_BASED_OBJ_SUBDIV:
396                {
397                        OspTree::OspSubdivisionCandidate *sc =
398                                dynamic_cast<OspTree::OspSubdivisionCandidate *>(mCurrentCandidate);
399
400                        mOspTree->CollectDirtyCandidates(sc, dirtyList);
401                        break;
402                }
403        case BV_BASED_OBJ_SUBDIV:
404                {
405                        BvHierarchy::BvhSubdivisionCandidate *sc =
406                                dynamic_cast<BvHierarchy::BvhSubdivisionCandidate *>(mCurrentCandidate);
407
408                        mBvHierarchy->CollectDirtyCandidates(sc, dirtyList);
409                        break;
410                }
411        default:
412                break;
413        }
414}
415
416
417void HierarchyManager::CollectViewSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
418{
419        VspTree::VspSubdivisionCandidate *sc =
420                dynamic_cast<VspTree::VspSubdivisionCandidate *>(mCurrentCandidate);
421
422        mVspTree->CollectDirtyCandidates(sc, dirtyList);
423}
424
425
426void HierarchyManager::CollectDirtyCandidates(SubdivisionCandidateContainer &dirtyList)
427{       
428        // we have either a object space or view space split
429        if (mCurrentCandidate->Type() == SubdivisionCandidate::VIEW_SPACE)
430        {
431                CollectViewSpaceDirtyList(dirtyList);
432        }
433        else // object space split
434        {       
435                CollectObjectSpaceDirtyList(dirtyList);
436        }
437}
438
439
440void HierarchyManager::RepairQueue()
441{
442        // TODO
443        // for each update of the view space partition:
444        // the candidates from object space partition which
445        // have been afected by the view space split (the kd split candidates
446        // which saw the view cell which was split) must be reevaluated
447        // (maybe not locally, just reinsert them into the queue)
448        //
449        // vice versa for the view cells
450        // for each update of the object space partition
451        // reevaluate split candidate for view cells which saw the split kd cell
452        //
453        // the priority queue update can be solved by implementing a binary heap
454        // (explicit data structure, binary tree)
455        // *) inserting and removal is efficient
456        // *) search is not efficient => store queue position with each
457        // split candidate
458
459        // collect list of "dirty" candidates
460        vector<SubdivisionCandidate *> dirtyList;
461        CollectDirtyCandidates(dirtyList);
462       
463        //-- reevaluate the dirty list
464        vector<SubdivisionCandidate *>::const_iterator sit, sit_end = dirtyList.end();
465
466        for (sit = dirtyList.begin(); sit != sit_end; ++ sit)
467        {
468                SubdivisionCandidate* sc = *sit;
469
470                mTQueue.Erase(sc);
471
472                // reevaluate
473                sc->EvalPriority();
474
475                // reinsert
476                mTQueue.Push(sc);
477        }
478}
479
480
481void HierarchyManager::ExportObjectSpaceHierarchy(OUT_STREAM &stream)
482{
483        // the type of the view cells hierarchy
484        switch (mObjectSpaceSubdivisonType)
485        {
486        case KD_BASED_OBJ_SUBDIV:
487                stream << "<ObjectSpaceHierarchy type=\"osp\">" << endl;
488                mOspTree->Export(stream);
489                stream << endl << "</ObjectSpaceHierarchy>" << endl;
490                break;
491               
492        case BV_BASED_OBJ_SUBDIV:
493                stream << "<ObjectSpaceHierarchy type=\"bvh\">" << endl;
494                mBvHierarchy->Export(stream);
495                stream << endl << "</ObjectSpaceHierarchy>" << endl;
496                break;
497        }
498}
499
500
501bool HierarchyManager::AddSampleToPvs(Intersectable *obj,
502                                                                          const Vector3 &hitPoint,
503                                                                          ViewCell *vc,
504                                                                          const float pdf,
505                                                                          float &contribution) const
506{
507        if (!obj) return false;
508
509        switch (mObjectSpaceSubdivisonType)
510        {
511        case NO_OBJ_SUBDIV:
512                // potentially visible objects
513                return vc->AddPvsSample(obj, pdf, contribution);
514
515        case KD_BASED_OBJ_SUBDIV:
516                {
517                        // potentially visible kd cells
518                        KdLeaf *leaf = mOspTree->GetLeaf(hitPoint/*ray->mOriginNode*/);
519                        return mOspTree->AddLeafToPvs(leaf, vc, pdf, contribution);
520                }
521        case BV_BASED_OBJ_SUBDIV:
522                {
523                        BvhLeaf *leaf = mBvHierarchy->GetLeaf(obj);
524                        return mBvHierarchy->AddLeafToPvs(leaf, vc, pdf, contribution);
525                }
526        default:
527                return false;
528        }
529}
530
531
532void HierarchyManager::PrintObjectSpaceHierarchyStatistics(ofstream &stream) const
533{
534        switch (mObjectSpaceSubdivisonType)
535        {
536        case KD_BASED_OBJ_SUBDIV:
537                {
538                        stream << mOspTree->GetStatistics();
539                        break;
540                }
541        case BV_BASED_OBJ_SUBDIV:
542                {
543                        stream << mBvHierarchy->GetStatistics();
544                        break;
545                }
546        default:
547                break;
548        }
549}
550
551
552void HierarchyManager::ExportObjectSpaceHierarchyForViz(const ObjectContainer &objects) const
553{
554        if (mOspTree && mOspTree->GetRoot())
555        {       
556                //-- export final object partition
557                Exporter *exporter = Exporter::GetExporter("final_object_partition.wrl");
558               
559                if (exporter)
560                {
561                        cout << "exporting object space partition ... ";
562
563                        if (1)
564                        {
565                                exporter->ExportGeometry(objects);
566                        }
567                       
568#if 0           
569                        // export rays
570                        exporter->ExportRays(visRays, RgbColor(0, 1, 0));
571#endif
572
573                        exporter->SetWireframe();
574       
575                        const int colorCode = 0;
576                        const int maxPvs = 0;//mOspTree.GetStatistics().maxPvs;
577
578                        exporter->ExportOspTree(*mOspTree, 0);
579
580                        delete exporter;
581
582                        cout << "finished" << endl;
583                }
584        }
585}
586
587}
Note: See TracBrowser for help on using the repository browser.