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

Revision 1744, 153.7 KB checked in by mattausch, 18 years ago (diff)
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"
[1233]10#include "HierarchyManager.h"
[440]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"
[931]17#include "BoundingBoxConverter.h"
[979]18#include "GlRenderer.h"
[1001]19#include "ResourceManager.h"
[1315]20#include "IntersectableWrapper.h"
[1233]21#include "VspTree.h"
22#include "OspTree.h"
[1259]23#include "BvHierarchy.h"
[1520]24#include "SamplingStrategy.h"
[1545]25#include "SceneGraph.h"
[440]26
[1278]27
[1715]28#define ABS_CONTRIBUTION_WEIGHT 1.0f
29
[1667]30// warning: Should not count origin object for sampling because it disturbs heuristics
[1715]31#define SAMPLE_ORIGIN_OBJECTS 0  // matt temp
[931]32
[1594]33// $$JB HACK
[1627]34#define USE_KD_PVS 0
[1694]35#define KD_PVS_AREA (5*1e-4f)
[1486]36
[1703]37
38
[863]39namespace GtpVisibilityPreprocessor {
[860]40
41
[712]42// HACK
43const static bool SAMPLE_AFTER_SUBDIVISION = true;
[1744]44//const static bool CLAMP_TO_BOX = false;
45const static bool CLAMP_TO_BOX = true;
[517]46
[1705]47
[1703]48int ViewCellsManager::sRenderCostEvaluationType = 0;
49
50
[697]51template <typename T> class myless
52{
53public:
54        //bool operator() (HierarchyNode *v1, HierarchyNode *v2) const
55        bool operator() (T v1, T v2) const
56        {
57                return (v1->GetMergeCost() < v2->GetMergeCost());
58        }
59};
60
61
[1264]62ViewCellsManager::ViewCellsManager(ViewCellsTree *viewCellsTree):
[480]63mRenderer(NULL),
[574]64mInitialSamples(0),
[440]65mConstructionSamples(0),
66mPostProcessSamples(0),
[470]67mVisualizationSamples(0),
68mTotalAreaValid(false),
[517]69mTotalArea(0.0f),
[547]70mViewCellsFinished(false),
[562]71mMaxPvsSize(9999999),
[1686]72mMinPvsSize(0),
[719]73mMaxPvsRatio(1.0),
[1145]74mViewCellPvsIsUpdated(false),
[1264]75mPreprocessor(NULL),
[1545]76mViewCellsTree(viewCellsTree),
77mUsePredefinedViewCells(false)
[440]78{
[542]79        mViewSpaceBox.Initialize();
[482]80        ParseEnvironment();
[580]81
[1264]82        mViewCellsTree->SetViewCellsManager(this);
[440]83}
84
[517]85
[482]86void ViewCellsManager::ParseEnvironment()
87{
[503]88        // visualization stuff
[1004]89        Environment::GetSingleton()->GetBoolValue("ViewCells.Visualization.exportRays", mExportRays);
90        Environment::GetSingleton()->GetBoolValue("ViewCells.Visualization.exportGeometry", mExportGeometry);
91        Environment::GetSingleton()->GetFloatValue("ViewCells.maxPvsRatio", mMaxPvsRatio);
[664]92       
[1004]93        Environment::GetSingleton()->GetBoolValue("ViewCells.processOnlyValidViewCells", mOnlyValidViewCells);
[485]94
[1004]95        Environment::GetSingleton()->GetIntValue("ViewCells.Construction.samples", mConstructionSamples);
96        Environment::GetSingleton()->GetIntValue("ViewCells.PostProcess.samples", mPostProcessSamples);
97        Environment::GetSingleton()->GetBoolValue("ViewCells.PostProcess.useRaysForMerge", mUseRaysForMerge);
[595]98
[1004]99        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.samples", mVisualizationSamples);
[574]100
[1004]101        Environment::GetSingleton()->GetIntValue("ViewCells.Construction.samplesPerPass", mSamplesPerPass);
102        Environment::GetSingleton()->GetBoolValue("ViewCells.exportToFile", mExportViewCells);
[581]103       
[1004]104        Environment::GetSingleton()->GetIntValue("ViewCells.active", mNumActiveViewCells);
105        Environment::GetSingleton()->GetBoolValue("ViewCells.PostProcess.compress", mCompressViewCells);
106        Environment::GetSingleton()->GetBoolValue("ViewCells.Visualization.useClipPlane", mUseClipPlaneForViz);
107        Environment::GetSingleton()->GetBoolValue("ViewCells.PostProcess.merge", mMergeViewCells);
108        Environment::GetSingleton()->GetBoolValue("ViewCells.evaluateViewCells", mEvaluateViewCells);
109        Environment::GetSingleton()->GetBoolValue("ViewCells.showVisualization", mShowVisualization);
110        Environment::GetSingleton()->GetIntValue("ViewCells.Filter.maxSize", mMaxFilterSize);
111        Environment::GetSingleton()->GetFloatValue("ViewCells.Filter.width", mFilterWidth);
[1703]112        Environment::GetSingleton()->GetIntValue("ViewCells.renderCostEvaluationType", sRenderCostEvaluationType);
[710]113
[1004]114        Environment::GetSingleton()->GetBoolValue("ViewCells.exportBboxesForPvs", mExportBboxesForPvs);
115        Environment::GetSingleton()->GetBoolValue("ViewCells.exportPvs", mExportPvs);
[1142]116       
[664]117        char buf[100];
[1004]118        Environment::GetSingleton()->GetStringValue("ViewCells.samplingType", buf);
[664]119
[660]120       
[1744]121        /*ObjectPvs pvs1, pvs2, mergedPvs;
[1742]122
123        pvs1.AddSample((Intersectable *)1, 1);
124        pvs1.AddSample((Intersectable *)3, 1);
125        pvs1.AddSample((Intersectable *)6, 1);
126        pvs1.AddSample((Intersectable *)7, 1);
127        pvs1.AddSample((Intersectable *)9, 1);
128        pvs1.AddSample((Intersectable *)12, 1);
129        pvs1.AddSample((Intersectable *)15, 1);
130        pvs1.AddSample((Intersectable *)7, 1);
131        pvs2.AddSample((Intersectable *)3, 1);
132        pvs2.AddSample((Intersectable *)4, 1);
133        pvs2.AddSample((Intersectable *)6, 1);
134        pvs2.AddSample((Intersectable *)8, 1);
135        pvs2.AddSample((Intersectable *)9, 1);
136        pvs2.AddSample((Intersectable *)14, 1);
137
138        ObjectPvs::Merge(mergedPvs, pvs1, pvs2);
139
140        Debug << "\npvs1\n";
141        cout << "\npvs1\n";
142        ObjectPvsIterator pvs1It = pvs1.GetIterator();
143
144        while (pvs1It.HasMoreEntries())
145        {
146                ObjectPvsEntry entry = pvs1It.Next();
147               
148                Debug << (int)entry.mObject << " ";
149                cout << (int)entry.mObject << " ";
150        }
151
152Debug << "\npvs2\n";
153        cout << "\npvs2\n";
154        ObjectPvsIterator pvs2It = pvs2.GetIterator();
155
156        while (pvs2It.HasMoreEntries())
157        {
158                ObjectPvsEntry entry = pvs2It.Next();
159               
160                Debug << (int)entry.mObject << " ";
161                cout << (int)entry.mObject << " ";
162        }
163
164Debug << "\nmerged\n";
165        cout << "\nmerged\n";
166        ObjectPvsIterator mergedIt = mergedPvs.GetIterator();
167
168        while (mergedIt.HasMoreEntries())
169        {
170                ObjectPvsEntry entry = mergedIt.Next();
171                Debug << (int)entry.mObject << " " << entry.mData.mSumPdf << " x ";
172                cout << (int)entry.mObject << " " << entry.mData.mSumPdf << " x ";
173        }
[1744]174*/
[1020]175        // sampling type for view cells construction samples
[1695]176        if (strcmp(buf, "object") == 0)
[722]177        {
[1695]178                mSamplingType = SamplingStrategy::OBJECT_BASED_DISTRIBUTION;
179        }
180        else if (strcmp(buf, "box") == 0)
181        {
[1520]182                mSamplingType = SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION;
[722]183        }
[664]184        else if (strcmp(buf, "directional") == 0)
[722]185        {
[1520]186                mSamplingType = SamplingStrategy::DIRECTION_BASED_DISTRIBUTION;
[722]187        }
[1020]188        else if (strcmp(buf, "object_directional") == 0)
189        {
[1520]190                mSamplingType = SamplingStrategy::OBJECT_DIRECTION_BASED_DISTRIBUTION;
[1020]191        }
[1695]192        else if (strcmp(buf, "reverse_object") == 0)
193        {
194                mSamplingType = SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION;
195        }
[1022]196        /*else if (strcmp(buf, "interior") == 0)
197        {
198                mSamplingType = Preprocessor::OBJECTS_INTERIOR_DISTRIBUTION;
199        }*/
[1020]200        else
201        {
[666]202                Debug << "error! wrong sampling type" << endl;
203                exit(0);
204        }
[660]205
[1020]206        // sampling type for evaluation samples
[1004]207        Environment::GetSingleton()->GetStringValue("ViewCells.Evaluation.samplingType", buf);
[722]208       
[1695]209        if (strcmp(buf, "object") == 0)
[722]210        {
[1695]211                mEvaluationSamplingType = SamplingStrategy::OBJECT_BASED_DISTRIBUTION;
212        }
213        else if (strcmp(buf, "box") == 0)
214        {
[1520]215                mEvaluationSamplingType = SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION;
[722]216        }
217        else if (strcmp(buf, "directional") == 0)
218        {
[1520]219                mEvaluationSamplingType = SamplingStrategy::DIRECTION_BASED_DISTRIBUTION;
[722]220        }
[1020]221        else if (strcmp(buf, "object_directional") == 0)
[722]222        {
[1520]223                mEvaluationSamplingType = SamplingStrategy::OBJECT_DIRECTION_BASED_DISTRIBUTION;
[1020]224        }
[1695]225        else if (strcmp(buf, "reverse_object") == 0)
226        {
227                mEvaluationSamplingType = SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION;
228        }
[1022]229        /*else if (strcmp(buf, "interior") == 0)
[1020]230        {
[1520]231                mEvaluationSamplingType = SamplingStrategy::OBJECTS_INTERIOR_DISTRIBUTION;
[1022]232        }*/
[1020]233        else
234        {
[1695]235                mEvaluationSamplingType = -1;
[722]236                Debug << "error! wrong sampling type" << endl;
237                exit(0);
238        }
[503]239
[1004]240        Environment::GetSingleton()->GetStringValue("ViewCells.renderCostEvaluationType", buf);
[728]241       
[734]242        if (strcmp(buf, "perobject") == 0)
[728]243        {
[1703]244                sRenderCostEvaluationType = ViewCellsManager::PER_OBJECT;
[728]245        }
[1703]246        else if (strcmp(buf, "pertriangle") == 0)
[728]247        {
[1703]248                sRenderCostEvaluationType = ViewCellsManager::PER_TRIANGLE;
[728]249        }
250        else
251        {
252                Debug << "error! wrong sampling type" << endl;
253                exit(0);
254        }
255
[1004]256    Environment::GetSingleton()->GetStringValue("ViewCells.Visualization.colorCode", buf);
[722]257
[482]258        if (strcmp(buf, "PVS") == 0)
259                mColorCode = 1;
260        else if (strcmp(buf, "MergedLeaves") == 0)
261                mColorCode = 2;
262        else if (strcmp(buf, "MergedTreeDiff") == 0)
263                mColorCode = 3;
264        else
265                mColorCode = 0;
266
[664]267
[1418]268        Debug << "************ View Cells Manager options ***************" << endl;
[664]269        Debug << "color code: " << mColorCode << endl;
270
271        Debug << "export rays: " << mExportRays << endl;
272        Debug << "export geometry: " << mExportGeometry << endl;
273        Debug << "max pvs ratio: " << mMaxPvsRatio << endl;
274       
275        Debug << "process only valid view cells: " << mOnlyValidViewCells << endl;
276        Debug << "construction samples: " << mConstructionSamples << endl;
277        Debug << "post process samples: " << mPostProcessSamples << endl;
278        Debug << "post process use rays for merge: " << mUseRaysForMerge << endl;
279        Debug << "visualization samples: " << mVisualizationSamples << endl;
280        Debug << "construction samples per pass: " << mSamplesPerPass << endl;
281        Debug << "export to file: " << mExportViewCells << endl;
282       
[801]283        Debug << "active view cells: " << mNumActiveViewCells << endl;
[664]284        Debug << "post process compress: " << mCompressViewCells << endl;
285        Debug << "visualization use clipPlane: " << mUseClipPlaneForViz << endl;
286        Debug << "post process merge: " << mMergeViewCells << endl;
287        Debug << "evaluate view cells: " << mEvaluateViewCells << endl;
288        Debug << "sampling type: " << mSamplingType << endl;
[1703]289        Debug << "render cost evaluation type: " << sRenderCostEvaluationType << endl;
[728]290        Debug << "evaluation sampling type: " << mEvaluationSamplingType << endl;
[666]291        Debug << "show visualization: " << mShowVisualization << endl;
[697]292        Debug << "filter width: " << mFilterWidth << endl;
[710]293        Debug << "sample after subdivision: " << SAMPLE_AFTER_SUBDIVISION << endl;
[850]294
295        Debug << "export bounding boxes: " << mExportBboxesForPvs << endl;
296        Debug << "export pvs for view cells: " << mExportPvs << endl;
[664]297        Debug << endl;
[440]298}
299
[485]300
[440]301ViewCellsManager::~ViewCellsManager()
302{
[1020]303        // HACK: if view cells tree does not
[1264]304        // handle view cells, we have to do it here
[1020]305        // question: rather create view cells resource manager?
[598]306        if (!ViewCellsTreeConstructed())
[1141]307        {
[598]308                CLEAR_CONTAINER(mViewCells);
[1141]309        }
[1696]310        else
311        {
312                DEL_PTR(mViewCellsTree);
313        }
[440]314}
315
[1743]316Intersectable *
317ViewCellsManager::GetIntersectable(const VssRay &ray, const bool isTermination) const
318{
319  return isTermination ? ray.mTerminationObject : ray.mOriginObject;
320}
[1221]321
[1737]322void
323ViewCellsManager::CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects)
324{
325  GetPreprocessor()->mKdTree->CollectObjects(box, objects);
326}
[1613]327
[1221]328AxisAlignedBox3 ViewCellsManager::GetViewCellBox(ViewCell *vc)
[859]329{
330  Mesh *m = vc->GetMesh();
331 
[1563]332  if (m)
333  {
334          m->ComputeBoundingBox();
335          return m->mBox;
[859]336  }
[485]337
[859]338  AxisAlignedBox3 box;
339  box.Initialize();
340 
341  if (!vc->IsLeaf()) {
342        ViewCellInterior *vci = (ViewCellInterior *) vc;
343       
344        ViewCellContainer::iterator it = vci->mChildren.begin();
345        for (; it != vci->mChildren.end(); ++it) {
346          box.Include(GetViewCellBox(*it));
347        }
348  }
349 
350  return box;
351}
352
[693]353
[574]354int ViewCellsManager::CastPassSamples(const int samplesPerPass,
355                                                                          const int sampleType,
356                                                                          VssRayContainer &passSamples) const
[527]357{
[570]358        SimpleRayContainer simpleRays;
[1633]359        long startTime = GetTime();
[564]360
[1701]361        // create one third of each type
362        int stype;
363       
[1709]364        const int numStrategies = 3;
365
[1701]366        stype = SamplingStrategy::OBJECT_BASED_DISTRIBUTION;
[1709]367        mPreprocessor->GenerateRays(samplesPerPass / numStrategies, sampleType, simpleRays);
[1701]368       
369        stype = SamplingStrategy::SPATIAL_BOX_BASED_DISTRIBUTION;
[1709]370        mPreprocessor->GenerateRays(samplesPerPass / numStrategies, sampleType, simpleRays);
[1701]371       
[1709]372        if (0)
373        {
374                stype = SamplingStrategy::DIRECTION_BASED_DISTRIBUTION;
375                mPreprocessor->GenerateRays(samplesPerPass / numStrategies, sampleType, simpleRays);
376        }
[1701]377
[1708]378        stype = SamplingStrategy::REVERSE_OBJECT_BASED_DISTRIBUTION;
[1709]379        mPreprocessor->GenerateRays(samplesPerPass / numStrategies, sampleType, simpleRays);
[1708]380
[1633]381        cout << "generated " << samplesPerPass << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[1221]382
[1633]383        startTime = GetTime();
[573]384        // shoot simple ray and add it to importance samples
[1520]385        mPreprocessor->CastRays(simpleRays, passSamples, true);
[1633]386        cout << "cast " <<  samplesPerPass << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[570]387
[574]388        return (int)passSamples.size();
389}
[570]390
[574]391
392/// helper function which destroys rays or copies them into the output ray container
[639]393inline void disposeRays(VssRayContainer &rays, VssRayContainer *outRays)
[574]394{
395        cout << "disposing samples ... ";
[582]396        long startTime = GetTime();
397        int n = (int)rays.size();
398
[573]399        if (outRays)
[542]400        {
[574]401                VssRayContainer::const_iterator it, it_end = rays.end();
402                for (it = rays.begin(); it != it_end; ++ it)
403                {
404                        outRays->push_back(*it);
405                }
[573]406        }
407        else
408        {
[639]409                VssRayContainer::const_iterator it, it_end = rays.end();
410                for (it = rays.begin(); it != it_end; ++ it)
411                {
412                        if (!(*it)->IsActive())
413                                delete (*it);
414                }
[573]415        }
[639]416
[574]417        cout << "finished" << endl;
[582]418        Debug << "disposed " << n << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[573]419}
[570]420
421
[573]422int ViewCellsManager::Construct(Preprocessor *preprocessor, VssRayContainer *outRays)
423{
424        int numSamples = 0;
[1077]425
[573]426        SimpleRayContainer simpleRays;
[574]427        VssRayContainer initialSamples;
[540]428
[1381]429        // store pointer to preprocessor for further use during construction
430        mPreprocessor = preprocessor;
431       
[1563]432
[1381]433        ///////////////////////////////////////////////////////
434        //-- Initial sampling for the construction of the view cell hierarchy.
435        //-- We use uniform sampling / box based sampling.
436       
[752]437        long startTime = GetTime();
[1633]438        cout << "view cell construction: casting " << mInitialSamples << " initial samples ... " << endl;
[1414]439
[1381]440        // cast initial samples
441        CastPassSamples(mInitialSamples, mSamplingType, initialSamples);
[1278]442
[1221]443        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
[574]444
[573]445        // construct view cells
[752]446        ConstructSubdivision(preprocessor->mObjects, initialSamples);
[540]447
[727]448        // initial samples count for overall samples ...
[752]449        numSamples += mInitialSamples;
[542]450
[574]451        // rays can be passed or deleted
[639]452        disposeRays(initialSamples, outRays);
[752]453
454        cout << "time needed for initial construction: "
455                 << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
456
457        Debug << "time needed for initial construction: "
458                  << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
459
[1444]460        // collect view cells and compute statistics
461        ResetViewCells();
[752]462
[1444]463
464        ///////////////////
465        //-- Initial hierarchy construction finished.
[1381]466        //-- We can do some stats and visualization
467       
[1444]468        if (0)
[660]469        {
[1444]470                //-- export initial view cell partition
[1563]471                Debug << "\nView cells after initial sampling:\n" << mCurrentViewCellsStats << endl;
[1416]472
[1414]473                const string filename("viewcells.wrl");
474                Exporter *exporter = Exporter::GetExporter(filename.c_str());
[712]475       
[660]476                if (exporter)
477                {
[1414]478                        cout << "exporting initial view cells (=leaves) to " << filename.c_str() << " ... ";
479
[660]480                        if (mExportGeometry)
[712]481                        {
[660]482                                exporter->ExportGeometry(preprocessor->mObjects);
[712]483                        }
[660]484
[750]485                        exporter->SetWireframe();
[1416]486                        ExportViewCellsForViz(exporter, NULL, GetClipPlane());
[660]487
488                        delete exporter;
[712]489                        cout << "finished" << endl;
[660]490                }
491        }
492
[1381]493
[1419]494        //////////////////////
[1381]495        //-- Cast some more sampling after initial construction.
496        //-- The additional rays can be used to gain
497        //-- some more information before the bottom-up merge
498        //-- note: guided rays could be used for this task
499
[1414]500        // time spent after construction of the initial partition
[1381]501        startTime = GetTime();
[574]502        const int n = mConstructionSamples; //+initialSamples;
[666]503        // should we use directional samples?
[1520]504        bool dirSamples = (mSamplingType == SamplingStrategy::DIRECTION_BASED_DISTRIBUTION);
[573]505
506        while (numSamples < n)
507        {
[596]508                cout << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
[727]509                Debug << "casting " << mSamplesPerPass << " samples of " << n << " ... ";
510
[574]511                VssRayContainer constructionSamples;
512
[694]513                const int samplingType = mSamplingType;
[1444]514                        //dirSamples ? Preprocessor::DIRECTION_BASED_DISTRIBUTION :     Preprocessor::SPATIAL_BOX_BASED_DISTRIBUTION;
[667]515
[720]516                if (0) dirSamples = !dirSamples; // toggle sampling method
[667]517
[727]518                // cast new samples
[574]519                numSamples += CastPassSamples(mSamplesPerPass,
[666]520                                                                          samplingType,
[574]521                                                                          constructionSamples);
522
523                cout << "finished" << endl;
524                cout << "computing sample contribution for " << (int)constructionSamples.size() << " samples ... ";
525
[727]526                // computes sample contribution of cast rays TODO: leak?
527                if (SAMPLE_AFTER_SUBDIVISION)
[605]528                        ComputeSampleContributions(constructionSamples, true, false);
[712]529
[574]530                cout << "finished" << endl;
531
[639]532                disposeRays(constructionSamples, outRays);
[574]533                cout << "total samples: " << numSamples << endl;
[542]534        }
[752]535
[1381]536       
[1563]537        if (0)
538        {
539                ///////////////
540                //-- Get stats after the additional sampling step
541                //-- and before the bottom-up merge step
[570]542
[1563]543                EvaluateViewCellsStats();
544                Debug << "\noriginal view cell partition before post process:\n"
545                          << mCurrentViewCellsStats << endl;
546       
547                mRenderer->RenderScene();
548                SimulationStatistics ss;
549                dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
[660]550
[1563]551                Debug << ss << endl;
552        }
[660]553
[1416]554        ////////////////////
[1381]555        //-- post processing of the initial construction
556        //-- We can bottom-up merge the view cells in this step
[1444]557        //-- We can additionally cast some post processing sample rays.
558        //-- These rays can be used to store the view cells with the rays
[1381]559
560        VssRayContainer postProcessSamples;
561        cout << "casting " << mPostProcessSamples << " post processing samples ... ";
562       
563        CastPassSamples(mPostProcessSamples, mSamplingType, postProcessSamples);
564
565        cout << "finished" << endl;
[574]566        cout << "starting post processing and visualization" << endl;
567
[1444]568        // store view cells with rays for post processing?
[574]569        const bool storeViewCells = true;
[605]570
571        if (SAMPLE_AFTER_SUBDIVISION)
572                ComputeSampleContributions(postProcessSamples, true, storeViewCells);
[663]573
[1381]574        PostProcess(preprocessor->mObjects, postProcessSamples);
[570]575
[1414]576        const float secs = TimeDiff(startTime, GetTime()) * 1e-3f;
577        cout << "post processing (=merge) finished in " << secs << " secs" << endl;
[752]578
[1414]579        Debug << "post processing time: " << secs << endl;
[1002]580        disposeRays(postProcessSamples, outRays);
581
[801]582       
[1416]583        ////////////////
[1381]584        //-- Evaluation of the resulting view cell partition.
585        //-- We cast a number of new samples and measure the render cost
586
[801]587        if (mEvaluateViewCells)
588        {
[1145]589                EvalViewCellPartition();
[801]590        }
[1705]591               
592        // write view cells to disc
593        if (1 && mExportViewCells)
594        {
595                char filename[100];
596                Environment::GetSingleton()->GetStringValue("ViewCells.filename", filename);
597                ExportViewCells(filename, mExportPvs, mPreprocessor->mObjects);
598        }
599
[1416]600        /////////////////
[1381]601        //-- Finally, we do some visualization
602
[666]603        if (mShowVisualization)
604        {
[1633]605                ///////////////
[1381]606                //-- visualization rays, e.g., to show some samples in the scene
[1633]607               
608                VssRayContainer visSamples;
609                int numSamples = CastPassSamples(mVisualizationSamples,
610                                                                                 mSamplingType,
611                                                                                 visSamples);
[574]612
[666]613                if (SAMPLE_AFTER_SUBDIVISION)
[1633]614                        ComputeSampleContributions(visSamples, true, storeViewCells);
[574]615
[1444]616                // various visualizations
[1633]617                Visualize(preprocessor->mObjects, visSamples);
[574]618
[1633]619                disposeRays(visSamples, outRays);
[666]620        }
[574]621
[1444]622        // recalculate view cells
623        EvaluateViewCellsStats();
624
[573]625        return numSamples;
[527]626}
627
[547]628
[1418]629AxisAlignedPlane *ViewCellsManager::GetClipPlane()
[1416]630{
631        return mUseClipPlaneForViz ? &mClipPlaneForViz : NULL;
632}
633
634
[752]635void ViewCellsManager::EvalViewCellHistogram(const string filename,
636                                                                                         const int nViewCells)
[728]637{
638        std::ofstream outstream;
639        outstream.open(filename.c_str());
640
641        ViewCellContainer viewCells;
[735]642        mViewCellsTree->CollectBestViewCellSet(viewCells, nViewCells);
[728]643
644        float maxRenderCost, minRenderCost;
[734]645
646        // sort by render cost
647        sort(viewCells.begin(), viewCells.end(), ViewCell::SmallerRenderCost);
648
649        minRenderCost = viewCells.front()->GetRenderCost();
650        maxRenderCost = viewCells.back()->GetRenderCost();
651
[991]652        Debug << "histogram min rc: " << minRenderCost << " max rc: " << maxRenderCost << endl;
[736]653
[997]654    int histoIntervals;
[1004]655        Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.intervals", histoIntervals);
[997]656        const int intervals = min(histoIntervals, (int)viewCells.size());
[735]657
[997]658        int histoMaxVal;
[1004]659        Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.maxValue", histoMaxVal);
[1145]660        maxRenderCost = max((float)histoMaxVal, maxRenderCost);
[991]661
[997]662       
[728]663        const float range = maxRenderCost - minRenderCost;
[735]664        const float stepSize = range / (float)intervals;
[728]665
[735]666        float currentRenderCost = minRenderCost;//(int)ceil(minRenderCost);
667
668        const float totalRenderCost = mViewCellsTree->GetRoot()->GetRenderCost();
669        const float totalVol = GetViewSpaceBox().GetVolume();
[736]670        //const float totalVol = mViewCellsTree->GetRoot()->GetVolume();
[735]671
[736]672        int j = 0;
[735]673        int i = 0;
674       
[734]675        ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();             
676
[744]677        // count for integral
678        float volSum = 0;
679        int smallerCostSum = 0;
[735]680       
[734]681        // note can skip computations for view cells already evaluated and delete them from vector ...
682    while (1)
683        {
[744]684                // count for histogram value
685                float volDif = 0;
686                int smallerCostDif = 0;
[736]687
[734]688                while ((i < (int)viewCells.size()) && (viewCells[i]->GetRenderCost() < currentRenderCost))
689                {
[744]690                        volSum += viewCells[i]->GetVolume();
691                        volDif += viewCells[i]->GetVolume();
692
[734]693                        ++ i;
[744]694                        ++ smallerCostSum;
695                        ++ smallerCostDif;
[734]696                }
[736]697               
[744]698                if ((i >= (int)viewCells.size()) || (currentRenderCost >= maxRenderCost))
[735]699                        break;
[736]700               
[744]701                const float rcRatio = currentRenderCost / maxRenderCost;
702                const float volRatioSum = volSum / totalVol;
703                const float volRatioDif = volDif / totalVol;
[735]704
[991]705                outstream << "#Pass\n" << j ++ << endl;
[736]706                outstream << "#RenderCostRatio\n" << rcRatio << endl;
707                outstream << "#WeightedCost\n" << currentRenderCost / totalVol << endl;
[744]708                outstream << "#ViewCellsDif\n" << smallerCostDif << endl;
709                outstream << "#ViewCellsSum\n" << smallerCostSum << endl;       
710                outstream << "#VolumeDif\n" << volRatioDif << endl << endl;
711                outstream << "#VolumeSum\n" << volRatioSum << endl << endl;
[735]712
713                // increase current render cost
[734]714                currentRenderCost += stepSize;
715        }
[735]716
[734]717        outstream.close();
718}
719
[735]720
[979]721
722ViewCellsManager *ViewCellsManager::LoadViewCells(const string &filename,
723                                                                                                  ObjectContainer *objects,
[1676]724                                                                                                  bool finalizeViewCells,
[979]725                                                                                                  BoundingBoxConverter *bconverter)
726                                                                                                 
727{
728        ViewCellsParser parser;
729        ViewCellsManager *vm = NULL;
730
[1616]731        const long startTime = GetTime();
732        bool success = parser.ParseViewCellsFile(filename, &vm, objects, bconverter);
733
[1715]734        cout<<"viewcells parsed "<<endl<<flush;
735       
[1616]736        if (success)
[979]737        {
[1621]738                //vm->ResetViewCells();
[1679]739                //hack
740                vm->mViewCells.clear();
741                ViewCellContainer leaves;
742                vm->mViewCellsTree->CollectLeaves(vm->mViewCellsTree->GetRoot(), leaves);
[979]743
[1679]744                ViewCellContainer::const_iterator it, it_end = leaves.end();
[1621]745
[1679]746                for (it = leaves.begin(); it != it_end; ++ it)
747                {
748                        vm->mViewCells.push_back(*it);
749                }
[979]750                vm->mViewCellsFinished = true;
751                vm->mMaxPvsSize = (int)objects->size();
752
753                if (finalizeViewCells)
754                {
[1444]755                        // create the meshes and compute volumes
[979]756                        vm->FinalizeViewCells(true);
[1616]757                        // vm->mViewCellsTree->AssignRandomColors();
[979]758                }
759
760                Debug << (int)vm->mViewCells.size() << " view cells loaded in "
761                          << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
762        }
763        else
764        {
765                Debug << "Error: loading view cells failed!" << endl;
766                DEL_PTR(vm);
767        }
768
769        return vm;
770}
771
772
773bool VspBspViewCellsManager::ExportViewCells(const string filename,
774                                                                                         const bool exportPvs,
775                                                                                         const ObjectContainer &objects)
776{
[1002]777        if (!ViewCellsConstructed() || !ViewCellsTreeConstructed())
[1545]778        {
[997]779                return false;
[1545]780        }
[997]781
[979]782        cout << "exporting view cells to xml ... ";
[1264]783
[1201]784        OUT_STREAM stream(filename.c_str());
[979]785
786        // for output we need unique ids for each view cell
787        CreateUniqueViewCellIds();
788
789        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
790        stream << "<VisibilitySolution>" << endl;
791
[1262]792        if (exportPvs)
793        {
794                //-- export bounding boxes
795                stream << "<BoundingBoxes>" << endl;
[1614]796#if USE_KD_PVS
797        KdIntersectableMap::const_iterator kit, kit_end = GetPreprocessor()->mKdTree->mKdIntersectables.end();
[979]798
[1614]799                int id = 0;
800                for (kit = GetPreprocessor()->mKdTree->mKdIntersectables.begin(); kit != kit_end; ++ kit, ++ id)
801                {
802                        Intersectable *obj = (*kit).second;
803                        const AxisAlignedBox3 box = obj->GetBox();
804               
805                        obj->SetId(id);
806
807                        stream << "<BoundingBox" << " id=\"" << id << "\""
808                                   << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
809                                   << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
810                }
811#else
812        ObjectContainer::const_iterator oit, oit_end = objects.end();
813
[1262]814                for (oit = objects.begin(); oit != oit_end; ++ oit)
815                {
[1563]816                        const AxisAlignedBox3 box = (*oit)->GetBox();
[979]817
[1551]818                        ////////////
[979]819                        //-- the bounding boxes
[1563]820                        stream << "<BoundingBox" << " id=\"" << (*oit)->GetId() << "\""
[979]821                                   << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
822                                   << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
[1262]823                }
[1614]824#endif
[1262]825                stream << "</BoundingBoxes>" << endl;
[1112]826        }
[979]827
[1264]828       
[1551]829        /////////////
[979]830        //-- export the view cells and the pvs
831
832        const int numViewCells = mCurrentViewCellsStats.viewCells;
833        stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
[1551]834
[979]835        mViewCellsTree->Export(stream, exportPvs);
836
837        stream << "</ViewCells>" << endl;
838
839
[1551]840        //////////
[1262]841        //-- export the view space hierarchy
[979]842       
[1262]843        stream << "<ViewSpaceHierarchy type=\"bsp\""
844                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
[1264]845                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\">" << endl;
[1262]846
[979]847        mVspBspTree->Export(stream);
[1286]848        stream << "</ViewSpaceHierarchy>" << endl;
[979]849
850        stream << "</VisibilitySolution>" << endl;
851
852        stream.close();
853        cout << "finished" << endl;
854
855        return true;
856}
857
858
[735]859void ViewCellsManager::EvalViewCellHistogramForPvsSize(const string filename,
860                                                                                                           const int nViewCells)
[734]861{
862        std::ofstream outstream;
863        outstream.open(filename.c_str());
864
865        ViewCellContainer viewCells;
[735]866        mViewCellsTree->CollectBestViewCellSet(viewCells, nViewCells);
[734]867
[1709]868        float maxPvs, maxVal, minVal;
[734]869
[997]870        // sort by pvs size
[735]871        sort(viewCells.begin(), viewCells.end(), ViewCell::SmallerPvs);
872
[1709]873        maxPvs = mViewCellsTree->GetPvsCost(viewCells.back());
[997]874        minVal = 0;
875
[991]876        // hack: normalize pvs size
[997]877        int histoMaxVal;
[1004]878        Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.maxValue", histoMaxVal);
[1709]879        maxVal = max((float)histoMaxVal, maxPvs);
[997]880               
[1121]881        Debug << "histogram minpvssize: " << minVal << " maxpvssize: " << maxVal
882                << " real maxpvs " << maxPvs << endl;
[752]883
[997]884        int histoIntervals;
[1004]885        Environment::GetSingleton()->GetIntValue("Preprocessor.histogram.intervals", histoIntervals);
[997]886        const int intervals = min(histoIntervals, (int)viewCells.size());
[735]887
[1709]888        const float range = maxVal - minVal;
889        int stepSize = (int)(range / intervals);
[735]890
[997]891        // set step size to avoid endless loop
[735]892        if (!stepSize) stepSize = 1;
[979]893       
894        Debug << "stepsize: " << stepSize << endl;
[997]895       
[735]896        const float totalRenderCost = mViewCellsTree->GetRoot()->GetRenderCost();
897        const float totalVol = GetViewSpaceBox().GetVolume();
898
[1709]899        float currentPvs = minVal;
[997]900       
[735]901        int i = 0;
902        int j = 0;
[744]903        float volSum = 0;
904        int smallerSum = 0;
905
[735]906        ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();             
907       
[997]908        for (int j = 0; j < intervals; ++ j)
[728]909        {
[744]910                float volDif = 0;
911                int smallerDif = 0;
[736]912
[997]913                while ((i < (int)viewCells.size()) &&
[1709]914                           (mViewCellsTree->GetPvsCost(viewCells[i]) < currentPvs))
[735]915                {
[744]916                        volDif += viewCells[i]->GetVolume();
917                        volSum += viewCells[i]->GetVolume();
[997]918
[735]919                        ++ i;
[744]920                        ++ smallerDif;
921                        ++ smallerSum;
[735]922                }
[736]923               
[997]924                if (0 && (i < (int)viewCells.size()))
[1709]925                        Debug << "new pvs cost increase: " << mViewCellsTree->GetPvsCost(viewCells[i])
[1121]926                        << " " << currentPvs << endl;
[997]927       
[744]928                const float volRatioDif = volDif / totalVol;
929                const float volRatioSum = volSum / totalVol;
[728]930
[997]931                outstream << "#Pass\n" << j << endl;
932                outstream << "#Pvs\n" << currentPvs << endl;
[744]933                outstream << "#ViewCellsDif\n" << smallerDif << endl;
934                outstream << "#ViewCellsSum\n" << smallerSum << endl;   
935                outstream << "#VolumeDif\n" << volRatioDif << endl << endl;
936                outstream << "#VolumeSum\n" << volRatioSum << endl << endl;
[997]937       
938                //-- increase current pvs size to define next interval
939                currentPvs += stepSize;
[728]940        }
[991]941
[735]942        outstream.close();
[728]943}
944
[735]945
[1002]946bool ViewCellsManager::GetExportPvs() const
947{
948        return mExportPvs;
949}
950
951
[1259]952bool ViewCellsManager::AddSampleToPvs(Intersectable *obj,
953                                                                          const Vector3 &hitPoint,
954                                                                          ViewCell *vc,
955                                                                          const float pdf,
956                                                                          float &contribution) const
957{
958        if (!obj) return false;
959
960        // potentially visible objects
961        return vc->AddPvsSample(obj, pdf, contribution);
962}
963
964
[1580]965void ViewCellsManager::ResetPvs()
966{
967        if (ViewCellsTreeConstructed())
968        {
969                mViewCellsTree->ResetPvs();
970        }
971        else
972        {
973                cout << "view cells tree not constructed" << endl;
974        }
975}
976
977
[1679]978void ViewCellsManager::ExportStats(const string &fileName)
979{
980        mViewCellsTree->ExportStats(fileName);
981}
982
983
[1145]984void ViewCellsManager::EvalViewCellPartition()
[660]985{
986        int samplesPerPass;
987        int numSamples;
988        int castSamples = 0;
[1570]989        char str[64];
[1695]990        int oldSamples = 0;
[660]991
[1695]992        int samplesForStats;
993
[1004]994        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
[1695]995        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesForStats", samplesForStats);
[1004]996        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samples", numSamples);
[660]997
[664]998        char statsPrefix[100];
[1004]999        Environment::GetSingleton()->GetStringValue("ViewCells.Evaluation.statsPrefix", statsPrefix);
[663]1000
[664]1001        Debug << "view cell evaluation samples per pass: " << samplesPerPass << endl;
1002        Debug << "view cell evaluation samples: " << numSamples << endl;
1003        Debug << "view cell stats prefix: " << statsPrefix << endl;
1004
[666]1005        // should directional sampling be used?
[1603]1006        bool dirSamples =
1007                (mEvaluationSamplingType == SamplingStrategy::DIRECTION_BASED_DISTRIBUTION);
[664]1008
[801]1009        cout << "reseting pvs ... ";
1010               
[1145]1011        const bool startFromZero = true;
[801]1012
[666]1013        // reset pvs and start over from zero
1014        if (startFromZero)
1015        {
1016                mViewCellsTree->ResetPvs();
1017        }
[1145]1018        else // start from current sampless
[666]1019        {
[1145]1020                // statistics before casting more samples
[666]1021                cout << "compute new statistics ... ";
[1570]1022                sprintf(str, "-%09d-eval.log", castSamples);
1023                string fName = string(statsPrefix) + string(str);
[666]1024
1025                mViewCellsTree->ExportStats(fName);
1026                cout << "finished" << endl;
1027        }
[1570]1028
[744]1029        cout << "finished" << endl;
[1178]1030    cout << "Evaluating view cell partition ... " << endl;
[744]1031
[660]1032        while (castSamples < numSamples)
[1686]1033        {               
1034                ///////////////
1035                //-- we have to use uniform sampling strategy for construction rays
1036
[664]1037                VssRayContainer evaluationSamples;
[1686]1038                const int samplingType = mEvaluationSamplingType;
[663]1039
[1004]1040                long startTime = GetTime();
1041
1042                cout << "casting " << samplesPerPass << " samples ... ";
1043                Debug << "casting " << samplesPerPass << " samples ... ";
1044
[664]1045                CastPassSamples(samplesPerPass, samplingType, evaluationSamples);
1046               
1047                castSamples += samplesPerPass;
1048
[1004]1049                Real timeDiff = TimeDiff(startTime, GetTime());
[1695]1050               
1051                cout << "finished in " << timeDiff * 1e-3f << " secs" << endl;
[1004]1052                cout << "computing sample contributions of " << (int)evaluationSamples.size()  << " samples ... ";
[1695]1053               
1054                Debug << "finished in " << timeDiff * 1e-3f << " secs" << endl;
[1004]1055                Debug << "computing sample contributions of " << (int)evaluationSamples.size()  << " samples ... ";
1056
1057                startTime = GetTime();
1058
[664]1059                ComputeSampleContributions(evaluationSamples, true, false);
1060
[1004]1061                timeDiff = TimeDiff(startTime, GetTime());
1062                cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
1063                Debug << "finished in " << timeDiff * 1e-3 << " secs" << endl;
[664]1064
[1695]1065                if ((castSamples >= samplesForStats + oldSamples) || (castSamples >= numSamples))
1066                {
1067                        oldSamples += samplesForStats;
[1686]1068
[1695]1069                        ///////////
1070                        //-- output stats
[1686]1071
[1695]1072                        sprintf(str, "-%09d-eval.log", castSamples);
1073                        string fileName = string(statsPrefix) + string(str);
[1686]1074
[1695]1075                        ///////////////
1076                        //-- propagate pvs or pvs size information
[1586]1077
[1695]1078                        startTime = GetTime();
1079                        ObjectPvs pvs;
[664]1080
[1709]1081                        cout << "updating pvs for evaluation ... " << endl;
[664]1082
[1695]1083                        UpdatePvsForEvaluation(mViewCellsTree->GetRoot(), pvs);
1084
1085                        timeDiff = TimeDiff(startTime, GetTime());
1086                        cout << "finished updating the pvs in " << timeDiff * 1e-3 << " secs" << endl;
1087                        Debug << "pvs evaluated in " << timeDiff * 1e-3 << " secs" << endl;
1088               
1089                        startTime = GetTime();
1090                        cout << "compute new statistics ... " << endl;
1091
1092                        ExportStats(fileName);
1093
1094                        timeDiff = TimeDiff(startTime, GetTime());
1095                        cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
1096                        Debug << "statistis computed in " << timeDiff * 1e-3 << " secs" << endl;
1097                }
1098
[664]1099                disposeRays(evaluationSamples, NULL);
[660]1100        }
[728]1101       
[997]1102
[1570]1103        ////////////
[997]1104        //-- histogram
1105
[1695]1106        const int numLeaves = mViewCellsTree->GetNumInitialViewCells(mViewCellsTree->GetRoot());
[735]1107        bool useHisto;
[997]1108        int histoStepSize;
[693]1109
[1004]1110        Environment::GetSingleton()->GetBoolValue("ViewCells.Evaluation.histogram", useHisto);
1111        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.histoStepSize", histoStepSize);
[728]1112
[735]1113        if (useHisto)
[734]1114        {
[735]1115                // evaluate view cells in a histogram           
1116                char s[64];
1117
[997]1118                for (int pass = histoStepSize; pass <= numLeaves; pass += histoStepSize)
[744]1119                {
[997]1120                        string filename;
[744]1121
[997]1122                        cout << "computing histogram for " << pass << " view cells" << endl;
1123#if 0
[744]1124                        //-- evaluate histogram for render cost
1125                        sprintf(s, "-%09d-histo.log", pass);
[997]1126                        filename = string(statsPrefix) + string(s);
[744]1127
1128                        EvalViewCellHistogram(filename, pass);
1129
[997]1130#endif
[744]1131                        //////////////////////////////////////////
[752]1132            //-- evaluate histogram for pvs size
[744]1133
1134                        cout << "computing pvs histogram for " << pass << " view cells" << endl;
1135
1136                        sprintf(s, "-%09d-histo-pvs.log", pass);
1137                        filename = string(statsPrefix) + string(s);
1138
1139                        EvalViewCellHistogramForPvsSize(filename, pass);
1140                }
[734]1141        }
[660]1142}
1143
[704]1144
1145inline float EvalMergeCost(ViewCell *root, ViewCell *candidate)
[703]1146{
[704]1147        return root->GetPvs().GetPvsHomogenity(candidate->GetPvs());
1148}
[660]1149
[703]1150
[1145]1151/// Returns index of the best view cells of the neighborhood
[1707]1152static int GetBestViewCellIdx(ViewCell *root, const ViewCellContainer &neighborhood)
[704]1153{
[705]1154        int bestViewCellIdx = 0;
[703]1155
[704]1156        float mergeCost = Limits::Infinity;
1157        int i = 0;
[703]1158
[734]1159        ViewCellContainer::const_iterator vit, vit_end = neighborhood.end();
[703]1160
[734]1161        for (vit = neighborhood.begin(); vit != vit_end; ++ vit, ++ i)
[703]1162        {
[734]1163                const float mc = EvalMergeCost(root, *vit);
[705]1164               
1165                if (mc < mergeCost)
[704]1166                {
1167                        mergeCost = mc;
1168                        bestViewCellIdx = i;
[703]1169                }
[704]1170        }
[703]1171
[704]1172        return bestViewCellIdx;
1173}
[703]1174
1175
[728]1176void ViewCellsManager::SetMaxFilterSize(const int size)
1177{
1178        mMaxFilterSize = size;
1179}
1180
1181
[1703]1182float ViewCellsManager::EvalRenderCost(Intersectable *obj) //const
[728]1183{
[1703]1184        switch (sRenderCostEvaluationType)
[728]1185        {
1186        case PER_OBJECT:
[752]1187                return 1.0f;
[728]1188       
1189        case PER_TRIANGLE:
[1703]1190                {
[1701]1191                        return (float)obj->NumberOfFaces();
[728]1192                }
1193        default:
[752]1194                cout << "default" << endl;
1195                return 1.0f;
[728]1196        }
1197
1198        // should not come here
[752]1199        return 0.0f;
[728]1200}
1201
1202
[704]1203ViewCell *ViewCellsManager::ConstructLocalMergeTree(ViewCell *currentViewCell,
1204                                                                                                        const ViewCellContainer &viewCells)
1205{
1206        ViewCell *root = currentViewCell;
1207        ViewCellContainer neighborhood = viewCells;
[703]1208
[704]1209        ViewCellContainer::const_iterator it, it_end = neighborhood.end();
[703]1210
[704]1211        const int n = min(mMaxFilterSize, (int)neighborhood.size());
[1545]1212       
1213        /////////////////
[704]1214        //-- use priority queue to merge leaf pairs
[1545]1215       
[704]1216        for (int nMergedViewCells = 0; nMergedViewCells < n; ++ nMergedViewCells)
[703]1217        {
[704]1218                const int bestViewCellIdx = GetBestViewCellIdx(root, neighborhood);
[703]1219               
[704]1220                ViewCell *bestViewCell = neighborhood[bestViewCellIdx];
[706]1221       
[704]1222                // remove from vector
1223                swap(neighborhood[bestViewCellIdx], neighborhood.back());
1224                neighborhood.pop_back();
[705]1225       
[704]1226                if (!bestViewCell || !root)
[1545]1227            cout << "warning!!" << endl;
[705]1228               
[704]1229                // create new root of the hierarchy
1230                root = MergeViewCells(root, bestViewCell);
[703]1231        }
1232
[704]1233        return root;   
[703]1234}
1235
[704]1236
[713]1237struct SortableViewCellEntry {
1238
[1174]1239        SortableViewCellEntry() {}
1240        SortableViewCellEntry(const float v, ViewCell *cell):mValue(v), mViewCell(cell) {}
[713]1241
[1174]1242        float mValue;
1243        ViewCell *mViewCell;
1244
1245        friend bool operator<(const SortableViewCellEntry &a, const SortableViewCellEntry &b) {
1246                return a.mValue < b.mValue;
1247        }
[713]1248};
1249
[1174]1250
1251ViewCell * ViewCellsManager::ConstructLocalMergeTree2(ViewCell *currentViewCell,
1252                                                                                                          const ViewCellContainer &viewCells)
[713]1253{
1254 
1255  vector<SortableViewCellEntry> neighborhood(viewCells.size());
1256  int i, j;
1257  for (i = 0, j = 0; i < viewCells.size(); i++) {
1258        if (viewCells[i] != currentViewCell)
1259          neighborhood[j++] = SortableViewCellEntry(
1260                                                                                                EvalMergeCost(currentViewCell, viewCells[i]),
1261                                                                                                viewCells[i]);
1262  }
1263  neighborhood.resize(j);
1264 
1265  sort(neighborhood.begin(), neighborhood.end());
1266 
1267  ViewCell *root = currentViewCell;
1268 
1269  vector<SortableViewCellEntry>::const_iterator it, it_end = neighborhood.end();
1270 
1271  const int n = min(mMaxFilterSize, (int)neighborhood.size());
1272  //-- use priority queue to merge leaf pairs
1273 
1274  //cout << "neighborhood: " << neighborhood.size() << endl;
1275  for (int nMergedViewCells = 0; nMergedViewCells < n; ++ nMergedViewCells)
[728]1276  {
[713]1277          ViewCell *bestViewCell = neighborhood[nMergedViewCells].mViewCell;
1278          //cout <<nMergedViewCells<<":"<<"homogenity=" <<neighborhood[nMergedViewCells].mValue<<endl;
1279          // create new root of the hierarchy
1280          root = MergeViewCells(root, bestViewCell);
1281          // set negative cost so that this view cell gets deleted
1282          root->SetMergeCost(-1.0f);
[728]1283  }
[713]1284 
1285  return root; 
1286}
1287
1288void
1289ViewCellsManager::DeleteLocalMergeTree(ViewCell *vc
1290                                                                           ) const
1291{
[1586]1292        if (!vc->IsLeaf() && vc->GetMergeCost() < 0.0f)
1293        {       
1294                ViewCellInterior *vci = (ViewCellInterior *) vc;
1295                ViewCellContainer::const_iterator it, it_end = vci->mChildren.end();
1296
1297        for (it = vci->mChildren.begin(); it != it_end; ++ it)
1298                        DeleteLocalMergeTree(*it);
1299               
1300                vci->mChildren.clear();
1301               
1302                delete vci;
[713]1303  }
1304}
1305
[1021]1306
[564]1307bool ViewCellsManager::CheckValidity(ViewCell *vc,
1308                                                                         int minPvsSize,
[562]1309                                                                         int maxPvsSize) const
[547]1310{
[569]1311
[1707]1312        if ((vc->GetPvs().EvalPvsCost() > maxPvsSize) ||
1313                (vc->GetPvs().EvalPvsCost() < minPvsSize))
[564]1314        {
[710]1315                return false;
[561]1316        }
[570]1317
[710]1318        return true;
[547]1319}
1320
1321
[710]1322int ViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
1323                                                                                          ViewCellContainer &viewCells) const
1324{
1325        return 0;
1326};
1327
[1021]1328
[697]1329AxisAlignedBox3 ViewCellsManager::GetFilterBBox(const Vector3 &viewPoint,
1330                                                                                                const float width) const
1331{
[746]1332  float w = Magnitude(mViewSpaceBox.Size())*width;
1333  Vector3 min = viewPoint - w * 0.5f;
1334  Vector3 max = viewPoint + w * 0.5f;
1335 
1336  return AxisAlignedBox3(min, max);
[697]1337}
1338
1339
[904]1340void ViewCellsManager::GetPrVS(const Vector3 &viewPoint,
1341                                                           PrVs &prvs,
1342                                                           const float filterWidth)
[697]1343{
[1594]1344  ViewCell *currentViewCell = GetViewCell(viewPoint);
[1112]1345
[1594]1346  if (mMaxFilterSize < 1) {
1347        prvs.mViewCell = currentViewCell;
1348        return;
1349  }
1350 
1351  const AxisAlignedBox3 box = GetFilterBBox(viewPoint, filterWidth);
1352 
1353  if (currentViewCell)
[1545]1354        {
[1594]1355          ViewCellContainer viewCells;
1356          ComputeBoxIntersections(box, viewCells);
1357         
1358          ViewCell *root = ConstructLocalMergeTree2(currentViewCell, viewCells);
1359          prvs.mViewCell = root;
1360         
[1545]1361        }
[1594]1362  else
[1545]1363        {
[1594]1364          prvs.mViewCell = NULL;
1365          //prvs.mPvs = root->GetPvs();
[1545]1366        }
[697]1367}
1368
1369
[581]1370bool ViewCellsManager::ViewCellsTreeConstructed() const
1371{
[1002]1372    return (mViewCellsTree && mViewCellsTree->GetRoot());
[581]1373}
1374
1375
[564]1376void ViewCellsManager::SetValidity(ViewCell *vc,
1377                                                                   int minPvs,
[562]1378                                                                   int maxPvs) const
1379{
1380        vc->SetValid(CheckValidity(vc, minPvs, maxPvs));
1381}
1382
[577]1383
[569]1384void
1385ViewCellsManager::SetValidity(
[570]1386                                                          int minPvsSize,
[569]1387                                                          int maxPvsSize) const
1388{
[991]1389        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[570]1390
[991]1391
1392        for (it = mViewCells.begin(); it != it_end; ++ it)
1393        {
1394                SetValidity(*it, minPvsSize, maxPvsSize);
1395        }
[569]1396}
[562]1397
[569]1398void
1399ViewCellsManager::SetValidityPercentage(
1400                                                                                const float minValid,
1401                                                                                const float maxValid
1402                                                                                )
1403{
[997]1404        sort(mViewCells.begin(), mViewCells.end(), ViewCell::SmallerPvs);
[570]1405
[1151]1406        int start = (int)(mViewCells.size() * minValid);
1407        int end = (int)(mViewCells.size() * maxValid);
[570]1408
[1151]1409        for (int i = 0; i < (int)mViewCells.size(); ++ i)
[997]1410        {
1411                mViewCells[i]->SetValid(i >= start && i <= end);
1412        }
[569]1413}
1414
[1148]1415
[991]1416int ViewCellsManager::CountValidViewcells() const
[569]1417{
[991]1418        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1419        int valid = 0;
1420
1421        for (it = mViewCells.begin(); it != it_end; ++ it)
1422        {       
1423                if ((*it)->GetValid())
1424                        ++ valid;
1425        }
1426
1427        return valid;
[569]1428}
1429
[577]1430
[1545]1431bool ViewCellsManager::LoadViewCellsGeometry(const string filename,
1432                                                                                         const bool extrudeBaseTriangles)
[440]1433{
[1545]1434        /// we use predefined view cells from now on
1435        mUsePredefinedViewCells = true;
[440]1436        X3dParser parser;
[1545]1437       
1438        if (extrudeBaseTriangles)
1439        {
1440                Environment::GetSingleton()->GetFloatValue("ViewCells.height", parser.mViewCellHeight);
[1563]1441                const bool success = parser.ParseFile(filename, *this);
1442
1443                if (!success)
1444                        return false;
[1545]1445        }
1446        else
1447        {
1448                // hack: use standard mesh loading
1449                // create temporary scene graph for loading the view cells geometry
[1563]1450                // note: delete the meshes as they are created two times for transformed mesh instances.
[1545]1451                SceneGraphNode *root = new SceneGraphNode();
[1563]1452                const bool success = parser.ParseFile(filename, root, true);
1453               
1454                if (!success)
[1545]1455                {
[1563]1456                        DEL_PTR(root);
1457                        return false;
1458                }
1459
1460                ObjectContainer::const_iterator oit, oit_end = root->mGeometry.end();
1461               
1462                for (oit = root->mGeometry.begin(); oit != oit_end; ++ oit)
1463                {
1464                        Mesh *mesh;
1465                        if ((*oit)->Type() == Intersectable::TRANSFORMED_MESH_INSTANCE)
[1545]1466                        {
[1563]1467                                TransformedMeshInstance *mit = dynamic_cast<TransformedMeshInstance *>(*oit);
1468                                mesh = MeshManager::GetSingleton()->CreateResource();
1469                                mit->GetTransformedMesh(*mesh);
[1545]1470                        }
[1563]1471                        else if ((*oit)->Type() == Intersectable::MESH_INSTANCE)
1472                        {
1473                                MeshInstance *mit = dynamic_cast<MeshInstance *>(*oit);
1474                                mesh = mit->GetMesh();
1475                        }
1476                        mesh->ComputeBoundingBox();
1477                        mViewCells.push_back(GenerateViewCell(mesh));
[1545]1478                }
[1563]1479
[1545]1480                DEL_PTR(root);
1481        }
[503]1482
[1563]1483        // set view space box to bounding box of the view cells
1484        AxisAlignedBox3 bbox;
1485        bbox.Initialize();
1486        ViewCellContainer::iterator it = mViewCells.begin(), it_end = mViewCells.end();
1487
1488        for (; it != it_end; ++ it)
[1545]1489        {
[1563]1490                bbox.Include((*it)->GetMesh()->mBox);
[1545]1491        }
[503]1492
[1563]1493        SetViewSpaceBox(bbox);
1494        cout << "view space box: " << bbox << endl;
1495        cout << "generated " << (int)mViewCells.size() << " view cells using the geometry " << filename << endl;
1496
1497        return true;
[440]1498}
1499
[485]1500
[487]1501bool ViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
1502{
[542]1503        viewPoint = mViewSpaceBox.GetRandomPoint();
[487]1504        return true;
1505}
1506
1507
[557]1508float ViewCellsManager::GetViewSpaceVolume()
1509{
[610]1510        return mViewSpaceBox.GetVolume() * (2.0f * sqr((float)M_PI));
[557]1511}
1512
1513
[490]1514bool ViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
1515{
[1444]1516        if (!ViewCellsConstructed())
1517        {
1518                return mViewSpaceBox.IsInside(viewPoint);
1519        }
1520        else
1521        {
1522                if (!mViewSpaceBox.IsInside(viewPoint))
1523                        return false;
[837]1524
[1444]1525                ViewCell *viewcell = GetViewCell(viewPoint);
1526
1527                if (!viewcell || !viewcell->GetValid())
1528                        return false;
1529        }
1530
1531        return true;
[490]1532}
1533
[501]1534
[1444]1535float ViewCellsManager::ComputeSampleContributions(const VssRayContainer &rays,
1536                                                                                                   const bool addRays,                                                                 
1537                                                                                                   const bool storeViewCells)
[440]1538{
[1444]1539        // view cells not yet constructed
1540        if (!ViewCellsConstructed())
1541                return 0.0f;
1542       
1543        float sum = 0.0f;
1544        VssRayContainer::const_iterator it, it_end = rays.end();
1545       
1546        for (it = rays.begin(); it != it_end; ++ it)
1547        {
1548                sum += ComputeSampleContribution(*(*it), addRays, storeViewCells);
1549        }
[503]1550
[1444]1551        return sum;
[440]1552}
1553
[485]1554
[479]1555void ViewCellsManager::EvaluateViewCellsStats()
1556{
[660]1557        mCurrentViewCellsStats.Reset();
[479]1558        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1559
1560        for (it = mViewCells.begin(); it != it_end; ++ it)
[487]1561        {
[660]1562                mViewCellsTree->UpdateViewCellsStats(*it, mCurrentViewCellsStats);
[487]1563        }
[479]1564}
1565
[485]1566
[580]1567void ViewCellsManager::EvaluateRenderStatistics(float &totalRenderCost,
[579]1568                                                                                                float &expectedRenderCost,
[580]1569                                                                                                float &deviation,
1570                                                                                                float &variance,
[1709]1571                                                                                                float &totalCost,
[580]1572                                                                                                float &avgRenderCost)
[579]1573{
[1444]1574        ////////////
1575        //-- compute expected value
[579]1576
1577        totalRenderCost = 0;
[1709]1578        totalCost = 0;
[579]1579
[1444]1580        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
1581
[579]1582        for (it = mViewCells.begin(); it != it_end; ++ it)
1583        {
1584                ViewCell *vc = *it;
[1707]1585                totalRenderCost += vc->GetPvs().EvalPvsCost() * vc->GetVolume();
[1709]1586                totalCost += (int)vc->GetPvs().EvalPvsCost();
[579]1587        }
1588
[580]1589        // normalize with view space box
1590        totalRenderCost /= mViewSpaceBox.GetVolume();
[579]1591        expectedRenderCost = totalRenderCost / (float)mViewCells.size();
[1709]1592        avgRenderCost = totalCost / (float)mViewCells.size();
[579]1593
1594
[1444]1595        ///////////
[580]1596        //-- compute standard defiation
[1444]1597
[579]1598        variance = 0;
[580]1599        deviation = 0;
[579]1600
1601        for (it = mViewCells.begin(); it != it_end; ++ it)
1602        {
1603                ViewCell *vc = *it;
1604
[1707]1605                float renderCost = vc->GetPvs().EvalPvsCost() * vc->GetVolume();
[580]1606                float dev;
[579]1607
[580]1608                if (1)
[1707]1609                        dev = fabs(avgRenderCost - (float)vc->GetPvs().EvalPvsCost());
[580]1610                else
1611                        dev = fabs(expectedRenderCost - renderCost);
[579]1612
[580]1613                deviation += dev;
1614                variance += dev * dev;
[579]1615        }
[580]1616
[579]1617        variance /= (float)mViewCells.size();
[580]1618        deviation /= (float)mViewCells.size();
[579]1619}
1620
1621
[478]1622float ViewCellsManager::GetArea(ViewCell *viewCell) const
1623{
1624        return viewCell->GetArea();
1625}
1626
1627
1628float ViewCellsManager::GetVolume(ViewCell *viewCell) const
1629{
1630        return viewCell->GetVolume();
1631}
1632
[485]1633
[503]1634ViewCell *ViewCellsManager::ExtrudeViewCell(const Triangle3 &baseTri,
[440]1635                                                                                        const float height) const
1636{
1637        // one mesh per view cell
[1001]1638        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
[503]1639
[1545]1640        ////////////
[440]1641        //-- construct prism
1642
[503]1643        // bottom
[440]1644        mesh->mFaces.push_back(new Face(2,1,0));
1645        // top
1646    mesh->mFaces.push_back(new Face(3,4,5));
1647        // sides
1648        mesh->mFaces.push_back(new Face(1, 4, 3, 0));
1649        mesh->mFaces.push_back(new Face(2, 5, 4, 1));
1650        mesh->mFaces.push_back(new Face(3, 5, 2, 0));
1651
[1545]1652
1653        /////////////
1654        //-- extrude new vertices for top of prism
1655
[1586]1656        const Vector3 triNorm = baseTri.GetNormal();
[503]1657        Triangle3 topTri;
[440]1658
1659        // add base vertices and calculate top vertices
1660        for (int i = 0; i < 3; ++ i)
[1545]1661        {
[440]1662                mesh->mVertices.push_back(baseTri.mVertices[i]);
[1545]1663        }
[503]1664
1665        // add top vertices
[440]1666        for (int i = 0; i < 3; ++ i)
[1545]1667        {
[440]1668                mesh->mVertices.push_back(baseTri.mVertices[i] + height * triNorm);
[1545]1669        }
[503]1670
[1545]1671        // do we have to preprocess this mesh (we don't want to trace view cells!)?
1672        mesh->ComputeBoundingBox();
1673       
[440]1674        return GenerateViewCell(mesh);
1675}
1676
[485]1677
[551]1678void ViewCellsManager::FinalizeViewCells(const bool createMesh)
1679{
1680        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[693]1681
1682        // volume and area of the view cells are recomputed and a view cell mesh is created
[551]1683        for (it = mViewCells.begin(); it != it_end; ++ it)
1684        {
1685                Finalize(*it, createMesh);
1686        }
[555]1687
[1584]1688        mViewCellsTree->AssignRandomColors();
1689
[555]1690        mTotalAreaValid = false;
[551]1691}
1692
1693
1694void ViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
1695{
1696        // implemented in subclasses
1697}
1698
[1001]1699
[1168]1700/** fast way of merging 2 view cells.
1701*/
[582]1702ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCell *left, ViewCell *right) const
[440]1703{
[580]1704        // generate parent view cell
[752]1705        ViewCellInterior *vc = new ViewCellInterior();
[710]1706
[752]1707        vc->GetPvs().Clear();
[1740]1708        ObjectPvs::Merge(vc->GetPvs(), left->GetPvs(), right->GetPvs());
[752]1709
[710]1710        // set only links to child (not from child to parent, maybe not wished!!)
1711        vc->mChildren.push_back(left);
1712        vc->mChildren.push_back(right);
1713
[752]1714        // update pvs size
[1707]1715        UpdateScalarPvsSize(vc, vc->GetPvs().EvalPvsCost(), vc->GetPvs().GetSize());
[752]1716
[440]1717        return vc;
1718}
1719
[485]1720
[582]1721ViewCellInterior *ViewCellsManager::MergeViewCells(ViewCellContainer &children) const
1722{
[752]1723        ViewCellInterior *vc = new ViewCellInterior();
[582]1724        ViewCellContainer::const_iterator it, it_end = children.end();
1725
1726        for (it = children.begin(); it != it_end; ++ it)
1727        {
[1740]1728                vc->GetPvs().MergeInPlace((*it)->GetPvs());
1729       
[710]1730                vc->mChildren.push_back(*it);
[582]1731        }
1732
1733        return vc;
1734}
1735
1736
[480]1737void ViewCellsManager::SetRenderer(Renderer *renderer)
1738{
1739        mRenderer = renderer;
1740}
[441]1741
[485]1742
[580]1743ViewCellsTree *ViewCellsManager::GetViewCellsTree()
[440]1744{
[580]1745        return mViewCellsTree;
[440]1746}
1747
1748
1749void ViewCellsManager::SetVisualizationSamples(const int visSamples)
1750{
[444]1751        mVisualizationSamples = visSamples;
[440]1752}
1753
[485]1754
[440]1755void ViewCellsManager::SetConstructionSamples(const int constructionSamples)
1756{
1757        mConstructionSamples = constructionSamples;
1758}
1759
[485]1760
[574]1761void ViewCellsManager::SetInitialSamples(const int initialSamples)
1762{
1763        mInitialSamples = initialSamples;
1764}
1765
1766
[440]1767void ViewCellsManager::SetPostProcessSamples(const int postProcessSamples)
1768{
1769        mPostProcessSamples = postProcessSamples;
1770}
1771
[485]1772
[440]1773int ViewCellsManager::GetVisualizationSamples() const
1774{
1775        return mVisualizationSamples;
1776}
1777
[485]1778
[440]1779int ViewCellsManager::GetConstructionSamples() const
1780{
1781        return mConstructionSamples;
1782}
1783
[485]1784
[440]1785int ViewCellsManager::GetPostProcessSamples() const
1786{
1787        return mPostProcessSamples;
1788}
1789
[485]1790
[719]1791void ViewCellsManager::UpdatePvs()
1792{
[1737]1793  if (mViewCellPvsIsUpdated || !ViewCellsTreeConstructed())
1794        return;
1795 
1796  mViewCellPvsIsUpdated = true;
1797 
1798  ViewCellContainer leaves;
1799  mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
1800 
1801  ViewCellContainer::const_iterator it, it_end = leaves.end();
1802 
1803  for (it = leaves.begin(); it != it_end; ++ it)
[719]1804        {
[1737]1805          mViewCellsTree->PropagatePvs(*it);
[719]1806        }
1807}
1808
1809
[485]1810void ViewCellsManager::GetPvsStatistics(PvsStatistics &stat)
[467]1811{
[1737]1812  // update pvs of view cells tree if necessary
1813  UpdatePvs();
1814 
1815  ViewCellContainer::const_iterator it = mViewCells.begin();
1816 
1817  stat.viewcells = 0;
1818  stat.minPvs = 100000000;
1819  stat.maxPvs = 0;
1820  stat.avgPvs = 0.0f;
1821  stat.avgFilteredPvs = 0.0f;
1822  stat.avgFilterContribution = 0.0f;
1823 
1824  for (; it != mViewCells.end(); ++ it)
[719]1825        {
[1737]1826          ViewCell *viewcell = *it;
1827         
1828          const float pvsCost = mViewCellsTree->GetPvsCost(viewcell);
1829         
1830          if (pvsCost < stat.minPvs)
1831                stat.minPvs = pvsCost;
1832          if (pvsCost > stat.maxPvs)
1833                stat.maxPvs = pvsCost;
1834         
1835          stat.avgPvs += pvsCost;
[1121]1836
[1737]1837          if (0) {
1838                ObjectPvs filteredPvs = viewcell->GetPvs();
1839                ApplyFilter2(viewcell, false, 1.0f, filteredPvs);
1840                float filteredCost = filteredPvs.EvalPvsCost();
1841                stat.avgFilteredPvs += filteredCost;
1842                stat.avgFilterContribution += filteredCost - pvsCost;
1843          }
1844         
1845          ++ stat.viewcells;
[719]1846        }
[1737]1847 
1848  if (stat.viewcells) {
1849        stat.avgPvs/=stat.viewcells;
1850        stat.avgFilteredPvs/=stat.viewcells;
1851        stat.avgFilterContribution/=stat.viewcells;
1852  }
[467]1853}
1854
[485]1855
[480]1856void ViewCellsManager::PrintPvsStatistics(ostream &s)
[467]1857{
1858  s<<"############# Viewcell PVS STAT ##################\n";
1859  PvsStatistics pvsStat;
1860  GetPvsStatistics(pvsStat);
1861  s<<"#AVG_PVS\n"<<pvsStat.avgPvs<<endl;
[1737]1862  s<<"#AVG_FILTERED_PVS\n"<<pvsStat.avgFilteredPvs<<endl;
1863  s<<"#AVG_FILTER_CONTRIBUTION\n"<<pvsStat.avgFilterContribution<<endl;
[467]1864  s<<"#MAX_PVS\n"<<pvsStat.maxPvs<<endl;
1865  s<<"#MIN_PVS\n"<<pvsStat.minPvs<<endl;
1866}
1867
[485]1868
[532]1869int ViewCellsManager::CastBeam(Beam &beam)
1870{
1871        return 0;
1872}
1873
[547]1874
[468]1875ViewCellContainer &ViewCellsManager::GetViewCells()
1876{
1877        return mViewCells;
1878}
1879
[485]1880
[487]1881void ViewCellsManager::SetViewSpaceBox(const AxisAlignedBox3 &box)
1882{
[542]1883        mViewSpaceBox = box;
[1074]1884       
[1027]1885        // hack: create clip plane relative to new view space box
[660]1886        CreateClipPlane();
[1027]1887        // the total area of the view space has changed
[577]1888        mTotalAreaValid = false;
[487]1889}
1890
1891
[660]1892void ViewCellsManager::CreateClipPlane()
[591]1893{
1894        int axis = 0;
[667]1895        float pos;
[1418]1896        bool orientation;
1897        Vector3 absPos;
[591]1898
[1004]1899        Environment::GetSingleton()->GetFloatValue("ViewCells.Visualization.clipPlanePos", pos);
[1416]1900        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.clipPlaneAxis", axis);
[591]1901
[1418]1902        if (axis < 0)
1903        {
1904                axis = -axis;
1905                orientation = false;
1906                absPos = mViewSpaceBox.Max() -  mViewSpaceBox.Size() * pos;
1907        }
1908        else
1909        {
1910                orientation = true;
1911                absPos = mViewSpaceBox.Min() +  mViewSpaceBox.Size() * pos;
1912        }
1913
[1416]1914        mClipPlaneForViz = AxisAlignedPlane(axis, absPos[axis]);
[1418]1915        mClipPlaneForViz.mOrientation = orientation;
[591]1916}
1917
1918
[519]1919AxisAlignedBox3 ViewCellsManager::GetViewSpaceBox() const
1920{
[542]1921        return mViewSpaceBox;
[519]1922}
1923
1924
[480]1925void ViewCellsManager::ResetViewCells()
1926{
[720]1927        // recollect view cells
[480]1928        mViewCells.clear();
1929        CollectViewCells();
[590]1930       
[720]1931        // stats are computed once more
[480]1932        EvaluateViewCellsStats();
[590]1933
[520]1934        // has to be recomputed
[480]1935        mTotalAreaValid = false;
1936}
1937
[485]1938
[547]1939int ViewCellsManager::GetMaxPvsSize() const
1940{
1941        return mMaxPvsSize;
1942}
1943
[590]1944
[563]1945void
1946ViewCellsManager::AddSampleContributions(const VssRayContainer &rays)
1947{
1948  if (!ViewCellsConstructed())
1949        return;
[564]1950
[563]1951  VssRayContainer::const_iterator it, it_end = rays.end();
[564]1952
[563]1953  for (it = rays.begin(); it != it_end; ++ it) {
1954        AddSampleContributions(*(*it));
1955  }
1956}
[547]1957
[581]1958
[562]1959int ViewCellsManager::GetMinPvsSize() const
1960{
1961        return mMinPvsSize;
1962}
1963
1964
1965
[561]1966float ViewCellsManager::GetMaxPvsRatio() const
1967{
1968        return mMaxPvsRatio;
1969}
1970
1971
[563]1972void
1973ViewCellsManager::AddSampleContributions(VssRay &ray)
[468]1974{
[563]1975  // assumes viewcells have been stored...
1976  ViewCellContainer *viewcells = &ray.mViewCells;
1977  ViewCellContainer::const_iterator it;
[1594]1978
1979  if (!ray.mTerminationObject)
1980        return;
1981 
1982#if USE_KD_PVS
1983  float area = GetPreprocessor()->mKdTree->GetBox().SurfaceArea()*KD_PVS_AREA;
1984  KdNode *node = GetPreprocessor()->mKdTree->GetNode(ray.mTermination, area);
1985  Intersectable *obj =
1986        GetPreprocessor()->mKdTree->
1987        GetOrCreateKdIntersectable(node);
1988#else
1989  Intersectable *obj = ray.mTerminationObject;
1990#endif
1991 
[563]1992  for (it = viewcells->begin(); it != viewcells->end(); ++it) {
1993        ViewCell *viewcell = *it;
[569]1994        if (viewcell->GetValid()) {
1995          // if ray not outside of view space
[1594]1996          viewcell->GetPvs().AddSample(obj, ray.mPdf);
[569]1997        }
[563]1998  }
1999}
[503]2000
[574]2001
[1159]2002float ViewCellsManager::ComputeSampleContribution(VssRay &ray,
2003                                                                                                  const bool addRays,
2004                                                                                                  const bool storeViewCells)
[563]2005{
[570]2006        ViewCellContainer viewcells;
[564]2007
[570]2008        ray.mPvsContribution = 0;
2009        ray.mRelativePvsContribution = 0.0f;
[485]2010
[570]2011        static Ray hray;
[564]2012        hray.Init(ray);
2013        //hray.mFlags |= Ray::CULL_BACKFACES;
2014        //Ray hray(ray);
2015
2016        float tmin = 0, tmax = 1.0;
2017
2018        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
[565]2019                return 0;
[564]2020
2021        Vector3 origin = hray.Extrap(tmin);
2022        Vector3 termination = hray.Extrap(tmax);
2023
[1291]2024        ViewCell::NewMail();
2025
[1006]2026        // traverse the view space subdivision
[564]2027        CastLineSegment(origin, termination, viewcells);
[664]2028
[574]2029        if (storeViewCells)
[1155]2030        {       // copy viewcells memory efficiently
[570]2031                ray.mViewCells.reserve(viewcells.size());
2032                ray.mViewCells = viewcells;
2033        }
[564]2034
[1594]2035#if USE_KD_PVS
2036        float area = GetPreprocessor()->mKdTree->GetBox().SurfaceArea()*KD_PVS_AREA;
2037        KdNode *node = GetPreprocessor()->mKdTree->GetNode(ray.mTermination, area);
2038        Intersectable *obj =
2039          GetPreprocessor()->mKdTree->
2040          GetOrCreateKdIntersectable(node);
2041#else
2042        Intersectable *obj = ray.mTerminationObject;
2043#endif
2044       
2045       
[570]2046        ViewCellContainer::const_iterator it = viewcells.begin();
[1594]2047       
[664]2048        for (; it != viewcells.end(); ++ it)
2049        {
2050                ViewCell *viewcell = *it;
[1522]2051               
[1528]2052                if (viewcell->GetValid()) // tests if view cell is in valid view space
[664]2053                {
2054                        float contribution;
[1291]2055
2056                        if (ray.mTerminationObject)
[1649]2057                        {                       
2058                                if (viewcell->GetPvs().GetSampleContribution(obj,
2059                                        ray.mPdf,
2060                                        contribution))
[1582]2061                                {
[1649]2062                                        ++ ray.mPvsContribution;
2063                                        ray.mRelativePvsContribution += contribution;
[1582]2064                                }
[664]2065                        }
[1291]2066                       
2067#if SAMPLE_ORIGIN_OBJECTS
[1582]2068
[840]2069                        // for directional sampling it is important to count only contributions
[718]2070                        // made in one direction!!!
2071                        // the other contributions of this sample will be counted for the oposite ray!
[1582]2072
[666]2073                        if (ray.mOriginObject &&
2074                                viewcell->GetPvs().GetSampleContribution(ray.mOriginObject,
2075                                                                                                                 ray.mPdf,
2076                                                                                                                 contribution))
[1582]2077                        {
[666]2078                                ++ ray.mPvsContribution;
[1582]2079                                ray.mRelativePvsContribution += contribution;
2080                        }
[718]2081#endif
[664]2082                }
[569]2083        }
[564]2084
[1528]2085        // if true, the sampled entities are stored in the pvs
[664]2086        if (addRays)
2087        {
2088                for (it = viewcells.begin(); it != viewcells.end(); ++ it)
2089                {
2090                        ViewCell *viewcell = *it;
2091           
[706]2092                        if (viewcell->GetValid())
[664]2093                        {
[1486]2094                                // if view point is valid, add new object to the pvs
[1155]2095                                if (ray.mTerminationObject)
[1545]2096                                {
[1594]2097                                        viewcell->GetPvs().AddSample(obj, ray.mPdf);
[1159]2098                                }                               
[1166]2099#if SAMPLE_ORIGIN_OBJECTS
[666]2100                                 if (ray.mOriginObject)
[1159]2101                                 {
[666]2102                                         viewcell->GetPvs().AddSample(ray.mOriginObject, ray.mPdf);
[1159]2103                                 }
[718]2104#endif
[664]2105                        }
2106                }
[563]2107        }
[570]2108
[1715]2109        return ABS_CONTRIBUTION_WEIGHT*ray.mPvsContribution +
2110          (1.0f - ABS_CONTRIBUTION_WEIGHT)*ray.mRelativePvsContribution;
[468]2111}
2112
2113
[469]2114void ViewCellsManager::GetRaySets(const VssRayContainer &sourceRays,
[485]2115                                                                  const int maxSize,
[503]2116                                                                  VssRayContainer &usedRays,
[485]2117                                                                  VssRayContainer *savedRays) const
[469]2118{
[485]2119        const int limit = min(maxSize, (int)sourceRays.size());
[473]2120        const float prop = (float)limit / ((float)sourceRays.size() + Limits::Small);
[469]2121
[485]2122        VssRayContainer::const_iterator it, it_end = sourceRays.end();
[469]2123        for (it = sourceRays.begin(); it != it_end; ++ it)
2124        {
[473]2125                if (Random(1.0f) < prop)
[485]2126                        usedRays.push_back(*it);
2127                else if (savedRays)
2128                        savedRays->push_back(*it);
[469]2129        }
2130}
2131
[477]2132
[728]2133float ViewCellsManager::GetRendercost(ViewCell *viewCell) const
[605]2134{
[1709]2135        return (float)mViewCellsTree->GetPvsCost(viewCell);
[605]2136}
2137
2138
[477]2139float ViewCellsManager::GetAccVcArea()
[470]2140{
2141        // if already computed
2142        if (mTotalAreaValid)
[728]2143        {
[470]2144                return mTotalArea;
[728]2145        }
[470]2146
2147        mTotalArea = 0;
2148        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2149
2150        for (it = mViewCells.begin(); it != it_end; ++ it)
[480]2151        {
2152                //Debug << "area: " << GetArea(*it);
[470]2153        mTotalArea += GetArea(*it);
[480]2154        }
2155
[470]2156        mTotalAreaValid = true;
2157
2158        return mTotalArea;
2159}
2160
[482]2161
[475]2162void ViewCellsManager::PrintStatistics(ostream &s) const
2163{
[660]2164        s << mCurrentViewCellsStats << endl;
[475]2165}
2166
[477]2167
[508]2168void ViewCellsManager::CreateUniqueViewCellIds()
[482]2169{
[651]2170        if (ViewCellsTreeConstructed())
[1284]2171        {
[651]2172                mViewCellsTree->CreateUniqueViewCellsIds();
[1284]2173        }
2174        else // no view cells tree, handle view cells "myself"
2175        {
[1551]2176                int i = 0;
2177                ViewCellContainer::const_iterator vit, vit_end = mViewCells.end();
2178                for (vit = mViewCells.begin(); vit != vit_end; ++ vit)
[1284]2179                {
[1557]2180                        if ((*vit)->GetId() != OUT_OF_BOUNDS_ID)
2181                        {
[1551]2182                                mViewCells[i]->SetId(i ++);
[1557]2183                        }
[1284]2184                }
2185        }
[508]2186}
2187
[1416]2188
2189void ViewCellsManager::ExportViewCellsForViz(Exporter *exporter,
2190                                                                                         const AxisAlignedBox3 *sceneBox,
[1571]2191                                                                                         const AxisAlignedPlane *clipPlane,
2192                                                                                         const bool colorCode
[1416]2193                                                                                         ) const
[508]2194{
[482]2195        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2196
2197        for (it = mViewCells.begin(); it != it_end; ++ it)
2198        {
[574]2199                if (!mOnlyValidViewCells || (*it)->GetValid())
2200                {
[1571]2201                        ExportColor(exporter, *it, colorCode); 
[1416]2202                        ExportViewCellGeometry(exporter, *it, sceneBox, clipPlane);
[574]2203                }
[482]2204        }
2205}
2206
2207
[517]2208void ViewCellsManager::CreateViewCellMeshes()
[503]2209{
2210        // convert to meshes
2211        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
2212
2213        for (it = mViewCells.begin(); it != it_end; ++ it)
2214        {
[517]2215                if (!(*it)->GetMesh())
[1001]2216                {
[517]2217                        CreateMesh(*it);
[1001]2218                }
[503]2219        }
2220}
2221
[508]2222
[944]2223bool ViewCellsManager::ExportViewCells(const string filename,
2224                                                                           const bool exportPvs,
2225                                                                           const ObjectContainer &objects)
[564]2226{
[508]2227        return false;
2228}
2229
2230
[610]2231void ViewCellsManager::CollectViewCells(const int n)
[508]2232{
[610]2233        mNumActiveViewCells = n;
2234        mViewCells.clear();
[1545]2235        // implemented in subclasses
[610]2236        CollectViewCells();
2237}
[508]2238
2239
[1707]2240void ViewCellsManager::SetViewCellActive(ViewCell *vc) const
2241{
2242        ViewCellContainer leaves;
2243        // sets the pointers to the currently active view cells
2244        mViewCellsTree->CollectLeaves(vc, leaves);
2245
2246        ViewCellContainer::const_iterator lit, lit_end = leaves.end();
2247        for (lit = leaves.begin(); lit != lit_end; ++ lit)
2248        {
2249                dynamic_cast<ViewCellLeaf *>(*lit)->SetActiveViewCell(vc);
2250        }
2251}
2252
2253
[660]2254void ViewCellsManager::SetViewCellsActive()
2255{
[1707]2256        // collect leaf view cells and set the pointers to
2257        // the currently active view cells
[660]2258        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[944]2259
[660]2260        for (it = mViewCells.begin(); it != it_end; ++ it)
2261        {
[1707]2262                SetViewCellActive(*it);
[660]2263        }
2264}
[508]2265
[840]2266
2267int ViewCellsManager::GetMaxFilterSize() const
2268{
2269        return mMaxFilterSize; 
2270}
2271
[1001]2272
[840]2273static const bool USE_ASCII = true;
2274
[1001]2275
[840]2276bool ViewCellsManager::ExportBoundingBoxes(const string filename,
2277                                                                                   const ObjectContainer &objects) const
2278{
2279        ObjectContainer::const_iterator it, it_end = objects.end();
2280       
2281        if (USE_ASCII)
2282        {
2283                ofstream boxesOut(filename.c_str());
2284                if (!boxesOut.is_open())
2285                        return false;
2286
2287                for (it = objects.begin(); it != it_end; ++ it)
2288                {
2289                        MeshInstance *mi = dynamic_cast<MeshInstance *>(*it);
2290                        const AxisAlignedBox3 box = mi->GetBox();
2291
2292                        boxesOut << mi->GetId() << " "
2293                                         << box.Min().x << " "
2294                                         << box.Min().y << " "
2295                                         << box.Min().z << " "
2296                                         << box.Max().x << " "
2297                                         << box.Max().y << " "
2298                     << box.Max().z << endl;   
2299                }
2300
2301                boxesOut.close();
2302        }
2303        else
2304        {
2305                ofstream boxesOut(filename.c_str(), ios::binary);
2306
2307                if (!boxesOut.is_open())
2308                        return false;
2309
2310                for (it = objects.begin(); it != it_end; ++ it)
2311                {       
2312                        MeshInstance *mi = dynamic_cast<MeshInstance *>(*it);
2313                        const AxisAlignedBox3 box = mi->GetBox();
2314                        Vector3 bmin = box.Min();
2315                        Vector3 bmax = box.Max();
[850]2316                        int id = mi->GetId();
[840]2317
[850]2318                        boxesOut.write(reinterpret_cast<char *>(&id), sizeof(int));
[840]2319                        boxesOut.write(reinterpret_cast<char *>(&bmin), sizeof(Vector3));
2320                        boxesOut.write(reinterpret_cast<char *>(&bmax), sizeof(Vector3));
2321                }
2322               
2323                boxesOut.close();
2324        }
2325
2326        return true;
2327}
2328
2329
[850]2330bool ViewCellsManager::LoadBoundingBoxes(const string filename,
2331                                                                                 IndexedBoundingBoxContainer &boxes) const
[840]2332{
[850]2333        Vector3 bmin, bmax;
2334        int id;
[840]2335
[850]2336        if (USE_ASCII)
[840]2337        {
[850]2338                ifstream boxesIn(filename.c_str());
[840]2339               
[850]2340                if (!boxesIn.is_open())
[840]2341                {
[850]2342                        cout << "failed to open file " << filename << endl;
2343                        return false;
[840]2344                }
[850]2345
2346                string buf;
2347                while (!(getline(boxesIn, buf)).eof())
[840]2348                {
[850]2349                        sscanf(buf.c_str(), "%d %f %f %f %f %f %f",
2350                                   &id, &bmin.x, &bmin.y, &bmin.z,
2351                                   &bmax.x, &bmax.y, &bmax.z);
2352               
2353                        AxisAlignedBox3 box(bmin, bmax);
2354                        //      MeshInstance *mi = new MeshInstance();
2355                        // HACK: set bounding box to new box
2356                        //mi->mBox = box;
2357
2358                        boxes.push_back(IndexedBoundingBox(id, box));
[840]2359                }
2360
[850]2361                boxesIn.close();
[840]2362        }
[850]2363        else
[840]2364        {
[850]2365                ifstream boxesIn(filename.c_str(), ios::binary);
[840]2366
[850]2367                if (!boxesIn.is_open())
2368                        return false;
2369
2370                while (1)
[840]2371                {
[850]2372                        boxesIn.read(reinterpret_cast<char *>(&id), sizeof(Vector3));
2373                        boxesIn.read(reinterpret_cast<char *>(&bmin), sizeof(Vector3));
2374                        boxesIn.read(reinterpret_cast<char *>(&bmax), sizeof(Vector3));
2375                       
2376                        if (boxesIn.eof())
2377                                break;
2378
2379                       
2380                        AxisAlignedBox3 box(bmin, bmax);
2381                        MeshInstance *mi = new MeshInstance(NULL);
2382
2383                        // HACK: set bounding box to new box
2384                        //mi->mBox = box;
2385                        //boxes.push_back(mi);
2386                        boxes.push_back(IndexedBoundingBox(id, box));
[840]2387                }
2388
[850]2389                boxesIn.close();
[840]2390        }
2391
2392        return true;
[850]2393}
[840]2394
[931]2395
2396float ViewCellsManager::GetFilterWidth()
2397{
2398        return mFilterWidth;
2399}
2400
2401
2402float ViewCellsManager::GetAbsFilterWidth()
2403{
2404        return Magnitude(mViewSpaceBox.Size()) * mFilterWidth;
2405}
2406
2407
[1168]2408void ViewCellsManager::UpdateScalarPvsSize(ViewCell *vc,
[1709]2409                                                                                   const float pvsCost,
[1168]2410                                                                                   const int entriesInPvs) const
[1002]2411{
[1709]2412        vc->mPvsCost = pvsCost;
[1160]2413        vc->mEntriesInPvs = entriesInPvs;
2414
[1002]2415        vc->mPvsSizeValid = true;
2416}
2417
2418
[1021]2419void
2420ViewCellsManager::ApplyFilter(ViewCell *viewCell,
2421                                                          KdTree *kdTree,
2422                                                          const float viewSpaceFilterSize,
2423                                                          const float spatialFilterSize,
2424                                                          ObjectPvs &pvs
2425                                                          )
2426{
2427  // extend the pvs of the viewcell by pvs of its neighbors
2428  // and apply spatial filter by including all neighbors of the objects
2429  // in the pvs
2430
2431  // get all viewcells intersecting the viewSpaceFilterBox
2432  // and compute the pvs union
2433 
2434  //Vector3 center = viewCell->GetBox().Center();
2435  //  Vector3 center = m->mBox.Center();
[1679]2436
2437        //  AxisAlignedBox3 box(center - Vector3(viewSpaceFilterSize/2),
2438        //                                        center + Vector3(viewSpaceFilterSize/2));
[1021]2439        if (!ViewCellsConstructed())
2440                return;
2441
[1679]2442        if (viewSpaceFilterSize >= 0.0f) {
[1021]2443
[1679]2444                const bool usePrVS = false;
[1021]2445
[1679]2446                if (!usePrVS) {
2447                        AxisAlignedBox3 box = GetViewCellBox(viewCell);
2448                        box.Enlarge(Vector3(viewSpaceFilterSize/2));
[1021]2449
[1679]2450                        ViewCellContainer viewCells;
2451                        ComputeBoxIntersections(box, viewCells);
2452
2453                        //  cout<<"box="<<box<<endl;
2454                        ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();
2455
[1740]2456                        for (; it != it_end; ++ it)
2457                        {
2458                                ObjectPvs interPvs;
[1679]2459                                //cout<<"v"<<i<<" pvs="<<(*it)->GetPvs().mEntries.size()<<endl;
[1740]2460                                ObjectPvs::Merge(interPvs, pvs, (*it)->GetPvs());
2461
2462                                pvs = interPvs;
[1679]2463                        }
[1740]2464                } else
2465                {
[1679]2466                        PrVs prvs;
2467                        AxisAlignedBox3 box = GetViewCellBox(viewCell);
2468
2469                        //  mViewCellsManager->SetMaxFilterSize(1);
2470                        GetPrVS(box.Center(), prvs, viewSpaceFilterSize);
2471                        pvs = prvs.mViewCell->GetPvs();
2472                        DeleteLocalMergeTree(prvs.mViewCell);
2473                }
[1740]2474        }
2475        else
2476        {
[1679]2477                pvs = viewCell->GetPvs();
[1740]2478        }
[1679]2479
2480        if (spatialFilterSize >=0.0f)
2481                ApplySpatialFilter(kdTree, spatialFilterSize, pvs);
2482
[1021]2483}
2484
2485
2486
2487void
2488ViewCellsManager::ApplyFilter(KdTree *kdTree,
2489                                                          const float relViewSpaceFilterSize,
2490                                                          const float relSpatialFilterSize
2491                                                          )
2492{
2493
2494        if (!ViewCellsConstructed())
2495                return;
2496
[1679]2497        ViewCellContainer::const_iterator it, it_end = mViewCells.end();
[1021]2498
[1679]2499        ObjectPvs *newPvs;
2500        newPvs = new ObjectPvs[mViewCells.size()];
[1021]2501
[1679]2502        float viewSpaceFilterSize = Magnitude(mViewSpaceBox.Size())*relViewSpaceFilterSize;
2503        float spatialFilterSize = Magnitude(kdTree->GetBox().Size())*relSpatialFilterSize;
[1715]2504       
[1679]2505        int i;
2506        for (i=0, it = mViewCells.begin(); it != it_end; ++ it, ++ i) {
[1715]2507          ApplyFilter(*it,
2508                                  kdTree,
2509                                  viewSpaceFilterSize,
2510                                  spatialFilterSize,
2511                                  newPvs[i]
2512                                  );
[1679]2513        }
[1715]2514       
[1679]2515        // now replace all pvss
2516        for (i = 0, it = mViewCells.begin(); it != it_end; ++ it, ++ i) {
[1715]2517         
2518          ObjectPvs &pvs = (*it)->GetPvs();
2519          pvs.Clear();
2520          pvs = newPvs[i];
2521          newPvs[i].Clear();
[1679]2522        }
[1021]2523
[1679]2524        delete [] newPvs;
2525}
[1021]2526
[1679]2527
[1021]2528void
2529ViewCellsManager::ApplySpatialFilter(
2530                                                                         KdTree *kdTree,
2531                                                                         const float spatialFilterSize,
2532                                                                         ObjectPvs &pvs
2533                                                                         )
2534{
[1716]2535  // now compute a new Pvs by including also objects intersecting the
2536  // extended boxes of visible objects
2537  Intersectable::NewMail();
[1742]2538
2539  ObjectPvsIterator pit = pvs.GetIterator();
2540
2541  while (pit.HasMoreEntries())
2542  {             
2543          ObjectPvsEntry entry = pit.Next();
[1716]2544 
[1742]2545          Intersectable *object = entry.mObject;
[1189]2546      object->Mail();
[1742]2547  }
[1021]2548
2549  ObjectPvs nPvs;
[1189]2550  int nPvsSize = 0;
[1742]2551 
2552  ObjectPvsIterator pit2 = pvs.GetIterator();
[1021]2553
[1742]2554  while (pit2.HasMoreEntries())
2555  {             
2556          // now go through the pvs again
2557          ObjectPvsEntry entry = pit2.Next();
2558          Intersectable *object = entry.mObject;
[1021]2559
[1742]2560          //    Vector3 center = object->GetBox().Center();
2561          //    AxisAlignedBox3 box(center - Vector3(spatialFilterSize/2),
2562          //                                            center + Vector3(spatialFilterSize/2));
2563
2564          AxisAlignedBox3 box = object->GetBox();
2565          box.Enlarge(Vector3(spatialFilterSize/2));
2566
2567          ObjectContainer objects;
2568
2569          // $$ warning collect objects takes only unmailed ones!
2570          kdTree->CollectObjects(box, objects);
2571          //    cout<<"collected objects="<<objects.size()<<endl;
2572          ObjectContainer::const_iterator noi = objects.begin();
2573          for (; noi != objects.end(); ++ noi)
2574          {
2575                  Intersectable *o = *noi;
2576                  // $$ JB warning: pdfs are not correct at this point!   
2577                  nPvs.AddSample(o, Limits::Small);
2578                  nPvsSize ++;
2579          }
[1021]2580  }
2581  //  cout<<"nPvs size = "<<nPvsSize<<endl;
[1740]2582
2583  pvs.MergeInPlace(nPvs);
[1021]2584}
2585
2586
[1715]2587void
2588ViewCellsManager::ApplyFilter2(ViewCell *viewCell,
[1737]2589                                                           const bool useViewSpaceFilter,
[1715]2590                                                           const float filterSize,
2591                                                           ObjectPvs &pvs
2592                                                           )
2593{
[1737]2594  AxisAlignedBox3 vbox = GetViewCellBox(viewCell);
2595  Vector3 center = vbox.Center();
[1716]2596  // first determine the average size of the filter
[1715]2597
[1743]2598  pvs = viewCell->GetPvs();
[1716]2599  Intersectable::NewMail();
[1743]2600 
[1742]2601  ObjectPvsIterator pit = pvs.GetIterator();
2602
[1716]2603  // first mark all object from this pvs
[1742]2604  while (pit.HasMoreEntries())
2605  {             
2606          ObjectPvsEntry entry = pit.Next();
2607
2608          Intersectable *object = entry.mObject;
2609          object->Mail();
[1716]2610  }
2611
2612  ObjectPvs nPvs;
2613  int pvsSize = 0;
2614  int nPvsSize = 0;
[1742]2615  float samples = (float)pvs.GetSamples();
[1737]2616  cout<<"Samples = "<<samples<<endl;
2617  //  cout<<"Filter size = "<<filterSize<<endl;
2618  //  cout<<"vbox = "<<vbox<<endl;
2619  //  cout<<"center = "<<center<<endl;
[1716]2620
[1737]2621
2622#define MIN_LOCAL_SAMPLES 5
2623
2624  // compute the average filter radius
2625  float globalC = 2.0f*filterSize/sqrt(samples);
2626
2627  float sumRadius = 0.0f;
[1742]2628
2629  ObjectPvsIterator pit2 = pvs.GetIterator();
2630
2631  // first mark all object from this pvs
2632   for (; pit2.HasMoreEntries(); pvsSize++) {
2633  ObjectPvsEntry entry = pit2.Next();
2634        Intersectable *object = entry.mObject;
[1716]2635        // compute filter size based on the distance and the numebr of samples
[1737]2636        AxisAlignedBox3 box = object->GetBox();
[1716]2637
[1737]2638        float distance = Distance(center, box.Center());
2639        float globalRadius = distance*globalC;
2640
[1742]2641        int objectSamples = (int)entry.mData.mSumPdf;
[1737]2642        float localRadius = MAX_FLOAT;
2643       
2644        if (objectSamples > MIN_LOCAL_SAMPLES)
2645          localRadius = 0.5f*Magnitude(box.Diagonal())/sqrt((float)objectSamples);
2646       
[1716]2647        // now compute the filter size
[1737]2648        float radius = Min(localRadius, globalRadius);
2649       
2650        sumRadius +=radius;
2651  }
2652 
2653  float avgRadius = sumRadius/pvsSize;
2654  float viewCellRadius = 0.5f*Magnitude(vbox.Diagonal());
2655  cout<<"radius ratio = "<<avgRadius/viewCellRadius<<endl;
2656 
2657  // now compute the filter box around the current viewCell
2658
2659  if (useViewSpaceFilter) {
2660        //      float radius = Max(viewCellRadius/100.0f, avgRadius - viewCellRadius);
2661        float radius = viewCellRadius/100.0f;
2662        vbox.Enlarge(radius);
2663        cout<<"vbox = "<<vbox<<endl;
2664        ViewCellContainer viewCells;
2665        ComputeBoxIntersections(vbox, viewCells);
2666       
2667        //  cout<<"box="<<box<<endl;
2668        ViewCellContainer::const_iterator it = viewCells.begin(), it_end = viewCells.end();
2669       
2670        int i;
2671        for (i=0; it != it_end; ++ it, ++ i)
2672          if ((*it) != viewCell) {
2673                //cout<<"v"<<i<<" pvs="<<(*it)->GetPvs().mEntries.size()<<endl;
[1740]2674                  pvs.MergeInPlace((*it)->GetPvs());
[1737]2675          }
2676
2677        // update samples and globalC
[1742]2678        samples = (float)pvs.GetSamples();
[1737]2679        globalC = 2.0f*filterSize/sqrt(samples);
2680        cout<<"neighboring viewcells = "<<i-1<<endl;
2681        cout<<"Samples' = "<<samples<<endl;
2682  }
2683 
[1742]2684  pit = pvs.GetIterator();
[1737]2685
[1742]2686  // first mark all object from this pvs
2687  while (pit.HasMoreEntries())
2688  {             
2689          ObjectPvsEntry entry = pit.Next();
[1737]2690
[1742]2691          Intersectable *object = entry.mObject;
2692          // compute filter size based on the distance and the numebr of samples
2693          AxisAlignedBox3 box = object->GetBox();
[1737]2694
[1742]2695          float distance = Distance(center, box.Center());
2696          float globalRadius = distance*globalC;
[1716]2697
[1742]2698          int objectSamples = (int)entry.mData.mSumPdf;
2699          float localRadius = MAX_FLOAT;
2700          if (objectSamples > MIN_LOCAL_SAMPLES)
2701                  localRadius = filterSize*0.5f*Magnitude(box.Diagonal())/sqrt((float)objectSamples);
2702
2703          //    cout<<"lr="<<localRadius<<" gr="<<globalRadius<<endl;
2704
2705          // now compute the filter size
2706          float radius = Min(localRadius, globalRadius);
2707
2708          // cout<<"box = "<<box<<endl;
2709          //    cout<<"distance = "<<distance<<endl;
2710          //    cout<<"radiues = "<<radius<<endl;
2711
2712          box.Enlarge(Vector3(radius));
2713
2714          ObjectContainer objects;
2715          // $$ warning collect objects takes only unmailed ones!
2716          CollectObjects(box, objects);
2717          //    cout<<"collected objects="<<objects.size()<<endl;
2718          ObjectContainer::const_iterator noi = objects.begin();
2719          for (; noi != objects.end(); ++ noi) {
[1743]2720                Intersectable *o = *noi;
2721                // $$ JB warning: pdfs are not correct at this point!     
2722                nPvs.AddSample(o, Limits::Small);
2723                nPvsSize ++;
[1742]2724          }
[1716]2725  }
[1737]2726  cout<<"nPvs size = "<<nPvsSize<<endl;
[1740]2727 
2728  pvs.MergeInPlace(nPvs);
[1743]2729 
[1737]2730  Intersectable::NewMail();
[1715]2731}
2732 
[1716]2733 
[1715]2734
[1716]2735 
2736
[1571]2737void ViewCellsManager::ExportColor(Exporter *exporter,
2738                                                                   ViewCell *vc,
2739                                                                   bool colorCode) const
[1021]2740{
2741        const bool vcValid = CheckValidity(vc, mMinPvsSize, mMaxPvsSize);
2742
2743        float importance = 0;
2744        static Material m;
2745
2746        switch (mColorCode)
2747        {
2748        case 0: // Random
2749                {
2750                        if (vcValid)
2751                        {
2752                                m.mDiffuseColor.r = 0.5f + RandomValue(0.0f, 0.5f);
2753                                m.mDiffuseColor.g = 0.5f + RandomValue(0.0f, 0.5f);
2754                                m.mDiffuseColor.b = 0.5f + RandomValue(0.f, 0.5f);
2755                        }
2756                        else
2757                        {
2758                                m.mDiffuseColor.r = 0.0f;
2759                                m.mDiffuseColor.g = 1.0f;
2760                                m.mDiffuseColor.b = 0.0f;
2761                        }
2762
2763                        exporter->SetForcedMaterial(m);
2764                        return;
2765                }
2766               
2767        case 1: // pvs
2768                {
2769                        if (mCurrentViewCellsStats.maxPvs)
[1121]2770                        {
2771                                importance =
[1709]2772                                        (float)mViewCellsTree->GetPvsCost(vc) /
[1121]2773                                        (float)mCurrentViewCellsStats.maxPvs;
2774                        }
[1021]2775                }
2776                break;
2777        case 2: // merges
2778                {
2779            const int lSize = mViewCellsTree->GetNumInitialViewCells(vc);
2780                        importance = (float)lSize / (float)mCurrentViewCellsStats.maxLeaves;
2781                }
2782                break;
2783#if 0
2784        case 3: // merge tree differene
2785                {
2786                        importance = (float)GetMaxTreeDiff(vc) /
2787                                (float)(mVspBspTree->GetStatistics().maxDepth * 2);
2788
2789                }
2790                break;
2791#endif
2792        default:
2793                break;
2794        }
2795
2796        // special color code for invalid view cells
2797        m.mDiffuseColor.r = importance;
2798        m.mDiffuseColor.g = 1.0f - m.mDiffuseColor.r;
2799        m.mDiffuseColor.b = vcValid ? 1.0f : 0.0f;
2800
2801        //Debug << "importance: " << importance << endl;
2802        exporter->SetForcedMaterial(m);
2803}
2804
2805
[1022]2806void ViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
2807                                                                                          vector<MergeCandidate> &candidates)
2808{
2809        // implemented in subclasses
2810}
2811
[1047]2812
[1718]2813void ViewCellsManager::UpdatePvsForEvaluation()
[1608]2814{
[1718]2815        ObjectPvs objPvs;
2816        UpdatePvsForEvaluation(mViewCellsTree->GetRoot(), objPvs);
[1608]2817}
2818
[1168]2819void ViewCellsManager::UpdatePvsForEvaluation(ViewCell *root, ObjectPvs &pvs)
2820{
2821        // terminate traversal
2822        if (root->IsLeaf())
2823        {
[1709]2824                //cout << "updating leaf" << endl;
[1168]2825                // we assume that pvs is explicitly stored in leaves
2826                pvs = root->GetPvs();
[1707]2827                UpdateScalarPvsSize(root, pvs.EvalPvsCost(), pvs.GetSize());
[1168]2828                return;
2829        }
[1709]2830
2831        //cout << "recursivly updating pvs" << endl;
2832
[1586]2833        ////////////////
2834        //-- interior node => propagate pvs up the tree
2835
[1168]2836        ViewCellInterior *interior = dynamic_cast<ViewCellInterior *>(root);
[1606]2837
2838        // reset interior pvs
[1168]2839        interior->GetPvs().Clear();
[1606]2840        // reset recursive pvs
[1168]2841        pvs.Clear();
[1695]2842
2843        // pvss of child nodes
[1168]2844        vector<ObjectPvs> pvsList;
[1709]2845        pvsList.resize((int)interior->mChildren.size());
[1168]2846
2847        ViewCellContainer::const_iterator vit, vit_end = interior->mChildren.end();
[1709]2848       
[1695]2849        int i = 0;
[1709]2850
[1695]2851        for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ i)
[1168]2852        {
[1586]2853                //////////////////
[1168]2854                //-- recursivly compute child pvss
[1695]2855                UpdatePvsForEvaluation(*vit, pvsList[i]/*objPvs*/);
[1168]2856        }
2857
2858#if 1
2859        Intersectable::NewMail();
2860
2861        //-- faster way of computing pvs:
[1586]2862        //-- construct merged pvs by adding
2863        //-- and only those of the next pvs which were not mailed.
2864        //-- note: sumpdf is not correct!!
2865
[1168]2866        vector<ObjectPvs>::iterator oit = pvsList.begin();
2867
2868        for (vit = interior->mChildren.begin(); vit != vit_end; ++ vit, ++ oit)
2869        {
[1742]2870                ObjectPvsIterator pit = (*oit).GetIterator();
2871               
2872                // first mark all object from this pvs
2873                while (pit.HasMoreEntries())
2874                {               
2875                        ObjectPvsEntry entry = pit.Next();
[1168]2876
[1742]2877                        Intersectable *intersect = entry.mObject;
2878
[1168]2879                        if (!intersect->Mailed())
2880                        {
[1742]2881                                pvs.AddSample(intersect, entry.mData.mSumPdf);
[1168]2882                                intersect->Mail();
2883                        }
2884                }
2885        }
2886
2887        // store pvs in this node
2888        if (mViewCellsTree->ViewCellsStorage() == ViewCellsTree::PVS_IN_INTERIORS)
2889        {
2890                interior->SetPvs(pvs);
2891        }
2892       
2893        // set new pvs size
[1707]2894        UpdateScalarPvsSize(interior, pvs.EvalPvsCost(), pvs.GetSize());
[1168]2895       
[1586]2896#else
2897        // really merge cells: slow put sumPdf is correct
[1168]2898        viewCellInterior->GetPvs().Merge(backVc->GetPvs());
2899        viewCellInterior->GetPvs().Merge(frontVc->GetPvs());
2900#endif
2901}
2902
[1174]2903
2904
[1145]2905/*******************************************************************/
2906/*               BspViewCellsManager implementation                */
2907/*******************************************************************/
[440]2908
[482]2909
[1264]2910BspViewCellsManager::BspViewCellsManager(ViewCellsTree *vcTree, BspTree *bspTree):
2911ViewCellsManager(vcTree), mBspTree(bspTree)
[440]2912{
[1004]2913        Environment::GetSingleton()->GetIntValue("BspTree.Construction.samples", mInitialSamples);
[1640]2914
[587]2915        mBspTree->SetViewCellsManager(this);
[1545]2916        mBspTree->SetViewCellsTree(mViewCellsTree);
[440]2917}
2918
[462]2919
[440]2920bool BspViewCellsManager::ViewCellsConstructed() const
2921{
2922        return mBspTree->GetRoot() != NULL;
2923}
2924
[480]2925
[440]2926ViewCell *BspViewCellsManager::GenerateViewCell(Mesh *mesh) const
2927{
2928        return new BspViewCell(mesh);
2929}
2930
[480]2931
[574]2932int BspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
2933                                                                                          const VssRayContainer &rays)
[440]2934{
[1545]2935        // if view cells were already constructed, we can finish
[440]2936        if (ViewCellsConstructed())
2937                return 0;
2938
2939        int sampleContributions = 0;
[503]2940
[469]2941        // construct view cells using the collected samples
2942        RayContainer constructionRays;
2943        VssRayContainer savedRays;
[440]2944
[1563]2945        // choose a a number of rays based on the ratio of cast rays / requested rays
[574]2946        const int limit = min(mInitialSamples, (int)rays.size());
[469]2947        VssRayContainer::const_iterator it, it_end = rays.end();
[448]2948
[473]2949        const float prop = (float)limit / ((float)rays.size() + Limits::Small);
[1586]2950
[469]2951        for (it = rays.begin(); it != it_end; ++ it)
2952        {
[473]2953                if (Random(1.0f) < prop)
[469]2954                        constructionRays.push_back(new Ray(*(*it)));
2955                else
2956                        savedRays.push_back(*it);
2957        }
[440]2958
[1545]2959    if (!mUsePredefinedViewCells)
[503]2960        {
2961                // no view cells loaded
[587]2962                mBspTree->Construct(objects, constructionRays, &mViewSpaceBox);
[469]2963                // collect final view cells
2964                mBspTree->CollectViewCells(mViewCells);
[503]2965        }
[469]2966        else
[1551]2967        {       
[1545]2968                // use predefined view cells geometry =>
2969                // contruct bsp hierarchy over them
[469]2970                mBspTree->Construct(mViewCells);
2971        }
2972
2973        // destroy rays created only for construction
2974        CLEAR_CONTAINER(constructionRays);
2975
[440]2976        Debug << mBspTree->GetStatistics() << endl;
[660]2977        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[480]2978
[469]2979        // recast rest of the rays
[649]2980        if (SAMPLE_AFTER_SUBDIVISION)
2981                ComputeSampleContributions(savedRays, true, false);
[469]2982
[719]2983        // real meshes are contructed at this stage
2984        if (0)
2985        {
2986                cout << "finalizing view cells ... ";
2987                FinalizeViewCells(true);
2988                cout << "finished" << endl;     
2989        }
2990
[440]2991        return sampleContributions;
2992}
2993
[503]2994
[480]2995void BspViewCellsManager::CollectViewCells()
[1545]2996{       
[587]2997        if (!ViewCellsTreeConstructed())
[1545]2998        {       // view cells tree constructed 
[587]2999                mBspTree->CollectViewCells(mViewCells);
3000        }
3001        else
[1545]3002        {       // we can use the view cells tree hierarchy to get the right set
3003                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
[587]3004        }
[480]3005}
[468]3006
[503]3007
[471]3008float BspViewCellsManager::GetProbability(ViewCell *viewCell)
[440]3009{
[591]3010        if (1)
3011                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
3012        else
[1545]3013                // compute view cell area as subsititute for probability
[591]3014                return GetArea(viewCell) / GetAccVcArea();
[466]3015}
[440]3016
[503]3017
[440]3018
[468]3019int BspViewCellsManager::CastLineSegment(const Vector3 &origin,
3020                                                                                 const Vector3 &termination,
3021                                                                                 ViewCellContainer &viewcells)
[440]3022{
[468]3023        return mBspTree->CastLineSegment(origin, termination, viewcells);
3024}
3025
3026
[1551]3027void ViewCellsManager::ExportMergedViewCells(const ObjectContainer &objects)
[1545]3028{
3029        // save color code
3030        const int savedColorCode = mColorCode;
3031
3032        // export merged view cells
3033        mColorCode = 0; // use random colors
3034
3035        Exporter *exporter = Exporter::GetExporter("merged_view_cells.wrl");
3036
3037        cout << "exporting view cells after merge ... ";
3038
3039        if (exporter)
3040        {
3041                if (mExportGeometry)
3042                {
3043                        exporter->ExportGeometry(objects);
3044                }
3045
3046                exporter->SetFilled();
3047                ExportViewCellsForViz(exporter, NULL, GetClipPlane());
3048
3049                delete exporter;
3050        }
3051        cout << "finished" << endl;
3052
3053        // export merged view cells using pvs color coding
3054        mColorCode = 1;
3055
3056        exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
3057        cout << "exporting view cells after merge (pvs size) ... ";     
3058
3059        if (exporter)
3060        {
3061                if (mExportGeometry)
3062                {
3063                        exporter->ExportGeometry(objects);
3064                }
3065
3066                exporter->SetFilled();
3067                ExportViewCellsForViz(exporter, NULL, GetClipPlane());
3068
3069                delete exporter;
3070        }
3071        cout << "finished" << endl;
3072       
3073        mColorCode = savedColorCode;
3074}
3075
3076
[503]3077int BspViewCellsManager::PostProcess(const ObjectContainer &objects,
[468]3078                                                                         const VssRayContainer &rays)
3079{
[469]3080        if (!ViewCellsConstructed())
[441]3081        {
3082                Debug << "view cells not constructed" << endl;
3083                return 0;
3084        }
[590]3085       
[1414]3086        // view cells already finished before post processing step,
3087        // i.e., because they were loaded from disc
[590]3088        if (mViewCellsFinished)
3089        {
3090                FinalizeViewCells(true);
3091                EvaluateViewCellsStats();
3092
3093                return 0;
3094        }
3095
[1444]3096        //////////////////
[1414]3097        //-- merge leaves of the view cell hierarchy   
3098       
[649]3099        cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
3100        long startTime = GetTime();
3101       
3102        VssRayContainer postProcessRays;
3103        GetRaySets(rays, mPostProcessSamples, postProcessRays);
3104
[592]3105        if (mMergeViewCells)
[591]3106        {
[660]3107                cout << "constructing visibility based merge tree" << endl;
[650]3108                mViewCellsTree->ConstructMergeTree(rays, objects);
[649]3109        }
3110        else
3111        {
[660]3112                cout << "constructing spatial merge tree" << endl;
[1545]3113                ViewCell *root;
3114                // the spatial merge tree is difficult to build for
3115                // this type of construction, as view cells cover several
3116                // leaves => create dummy tree which is only 2 levels deep
3117                if (mUsePredefinedViewCells)
3118                {
3119                        root = ConstructDummyMergeTree(mBspTree->GetRoot());
3120                }
3121                else
3122                {
3123                        // create spatial merge hierarchy
3124                        root = ConstructSpatialMergeTree(mBspTree->GetRoot());
3125                }
3126               
[752]3127                mViewCellsTree->SetRoot(root);
3128
[1415]3129                // recompute pvs in the whole hierarchy
[752]3130                ObjectPvs pvs;
3131                UpdatePvsForEvaluation(root, pvs);
[649]3132        }
[440]3133
[1415]3134        cout << "finished" << endl;
3135        cout << "merged view cells in "
3136                 << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
3137
3138        Debug << "Postprocessing: Merged view cells in "
3139                << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl << endl;
3140
3141       
[1418]3142        ////////////////////////
[1444]3143        //-- visualization and statistics after merge
[1415]3144
[666]3145        if (1)
3146        {
3147                char mstats[100];
[1004]3148                Environment::GetSingleton()->GetStringValue("ViewCells.mergeStats", mstats);
[666]3149                mViewCellsTree->ExportStats(mstats);
3150        }
[650]3151
[1551]3152        // recompute view cells and stats
3153        ResetViewCells();
[660]3154        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
[600]3155
[1551]3156        //  visualization of the view cells
[1545]3157        if (1) ExportMergedViewCells(objects);
[600]3158
[719]3159        // compute final meshes and volume / area
3160        if (1) FinalizeViewCells(true);
[840]3161       
[650]3162        return 0;
[440]3163}
3164
[477]3165
3166BspViewCellsManager::~BspViewCellsManager()
3167{
3168}
3169
3170
[440]3171int BspViewCellsManager::GetType() const
3172{
3173        return BSP;
3174}
3175
3176
3177void BspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]3178                                                                        const VssRayContainer &sampleRays)
[440]3179{
[469]3180        if (!ViewCellsConstructed())
3181                return;
[574]3182       
[1563]3183        const int savedColorCode = mColorCode;
[1551]3184       
[600]3185        if (1) // export final view cells
[440]3186        {
[1020]3187                mColorCode = 1; // hack color code
[1415]3188                Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
[600]3189       
3190                cout << "exporting view cells after merge (pvs size) ... ";     
[587]3191
[469]3192                if (exporter)
[440]3193                {
[600]3194                        if (mExportGeometry)
[1416]3195                        {
[600]3196                                exporter->ExportGeometry(objects);
[1416]3197                        }
[590]3198
[1416]3199                        ExportViewCellsForViz(exporter, NULL, GetClipPlane());
[469]3200                        delete exporter;
[440]3201                }
[469]3202                cout << "finished" << endl;
[503]3203        }
[1551]3204
[1545]3205        // reset color code
[600]3206        mColorCode = savedColorCode;
3207
[1416]3208
3209        //////////////////
[469]3210        //-- visualization of the BSP splits
[1416]3211
[469]3212        bool exportSplits = false;
[1004]3213        Environment::GetSingleton()->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
[503]3214
[469]3215        if (exportSplits)
[440]3216        {
[469]3217                cout << "exporting splits ... ";
[477]3218                ExportSplits(objects);
[469]3219                cout << "finished" << endl;
[440]3220        }
[477]3221
[1570]3222        int leafOut;
3223        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
3224        const int raysOut = 100;
3225        ExportSingleViewCells(objects, leafOut, false, true, false, raysOut, "");
[440]3226}
3227
3228
[477]3229void BspViewCellsManager::ExportSplits(const ObjectContainer &objects)
[440]3230{
3231        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
3232
[503]3233        if (exporter)
3234        {
[598]3235                //exporter->SetFilled();
3236                if (mExportGeometry)
[1545]3237                {
[598]3238                        exporter->ExportGeometry(objects);
[1545]3239                }
[598]3240
[503]3241                Material m;
[440]3242                m.mDiffuseColor = RgbColor(1, 0, 0);
3243                exporter->SetForcedMaterial(m);
3244                exporter->SetWireframe();
[503]3245
[440]3246                exporter->ExportBspSplits(*mBspTree, true);
3247
[1545]3248                // NOTE: take forced material, else big scenes cannot be viewed
[440]3249                m.mDiffuseColor = RgbColor(0, 1, 0);
3250                exporter->SetForcedMaterial(m);
[482]3251                //exporter->ResetForcedMaterial();
3252
[440]3253                delete exporter;
3254        }
3255}
3256
[477]3257
[1570]3258void BspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
3259                                                                                                const int maxViewCells,
3260                                                                                                const bool sortViewCells,
3261                                                                                                const bool exportPvs,
3262                                                                                                const bool exportRays,
3263                                                                                                const int maxRays,
3264                                                                                                const string prefix,
3265                                                                                                VssRayContainer *visRays)
[440]3266{
[1570]3267        if (sortViewCells)
3268        {       // sort view cells to visualize the largest view cells
3269                stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
3270        }
[440]3271
[1545]3272        //////////
[1570]3273        //-- some view cells for output
[503]3274
[1570]3275        ViewCell::NewMail();
3276        const int limit = min(maxViewCells, (int)mViewCells.size());
3277       
3278        for (int i = 0; i < limit; ++ i)
3279        {
3280                const int idx = sortViewCells ? (int)RandomValue(0, (float)mViewCells.size() - 0.5f) : i;
3281                ViewCell *vc = mViewCells[idx];
[503]3282
[1570]3283                if (vc->Mailed() || vc->GetId() == OUT_OF_BOUNDS_ID)
3284                        continue;
[587]3285
[1570]3286                vc->Mail();
[503]3287
[1570]3288                ObjectPvs pvs;
3289                mViewCellsTree->GetPvs(vc, pvs);
[582]3290
[1571]3291                char s[64]; sprintf(s, "%sviewcell-%04d.wrl", prefix.c_str(), i);
[1570]3292                Exporter *exporter = Exporter::GetExporter(s);
3293               
[1709]3294                cout << "view cell " << idx << ": pvs cost=" << (int)mViewCellsTree->GetPvsCost(vc) << endl;
[582]3295
[1570]3296                if (exportRays)
3297                {
3298                        ////////////
3299                        //-- export rays piercing this view cell
[469]3300
[1571]3301                        // use rays stored with the view cells
3302                        VssRayContainer vcRays, vcRays2, vcRays3;
[1570]3303            VssRayContainer collectRays;
3304
3305                        // collect initial view cells
3306                        ViewCellContainer leaves;
3307                        mViewCellsTree->CollectLeaves(vc, leaves);
3308
3309                        ViewCellContainer::const_iterator vit, vit_end = leaves.end();
3310                for (vit = leaves.begin(); vit != vit_end; ++ vit)
3311                        {       
[1571]3312                                // prepare some rays for output
[1696]3313                                VssRayContainer::const_iterator rit, rit_end = (*vit)->GetOrCreateRays()->end();
3314                                for (rit = (*vit)->GetOrCreateRays()->begin(); rit != rit_end; ++ rit)
[1570]3315                                {
3316                                        collectRays.push_back(*rit);
3317                                }
3318                        }
3319
3320                        const int raysOut = min((int)collectRays.size(), maxRays);
[1571]3321
[1570]3322                        // prepare some rays for output
3323                        VssRayContainer::const_iterator rit, rit_end = collectRays.end();
3324                        for (rit = collectRays.begin(); rit != rit_end; ++ rit)
[477]3325                        {
[1570]3326                                const float p = RandomValue(0.0f, (float)collectRays.size());
3327                                if (p < raysOut)
[587]3328                                {
[1571]3329                                        if ((*rit)->mFlags & VssRay::BorderSample)
[1580]3330                                        {
[1571]3331                                                vcRays.push_back(*rit);
[1580]3332                                        }
[1571]3333                                        else if ((*rit)->mFlags & VssRay::ReverseSample)
3334                                                vcRays2.push_back(*rit);
3335                                        else
3336                                                vcRays3.push_back(*rit);
3337                                               
[587]3338                                }
[477]3339                        }
[1571]3340
3341                        exporter->ExportRays(vcRays, RgbColor(1, 0, 0));
3342                        exporter->ExportRays(vcRays2, RgbColor(0, 1, 0));
3343                        exporter->ExportRays(vcRays3, RgbColor(1, 1, 1));
[477]3344                }
[1570]3345               
3346                ////////////////
3347                //-- export view cell geometry
[587]3348
[478]3349                exporter->SetWireframe();
[477]3350
[478]3351                Material m;//= RandomMaterial();
3352                m.mDiffuseColor = RgbColor(0, 1, 0);
3353                exporter->SetForcedMaterial(m);
[477]3354
[1416]3355                ExportViewCellGeometry(exporter, vc, NULL, NULL);
[478]3356                exporter->SetFilled();
[469]3357
[1570]3358                if (exportPvs)
[478]3359                {
[1570]3360                        Intersectable::NewMail();
[1742]3361                        ObjectPvsIterator pit = pvs.GetIterator();
3362
3363                        while (pit.HasMoreEntries())
[1570]3364                        {               
[1742]3365                                ObjectPvsEntry entry = pit.Next();
3366
3367                // output PVS of view cell
3368                                Intersectable *intersect = entry.mObject;
[1570]3369                               
3370                                if (!intersect->Mailed())
3371                                {
3372                                        intersect->Mail();
[1571]3373
[1570]3374                                        m = RandomMaterial();
3375                                        exporter->SetForcedMaterial(m);
3376                                        exporter->ExportIntersectable(intersect);
3377                                }
[503]3378                        }
[1570]3379                        cout << endl;
[477]3380                }
[1570]3381               
[478]3382                DEL_PTR(exporter);
3383                cout << "finished" << endl;
[477]3384        }
[440]3385}
3386
[441]3387
[693]3388void BspViewCellsManager::TestSubdivision()
3389{
3390        ViewCellContainer leaves;
3391        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
3392
3393        ViewCellContainer::const_iterator it, it_end = leaves.end();
3394
3395        const float vol = mViewSpaceBox.GetVolume();
3396        float subdivVol = 0;
3397        float newVol = 0;
3398
3399        for (it = leaves.begin(); it != it_end; ++ it)
3400        {
3401                BspNodeGeometry geom;
[1551]3402                mBspTree->ConstructGeometry(*it, geom);
[693]3403
3404                const float lVol = geom.GetVolume();
3405                newVol += lVol;
3406                subdivVol += (*it)->GetVolume();
[694]3407
[1551]3408                const float thres = 0.9f;
[694]3409                if ((lVol < ((*it)->GetVolume() * thres)) ||
3410                        (lVol * thres > ((*it)->GetVolume())))
3411                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
[693]3412        }
3413       
3414        Debug << "exact volume: " << vol << endl;
3415        Debug << "subdivision volume: " << subdivVol << endl;
3416        Debug << "new volume: " << newVol << endl;
3417}
3418
3419
[580]3420void BspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]3421                                                                                                 ViewCell *vc,
[1416]3422                                                                                                 const AxisAlignedBox3 *sceneBox,
3423                                                                                                 const AxisAlignedPlane *clipPlane
[1570]3424                                                                                                 ) const
[1557]3425{
[660]3426        if (clipPlane)
[591]3427        {
[1047]3428                const Plane3 plane = clipPlane->GetPlane();
3429
[726]3430                ViewCellContainer leaves;
3431                mViewCellsTree->CollectLeaves(vc, leaves);
3432                ViewCellContainer::const_iterator it, it_end = leaves.end();
[591]3433
[726]3434                for (it = leaves.begin(); it != it_end; ++ it)
[681]3435                {
[726]3436                        BspNodeGeometry geom;
[681]3437                        BspNodeGeometry front;
3438                        BspNodeGeometry back;
[591]3439
[1551]3440                        mBspTree->ConstructGeometry(*it, geom);
[681]3441
[1563]3442                        const float eps = 0.0001f;
[1047]3443                        const int cf = geom.Side(plane, eps);
[726]3444
3445                        if (cf == -1)
3446                        {
3447                                exporter->ExportPolygons(geom.GetPolys());
3448                        }
3449                        else if (cf == 0)
3450                        {
3451                                geom.SplitGeometry(front,
3452                                                                   back,
[1047]3453                                                                   plane,
[726]3454                                                                   mViewSpaceBox,
3455                                                                   eps);
[1563]3456
[726]3457                                if (back.Valid())
[1563]3458                                {
[726]3459                                        exporter->ExportPolygons(back.GetPolys());
3460                                }                       
3461                        }
[681]3462                }
[591]3463        }
3464        else
3465        {
[1563]3466                // export mesh if available
3467                // TODO: some bug here?
3468                if (1 && vc->GetMesh())
3469                {
3470                        exporter->ExportMesh(vc->GetMesh());
3471                }
3472                else
3473                {
3474                        BspNodeGeometry geom;
3475                        mBspTree->ConstructGeometry(vc, geom);
3476                        exporter->ExportPolygons(geom.GetPolys());
3477                }
[591]3478        }
[482]3479}
3480
[503]3481
3482void BspViewCellsManager::CreateMesh(ViewCell *vc)
3483{
[1551]3484        // note: should previous mesh be deleted (via mesh manager?)
[587]3485        BspNodeGeometry geom;
3486        mBspTree->ConstructGeometry(vc, geom);
3487
[1001]3488        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
[726]3489
[840]3490        IncludeNodeGeomInMesh(geom, *mesh);
[587]3491        vc->SetMesh(mesh);
[503]3492}
3493
[551]3494
[587]3495void BspViewCellsManager::Finalize(ViewCell *viewCell,
3496                                                                   const bool createMesh)
[502]3497{
[587]3498        float area = 0;
3499        float volume = 0;
[572]3500
[587]3501        ViewCellContainer leaves;
3502        mViewCellsTree->CollectLeaves(viewCell, leaves);
3503
3504        ViewCellContainer::const_iterator it, it_end = leaves.end();
3505
[693]3506    for (it = leaves.begin(); it != it_end; ++ it)
[587]3507        {
3508                BspNodeGeometry geom;
3509
[1551]3510                mBspTree->ConstructGeometry(*it, geom);
3511
[719]3512                const float lVol = geom.GetVolume();
3513                const float lArea = geom.GetArea();
[693]3514
3515                area += lArea;
3516                volume += lVol;
[1551]3517       
3518                CreateMesh(*it);
[587]3519        }
3520
3521        viewCell->SetVolume(volume);
3522        viewCell->SetArea(area);
[502]3523}
3524
[580]3525
[879]3526ViewCell *BspViewCellsManager::GetViewCell(const Vector3 &point, const bool active) const
[580]3527{
[1021]3528        if (!ViewCellsConstructed())
[1545]3529        {
[587]3530                return NULL;
[1545]3531        }
[587]3532        if (!mViewSpaceBox.IsInside(point))
[1545]3533        {
[587]3534                return NULL;
[1545]3535        }
[587]3536        return mBspTree->GetViewCell(point);
[580]3537}
3538
3539
[587]3540void BspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
3541                                                                                                 vector<MergeCandidate> &candidates)
3542{
3543        cout << "collecting merge candidates ... " << endl;
3544
3545        if (mUseRaysForMerge)
3546        {
3547                mBspTree->CollectMergeCandidates(rays, candidates);
3548        }
3549        else
3550        {
3551                vector<BspLeaf *> leaves;
3552                mBspTree->CollectLeaves(leaves);
3553                mBspTree->CollectMergeCandidates(leaves, candidates);
3554        }
3555
3556        cout << "fininshed collecting candidates" << endl;
3557}
3558
3559
[440]3560
[1047]3561bool BspViewCellsManager::ExportViewCells(const string filename,
3562                                                                                  const bool exportPvs,
3563                                                                                  const ObjectContainer &objects)
[590]3564{
[1551]3565        if (!ViewCellsConstructed() || !ViewCellsTreeConstructed())
3566        {
3567                return false;
3568        }
3569
[590]3570        cout << "exporting view cells to xml ... ";
[503]3571
[1551]3572        OUT_STREAM stream(filename.c_str());
3573
[590]3574        // for output we need unique ids for each view cell
3575        CreateUniqueViewCellIds();
[503]3576
[590]3577        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
[975]3578        stream << "<VisibilitySolution>" << endl;
[590]3579
[1551]3580        if (exportPvs)
3581        {
3582                //////////
3583                //-- export bounding boxes: they are used to identify the objects from the pvs and
3584                //-- assign them to the entities in the rendering engine
[590]3585
[1551]3586                stream << "<BoundingBoxes>" << endl;
3587                ObjectContainer::const_iterator oit, oit_end = objects.end();
[610]3588
[1551]3589                for (oit = objects.begin(); oit != oit_end; ++ oit)
3590                {
[1563]3591                        const AxisAlignedBox3 box = (*oit)->GetBox();
[1551]3592                       
[1563]3593                        stream << "<BoundingBox" << " id=\"" << (*oit)->GetId() << "\""
[1551]3594                                   << " min=\"" << box.Min().x << " " << box.Min().y << " " << box.Min().z << "\""
3595                                   << " max=\"" << box.Max().x << " " << box.Max().y << " " << box.Max().z << "\" />" << endl;
3596                }
[590]3597
[1551]3598                stream << "</BoundingBoxes>" << endl;
3599        }
3600
3601        ///////////
3602        //-- export the view cells and the pvs
3603
3604        const int numViewCells = mCurrentViewCellsStats.viewCells;
3605        stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
3606
3607        mViewCellsTree->Export(stream, exportPvs);
3608       
[590]3609        stream << "</ViewCells>" << endl;
3610
[1551]3611        /////////////
3612        //-- export the view space hierarchy
3613        stream << "<ViewSpaceHierarchy type=\"bsp\""
3614                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
3615                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\">" << endl;
3616
[590]3617        mBspTree->Export(stream);
3618
[1551]3619        // end tags
3620        stream << "</ViewSpaceHierarchy>" << endl;
[975]3621        stream << "</VisibilitySolution>" << endl;
[590]3622
[1551]3623        stream.close();
[590]3624        cout << "finished" << endl;
[1551]3625
[590]3626        return true;
3627}
3628
3629
[1545]3630ViewCell *BspViewCellsManager::ConstructDummyMergeTree(BspNode *root)
3631{
3632        ViewCellInterior *vcRoot = new ViewCellInterior();
3633               
3634        // evaluate merge cost for priority traversal
[1713]3635        const float mergeCost =  -(float)root->mTimeStamp;
[1545]3636        vcRoot->SetMergeCost(mergeCost);
3637
3638        float volume = 0;
3639        vector<BspLeaf *> leaves;
3640        mBspTree->CollectLeaves(leaves);
3641        vector<BspLeaf *>::const_iterator lit, lit_end = leaves.end();
[1548]3642        ViewCell::NewMail();
3643
[1545]3644        for (lit = leaves.begin(); lit != lit_end; ++ lit)
3645        {
3646                BspLeaf *leaf = *lit;
3647                ViewCell *vc = leaf->GetViewCell();
3648
[1548]3649                if (!vc->Mailed())
3650                {
3651                        vc->Mail();
3652                        vc->SetMergeCost(0.0f);
3653                        vcRoot->SetupChildLink(vc);
[1545]3654
[1548]3655                        volume += vc->GetVolume();
3656                        volume += vc->GetVolume();     
3657                        vcRoot->SetVolume(volume);
3658                }
[1545]3659        }
3660       
3661        return vcRoot;
3662}
3663
3664
[650]3665ViewCell *BspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
[610]3666{
[752]3667        // terminate recursion
[650]3668        if (root->IsLeaf())
3669        {
[752]3670                BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
3671                leaf->GetViewCell()->SetMergeCost(0.0f);
3672                return leaf->GetViewCell();
[650]3673        }
3674       
3675        BspInterior *interior = dynamic_cast<BspInterior *>(root);
3676        ViewCellInterior *viewCellInterior = new ViewCellInterior();
3677               
[752]3678        // evaluate merge cost for priority traversal
[1713]3679        const float mergeCost = -(float)root->mTimeStamp;
[650]3680        viewCellInterior->SetMergeCost(mergeCost);
[649]3681
[650]3682        float volume = 0;
[649]3683       
[650]3684        BspNode *front = interior->GetFront();
3685        BspNode *back = interior->GetBack();
[649]3686
[752]3687
[1545]3688        ////////////
[752]3689        //-- recursivly compute child hierarchies
[1545]3690
[650]3691        ViewCell *backVc = ConstructSpatialMergeTree(back);
3692        ViewCell *frontVc = ConstructSpatialMergeTree(front);
[610]3693
[752]3694        viewCellInterior->SetupChildLink(backVc);
[650]3695        viewCellInterior->SetupChildLink(frontVc);
[610]3696
[650]3697        volume += backVc->GetVolume();
3698        volume += frontVc->GetVolume();
[649]3699
[650]3700        viewCellInterior->SetVolume(volume);
[649]3701
[650]3702        return viewCellInterior;
[610]3703}
3704
[650]3705
[590]3706/************************************************************************/
3707/*                   KdViewCellsManager implementation                  */
3708/************************************************************************/
3709
3710
3711
[1264]3712KdViewCellsManager::KdViewCellsManager(ViewCellsTree *vcTree, KdTree *kdTree):
3713ViewCellsManager(vcTree), mKdTree(kdTree), mKdPvsDepth(100)
[440]3714{
3715}
3716
[605]3717
[471]3718float KdViewCellsManager::GetProbability(ViewCell *viewCell)
[468]3719{
[479]3720        // compute view cell area / volume as subsititute for probability
[605]3721        if (0)
3722                return GetArea(viewCell) / GetViewSpaceBox().SurfaceArea();
3723        else
3724                return GetVolume(viewCell) / GetViewSpaceBox().GetVolume();
[468]3725}
3726
3727
3728
[479]3729
[480]3730void KdViewCellsManager::CollectViewCells()
3731{
3732        //mKdTree->CollectViewCells(mViewCells); TODO
3733}
[479]3734
[519]3735
[574]3736int KdViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
[487]3737                                                                  const VssRayContainer &rays)
[440]3738{
[441]3739        // if view cells already constructed
[440]3740        if (ViewCellsConstructed())
3741                return 0;
[441]3742
[440]3743        mKdTree->Construct();
3744
[480]3745        mTotalAreaValid = false;
[469]3746        // create the view cells
3747        mKdTree->CreateAndCollectViewCells(mViewCells);
[480]3748        // cast rays
[574]3749        ComputeSampleContributions(rays, true, false);
[480]3750
[479]3751        EvaluateViewCellsStats();
[660]3752        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[469]3753
[440]3754        return 0;
3755}
3756
[587]3757
[440]3758bool KdViewCellsManager::ViewCellsConstructed() const
3759{
3760        return mKdTree->GetRoot() != NULL;
3761}
3762
[1020]3763
[503]3764int KdViewCellsManager::PostProcess(const ObjectContainer &objects,
[466]3765                                                                        const VssRayContainer &rays)
[440]3766{
3767        return 0;
3768}
3769
[1020]3770
[1570]3771void KdViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
3772                                                                                           const int maxViewCells,
3773                                                                                           const bool sortViewCells,
3774                                                                                           const bool exportPvs,
3775                                                                                           const bool exportRays,
3776                                                                                           const int maxRays,
3777                                                                                           const string prefix,
3778                                                                                           VssRayContainer *visRays)
3779{
3780        // TODO
3781}
3782
3783
[440]3784void KdViewCellsManager::Visualize(const ObjectContainer &objects,
[466]3785                                                                   const VssRayContainer &sampleRays)
[440]3786{
[441]3787        if (!ViewCellsConstructed())
3788                return;
3789
[469]3790        // using view cells instead of the kd PVS of objects
3791        const bool useViewCells = true;
3792        bool exportRays = false;
[440]3793
3794        int limit = min(mVisualizationSamples, (int)sampleRays.size());
[469]3795        const int pvsOut = min((int)objects.size(), 10);
[466]3796        VssRayContainer *rays = new VssRayContainer[pvsOut];
[440]3797
[469]3798        if (useViewCells)
[440]3799        {
[469]3800                const int leafOut = 10;
[503]3801
[469]3802                ViewCell::NewMail();
[503]3803
[469]3804                //-- some rays for output
3805                const int raysOut = min((int)sampleRays.size(), mVisualizationSamples);
3806                Debug << "visualization using " << raysOut << " samples" << endl;
3807
3808                //-- some random view cells and rays for output
3809                vector<KdLeaf *> kdLeaves;
[503]3810
[469]3811                for (int i = 0; i < leafOut; ++ i)
3812                        kdLeaves.push_back(dynamic_cast<KdLeaf *>(mKdTree->GetRandomLeaf()));
[503]3813
[469]3814                for (int i = 0; i < kdLeaves.size(); ++ i)
[440]3815                {
[469]3816                        KdLeaf *leaf = kdLeaves[i];
3817                        RayContainer vcRays;
[503]3818
[469]3819                        cout << "creating output for view cell " << i << " ... ";
[503]3820#if 0
[469]3821                        // check whether we can add the current ray to the output rays
[503]3822                        for (int k = 0; k < raysOut; ++ k)
[440]3823                        {
[469]3824                                Ray *ray = sampleRays[k];
[503]3825
[469]3826                                for (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
3827                                {
3828                                        BspLeaf *leaf2 = ray->bspIntersections[j].mLeaf;
[503]3829
3830                                        if (leaf->GetViewCell() == leaf2->GetViewCell())
[469]3831                                        {
3832                                                vcRays.push_back(ray);
3833                                        }
3834                                }
[479]3835                        }
[503]3836#endif
[469]3837                        Intersectable::NewMail();
[503]3838
[469]3839                        ViewCell *vc = leaf->mViewCell;
[1570]3840                        char str[64]; sprintf(str, "viewcell%04d.wrl", i);
[503]3841
[1570]3842                        Exporter *exporter = Exporter::GetExporter(str);
[469]3843                        exporter->SetFilled();
3844
3845                        exporter->SetWireframe();
3846                        //exporter->SetFilled();
[503]3847
[469]3848                        Material m;//= RandomMaterial();
3849                        m.mDiffuseColor = RgbColor(1, 1, 0);
3850                        exporter->SetForcedMaterial(m);
[503]3851
[469]3852                        AxisAlignedBox3 box = mKdTree->GetBox(leaf);
3853                        exporter->ExportBox(box);
3854
3855                        // export rays piercing this view cell
[503]3856                        exporter->ExportRays(vcRays, 1000, RgbColor(0, 1, 0));
3857
[469]3858                        m.mDiffuseColor = RgbColor(1, 0, 0);
3859                        exporter->SetForcedMaterial(m);
[503]3860
[469]3861                        // exporter->SetWireframe();
3862                        exporter->SetFilled();
[503]3863
[1742]3864                        ObjectPvsIterator pit = vc->GetPvs().GetIterator();
3865                       
3866                        while (pit.HasMoreEntries())
3867                        {               
3868                                ObjectPvsEntry entry = pit.Next();
3869                               
3870                                //-- output PVS of view cell
3871                                Intersectable *intersect = entry.mObject;
[469]3872                                if (!intersect->Mailed())
3873                                {
3874                                        exporter->ExportIntersectable(intersect);
3875                                        intersect->Mail();
[503]3876                                }
[440]3877                        }
[503]3878
[469]3879                        DEL_PTR(exporter);
3880                        cout << "finished" << endl;
[440]3881                }
[469]3882
3883                DEL_PTR(rays);
[440]3884        }
[469]3885        else // using kd PVS of objects
3886        {
3887                for (int i = 0; i < limit; ++ i)
3888                {
3889                        VssRay *ray = sampleRays[i];
[503]3890
[469]3891                        // check whether we can add this to the rays
[503]3892                        for (int j = 0; j < pvsOut; j++)
[469]3893                        {
3894                                if (objects[j] == ray->mTerminationObject)
3895                                {
3896                                        rays[j].push_back(ray);
3897                                }
3898                        }
3899                }
[440]3900
[503]3901                if (exportRays)
[469]3902                {
3903                        Exporter *exporter = NULL;
3904                        exporter = Exporter::GetExporter("sample-rays.x3d");
3905                        exporter->SetWireframe();
3906                        exporter->ExportKdTree(*mKdTree);
[503]3907
[728]3908                        for (i = 0; i < pvsOut; i++)
[469]3909                                exporter->ExportRays(rays[i], RgbColor(1, 0, 0));
3910
3911                        exporter->SetFilled();
3912                        delete exporter;
3913                }
[440]3914
[503]3915                for (int k=0; k < pvsOut; k++)
[469]3916                {
3917                        Intersectable *object = objects[k];
[1570]3918                        char str[64]; sprintf(str, "viewcell%04d.wrl", i);
[440]3919
[1570]3920                        Exporter *exporter = Exporter::GetExporter(str);
[469]3921                        exporter->SetWireframe();
[503]3922
[1736]3923                        // matt: no kd pvs
3924                        /*
[1233]3925                        KdPvsMap::iterator kit = object->mKdPvs.mEntries.begin();
[469]3926                        Intersectable::NewMail();
[503]3927
[469]3928                        // avoid adding the object to the list
3929                        object->Mail();
3930                        ObjectContainer visibleObjects;
[503]3931
[1233]3932                        for (; kit != object->mKdPvs.mEntries.end(); i++)
[469]3933                        {
[1233]3934                                KdNode *node = (*kit).first;
[469]3935                                exporter->ExportBox(mKdTree->GetBox(node));
[503]3936
[469]3937                                mKdTree->CollectObjects(node, visibleObjects);
3938                        }
[503]3939
[469]3940                        exporter->ExportRays(rays[k],  RgbColor(0, 1, 0));
3941                        exporter->SetFilled();
[503]3942
[469]3943                        for (int j = 0; j < visibleObjects.size(); j++)
3944                                exporter->ExportIntersectable(visibleObjects[j]);
[503]3945
[469]3946                        Material m;
3947                        m.mDiffuseColor = RgbColor(1, 0, 0);
3948                        exporter->SetForcedMaterial(m);
3949                        exporter->ExportIntersectable(object);
[1736]3950*/
[469]3951                        delete exporter;
[440]3952                }
[503]3953        }
[440]3954}
3955
[469]3956
[580]3957ViewCell *KdViewCellsManager::GenerateViewCell(Mesh *mesh) const
3958{
3959        return new KdViewCell(mesh);
3960}
[482]3961
[580]3962
3963void KdViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[591]3964                                                                                                ViewCell *vc,
[1416]3965                                                                                                const AxisAlignedBox3 *sceneBox,
3966                                                                                                const AxisAlignedPlane *clipPlane
3967                                                                                                ) const
[482]3968{
[580]3969        ViewCellContainer leaves;
3970        mViewCellsTree->CollectLeaves(vc, leaves);
3971        ViewCellContainer::const_iterator it, it_end = leaves.end();
3972
3973        for (it = leaves.begin(); it != it_end; ++ it)
3974        {
3975                KdViewCell *kdVc = dynamic_cast<KdViewCell *>(*it);
[1551]3976                exporter->ExportBox(mKdTree->GetBox(kdVc->mLeaves[0]));
[580]3977        }
[482]3978}
3979
3980
[440]3981int KdViewCellsManager::GetType() const
3982{
3983        return ViewCellsManager::KD;
3984}
3985
3986
[441]3987
[440]3988KdNode *KdViewCellsManager::GetNodeForPvs(KdLeaf *leaf)
3989{
3990        KdNode *node = leaf;
3991
3992        while (node->mParent && node->mDepth > mKdPvsDepth)
3993                node = node->mParent;
[1176]3994
[440]3995        return node;
3996}
3997
[469]3998int KdViewCellsManager::CastLineSegment(const Vector3 &origin,
3999                                                                                const Vector3 &termination,
4000                                                                                ViewCellContainer &viewcells)
[466]4001{
[469]4002        return mKdTree->CastLineSegment(origin, termination, viewcells);
[466]4003}
4004
[469]4005
[503]4006void KdViewCellsManager::CreateMesh(ViewCell *vc)
4007{
[551]4008        // TODO
[503]4009}
4010
[580]4011
4012
4013void KdViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
4014                                                                                                vector<MergeCandidate> &candidates)
4015{
4016        // TODO
4017}
4018
[1021]4019
4020
[503]4021/**************************************************************************/
4022/*                   VspBspViewCellsManager implementation                */
4023/**************************************************************************/
[482]4024
[503]4025
[1264]4026VspBspViewCellsManager::VspBspViewCellsManager(ViewCellsTree *vcTree, VspBspTree *vspBspTree):
4027ViewCellsManager(vcTree), mVspBspTree(vspBspTree)
[442]4028{
[1004]4029        Environment::GetSingleton()->GetIntValue("VspBspTree.Construction.samples", mInitialSamples);
[478]4030        mVspBspTree->SetViewCellsManager(this);
[590]4031        mVspBspTree->mViewCellsTree = mViewCellsTree;
[442]4032}
4033
[477]4034
[475]4035VspBspViewCellsManager::~VspBspViewCellsManager()
4036{
4037}
4038
[477]4039
[471]4040float VspBspViewCellsManager::GetProbability(ViewCell *viewCell)
[468]4041{
[551]4042        if (0 && mVspBspTree->mUseAreaForPvs)
[547]4043                return GetArea(viewCell) / GetAccVcArea();
4044        else
4045                return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
[468]4046}
4047
[477]4048
[480]4049void VspBspViewCellsManager::CollectViewCells()
4050{
[1545]4051        // view cells tree constructed?
[581]4052        if (!ViewCellsTreeConstructed())
4053        {
[590]4054                mVspBspTree->CollectViewCells(mViewCells, false);
[581]4055        }
4056        else
[1264]4057        {       
4058                // we can use the view cells tree hierarchy to get the right set
[600]4059                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
[581]4060        }
[480]4061}
4062
4063
[1021]4064void VspBspViewCellsManager::CollectMergeCandidates(const VssRayContainer &rays,
4065                                                                                                        vector<MergeCandidate> &candidates)
4066{       
4067        cout << "collecting merge candidates ... " << endl;
4068
4069        if (mUseRaysForMerge)
4070        {
4071                mVspBspTree->CollectMergeCandidates(rays, candidates);
4072        }
4073        else
4074        {
4075                vector<BspLeaf *> leaves;
4076                mVspBspTree->CollectLeaves(leaves);
4077       
4078                mVspBspTree->CollectMergeCandidates(leaves, candidates);
4079        }
4080
4081        cout << "fininshed collecting candidates" << endl;
4082}
4083
4084
[442]4085bool VspBspViewCellsManager::ViewCellsConstructed() const
4086{
4087        return mVspBspTree->GetRoot() != NULL;
4088}
4089
[462]4090
[442]4091ViewCell *VspBspViewCellsManager::GenerateViewCell(Mesh *mesh) const
4092{
4093        return new BspViewCell(mesh);
4094}
4095
[569]4096
[574]4097int VspBspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
[600]4098                                                                                                 const VssRayContainer &rays)
[442]4099{
[710]4100        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
4101
[503]4102        // if view cells were already constructed
4103        if (ViewCellsConstructed())
[1545]4104        {
[503]4105                return 0;
[1545]4106        }
[442]4107
[503]4108        int sampleContributions = 0;
4109        VssRayContainer sampleRays;
4110
[1545]4111        const int limit = min(mInitialSamples, (int)rays.size());
[503]4112
[660]4113        Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
[664]4114                  << ", actual rays: " << (int)rays.size() << endl;
[587]4115
[1545]4116        VssRayContainer savedRays;
[487]4117
[1545]4118        if (SAMPLE_AFTER_SUBDIVISION)
4119        {
4120                VssRayContainer constructionRays;
4121               
4122                GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
[485]4123
[1545]4124                Debug << "rays used for initial construction: " << (int)constructionRays.size() << endl;
4125                Debug << "rays saved for later use: " << (int)savedRays.size() << endl;
4126       
[667]4127                mVspBspTree->Construct(constructionRays, &mViewSpaceBox);
[1221]4128        }
[666]4129        else
[1221]4130        {
[1545]4131                Debug << "rays used for initial construction: " << (int)rays.size() << endl;
[667]4132                mVspBspTree->Construct(rays, &mViewSpaceBox);
[1221]4133        }
[667]4134
[490]4135        // collapse invalid regions
[491]4136        cout << "collapsing invalid tree regions ... ";
[1545]4137        long startTime = GetTime();
4138
[1002]4139        const int collapsedLeaves = mVspBspTree->CollapseTree();
[587]4140        Debug << "collapsed in " << TimeDiff(startTime, GetTime()) * 1e-3
4141                  << " seconds" << endl;
4142
[495]4143    cout << "finished" << endl;
[503]4144
[1444]4145        /////////////////
[1221]4146        //-- stats after construction
4147
[660]4148        Debug << mVspBspTree->GetStatistics() << endl;
4149
[480]4150        ResetViewCells();
[660]4151        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
[503]4152
[491]4153
[1444]4154        //////////////////////
[1545]4155        //-- recast the rest of the rays
[1570]4156
[495]4157        startTime = GetTime();
[503]4158
[491]4159        cout << "Computing remaining ray contributions ... ";
[605]4160
4161        if (SAMPLE_AFTER_SUBDIVISION)
4162                ComputeSampleContributions(savedRays, true, false);
[752]4163
[491]4164        cout << "finished" << endl;
4165
[503]4166        Debug << "Computed remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[485]4167                  << " secs" << endl;
[442]4168
[485]4169        cout << "construction finished" << endl;
[503]4170
[719]4171        if (0)
[1545]4172        {       ////////
[1077]4173                //-- real meshes are contructed at this stage
[719]4174                cout << "finalizing view cells ... ";
4175                FinalizeViewCells(true);
4176                cout << "finished" << endl;
4177        }
4178
[442]4179        return sampleContributions;
4180}
4181
[489]4182
[503]4183void VspBspViewCellsManager::MergeViewCells(const VssRayContainer &rays,
4184                                                                                        const ObjectContainer &objects)
[475]4185{
[442]4186    int vcSize = 0;
4187        int pvsSize = 0;
4188
[650]4189        //-- merge view cells
4190        cout << "starting merge using " << mPostProcessSamples << " samples ... " << endl;
4191        long startTime = GetTime();
4192
4193
[597]4194        if (mMergeViewCells)
4195        {
4196                // TODO: should be done BEFORE the ray casting
[710]4197                // compute tree by merging the nodes based on cost heuristics
[650]4198                mViewCellsTree->ConstructMergeTree(rays, objects);
4199        }
4200        else
4201        {
[710]4202                // compute tree by merging the nodes of the spatial hierarchy
4203                ViewCell *root = ConstructSpatialMergeTree(mVspBspTree->GetRoot());
4204                mViewCellsTree->SetRoot(root);
[752]4205
4206                // compute pvs
4207                ObjectPvs pvs;
4208                UpdatePvsForEvaluation(root, pvs);
[650]4209        }
[442]4210
[666]4211        if (1)
4212        {
4213                char mstats[100];
[752]4214                ObjectPvs pvs;
4215
[1004]4216                Environment::GetSingleton()->GetStringValue("ViewCells.mergeStats", mstats);
[666]4217                mViewCellsTree->ExportStats(mstats);
4218        }
[485]4219
[650]4220        cout << "merged view cells in "
4221                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
[503]4222
[650]4223        Debug << "Postprocessing: Merged view cells in "
4224                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
4225       
4226
[1444]4227        //////////////////
4228        //-- stats and visualizations
4229
[600]4230        int savedColorCode = mColorCode;
4231       
[660]4232        // get currently active view cell set
4233        ResetViewCells();
4234        Debug << "\nView cells after merge:\n" << mCurrentViewCellsStats << endl;
[1444]4235       
[1616]4236        if (mShowVisualization) // export merged view cells
[483]4237        {
[600]4238                mColorCode = 0;
[744]4239                Exporter *exporter = Exporter::GetExporter("merged_view_cells.wrl");
[660]4240               
[485]4241                cout << "exporting view cells after merge ... ";
4242
4243                if (exporter)
[483]4244                {
[600]4245                        if (0)
4246                                exporter->SetWireframe();
4247                        else
4248                                exporter->SetFilled();
4249
[1416]4250                        ExportViewCellsForViz(exporter, NULL, GetClipPlane());
[600]4251
[485]4252                        if (mExportGeometry)
[483]4253                        {
[485]4254                                Material m;
4255                                m.mDiffuseColor = RgbColor(0, 1, 0);
4256                                exporter->SetForcedMaterial(m);
4257                                exporter->SetFilled();
[442]4258
[485]4259                                exporter->ExportGeometry(objects);
[442]4260                        }
[485]4261
[600]4262                        delete exporter;
4263                }
4264                cout << "finished" << endl;
4265        }
4266
[1616]4267        if (mShowVisualization)
[600]4268        {
[1416]4269                // use pvs size for color coding
4270                mColorCode = 1;
[744]4271                Exporter *exporter = Exporter::GetExporter("merged_view_cells_pvs.wrl");
[1176]4272
[600]4273                cout << "exporting view cells after merge (pvs size) ... ";     
4274
4275                if (exporter)
4276                {
[1416]4277                        exporter->SetFilled();
[598]4278
[1416]4279                        ExportViewCellsForViz(exporter, NULL, GetClipPlane());
[598]4280
[600]4281                        if (mExportGeometry)
4282                        {
4283                                Material m;
4284                                m.mDiffuseColor = RgbColor(0, 1, 0);
4285                                exporter->SetForcedMaterial(m);
4286                                exporter->SetFilled();
4287
4288                                exporter->ExportGeometry(objects);
4289                        }
4290
[485]4291                        delete exporter;
[442]4292                }
[485]4293                cout << "finished" << endl;
[442]4294        }
[600]4295
4296        mColorCode = savedColorCode;
[503]4297}
[475]4298
[503]4299
[564]4300void VspBspViewCellsManager::RefineViewCells(const VssRayContainer &rays,
4301                                                                                         const ObjectContainer &objects)
[503]4302{
[485]4303        mRenderer->RenderScene();
[1616]4304
[503]4305        SimulationStatistics ss;
[485]4306        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
[1415]4307    Debug << "render time before refine\n\n" << ss << endl;
[485]4308
[1414]4309        const long startTime = GetTime();
[489]4310        cout << "Refining the merged view cells ... ";
[485]4311
4312        // refining the merged view cells
[580]4313        const int refined = mViewCellsTree->RefineViewCells(rays, objects);
[485]4314
[442]4315        //-- stats and visualizations
4316        cout << "finished" << endl;
[485]4317        cout << "refined " << refined << " view cells in "
[442]4318                 << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
4319
[485]4320        Debug << "Postprocessing: refined " << refined << " view cells in "
[475]4321                  << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl << endl;
[503]4322}
[495]4323
[517]4324
[503]4325int VspBspViewCellsManager::PostProcess(const ObjectContainer &objects,
4326                                                                                const VssRayContainer &rays)
[840]4327{
[503]4328        if (!ViewCellsConstructed())
4329        {
[517]4330                Debug << "postprocess error: no view cells constructed" << endl;
[503]4331                return 0;
4332        }
[520]4333
[609]4334        // view cells already finished before post processing step
4335        // (i.e. because they were loaded)
[520]4336        if (mViewCellsFinished)
[542]4337        {
[551]4338                FinalizeViewCells(true);
[542]4339                EvaluateViewCellsStats();
[577]4340
[517]4341                return 0;
[542]4342        }
[448]4343
[710]4344        // check if new view cells turned invalid
4345        int minPvs, maxPvs;
[564]4346
[710]4347        if (0)
4348        {
4349                minPvs = mMinPvsSize;
4350                maxPvs = mMaxPvsSize;
4351        }
4352        else
4353        {
[1414]4354                // problem matt: why did I start here from zero?
4355                minPvs = 0;
[710]4356                maxPvs = mMaxPvsSize;
4357        }
[720]4358
[710]4359        Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
4360        cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
4361       
4362        SetValidity(minPvs, maxPvs);
4363
[574]4364        // update valid view space according to valid view cells
[720]4365        if (0) mVspBspTree->ValidateTree();
[542]4366
[720]4367        // area has to be recomputed
[574]4368        mTotalAreaValid = false;
[517]4369        VssRayContainer postProcessRays;
[605]4370        GetRaySets(rays, mPostProcessSamples, postProcessRays);
4371
[517]4372        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
[564]4373
[1414]4374        // should maybe be done here to allow merge working
4375        // with area or volume and to correct the rendering statistics
[719]4376        if (0) FinalizeViewCells(false);
[720]4377               
[1444]4378        //////////
[597]4379        //-- merge the individual view cells
4380        MergeViewCells(postProcessRays, objects);
[591]4381       
[1444]4382        // refines the merged view cells
[720]4383        if (0) RefineViewCells(postProcessRays, objects);
[568]4384
[1444]4385
4386        ///////////
[660]4387        //-- render simulation after merge + refine
[1414]4388
[1415]4389        cout << "\nview cells partition render time before compress" << endl << endl;;
[605]4390        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
4391        SimulationStatistics ss;
4392        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
[1486]4393        cout << ss << endl;
[1414]4394       
[600]4395
[1418]4396        ////////////
[600]4397        //-- compression
[1586]4398//#if HAS_TO_BE_REDONE
[600]4399        if (ViewCellsTreeConstructed() && mCompressViewCells)
4400        {
[1586]4401                int pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
[600]4402                Debug << "number of entries before compress: " << pvsEntries << endl;
4403
[752]4404                mViewCellsTree->SetViewCellsStorage(ViewCellsTree::COMPRESSED);
[600]4405
[1586]4406                pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
[600]4407                Debug << "number of entries after compress: " << pvsEntries << endl;
4408        }
[1586]4409//#endif
[600]4410
[517]4411        // collapse sibling leaves that share the same view cell
[840]4412        if (0) mVspBspTree->CollapseTree();
[586]4413
[574]4414        // recompute view cell list and statistics
[520]4415        ResetViewCells();
4416
[719]4417        // compute final meshes and volume / area
4418        if (1) FinalizeViewCells(true);
[1444]4419
[503]4420        return 0;
[442]4421}
4422
[490]4423
[442]4424int VspBspViewCellsManager::GetType() const
4425{
4426        return VSP_BSP;
4427}
4428
4429
[650]4430ViewCell *VspBspViewCellsManager::ConstructSpatialMergeTree(BspNode *root)
[609]4431{
[752]4432        // terminate recursion
[650]4433        if (root->IsLeaf())
4434        {
[752]4435                BspLeaf *leaf = dynamic_cast<BspLeaf *>(root);
4436                leaf->GetViewCell()->SetMergeCost(0.0f);
4437                return leaf->GetViewCell();
[650]4438        }
4439       
[752]4440       
[650]4441        BspInterior *interior = dynamic_cast<BspInterior *>(root);
4442        ViewCellInterior *viewCellInterior = new ViewCellInterior();
4443               
[752]4444        // evaluate merge cost for priority traversal
[650]4445        float mergeCost = 1.0f / (float)root->mTimeStamp;
4446        viewCellInterior->SetMergeCost(mergeCost);
[610]4447
[650]4448        float volume = 0;
4449       
4450        BspNode *front = interior->GetFront();
4451        BspNode *back = interior->GetBack();
[649]4452
[752]4453
4454        ObjectPvs frontPvs, backPvs;
4455
4456        //-- recursivly compute child hierarchies
[650]4457        ViewCell *backVc = ConstructSpatialMergeTree(back);
4458        ViewCell *frontVc = ConstructSpatialMergeTree(front);
[610]4459
[752]4460
4461        viewCellInterior->SetupChildLink(backVc);
[650]4462        viewCellInterior->SetupChildLink(frontVc);
4463
4464        volume += backVc->GetVolume();
4465        volume += frontVc->GetVolume();
4466
4467        viewCellInterior->SetVolume(volume);
4468
4469        return viewCellInterior;
[609]4470}
4471
4472
[490]4473bool VspBspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
4474{
4475        if (!ViewCellsConstructed())
4476                return ViewCellsManager::GetViewPoint(viewPoint);
4477
4478        // TODO: set reasonable limit
4479        const int limit = 20;
4480
4481        for (int i = 0; i < limit; ++ i)
4482        {
[542]4483                viewPoint = mViewSpaceBox.GetRandomPoint();
[490]4484                if (mVspBspTree->ViewPointValid(viewPoint))
4485                {
4486                        return true;
4487                }
4488        }
[997]4489
[490]4490        Debug << "failed to find valid view point, taking " << viewPoint << endl;
4491        return false;
4492}
4493
4494
4495bool VspBspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
4496{
[1551]4497        // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
4498        // validy update in preprocessor for all managers)
4499        return ViewCellsManager::ViewPointValid(viewPoint);
[570]4500
[1551]4501        //      return mViewSpaceBox.IsInside(viewPoint) &&
4502        //                 mVspBspTree->ViewPointValid(viewPoint);
[490]4503}
4504
4505
[442]4506void VspBspViewCellsManager::Visualize(const ObjectContainer &objects,
[466]4507                                                                           const VssRayContainer &sampleRays)
[442]4508{
4509        if (!ViewCellsConstructed())
4510                return;
4511
[485]4512        VssRayContainer visRays;
4513        GetRaySets(sampleRays, mVisualizationSamples, visRays);
[1416]4514       
[1551]4515        if (1)
[1047]4516        {       
[1416]4517                //////////////////
4518                //-- export final view cell partition
4519
[1020]4520                Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
[600]4521               
[442]4522                if (exporter)
4523                {
[580]4524                        cout << "exporting view cells after post process ... ";
[600]4525                        if (0)
[1563]4526                        {       // export view space box
[542]4527                                exporter->SetWireframe();
4528                                exporter->ExportBox(mViewSpaceBox);
4529                                exporter->SetFilled();
4530                        }
4531
[1052]4532                        Material m;
4533                        m.mDiffuseColor.r = 0.0f;
4534                        m.mDiffuseColor.g = 0.5f;
4535                        m.mDiffuseColor.b = 0.5f;
4536
4537            exporter->SetForcedMaterial(m);
4538
[1563]4539                        if (1 && mExportGeometry)
[542]4540                        {
[485]4541                                exporter->ExportGeometry(objects);
[542]4542                        }
[489]4543
[1047]4544                        if (0 && mExportRays)
[489]4545                        {
[1052]4546                                exporter->ExportRays(visRays, RgbColor(1, 0, 0));
[490]4547                        }
[1416]4548                        ExportViewCellsForViz(exporter, NULL, GetClipPlane());
[1020]4549
[442]4550                        delete exporter;
[580]4551                        cout << "finished" << endl;
[442]4552                }
[557]4553        }
[503]4554
[1551]4555        ////////////////
[442]4556        //-- visualization of the BSP splits
[1551]4557
[442]4558        bool exportSplits = false;
[1004]4559        Environment::GetSingleton()->GetBoolValue("VspBspTree.Visualization.exportSplits", exportSplits);
[503]4560
[442]4561        if (exportSplits)
4562        {
4563                cout << "exporting splits ... ";
[485]4564                ExportSplits(objects, visRays);
[442]4565                cout << "finished" << endl;
4566        }
4567
[1551]4568        ////////
[542]4569        //-- export single view cells
[1570]4570       
4571        int leafOut;
4572        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
4573        const int raysOut = 100;
4574       
4575        ExportSingleViewCells(objects, leafOut, false, true, false, raysOut, "");
[442]4576}
4577
[503]4578
[485]4579void VspBspViewCellsManager::ExportSplits(const ObjectContainer &objects,
4580                                                                                  const VssRayContainer &rays)
[442]4581{
4582        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
4583
[503]4584        if (exporter)
4585        {
4586                Material m;
[442]4587                m.mDiffuseColor = RgbColor(1, 0, 0);
4588                exporter->SetForcedMaterial(m);
4589                exporter->SetWireframe();
[503]4590
[448]4591                exporter->ExportBspSplits(*mVspBspTree, true);
[442]4592
4593                // take forced material, else big scenes cannot be viewed
4594                m.mDiffuseColor = RgbColor(0, 1, 0);
4595                exporter->SetForcedMaterial(m);
4596                exporter->SetFilled();
4597
4598                exporter->ResetForcedMaterial();
[503]4599
[442]4600                // export rays
[485]4601                if (mExportRays)
[1545]4602                {
[485]4603                        exporter->ExportRays(rays, RgbColor(1, 1, 0));
[1545]4604                }
[503]4605
[485]4606                if (mExportGeometry)
[1545]4607                {
[442]4608                        exporter->ExportGeometry(objects);
[1545]4609                }
[442]4610                delete exporter;
4611        }
4612}
4613
[503]4614
[1570]4615void VspBspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
4616                                                                                                   const int maxViewCells,
4617                                                                                                   const bool sortViewCells,
4618                                                                                                   const bool exportPvs,
4619                                                                                                   const bool exportRays,
4620                                                                                                   const int maxRays,
4621                                                                                                   const string prefix,
4622                                                                                                   VssRayContainer *visRays)
4623{       
[694]4624        if (sortViewCells)
[801]4625        {
[1570]4626                // sort view cells to visualize the largest view cells
[801]4627                stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
4628        }
4629
[1566]4630        //////////
[1570]4631        //-- some view cells for output
[483]4632
[1570]4633        ViewCell::NewMail();
4634        const int limit = min(maxViewCells, (int)mViewCells.size());
4635       
[478]4636        for (int i = 0; i < limit; ++ i)
[442]4637        {
[478]4638                cout << "creating output for view cell " << i << " ... ";
[503]4639
[1570]4640                ViewCell *vc = sortViewCells ? // largest view cell pvs first?
4641                        mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 0.5f)] : mViewCells[i];
[442]4642
[1570]4643                if (vc->Mailed() || vc->GetId() == OUT_OF_BOUNDS_ID)
4644                        continue;
4645
4646                vc->Mail();
4647
[801]4648                ObjectPvs pvs;
4649                mViewCellsTree->GetPvs(vc, pvs);
4650
[1570]4651                char s[64]; sprintf(s, "%sviewcell%04d.wrl", prefix.c_str(), i);
[639]4652                Exporter *exporter = Exporter::GetExporter(s);
4653               
[1709]4654                const float pvsCost = mViewCellsTree->GetPvsCost(vc);
4655                cout << "view cell " << vc->GetId() << ": pvs cost=" << pvsCost << endl;
[587]4656
[1570]4657                if (exportRays)
[442]4658                {
[1566]4659                        ////////////
4660                        //-- export rays piercing this view cell
4661
4662                        // take rays stored with the view cells during subdivision
[1551]4663                        VssRayContainer vcRays;
4664            VssRayContainer collectRays;
[639]4665
[1566]4666                        // collect initial view cells
[1551]4667                        ViewCellContainer leaves;
4668                        mViewCellsTree->CollectLeaves(vc, leaves);
[639]4669
[1551]4670                        ViewCellContainer::const_iterator vit, vit_end = leaves.end();
[1566]4671                for (vit = leaves.begin(); vit != vit_end; ++ vit)
[1570]4672                        {       
[1551]4673                                BspLeaf *vcLeaf = dynamic_cast<BspViewCell *>(*vit)->mLeaves[0];
4674                                VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
[587]4675
[1551]4676                                for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
[639]4677                                {
[1551]4678                                        collectRays.push_back(*rit);
[639]4679                                }
[1551]4680                        }
[801]4681
[1570]4682                        const int raysOut = min((int)collectRays.size(), maxRays);
[1571]4683               
[1566]4684                        // prepare some rays for output
[1551]4685                        VssRayContainer::const_iterator rit, rit_end = collectRays.end();
4686                        for (rit = collectRays.begin(); rit != rit_end; ++ rit)
[639]4687                        {
[1566]4688                                const float p = RandomValue(0.0f, (float)collectRays.size());
[1551]4689                       
4690                                if (p < raysOut)
[1566]4691                                {
[1551]4692                                        vcRays.push_back(*rit);
[1566]4693                                }
[639]4694                        }
4695
[1551]4696                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
[442]4697                }
[639]4698               
[1416]4699                ////////////////
[1020]4700                //-- export view cell geometry
[1416]4701
[478]4702                exporter->SetWireframe();
[442]4703
[478]4704                Material m;//= RandomMaterial();
4705                m.mDiffuseColor = RgbColor(0, 1, 0);
4706                exporter->SetForcedMaterial(m);
[442]4707
[1416]4708                ExportViewCellGeometry(exporter, vc, NULL, NULL);
[639]4709                exporter->SetFilled();
[503]4710
[1570]4711                if (exportPvs)
[574]4712                {
[801]4713                        Intersectable::NewMail();
[1570]4714
[1742]4715                        ObjectPvsIterator pit = pvs.GetIterator();
4716
[1570]4717                        cout << endl;
[1742]4718
[639]4719                        // output PVS of view cell
[1742]4720                        while (pit.HasMoreEntries())
4721                        {
4722                                ObjectPvsEntry entry = pit.Next();             
4723                                Intersectable *intersect = entry.mObject;
[1570]4724                               
[639]4725                                if (!intersect->Mailed())
4726                                {
[1570]4727                                        intersect->Mail();
[1571]4728
[643]4729                                        m = RandomMaterial();
4730                                        exporter->SetForcedMaterial(m);
[639]4731                                        exporter->ExportIntersectable(intersect);
4732                                }
[503]4733                        }
[1570]4734                        cout << endl;
[442]4735                }
[801]4736               
[478]4737                DEL_PTR(exporter);
4738                cout << "finished" << endl;
[442]4739        }
4740}
4741
4742
[1021]4743void VspBspViewCellsManager::TestFilter(const ObjectContainer &objects)
[697]4744{
[1021]4745        Exporter *exporter = Exporter::GetExporter("filter.x3d");
[697]4746
[1021]4747        Vector3 bsize = mViewSpaceBox.Size();
4748        const Vector3 viewPoint(mViewSpaceBox.Center());
4749        float w = Magnitude(mViewSpaceBox.Size()) * mFilterWidth;
4750        const Vector3 width = Vector3(w);
4751       
4752        PrVs testPrVs;
4753       
4754        if (exporter)
4755        {
4756                ViewCellContainer viewCells;
4757       
4758        const AxisAlignedBox3 tbox = GetFilterBBox(viewPoint, mFilterWidth);
[697]4759
[1021]4760                GetPrVS(viewPoint, testPrVs, GetFilterWidth());
[482]4761
[1021]4762                exporter->SetWireframe();
[482]4763
[1021]4764                exporter->SetForcedMaterial(RgbColor(1,1,1));
4765                exporter->ExportBox(tbox);
4766               
4767                exporter->SetFilled();
[503]4768
[1021]4769                exporter->SetForcedMaterial(RgbColor(0,1,0));
[1416]4770                ExportViewCellGeometry(exporter, GetViewCell(viewPoint), NULL, NULL);
[564]4771
[1021]4772                //exporter->ResetForcedMaterial();
4773                exporter->SetForcedMaterial(RgbColor(0,0,1));
[1416]4774                ExportViewCellGeometry(exporter, testPrVs.mViewCell, NULL, NULL);
[591]4775
[1021]4776        exporter->SetForcedMaterial(RgbColor(1,0,0));
4777                exporter->ExportGeometry(objects);
[547]4778
[1021]4779                delete exporter;
[482]4780        }
[1021]4781}
[482]4782
[547]4783
[1021]4784int VspBspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
4785                                                                                                        ViewCellContainer &viewCells) const
4786{
4787        return mVspBspTree->ComputeBoxIntersections(box, viewCells);
[482]4788}
4789
4790
[1021]4791int VspBspViewCellsManager::CastLineSegment(const Vector3 &origin,
4792                                                                                        const Vector3 &termination,
4793                                                                                        ViewCellContainer &viewcells)
4794{
4795        return mVspBspTree->CastLineSegment(origin, termination, viewcells);
4796}
4797
4798
[979]4799void VspBspViewCellsManager::VisualizeWithFromPointQueries()
4800{
4801        int numSamples;
[1161]4802       
[1004]4803        Environment::GetSingleton()->GetIntValue("RenderSampler.samples", numSamples);
[979]4804        cout << "samples" << numSamples << endl;
4805
4806        vector<RenderCostSample> samples;
4807 
[1145]4808        if (!mPreprocessor->GetRenderer())
[979]4809                return;
4810
[1145]4811        //start the view point queries
[979]4812        long startTime = GetTime();
4813        cout << "starting sampling of render cost ... ";
4814       
[1145]4815        mPreprocessor->GetRenderer()->SampleRenderCost(numSamples, samples, true);
[979]4816
4817        cout << "finished in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
4818
4819
[1161]4820        // for each sample:
4821        //    find view cells associated with the samples
4822        //    store the sample pvs with the pvs associated with the view cell
[1415]4823        //
[1161]4824        // for each view cell:
4825        //    compute difference point sampled pvs - view cell pvs
4826        //    export geometry with color coded pvs difference
4827       
4828    std::map<ViewCell *, ObjectPvs> sampleMap;
4829
[979]4830        vector<RenderCostSample>::const_iterator rit, rit_end = samples.end();
4831
[1161]4832        for (rit = samples.begin(); rit != rit_end; ++ rit)
4833        {
4834                RenderCostSample sample = *rit;
4835       
4836                ViewCell *vc = GetViewCell(sample.mPosition);
[991]4837
[1161]4838                std::map<ViewCell *, ObjectPvs>::iterator it = sampleMap.find(vc);
4839
4840                if (it == sampleMap.end())
4841                {
4842                        sampleMap[vc] = sample.mPvs;
4843                }
4844                else
4845                {
[1740]4846                        (*it).second.MergeInPlace(sample.mPvs);
[1161]4847                }
4848        }
4849
4850        // visualize the view cells
4851        std::map<ViewCell *, ObjectPvs>::const_iterator vit, vit_end = sampleMap.end();
4852
4853        Material m;//= RandomMaterial();
4854
4855        for (vit = sampleMap.begin(); vit != vit_end; ++ vit)
4856        {
4857                ViewCell *vc = (*vit).first;
4858               
4859                const int pvsVc = mViewCellsTree->GetPvsEntries(vc);
[1168]4860                const int pvsPtSamples = (*vit).second.GetSize();
[1161]4861
[1168]4862        m.mDiffuseColor.r = (float) (pvsVc - pvsPtSamples);
[1161]4863                m.mDiffuseColor.b = 1.0f;
4864                //exporter->SetForcedMaterial(m);
[1416]4865                //ExportViewCellGeometry(exporter, vc, mClipPlaneForViz);
[1161]4866
[1415]4867                /*      // counting the pvss
4868                for (rit = samples.begin(); rit != rit_end; ++ rit)
4869                {
4870                        RenderCostSample sample = *rit;
4871                        ViewCell *vc = GetViewCell(sample.mPosition);
[1161]4872
[1415]4873                        AxisAlignedBox3 box(sample.mPosition - Vector3(1, 1, 1), sample.mPosition + Vector3(1, 1, 1));
4874                        Mesh *hMesh = CreateMeshFromBox(box);
[1001]4875
[1415]4876                        DEL_PTR(hMesh);
4877                }
4878                */
[979]4879        }
4880}
4881
4882
[580]4883void VspBspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
[1416]4884                                                                                                        ViewCell *vc,
4885                                                                                                        const AxisAlignedBox3 *sceneBox,
4886                                                                                                        const AxisAlignedPlane *clipPlane
4887                                                                                                        ) const
[482]4888{
[660]4889        if (clipPlane)
[591]4890        {
[1047]4891                const Plane3 plane = clipPlane->GetPlane();
4892
[591]4893                ViewCellContainer leaves;
4894                mViewCellsTree->CollectLeaves(vc, leaves);
4895                ViewCellContainer::const_iterator it, it_end = leaves.end();
4896
4897                for (it = leaves.begin(); it != it_end; ++ it)
4898                {
4899                        BspNodeGeometry geom;
4900                        BspNodeGeometry front;
4901                        BspNodeGeometry back;
4902
[1551]4903                        mVspBspTree->ConstructGeometry(*it, geom);
[591]4904
[1052]4905                        const float eps = 0.0001f;
[1047]4906                        const int cf = geom.Side(plane, eps);
[682]4907
[710]4908                        if (cf == -1)
[682]4909                        {
4910                                exporter->ExportPolygons(geom.GetPolys());
4911                        }
[710]4912                        else if (cf == 0)
[684]4913                        {
[682]4914                                geom.SplitGeometry(front,
4915                                                                   back,
[1047]4916                                                                   plane,
[682]4917                                                                   mViewSpaceBox,
[710]4918                                                                   eps);
[801]4919
[683]4920                                if (back.Valid())
4921                                {
[682]4922                                        exporter->ExportPolygons(back.GetPolys());
[708]4923                                }                       
[684]4924                        }
[591]4925                }
4926        }
4927        else
4928        {
[801]4929                // export mesh if available
[1001]4930                // TODO: some bug here?
[1563]4931                if (1 && vc->GetMesh())
[801]4932                {
4933                        exporter->ExportMesh(vc->GetMesh());
4934                }
4935                else
[1001]4936                {
[801]4937                        BspNodeGeometry geom;
4938                        mVspBspTree->ConstructGeometry(vc, geom);
4939                        exporter->ExportPolygons(geom.GetPolys());
[1001]4940                }
[591]4941        }
[482]4942}
4943
4944
4945int VspBspViewCellsManager::GetMaxTreeDiff(ViewCell *vc) const
4946{
[580]4947        ViewCellContainer leaves;
4948        mViewCellsTree->CollectLeaves(vc, leaves);
[482]4949
4950        int maxDist = 0;
[580]4951       
[482]4952        // compute max height difference
[580]4953        for (int i = 0; i < (int)leaves.size(); ++ i)
[1001]4954        {
[580]4955                for (int j = 0; j < (int)leaves.size(); ++ j)
[1001]4956                {
[1551]4957                        BspLeaf *leaf = dynamic_cast<BspViewCell *>(leaves[i])->mLeaves[0];
[482]4958
[1001]4959                        if (i != j)
4960                        {
[1551]4961                                BspLeaf *leaf2 =dynamic_cast<BspViewCell *>(leaves[j])->mLeaves[0];
4962                                const int dist = mVspBspTree->TreeDistance(leaf, leaf2);
[1001]4963                               
4964                                if (dist > maxDist)
4965                                        maxDist = dist;
4966                        }
[482]4967                }
4968        }
[580]4969
[492]4970        return maxDist;
4971}
[482]4972
[492]4973
[879]4974ViewCell *VspBspViewCellsManager::GetViewCell(const Vector3 &point, const bool active) const
[492]4975{
[1021]4976        if (!ViewCellsConstructed())
[508]4977                return NULL;
[572]4978
4979        if (!mViewSpaceBox.IsInside(point))
4980          return NULL;
4981
[879]4982        return mVspBspTree->GetViewCell(point, active);
[492]4983}
[503]4984
4985
4986void VspBspViewCellsManager::CreateMesh(ViewCell *vc)
4987{
4988        BspNodeGeometry geom;
[590]4989        mVspBspTree->ConstructGeometry(vc, geom);
[582]4990       
[1001]4991        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
[840]4992        IncludeNodeGeomInMesh(geom, *mesh);
4993
[503]4994        vc->SetMesh(mesh);
4995}
[508]4996
4997
[532]4998int VspBspViewCellsManager::CastBeam(Beam &beam)
4999{
[535]5000        return mVspBspTree->CastBeam(beam);
[532]5001}
[551]5002
5003
[587]5004void VspBspViewCellsManager::Finalize(ViewCell *viewCell,
5005                                                                          const bool createMesh)
[551]5006{
5007        float area = 0;
5008        float volume = 0;
5009
[580]5010        ViewCellContainer leaves;
[582]5011        mViewCellsTree->CollectLeaves(viewCell, leaves);
[580]5012
5013        ViewCellContainer::const_iterator it, it_end = leaves.end();
5014
[693]5015    for (it = leaves.begin(); it != it_end; ++ it)
[551]5016        {
5017                BspNodeGeometry geom;
[1551]5018                mVspBspTree->ConstructGeometry(*it, geom);
[551]5019
[719]5020                const float lVol = geom.GetVolume();
5021                const float lArea = geom.GetArea();
[693]5022
5023                area += lArea;
5024                volume += lVol;
5025
[1616]5026                if (createMesh)
5027                        CreateMesh(*it);
[551]5028        }
5029
5030        viewCell->SetVolume(volume);
5031        viewCell->SetArea(area);
[563]5032}
[575]5033
5034
[693]5035void VspBspViewCellsManager::TestSubdivision()
5036{
5037        ViewCellContainer leaves;
5038        mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), leaves);
5039
5040        ViewCellContainer::const_iterator it, it_end = leaves.end();
5041
5042        const float vol = mViewSpaceBox.GetVolume();
5043        float subdivVol = 0;
5044        float newVol = 0;
5045
5046        for (it = leaves.begin(); it != it_end; ++ it)
5047        {
5048                BspNodeGeometry geom;
[1551]5049                mVspBspTree->ConstructGeometry(*it, geom);
[693]5050
5051                const float lVol = geom.GetVolume();
5052               
5053                newVol += lVol;
5054                subdivVol += (*it)->GetVolume();
[697]5055               
[704]5056                float thres = 0.9f;
[697]5057                if ((lVol < ((*it)->GetVolume() * thres)) || (lVol * thres > ((*it)->GetVolume())))
5058                        Debug << "warning: " << lVol << " " << (*it)->GetVolume() << endl;
[693]5059        }
5060       
5061        Debug << "exact volume: " << vol << endl;
5062        Debug << "subdivision volume: " << subdivVol << endl;
5063        Debug << "new volume: " << newVol << endl;
5064}
5065
5066
[577]5067void VspBspViewCellsManager::PrepareLoadedViewCells()
5068{
5069        // TODO: do I still need this here?
[590]5070        if (0)
[693]5071                mVspBspTree->RepairViewCellsLeafLists();
[577]5072}
[575]5073
[1021]5074
5075
5076/**************************************************************************/
[1047]5077/*                   VspOspViewCellsManager implementation                */
[1021]5078/**************************************************************************/
5079
5080
[1740]5081VspOspViewCellsManager::VspOspViewCellsManager(ViewCellsTree *vcTree, const string &hierarchyType)
5082: ViewCellsManager(vcTree)
5083{
5084        Environment::GetSingleton()->GetIntValue("Hierarchy.Construction.samples", mInitialSamples);
5085
5086        mHierarchyManager = CreateHierarchyManager(hierarchyType);
5087        mHierarchyManager->SetViewCellsManager(this);
5088        mHierarchyManager->SetViewCellsTree(mViewCellsTree);
5089}
5090
5091
[1278]5092VspOspViewCellsManager::VspOspViewCellsManager(ViewCellsTree *vcTree, HierarchyManager *hm)
5093: ViewCellsManager(vcTree), mHierarchyManager(hm)
[859]5094{
[1640]5095        Environment::GetSingleton()->GetIntValue("Hierarchy.Construction.samples", mInitialSamples);
[1106]5096
[1278]5097        mHierarchyManager->SetViewCellsManager(this);
5098        mHierarchyManager->SetViewCellsTree(mViewCellsTree);
[1021]5099}
[859]5100
[1743]5101Intersectable *
5102VspOspViewCellsManager::GetIntersectable(const VssRay &ray, const bool isTermination) const
5103{
5104  return mHierarchyManager->GetIntersectable(ray, isTermination);
5105}
[859]5106
[1740]5107HierarchyManager *VspOspViewCellsManager::CreateHierarchyManager(const string &hierarchyType)
5108{
5109        HierarchyManager *hierarchyManager;
5110
5111        if (strcmp(hierarchyType.c_str(), "osp") == 0)
5112        {
5113                Debug << "hierarchy manager: osp" << endl;
5114                hierarchyManager = new HierarchyManager(HierarchyManager::KD_BASED_OBJ_SUBDIV);
5115        }
5116        else if (strcmp(hierarchyType.c_str(), "bvh") == 0)
5117        {
5118                Debug << "hierarchy manager: bvh" << endl;
5119                hierarchyManager = new HierarchyManager(HierarchyManager::BV_BASED_OBJ_SUBDIV);
5120        }
5121        else // only view space partition
5122        {
5123                Debug << "hierarchy manager: obj" << endl;
5124                hierarchyManager = new HierarchyManager(HierarchyManager::NO_OBJ_SUBDIV);
5125        }
5126
5127        return hierarchyManager;
5128}
5129
5130
[1021]5131VspOspViewCellsManager::~VspOspViewCellsManager()
5132{
[1740]5133        DEL_PTR(mHierarchyManager);
[1021]5134}
5135
5136
5137float VspOspViewCellsManager::GetProbability(ViewCell *viewCell)
5138{
5139        return GetVolume(viewCell) / mViewSpaceBox.GetVolume();
5140}
5141
5142
5143void VspOspViewCellsManager::CollectViewCells()
5144{
5145        // view cells tree constructed
5146        if (!ViewCellsTreeConstructed())
5147        {
[1278]5148                mHierarchyManager->GetVspTree()->CollectViewCells(mViewCells, false);
[1021]5149        }
5150        else
5151        {       // we can use the view cells tree hierarchy to get the right set
5152                mViewCellsTree->CollectBestViewCellSet(mViewCells, mNumActiveViewCells);
5153        }
5154}
5155
5156
5157bool VspOspViewCellsManager::ViewCellsConstructed() const
5158{
[1278]5159        return mHierarchyManager->GetVspTree()->GetRoot() != NULL;
[1021]5160}
5161
5162
5163ViewCell *VspOspViewCellsManager::GenerateViewCell(Mesh *mesh) const
5164{
5165        return new VspViewCell(mesh);
5166}
5167
5168
5169int VspOspViewCellsManager::ConstructSubdivision(const ObjectContainer &objects,
5170                                                                                                 const VssRayContainer &rays)
5171{
5172        mMaxPvsSize = (int)(mMaxPvsRatio * (float)objects.size());
5173
[1074]5174        // skip rest if view cells were already constructed
[1021]5175        if (ViewCellsConstructed())
5176                return 0;
5177
5178        int sampleContributions = 0;
5179        VssRayContainer sampleRays;
5180
5181        int limit = min (mInitialSamples, (int)rays.size());
5182
5183        VssRayContainer constructionRays;
5184        VssRayContainer savedRays;
5185
5186        Debug << "samples used for vsp bsp subdivision: " << mInitialSamples
5187                  << ", actual rays: " << (int)rays.size() << endl;
5188
5189        GetRaySets(rays, mInitialSamples, constructionRays, &savedRays);
5190
[1421]5191        Debug << "initial rays used for construction: " << (int)constructionRays.size() << endl;
[1021]5192        Debug << "saved rays: " << (int)savedRays.size() << endl;
5193
[1293]5194        mHierarchyManager->Construct(constructionRays, objects, &mViewSpaceBox);
[1142]5195
[1576]5196#if TEST_EVALUATION
5197        VssRayContainer::const_iterator tit, tit_end = constructionRays.end();
5198        for (tit = constructionRays.begin(); tit != tit_end; ++ tit)
5199        {
5200                storedRays.push_back(new VssRay(*(*tit)));
5201        }
5202#endif
5203
[1545]5204        /////////////////////////
[1444]5205        //-- print satistics for subdivision and view cells
5206
[1421]5207        Debug << endl << endl << *mHierarchyManager << endl;
[1021]5208
[1444]5209        ResetViewCells();
5210        Debug << "\nView cells after construction:\n" << mCurrentViewCellsStats << endl;
5211
[1545]5212        //////////////
[1444]5213        //-- recast rest of rays
5214       
[1286]5215        const long startTime = GetTime();
[1021]5216        cout << "Computing remaining ray contributions ... ";
5217
5218        if (SAMPLE_AFTER_SUBDIVISION)
5219                ComputeSampleContributions(savedRays, true, false);
5220
[1415]5221        Debug << "finished computing remaining ray contribution in " << TimeDiff(startTime, GetTime()) * 1e-3
[1021]5222                  << " secs" << endl;
5223
5224        if (0)
[1545]5225        {       // real meshes are constructed at this stage
[1021]5226                cout << "finalizing view cells ... ";
5227                FinalizeViewCells(true);
5228                cout << "finished" << endl;
5229        }
5230
5231        return sampleContributions;
5232}
5233
5234
5235int VspOspViewCellsManager::PostProcess(const ObjectContainer &objects,
5236                                                                                const VssRayContainer &rays)
5237{
5238        if (!ViewCellsConstructed())
5239        {
5240                Debug << "postprocess error: no view cells constructed" << endl;
5241                return 0;
5242        }
5243
[1418]5244        // if view cells were already constructed before post processing step
5245        // (e.g., because they were loaded), we are finished
[1021]5246        if (mViewCellsFinished)
5247        {
5248                FinalizeViewCells(true);
5249                EvaluateViewCellsStats();
5250
5251                return 0;
5252        }
5253
5254        // check if new view cells turned invalid
5255        int minPvs, maxPvs;
5256
5257        if (0)
5258        {
5259                minPvs = mMinPvsSize;
5260                maxPvs = mMaxPvsSize;
5261        }
5262        else
5263        {
[1414]5264                // problem matt: why did I start here from zero?
5265                minPvs = 0;
[1021]5266                maxPvs = mMaxPvsSize;
5267        }
5268
5269        Debug << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
5270        cout << "setting validity, min: " << minPvs << " max: " << maxPvs << endl;
5271       
5272        SetValidity(minPvs, maxPvs);
5273
5274       
[1414]5275        // area is not up to date, has to be recomputed
[1021]5276        mTotalAreaValid = false;
5277        VssRayContainer postProcessRays;
5278        GetRaySets(rays, mPostProcessSamples, postProcessRays);
5279
5280        Debug << "post processing using " << (int)postProcessRays.size() << " samples" << endl;
5281
5282
5283        // compute tree by merging the nodes of the spatial hierarchy
[1278]5284        ViewCell *root = ConstructSpatialMergeTree(mHierarchyManager->GetVspTree()->GetRoot());
[1021]5285        mViewCellsTree->SetRoot(root);
5286
[1696]5287        //////////////////////////
5288        //-- update pvs up to the root of the hierarchy
[1418]5289
[1021]5290        ObjectPvs pvs;
5291        UpdatePvsForEvaluation(root, pvs);
5292
[1414]5293
[1418]5294        //////////////////////
[1021]5295        //-- render simulation after merge + refine
[1414]5296
[1415]5297        cout << "\nview cells partition render time before compress" << endl << endl;
[1021]5298        dynamic_cast<RenderSimulator *>(mRenderer)->RenderScene();
5299        SimulationStatistics ss;
5300        dynamic_cast<RenderSimulator *>(mRenderer)->GetStatistics(ss);
5301        cout << ss << endl;
[1414]5302       
[1486]5303
[1586]5304        ///////////
[1021]5305        //-- compression
[1262]5306
[1021]5307        if (ViewCellsTreeConstructed() && mCompressViewCells)
5308        {
[1586]5309                int pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
[1021]5310                Debug << "number of entries before compress: " << pvsEntries << endl;
[859]5311
[1021]5312                mViewCellsTree->SetViewCellsStorage(ViewCellsTree::COMPRESSED);
[859]5313
[1586]5314                pvsEntries = mViewCellsTree->CountStoredPvsEntries(mViewCellsTree->GetRoot());
[1021]5315                Debug << "number of entries after compress: " << pvsEntries << endl;
[859]5316        }
[1021]5317
[1486]5318        /////////////
5319        //-- some tasks still to do on the view cells:
5320        //-- Compute meshes from view cell geometry, evaluate volume and / or area
[1696]5321
[1021]5322        if (1) FinalizeViewCells(true);
5323
5324        return 0;
[859]5325}
5326
[1021]5327
5328int VspOspViewCellsManager::GetType() const
[884]5329{
[1021]5330        return VSP_OSP;
5331}
[859]5332
[1021]5333
5334ViewCell *VspOspViewCellsManager::ConstructSpatialMergeTree(VspNode *root)
5335{
5336        // terminate recursion
5337        if (root->IsLeaf())
5338        {
5339                VspLeaf *leaf = dynamic_cast<VspLeaf *>(root);
5340                leaf->GetViewCell()->SetMergeCost(0.0f);
5341                return leaf->GetViewCell();
5342        }
5343       
5344        VspInterior *interior = dynamic_cast<VspInterior *>(root);
5345        ViewCellInterior *viewCellInterior = new ViewCellInterior();
5346               
5347        // evaluate merge cost for priority traversal
[1713]5348        const float mergeCost = -(float)root->mTimeStamp;
[1021]5349        viewCellInterior->SetMergeCost(mergeCost);
5350
5351        float volume = 0;
5352       
5353        VspNode *front = interior->GetFront();
5354        VspNode *back = interior->GetBack();
5355
5356        ObjectPvs frontPvs, backPvs;
5357
[1545]5358        /////////
[1021]5359        //-- recursivly compute child hierarchies
[1545]5360
[1021]5361        ViewCell *backVc = ConstructSpatialMergeTree(back);
5362        ViewCell *frontVc = ConstructSpatialMergeTree(front);
5363
5364        viewCellInterior->SetupChildLink(backVc);
5365        viewCellInterior->SetupChildLink(frontVc);
5366
5367        volume += backVc->GetVolume();
5368        volume += frontVc->GetVolume();
5369
5370        viewCellInterior->SetVolume(volume);
5371
5372        return viewCellInterior;
5373}
5374
5375
5376bool VspOspViewCellsManager::GetViewPoint(Vector3 &viewPoint) const
5377{
5378        if (!ViewCellsConstructed())
5379                return ViewCellsManager::GetViewPoint(viewPoint);
5380
5381        // TODO: set reasonable limit
5382        const int limit = 20;
5383
5384        for (int i = 0; i < limit; ++ i)
5385        {
5386                viewPoint = mViewSpaceBox.GetRandomPoint();
[1047]5387
[1278]5388                if (mHierarchyManager->GetVspTree()->ViewPointValid(viewPoint))
[1021]5389                {
5390                        return true;
5391                }
[904]5392        }
[859]5393
[1021]5394        Debug << "failed to find valid view point, taking " << viewPoint << endl;
5395        return false;
[884]5396}
5397
5398
[1027]5399void VspOspViewCellsManager::ExportViewCellGeometry(Exporter *exporter,
5400                                                                                                        ViewCell *vc,
[1416]5401                                                                                                        const AxisAlignedBox3 *sceneBox,
5402                                                                                                        const AxisAlignedPlane *clipPlane
5403                                                                                                        ) const
[1027]5404{
5405        ViewCellContainer leaves;
5406        mViewCellsTree->CollectLeaves(vc, leaves);
5407        ViewCellContainer::const_iterator it, it_end = leaves.end();
5408
[1047]5409        Plane3 plane;
5410        if (clipPlane)
[1418]5411        {
5412                // arbitrary plane definition
[1047]5413                plane = clipPlane->GetPlane();
[1418]5414        }
[1047]5415
[1027]5416        for (it = leaves.begin(); it != it_end; ++ it)
5417        {
5418                VspViewCell *vspVc = dynamic_cast<VspViewCell *>(*it);
[1551]5419                VspLeaf *l = vspVc->mLeaves[0];
[1027]5420
[1416]5421                const AxisAlignedBox3 box =
[1551]5422                        mHierarchyManager->GetVspTree()->GetBoundingBox(vspVc->mLeaves[0]);
[1047]5423               
[1418]5424                if (sceneBox && !Overlap(*sceneBox, box))
[1415]5425                        continue;
5426
[1047]5427                if (clipPlane)
5428                {
5429                        if (box.Side(plane) == -1)
[1144]5430                        {
[1047]5431                                exporter->ExportBox(box);
[1144]5432                        }
[1047]5433                        else if (box.Side(plane) == 0)
5434                        {
[1418]5435                                // intersection
[1047]5436                                AxisAlignedBox3 fbox, bbox;
[1418]5437                                box.Split(clipPlane->mAxis, clipPlane->mPosition, fbox, bbox);
[1047]5438                                exporter->ExportBox(bbox);
5439                        }
5440                }
5441                else
5442                {
[1027]5443                        exporter->ExportBox(box);
[1047]5444                }
[1027]5445        }
5446}
5447
5448
[1021]5449bool VspOspViewCellsManager::ViewPointValid(const Vector3 &viewPoint) const
5450{
5451  // $$JB -> implemented in viewcellsmanager (slower, but allows dynamic
5452  // validy update in preprocessor for all managers)
5453  return ViewCellsManager::ViewPointValid(viewPoint);
[884]5454
[1021]5455  //    return mViewSpaceBox.IsInside(viewPoint) &&
[1027]5456  //               mVspTree->ViewPointValid(viewPoint);
[1021]5457}
5458
5459
5460void VspOspViewCellsManager::Visualize(const ObjectContainer &objects,
5461                                                                           const VssRayContainer &sampleRays)
[859]5462{
[997]5463        if (!ViewCellsConstructed())
5464                return;
[1027]5465
[1021]5466        VssRayContainer visRays;
5467        GetRaySets(sampleRays, mVisualizationSamples, visRays);
[997]5468
[1633]5469        ////////////
5470        //-- export final view cells
[1106]5471
[1633]5472        Exporter *exporter = Exporter::GetExporter("final_view_cells.wrl");
5473
5474        if (exporter)
5475        {
[1415]5476                // hack color code (show pvs size)
[1021]5477                const int savedColorCode = mColorCode;
[1047]5478                mColorCode = 0;
[859]5479
[1633]5480                const long starttime = GetTime();
5481                cout << "exporting final view cells (after initial construction + post process) ... ";
[1420]5482
[1633]5483                // matt: hack for clamping scene
5484                AxisAlignedBox3 bbox = mViewSpaceBox;
5485                bbox.Scale(Vector3(0.5, 1, 0.5));
[1703]5486
[1633]5487                if (CLAMP_TO_BOX)
5488                {       
5489                        exporter->SetWireframe();
5490                        exporter->ExportBox(bbox);
5491                        exporter->SetFilled();
[1021]5492                }
5493
[1633]5494                if (0 && mExportGeometry)
5495                {
5496                        exporter->ExportGeometry(objects, true, CLAMP_TO_BOX ? &bbox : NULL);
5497                }
5498
5499                if (1 && mExportRays)
5500                {       
5501                        exporter->ExportRays(visRays, RgbColor(0, 1, 0));
5502                }
5503
[1703]5504                mHierarchyManager->ExportObjectSpaceHierarchy(exporter,
5505                                objects, CLAMP_TO_BOX ? &bbox : NULL, false);
[1633]5506                ExportViewCellsForViz(exporter, CLAMP_TO_BOX ? &bbox : NULL, GetClipPlane());
5507
5508                delete exporter;
5509                cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3f << " secs" << endl;
[1021]5510                mColorCode = savedColorCode;
5511        }
5512
[1633]5513        // export final object partition
5514        exporter = Exporter::GetExporter("final_object_partition.wrl");
5515
5516        if (exporter)
[1287]5517        {
[1633]5518                const long starttime = GetTime();
[1287]5519
[1633]5520                // matt: hack for making visualization smaller in size
5521                AxisAlignedBox3 bbox = mHierarchyManager->GetObjectSpaceBox();
5522                bbox.Scale(Vector3(0.5, 1, 0.5));
[1415]5523
[1633]5524                cout << "exporting object space hierarchy ... ";
5525                mHierarchyManager->ExportObjectSpaceHierarchy(exporter, objects, CLAMP_TO_BOX ? &bbox : NULL);
5526
5527                delete exporter;
5528                cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3f << " secs" << endl;
[1287]5529        }
[1633]5530
[1121]5531       
[1633]5532        //  visualization of the view cells
5533        if (0) ExportMergedViewCells(objects);
5534
[1570]5535        // export some view cell
[1021]5536        int leafOut;
5537        Environment::GetSingleton()->GetIntValue("ViewCells.Visualization.maxOutput", leafOut);
[1570]5538        const int raysOut = 100;
[580]5539
[1570]5540        ExportSingleViewCells(objects, leafOut, false, true, false, raysOut, "");
5541}
[1021]5542
5543
[1570]5544void VspOspViewCellsManager::ExportSingleViewCells(const ObjectContainer &objects,
5545                                                                                                   const int maxViewCells,
5546                                                                                                   const bool sortViewCells,
5547                                                                                                   const bool exportPvs,
5548                                                                                                   const bool exportRays,
5549                                                                                                   const int maxRays,
5550                                                                                                   const string prefix,
5551                                                                                                   VssRayContainer *visRays)
5552{
5553        if (sortViewCells)
[697]5554        {
[1415]5555                // sort view cells to visualize the view cells with highest render cost
[1021]5556                stable_sort(mViewCells.begin(), mViewCells.end(), ViewCell::LargerRenderCost);
5557        }
5558
[1570]5559        ViewCell::NewMail();
5560        const int limit = min(maxViewCells, (int)mViewCells.size());
[1178]5561       
[1570]5562        cout << "\nExporting " << limit << " single view cells: " << endl;
5563       
[1021]5564        for (int i = 0; i < limit; ++ i)
5565        {
5566                cout << "creating output for view cell " << i << " ... ";
[1418]5567               
5568                // largest view cell pvs first of random view cell
[1570]5569                ViewCell *vc = sortViewCells ?
[1418]5570                        mViewCells[i] : mViewCells[(int)RandomValue(0, (float)mViewCells.size() - 1)];
5571               
[1570]5572                if (vc->Mailed()) // already used
5573                        continue;
5574
5575                vc->Mail();
5576
[1021]5577                ObjectPvs pvs;
5578                mViewCellsTree->GetPvs(vc, pvs);
[704]5579
[1570]5580                char s[64]; sprintf(s, "%sviewcell%04d.wrl", prefix.c_str(), i);
[1021]5581                Exporter *exporter = Exporter::GetExporter(s);
5582               
[1709]5583                cout << "view cell " << vc->GetId() << ": pvs cost=" << mViewCellsTree->GetPvsCost(vc) << endl;
[1021]5584
[1570]5585                if (exportPvs)
5586                {
5587                        Material m;
[1418]5588
[1570]5589                        Intersectable::NewMail();
5590                       
[1742]5591                        ObjectPvsIterator pit = pvs.GetIterator();
5592
[1570]5593                        // output PVS of view cell
[1742]5594                        while (pit.HasMoreEntries())
[1570]5595                        {               
[1742]5596                                ObjectPvsEntry entry = pit.Next();
5597                               
5598                                Intersectable *intersect = entry.mObject;
5599
[1570]5600                                if (!intersect->Mailed())
5601                                {
5602                                        m = RandomMaterial();
5603                                        exporter->SetForcedMaterial(m);
5604
5605                                        exporter->ExportIntersectable(intersect);
5606                                        intersect->Mail();
5607                                }
5608                        }
5609                }
5610
5611                if (exportRays)
[1021]5612                {
[1570]5613                        ////////////
5614                        //-- export the sample rays
5615
[1021]5616                        // output rays stored with the view cells during subdivision
[1570]5617                        VssRayContainer vcRays;
5618                        VssRayContainer collectRays;
[1021]5619
[1570]5620                        // collect intial view cells
5621                        ViewCellContainer leaves;
5622                        mViewCellsTree->CollectLeaves(vc, leaves);
[1021]5623
[1570]5624                        ViewCellContainer::const_iterator vit, vit_end = leaves.end();
[1021]5625
[1570]5626                        for (vit = leaves.begin(); vit != vit_end; ++ vit)
5627                        {
5628                                VspLeaf *vcLeaf = dynamic_cast<VspViewCell *>(*vit)->mLeaves[0];
5629                                VssRayContainer::const_iterator rit, rit_end = vcLeaf->mVssRays.end();
5630
5631                                for (rit = vcLeaf->mVssRays.begin(); rit != rit_end; ++ rit)
[1021]5632                                {
[1570]5633                                        collectRays.push_back(*rit);
[1021]5634                                }
[1570]5635                        }
[1021]5636
[1570]5637                        const int raysOut = min((int)collectRays.size(), maxRays);
[1021]5638
[1570]5639                        VssRayContainer::const_iterator rit, rit_end = collectRays.end();
[1021]5640
[1570]5641                        for (rit = collectRays.begin(); rit != rit_end; ++ rit)
5642                        {
5643                                const float p = RandomValue(0.0f, (float)collectRays.size());
5644
5645                                if (p < raysOut)
5646                                        vcRays.push_back(*rit);
[1021]5647                        }
[1570]5648
5649                        exporter->ExportRays(vcRays, RgbColor(1, 1, 1));
[1021]5650                }
[1570]5651               
5652       
[1415]5653                /////////////////
[1021]5654                //-- export view cell geometry
[1121]5655
[697]5656                exporter->SetWireframe();
5657
[1416]5658                Material m;
[1021]5659                m.mDiffuseColor = RgbColor(0, 1, 0);
5660                exporter->SetForcedMaterial(m);
5661
[1416]5662                ExportViewCellGeometry(exporter, vc, NULL, NULL);
[697]5663                exporter->SetFilled();
5664
[1021]5665                DEL_PTR(exporter);
5666                cout << "finished" << endl;
[697]5667        }
[1021]5668
[1570]5669        cout << endl;
[697]5670}
5671
5672
[1021]5673int VspOspViewCellsManager::ComputeBoxIntersections(const AxisAlignedBox3 &box,
5674                                                                                                        ViewCellContainer &viewCells) const
5675{
[1278]5676        return mHierarchyManager->GetVspTree()->ComputeBoxIntersections(box, viewCells);
[1021]5677}
[580]5678
[1021]5679
5680int VspOspViewCellsManager::CastLineSegment(const Vector3 &origin,
5681                                                                                        const Vector3 &termination,
5682                                                                                        ViewCellContainer &viewcells)
5683{
[1278]5684        return mHierarchyManager->GetVspTree()->CastLineSegment(origin, termination, viewcells);
[1021]5685}
5686
5687
5688bool VspOspViewCellsManager::ExportViewCells(const string filename,
5689                                                                                         const bool exportPvs,
5690                                                                                         const ObjectContainer &objects)
5691{
5692        if (!ViewCellsConstructed() || !ViewCellsTreeConstructed())
5693                return false;
5694
[1415]5695        const long starttime = GetTime();
[1021]5696        cout << "exporting view cells to xml ... ";
5697       
[1201]5698        OUT_STREAM stream(filename.c_str());
[1021]5699
5700        // for output we need unique ids for each view cell
5701        CreateUniqueViewCellIds();
5702
5703        stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl;
5704        stream << "<VisibilitySolution>" << endl;
5705
[1580]5706        if (exportPvs)
5707        {
5708        ///////////////
5709                //-- export bounding boxes
5710                //-- The bounding boxes are used to identify
5711                //-- the objects in the rendering engine
[1614]5712                mHierarchyManager->ExportBoundingBoxes(stream, objects);
[580]5713        }
[1021]5714
[1415]5715        //////////////////////////
[1021]5716        //-- export the view cells and the pvs
5717
5718        const int numViewCells = mCurrentViewCellsStats.viewCells;
5719
5720        stream << "<ViewCells number=\"" << numViewCells << "\" >" << endl;
5721        mViewCellsTree->Export(stream, exportPvs);
5722        stream << "</ViewCells>" << endl;
5723
[1415]5724        //////////////////////
[1201]5725        //-- export the view space hierarchy
[1021]5726       
[1262]5727        stream << "<ViewSpaceHierarchy type=\"vsp\""
5728                   << " min=\"" << mViewSpaceBox.Min().x << " " << mViewSpaceBox.Min().y << " " << mViewSpaceBox.Min().z << "\""
[1286]5729                   << " max=\"" << mViewSpaceBox.Max().x << " " << mViewSpaceBox.Max().y << " " << mViewSpaceBox.Max().z << "\">" << endl;
[1262]5730
[1278]5731        mHierarchyManager->GetVspTree()->Export(stream);
[1286]5732        stream << "</ViewSpaceHierarchy>" << endl;
[1021]5733
[1415]5734        ////////////////////// 
[1201]5735        //-- export the object space partition
5736       
[1278]5737        mHierarchyManager->ExportObjectSpaceHierarchy(stream);
5738       
[1201]5739        stream << "</VisibilitySolution>" << endl;
[1021]5740        stream.close();
[1201]5741       
[1415]5742        cout << "finished in " << TimeDiff(starttime, GetTime()) * 1e-3 << " secs" << endl;
[1021]5743        return true;
5744}
5745
5746
5747
[1027]5748ViewCell *VspOspViewCellsManager::GetViewCell(const Vector3 &point,
5749                                                                                          const bool active) const
[1021]5750{
5751        if (!ViewCellsConstructed())
5752                return NULL;
[1588]5753
[1021]5754        if (!mViewSpaceBox.IsInside(point))
[1418]5755                return NULL;
[1588]5756
[1278]5757        return mHierarchyManager->GetVspTree()->GetViewCell(point, active);
[1021]5758}
5759
5760
5761void VspOspViewCellsManager::CreateMesh(ViewCell *vc)
5762{
5763        // matt: TODO
5764        Mesh *mesh = MeshManager::GetSingleton()->CreateResource();
[1027]5765
5766        ViewCellContainer leaves;
5767        mViewCellsTree->CollectLeaves(vc, leaves);
5768
5769        ViewCellContainer::const_iterator it, it_end = leaves.end();
5770
5771    for (it = leaves.begin(); it != it_end; ++ it)
5772        {
[1551]5773                VspLeaf *leaf = dynamic_cast<VspViewCell *>(*it)->mLeaves[0];
[1278]5774                const AxisAlignedBox3 box = mHierarchyManager->GetVspTree()->GetBoundingBox(leaf);
[1027]5775        IncludeBoxInMesh(box, *mesh);
5776        }
5777
[1021]5778        vc->SetMesh(mesh);
5779}
5780
5781
5782int VspOspViewCellsManager::CastBeam(Beam &beam)
5783{
5784        // matt: TODO
5785        return 0;
5786}
5787
5788
[1667]5789void VspOspViewCellsManager::Finalize(ViewCell *viewCell, const bool createMesh)
[1021]5790{
5791        float area = 0;
5792        float volume = 0;
5793
5794        ViewCellContainer leaves;
5795        mViewCellsTree->CollectLeaves(viewCell, leaves);
5796
5797        ViewCellContainer::const_iterator it, it_end = leaves.end();
5798
5799    for (it = leaves.begin(); it != it_end; ++ it)
[580]5800        {
[1551]5801                VspLeaf *leaf = dynamic_cast<VspViewCell *>(*it)->mLeaves[0];
[1027]5802               
[1278]5803                const AxisAlignedBox3 box = mHierarchyManager->GetVspTree()->GetBoundingBox(leaf);
[1021]5804
[1027]5805                const float lVol = box.GetVolume();
5806                const float lArea = box.SurfaceArea();
[1021]5807
5808                area += lArea;
5809                volume += lVol;
5810
5811        CreateMesh(*it);
[580]5812        }
5813
[1021]5814        viewCell->SetVolume(volume);
5815        viewCell->SetArea(area);
[580]5816}
[1021]5817       
[580]5818
[1159]5819float VspOspViewCellsManager::ComputeSampleContribution(VssRay &ray,
5820                                                                                                                const bool addRays,
5821                                                                                                                const bool storeViewCells)
5822{
5823        ViewCellContainer viewcells;
5824
5825        ray.mPvsContribution = 0;
5826        ray.mRelativePvsContribution = 0.0f;
5827
5828        static Ray hray;
5829        hray.Init(ray);
5830        //hray.mFlags |= Ray::CULL_BACKFACES;
5831        //Ray hray(ray);
5832
5833        float tmin = 0, tmax = 1.0;
5834
5835        if (!GetViewSpaceBox().GetRaySegment(hray, tmin, tmax) || (tmin > tmax))
5836                return 0;
5837
5838        Vector3 origin = hray.Extrap(tmin);
5839        Vector3 termination = hray.Extrap(tmax);
5840
[1291]5841        ViewCell::NewMail();
5842
[1159]5843        // traverse the view space subdivision
5844        CastLineSegment(origin, termination, viewcells);
5845
5846        if (storeViewCells)
[1291]5847        {       
5848                // copy viewcells memory efficiently
[1159]5849                ray.mViewCells.reserve(viewcells.size());
5850                ray.mViewCells = viewcells;
5851        }
5852
5853        ViewCellContainer::const_iterator it = viewcells.begin();
5854
5855        for (; it != viewcells.end(); ++ it)
5856        {
5857                ViewCell *viewcell = *it;
[1666]5858
[1159]5859                if (viewcell->GetValid())
[1566]5860                {       // if ray not outside of view space
[1159]5861                        float contribution;
5862
5863                        if (ray.mTerminationObject)
5864                        {
[1666]5865                                // todo: maybe not correct for kd node pvs
5866                                Intersectable *obj = mHierarchyManager->GetIntersectable(ray, true);
5867
5868                                if (viewcell->GetPvs().GetSampleContribution(obj,
5869                                        ray.mPdf,
5870                                        contribution))
[1159]5871                                {
[1666]5872                                        ++ ray.mPvsContribution;
[1159]5873                                }
[1666]5874
5875                                ray.mRelativePvsContribution += contribution;
[1159]5876                        }
[1666]5877
[1686]5878                        ////////////////
[1666]5879                        //-- for directional sampling it is important to count only contributions
5880                        //-- made in one direction!
5881                        //-- the other contributions of this sample will be counted for the opposite ray!
[1166]5882#if SAMPLE_ORIGIN_OBJECTS
[1159]5883                        if (ray.mOriginObject &&
5884                                viewcell->GetPvs().GetSampleContribution(ray.mOriginObject,
[1666]5885                                ray.mPdf,
5886                                contribution))
[1159]5887                        {
5888                                ++ ray.mPvsContribution;
[1582]5889                                ray.mRelativePvsContribution += contribution;
[1159]5890                        }
5891#endif
5892                }
5893        }
5894
[1259]5895        if (!addRays)
[1566]5896        {
[1259]5897                return ray.mRelativePvsContribution;
[1566]5898        }
[1259]5899
5900        // sampled objects are stored in the pvs
5901        for (it = viewcells.begin(); it != viewcells.end(); ++ it)
[1159]5902        {
[1259]5903                ViewCell *viewCell = *it;
[1159]5904
[1259]5905                if (!viewCell->GetValid())
5906                        break;
[1159]5907
[1259]5908                AddSampleToPvs(
5909                        ray.mTerminationObject,
5910                        ray.mTermination,
5911                        viewCell,
5912                        ray.mPdf,
5913                        ray.mRelativePvsContribution);
5914
[1166]5915#if SAMPLE_ORIGIN_OBJECTS
[1168]5916
[1259]5917                AddSampleToPvs(
5918                        ray.mOriginObject,
5919                        ray.mOrigin,
5920                        viewCell,
5921                        ray.mPdf,
5922                        ray.mRelativePvsContribution);
5923#endif                 
[1159]5924        }
5925
[1715]5926       
5927
5928        return ABS_CONTRIBUTION_WEIGHT*ray.mPvsContribution +
5929          (1.0f - ABS_CONTRIBUTION_WEIGHT)*ray.mRelativePvsContribution;
[1159]5930}
5931
5932
[1259]5933bool VspOspViewCellsManager::AddSampleToPvs(Intersectable *obj,
5934                                                                                        const Vector3 &hitPoint,
5935                                                                                        ViewCell *vc,
5936                                                                                        const float pdf,
5937                                                                                        float &contribution) const
5938{
[1486]5939        // The hierarchy manager decides about the type of sample cast
[1278]5940        return mHierarchyManager->AddSampleToPvs(obj, hitPoint, vc, pdf, contribution);
[1259]5941}
5942
5943
[1021]5944void VspOspViewCellsManager::PrepareLoadedViewCells()
5945{
5946        // TODO
5947}
[580]5948
[1201]5949
5950ViewCellsManager *VspOspViewCellsManager::LoadViewCells(const string &filename,
5951                                                                                                                ObjectContainer *objects,
5952                                                                                                                const bool finalizeViewCells,
5953                                                                                                                BoundingBoxConverter *bconverter)
5954                                                                                                 
5955{
5956        ViewCellsManager *vm =
5957                ViewCellsManager::LoadViewCells(filename, objects, finalizeViewCells, bconverter);
[1278]5958#if 0
5959        // insert scene objects in tree
[1201]5960        mOspTree->InsertObjects(mOspTree->GetRoot(), *objects);
[1278]5961#endif
[1201]5962        return vm;
5963}
5964
[1737]5965void
5966VspOspViewCellsManager::CollectObjects(const AxisAlignedBox3 &box, ObjectContainer &objects)
5967{
5968  mHierarchyManager->CollectObjects(box, objects);
5969}
[1692]5970
[1737]5971
[1709]5972#if 1
[1180]5973
[1686]5974void VspOspViewCellsManager::EvalViewCellPartition()
5975{
5976        int samplesPerPass;
5977        int numSamples;
5978        int castSamples = 0;
[1718]5979        int oldSamples = 0;
5980        int samplesForStats;
5981        char statsPrefix[100];
5982        char suffix[100];
[1713]5983        int splitsStepSize;
[1686]5984
[1718]5985
[1686]5986        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesPerPass", samplesPerPass);
[1718]5987        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samplesForStats", samplesForStats);
[1686]5988        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.samples", numSamples);
5989        Environment::GetSingleton()->GetStringValue("ViewCells.Evaluation.statsPrefix", statsPrefix);
[1718]5990        Environment::GetSingleton()->GetIntValue("ViewCells.Evaluation.stepSize", splitsStepSize);
5991       
5992        Debug << "step size: " << splitsStepSize << endl;
[1686]5993        Debug << "view cell evaluation samples per pass: " << samplesPerPass << endl;
5994        Debug << "view cell evaluation samples: " << numSamples << endl;
5995        Debug << "view cell stats prefix: " << statsPrefix << endl;
5996
[1718]5997        // should directional sampling be used?
5998        bool dirSamples =
5999                (mEvaluationSamplingType == SamplingStrategy::DIRECTION_BASED_DISTRIBUTION);
6000
[1686]6001        cout << "reseting pvs ... ";
6002               
6003        // reset pvs and start over from zero
[1718]6004        mViewCellsTree->ResetPvs();
6005       
[1686]6006        cout << "finished" << endl;
6007    cout << "Evaluating view cell partition ... " << endl;
6008
6009        while (castSamples < numSamples)
6010        {               
6011                ///////////////
6012                //-- we have to use uniform sampling strategy for construction rays
6013
[1718]6014                VssRayContainer evaluationSamples;
[1686]6015                const int samplingType = mEvaluationSamplingType;
6016
6017                long startTime = GetTime();
6018
6019                cout << "casting " << samplesPerPass << " samples ... ";
6020                Debug << "casting " << samplesPerPass << " samples ... ";
6021
6022                CastPassSamples(samplesPerPass, samplingType, evaluationSamples);
6023               
6024                castSamples += samplesPerPass;
6025
6026                Real timeDiff = TimeDiff(startTime, GetTime());
[1718]6027               
6028                cout << "finished in " << timeDiff * 1e-3f << " secs" << endl;
[1686]6029                cout << "computing sample contributions of " << (int)evaluationSamples.size()  << " samples ... ";
[1718]6030               
6031                Debug << "finished in " << timeDiff * 1e-3f << " secs" << endl;
[1686]6032                Debug << "computing sample contributions of " << (int)evaluationSamples.size()  << " samples ... ";
6033
6034                startTime = GetTime();
6035
6036                ComputeSampleContributions(evaluationSamples, true, false);
6037
6038                timeDiff = TimeDiff(startTime, GetTime());
6039                cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
6040                Debug << "finished in " << timeDiff * 1e-3 << " secs" << endl;
6041
[1718]6042                if ((castSamples >= samplesForStats + oldSamples) || (castSamples >= numSamples))
6043                {
6044                        oldSamples += samplesForStats;
[1686]6045
[1718]6046                        ///////////
6047                        //-- output stats
[1686]6048
[1718]6049                        sprintf(suffix, "-%09d-eval.log", castSamples);
6050                        const string filename = string(statsPrefix) + string(suffix);
[1710]6051
[1718]6052                        startTime = GetTime();
[1732]6053                       
[1718]6054                        cout << "compute new statistics ... " << endl;
[1710]6055
[1718]6056                        ofstream ofstr(filename.c_str());
6057                        mHierarchyManager->EvaluateSubdivision2(ofstr, splitsStepSize);
6058
6059                        timeDiff = TimeDiff(startTime, GetTime());
6060                        cout << "finished in " << timeDiff * 1e-3 << " secs" << endl;
[1732]6061                        cout << "*************************************" << endl;
6062
[1718]6063                        Debug << "statistics computed in " << timeDiff * 1e-3 << " secs" << endl;
6064
6065                        // only for debugging purpose
[1732]6066                        if (0)
[1718]6067                        {
6068                                ViewCellContainer viewCells;
6069                                mViewCellsTree->CollectLeaves(mViewCellsTree->GetRoot(), viewCells);
6070
6071                                ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
6072                                int pvsSize = 0;
6073
6074                                for (vit = viewCells.begin(); vit != vit_end; ++ vit)
6075                                {
6076                                        pvsSize += (*vit)->GetPvs().GetSize();
6077                                }
6078
6079                                cout << "debug entries: " << pvsSize << ", memcost: " << (float)pvsSize * ObjectPvs::GetEntrySize() << endl;
6080                        }
6081                }
6082
[1709]6083                disposeRays(evaluationSamples, NULL);
[1686]6084        }
[1718]6085       
[1686]6086}
[1551]6087#endif
[878]6088}
Note: See TracBrowser for help on using the repository browser.