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

Revision 1314, 18.6 KB checked in by mattausch, 18 years ago (diff)

started osp mesh construction for obj files. Introduced new primitive faceintersectable

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):
38mObjectSpaceSubdivisionType(objectSpaceSubdivisionType),
39mVspTree(vspTree),
40mOspTree(NULL),
41mBvHierarchy(NULL)
42{
43        switch(mObjectSpaceSubdivisionType)
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        ParseEnvironment();
65}
66
67
68HierarchyManager::HierarchyManager(VspTree *vspTree, KdTree *kdTree):
69mObjectSpaceSubdivisionType(KD_BASED_OBJ_SUBDIV),
70mVspTree(vspTree),
71mBvHierarchy(NULL)
72{
73        mOspTree = new OspTree(*kdTree);
74        mOspTree->mVspTree = mVspTree;
75
76        //mOspTree->mHierarchyManager = this;
77        Debug << "creating osp tree" << endl;
78
79        if (mVspTree)
80                mVspTree->mHierarchyManager = this;
81
82        ParseEnvironment();
83}
84
85
86void HierarchyManager::ParseEnvironment()
87{
88        char subdivisionStatsLog[100];
89        Environment::GetSingleton()->GetStringValue("Hierarchy.subdivisionStats",
90                subdivisionStatsLog);
91        mSubdivisionStats.open(subdivisionStatsLog);
92
93        Environment::GetSingleton()->GetFloatValue(
94                "Hierarchy.Termination.minGlobalCostRatio", mTermMinGlobalCostRatio);
95        Environment::GetSingleton()->GetIntValue(
96                "Hierarchy.Termination.globalCostMissTolerance", mTermGlobalCostMissTolerance);
97
98        Environment::GetSingleton()->GetIntValue(
99                "Hierarchy.Termination.maxLeaves", mTermMaxLeaves);
100
101        Environment::GetSingleton()->GetIntValue(
102                "Hierarchy.Construction.type", mConstructionType);
103
104        Environment::GetSingleton()->GetIntValue(
105                "Hierarchy.Construction.minDepthForOsp", mMinDepthForObjectSpaceSubdivion);
106       
107        Environment::GetSingleton()->GetBoolValue(
108                "Hierarchy.Construction.repairQueue", mRepairQueue);
109
110        Debug << "******** Hierachy Manager Parameters ***********" << endl;
111        Debug << "max leaves: " << mTermMaxLeaves << endl;
112        Debug << "min global cost ratio: " << mTermMinGlobalCostRatio << endl;
113        Debug << "global cost miss tolerance: " << mTermGlobalCostMissTolerance << endl;
114        Debug << "construction type: " << mConstructionType << endl;
115        Debug << "min depth for object space subdivision: " << mMinDepthForObjectSpaceSubdivion << endl;
116        Debug << "repair queue: " << mRepairQueue << endl;
117}
118
119
120HierarchyManager::~HierarchyManager()
121{
122        DEL_PTR(mOspTree);
123        //DEL_PTR(mVspTree);
124        DEL_PTR(mBvHierarchy);
125}
126
127
128void HierarchyManager::SetViewCellsManager(ViewCellsManager *vcm)
129{
130        mVspTree->SetViewCellsManager(vcm);
131
132        if (mOspTree)
133                mOspTree->SetViewCellsManager(vcm);
134        if (mBvHierarchy)
135                mBvHierarchy->SetViewCellsManager(vcm);
136}
137
138
139void HierarchyManager::SetViewCellsTree(ViewCellsTree *vcTree)
140{
141        mVspTree->SetViewCellsTree(vcTree);
142}
143
144
145SubdivisionCandidate *HierarchyManager::NextSubdivisionCandidate()
146{
147        SubdivisionCandidate *splitCandidate = mTQueue.Top();
148        mTQueue.Pop();
149
150        return splitCandidate;
151}
152
153
154void HierarchyManager::EvalSubdivisionStats(const SubdivisionCandidate &tData)
155{
156        const float costDecr = tData.GetRenderCostDecrease();
157
158        switch (mObjectSpaceSubdivisionType)
159        {
160        case KD_BASED_OBJ_SUBDIV:
161                AddSubdivisionStats(mOspTree->mOspStats.Leaves() + mVspTree->mVspStats.Leaves(),
162                                                        costDecr,
163                                                        mTotalCost
164                                                        );
165                break;
166        case BV_BASED_OBJ_SUBDIV:
167                AddSubdivisionStats(mBvHierarchy->mBvhStats.Leaves() + mVspTree->mVspStats.Leaves(),
168                                                        costDecr,
169                                                        mTotalCost
170                                                        );
171                break;
172        default:
173                AddSubdivisionStats(mVspTree->mVspStats.Leaves(),
174                                                        costDecr,
175                                                        mTotalCost
176                                                        );
177                break;
178        }
179}
180
181
182void HierarchyManager::AddSubdivisionStats(const int splits,
183                                                                                   const float renderCostDecr,
184                                                                                   const float totalRenderCost)
185{
186        mSubdivisionStats
187                        << "#Splits\n" << splits << endl
188                        << "#RenderCostDecrease\n" << renderCostDecr << endl
189                        << "#TotalRenderCost\n" << totalRenderCost << endl;
190                        //<< "#AvgRenderCost\n" << avgRenderCost << endl;
191}
192
193
194bool HierarchyManager::GlobalTerminationCriteriaMet(SubdivisionCandidate *candidate) const
195{
196        return (0
197                || (mHierarchyStats.Leaves() >= mTermMaxLeaves)
198                //|| (mGlobalCostMisses >= mTermGlobalCostMissTolerance)
199                ||      candidate->GlobalTerminationCriteriaMet()
200                );
201}
202
203
204void HierarchyManager::Construct(const VssRayContainer &sampleRays,
205                                                                 const ObjectContainer &objects,
206                                                                 AxisAlignedBox3 *forcedViewSpace)
207{
208       
209        mHierarchyStats.Reset();
210        mHierarchyStats.Start();
211       
212        mTotalCost = (float)objects.size();
213        Debug << "setting total cost to " << mTotalCost << endl;
214
215        const long startTime = GetTime();
216        cout << "Constructing view space / object space tree ... \n";
217       
218        // process object space candidates
219        RunConstruction(sampleRays, objects, forcedViewSpace);
220       
221        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
222        mHierarchyStats.Stop();
223        mVspTree->mVspStats.Stop();
224}
225
226
227void HierarchyManager::PrepareViewSpaceSubdivision(const VssRayContainer &sampleRays,
228                                                                                                   const ObjectContainer &objects,
229                                                                                                   AxisAlignedBox3 *forcedViewSpace)
230{
231        RayInfoContainer *viewSpaceRays = new RayInfoContainer();
232        SubdivisionCandidate *vsc =
233                mVspTree->PrepareConstruction(sampleRays, forcedViewSpace, *viewSpaceRays);
234
235        mTQueue.Push(vsc);
236}
237
238
239void HierarchyManager::PrepareObjectSpaceSubdivision(const VssRayContainer &sampleRays,
240                                                                                                         const ObjectContainer &objects)
241{
242        if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
243        {
244                PrepareOspTree(sampleRays, objects);
245        }
246        else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
247        {
248                PrepareBvHierarchy(sampleRays, objects);
249        }
250}
251
252
253void HierarchyManager::PrepareBvHierarchy(const VssRayContainer &sampleRays,
254                                                                                  const ObjectContainer &objects)
255
256{
257        cout << "starting bv hierarchy construction ... " << endl;
258
259        mBvHierarchy->CreateRoot(objects);
260
261        // compute first candidate
262        SubdivisionCandidate *sc =
263                mBvHierarchy->PrepareConstruction(sampleRays, objects);
264
265        mTotalCost = mBvHierarchy->mTotalCost;
266        Debug << "reseting cost, new total cost: " << mTotalCost << endl;
267
268    mTQueue.Push(sc);
269}
270
271
272void HierarchyManager::PrepareOspTree(const VssRayContainer &sampleRays,
273                                                                          const ObjectContainer &objects)
274{
275        RayInfoContainer *objectSpaceRays = new RayInfoContainer();
276
277        cout << "starting osp tree construction ... " << endl;
278
279        // start with one big kd cell - all objects can be seen from everywhere
280        // note: only true for view space = object space
281
282        // compute first candidate
283        SubdivisionCandidate *osc =
284                mOspTree->PrepareConstruction(sampleRays, objects, *objectSpaceRays);
285
286        mTotalCost = mOspTree->mTotalCost;
287        Debug << "reseting cost, new total cost: " << mTotalCost << endl;
288       
289    mTQueue.Push(osc);
290}
291
292
293bool HierarchyManager::ApplySubdivisionCandidate(SubdivisionCandidate *sc)
294{
295        const bool globalTerminationCriteriaMet = GlobalTerminationCriteriaMet(sc);
296        const bool vspSplit = (sc->Type() == SubdivisionCandidate::VIEW_SPACE);
297
298        if (vspSplit)
299        {
300                VspNode *n = mVspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
301
302                if (n->IsLeaf()) // local or global termination criteria failed
303                        return false;
304        }
305        else
306        {
307                if (mObjectSpaceSubdivisionType == KD_BASED_OBJ_SUBDIV)
308                {
309                        KdNode *n = mOspTree->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
310
311                        if (n->IsLeaf()) // local or global termination criteria failed
312                                return false;
313                }
314                else if (mObjectSpaceSubdivisionType == BV_BASED_OBJ_SUBDIV)
315                {
316                        BvhNode *n = mBvHierarchy->Subdivide(mTQueue, sc, globalTerminationCriteriaMet);
317
318                        if (n->IsLeaf()) // local or global termination criteria failed
319                                return false;
320                }
321        }
322        return true;//!globalTerminationCriteriaMet;
323}
324
325
326bool HierarchyManager::StartObjectSpaceSubdivision() const
327{
328        const bool ospDepthReached =
329                (mMinDepthForObjectSpaceSubdivion <= mVspTree->mVspStats.maxDepth);
330        const bool stillNotOsp = (mObjectSpaceSubdivisionType == NO_OBJ_SUBDIV);
331   
332        return stillNotOsp && (mTQueue.Empty() || ((mConstructionType == 1) && ospDepthReached));
333}
334
335
336void HierarchyManager::RunConstruction(const VssRayContainer &sampleRays,
337                                                                           const ObjectContainer &objects,
338                                                                           AxisAlignedBox3 *forcedViewSpace)
339{
340        mHierarchyStats.nodes = 0;
341        mGlobalCostMisses = 0;
342
343        // use objects for evaluating vsp tree construction in the first levels
344        // of the subdivision
345        const int savedObjectSpaceSubdivisionType = mObjectSpaceSubdivisionType;
346        mObjectSpaceSubdivisionType = NO_OBJ_SUBDIV;
347
348        // start with view space subdivison: prepare vsp tree for traversal
349        PrepareViewSpaceSubdivision(sampleRays, objects, forcedViewSpace);
350
351        // start object space subdivision immediately?
352        if (StartObjectSpaceSubdivision())
353        {cout << "here1155 ";
354                mObjectSpaceSubdivisionType = savedObjectSpaceSubdivisionType;
355                PrepareObjectSpaceSubdivision(sampleRays, objects);
356        }
357
358        int i = 0;
359        while (!FinishedConstruction())
360        {
361                mCurrentCandidate = NextSubdivisionCandidate();   
362                mTotalCost -= mCurrentCandidate->GetRenderCostDecrease();
363
364                // cost ratio of cost decrease / totalCost
365                const float costRatio = mCurrentCandidate->GetRenderCostDecrease() / mTotalCost;
366
367                //Debug << "ratio: " << costRatio << " min ratio: " << mTermMinGlobalCostRatio << endl;
368                if (costRatio < mTermMinGlobalCostRatio)
369                {
370                        ++ mGlobalCostMisses;
371                }
372               
373                //-- subdivide leaf node
374                if (ApplySubdivisionCandidate(mCurrentCandidate))
375                {
376                        cout << "subdividing candidate " << ++ i << " of type " << mCurrentCandidate->Type() << endl;
377                        mHierarchyStats.nodes += 2;
378
379                        // subdivision successful
380                        EvalSubdivisionStats(*mCurrentCandidate);
381               
382                        // reevaluate candidates affected by the split for view space splits,
383                        // this would be object space splits and other way round
384                        if (mRepairQueue) RepairQueue();
385                }
386
387                // we use objects for evaluating vsp tree construction until
388                // a certain depth once a certain depth existiert ....
389                if (StartObjectSpaceSubdivision())
390                {
391                        mObjectSpaceSubdivisionType = savedObjectSpaceSubdivisionType;
392
393                        cout << "starting object space subdivision at maximal view space subdivison depth " << mVspTree->mVspStats.maxDepth << " (" << mMinDepthForObjectSpaceSubdivion << ") " << endl;
394                        PrepareObjectSpaceSubdivision(sampleRays, objects);
395
396                        cout << "reseting queue ... ";
397                        ResetQueue();
398                        cout << "finished" << endl;
399                }
400
401                DEL_PTR(mCurrentCandidate);
402        }
403       
404        mObjectSpaceSubdivisionType = savedObjectSpaceSubdivisionType;
405}
406
407
408bool HierarchyManager::FinishedConstruction() const
409{
410        return mTQueue.Empty();
411}
412
413
414bool HierarchyManager::ObjectSpaceSubdivisionConstructed() const
415{
416        switch (mObjectSpaceSubdivisionType)
417        {
418        case KD_BASED_OBJ_SUBDIV:
419                return mOspTree && mOspTree->GetRoot();
420        case BV_BASED_OBJ_SUBDIV:
421                return mBvHierarchy && mOspTree->GetRoot();
422        default:
423        return false;
424        }
425}
426
427
428void HierarchyManager::CollectObjectSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
429{
430        switch (mObjectSpaceSubdivisionType)
431        {
432        case KD_BASED_OBJ_SUBDIV:
433                {
434                        OspTree::OspSubdivisionCandidate *sc =
435                                dynamic_cast<OspTree::OspSubdivisionCandidate *>(mCurrentCandidate);
436
437                        mOspTree->CollectDirtyCandidates(sc, dirtyList);
438                        break;
439                }
440        case BV_BASED_OBJ_SUBDIV:
441                {
442                        BvHierarchy::BvhSubdivisionCandidate *sc =
443                                dynamic_cast<BvHierarchy::BvhSubdivisionCandidate *>(mCurrentCandidate);
444
445                        mBvHierarchy->CollectDirtyCandidates(sc, dirtyList);
446                        break;
447                }
448        default:
449                break;
450        }
451}
452
453
454void HierarchyManager::CollectViewSpaceDirtyList(SubdivisionCandidateContainer &dirtyList)
455{
456        VspTree::VspSubdivisionCandidate *sc =
457                dynamic_cast<VspTree::VspSubdivisionCandidate *>(mCurrentCandidate);
458
459        mVspTree->CollectDirtyCandidates(sc, dirtyList);
460}
461
462
463void HierarchyManager::CollectDirtyCandidates(SubdivisionCandidateContainer &dirtyList)
464{
465        // we have either a object space or view space split
466        if (mCurrentCandidate->Type() == SubdivisionCandidate::VIEW_SPACE)
467        {
468                CollectViewSpaceDirtyList(dirtyList);
469        }
470        else // object space split
471        {
472                CollectObjectSpaceDirtyList(dirtyList);
473        }
474}
475
476
477void HierarchyManager::RepairQueue()
478{
479        // for each update of the view space partition:
480        // the candidates from object space partition which
481        // have been afected by the view space split (the kd split candidates
482        // which saw the view cell which was split) must be reevaluated
483        // (maybe not locally, just reinsert them into the queue)
484        //
485        // vice versa for the view cells
486        // for each update of the object space partition
487        // reevaluate split candidate for view cells which saw the split kd cell
488        //
489        // the priority queue update can be solved by implementing a binary heap
490        // (explicit data structure, binary tree)
491        // *) inserting and removal is efficient
492        // *) search is not efficient => store queue position with each
493        // split candidate
494
495        // collect list of "dirty" candidates
496        long startTime = GetTime();
497   
498        vector<SubdivisionCandidate *> dirtyList;
499        CollectDirtyCandidates(dirtyList);
500        cout << "repairing " << (int)dirtyList.size() << " candidates ... ";
501       
502        //-- reevaluate the dirty list
503        SubdivisionCandidateContainer::const_iterator sit, sit_end = dirtyList.end();
504       
505        for (sit = dirtyList.begin(); sit != sit_end; ++ sit)
506        {
507                SubdivisionCandidate* sc = *sit;
508                const float rcd = sc->GetRenderCostDecrease();
509               
510                mTQueue.Erase(sc); // erase from queue
511                sc->EvalPriority(); // reevaluate
512               
513                /*
514                Debug << "candidate " << sc << " reevaluated\n"
515                          << "render cost decrease diff " <<  rcd - sc->GetRenderCostDecrease()
516                          << " old: " << rcd << " new " << sc->GetRenderCostDecrease() << endl;*/
517                if (0)
518                {
519                        const float rcDiff =  rcd - sc->GetRenderCostDecrease();
520                        mTotalCost += rcDiff;
521                }
522                mTQueue.Push(sc); // reinsert
523        }
524
525        long endTime = GetTime();
526        Real timeDiff = TimeDiff(startTime, endTime);
527
528        mHierarchyStats.repairTime += timeDiff;
529
530        cout << "finished in " << timeDiff * 1e-3f << " secs" << endl;
531}
532
533
534void HierarchyManager::ResetQueue()
535{
536        SubdivisionCandidateContainer mCandidateBuffer;
537
538        // remove from queue
539        while (!mTQueue.Empty())
540        {
541                SubdivisionCandidate *candidate = NextSubdivisionCandidate();
542                candidate->EvalPriority(); // reevaluate
543                cout << ".";
544                mCandidateBuffer.push_back(candidate);
545        }
546
547        // put back into queue
548        SubdivisionCandidateContainer::const_iterator sit, sit_end = mCandidateBuffer.end();
549    for (sit = mCandidateBuffer.begin(); sit != sit_end; ++ sit)
550        {cout << ":";
551                mTQueue.Push(*sit);
552        }
553}
554
555
556void HierarchyManager::ExportObjectSpaceHierarchy(OUT_STREAM &stream)
557{
558        // the type of the view cells hierarchy
559        switch (mObjectSpaceSubdivisionType)
560        {
561        case KD_BASED_OBJ_SUBDIV:
562                stream << "<ObjectSpaceHierarchy type=\"osp\">" << endl;
563                mOspTree->Export(stream);
564                stream << endl << "</ObjectSpaceHierarchy>" << endl;
565                break;         
566        case BV_BASED_OBJ_SUBDIV:
567                stream << "<ObjectSpaceHierarchy type=\"bvh\">" << endl;
568                mBvHierarchy->Export(stream);
569                stream << endl << "</ObjectSpaceHierarchy>" << endl;
570                break;
571        }
572}
573
574
575bool HierarchyManager::AddSampleToPvs(Intersectable *obj,
576                                                                          const Vector3 &hitPoint,
577                                                                          ViewCell *vc,
578                                                                          const float pdf,
579                                                                          float &contribution) const
580{
581        if (!obj) return false;
582
583        switch (mObjectSpaceSubdivisionType)
584        {
585        case NO_OBJ_SUBDIV:
586                // potentially visible objects
587                return vc->AddPvsSample(obj, pdf, contribution);
588        case KD_BASED_OBJ_SUBDIV:
589                {
590                        // potentially visible kd cells
591                        KdLeaf *leaf = mOspTree->GetLeaf(hitPoint/*ray->mOriginNode*/);
592                        return mOspTree->AddLeafToPvs(leaf, vc, pdf, contribution);
593                }
594        case BV_BASED_OBJ_SUBDIV:
595                {
596                        BvhLeaf *leaf = mBvHierarchy->GetLeaf(obj);
597                        return mBvHierarchy->AddLeafToPvs(leaf, vc, pdf, contribution);
598                }
599        default:
600                return false;
601        }
602}
603
604
605void HierarchyManager::PrintHierarchyStatistics(ofstream &stream) const
606{
607        stream << mHierarchyStats << endl;
608
609        stream << "\nview space:" << endl << endl;
610        stream << mVspTree->GetStatistics() << endl;
611        stream << "\nobject space:" << endl << endl;
612        switch (mObjectSpaceSubdivisionType)
613        {
614        case KD_BASED_OBJ_SUBDIV:
615                {
616                        stream << mOspTree->GetStatistics() << endl;
617                        break;
618                }
619        case BV_BASED_OBJ_SUBDIV:
620                {
621                        stream << mBvHierarchy->GetStatistics() << endl;
622                        break;
623                }
624        default:
625                break;
626        }
627}
628
629
630void HierarchyManager::ExportObjectSpaceHierarchy(Exporter *exporter,
631                                                                                                  const ObjectContainer &objects) const
632{
633        switch (mObjectSpaceSubdivisionType)
634        {
635        case KD_BASED_OBJ_SUBDIV:
636                {
637                        ExportOspTree(exporter, objects);
638                        break;
639                }
640        case BV_BASED_OBJ_SUBDIV:
641                {
642                        ExportBvHierarchy(exporter, objects);
643                        break;
644                }
645        default:
646                break;
647        }
648}
649
650
651void HierarchyManager::ExportBvHierarchy(Exporter *exporter,
652                                                                                 const ObjectContainer &objects) const
653{
654        exporter->SetWireframe();
655        exporter->ExportBvHierarchy(*mBvHierarchy, 0);
656}
657
658
659void HierarchyManager::ExportOspTree(Exporter *exporter,
660                                                                         const ObjectContainer &objects) const
661{
662        if (0) exporter->ExportGeometry(objects);
663                       
664        exporter->SetWireframe();
665        exporter->ExportOspTree(*mOspTree, 0);
666}
667
668
669void HierarchyStatistics::Print(ostream &app) const
670{
671        app << "=========== Hierarchy statistics ===============\n";
672
673        app << setprecision(4);
674
675        app << "#N_CTIME  ( Construction time [s] )\n" << Time() << " \n";
676       
677        app << "#N_RTIME  ( Repair time [s] )\n" << repairTime * 1e-3f << " \n";
678
679        app << "#N_NODES ( Number of nodes )\n" << nodes << "\n";
680
681        app << "#N_INTERIORS ( Number of interior nodes )\n" << Interior() << "\n";
682
683        app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n";
684
685        app << "#N_PMAXDEPTH ( Maximal reached depth )\n" << maxDepth << endl;
686       
687        app << "========== END OF Hierarchy statistics ==========\n";
688}
689
690
691}
Note: See TracBrowser for help on using the repository browser.