source: GTP/trunk/Lib/Vis/Preprocessing/src/ViewCellsManager.cpp @ 703

Revision 703, 99.3 KB checked in by mattausch, 19 years ago (diff)

started implementation of visibility filter

RevLine 
[440]1#include "ViewCellsManager.h"
2#include "RenderSimulator.h"
3#include "Mesh.h"
4#include "Triangle3.h"
5#include "ViewCell.h"
6#include "Environment.h"
7#include "X3dParser.h"
8#include "ViewCellBsp.h"
9#include "KdTree.h"
10#include "VspKdTree.h"
11#include "Exporter.h"
[442]12#include "VspBspTree.h"
[508]13#include "ViewCellsParser.h"
[532]14#include "Beam.h"
[540]15#include "VssPreprocessor.h"
16#include "RssPreprocessor.h"
[440]17
[667]18#define SAMPLE_AFTER_SUBDIVISION 1
[694]19#define TEST_EMPTY_VIEW_CELLS 0
[517]20
[697]21
22
23template <typename T> class myless
24{
25public:
26        //bool operator() (HierarchyNode *v1, HierarchyNode *v2) const
27        bool operator() (T v1, T v2) const
28        {
29                return (v1->GetMergeCost() < v2->GetMergeCost());
30        }
31};
32
33typedef priority_queue<ViewCell *, vector<ViewCell *>, myless<vector<ViewCell *>::value_type> > FilterQueue;
34
35
36
[440]37ViewCellsManager::ViewCellsManager():
[480]38mRenderer(NULL),
[574]39mInitialSamples(0),
[440]40mConstructionSamples(0),
41mPostProcessSamples(0),
[470]42mVisualizationSamples(0),
43mTotalAreaValid(false),
[517]44mTotalArea(0.0f),
[547]45mViewCellsFinished(false),
[562]46mMaxPvsSize(9999999),
[564]47mMinPvsSize(0), // one means only empty view cells are invalid
[561]48mMaxPvsRatio(1.0)
[440]49{
[542]50        mViewSpaceBox.Initialize();
[482]51        ParseEnvironment();
[580]52
53        mViewCellsTree = new ViewCellsTree(this);
[440]54}
55
[517]56
[482]57void ViewCellsManager::ParseEnvironment()
58{
[503]59        // visualization stuff
[485]60        environment->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
61        environment->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
[547]62        environment->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
[664]63       
[564]64        bool emptyViewCells = false;
65        environment->GetBoolValue("ViewCells.pruneEmptyViewCells", emptyViewCells);
[664]66        mMinPvsSize = emptyViewCells ? 1 : 0;
67
[564]68        environment->GetBoolValue("ViewCells.processOnlyValidViewCells", mOnlyValidViewCells);
[485]69
[574]70        environment->GetIntValue("ViewCells.Construction.samples", mConstructionSamples);
71        environment->GetIntValue("ViewCells.PostProcess.samples", mPostProcessSamples);
[595]72        environment->GetBoolValue("ViewCells.PostProcess.useRaysForMerge", mUseRaysForMerge);
73
[574]74        environment->GetIntValue("ViewCells.Visualization.samples", mVisualizationSamples);
75
76        environment->GetIntValue("ViewCells.Construction.samplesPerPass", mSamplesPerPass);
[577]77        environment->GetBoolValue("ViewCells.exportToFile", mExportViewCells);
[581]78       
[600]79        environment->GetIntValue("ViewCells.active", mNumActiveViewCells);
[586]80        environment->GetBoolValue("ViewCells.PostProcess.compress", mCompressViewCells);
[660]81        environment->GetBoolValue("ViewCells.Visualization.useClipPlane", mUseClipPlaneForViz);
[591]82        environment->GetBoolValue("ViewCells.PostProcess.merge", mMergeViewCells);
[664]83        environment->GetBoolValue("ViewCells.evaluateViewCells", mEvaluateViewCells);
[666]84        environment->GetBoolValue("ViewCells.showVisualization", mShowVisualization);
[697]85        environment->GetIntValue("ViewCells.Filter.maxSize", mMaxFilterSize);
86        environment->GetFloatValue("ViewCells.Filter.width", mFilterWidth);
87
[664]88        char buf[100];
89        environment->GetStringValue("ViewCells.samplingType", buf);
90
[660]91       
[664]92        if (strcmp(buf, "box") == 0)
[660]93                mSamplingType = Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
[664]94        else if (strcmp(buf, "directional") == 0)
[660]95                mSamplingType = Preprocessor::DIRECTION_BASED_DISTRIBUTION;
[666]96        else
97        {
98                Debug << "error! wrong sampling type" << endl;
99                exit(0);
100        }
[660]101
[482]102        environment->GetStringValue("ViewCells.Visualization.colorCode", buf);
[503]103
[482]104        if (strcmp(buf, "PVS") == 0)
105                mColorCode = 1;
106        else if (strcmp(buf, "MergedLeaves") == 0)
107                mColorCode = 2;
108        else if (strcmp(buf, "MergedTreeDiff") == 0)
109                mColorCode = 3;
110        else
111                mColorCode = 0;
112
[664]113
114        Debug << "***********View Cells options ****************" << endl;
115        Debug << "color code: " << mColorCode << endl;
116
117        Debug << "export rays: " << mExportRays << endl;
118        Debug << "export geometry: " << mExportGeometry << endl;
119        Debug << "max pvs ratio: " << mMaxPvsRatio << endl;
120       
121        Debug << "prune empty view cells: " << emptyViewCells << endl;
122       
123        Debug << "process only valid view cells: " << mOnlyValidViewCells << endl;
124        Debug << "construction samples: " << mConstructionSamples << endl;
125        Debug << "post process samples: " << mPostProcessSamples << endl;
126        Debug << "post process use rays for merge: " << mUseRaysForMerge << endl;
127        Debug << "visualization samples: " << mVisualizationSamples << endl;
128        Debug << "construction samples per pass: " << mSamplesPerPass << endl;
129        Debug << "export to file: " << mExportViewCells << endl;
130       
131        Debug << "active: " << mNumActiveViewCells << endl;
132        Debug << "post process compress: " << mCompressViewCells << endl;
133        Debug << "visualization use clipPlane: " << mUseClipPlaneForViz << endl;
134        Debug << "post process merge: " << mMergeViewCells << endl;
135        Debug << "evaluate view cells: " << mEvaluateViewCells << endl;
136        Debug << "sampling type: " << mSamplingType << endl;
[666]137        Debug << "show visualization: " << mShowVisualization << endl;
[697]138        Debug << "filter width: " << mFilterWidth << endl;
[664]139
140        Debug << endl;
[440]141}
142
[485]143
[440]144ViewCellsManager::~ViewCellsManager()
145{
[480]146        DEL_PTR(mRenderer);
[580]147
[598]148        if (!ViewCellsTreeConstructed())
149                CLEAR_CONTAINER(mViewCells);
150        else
151                DEL_PTR(mViewCellsTree);
152
[503]153        CLEAR_CONTAINER(mMeshContainer);
[440]154}
155
[485]156
[693]157void ViewCellsManager::CollectEmptyViewCells()
158{
159        mEmptyViewCells.clear();
160        ViewCellContainer leaves;
161        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
162
163        ViewCellContainer::const_iterator it, it_end = leaves.end();
164
165        cout << "collecting empty view cells" << endl;
[694]166       
[693]167        for (it = leaves.begin(); it != it_end; ++ it)
168        {
169                if ((*it)->GetPvs().Empty())
170                {
171                        mEmptyViewCells.push_back(*it);
172                }
173        }
[694]174        Debug << "empty view cells found: " << (int)mEmptyViewCells.size() << endl;
[693]175}
176
177
[694]178void ViewCellsManager::TestEmptyViewCells(const ObjectContainer &obj)
[693]179{
180        ViewCellContainer::const_iterator it, it_end = mEmptyViewCells.end();
181
182        char buf[50];
183        int i = 0;
184        for (it = mEmptyViewCells.begin(); it != it_end; ++ it)
185        {
186                if (!(*it)->GetPvs().Empty())
187                {
[694]188                        sprintf(buf, "empty-viewcells-%09d.x3d", i/*(*it)->GetId()*/);
[693]189                        Exporter *exporter = Exporter::GetExporter(buf);
190                       
191                        if (exporter && i < 20)
192                        {
[694]193                                Ray *pray = (*it)->mPiercingRays[0];
[697]194                                Debug << "view cell " << (*it)->GetId() << " not empty, pvs: " << (*it)->GetPvs().GetSize() << " " << (int)pray->intersections.size() << endl;
[694]195
196                                exporter->ExportRays((*it)->mPiercingRays);
197                                                       
198                                exporter->SetFilled();
199                                exporter->SetForcedMaterial(RgbColor(0,0,1));
200
201                                for (int j = 0; j < (int)pray->intersections.size(); ++ j)
202                                {
203                                        if (pray->intersections[j].mObject)
204                                                exporter->ExportIntersectable(pray->intersections[j].mObject);
205                                }
206
207                                //exporter->SetWireframe();
208                                exporter->SetForcedMaterial(RgbColor(0,1,0));
209                                exporter->ExportGeometry(obj);
210
211                                exporter->SetFilled();
212
213                                exporter->SetForcedMaterial(RgbColor(1,0,0));
[693]214                                ExportViewCellGeometry(exporter, *it);
[694]215
216                                delete exporter;               
[693]217                        }
218
[694]219               
[693]220                        ++ i;
221                }
222        }
[694]223        Debug << "\nSampled " << i << " new view cells (" << " of " << (int)mEmptyViewCells.size() << ")" << endl << endl;
[693]224}
225
226
[574]227int ViewCellsManager::CastPassSamples(const int samplesPerPass,
228                                                                          const int sampleType,
229                                                                          VssRayContainer &passSamples) const
[527]230{
[570]231        SimpleRayContainer simpleRays;
[540]232
[573]233        preprocessor->GenerateRays(samplesPerPass,
234                                                           sampleType,
[570]235                                                           simpleRays);
[564]236
[573]237        // shoot simple ray and add it to importance samples
238        preprocessor->CastRays(simpleRays, passSamples);
[570]239
[574]240        return (int)passSamples.size();
241}
[570]242
[574]243
[607]244
[574]245/// helper function which destroys rays or copies them into the output ray container
[639]246inline void disposeRays(VssRayContainer &rays, VssRayContainer *outRays)
[574]247{
248        cout << "disposing samples ... ";
[582]249        long startTime = GetTime();
250        int n = (int)rays.size();
251
[573]252        if (outRays)
[542]253        {
[574]254                VssRayContainer::const_iterator it, it_end = rays.end();
255
256                for (it = rays.begin(); it != it_end; ++ it)
257                {
258                        outRays->push_back(*it);
259                }
[573]260        }
261        else
262        {
[639]263                VssRayContainer::const_iterator it, it_end = rays.end();
264
265                for (it = rays.begin(); it != it_end; ++ it)
266                {
267                        //(*it)->Unref();
268                        if (!(*it)->IsActive())
269                                delete (*it);
270                }
[573]271        }
[639]272
[574]273        cout << "finished" << endl;
[582]274        Debug << "disposed " << n << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[573]275}
[570]276
277
[573]278int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays)
279{
280        int numSamples = 0;
281        SimpleRayContainer simpleRays;
282       
[574]283        VssRayContainer initialSamples;
[540]284
[574]285        cout << "view cell construction: casting " << mInitialSamples << " initial samples ... ";
[573]286        //-- construction rays => we use uniform samples for this
[574]287        CastPassSamples(mInitialSamples,
[660]288                                        mSamplingType,
[574]289                                        initialSamples);
[573]290       
[574]291        cout << "finished" << endl;
292
[660]293       
[573]294        // construct view cells
[574]295        const int numInitialSamples =
296                ConstructSubdivision(preprocessor->mObjects, initialSamples);
[540]297
[574]298        numSamples += numInitialSamples;
[542]299
[574]300        // rays can be passed or deleted
[639]301        disposeRays(initialSamples, outRays);
[574]302       
[697]303        cout << "testing filter ... ";
[570]304
[697]305        TestFilter(preprocessor->mObjects);
306
307        cout << "finished" << endl;
308
[660]309        // -- stats after contruction
310        ResetViewCells();
311
[667]312        Debug << "\nView cells after initial sampling:\n" << mCurrentViewCellsStats << endl;
313
[683]314        if (1) // export initial view cells
[660]315        {
316                cout << "exporting initial view cells (=leaves) ... ";
317                Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
318
319                if (exporter)
320                {
321                        if (mExportGeometry)
322                                exporter->ExportGeometry(preprocessor->mObjects);
323
324                        ExportViewCellsForViz(exporter);
325
326                        delete exporter;
327                }
328                cout << "finished" << endl;
329        }
330
[573]331        //-- guided rays are used for further sampling
[574]332        const int n = mConstructionSamples; //+initialSamples;
[570]333
[666]334        // should we use directional samples?
[694]335        bool dirSamples = (mSamplingType == Preprocessor::DIRECTION_BASED_DISTRIBUTION);
[573]336
337        while (numSamples < n)
338        {
[596]339                cout << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
[574]340                VssRayContainer constructionSamples;
341
[694]342                const int samplingType = mSamplingType;
343                        /*dirSamples ?
[574]344                                                Preprocessor::DIRECTION_BASED_DISTRIBUTION :
[694]345                                                Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;*/
[667]346
[600]347                if (0)
[666]348                        dirSamples = !dirSamples; // toggle sampling method
[667]349
[574]350                numSamples += CastPassSamples(mSamplesPerPass,
[666]351                                                                          samplingType,
[574]352                                                                          constructionSamples);
353
354                cout << "finished" << endl;
355
356                cout << "computing sample contribution for " << (int)constructionSamples.size() << " samples ... ";
357
358                // TODO: leak?
[605]359                if (SAMPLE_AFTER_SUBDIVISION)
360                        ComputeSampleContributions(constructionSamples, true, false);
[574]361                cout << "finished" << endl;
362
363
[639]364                disposeRays(constructionSamples, outRays);
[574]365
366                cout << "total samples: " << numSamples << endl;
[542]367        }
[573]368       
[570]369
[573]370        //-- post processing
371        VssRayContainer postProcessSamples;
[570]372
[694]373        //-- construction rays
[574]374        CastPassSamples(mPostProcessSamples,
[694]375                                        mSamplingType,
[574]376                                        postProcessSamples);
[660]377
378
379        // stats before post processing (i.e., merge)
380        EvaluateViewCellsStats();
381        Debug << "\noriginal view cell partition before post process:\n" << mCurrentViewCellsStats << endl;
382
383        mRenderer->RenderScene();
384        SimulationStatistics ss;
385        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
386
387    Debug << ss << endl;
388
389
390
[574]391        cout << "starting post processing and visualization" << endl;
392
[660]393
[666]394        // store view cells for postprocessing
[574]395        const bool storeViewCells = true;
[605]396
[660]397
[605]398        if (SAMPLE_AFTER_SUBDIVISION)
399                ComputeSampleContributions(postProcessSamples, true, storeViewCells);
[663]400
[570]401        // merge the view cells
[573]402        PostProcess(preprocessor->mObjects, postProcessSamples);
[570]403
[693]404        // only for testing
[694]405        if (TEST_EMPTY_VIEW_CELLS)
406                CollectEmptyViewCells();
[570]407
[693]408
[574]409        //-- visualization
[666]410        if (mShowVisualization)
411        {
412                VssRayContainer visualizationSamples;
[574]413
[666]414                //-- construction rays => we use uniform samples for this
415                CastPassSamples(mVisualizationSamples,
416                                            Preprocessor::DIRECTION_BASED_DISTRIBUTION,
417                                                visualizationSamples);
[574]418
[666]419                if (SAMPLE_AFTER_SUBDIVISION)
420                        ComputeSampleContributions(visualizationSamples, true, storeViewCells);
[574]421
[666]422                // different visualizations
423                Visualize(preprocessor->mObjects, visualizationSamples);
[574]424
[666]425                disposeRays(visualizationSamples, outRays);
426        }
[574]427
[664]428        if (mEvaluateViewCells)
429        {
[666]430                EvalViewCellPartition(preprocessor);
[664]431        }
[666]432       
[667]433        if (0)
434        {
435                ViewCellContainer leaves;
436                mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
437                mViewCellsTree->ResetPvs();
438                VssRayContainer dummyRays;
439                CastPassSamples(mInitialSamples, mSamplingType, dummyRays);
[666]440       
[667]441                //ComputeSampleContributions(initialSamples, true, false);
442                ComputeSampleContributions(dummyRays, true, false);
[664]443
[667]444                ViewCellContainer::const_iterator it, it_end = leaves.end();
[666]445
[667]446                for (it = leaves.begin(); it != it_end; ++ it)
447                {
448                        mViewCellsTree->PropagatePvs(*it);
449                }
450
451                mViewCellsTree->ExportStats("dummy.log");
[666]452        }
453
[573]454        return numSamples;
[527]455}
456
[547]457
[664]458void ViewCellsManager::EvalViewCellPartition(Preprocessor *preprocessor)
[660]459{
460        int samplesPerPass;
461        int numSamples;
462        int castSamples = 0;
463
[664]464        char s[64];
465
[660]466        environment->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
467        environment->GetIntValue("ViewCells.Evaluation.samples", numSamples);
468
[664]469        char statsPrefix[100];
470        environment->GetStringValue("ViewCells.Evaluation.statsPrefix", statsPrefix);
[663]471
[664]472        Debug << "view cell evaluation samples per pass: " << samplesPerPass << endl;
473        Debug << "view cell evaluation samples: " << numSamples << endl;
474        Debug << "view cell stats prefix: " << statsPrefix << endl;
475
476        //VssRayContainer outRays;
[666]477        // should directional sampling be used?
478        bool dirSamples = mSamplingType == Preprocessor::DIRECTION_BASED_DISTRIBUTION;
[664]479
480        cout << "Evaluating view cell partition" << endl;
481
482        ViewCellContainer leaves;
483        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
484
[666]485        bool startFromZero = true;
486
487        // reset pvs and start over from zero
488        if (startFromZero)
489        {
490                mViewCellsTree->ResetPvs();
491        }
492        else // statistics without addidtional samples
493        {
494                cout << "compute new statistics ... ";
495                sprintf(s, "-%09d-eval.log", castSamples);
496                string fName = string(statsPrefix) + string(s);
497
498                mViewCellsTree->ExportStats(fName);
499                cout << "finished" << endl;
500        }
501       
502
[660]503        while (castSamples < numSamples)
504        {
[664]505                VssRayContainer evaluationSamples;
[663]506
[666]507                const int samplingType = mSamplingType;
508                /*      dirSamples ?
[664]509                                                Preprocessor::DIRECTION_BASED_DISTRIBUTION :
510                                                Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
[666]511                */
[664]512                //-- construction rays => we use uniform samples for this
513                CastPassSamples(samplesPerPass, samplingType, evaluationSamples);
514               
515                castSamples += samplesPerPass;
516
517                cout << "casting " << (int)evaluationSamples.size() << " samples " << endl;
518
519                ComputeSampleContributions(evaluationSamples, true, false);
520
521                cout << "compute new statistics ... ";
522
523                ViewCellContainer::const_iterator it, it_end = leaves.end();
524
525                for (it = leaves.begin(); it != it_end; ++ it)
526                {
527                        mViewCellsTree->PropagatePvs(*it);
528                }
529
530                // output stats
[667]531                sprintf(s, "-%09d-eval.log", castSamples);
[664]532                string fileName = string(statsPrefix) + string(s);
533
534                mViewCellsTree->ExportStats(fileName);
535
536                cout << "finished" << endl;
537       
538                disposeRays(evaluationSamples, NULL);
[660]539        }
[693]540
541        // find empty view cells bug
[694]542        if (TEST_EMPTY_VIEW_CELLS)
543                TestEmptyViewCells(preprocessor->mObjects);
[660]544}
545
[703]546/*
547int ViewCellsManager::ConstructLocalMergeTree(vector<LocalMergeCandidate> candidates)
548                                                                                         
549{
550        while(!candidates.empty())
551        {
552                MergeCandidate mc = candidates.back();
553                candidates.pop_back();
554                EvalMergeCost(mc);
555                mergeQueue.push(mc);
556        }
[660]557
[703]558        ViewCell::NewMail();
559
560       
561        long startTime = GetTime();
562
563        mergeStats.candidates = (int)mMergeQueue.size();
564
565        // passes are needed for statistics, because we don't want to record
566        // every merge
567        int pass = 0;
568        int mergedPerPass = 0;
569        float realExpectedCost = mExpectedCost;
570        float realAvgRenderCost = mAvgRenderCost;
571        int realNumActiveViewCells = mNumActiveViewCells;
572       
573         reset.
574
575        int numMergedViewCells = 0;
576
577        environment->GetIntValue("ViewCells.PostProcess.maxMergesPerPass", maxMergesPerPass);
578        environment->GetFloatValue("ViewCells.PostProcess.avgCostMaxDeviation", avgCostMaxDeviation);
579
580        cout << "actual merge starts now ... " << endl;
581
582        //-- use priority queue to merge leaf pairs
583
584        //const float maxAvgCost = 350;
585        while (!mMergeQueue.empty())//NumActiveViewCells > mMergeMinViewCells))
586        {
587                //-- reset merge queue if the ratio of current expected cost / real expected cost
588                //   too small or after a given number of merges
589                if ((mergedPerPass > maxMergesPerPass) ||
590                        (avgCostMaxDeviation > mAvgRenderCost / realAvgRenderCost))
591                {
592                        // adjust render cost
593                        ++ pass;
594
595                        mergedPerPass = 0;
596                        mExpectedCost = realExpectedCost;
597                                       
598                       
599               
600                        // refines the view cells
601                        // then priorities are recomputed
602                        // and the candidates are put back into merge queue
603                        if (mRefineViewCells)
604                                RefineViewCells(rays, objects);
605                        else
606                                ResetMergeQueue();
607
608                        Debug << "Values after reset: " 
609                                  << " erc: " << mExpectedCost
610                                  << " avg: " << mAvgRenderCost
611                                  << " dev: " << mDeviation << endl;
612
613                        if (mExportMergedViewCells)
614                        {
615                                ExportMergedViewCells(activeViewCells, objects, numMergedViewCells);
616                        }
617                }
618
619
620                MergeCandidate mc = mMergeQueue.top();
621                mMergeQueue.pop();
622       
623                // both view cells equal
624                // NOTE: do I really still need this? probably cannot happen!!
625                if (mc.mLeftViewCell == mc.mRightViewCell)
626                        continue;
627
628                if (mc.IsValid())
629                {
630                        ViewCell::NewMail();
631
632                        //-- update statistical values
633                        -- realNumActiveViewCells;
634                        ++ mergeStats.merged;
635                        ++ mergedPerPass;
636
637                        const float renderCostIncr = mc.GetRenderCost();
638                        const float mergeCostIncr = mc.GetMergeCost();
639
640                        totalRenderCost += renderCostIncr;
641                        mDeviation += mc.GetDeviationIncr();
642                       
643                       
644                        // merge the view cells of leaf1 and leaf2
645                        int pvsDiff;
646                        ViewCellInterior *mergedVc =
647                                MergeViewCells(mc.mLeftViewCell, mc.mRightViewCell, pvsDiff);
648
649
650                        // total render cost and deviation has changed
651                        // real expected cost will be larger than expected cost used for the
652                        // cost heuristics, but cannot recompute costs on each increase of the
653                        // expected cost
654                        totalPvs += pvsDiff;
655                        realExpectedCost = totalRenderCost / (float)realNumActiveViewCells;
656                        realAvgRenderCost = (float)totalPvs / (float)realNumActiveViewCells;
657       
658                        // set merge cost to this node
659                        mergedVc->SetMergeCost(totalRenderCost);
660
661                        //if (mViewCellsManager->EqualToSpatialNode(mergedVc))
662                        //      ++ mergeStats.siblings;
663                        mergedVc->SetCost(realExpectedCost);
664
665                        if ((mergeStats.merged % statsOut) == 0)
666                                cout << "merged " << mergeStats.merged << " view cells" << endl;
667
668                }
669                else
670                {
671                        // merge candidate not valid, because one of the leaves was already
672                        // merged with another one => validate and reinsert into queue
673                        if (ValidateMergeCandidate(mc))
674                        {
675                                EvalMergeCost(mc);
676                                mMergeQueue.push(mc);
677                        }
678                }
679               
680        }
681
682       
683        // adjust stats and reset queue one final time
684        mExpectedCost = realExpectedCost;
685        mAvgRenderCost = realAvgRenderCost;
686        mNumActiveViewCells = realNumActiveViewCells;
687
688        UpdateActiveViewCells(activeViewCells);
689
690       
691        // refine view cells and reset costs
692        if (mRefineViewCells)
693                RefineViewCells(rays, objects);
694        else
695                ResetMergeQueue();
696
697        // create a root node if the merge was not done till root level,
698        // else take the single node as new root
699        if ((int)activeViewCells.size() > 1)
700        {
701                Debug << "creating root of view cell hierarchy for "
702                          << (int)activeViewCells.size() << " view cells" << endl;
703               
704                ViewCellInterior *root = mViewCellsManager->MergeViewCells(activeViewCells);
705                root->SetMergeCost(totalRenderCost);
706                // $$JB keep this 0 temporarilly
707                root->SetCost(0.0f);
708
709                mRoot = root;
710        }
711        else if ((int)activeViewCells.size() == 1)
712        {
713                Debug << "setting root of the merge history" << endl;
714                mRoot = activeViewCells[0];
715        }
716
717        //-- empty merge queue just in case
718        while (!mMergeQueue.empty())
719        {
720                mMergeQueue.pop();
721        }
722
723        // TODO delete because makes no sense here
724        mergeStats.expectedRenderCost = realExpectedCost;
725        mergeStats.deviation = mDeviation;
726
727        // we want to optimize this heuristics
728        mergeStats.heuristics =
729                mDeviation * (1.0f - mRenderCostWeight) +
730                mExpectedCost * mRenderCostWeight;
731
732        mergeStats.mergeTime = TimeDiff(startTime, GetTime());
733        mergeStats.Stop();
734        Debug << mergeStats << endl << endl;
735
736        // assign colors for the view cells so that at least one is always consistent
737        AssignRandomColors();
738       
739        //TODO: should return sample contributions?
740        return mergeStats.merged;
741}
742*/
743
[564]744bool ViewCellsManager::CheckValidity(ViewCell *vc,
745                                                                         int minPvsSize,
[562]746                                                                         int maxPvsSize) const
[547]747{
[569]748
749  if ((vc->GetPvs().GetSize() > maxPvsSize) ||
750          (vc->GetPvs().GetSize() < minPvsSize))
[564]751        {
[569]752          return false;
[561]753        }
[570]754
[569]755  return true;
[547]756}
757
758
[697]759AxisAlignedBox3 ViewCellsManager::GetFilterBBox(const Vector3 &viewPoint,
760                                                                                                const float width) const
761{
762        Vector3 min = viewPoint - width * 0.5f;
763        Vector3 max = viewPoint + width * 0.5;
764
765        return AxisAlignedBox3(min, max);
766}
767
768
769void ViewCellsManager::GetPrVS(const Vector3 &viewPoint, PrVs &prvs)
770{
771        const AxisAlignedBox3 box = GetFilterBBox(viewPoint, mFilterWidth);
772
773        ViewCellContainer viewCells;
774        ComputeBoxIntersections(box, viewCells);
775
776               
777}
778
779
[581]780bool ViewCellsManager::ViewCellsTreeConstructed() const
781{
782        return mViewCellsTree->GetRoot();
783}
784
785
[564]786void ViewCellsManager::SetValidity(ViewCell *vc,
787                                                                   int minPvs,
[562]788                                                                   int maxPvs) const
789{
790        vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
791}
792
[577]793
[569]794void
795ViewCellsManager::SetValidity(
[570]796                                                          int minPvsSize,
[569]797                                                          int maxPvsSize) const
798{
799  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[570]800
[569]801  for (it = mViewCells.begin(); it != it_end; ++ it) {
802        SetValidity(*it, minPvsSize, maxPvsSize);
803  }
804}
[562]805
[569]806void
807ViewCellsManager::SetValidityPercentage(
808                                                                                const float minValid,
809                                                                                const float maxValid
810                                                                                )
811{
812  sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
[570]813
[569]814  int start = mViewCells.size()*minValid;
815  int end = mViewCells.size()*maxValid;
[570]816
[569]817  for (int i=0; i < mViewCells.size(); i++)
818        mViewCells[i]->SetValid(i >= start && i <= end);
819}
820
821int
822ViewCellsManager::CountValidViewcells() const
823{
824  ViewCellContainer::const_iterator it, it_end = mViewCells.end();
825  int valid = 0;
826  for (it = mViewCells.begin(); it != it_end; ++ it) {
827        if ((*it)->GetValid())
828          valid++;
829  }
830  return valid;
831}
832
[577]833
834bool ViewCellsManager::LoadViewCellsGeometry(const string filename)
[440]835{
836        X3dParser parser;
[503]837
[440]838        environment->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
[503]839
[440]840        bool success = parser.ParseFile(filename, *this);
841        Debug << (int)mViewCells.size() << " view cells loaded" << endl;
842
843        return success;
844}
845
[485]846
[487]847bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
848{
[542]849        viewPoint = mViewSpaceBox.GetRandomPoint();
[487]850
851        return true;
852}
853
854
[557]855float ViewCellsManager::GetViewSpaceVolume()
856{
[610]857        return mViewSpaceBox.GetVolume() * (2.0f * sqr((float)M_PI));
[557]858}
859
860
[490]861bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
862{
[569]863  if (!ViewCellsConstructed())
[542]864        return mViewSpaceBox.IsInside(viewPoint);
[569]865  else {
866        if (!mViewSpaceBox.IsInside(viewPoint))
867          return false;
868        ViewCell *viewcell = GetViewCell(viewPoint);
869        if (!viewcell || !viewcell->GetValid())
870          return false;
871  }
872  return true;
[490]873}
874
[501]875
[563]876float
877ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
[574]878                                                                                         const bool addRays,
879                                                                                         const bool storeViewCells
[563]880                                                                                         )
[440]881{
[563]882  // view cells not yet constructed
883  if (!ViewCellsConstructed())
884        return 0.0f;
[564]885
[563]886  VssRayContainer::const_iterator it, it_end = rays.end();
[503]887
[563]888  float sum = 0.0f;
[664]889  for (it = rays.begin(); it != it_end; ++ it)
890  {
891          sum += ComputeSampleContributions(*(*it), addRays, storeViewCells);
892          //ComputeSampleContributions(*(*it), addRays);
893          //    sum += (*it)->mPvsContribution;
[563]894  }
[664]895
[563]896  return sum;
[440]897}
898
[485]899
[479]900void ViewCellsManager::EvaluateViewCellsStats()
901{
[660]902        mCurrentViewCellsStats.Reset();
[479]903
904        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
905
906        for (it = mViewCells.begin(); it != it_end; ++ it)
[487]907        {
[660]908                mViewCellsTree->UpdateViewCellsStats(*it, mCurrentViewCellsStats);
[487]909        }
[479]910}
911
[485]912
[580]913void ViewCellsManager::EvaluateRenderStatistics(float &totalRenderCost,
[579]914                                                                                                float &expectedRenderCost,
[580]915                                                                                                float &deviation,
916                                                                                                float &variance,
917                                                                                                int &totalPvs,
918                                                                                                float &avgRenderCost)
[579]919{
920        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
921
[580]922
[579]923        //-- compute expected value
924
925        totalRenderCost = 0;
[580]926        totalPvs = 0;
[579]927
928        for (it = mViewCells.begin(); it != it_end; ++ it)
929        {
930                ViewCell *vc = *it;
931                totalRenderCost += vc->GetPvs().GetSize() * vc->GetVolume();
[580]932                totalPvs += (int)vc->GetPvs().GetSize();
[579]933        }
934
[580]935        // normalize with view space box
936        totalRenderCost /= mViewSpaceBox.GetVolume();
[579]937        expectedRenderCost = totalRenderCost / (float)mViewCells.size();
[580]938        avgRenderCost = totalPvs / (float)mViewCells.size();
[579]939
940
[580]941        //-- compute standard defiation
[579]942        variance = 0;
[580]943        deviation = 0;
[579]944
945        for (it = mViewCells.begin(); it != it_end; ++ it)
946        {
947                ViewCell *vc = *it;
948
949                float renderCost = vc->GetPvs().GetSize() * vc->GetVolume();
[580]950                float dev;
[579]951
[580]952                if (1)
953                        dev = fabs(avgRenderCost - (float)vc->GetPvs().GetSize());
954                else
955                        dev = fabs(expectedRenderCost - renderCost);
[579]956
[580]957                deviation += dev;
958                variance += dev * dev;
[579]959        }
[580]960
[579]961        variance /= (float)mViewCells.size();
[580]962        deviation /= (float)mViewCells.size();
[579]963}
964
965
966
[440]967void ViewCellsManager::AddViewCell(ViewCell *viewCell)
968{
969        mViewCells.push_back(viewCell);
970}
971
[485]972
[478]973float ViewCellsManager::GetArea(ViewCell *viewCell) const
974{
975        return viewCell->GetArea();
976}
977
978
979float ViewCellsManager::GetVolume(ViewCell *viewCell) const
980{
981        return viewCell->GetVolume();
982}
983
[485]984
[503]985void ViewCellsManager::DeriveViewCells(const ObjectContainer &objects,
986                                                                           ViewCellContainer &viewCells,
[440]987                                                                           const int maxViewCells) const
988{
989        // maximal max viewcells
[503]990        int limit = maxViewCells > 0 ?
[440]991                Min((int)objects.size(), maxViewCells) : (int)objects.size();
992
993        for (int i = 0; i < limit; ++ i)
994        {
995                Intersectable *object = objects[i];
[503]996
[440]997                // extract the mesh instances
998                if (object->Type() == Intersectable::MESH_INSTANCE)
999                {
1000                        MeshInstance *inst = dynamic_cast<MeshInstance *>(object);
1001
1002                        ViewCell *viewCell = GenerateViewCell(inst->GetMesh());
1003                        viewCells.push_back(viewCell);
1004                }
1005                //TODO: transformed meshes
1006        }
1007}
1008
[485]1009
[503]1010ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
[440]1011                                                                                        const float height) const
1012{
1013        // one mesh per view cell
1014        Mesh *mesh = new Mesh();
[503]1015
[440]1016        //-- construct prism
1017
[503]1018        // bottom
[440]1019        mesh->mFaces.push_back(new Face(2,1,0));
1020        // top
1021    mesh->mFaces.push_back(new Face(3,4,5));
1022        // sides
1023        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
1024        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
1025        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
1026
1027        //--- extrude new vertices for top of prism
1028        Vector3 triNorm = baseTri.GetNormal();
1029
[503]1030        Triangle3 topTri;
[440]1031
1032        // add base vertices and calculate top vertices
1033        for (int i = 0; i < 3; ++ i)
1034                mesh->mVertices.push_back(baseTri.mVertices[i]);
[503]1035
1036        // add top vertices
[440]1037        for (int i = 0; i < 3; ++ i)
1038                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
[503]1039
[440]1040        mesh->Preprocess();
1041
1042        return GenerateViewCell(mesh);
1043}
1044
[485]1045
[551]1046void ViewCellsManager::FinalizeViewCells(const bool createMesh)
1047{
1048        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[693]1049
1050        // volume and area of the view cells are recomputed and a view cell mesh is created
[551]1051        for (it = mViewCells.begin(); it != it_end; ++ it)
1052        {
1053                Finalize(*it, createMesh);
1054        }
[555]1055
1056        mTotalAreaValid = false;
[551]1057}
1058
1059
1060void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
1061{
1062        // implemented in subclasses
1063}
1064
1065
[582]1066ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCell *left, ViewCell *right) const
[440]1067{
[580]1068        // generate parent view cell
1069        ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
[462]1070
[610]1071        vc->GetPvs() = left->GetPvs();
[440]1072        // merge pvs
[610]1073        vc->GetPvs().Merge(right->GetPvs());
[440]1074
[462]1075        //-- merge ray sets
[564]1076        if (0)
1077        {
[582]1078                stable_sort(left->mPiercingRays.begin(), left->mPiercingRays.end());
1079                stable_sort(right->mPiercingRays.begin(), right->mPiercingRays.end());
[440]1080
[582]1081                std::merge(left->mPiercingRays.begin(), left->mPiercingRays.end(),
1082                                   right->mPiercingRays.begin(), right->mPiercingRays.end(),
[564]1083                                   vc->mPiercingRays.begin());
1084        }
[440]1085
[580]1086
[582]1087        vc->SetupChildLink(left);
1088        vc->SetupChildLink(right);
[580]1089
1090
[440]1091        return vc;
1092}
1093
[485]1094
[582]1095ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCellContainer &children) const
1096{
1097        ViewCellInterior *vc = new ViewCellInterior();//GenerateViewCell();
1098
1099        ViewCellContainer::const_iterator it, it_end = children.end();
1100
1101        for (it = children.begin(); it != it_end; ++ it)
1102        {
1103                // merge pvs
[610]1104                vc->GetPvs().Merge((*it)->GetPvs());
[582]1105
1106                vc->SetupChildLink(*it);
1107        }
1108
1109        return vc;
1110}
1111
1112
[480]1113void ViewCellsManager::SetRenderer(Renderer *renderer)
1114{
1115        mRenderer = renderer;
1116}
[441]1117
[485]1118
[580]1119ViewCellsTree *ViewCellsManager::GetViewCellsTree()
[440]1120{
[580]1121        return mViewCellsTree;
[440]1122}
1123
1124
1125void ViewCellsManager::SetVisualizationSamples(const int visSamples)
1126{
[444]1127        mVisualizationSamples = visSamples;
[440]1128}
1129
[485]1130
[440]1131void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
1132{
1133        mConstructionSamples = constructionSamples;
1134}
1135
[485]1136
[574]1137void ViewCellsManager::SetInitialSamples(const int initialSamples)
1138{
1139        mInitialSamples = initialSamples;
1140}
1141
1142
[440]1143void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
1144{
1145        mPostProcessSamples = postProcessSamples;
1146}
1147
[485]1148
[440]1149int ViewCellsManager::GetVisualizationSamples() const
1150{
1151        return mVisualizationSamples;
1152}
1153
[485]1154
[440]1155int ViewCellsManager::GetConstructionSamples() const
1156{
1157        return mConstructionSamples;
1158}
1159
[485]1160
[440]1161int ViewCellsManager::GetPostProcessSamples() const
1162{
1163        return mPostProcessSamples;
1164}
1165
[485]1166
1167void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
[467]1168{
1169  ViewCellContainer::const_iterator it = mViewCells.begin();
1170  stat.viewcells = 0;
1171  stat.minPvs = 100000000;
1172  stat.maxPvs = 0;
1173  stat.avgPvs = 0.0f;
1174
1175  for (; it != mViewCells.end(); ++it) {
1176        ViewCell *viewcell = *it;
1177        int pvsSize = viewcell->GetPvs().GetSize();
1178        if ( pvsSize < stat.minPvs)
1179          stat.minPvs = pvsSize;
1180        if (pvsSize > stat.maxPvs)
1181          stat.maxPvs = pvsSize;
1182        stat.avgPvs += pvsSize;
1183        stat.viewcells++;
1184  }
1185  if (stat.viewcells)
1186        stat.avgPvs/=stat.viewcells;
1187}
1188
[485]1189
[480]1190void ViewCellsManager::PrintPvsStatistics(ostream &s)
[467]1191{
1192  s<<"############# Viewcell PVS STAT ##################\n";
1193  PvsStatistics pvsStat;
1194  GetPvsStatistics(pvsStat);
1195  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
1196  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
1197  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
1198}
1199
[485]1200
[532]1201int ViewCellsManager::CastBeam(Beam &beam)
1202{
1203        return 0;
1204}
1205
[547]1206
[468]1207ViewCellContainer &ViewCellsManager::GetViewCells()
1208{
1209        return mViewCells;
1210}
1211
[485]1212
[487]1213void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
1214{
[542]1215        mViewSpaceBox = box;
[591]1216
[660]1217        CreateClipPlane();
[591]1218       
[577]1219        mTotalAreaValid = false;
[487]1220}
1221
1222
[660]1223void ViewCellsManager::CreateClipPlane()
[591]1224{
1225        int axis = 0;
[667]1226        float pos;
[591]1227
[667]1228        environment->GetFloatValue("ViewCells.Visualization.clipPlanePos", pos);
[591]1229
[667]1230        Vector3 point = mViewSpaceBox.Min() +  mViewSpaceBox.Size() * pos;
1231
[660]1232        if (mUseClipPlaneForViz)
1233        environment->GetIntValue("ViewCells.Visualization.clipPlaneAxis", axis);
[591]1234
1235        Vector3 normal(0,0,0);
1236        normal[axis] = 1;
1237
[660]1238        mClipPlane = Plane3(normal, point);
[591]1239}
1240
1241
[519]1242AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
1243{
[542]1244        return mViewSpaceBox;
[519]1245}
1246
1247
[480]1248void ViewCellsManager::ResetViewCells()
1249{
1250        mViewCells.clear();
[590]1251       
[480]1252        CollectViewCells();
[590]1253       
[660]1254        mCurrentViewCellsStats.Reset();
[480]1255        EvaluateViewCellsStats();
[590]1256
[520]1257        // has to be recomputed
[480]1258        mTotalAreaValid = false;
1259}
1260
[485]1261
[547]1262int ViewCellsManager::GetMaxPvsSize() const
1263{
1264        return mMaxPvsSize;
1265}
1266
[590]1267
[563]1268void
1269ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
1270{
1271  if (!ViewCellsConstructed())
1272        return;
[564]1273
[563]1274  VssRayContainer::const_iterator it, it_end = rays.end();
[564]1275
[563]1276  for (it = rays.begin(); it != it_end; ++ it) {
1277        AddSampleContributions(*(*it));
1278  }
1279}
[547]1280
[581]1281
[562]1282int ViewCellsManager::GetMinPvsSize() const
1283{
1284        return mMinPvsSize;
1285}
1286
1287
1288
[561]1289float ViewCellsManager::GetMaxPvsRatio() const
1290{
1291        return mMaxPvsRatio;
1292}
1293
1294
[563]1295void
1296ViewCellsManager::AddSampleContributions(VssRay &ray)
[468]1297{
[563]1298  // assumes viewcells have been stored...
1299  ViewCellContainer *viewcells = &ray.mViewCells;
1300  ViewCellContainer::const_iterator it;
1301  for (it = viewcells->begin(); it != viewcells->end(); ++it) {
1302        ViewCell *viewcell = *it;
[569]1303        if (viewcell->GetValid()) {
1304          // if ray not outside of view space
1305          viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
1306        }
[563]1307  }
1308}
[503]1309
[574]1310
[570]1311float ViewCellsManager::ComputeSampleContributions(VssRay &ray,
[574]1312                                                                                                   const bool addRays,
1313                                                                                                   const bool storeViewCells)
[563]1314{
[570]1315        ViewCellContainer viewcells;
[564]1316
[570]1317        ray.mPvsContribution = 0;
1318        ray.mRelativePvsContribution = 0.0f;
[485]1319
[570]1320        static Ray hray;
[564]1321        hray.Init(ray);
1322        //hray.mFlags |= Ray::CULL_BACKFACES;
1323        //Ray hray(ray);
1324
1325        float tmin = 0, tmax = 1.0;
1326
1327        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
[565]1328                return 0;
[564]1329
1330        Vector3 origin = hray.Extrap(tmin);
1331        Vector3 termination = hray.Extrap(tmax);
1332
1333        CastLineSegment(origin, termination, viewcells);
[664]1334
[570]1335        // copy viewcells memory efficiently
[574]1336        //const bool storeViewcells = !addRays;
[564]1337
[574]1338        if (storeViewCells)
[570]1339        {
1340                ray.mViewCells.reserve(viewcells.size());
1341                ray.mViewCells = viewcells;
1342        }
[564]1343
[570]1344        ViewCellContainer::const_iterator it = viewcells.begin();
[564]1345
[664]1346        for (; it != viewcells.end(); ++ it)
1347        {
1348                ViewCell *viewcell = *it;
[694]1349
[664]1350                if (viewcell->GetValid())
1351                {
[694]1352                        // HACK
1353                        if (TEST_EMPTY_VIEW_CELLS)
1354                                for (int i = 0; i < mEmptyViewCells.size(); ++i)
1355                                {
1356                                        if (viewcell == mEmptyViewCells[i])
1357                                        {
1358                                                viewcell->mPiercingRays.push_back(new Ray(ray));
1359                                                Debug << "empty view cell ray found: " << ray.mOriginObject << ", " << ray.mTerminationObject << endl;
1360                                        }
1361                                }
1362
[664]1363                        // if ray not outside of view space
1364                        float contribution;
[666]1365                        if (ray.mTerminationObject &&
1366                                viewcell->GetPvs().GetSampleContribution(ray.mTerminationObject,
[664]1367                                                                                                                 ray.mPdf,
1368                                                                                                                 contribution))
1369                        {
1370                                ++ ray.mPvsContribution;
1371                                ray.mRelativePvsContribution += contribution;
1372                        }
[666]1373                        if (ray.mOriginObject &&
1374                                viewcell->GetPvs().GetSampleContribution(ray.mOriginObject,
1375                                                                                                                 ray.mPdf,
1376                                                                                                                 contribution))
1377                        {
1378                                ++ ray.mPvsContribution;
1379                                ray.mRelativePvsContribution += contribution;
1380                        }
[664]1381                }
[569]1382        }
[564]1383
[664]1384       
1385        if (addRays)
1386        {
1387                for (it = viewcells.begin(); it != viewcells.end(); ++ it)
1388                {
1389                        ViewCell *viewcell = *it;
1390           
1391                        if (viewcell->GetValid())
1392                        {
1393                                // if ray not outside of view space
[666]1394                                 if (ray.mTerminationObject)
1395                                         viewcell->GetPvs().AddSample(ray.mTerminationObject, ray.mPdf);
1396                                 if (ray.mOriginObject)
1397                                         viewcell->GetPvs().AddSample(ray.mOriginObject, ray.mPdf);
[664]1398                        }
1399                }
[563]1400        }
[570]1401
1402        return ray.mRelativePvsContribution;
[468]1403}
1404
1405
[469]1406void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
[485]1407                                                                  const int maxSize,
[503]1408                                                                  VssRayContainer &usedRays,
[485]1409                                                                  VssRayContainer *savedRays) const
[469]1410{
[485]1411        const int limit = min(maxSize, (int)sourceRays.size());
[473]1412        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
[469]1413
[485]1414        VssRayContainer::const_iterator it, it_end = sourceRays.end();
[469]1415        for (it = sourceRays.begin(); it != it_end; ++ it)
1416        {
[473]1417                if (Random(1.0f) < prop)
[485]1418                        usedRays.push_back(*it);
1419                else if (savedRays)
1420                        savedRays->push_back(*it);
[469]1421        }
1422}
1423
[477]1424
[605]1425float ViewCellsManager::GetRendercost(ViewCell *viewCell, float objRendercost) const
1426{
1427        return mViewCellsTree->GetPvsSize(viewCell) * objRendercost;
1428}
1429
1430
[477]1431float ViewCellsManager::GetAccVcArea()
[470]1432{
1433        // if already computed
1434        if (mTotalAreaValid)
1435                return mTotalArea;
1436
1437        mTotalArea = 0;
1438        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1439
1440        for (it = mViewCells.begin(); it != it_end; ++ it)
[480]1441        {
1442                //Debug << "area: " << GetArea(*it);
[470]1443        mTotalArea += GetArea(*it);
[480]1444        }
1445
[470]1446        mTotalAreaValid = true;
1447
1448        return mTotalArea;
1449}
1450
[482]1451
[475]1452void ViewCellsManager::PrintStatistics(ostream &s) const
1453{
[660]1454        s << mCurrentViewCellsStats << endl;
[475]1455}
1456
[477]1457
[508]1458void ViewCellsManager::CreateUniqueViewCellIds()
[482]1459{
[651]1460        if (ViewCellsTreeConstructed())
1461                mViewCellsTree->CreateUniqueViewCellsIds();
1462        else
1463                for (int i = 0; i < (int)mViewCells.size(); ++ i)
1464                        mViewCells[i]->SetId(i);
[508]1465}
1466
1467
1468void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter) const
1469{
[482]1470        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1471
1472        for (it = mViewCells.begin(); it != it_end; ++ it)
1473        {
[574]1474                if (!mOnlyValidViewCells || (*it)->GetValid())
1475                {
[582]1476                        ExportColor(exporter, *it);             
[591]1477                        ExportViewCellGeometry(exporter, *it,
[660]1478                                mUseClipPlaneForViz ? &mClipPlane : NULL);
[574]1479                }
[482]1480        }
1481}
1482
1483
[517]1484void ViewCellsManager::CreateViewCellMeshes()
[503]1485{
1486        // convert to meshes
1487        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1488
1489        for (it = mViewCells.begin(); it != it_end; ++ it)
1490        {
[517]1491                if (!(*it)->GetMesh())
1492                        CreateMesh(*it);
[503]1493        }
1494}
1495
[508]1496
[564]1497bool ViewCellsManager::ExportViewCells(const string filename)
1498{
[508]1499        return false;
1500}
1501
1502
[610]1503void ViewCellsManager::CollectViewCells(const int n)
[508]1504{
[610]1505        mNumActiveViewCells = n;
1506        mViewCells.clear();
1507        CollectViewCells();
1508}
[508]1509
1510
[660]1511void ViewCellsManager::SetViewCellsActive()
1512{
1513        ++ ViewCell::sLastUpdated;
1514        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1515        for (it = mViewCells.begin(); it != it_end; ++ it)
1516        {
1517                (*it)->SetActive();
1518        }
1519}
[508]1520
[440]1521/**********************************************************************/
1522/*                   BspViewCellsManager implementation               */
1523/**********************************************************************/
1524
[482]1525
[574]1526BspViewCellsManager::BspViewCellsManager(BspTree *bspTree):
1527ViewCellsManager(), mBspTree(bspTree)
[440]1528{
[574]1529        environment->GetIntValue("BspTree.Construction.samples", mInitialSamples);
[587]1530        mBspTree->SetViewCellsManager(this);
[590]1531        mBspTree->mViewCellsTree = mViewCellsTree;
[440]1532}
1533
[462]1534
[440]1535bool BspViewCellsManager::ViewCellsConstructed() const
1536{
1537        return mBspTree->GetRoot() != NULL;
1538}
1539
[480]1540
[440]1541ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
1542{
1543        return new BspViewCell(mesh);
1544}
1545
[480]1546
[574]1547int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
1548                                                                                          const VssRayContainer &rays)
[440]1549{
[441]1550        // if view cells were already constructed
[440]1551        if (ViewCellsConstructed())
1552                return 0;
1553
1554        int sampleContributions = 0;
[503]1555
[469]1556        // construct view cells using the collected samples
1557        RayContainer constructionRays;
1558        VssRayContainer savedRays;
[440]1559
[574]1560        const int limit = min(mInitialSamples, (int)rays.size());
[440]1561
[469]1562        VssRayContainer::const_iterator it, it_end = rays.end();
[448]1563
[473]1564        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
1565
[469]1566        for (it = rays.begin(); it != it_end; ++ it)
1567        {
[473]1568                if (Random(1.0f) < prop)
[469]1569                        constructionRays.push_back(new Ray(*(*it)));
1570                else
1571                        savedRays.push_back(*it);
1572        }
[440]1573
[503]1574    if (mViewCells.empty())
1575        {
1576                // no view cells loaded
[587]1577                mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
[469]1578                // collect final view cells
1579                mBspTree->CollectViewCells(mViewCells);
[503]1580        }
[469]1581        else
1582        {
1583                mBspTree->Construct(mViewCells);
1584        }
1585
1586        // destroy rays created only for construction
1587        CLEAR_CONTAINER(constructionRays);
1588
[440]1589        Debug << mBspTree->GetStatistics() << endl;
[503]1590
1591        //EvaluateViewCellsStats();
[660]1592        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[480]1593
[469]1594        // recast rest of the rays
[649]1595        if (SAMPLE_AFTER_SUBDIVISION)
1596                ComputeSampleContributions(savedRays, true, false);
[469]1597
[440]1598        return sampleContributions;
1599}
1600
[503]1601
[480]1602void BspViewCellsManager::CollectViewCells()
1603{
[587]1604        // view cells tree constructed
1605        if (!ViewCellsTreeConstructed())
[591]1606        {               
[587]1607                mBspTree->CollectViewCells(mViewCells);
1608        }
1609        else
1610        {
1611                // we can use the view cells tree hierarchy to get the right set
[591]1612                mViewCellsTree->CollectBestViewCellSet(mViewCells,
[600]1613                                                                                           mNumActiveViewCells);
[587]1614        }
[480]1615}
[468]1616
[503]1617
[471]1618float BspViewCellsManager::GetProbability(ViewCell *viewCell)
[440]1619{
[471]1620        // compute view cell area as subsititute for probability
[591]1621        if (1)
1622                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
1623        else
1624                return GetArea(viewCell) / GetAccVcArea();
[466]1625}
[440]1626
[503]1627
[440]1628
[468]1629int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
1630                                                                                 const Vector3 &termination,
1631                                                                                 ViewCellContainer &viewcells)
[440]1632{
[468]1633        return mBspTree->CastLineSegment(origin, termination, viewcells);
1634}
1635
1636
[503]1637int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
[468]1638                                                                         const VssRayContainer &rays)
1639{
[469]1640        if (!ViewCellsConstructed())
[441]1641        {
1642                Debug << "view cells not constructed" << endl;
1643                return 0;
1644        }
[590]1645       
1646        // view cells already finished before post processing step (i.e. because they were loaded)
1647        if (mViewCellsFinished)
1648        {
1649                FinalizeViewCells(true);
1650                EvaluateViewCellsStats();
1651
1652                return 0;
1653        }
1654
[440]1655        //-- post processing of bsp view cells
[600]1656
[440]1657    int vcSize = 0;
1658        int pvsSize = 0;
1659
[591]1660        //-- merge view cells
[649]1661        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
1662        long startTime = GetTime();
1663       
1664        VssRayContainer postProcessRays;
1665        GetRaySets(rays, mPostProcessSamples, postProcessRays);
1666
[592]1667        if (mMergeViewCells)
[591]1668        {
[660]1669                cout << "constructing visibility based merge tree" << endl;
[650]1670                mViewCellsTree->ConstructMergeTree(rays, objects);
[649]1671        }
1672        else
1673        {
[660]1674                cout << "constructing spatial merge tree" << endl;
[649]1675                // create spatial merge hierarchy
[650]1676                mViewCellsTree->SetRoot(ConstructSpatialMergeTree(mBspTree->GetRoot()));
[649]1677        }
[440]1678
[660]1679        // export statistics after merge
[666]1680        if (1)
1681        {
1682                char mstats[100];
1683                environment->GetStringValue("ViewCells.mergeStats", mstats);
1684                mViewCellsTree->ExportStats(mstats);
1685        }
[650]1686
[649]1687        //-- stats and visualizations
1688        cout << "finished" << endl;
[650]1689        cout << "merged view cells in "
[649]1690                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
[440]1691
[650]1692        Debug << "Postprocessing: Merged view cells in "
[649]1693                << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
1694       
[503]1695
[660]1696        //-- visualization and statistics
[600]1697    // reset view cells and stats
[480]1698        ResetViewCells();
[660]1699        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
[600]1700
[660]1701
[600]1702        int savedColorCode  = mColorCode;
[605]1703       
[600]1704        //BspLeaf::NewMail();
1705        if (1) // export merged view cells
1706        {
1707                mColorCode = 0;
[605]1708               
[600]1709                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
[605]1710               
[600]1711
1712                cout << "exporting view cells after merge ... ";
1713
1714                if (exporter)
1715                {
1716                        if (mExportGeometry)
1717                                exporter->ExportGeometry(objects);
1718
1719                        //exporter->SetWireframe();
1720                        exporter->SetFilled();
1721                        ExportViewCellsForViz(exporter);
1722
1723
1724                        delete exporter;
1725                }
1726                cout << "finished" << endl;
1727        }
1728
1729        if (1) // export merged view cells
1730        {
1731                mColorCode = 1;
1732
1733                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
1734       
1735                cout << "exporting view cells after merge (pvs size) ... ";     
1736
1737                if (exporter)
1738                {
1739                        //exporter->SetWireframe();
1740                       
1741                        if (mExportGeometry)
1742                                exporter->ExportGeometry(objects);
1743
1744                        //exporter->SetWireframe();
1745                        exporter->SetFilled();
1746                        ExportViewCellsForViz(exporter);
1747
1748                        delete exporter;
1749                }
1750                cout << "finished" << endl;
1751        }
1752
[693]1753       
1754        // only for testing
1755        TestSubdivision();
1756
[600]1757        mColorCode = savedColorCode;
1758
[587]1759        FinalizeViewCells(true);
1760       
1761        // write view cells to disc
1762        if (mExportViewCells)
1763        {
1764                char buff[100];
1765                environment->GetStringValue("ViewCells.filename", buff);
1766                string vcFilename(buff);
1767
1768                ExportViewCells(buff);
1769        }
1770
[650]1771        return 0;
[440]1772}
1773
[477]1774
1775BspViewCellsManager::~BspViewCellsManager()
1776{
1777}
1778
1779
[440]1780int BspViewCellsManager::GetType() const
1781{
1782        return BSP;
1783}
1784
1785
1786void BspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]1787                                                                        const VssRayContainer &sampleRays)
[440]1788{
[469]1789        if (!ViewCellsConstructed())
1790                return;
[574]1791       
[600]1792        int savedColorCode = mColorCode;
1793
1794       
1795       
1796        if (1) // export final view cells
[440]1797        {
[600]1798                mColorCode = 1;
[587]1799
[600]1800                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
1801       
1802                cout << "exporting view cells after merge (pvs size) ... ";     
[587]1803
[469]1804                if (exporter)
[440]1805                {
[600]1806                        //exporter->SetWireframe();
1807                       
1808                        if (mExportGeometry)
1809                                exporter->ExportGeometry(objects);
[590]1810
[600]1811                        //exporter->SetWireframe();
1812                        exporter->SetFilled();
[508]1813                        ExportViewCellsForViz(exporter);
[587]1814
[469]1815                        delete exporter;
[440]1816                }
[469]1817                cout << "finished" << endl;
[503]1818        }
[477]1819
[600]1820        mColorCode = savedColorCode;
1821
[469]1822        //-- visualization of the BSP splits
1823        bool exportSplits = false;
1824        environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
[503]1825
[469]1826        if (exportSplits)
[440]1827        {
[469]1828                cout << "exporting splits ... ";
[477]1829                ExportSplits(objects);
[469]1830                cout << "finished" << endl;
[440]1831        }
[477]1832
[600]1833        // export single view cells
[477]1834        ExportBspPvs(objects);
[440]1835}
1836
1837
[503]1838inline bool vc_gt(ViewCell *a, ViewCell *b)
1839{
[440]1840        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
1841}
1842
[477]1843
1844void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
[440]1845{
1846        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
1847
[503]1848        if (exporter)
1849        {
[598]1850                //exporter->SetFilled();
1851
1852                if (mExportGeometry)
1853                        exporter->ExportGeometry(objects);
1854
[503]1855                Material m;
[440]1856                m.mDiffuseColor = RgbColor(1, 0, 0);
1857                exporter->SetForcedMaterial(m);
1858                exporter->SetWireframe();
[503]1859
[440]1860                exporter->ExportBspSplits(*mBspTree, true);
1861
[482]1862                //NOTE: take forced material, else big scenes cannot be viewed
[440]1863                m.mDiffuseColor = RgbColor(0, 1, 0);
1864                exporter->SetForcedMaterial(m);
[482]1865                //exporter->ResetForcedMaterial();
1866
[440]1867                delete exporter;
1868        }
1869}
1870
[477]1871
1872void BspViewCellsManager::ExportBspPvs(const ObjectContainer &objects)
[440]1873{
[477]1874        const int leafOut = 10;
[503]1875
[477]1876        ViewCell::NewMail();
[440]1877
[477]1878        //-- some rays for output
1879        const int raysOut = min((int)mBspRays.size(), mVisualizationSamples);
[503]1880
[477]1881        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
1882        Debug << "\nOutput view cells: " << endl;
[503]1883
[478]1884        // sort view cells to get largest view cells
[587]1885        if (0)
1886                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
1887
[503]1888        int limit = min(leafOut, (int)mViewCells.size());
1889
[478]1890        for (int i = 0; i < limit; ++ i)
[477]1891        {
[478]1892                cout << "creating output for view cell " << i << " ... ";
1893                VssRayContainer vcRays;
1894                Intersectable::NewMail();
[582]1895                ViewCell *vc;
1896
1897                if (0)
1898                        vc = mViewCells[i];
1899                else
1900                        vc = mViewCells[Random((int)mViewCells.size())];
1901
[478]1902                cout << "creating output for view cell " << i << " ... ";
[469]1903
[587]1904                if(0)
[477]1905                {
[587]1906                        // check whether we can add the current ray to the output rays
1907                        for (int k = 0; k < raysOut; ++ k)
[477]1908                        {
[587]1909                                BspRay *ray = mBspRays[k];
1910                                for     (int j = 0; j < (int)ray->intersections.size(); ++ j)
1911                                {
1912                                        BspLeaf *leaf = ray->intersections[j].mLeaf;
1913                                        if (vc == leaf->GetViewCell())
1914                                                vcRays.push_back(ray->vssRay);
1915                                }
[477]1916                        }
1917                }
[587]1918
[478]1919                //bspLeaves[j]->Mail();
1920                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
[477]1921
[478]1922                Exporter *exporter = Exporter::GetExporter(s);
[503]1923
[478]1924                exporter->SetWireframe();
[477]1925
[478]1926                Material m;//= RandomMaterial();
1927                m.mDiffuseColor = RgbColor(0, 1, 0);
1928                exporter->SetForcedMaterial(m);
[477]1929
[587]1930                ExportViewCellGeometry(exporter, vc);
1931               
[478]1932                // export rays piercing this view cell
1933                exporter->ExportRays(vcRays, RgbColor(0, 1, 0));
[580]1934
[478]1935                m.mDiffuseColor = RgbColor(1, 0, 0);
1936                exporter->SetForcedMaterial(m);
[440]1937
[478]1938                ObjectPvsMap::const_iterator it,
1939                        it_end = vc->GetPvs().mEntries.end();
[440]1940
[478]1941                exporter->SetFilled();
[469]1942
[478]1943                // output PVS of view cell
[503]1944                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[478]1945                {
1946                        Intersectable *intersect = (*it).first;
[469]1947
[478]1948                        if (!intersect->Mailed())
1949                        {
1950                                Material m = RandomMaterial();
1951                                exporter->SetForcedMaterial(m);
1952
1953                                exporter->ExportIntersectable(intersect);
1954                                intersect->Mail();
[503]1955                        }
[477]1956                }
[503]1957
[478]1958                DEL_PTR(exporter);
1959                cout << "finished" << endl;
[477]1960        }
1961
1962        Debug << endl;
[440]1963}
1964
[441]1965
[503]1966void BspViewCellsManager::ExportColor(Exporter *exporter,
[482]1967                                                                          ViewCell *vc) const
1968{
[600]1969        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
[482]1970
1971        float importance = 0;
[598]1972        static Material m;
[482]1973
1974        switch (mColorCode)
1975        {
[598]1976        case 0: // Random
1977                {
1978                        if (vcValid)
1979                        {
1980                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
1981                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
[600]1982                                m.mDiffuseColor.b = 0.5f + RandomValue(0.0f, 0.5f);
[598]1983                        }
1984                        else
1985                        {
1986                                m.mDiffuseColor.r = 0.0f;
1987                                m.mDiffuseColor.g = 1.0f;
1988                                m.mDiffuseColor.b = 0.0f;
1989                        }
1990
1991                        exporter->SetForcedMaterial(m);
1992                        return;
1993                }
1994               
[482]1995        case 1: // pvs
1996                {
[503]1997                        importance = (float)vc->GetPvs().GetSize() /
[660]1998                                (float)mCurrentViewCellsStats.maxPvs;
[598]1999
[482]2000                }
2001                break;
2002        case 2: // merges
2003                {
[598]2004            int lSize = mViewCellsTree->GetSize(vc);
[660]2005                        importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
[482]2006                }
[598]2007                //break;
[482]2008        case 3: // merge tree differene
2009                {
2010                        // TODO
[598]2011                        //importance = (float)GetMaxTreeDiff(vc) /
2012                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2013
[482]2014                }
2015                break;
2016        default:
2017                break;
2018        }
2019
[598]2020        // special color code for invalid view cells
[482]2021        m.mDiffuseColor.r = importance;
2022        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[598]2023        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
[503]2024
[598]2025        //Debug << "importance: " << importance << endl;
[482]2026        exporter->SetForcedMaterial(m);
2027}
2028
[587]2029
[693]2030void BspViewCellsManager::TestSubdivision()
2031{
2032        ViewCellContainer leaves;
2033        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
2034
2035        ViewCellContainer::const_iterator it, it_end = leaves.end();
2036
2037        const float vol = mViewSpaceBox.GetVolume();
2038        float subdivVol = 0;
2039        float newVol = 0;
2040
2041        for (it = leaves.begin(); it != it_end; ++ it)
2042        {
2043                BspNodeGeometry geom;
2044                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
2045                mBspTree->ConstructGeometry(leaf, geom);
2046
2047                const float lVol = geom.GetVolume();
2048               
2049                newVol += lVol;
2050                subdivVol += (*it)->GetVolume();
[694]2051
2052                float thres = 0.9;
2053                if ((lVol < ((*it)->GetVolume() * thres)) ||
2054                        (lVol * thres > ((*it)->GetVolume())))
2055                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
[693]2056        }
2057       
2058        Debug << "exact volume: " << vol << endl;
2059        Debug << "subdivision volume: " << subdivVol << endl;
2060        Debug << "new volume: " << newVol << endl;
2061}
2062
2063
[580]2064void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]2065                                                                                                 ViewCell *vc,
[660]2066                                                                                                 const Plane3 *clipPlane) const
[482]2067{
2068        if (vc->GetMesh())
2069        {
[587]2070                exporter->ExportMesh(vc->GetMesh());
2071                return;
[482]2072        }
[587]2073
2074        BspNodeGeometry geom;
2075        mBspTree->ConstructGeometry(vc, geom);
[591]2076
[660]2077        if (clipPlane)
[591]2078        {
[681]2079                const int cf = Polygon3::ClassifyPlane(geom.GetPolys(), *clipPlane, 0.0001f);
[591]2080
[681]2081                if (cf == Polygon3::BACK_SIDE)
2082                {
2083                        exporter->ExportPolygons(geom.GetPolys());
2084                }
2085                else if (cf == Polygon3::SPLIT)
2086                {
2087                        BspNodeGeometry front;
2088                        BspNodeGeometry back;
[591]2089
[681]2090                        geom.SplitGeometry(front,
2091                                                           back,
2092                                                           *clipPlane,
2093                                                           mViewSpaceBox,
2094                                                           0.0001f);
2095
2096                        if (back.Valid())
2097                                exporter->ExportPolygons(back.GetPolys());
2098                }
[591]2099        }
2100        else
2101        {
[678]2102                exporter->ExportPolygons(geom.GetPolys());
[591]2103        }
[482]2104}
2105
[503]2106
2107void BspViewCellsManager::CreateMesh(ViewCell *vc)
2108{
[587]2109        if (vc->GetMesh())
2110                delete vc->GetMesh();
2111
2112        BspNodeGeometry geom;
2113       
2114        mBspTree->ConstructGeometry(vc, geom);
2115
2116        Mesh *mesh = new Mesh();
2117        geom.AddToMesh(*mesh);
2118        vc->SetMesh(mesh);
2119        mMeshContainer.push_back(mesh);
[503]2120}
2121
[551]2122
[587]2123void BspViewCellsManager::Finalize(ViewCell *viewCell,
2124                                                                   const bool createMesh)
[502]2125{
[587]2126        float area = 0;
2127        float volume = 0;
[572]2128
[587]2129        ViewCellContainer leaves;
2130        mViewCellsTree->CollectLeaves(viewCell, leaves);
2131
2132        ViewCellContainer::const_iterator it, it_end = leaves.end();
2133
[693]2134    for (it = leaves.begin(); it != it_end; ++ it)
[587]2135        {
2136                BspNodeGeometry geom;
2137                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
2138                mBspTree->ConstructGeometry(leaf, geom);
2139
[693]2140                float lVol = geom.GetVolume();
2141                float lArea = geom.GetArea();
2142
2143                //(*it)->SetVolume(vol);
2144                //(*it)->SetArea(area);
2145
2146                area += lArea;
2147                volume += lVol;
2148
2149        CreateMesh(*it);
[587]2150        }
2151
2152        viewCell->SetVolume(volume);
2153        viewCell->SetArea(area);
[502]2154}
2155
[580]2156
[587]2157ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point) const
[580]2158{
[587]2159        if (!mBspTree)
2160                return NULL;
2161
2162        if (!mViewSpaceBox.IsInside(point))
2163                return NULL;
2164       
2165        return mBspTree->GetViewCell(point);
[580]2166}
2167
2168
[587]2169void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2170                                                                                                 vector<MergeCandidate> &candidates)
2171{
2172        cout << "collecting merge candidates ... " << endl;
2173
2174        if (mUseRaysForMerge)
2175        {
2176                mBspTree->CollectMergeCandidates(rays, candidates);
2177        }
2178        else
2179        {
2180                vector<BspLeaf *> leaves;
2181                mBspTree->CollectLeaves(leaves);
2182                mBspTree->CollectMergeCandidates(leaves, candidates);
2183        }
2184
2185        cout << "fininshed collecting candidates" << endl;
2186}
2187
2188
[440]2189
[590]2190bool BspViewCellsManager::ExportViewCells(const string filename)
2191{
2192        cout << "exporting view cells to xml ... ";
2193        std::ofstream stream;
[503]2194
[590]2195        // for output we need unique ids for each view cell
2196        CreateUniqueViewCellIds();
[503]2197
[590]2198
2199        stream.open(filename.c_str());
2200        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
2201        stream << "<Visibility_Solution>" << endl;
2202
2203        //-- the view space bounding box
2204        stream << "<ViewSpaceBox"
2205                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
2206                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
2207
2208        //-- the type of the view cells hierarchy
2209        //stream << "<Hierarchy name=\"bspTree\" />" << endl;
2210        stream << "<Hierarchy name=\"vspBspTree\" />" << endl; // write vsp bsp here because can use same tree and is bug free
2211        //-- load the view cells itself, i.e., the ids and the pvs
2212        stream << "<ViewCells>" << endl;
[610]2213
2214#if 0
2215       
[590]2216        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[610]2217               
[590]2218        for (it = mViewCells.begin(); it != it_end; ++ it)
2219                ExportViewCell(*it, stream);
[610]2220#else
2221        mViewCellsTree->Export(stream);
2222#endif
[590]2223
2224        stream << "</ViewCells>" << endl;
2225
2226        //-- load the hierarchy
2227        stream << "<Hierarchy>" << endl;
2228        mBspTree->Export(stream);
2229        stream << endl << "</Hierarchy>" << endl;
2230
2231        stream << "</Visibility_Solution>" << endl;
2232        stream.close();
2233
2234        cout << "finished" << endl;
2235
2236        return true;
2237}
2238
2239
2240void BspViewCellsManager::AddCurrentViewCellsToHierarchy()
2241{
2242        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2243        for (it = mViewCells.begin(); it != it_end; ++ it)
2244        {
2245                ViewCell *vc = *it;
2246                ViewCellContainer leaves;
2247                mViewCellsTree->CollectLeaves(vc, leaves);
2248               
2249                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2250
2251                for (lit = leaves.begin(); lit != lit_end; ++ lit)
2252                {
2253                        BspViewCell *bspVc = dynamic_cast<BspViewCell *>(*lit);
2254                        bspVc->mLeaf->SetViewCell(vc);
2255                }
2256        }
2257}
2258
[610]2259
[650]2260ViewCell *BspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
[610]2261{
[650]2262        if (root->IsLeaf())
2263        {
2264                ViewCell *viewCell = dynamic_cast<BspLeaf *>(root)->GetViewCell();
[610]2265
[650]2266                viewCell->SetMergeCost(0.0f);
[610]2267
[650]2268                return viewCell;
2269        }
2270       
2271        BspInterior *interior = dynamic_cast<BspInterior *>(root);
2272        ViewCellInterior *viewCellInterior = new ViewCellInterior();
2273               
2274        float mergeCost = 1.0f / (float)root->mTimeStamp;
2275        //Debug << "timestamp: " << root->mTimeStamp;
2276        //Debug << "merge cost: " << mergeCost << endl;
[649]2277
[650]2278        viewCellInterior->SetMergeCost(mergeCost);
[649]2279
[650]2280        float volume = 0;
[649]2281       
[650]2282        BspNode *front = interior->GetFront();
2283        BspNode *back = interior->GetBack();
[649]2284
[650]2285        // recursivly compute child hierarchies
2286        ViewCell *backVc = ConstructSpatialMergeTree(back);
2287        ViewCell *frontVc = ConstructSpatialMergeTree(front);
[610]2288
[650]2289        viewCellInterior->SetupChildLink(frontVc);
2290        viewCellInterior->SetupChildLink(backVc);
[610]2291
[649]2292
[650]2293        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
2294        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
[649]2295
[650]2296        volume += backVc->GetVolume();
2297        volume += frontVc->GetVolume();
[649]2298
[650]2299        viewCellInterior->SetVolume(volume);
[649]2300
[650]2301        return viewCellInterior;
[610]2302}
2303
[650]2304
[590]2305/************************************************************************/
2306/*                   KdViewCellsManager implementation                  */
2307/************************************************************************/
2308
2309
2310
[440]2311KdViewCellsManager::KdViewCellsManager(KdTree *kdTree):
[469]2312ViewCellsManager(), mKdTree(kdTree), mKdPvsDepth(100)
[440]2313{
2314}
2315
[605]2316
[471]2317float KdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]2318{
[479]2319        // compute view cell area / volume as subsititute for probability
[605]2320        if (0)
2321                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
2322        else
2323                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[468]2324}
2325
2326
2327
[479]2328
[480]2329void KdViewCellsManager::CollectViewCells()
2330{
2331        //mKdTree->CollectViewCells(mViewCells); TODO
2332}
[479]2333
[519]2334
[574]2335int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
[487]2336                                                                  const VssRayContainer &rays)
[440]2337{
[441]2338        // if view cells already constructed
[440]2339        if (ViewCellsConstructed())
2340                return 0;
[441]2341
[440]2342        mKdTree->Construct();
2343
[480]2344        mTotalAreaValid = false;
[469]2345        // create the view cells
2346        mKdTree->CreateAndCollectViewCells(mViewCells);
[503]2347
[480]2348        // cast rays
[574]2349        ComputeSampleContributions(rays, true, false);
[480]2350
[479]2351        EvaluateViewCellsStats();
[660]2352        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[469]2353
[440]2354        return 0;
2355}
2356
[587]2357
[440]2358bool KdViewCellsManager::ViewCellsConstructed() const
2359{
2360        return mKdTree->GetRoot() != NULL;
2361}
2362
[503]2363int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]2364                                                                        const VssRayContainer &rays)
[440]2365{
2366        return 0;
2367}
2368
2369void KdViewCellsManager::Visualize(const ObjectContainer &objects,
[466]2370                                                                   const VssRayContainer &sampleRays)
[440]2371{
[441]2372        if (!ViewCellsConstructed())
2373                return;
2374
[469]2375        // using view cells instead of the kd PVS of objects
2376        const bool useViewCells = true;
2377        bool exportRays = false;
[440]2378
2379        int limit = min(mVisualizationSamples, (int)sampleRays.size());
[469]2380        const int pvsOut = min((int)objects.size(), 10);
[466]2381        VssRayContainer *rays = new VssRayContainer[pvsOut];
[440]2382
[469]2383        if (useViewCells)
[440]2384        {
[469]2385                const int leafOut = 10;
[503]2386
[469]2387                ViewCell::NewMail();
[503]2388
[469]2389                //-- some rays for output
2390                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
2391                Debug << "visualization using " << raysOut << " samples" << endl;
2392
2393                //-- some random view cells and rays for output
2394                vector<KdLeaf *> kdLeaves;
[503]2395
[469]2396                for (int i = 0; i < leafOut; ++ i)
2397                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
[503]2398
[469]2399                for (int i = 0; i < kdLeaves.size(); ++ i)
[440]2400                {
[469]2401                        KdLeaf *leaf = kdLeaves[i];
2402                        RayContainer vcRays;
[503]2403
[469]2404                        cout << "creating output for view cell " << i << " ... ";
[503]2405#if 0
[469]2406                        // check whether we can add the current ray to the output rays
[503]2407                        for (int k = 0; k < raysOut; ++ k)
[440]2408                        {
[469]2409                                Ray *ray = sampleRays[k];
[503]2410
[469]2411                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
2412                                {
2413                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
[503]2414
2415                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
[469]2416                                        {
2417                                                vcRays.push_back(ray);
2418                                        }
2419                                }
[479]2420                        }
[503]2421#endif
[469]2422                        Intersectable::NewMail();
[503]2423
[469]2424                        ViewCell *vc = leaf->mViewCell;
[503]2425
[469]2426                        //bspLeaves[j]->Mail();
2427                        char s[64]; sprintf(s, "kd-pvs%04d.x3d", i);
[503]2428
[469]2429                        Exporter *exporter = Exporter::GetExporter(s);
2430                        exporter->SetFilled();
2431
2432                        exporter->SetWireframe();
2433                        //exporter->SetFilled();
[503]2434
[469]2435                        Material m;//= RandomMaterial();
2436                        m.mDiffuseColor = RgbColor(1, 1, 0);
2437                        exporter->SetForcedMaterial(m);
[503]2438
[469]2439                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
2440                        exporter->ExportBox(box);
2441
2442                        // export rays piercing this view cell
[503]2443                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
2444
[469]2445                        m.mDiffuseColor = RgbColor(1, 0, 0);
2446                        exporter->SetForcedMaterial(m);
[503]2447
[469]2448                        // exporter->SetWireframe();
2449                        exporter->SetFilled();
[503]2450
[469]2451                        ObjectPvsMap::iterator it, it_end = vc->GetPvs().mEntries.end();
2452                        // output PVS of view cell
[503]2453                        for (it = vc->GetPvs().mEntries.begin(); it !=  it_end; ++ it)
[469]2454                        {
2455                                Intersectable *intersect = (*it).first;
2456                                if (!intersect->Mailed())
2457                                {
2458                                        exporter->ExportIntersectable(intersect);
2459                                        intersect->Mail();
[503]2460                                }
[440]2461                        }
[503]2462
[469]2463                        DEL_PTR(exporter);
2464                        cout << "finished" << endl;
[440]2465                }
[469]2466
2467                DEL_PTR(rays);
[440]2468        }
[469]2469        else // using kd PVS of objects
2470        {
2471                for (int i = 0; i < limit; ++ i)
2472                {
2473                        VssRay *ray = sampleRays[i];
[503]2474
[469]2475                        // check whether we can add this to the rays
[503]2476                        for (int j = 0; j < pvsOut; j++)
[469]2477                        {
2478                                if (objects[j] == ray->mTerminationObject)
2479                                {
2480                                        rays[j].push_back(ray);
2481                                }
2482                        }
2483                }
[440]2484
[503]2485                if (exportRays)
[469]2486                {
2487                        Exporter *exporter = NULL;
2488                        exporter = Exporter::GetExporter("sample-rays.x3d");
2489                        exporter->SetWireframe();
2490                        exporter->ExportKdTree(*mKdTree);
[503]2491
2492                        for (i=0; i < pvsOut; i++)
[469]2493                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
2494
2495                        exporter->SetFilled();
[503]2496
[469]2497                        delete exporter;
2498                }
[440]2499
[503]2500                for (int k=0; k < pvsOut; k++)
[469]2501                {
2502                        Intersectable *object = objects[k];
[503]2503                        char s[64];
[469]2504                        sprintf(s, "sample-pvs%04d.x3d", k);
[440]2505
[469]2506                        Exporter *exporter = Exporter::GetExporter(s);
2507                        exporter->SetWireframe();
[503]2508
[469]2509                        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
2510                        Intersectable::NewMail();
[503]2511
[469]2512                        // avoid adding the object to the list
2513                        object->Mail();
2514                        ObjectContainer visibleObjects;
[503]2515
2516                        for (; i != object->mKdPvs.mEntries.end(); i++)
[469]2517                        {
2518                                KdNode *node = (*i).first;
2519                                exporter->ExportBox(mKdTree->GetBox(node));
[503]2520
[469]2521                                mKdTree->CollectObjects(node, visibleObjects);
2522                        }
[503]2523
[469]2524                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
2525                        exporter->SetFilled();
[503]2526
[469]2527                        for (int j = 0; j < visibleObjects.size(); j++)
2528                                exporter->ExportIntersectable(visibleObjects[j]);
[503]2529
[469]2530                        Material m;
2531                        m.mDiffuseColor = RgbColor(1, 0, 0);
2532                        exporter->SetForcedMaterial(m);
2533                        exporter->ExportIntersectable(object);
[503]2534
[469]2535                        delete exporter;
[440]2536                }
[503]2537        }
[440]2538}
2539
[469]2540
[482]2541void KdViewCellsManager::ExportColor(Exporter *exporter,
2542                                                                         ViewCell *vc) const
2543{
2544        // TODO
2545}
2546
[666]2547
[580]2548ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
2549{
2550        return new KdViewCell(mesh);
2551}
[482]2552
[580]2553
2554void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]2555                                                                                                ViewCell *vc,
[660]2556                                                                                                const Plane3 *clipPlane) const
[482]2557{
[580]2558        ViewCellContainer leaves;
[485]2559
[580]2560        mViewCellsTree->CollectLeaves(vc, leaves);
2561        ViewCellContainer::const_iterator it, it_end = leaves.end();
2562
2563        for (it = leaves.begin(); it != it_end; ++ it)
2564        {
2565                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
2566       
2567                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaf));
2568        }
[482]2569}
2570
2571
[440]2572int KdViewCellsManager::GetType() const
2573{
2574        return ViewCellsManager::KD;
2575}
2576
2577
[441]2578
[440]2579KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
2580{
2581        KdNode *node = leaf;
2582
2583        while (node->mParent && node->mDepth > mKdPvsDepth)
2584                node = node->mParent;
2585        return node;
2586}
2587
[469]2588int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
2589                                                                                const Vector3 &termination,
2590                                                                                ViewCellContainer &viewcells)
[466]2591{
[469]2592        return mKdTree->CastLineSegment(origin, termination, viewcells);
[466]2593}
2594
[469]2595
[503]2596void KdViewCellsManager::CreateMesh(ViewCell *vc)
2597{
[551]2598        // TODO
[503]2599}
2600
[580]2601
2602
2603void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2604                                                                                                vector<MergeCandidate> &candidates)
2605{
2606        // TODO
2607}
2608
2609
[440]2610/**********************************************************************/
2611/*                   VspKdViewCellsManager implementation             */
2612/**********************************************************************/
2613
[482]2614
[574]2615VspKdViewCellsManager::VspKdViewCellsManager(VspKdTree *vspKdTree):
2616ViewCellsManager(), mVspKdTree(vspKdTree)
[440]2617{
[574]2618        environment->GetIntValue("VspKdTree.Construction.samples", mInitialSamples);
[468]2619        mVspKdTree->SetViewCellsManager(this);
2620}
[462]2621
[471]2622float VspKdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]2623{
[605]2624        // compute view cell area / volume as subsititute for probability
2625        if (0)
2626                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
2627        else
2628                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[440]2629}
2630
[462]2631
[468]2632
[503]2633
[480]2634void VspKdViewCellsManager::CollectViewCells()
2635{
2636        mVspKdTree->CollectViewCells(mViewCells);
2637}
[462]2638
[570]2639
[574]2640int VspKdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2641                                                                                                const VssRayContainer &rays)
[440]2642{
[441]2643        // if view cells already constructed
[440]2644        if (ViewCellsConstructed())
2645                return 0;
[503]2646
[469]2647        VssRayContainer constructionRays;
2648        VssRayContainer savedRays;
[440]2649
[503]2650        GetRaySets(rays,
[574]2651                           mInitialSamples,
[503]2652                           constructionRays,
[485]2653                           &savedRays);
[503]2654
2655        Debug << "constructing vsp kd tree using "
[469]2656                  << (int)constructionRays.size() << " samples" << endl;
[452]2657
[542]2658        mVspKdTree->Construct(constructionRays, &mViewSpaceBox);
[452]2659        Debug << mVspKdTree->GetStatistics() << endl;
2660
[482]2661        // export leaf building blocks
2662        ExportLeaves(objects, rays);
[480]2663
[469]2664        // finally merge kd leaf building blocks to view cells
[485]2665        const int merged = mVspKdTree->MergeViewCells(rays);
2666
2667        // collapse siblings belonging to the same view cell
[486]2668        mVspKdTree->RefineViewCells(rays);
[485]2669
[542]2670        // collapse siblings belonging to the same view cell
[503]2671        mVspKdTree->CollapseTree();
2672
[482]2673        // evaluale view cell stats
2674        ResetViewCells();
[469]2675
[660]2676        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[482]2677
[485]2678        long startTime = GetTime();
[660]2679
[469]2680        // recast rest of rays
[574]2681        ComputeSampleContributions(savedRays, true, false);
[503]2682
2683        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]2684                  << " secs" << endl;
[469]2685
2686        return merged;
[440]2687}
2688
2689bool VspKdViewCellsManager::ViewCellsConstructed() const
2690{
2691        return mVspKdTree->GetRoot() != NULL;
2692}
2693
[441]2694
[462]2695ViewCell *VspKdViewCellsManager::GenerateViewCell(Mesh *mesh) const
2696{
2697        return new VspKdViewCell(mesh);
2698}
2699
[503]2700int VspKdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]2701                                                                           const VssRayContainer &rays)
[440]2702{
[441]2703        if (!ViewCellsConstructed())
2704                return 0;
2705
[482]2706        // recalculate stats
2707        EvaluateViewCellsStats();
2708
[469]2709        return 0;
[440]2710}
2711
[482]2712
2713void VspKdViewCellsManager::ExportLeaves(const ObjectContainer &objects,
2714                                                                                 const VssRayContainer &sampleRays)
[440]2715{
[441]2716        if (!ViewCellsConstructed())
2717                return;
2718
[482]2719        //-- export leaf building blocks
[503]2720        Exporter *exporter = Exporter::GetExporter("vspkdtree.x3d");
[482]2721        if (!exporter)
2722                return;
2723
[598]2724        if (mExportGeometry)
2725                exporter->ExportGeometry(objects);
2726       
[482]2727        //exporter->SetWireframe();
2728        //exporter->ExportVspKdTree(*mVspKdTree, mVspKdTree->GetStatistics().maxPvsSize);
2729        exporter->ExportVspKdTree(*mVspKdTree);
2730
[503]2731        if (mExportRays)
[440]2732        {
[503]2733                const float prob = (float)mVisualizationSamples
[482]2734                        / ((float)sampleRays.size() + Limits::Small);
[440]2735
[482]2736                exporter->SetWireframe();
[440]2737
[482]2738                //-- collect uniformly distributed rays
2739                VssRayContainer rays;
[440]2740
[482]2741                for (int i = 0; i < sampleRays.size(); ++ i)
2742                {
2743                        if (RandomValue(0,1) < prob)
2744                                rays.push_back(sampleRays[i]);
[440]2745                }
[482]2746                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[440]2747        }
2748
[482]2749        delete exporter;
2750}
2751
2752void VspKdViewCellsManager::Visualize(const ObjectContainer &objects,
2753                                                                          const VssRayContainer &sampleRays)
2754{
2755        if (!ViewCellsConstructed())
2756                return;
[503]2757
[482]2758        //-- export single view cells
2759        for (int i = 0; i < 10; ++ i)
[440]2760        {
[482]2761                char s[64];
2762                sprintf(s, "vsp_viewcell%04d.x3d", i);
2763                Exporter *exporter = Exporter::GetExporter(s);
[503]2764                const int idx =
[482]2765                        (int)RandomValue(0.0, (Real)((int)mViewCells.size() - 1));
[440]2766
[503]2767                VspKdViewCell *vc = dynamic_cast<VspKdViewCell *>(mViewCells[idx]);
[482]2768
2769                //-- export geometry
2770                Material m;
2771                m.mDiffuseColor = RgbColor(0, 1, 1);
[503]2772
[482]2773                exporter->SetForcedMaterial(m);
2774                exporter->SetWireframe();
2775
[580]2776                ExportViewCellGeometry(exporter, vc);
[482]2777
2778                //-- export stored rays
[580]2779               
[485]2780                if (mExportRays)
[440]2781                {
[580]2782                        ViewCellContainer leaves;
2783                        mViewCellsTree->CollectLeaves(vc, leaves);
[440]2784
[580]2785                        ViewCellContainer::const_iterator it,
2786                                it_end = leaves.end();
2787
2788                        for (it = leaves.begin(); it != it_end; ++ it)
[482]2789                        {
[580]2790                                VspKdViewCell *vspKdVc = dynamic_cast<VspKdViewCell *>(*it);
2791                                VspKdLeaf *leaf = vspKdVc->mLeaf;
[482]2792                                AxisAlignedBox3 box = mVspKdTree->GetBBox(leaf);
[440]2793
[482]2794                                VssRayContainer vssRays;
[483]2795
2796                                VssRayContainer castRays;
2797                                VssRayContainer initRays;
2798
[482]2799                                leaf->GetRays(vssRays);
[440]2800
[482]2801                                VssRayContainer::const_iterator it, it_end = vssRays.end();
[483]2802                                const float prop = 200.0f / (float)vssRays.size();
[440]2803
[482]2804                                for (it = vssRays.begin(); it != it_end; ++ it)
[483]2805                                {
[485]2806                                        if (Random(1) < prop)
[483]2807                                                if ((*it)->mTerminationObject == NULL)
2808                                                        castRays.push_back(*it);
[503]2809                                                else
[483]2810                                                        initRays.push_back(*it);
2811                                }
2812
2813                                exporter->ExportRays(castRays, RgbColor(1, 0, 0));
2814                                exporter->ExportRays(initRays, RgbColor(0, 1, 0));
[482]2815                        }
2816                }
[580]2817       
[482]2818                //-- output PVS of view cell
2819                m.mDiffuseColor = RgbColor(1, 0, 0);
2820                exporter->SetForcedMaterial(m);
[440]2821
[483]2822                Intersectable::NewMail();
2823
[482]2824                ObjectPvsMap::const_iterator it,
2825                        it_end = vc->GetPvs().mEntries.end();
2826
2827                exporter->SetFilled();
2828
[503]2829                for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
[482]2830                {
2831                        Intersectable *intersect = (*it).first;
2832
2833                        if (!intersect->Mailed())
2834                        {
2835                                Material m = RandomMaterial();
2836                                exporter->SetForcedMaterial(m);
2837
2838                                exporter->ExportIntersectable(intersect);
2839                                intersect->Mail();
[503]2840                        }
[482]2841                }
2842
2843                delete exporter;
[440]2844        }
[462]2845
2846        //-- export final view cells
[503]2847        Exporter *exporter = Exporter::GetExporter("vspkdtree_merged.x3d");
2848
[485]2849        //if (exportGeometry) exporter->SetWireframe();
2850        //else exporter->SetFilled();
[483]2851
[508]2852        ExportViewCellsForViz(exporter);
[462]2853
[503]2854        if (mExportGeometry)
[465]2855        {
2856                exporter->SetFilled();
[462]2857                exporter->ExportGeometry(objects);
[465]2858        }
[469]2859
[503]2860        if (mExportRays)
[462]2861        {
[503]2862                const float prob = (float)mVisualizationSamples
[482]2863                        / ((float)sampleRays.size() + Limits::Small);
[503]2864
[462]2865                exporter->SetWireframe();
[503]2866
[466]2867                VssRayContainer rays;
[503]2868
[462]2869                for (int i = 0; i < sampleRays.size(); ++ i)
2870                {
[466]2871                  if (RandomValue(0,1) < prob)
2872                        rays.push_back(sampleRays[i]);
[462]2873                }
[503]2874                exporter->ExportRays(rays, RgbColor(1, 0, 0));
[462]2875        }
2876
2877        delete exporter;
[440]2878}
2879
2880int VspKdViewCellsManager::GetType() const
2881{
2882        return VSP_KD;
2883}
[442]2884
[462]2885
[469]2886int VspKdViewCellsManager::CastLineSegment(const Vector3 &origin,
2887                                                                                   const Vector3 &termination,
2888                                                                                   ViewCellContainer &viewcells)
[466]2889{
[469]2890        return mVspKdTree->CastLineSegment(origin, termination, viewcells);
[466]2891}
2892
[477]2893
[482]2894void VspKdViewCellsManager::ExportColor(Exporter *exporter,
2895                                                                                ViewCell *vc) const
2896{
2897        if (mColorCode == 0) // Random color
2898                return;
[503]2899
[482]2900        float importance = 0;
[477]2901
[482]2902        switch (mColorCode)
2903        {
2904        case 1: // pvs
2905                {
[503]2906                        importance = (float)vc->GetPvs().GetSize() /
[660]2907                                (float)mCurrentViewCellsStats.maxPvs;
[482]2908                }
2909                break;
[580]2910        case 2: // merged leaves
[482]2911                {
[580]2912                int lSize = mViewCellsTree->GetSize(vc);
2913                        importance = (float)lSize /
[660]2914                                (float)mCurrentViewCellsStats.maxLeaves;
[482]2915                }
2916                break;
[485]2917        case 3: // merged tree depth difference
[482]2918                {
[503]2919                        //importance = (float)GetMaxTreeDiff(vc) /
[482]2920                        //      (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2921                }
2922                break;
2923        default:
2924                break;
2925        }
2926
2927        Material m;
2928        m.mDiffuseColor.b = 1.0f;
2929        m.mDiffuseColor.r = importance;
2930        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2931        //Debug << "importance: " << importance << endl;
2932        exporter->SetForcedMaterial(m);
2933}
2934
2935
[580]2936void VspKdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]2937                                                                                                   ViewCell *vc,
[660]2938                                                                                                   const Plane3 *clipPlane) const
[482]2939{
2940        VspKdViewCell *kdVc = dynamic_cast<VspKdViewCell *>(vc);
2941
[486]2942        Mesh m;
[580]2943
2944        ViewCellContainer leaves;
2945        mViewCellsTree->CollectLeaves(vc, leaves);
2946
2947        ViewCellContainer::const_iterator it, it_end = leaves.end();
2948
2949        for (it = leaves.begin(); it != it_end; ++ it)
[486]2950        {
[580]2951                VspKdLeaf *l = dynamic_cast<VspKdViewCell *>(*it)->mLeaf;
2952                mVspKdTree->GetBBox(l).AddBoxToMesh(&m);
[486]2953        }
2954
2955        exporter->ExportMesh(&m);
[482]2956}
2957
2958
[503]2959void VspKdViewCellsManager::CreateMesh(ViewCell *vc)
2960{
[551]2961        //TODO
[503]2962}
[442]2963
[574]2964
[584]2965void VspKdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2966                                                                                                   vector<MergeCandidate> &candidates)
[580]2967{
2968        // TODO
2969}
[574]2970
[580]2971
[503]2972/**************************************************************************/
2973/*                   VspBspViewCellsManager implementation                */
2974/**************************************************************************/
[482]2975
[503]2976
[574]2977VspBspViewCellsManager::VspBspViewCellsManager(VspBspTree *vspBspTree):
2978ViewCellsManager(), mVspBspTree(vspBspTree)
[442]2979{
[574]2980        environment->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
[478]2981        mVspBspTree->SetViewCellsManager(this);
[590]2982        mVspBspTree->mViewCellsTree = mViewCellsTree;
[442]2983}
2984
[477]2985
[475]2986VspBspViewCellsManager::~VspBspViewCellsManager()
2987{
2988}
2989
[477]2990
[471]2991float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
[468]2992{
[551]2993        if (0 && mVspBspTree->mUseAreaForPvs)
[547]2994                return GetArea(viewCell) / GetAccVcArea();
2995        else
2996                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
[468]2997}
2998
[477]2999
[480]3000void VspBspViewCellsManager::CollectViewCells()
3001{
[581]3002        // view cells tree constructed
3003        if (!ViewCellsTreeConstructed())
3004        {
[590]3005                mVspBspTree->CollectViewCells(mViewCells, false);
[581]3006        }
3007        else
[664]3008        {       // we can use the view cells tree hierarchy to get the right set
[600]3009                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
[581]3010        }
[480]3011}
3012
3013
[442]3014bool VspBspViewCellsManager::ViewCellsConstructed() const
3015{
3016        return mVspBspTree->GetRoot() != NULL;
3017}
3018
[462]3019
[442]3020ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
3021{
3022        return new BspViewCell(mesh);
3023}
3024
[569]3025
[574]3026int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
[600]3027                                                                                                 const VssRayContainer &rays)
[442]3028{
[503]3029        // if view cells were already constructed
3030        if (ViewCellsConstructed())
3031                return 0;
[442]3032
[503]3033        int sampleContributions = 0;
3034
3035        VssRayContainer sampleRays;
3036
[574]3037        int limit = min (mInitialSamples, (int)rays.size());
[503]3038
[469]3039        VssRayContainer constructionRays;
3040        VssRayContainer savedRays;
[442]3041
[660]3042        Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
[664]3043                  << ", actual rays: " << (int)rays.size() << endl;
[587]3044
[574]3045        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
[487]3046
[574]3047        Debug << "initial rays: " << (int)constructionRays.size() << endl;
[508]3048        Debug << "saved rays: " << (int)savedRays.size() << endl;
[485]3049
[547]3050        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
[564]3051
[666]3052        //TODO: remove
[667]3053        if (1)
3054                mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
[666]3055        else
[667]3056                mVspBspTree->Construct(rays, &mViewSpaceBox);
3057
[490]3058        // collapse invalid regions
[491]3059        cout << "collapsing invalid tree regions ... ";
[495]3060        long startTime = GetTime();
[503]3061        int collapsedLeaves = mVspBspTree->CollapseTree();
[587]3062        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
3063                  << " seconds" << endl;
3064
[495]3065    cout << "finished" << endl;
[503]3066
[660]3067        // -- stats
3068        Debug << mVspBspTree->GetStatistics() << endl;
3069
[480]3070        ResetViewCells();
[660]3071        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[503]3072
[491]3073
[495]3074        startTime = GetTime();
[503]3075
[491]3076        cout << "Computing remaining ray contributions ... ";
[605]3077
[469]3078        // recast rest of rays
[605]3079        if (SAMPLE_AFTER_SUBDIVISION)
3080                ComputeSampleContributions(savedRays, true, false);
[491]3081        cout << "finished" << endl;
3082
[503]3083        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]3084                  << " secs" << endl;
[442]3085
[485]3086        cout << "construction finished" << endl;
[503]3087
[442]3088        return sampleContributions;
3089}
3090
[489]3091
[503]3092void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
3093                                                                                        const ObjectContainer &objects)
[475]3094{
[442]3095        //-- post processing of bsp view cells
3096    int vcSize = 0;
3097        int pvsSize = 0;
3098
[650]3099        //-- merge view cells
3100       
3101        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
3102        long startTime = GetTime();
3103
3104
[597]3105        if (mMergeViewCells)
3106        {
3107                // TODO: should be done BEFORE the ray casting
[650]3108                mViewCellsTree->ConstructMergeTree(rays, objects);
3109        }
3110        else
3111        {
3112                mViewCellsTree->SetRoot(ConstructSpatialMergeTree(mVspBspTree->GetRoot()));
3113        }
[442]3114
[666]3115        if (1)
3116        {
3117                char mstats[100];
3118                environment->GetStringValue("ViewCells.mergeStats", mstats);
3119                mViewCellsTree->ExportStats(mstats);
3120        }
[485]3121
[650]3122        //-- stats and visualizations
3123        cout << "finished merging" << endl;
3124        cout << "merged view cells in "
3125                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
[503]3126
[650]3127        Debug << "Postprocessing: Merged view cells in "
3128                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
3129       
3130
[600]3131        int savedColorCode = mColorCode;
3132       
[660]3133        // get currently active view cell set
3134        ResetViewCells();
3135        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
3136
[485]3137        //BspLeaf::NewMail();
[667]3138        if (1) // export merged view cells
[483]3139        {
[600]3140                mColorCode = 0;
[485]3141                Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
[660]3142               
[485]3143                cout << "exporting view cells after merge ... ";
3144
3145                if (exporter)
[483]3146                {
[600]3147                        if (0)
3148                                exporter->SetWireframe();
3149                        else
3150                                exporter->SetFilled();
3151
3152                        ExportViewCellsForViz(exporter);
3153
[485]3154                        if (mExportGeometry)
[483]3155                        {
[485]3156                                Material m;
3157                                m.mDiffuseColor = RgbColor(0, 1, 0);
3158                                exporter->SetForcedMaterial(m);
3159                                exporter->SetFilled();
[442]3160
[485]3161                                exporter->ExportGeometry(objects);
[442]3162                        }
[485]3163
[600]3164                        delete exporter;
3165                }
3166                cout << "finished" << endl;
3167        }
3168
[667]3169        if (1) // export merged view cells using pvs coding
[600]3170        {
3171                mColorCode = 1;
3172
3173                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.x3d");
3174       
3175                cout << "exporting view cells after merge (pvs size) ... ";     
3176
3177                if (exporter)
3178                {
[598]3179                        if (0)
3180                                exporter->SetWireframe();
3181                        else
3182                                exporter->SetFilled();
3183
3184                        ExportViewCellsForViz(exporter);
3185
[600]3186                        if (mExportGeometry)
3187                        {
3188                                Material m;
3189                                m.mDiffuseColor = RgbColor(0, 1, 0);
3190                                exporter->SetForcedMaterial(m);
3191                                exporter->SetFilled();
3192
3193                                exporter->ExportGeometry(objects);
3194                        }
3195
[485]3196                        delete exporter;
[442]3197                }
[485]3198                cout << "finished" << endl;
[442]3199        }
[600]3200
3201        mColorCode = savedColorCode;
3202
[503]3203}
[475]3204
[503]3205
[609]3206bool VspBspViewCellsManager::EqualToSpatialNode(ViewCell *viewCell) const
[607]3207{
[609]3208        return GetSpatialNode(viewCell) != NULL;
[607]3209}
3210
3211
[609]3212BspNode *VspBspViewCellsManager::GetSpatialNode(ViewCell *viewCell) const
[607]3213{
3214        if (!viewCell->IsLeaf())
3215        {
3216                BspViewCell *bspVc = dynamic_cast<BspViewCell *>(viewCell);
3217
[609]3218                return bspVc->mLeaf;
3219        }
[607]3220        else
3221        {
3222                ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(viewCell);
3223
3224                // cannot be node of binary tree
3225                if (interior->mChildren.size() != 2)
[609]3226                        return NULL;
[607]3227
3228                ViewCell *left = interior->mChildren[0];
3229                ViewCell *right = interior->mChildren[1];
3230
[609]3231                BspNode *leftNode = GetSpatialNode(left);
3232                BspNode *rightNode = GetSpatialNode(right);
[607]3233
[609]3234                if (leftNode && rightNode && leftNode->IsSibling(rightNode))
[607]3235                {
[609]3236                        return leftNode->GetParent();
[607]3237                }
[609]3238        }
[607]3239
[609]3240        return NULL;
[607]3241}
3242
3243
[564]3244void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
3245                                                                                         const ObjectContainer &objects)
[503]3246{
[485]3247        Debug << "render time before refine:" << endl;
3248        mRenderer->RenderScene();
[503]3249        SimulationStatistics ss;
[485]3250        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
3251    Debug << ss << endl;
3252
[489]3253        cout << "Refining the merged view cells ... ";
[503]3254        long startTime = GetTime();
[485]3255
3256        // refining the merged view cells
[580]3257        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
[485]3258
[442]3259        //-- stats and visualizations
3260        cout << "finished" << endl;
[485]3261        cout << "refined " << refined << " view cells in "
[442]3262                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
3263
[485]3264        Debug << "Postprocessing: refined " << refined << " view cells in "
[475]3265                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
[503]3266}
[495]3267
[517]3268
[503]3269int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
3270                                                                                const VssRayContainer &rays)
3271{
3272        if (!ViewCellsConstructed())
3273        {
[517]3274                Debug << "postprocess error: no view cells constructed" << endl;
[503]3275                return 0;
3276        }
[520]3277
[564]3278
[609]3279        // view cells already finished before post processing step
3280        // (i.e. because they were loaded)
[520]3281        if (mViewCellsFinished)
[542]3282        {
[551]3283                FinalizeViewCells(true);
[542]3284                EvaluateViewCellsStats();
[577]3285
[517]3286                return 0;
[542]3287        }
[448]3288
[564]3289
[542]3290        // check if new view cells turned invalid
[574]3291        SetValidity(mMinPvsSize, mMaxPvsSize);
3292        // update valid view space according to valid view cells
[544]3293        mVspBspTree->ValidateTree();
[542]3294
[574]3295        // has to be recomputed
3296        mTotalAreaValid = false;
[517]3297        VssRayContainer postProcessRays;
[605]3298        GetRaySets(rays, mPostProcessSamples, postProcessRays);
3299
[517]3300        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
[564]3301
[517]3302
[552]3303        // should maybe be done here to allow merge working with area or volume
3304        // and to correct the rendering statistics
[554]3305        if (0)
[551]3306        {
3307                FinalizeViewCells(false);
3308        }
3309
[597]3310        //-- merge the individual view cells
3311        MergeViewCells(postProcessRays, objects);
[591]3312       
[693]3313        // only for testing
3314        TestSubdivision();
3315
[597]3316        //-- refines the merged view cells
3317        if (0)
3318                RefineViewCells(postProcessRays, objects);
[568]3319
[660]3320
3321        //-- render simulation after merge + refine
3322       
[605]3323        cout << "\nevaluating bsp view cells render time before compress ... ";
3324        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
3325        SimulationStatistics ss;
3326        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
[600]3327 
[580]3328
[605]3329        cout << " finished" << endl;
3330        cout << ss << endl;
3331        Debug << ss << endl;
[600]3332
3333
3334        //-- compression
3335
3336        if (ViewCellsTreeConstructed() && mCompressViewCells)
3337        {
3338                int pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
3339                Debug << "number of entries before compress: " << pvsEntries << endl;
3340
3341                mViewCellsTree->CompressViewCellsPvs();
3342
3343                pvsEntries = mViewCellsTree->GetNumPvsEntries(mViewCellsTree->GetRoot());
3344                Debug << "number of entries after compress: " << pvsEntries << endl;
3345        }
3346
[660]3347
[517]3348        // collapse sibling leaves that share the same view cell
[586]3349        if (0)
3350                mVspBspTree->CollapseTree();
3351
[574]3352        // recompute view cell list and statistics
[520]3353        ResetViewCells();
3354
[508]3355        // real meshes are only contructed only at this stage
[551]3356        FinalizeViewCells(true);
[517]3357
[508]3358        // write view cells to disc
3359        if (mExportViewCells)
3360        {
[517]3361                char buff[100];
3362                environment->GetStringValue("ViewCells.filename", buff);
3363                string vcFilename(buff);
3364
3365                ExportViewCells(buff);
[508]3366        }
[503]3367
3368        return 0;
[442]3369}
3370
[490]3371
[442]3372int VspBspViewCellsManager::GetType() const
3373{
3374        return VSP_BSP;
3375}
3376
3377
[650]3378ViewCell *VspBspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
[609]3379{
[650]3380        if (root->IsLeaf())
3381        {
3382                ViewCell *viewCell = dynamic_cast<BspLeaf *>(root)->GetViewCell();
[610]3383
[650]3384                viewCell->SetMergeCost(0.0f);
[649]3385
[650]3386                return viewCell;
3387        }
3388       
3389        BspInterior *interior = dynamic_cast<BspInterior *>(root);
3390        ViewCellInterior *viewCellInterior = new ViewCellInterior();
3391               
3392        float mergeCost = 1.0f / (float)root->mTimeStamp;
3393        //Debug << "timestamp: " << root->mTimeStamp;
3394        //Debug << "merge cost: " << mergeCost << endl;
[610]3395
[650]3396        viewCellInterior->SetMergeCost(mergeCost);
[610]3397
[650]3398        float volume = 0;
3399       
3400        BspNode *front = interior->GetFront();
3401        BspNode *back = interior->GetBack();
[649]3402
[650]3403        // recursivly compute child hierarchies
3404        ViewCell *backVc = ConstructSpatialMergeTree(back);
3405        ViewCell *frontVc = ConstructSpatialMergeTree(front);
[610]3406
[650]3407        viewCellInterior->SetupChildLink(frontVc);
3408        viewCellInterior->SetupChildLink(backVc);
3409
3410
3411        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
3412        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
3413
3414        volume += backVc->GetVolume();
3415        volume += frontVc->GetVolume();
3416
3417        viewCellInterior->SetVolume(volume);
3418
3419        return viewCellInterior;
[609]3420}
3421
3422
[490]3423bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
3424{
3425        if (!ViewCellsConstructed())
3426                return ViewCellsManager::GetViewPoint(viewPoint);
3427
3428        // TODO: set reasonable limit
3429        const int limit = 20;
3430
3431        for (int i = 0; i < limit; ++ i)
3432        {
[542]3433                viewPoint = mViewSpaceBox.GetRandomPoint();
[490]3434                if (mVspBspTree->ViewPointValid(viewPoint))
3435                {
3436                        return true;
3437                }
3438        }
3439        Debug << "failed to find valid view point, taking " << viewPoint << endl;
3440        return false;
3441}
3442
3443
3444bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
3445{
[569]3446  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
3447  // validy update in preprocessor for all managers)
3448  return ViewCellsManager::ViewPointValid(viewPoint);
[570]3449
[569]3450  //    return mViewSpaceBox.IsInside(viewPoint) &&
3451  //               mVspBspTree->ViewPointValid(viewPoint);
[490]3452}
3453
3454
[442]3455void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]3456                                                                           const VssRayContainer &sampleRays)
[442]3457{
3458        if (!ViewCellsConstructed())
3459                return;
3460
[485]3461        VssRayContainer visRays;
3462        GetRaySets(sampleRays, mVisualizationSamples, visRays);
[483]3463
[600]3464       
[651]3465        if (1) // export view cells
[612]3466        {       // hack pvs
[600]3467                int savedColorCode = mColorCode;
[651]3468                mColorCode = 0;
[485]3469                Exporter *exporter = Exporter::GetExporter("final_view_cells.x3d");
[600]3470               
[442]3471                if (exporter)
3472                {
[580]3473                        cout << "exporting view cells after post process ... ";
3474
[600]3475                        if (0)
[542]3476                        {
3477                                exporter->SetWireframe();
3478                                exporter->ExportBox(mViewSpaceBox);
3479                                exporter->SetFilled();
3480                        }
3481
[485]3482                        if (mExportGeometry)
[542]3483                        {
[485]3484                                exporter->ExportGeometry(objects);
[542]3485                        }
[489]3486
3487                        // export rays
[490]3488                        if (mExportRays)
[489]3489                        {
[490]3490                                exporter->ExportRays(visRays, RgbColor(0, 1, 0));
3491                        }
[564]3492
[508]3493                        ExportViewCellsForViz(exporter);
[442]3494                        delete exporter;
[580]3495                        cout << "finished" << endl;
[442]3496                }
[600]3497
3498                mColorCode = savedColorCode;
[557]3499        }
[503]3500
[600]3501        if (0)
[577]3502        {
3503                cout << "exporting depth map ... ";
3504
3505                Exporter *exporter = Exporter::GetExporter("depth_map.x3d");
3506                if (exporter)
3507                {
3508                        if (1)
3509                        {
3510                                exporter->SetWireframe();
3511                                exporter->ExportBox(mViewSpaceBox);
3512                                exporter->SetFilled();
3513                        }
3514
3515                        if (mExportGeometry)
3516                        {
3517                                exporter->ExportGeometry(objects);
3518                        }
3519
3520                        const int maxDepth = mVspBspTree->mBspStats.maxDepth;
3521
3522                        ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
3523
3524                        for (vit = mViewCells.begin(); vit != mViewCells.end(); ++ vit)
3525                        {
[582]3526                                ViewCell *vc = *vit;
[577]3527
[580]3528                                ViewCellContainer leaves;
3529                                mViewCellsTree->CollectLeaves(vc, leaves);
[577]3530
[580]3531                                ViewCellContainer::const_iterator lit, lit_end = leaves.end();
3532
3533                                for (lit = leaves.begin(); lit != lit_end; ++ lit)
[577]3534                                {
[580]3535                                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*lit)->mLeaf;
[577]3536
3537                                        Material m;
3538
3539                                        float relDepth = (float)leaf->GetDepth() / (float)maxDepth;
3540                                        m.mDiffuseColor.r = relDepth;
3541                                        m.mDiffuseColor.g = 0.0f;
3542                                        m.mDiffuseColor.b = 1.0f - relDepth;
3543
3544                    exporter->SetForcedMaterial(m);
3545                               
3546
3547                                        BspNodeGeometry geom;
3548                                        mVspBspTree->ConstructGeometry(leaf, geom);
[678]3549                                        exporter->ExportPolygons(geom.GetPolys());
[577]3550                                }
3551                        }
3552
3553                        delete exporter;
3554                }
3555
3556
3557                cout << "finished" << endl;
3558        }
3559
[442]3560        //-- visualization of the BSP splits
3561        bool exportSplits = false;
[489]3562        environment->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
[503]3563
[442]3564        if (exportSplits)
3565        {
3566                cout << "exporting splits ... ";
[485]3567                ExportSplits(objects, visRays);
[442]3568                cout << "finished" << endl;
3569        }
3570
[542]3571        //-- export single view cells
[485]3572        ExportBspPvs(objects, visRays);
[442]3573}
3574
[503]3575
[485]3576void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
3577                                                                                  const VssRayContainer &rays)
[442]3578{
3579        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
3580
[503]3581        if (exporter)
3582        {
3583                Material m;
[442]3584                m.mDiffuseColor = RgbColor(1, 0, 0);
3585                exporter->SetForcedMaterial(m);
3586                exporter->SetWireframe();
[503]3587
[448]3588                exporter->ExportBspSplits(*mVspBspTree, true);
[442]3589
3590                // take forced material, else big scenes cannot be viewed
3591                m.mDiffuseColor = RgbColor(0, 1, 0);
3592                exporter->SetForcedMaterial(m);
3593                exporter->SetFilled();
3594
3595                exporter->ResetForcedMaterial();
[503]3596
[442]3597                // export rays
[485]3598                if (mExportRays)
3599                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
[503]3600
[485]3601                if (mExportGeometry)
[442]3602                        exporter->ExportGeometry(objects);
3603
3604                delete exporter;
3605        }
3606}
3607
[503]3608
[485]3609void VspBspViewCellsManager::ExportBspPvs(const ObjectContainer &objects,
3610                                                                                  const VssRayContainer &rays)
[442]3611{
[639]3612        const int leafOut = 20;
[503]3613
[442]3614        ViewCell::NewMail();
[503]3615
[639]3616        cout << "visualization using " << (int)rays.size() << " samples" << endl;
3617        Debug << "visualization using " << (int)rays.size() << " samples" << endl;
[475]3618        Debug << "\nOutput view cells: " << endl;
[503]3619
[694]3620        const bool sortViewCells = true;
3621
[485]3622        // sort view cells to visualize the largest view cells
[694]3623        if (sortViewCells)
[587]3624                stable_sort(mViewCells.begin(), mViewCells.end(), vc_gt);
[639]3625       
[503]3626        int limit = min(leafOut, (int)mViewCells.size());
[483]3627
[639]3628        int raysOut = 0;
[587]3629
[485]3630        //-- some rays for output
[478]3631        for (int i = 0; i < limit; ++ i)
[442]3632        {
[478]3633                cout << "creating output for view cell " << i << " ... ";
[503]3634
[582]3635                ViewCell *vc;
[574]3636       
[694]3637                if (sortViewCells) // largest view cell pvs first
[582]3638                        vc = mViewCells[i];
[574]3639                else
[639]3640                        vc = mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 1)];
[442]3641
[639]3642                //bspLeaves[j]->Mail();
3643                char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
3644                Exporter *exporter = Exporter::GetExporter(s);
3645               
3646                Debug << i << ": pvs size=" << (int)mViewCellsTree->GetPvsSize(vc) << endl;
[587]3647
[639]3648                if (1 || mExportRays)
[442]3649                {
[694]3650                        // output rays stored with the view cells during subdivision
[643]3651                        if (0)
[442]3652                        {
[639]3653                                VssRayContainer vcRays;
3654                VssRayContainer collectRays;
3655
3656                                raysOut = min((int)rays.size(), 100);
3657
3658                                // collect intial view cells
3659                                ViewCellContainer leaves;
3660                                mViewCellsTree->CollectLeaves(vc, leaves);
3661
3662                                ViewCellContainer::const_iterator vit, vit_end = leaves.end();
3663       
3664                                for (vit = leaves.begin(); vit != vit_end; ++ vit)
[574]3665                                {
[639]3666                                        BspLeaf *vcLeaf = dynamic_cast<BspViewCell *>(*vit)->mLeaf;
3667                               
3668                                        VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
[587]3669
[639]3670                                        for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
3671                                        {
3672                                                collectRays.push_back(*rit);
3673                                        }
[574]3674                                }
[639]3675
3676                                VssRayContainer::const_iterator rit, rit_end = collectRays.end();
3677
3678                                for (rit = collectRays.begin(); rit != rit_end; ++ rit)
3679                                {
3680                                        float p = RandomValue(0.0f, (float)collectRays.size());
3681                       
3682                                        if (p < raysOut)
3683                                                vcRays.push_back(*rit);
3684                                }
3685                                //-- export rays piercing this view cell
3686                                exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
[442]3687                        }
[651]3688               
[694]3689                        // associate new rays with output view cell
[643]3690                        if (1)
[639]3691                        {
3692                                VssRayContainer vcRays;
3693                                raysOut = min((int)rays.size(), mVisualizationSamples);
3694                                // check whether we can add the current ray to the output rays
3695                                for (int k = 0; k < raysOut; ++ k)
3696                                {
3697                                        VssRay *ray = rays[k];
3698                                        for     (int j = 0; j < (int)ray->mViewCells.size(); ++ j)
3699                                        {
3700                                                ViewCell *rayvc = ray->mViewCells[j];
3701       
3702                                                if (rayvc == vc)
3703                                                        vcRays.push_back(ray);
3704                                        }
3705                                }       
3706                               
3707                                //-- export rays piercing this view cell
3708                                exporter->ExportRays(vcRays, RgbColor(1, 1, 0));
3709                        }
3710
[442]3711                }
[639]3712               
[574]3713
[478]3714                exporter->SetWireframe();
[442]3715
[478]3716                Material m;//= RandomMaterial();
3717                m.mDiffuseColor = RgbColor(0, 1, 0);
3718                exporter->SetForcedMaterial(m);
[442]3719
[580]3720                ExportViewCellGeometry(exporter, vc);
[639]3721       
3722                exporter->SetFilled();
[503]3723
[639]3724
[574]3725                if (1)
3726                {
[639]3727                        ObjectPvsMap::const_iterator oit,
3728                                oit_end = vc->GetPvs().mEntries.end();
[483]3729
[580]3730
[639]3731                        exporter->SetFilled();
[580]3732
[639]3733                        Intersectable::NewMail();
[574]3734       
[639]3735                        // output PVS of view cell
3736                        for (oit = vc->GetPvs().mEntries.begin(); oit != oit_end; ++ oit)
3737                        {               
3738                                Intersectable *intersect = (*oit).first;
[442]3739
[639]3740                                if (!intersect->Mailed())
3741                                {
[643]3742                                        m = RandomMaterial();
3743                                        exporter->SetForcedMaterial(m);
[442]3744
[639]3745                                        exporter->ExportIntersectable(intersect);
3746                                        intersect->Mail();
3747                                }
[503]3748                        }
[442]3749                }
[639]3750                else
3751                {
[643]3752                        m.mDiffuseColor = RgbColor(1, 0, 0);
3753                        exporter->SetForcedMaterial(m);
3754
[639]3755                        exporter->ExportGeometry(objects);
3756                }
[503]3757
[478]3758                DEL_PTR(exporter);
3759                cout << "finished" << endl;
[442]3760        }
[475]3761
3762        Debug << endl;
[442]3763}
3764
3765
[697]3766int VspBspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box, ViewCellContainer &viewCells) const
3767{
3768        return mVspBspTree->ComputeBoxIntersections(box, viewCells);
3769}
3770
3771
[469]3772int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
3773                                                                                        const Vector3 &termination,
3774                                                                                        ViewCellContainer &viewcells)
[466]3775{
[469]3776        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
[466]3777}
[482]3778
3779
[503]3780void VspBspViewCellsManager::ExportColor(Exporter *exporter,
[482]3781                                                                                 ViewCell *vc) const
3782{
[564]3783        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
[503]3784
[482]3785        float importance = 0;
[564]3786        static Material m;
3787
[482]3788        switch (mColorCode)
3789        {
[564]3790        case 0: // Random
3791                {
3792                        if (vcValid)
3793                        {
[598]3794                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
3795                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
3796                                m.mDiffuseColor.b = 0.5f + RandomValue(0.f, 0.5f);
[564]3797                        }
3798                        else
3799                        {
3800                                m.mDiffuseColor.r = 0.0f;
3801                                m.mDiffuseColor.g = 1.0f;
3802                                m.mDiffuseColor.b = 0.0f;
3803                        }
[591]3804
3805                        exporter->SetForcedMaterial(m);
3806                        return;
[564]3807                }
[591]3808               
[482]3809        case 1: // pvs
3810                {
[503]3811                        importance = (float)vc->GetPvs().GetSize() /
[660]3812                                (float)mCurrentViewCellsStats.maxPvs;
[570]3813
[482]3814                }
3815                break;
3816        case 2: // merges
3817                {
[580]3818            int lSize = mViewCellsTree->GetSize(vc);
[660]3819                        importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
[482]3820                }
3821                break;
3822        case 3: // merge tree differene
3823                {
[503]3824                        importance = (float)GetMaxTreeDiff(vc) /
[482]3825                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
[547]3826
[482]3827                }
3828                break;
3829        default:
3830                break;
3831        }
3832
[564]3833        // special color code for invalid view cells
[482]3834        m.mDiffuseColor.r = importance;
3835        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
[564]3836        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
[547]3837
[482]3838        //Debug << "importance: " << importance << endl;
3839        exporter->SetForcedMaterial(m);
3840}
3841
3842
[580]3843void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]3844                                                    ViewCell *vc,
[660]3845                                                                                                        const Plane3 *clipPlane) const
[482]3846{
[542]3847        if (vc->GetMesh())
[503]3848        {
3849                exporter->ExportMesh(vc->GetMesh());
[590]3850       
[503]3851                return;
3852        }
3853
[591]3854       
[660]3855        if (clipPlane)
[591]3856        {
3857                ViewCellContainer leaves;
3858                mViewCellsTree->CollectLeaves(vc, leaves);
3859                ViewCellContainer::const_iterator it, it_end = leaves.end();
3860
3861                for (it = leaves.begin(); it != it_end; ++ it)
3862                {
3863                        BspNodeGeometry geom;
3864
3865                        BspNodeGeometry front;
3866                        BspNodeGeometry back;
3867
3868                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
3869                        mVspBspTree->ConstructGeometry(leaf, geom);
3870
[683]3871                        const int cf = Polygon3::ClassifyPlane(geom.GetPolys(), *clipPlane, 0.00000001f);
[682]3872
[684]3873                        if (cf == Polygon3::BACK_SIDE)
[682]3874                        {
3875                                exporter->ExportPolygons(geom.GetPolys());
3876                        }
3877                        else if (cf == Polygon3::SPLIT)
[684]3878                        {
[682]3879                                geom.SplitGeometry(front,
3880                                                                   back,
3881                                                                   *clipPlane,
3882                                                                   mViewSpaceBox,
[683]3883                                                                   0.00000001f);
[682]3884       
[694]3885                                //Debug << "geo size: " << geom.Size() << endl;
3886                                //Debug << "size b: " << back.Size() << " f: " << front.Size() << endl;
[683]3887                                if (back.Valid())
3888                                {
[682]3889                                        exporter->ExportPolygons(back.GetPolys());
[683]3890                                }
[694]3891                       
[684]3892                        }
[591]3893                }
3894        }
3895        else
3896        {
3897                BspNodeGeometry geom;
3898                mVspBspTree->ConstructGeometry(vc, geom);
3899                       
[678]3900                exporter->ExportPolygons(geom.GetPolys());
[591]3901        }
[482]3902}
3903
3904
3905int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
3906{
[580]3907        ViewCellContainer leaves;
3908        mViewCellsTree->CollectLeaves(vc, leaves);
[482]3909
3910        int maxDist = 0;
[580]3911       
[482]3912        // compute max height difference
[580]3913        for (int i = 0; i < (int)leaves.size(); ++ i)
3914                for (int j = 0; j < (int)leaves.size(); ++ j)
[482]3915        {
[580]3916                BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaf;
[482]3917
3918                if (i != j)
3919                {
[580]3920                        BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaf;
[482]3921                        int dist = mVspBspTree->TreeDistance(leaf, leaf2);
3922                        if (dist > maxDist)
3923                                maxDist = dist;
3924                }
3925        }
[580]3926
[492]3927        return maxDist;
3928}
[482]3929
[492]3930
[569]3931ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point) const
[492]3932{
[508]3933        if (!mVspBspTree)
3934                return NULL;
[572]3935
3936        if (!mViewSpaceBox.IsInside(point))
3937          return NULL;
3938
[508]3939        return mVspBspTree->GetViewCell(point);
[492]3940}
[503]3941
3942
3943void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
3944{
[577]3945        if (vc->GetMesh())
3946                delete vc->GetMesh();
3947
[590]3948       
[503]3949        BspNodeGeometry geom;
[590]3950
3951        mVspBspTree->ConstructGeometry(vc, geom);
[582]3952       
[503]3953        Mesh *mesh = new Mesh();
3954        geom.AddToMesh(*mesh);
3955        vc->SetMesh(mesh);
3956        mMeshContainer.push_back(mesh);
3957}
[508]3958
3959
[577]3960ViewCellsManager *ViewCellsManager::LoadViewCells(const string filename,
3961                                                                                                  ObjectContainer *objects)
[508]3962{
3963        ViewCellsParser parser;
[564]3964
[577]3965        ViewCellsManager *vm = NULL;
[564]3966
[577]3967        if (parser.ParseFile(filename, &vm, objects))
3968        {
[590]3969                //vm->PrepareLoadedViewCells();
[577]3970                vm->ResetViewCells();
[564]3971
[577]3972                vm->mViewCellsFinished = true;
3973                vm->mMaxPvsSize = (int)objects->size();
[517]3974
[577]3975                vm->FinalizeViewCells(true);
[564]3976
[685]3977                vm->mViewCellsTree->AssignRandomColors();
[577]3978                Debug << (int)vm->mViewCells.size() << " view cells loaded" << endl;
3979        }
3980        else
3981        {
3982                Debug << "failed loading view cells" << endl;
3983                DEL_PTR(vm);
3984        }
3985
3986
3987        return vm;
[508]3988}
3989
3990
3991inline bool ilt(Intersectable *obj1, Intersectable *obj2)
3992{
3993        return obj1->mId < obj2->mId;
3994}
3995
3996
3997bool VspBspViewCellsManager::ExportViewCells(const string filename)
3998{
[564]3999        cout << "exporting view cells to xml ... ";
[508]4000        std::ofstream stream;
4001
[577]4002        // for output we need unique ids for each view cell
[590]4003        CreateUniqueViewCellIds();
[508]4004
4005        stream.open(filename.c_str());
4006        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
4007        stream << "<Visibility_Solution>" << endl;
[564]4008
[577]4009        //-- the view space bounding box
4010        stream << "<ViewSpaceBox"
4011                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
4012                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\" />" << endl;
4013
4014        //-- the type of the view cells hierarchy
4015        stream << "<Hierarchy name=\"vspBspTree\" />" << endl;
4016
[508]4017        //-- load the view cells itself, i.e., the ids and the pvs
4018        stream << "<ViewCells>" << endl;
[610]4019       
4020#if 0
4021       
[508]4022        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[610]4023               
[508]4024        for (it = mViewCells.begin(); it != it_end; ++ it)
4025                ExportViewCell(*it, stream);
[610]4026#else
4027        mViewCellsTree->Export(stream);
4028#endif
[564]4029
[508]4030        stream << "</ViewCells>" << endl;
[564]4031
[508]4032        //-- load the hierarchy
[590]4033        stream << "<Hierarchy>" << endl;
[508]4034        mVspBspTree->Export(stream);
[590]4035        stream << endl << "</Hierarchy>" << endl;
[564]4036
[508]4037        stream << "</Visibility_Solution>" << endl;
4038        stream.close();
4039
4040        cout << "finished" << endl;
4041
4042        return true;
[532]4043}
4044
4045
4046int VspBspViewCellsManager::CastBeam(Beam &beam)
4047{
[535]4048        return mVspBspTree->CastBeam(beam);
[532]4049}
[551]4050
4051
[587]4052void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
4053                                                                          const bool createMesh)
[551]4054{
4055        float area = 0;
4056        float volume = 0;
4057
[580]4058        ViewCellContainer leaves;
[582]4059        mViewCellsTree->CollectLeaves(viewCell, leaves);
[580]4060
4061        ViewCellContainer::const_iterator it, it_end = leaves.end();
4062
[693]4063    for (it = leaves.begin(); it != it_end; ++ it)
[551]4064        {
4065                BspNodeGeometry geom;
[580]4066                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
[551]4067                mVspBspTree->ConstructGeometry(leaf, geom);
4068
[693]4069                float lVol = geom.GetVolume();
4070                float lArea = geom.GetArea();
4071
4072                //(*it)->SetVolume(vol);
4073                //(*it)->SetArea(area);
4074
4075                area += lArea;
4076                volume += lVol;
4077
4078        CreateMesh(*it);
[551]4079        }
4080
4081        viewCell->SetVolume(volume);
4082        viewCell->SetArea(area);
[563]4083}
[575]4084
4085
[693]4086void VspBspViewCellsManager::TestSubdivision()
4087{
4088        ViewCellContainer leaves;
4089        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
4090
4091        ViewCellContainer::const_iterator it, it_end = leaves.end();
4092
4093        const float vol = mViewSpaceBox.GetVolume();
4094        float subdivVol = 0;
4095        float newVol = 0;
4096
4097        for (it = leaves.begin(); it != it_end; ++ it)
4098        {
4099                BspNodeGeometry geom;
4100                BspLeaf *leaf = dynamic_cast<BspViewCell *>(*it)->mLeaf;
4101                mVspBspTree->ConstructGeometry(leaf, geom);
4102
4103                const float lVol = geom.GetVolume();
4104               
4105                newVol += lVol;
4106                subdivVol += (*it)->GetVolume();
[697]4107               
4108                float thres = 0.9;
4109                if ((lVol < ((*it)->GetVolume() * thres)) || (lVol * thres > ((*it)->GetVolume())))
4110                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
[693]4111        }
4112       
4113        Debug << "exact volume: " << vol << endl;
4114        Debug << "subdivision volume: " << subdivVol << endl;
4115        Debug << "new volume: " << newVol << endl;
4116}
4117
4118
[577]4119void VspBspViewCellsManager::PrepareLoadedViewCells()
4120{
4121        // TODO: do I still need this here?
[590]4122        if (0)
[693]4123                mVspBspTree->RepairViewCellsLeafLists();
[577]4124}
[575]4125
[577]4126
[697]4127void VspBspViewCellsManager::TestFilter(const ObjectContainer &objects)
4128{
4129        Exporter *exporter = Exporter::GetExporter("filter.x3d");
[580]4130
[697]4131        if (exporter)
4132        {
4133                AxisAlignedBox3 testBox = mViewSpaceBox;
4134                Vector3 bsize = mViewSpaceBox.Size();
4135
4136                testBox.Enlarge(Vector3(-bsize[0] * 0.3, 0, -bsize[2] * 0.4));
4137               
4138                ViewCellContainer viewCells;
4139       
4140                mVspBspTree->ComputeBoxIntersections(testBox, viewCells);
4141                cout << "view cells: " << viewCells.size() << endl;
4142               
4143                exporter->SetWireframe();
4144
4145                exporter->SetForcedMaterial(RgbColor(1,1,1));
4146                exporter->ExportBox(testBox);
4147               
4148                exporter->SetFilled();
4149                exporter->ResetForcedMaterial();
4150        for (int i = 0; i < viewCells.size(); ++ i)
4151                {
4152                        BspNodeGeometry geom;
4153                               
4154                        mVspBspTree->ConstructGeometry(viewCells[i], geom);
4155                        exporter->ExportPolygons(geom.GetPolys());
4156                }               
4157
4158                exporter->SetForcedMaterial(RgbColor(1,0,0));
4159                exporter->ExportGeometry(objects);
4160
4161                delete exporter;
4162        }
4163}
4164
4165
[580]4166void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
4167                                                                                                        vector<MergeCandidate> &candidates)
4168{       
4169        cout << "collecting merge candidates ... " << endl;
4170
4171        if (mUseRaysForMerge)
4172        {
4173                mVspBspTree->CollectMergeCandidates(rays, candidates);
4174        }
4175        else
4176        {
4177                vector<BspLeaf *> leaves;
4178                mVspBspTree->CollectLeaves(leaves);
4179                mVspBspTree->CollectMergeCandidates(leaves, candidates);
4180        }
4181
4182        cout << "fininshed collecting candidates" << endl;
4183}
4184
4185
[590]4186void VspBspViewCellsManager::AddCurrentViewCellsToHierarchy()
4187{
4188        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
4189        for (it = mViewCells.begin(); it != it_end; ++ it)
4190        {
4191        }
4192}
[580]4193
4194//////////////////////////////////
[575]4195ViewCellsManager *ViewCellsManagerFactory::Create(const string mName)
4196{
4197        //TODO
4198        return NULL;// new VspBspViewCellsManager();
4199}
[580]4200
Note: See TracBrowser for help on using the repository browser.