source: trunk/VUT/GtpVisibilityPreprocessor/src/SamplingPreprocessor.cpp @ 396

Revision 396, 28.0 KB checked in by mattausch, 19 years ago (diff)

fixed bug in bsp geometry construction

Line 
1#include "SceneGraph.h"
2#include "KdTree.h"
3#include "SamplingPreprocessor.h"
4#include "X3dExporter.h"
5#include "Environment.h"
6#include "MutualVisibility.h"
7#include "Polygon3.h"
8#include "ViewCell.h"
9
10SamplingPreprocessor::SamplingPreprocessor(): mPass(0), mSampleRays(NULL)
11{
12  // this should increase coherence of the samples
13  environment->GetIntValue("Sampling.samplesPerPass", mSamplesPerPass);
14  environment->GetIntValue("Sampling.totalSamples", mTotalSamples);
15  environment->GetIntValue("BspTree.Construction.samples", mBspConstructionSamples);
16  environment->GetIntValue("ViewCells.PostProcessing.samples", mPostProcessSamples);
17  environment->GetIntValue("BspTree.Visualization.samples", mVisualizationSamples);
18
19  mKdPvsDepth = 100;
20  mStats.open("stats.log");
21
22}
23
24SamplingPreprocessor::~SamplingPreprocessor()
25{
26        CLEAR_CONTAINER(mSampleRays);
27}
28
29void
30SamplingPreprocessor::SetupRay(Ray &ray,
31                                                                                                                         const Vector3 &point,
32                                                                                                                         const Vector3 &direction,
33                                                                                                                         const int type)
34{
35  ray.intersections.clear();
36  ray.kdLeaves.clear();
37  ray.testedObjects.clear();
38  ray.bspIntersections.clear();
39        ray.mFlags |= Ray::STORE_KDLEAVES | Ray::STORE_BSP_INTERSECTIONS;
40  //  cout<<point<<" "<<direction<<endl;
41  ray.Init(point, direction, type);
42}
43
44KdNode *
45SamplingPreprocessor::GetNodeForPvs(KdLeaf *leaf)
46{
47  KdNode *node = leaf;
48  while (node->mParent && node->mDepth > mKdPvsDepth)
49    node = node->mParent;
50  return node;
51}
52
53bool
54SamplingPreprocessor::BuildBspTree()
55{
56        // delete old tree
57        DEL_PTR(mBspTree);
58        mBspTree = new BspTree(&mUnbounded);
59        ObjectContainer objects;
60       
61        switch (BspTree::sConstructionMethod)
62        {
63        case BspTree::FROM_INPUT_VIEW_CELLS:
64                mBspTree->SetGenerateViewCells(false);
65                mBspTree->Construct(mViewCells);
66                break;
67        case BspTree::FROM_SCENE_GEOMETRY:
68                DeleteViewCells(); // we generate new view cells
69                mBspTree->SetGenerateViewCells(true);
70                mSceneGraph->CollectObjects(&objects);
71                mBspTree->Construct(objects);
72                break;
73        case BspTree::FROM_RAYS:
74                DeleteViewCells(); // we generate new view cells
75                mBspTree->SetGenerateViewCells(true);
76                mBspTree->Construct(mSampleRays);
77                break;
78        default:
79                Debug << "Error: Method not available\n";
80                break;
81        }
82       
83       
84        return true;
85}
86
87int
88SamplingPreprocessor::AddNodeSamples(const Ray &ray,
89                                                                                                                                                 Intersectable *sObject,
90                                                                                                                                                 Intersectable *tObject
91                                                                                                                                                 )
92{
93  int contributingSamples = 0;
94  int j;
95        int objects = 0;
96        if (sObject)
97                objects++;
98        if (tObject)
99                objects++;
100
101        if (objects) {
102                for (j=0; j < ray.kdLeaves.size(); j++) {
103                        KdNode *node = GetNodeForPvs( ray.kdLeaves[j] );
104                        if (sObject)
105                                contributingSamples += sObject->mKdPvs.AddSample(node);
106                        if (tObject)
107                                contributingSamples += tObject->mKdPvs.AddSample(node);
108                }
109        }
110       
111        for (j=1; j < ((int)ray.kdLeaves.size() - 1); j++) {
112                ray.kdLeaves[j]->AddPassingRay2(ray,
113                                                                                                                                                objects,
114                                                                                                                                                ray.kdLeaves.size()
115                                                                                                                                                );
116  }
117 
118  return contributingSamples;
119}
120
121
122int SamplingPreprocessor::AddObjectSamples(Intersectable *obj, const Ray &ray)
123{
124        int contributingSamples = 0;
125        int j;
126 
127        // object can be seen from the view cell => add to view cell pvs
128        for (j=0; j < ray.bspIntersections.size(); ++ j)
129        {       
130                BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
131                // if ray not in unbounded space
132                if (leaf->GetViewCell() != &mUnbounded)
133                        contributingSamples +=
134                                leaf->GetViewCell()->GetPvs().AddSample(obj);
135        }
136 
137        // rays passing through this viewcell
138        if (mPass > 1)
139                for (j=1; j < ((int)ray.bspIntersections.size() - 1); ++ j)
140                {
141                        BspLeaf *leaf = ray.bspIntersections[j].mLeaf;
142
143                        if (leaf->GetViewCell() != &mUnbounded)
144                                leaf->GetViewCell()->
145                                        AddPassingRay(ray, contributingSamples ? 1 : 0);
146                }
147 
148        return contributingSamples;
149}
150
151
152void
153SamplingPreprocessor::HoleSamplingPass()
154{
155  vector<KdLeaf *> leaves;
156  mKdTree->CollectLeaves(leaves);
157 
158  // go through all the leaves and evaluate their passing contribution
159  for (int i=0 ; i < leaves.size(); i++) {
160    KdLeaf *leaf = leaves[i];
161    cout<<leaf->mPassingRays<<endl;
162  }
163}
164
165
166int
167SamplingPreprocessor::CastRay(Intersectable *object,
168                                                                                                                        Ray &ray
169                                                                                                                        )
170{
171        int sampleContributions = 0;
172
173        long t1 = GetRealTime();
174        // cast ray to KD tree to find intersection with other objects
175        mKdTree->CastRay(ray);
176        long t2 = GetRealTime();
177
178        if (0 && object && object->GetId() > 2197) {
179                object->Describe(cout)<<endl;
180                cout<<ray<<endl;
181        }
182
183        if (ViewCell::sHierarchy == ViewCell::BSP)
184        {
185                // cast ray to BSP tree to get intersection with view cells
186                if (mBspTree)
187                {
188                        mBspTree->CastRay(ray);
189                       
190                        if (object)
191                                sampleContributions += AddObjectSamples(object, ray);
192                       
193                        if (!ray.intersections.empty()) // second intersection found
194                                {
195                                        sampleContributions +=
196                                                AddObjectSamples(ray.intersections[0].mObject, ray);
197                                }
198                }
199        }
200        else
201                {
202                        if (ray.kdLeaves.size()) {
203                                Intersectable *terminator =
204                                        ray.intersections.size() ? ray.intersections[0].mObject: NULL;
205
206                                sampleContributions += AddNodeSamples(ray,
207                                                                                                                                                                                        object,
208                                                                                                                                                                                        terminator);
209                        }
210                }
211       
212        return sampleContributions;
213}
214
215//  void
216//  SamplingPreprocessor::AvsGenerateRandomRay(Ray &ray)
217//  {
218//    int objId = RandomValue(0, mObjects.size());
219//    Intersectable *object = objects[objId];
220//    object->GetRandomSurfacePoint(point, normal);
221//    direction = UniformRandomVector(normal);
222//    SetupRay(ray, point, direction);
223//  }
224
225//  void
226//  SamplingPreprocessor::AvsHandleRay(Ray &ray)
227//  {
228//    int sampleContributions = 0;
229
230//    mKdTree->CastRay(ray);
231 
232//    if (ray.leaves.size()) {
233//      sampleContributions += AddNodeSamples(object, ray, pass);
234   
235//      if (ray.intersections.size()) {
236//        sampleContributions += AddNodeSamples(ray.intersections[0].mObject, ray, pass);
237//      }
238//    }
239//  }
240
241//  void
242//  SamplingPreprocessor::AvsBorderSampling(Ray &ray)
243//  {
244 
245
246//  }
247
248//  void
249//  SamplingPreprocessor::AvsPass()
250//  {
251//    Ray ray;
252//    while (1) {
253//      AvsGenerateRay(ray);
254//      HandleRay(ray);
255//      while ( !mRayQueue.empty() ) {
256//        Ray ray = mRayQueue.pop();
257//        mRayQueue.pop();
258//        AdaptiveBorderSampling(ray);
259//      }
260//    }
261 
262 
263
264//  }
265
266
267int
268SamplingPreprocessor::CastEdgeSamples(
269                                                                                                                                                        Intersectable *object,
270                                                                                                                                                        const Vector3 &point,
271                                                                                                                                                        MeshInstance *mi,
272                                                                                                                                                        const int samples
273                                                                                                                                                        )
274{
275        Ray ray;
276        int maxTries = samples*10;
277        int i;
278        int rays = 0;
279        int edgeSamplesContributions = 0;
280        for (i=0; i < maxTries && rays < samples; i++) {
281                // pickup a random face of each mesh
282                Mesh *mesh = mi->GetMesh();
283                int face = RandomValue(0, mesh->mFaces.size()-1);
284               
285                Polygon3 poly(mesh->mFaces[face], mesh);
286                poly.Scale(1.001);
287                // now extend a random edge of the face
288                int edge = RandomValue(0, poly.mVertices.size()-1);
289                float t = RandomValue(0.0f,1.0f);
290                Vector3 target = t*poly.mVertices[edge] + (1.0f-t)*poly.mVertices[(edge + 1)%
291                                                                                                                                                                                                                                                                                 poly.mVertices.size()];
292                SetupRay(ray, point, target - point, Ray::LOCAL_RAY);
293                if (!mesh->CastRay(ray, mi)) {
294                        // the rays which intersect the mesh have been discarded since they are not tangent
295                        // to the mesh
296                        rays++;
297                        edgeSamplesContributions += CastRay(object, ray);
298                }
299        }
300        return edgeSamplesContributions;
301}
302
303KdNode *
304SamplingPreprocessor::GetNodeToSample(Intersectable *object)
305{
306        int pvsSize = object->mKdPvs.GetSize();
307        KdNode *nodeToSample = NULL;
308       
309        bool samplePvsBoundary = false;
310        if (pvsSize && samplePvsBoundary) {
311                // this samples the nodes from the boundary of the current PVS
312                // mail all nodes from the pvs
313                Intersectable::NewMail();
314                KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
315               
316                for (; i != object->mKdPvs.mEntries.end(); i++) {
317                        KdNode *node = (*i).first;
318                        node->Mail();
319                }
320               
321                int maxTries = 2*pvsSize;
322                Debug << "Finding random neighbour" << endl;   
323                for (int tries = 0; tries < 10; tries++) {
324                        int index = RandomValue(0, pvsSize - 1);
325                        KdPvsData data;
326                        KdNode *node;
327                        object->mKdPvs.GetData(index, node, data);
328                        nodeToSample = mKdTree->FindRandomNeighbor(node, true);
329                        if (nodeToSample)
330                                break;
331                }
332        } else {
333                // just pickup a random node
334                //              nodeToSample = mKdTree->GetRandomLeaf(Plane3(normal, point));
335                nodeToSample = mKdTree->GetRandomLeaf();
336        }
337        return nodeToSample;
338}
339
340void
341SamplingPreprocessor::VerifyVisibility(Intersectable *object)
342{
343        // mail all nodes from the pvs
344        Intersectable::NewMail();
345        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
346        for (; i != object->mKdPvs.mEntries.end(); i++) {
347                KdNode *node = (*i).first;
348                node->Mail();
349        }
350        Debug << "Get all neighbours from PVS" << endl;
351        vector<KdNode *> invisibleNeighbors;
352        // get all neighbors of all PVS nodes
353        i = object->mKdPvs.mEntries.begin();
354        for (; i != object->mKdPvs.mEntries.end(); i++) {
355                KdNode *node = (*i).first;
356                mKdTree->FindNeighbors(node, invisibleNeighbors, true);
357                AxisAlignedBox3 box = object->GetBox();
358                for (int j=0; j < invisibleNeighbors.size(); j++) {
359                        int visibility = ComputeBoxVisibility(mSceneGraph,
360                                                              mKdTree,
361                                                              box,
362                                                              mKdTree->GetBox(invisibleNeighbors[j]),
363                                                              1e-6f);
364                        //            exit(0);
365                }
366                // now rank all the neighbors according to probability that a new
367                // sample creates some contribution
368        }
369}
370
371bool
372SamplingPreprocessor::ComputeVisibility()
373{
374 
375  // pickup an object
376  ObjectContainer objects;
377 
378  mSceneGraph->CollectObjects(&objects);
379
380  Vector3 point, normal, direction;
381  Ray ray;
382
383  long startTime = GetTime();
384 
385  int i;
386  int totalSamples = 0;
387
388  int pvsOut = Min((int)objects.size(), 10);
389
390  RayContainer rays[10];
391
392  while (totalSamples < mTotalSamples) {
393                int passContributingSamples = 0;
394                int passSampleContributions = 0;
395                int passSamples = 0;
396                int index = 0;
397               
398                int reverseSamples = 0;
399               
400                       
401                //cout << "totalSamples: "  << totalSamples << endl;
402
403                for (i = 0; i < objects.size(); i++) {
404                                               
405                        KdNode *nodeToSample = NULL;
406                        Intersectable *object = objects[i];
407               
408                        int pvsSize = 0;
409                        if (ViewCell::sHierarchy == ViewCell::KD)
410                                pvsSize = object->mKdPvs.GetSize();
411                                               
412                       
413                        if (0 && pvsSize && mPass == 1000 ) {
414                                VerifyVisibility(object);
415                        }
416                       
417                        int faceIndex = object->GetRandomSurfacePoint(point, normal);
418                       
419                        bool viewcellSample = true;
420                        int sampleContributions;
421                        bool debug = false; //(object->GetId() >= 2199);
422                        if (viewcellSample) {
423                                //mKdTree->GetRandomLeaf(Plane3(normal, point));
424
425                                nodeToSample = GetNodeToSample(object);
426
427                                for (int k=0; k < mSamplesPerPass; k++) {
428                                        bool reverseSample = false;
429                                       
430
431                                        if (nodeToSample) {
432                                                AxisAlignedBox3 box = mKdTree->GetBox(nodeToSample);
433                                                Vector3 pointToSample = box.GetRandomPoint();
434                                                //                                              pointToSample.y = 0.9*box.Min().y + 0.1*box.Max().y;
435                                                if (object->GetRandomVisibleSurfacePoint( point, normal, pointToSample, 3 )) {
436                                                        direction = pointToSample - point;
437                                                } else {
438                                                        reverseSamples++;
439                                                        reverseSample = true;
440                                                        direction = point - pointToSample;
441                                                        point = pointToSample;
442                                                }
443                                        }
444                                        else {
445                                                direction = UniformRandomVector(normal);
446                                        }
447                                       
448                                        // construct a ray
449                                        SetupRay(ray, point, direction, Ray::LOCAL_RAY);
450                                       
451                                        sampleContributions = CastRay(reverseSample ? NULL : object, ray);
452                                       
453                                        //-- CORR matt: put block inside loop
454                                        if (sampleContributions) {
455                                                passContributingSamples ++;
456                                                passSampleContributions += sampleContributions;
457                                        }
458
459                                        if ( i < pvsOut ) {
460                                                Ray *nray = new Ray(ray);
461                                                rays[i].push_back(nray);
462                                        }
463               
464                                        if (!ray.intersections.empty()) {
465                                                // check whether we can add this to the rays
466                                                for (int j = 0; j < pvsOut; j++) {
467                                                        if (objects[j] == ray.intersections[0].mObject) {
468                                                                Ray *nray = new Ray(ray);
469                                                                rays[j].push_back(nray);
470                                                        }
471                                                }
472                                        }
473                                        //-------------------
474                                        if (ViewCell::sHierarchy == ViewCell::BSP)
475                                        {
476                                                ProcessBspViewCells(ray,
477                                                                                        object,
478                                                                                        faceIndex,
479                                                                                        passContributingSamples,
480                                                                                        passSampleContributions);
481                                        }
482                                }
483                        } else {
484                                // edge samples
485                                // get random visible mesh
486                                //                              object->GetRandomVisibleMesh(Plane3(normal, point));
487                        }
488       
489                        // CORR matt: must add all samples
490                        passSamples += mSamplesPerPass;
491                }
492       
493                totalSamples += passSamples;
494               
495                //    if (pass>10)
496                //      HoleSamplingPass();
497   
498                mPass++;
499
500                int pvsSize = 0;
501       
502                if (ViewCell::sHierarchy == ViewCell::BSP) {
503                        for (i=0; i < mViewCells.size(); i++) {
504                                ViewCell *vc = mViewCells[i];
505                                pvsSize += vc->GetPvs().GetSize();
506                        }
507                } else  {
508                        for (i=0; i < objects.size(); i++) {
509                                Intersectable *object = objects[i];
510                                pvsSize += object->mKdPvs.GetSize();
511                        }
512                }
513
514                float avgRayContrib = (passContributingSamples > 0) ?
515                        passSampleContributions/(float)passContributingSamples : 0;
516
517                cout << "#Pass " << mPass << " : t = " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
518                cout << "#TotalSamples=" << totalSamples/1000
519                                 << "k   #SampleContributions=" << passSampleContributions << " ("
520                                 << 100*passContributingSamples/(float)passSamples<<"%)" << " avgPVS="
521                                 << pvsSize /(float)objects.size() << endl
522                                 << "avg ray contrib=" << avgRayContrib << endl
523                                 << "reverse samples [%]" << reverseSamples/(float)passSamples*100.0f << endl;
524
525                mStats <<
526                        "#Pass\n" <<mPass<<endl<<
527                        "#Time\n" << TimeDiff(startTime, GetTime())*1e-3 << endl<<
528                        "#TotalSamples\n" << totalSamples<< endl<<
529                        "#SampleContributions\n" << passSampleContributions << endl <<
530                        "#PContributingSamples\n"<<100*passContributingSamples/(float)passSamples<<endl <<
531                        "#AvgPVS\n"<< pvsSize/(float)objects.size() << endl <<
532                        "#AvgRayContrib\n" << avgRayContrib << endl;
533        }
534       
535        if (ViewCell::sHierarchy == ViewCell::KD)       
536                cout << "#totalPvsSize=" << mKdTree->CollectLeafPvs() << endl;
537 
538        if (mBspTree)
539        {
540                //-- render simulation
541                cout << "\nevaluating render time before merge ... ";
542                Real rt = SimulateRendering();
543               
544                cout << "avg render time: " << rt * 1e-3 << endl;
545                Debug << "avg render time: " << rt * 1e-3 << endl;
546
547                //-- post processing of bsp view cells
548        int vcSize = 0;
549                int pvsSize = 0;
550
551                BspViewCellsStatistics stat;
552               
553                Debug << "overall scene size: " << (int)objects.size() << endl;
554                mBspTree->EvaluateViewCellsStats(stat);
555               
556                Debug << "original view cell partition:\n" << stat << endl;
557               
558                if (1) // export view cells
559                {
560                        cout << "exporting initial view cells (=leaves) ... ";
561                        Exporter *exporter = Exporter::GetExporter("view_cells.x3d");
562                        if (exporter)
563                        {
564                                exporter->ExportBspLeaves(*mBspTree, stat.maxPvs);
565                                //exporter->ExportBspViewCellPartition(*mBspTree, 0);
566                                delete exporter;
567                        }
568                        cout << "finished" << endl;
569                }
570
571                cout << "starting post processing using " << mPostProcessSamples << " samples ... ";
572               
573                long startTime = GetTime();
574                int merged = PostprocessViewCells(mSampleRays);
575               
576                cout << "finished" << endl;
577                cout << "merged " << merged << " view cells in "
578                         << TimeDiff(startTime, GetTime()) *1e-3 << " secs" << endl;
579
580                //-- recount pvs
581                mBspTree->EvaluateViewCellsStats(stat);
582               
583                Debug << "after post processing:\n" << stat << endl;
584
585                //-- render simulation
586                cout << "\nevaluating render time after merge ... ";
587                       
588                rt = SimulateRendering();
589
590                cout << "render time: " << rt * 1e-3 << endl;
591                Debug << "render time: " << rt * 1e-3 << endl;
592
593                if (1) // export view cells
594                {
595                        cout << "exporting view cells after merge ... ";
596                        Exporter *exporter = Exporter::GetExporter("merged_view_cells.x3d");
597                        if (exporter)
598                        {
599                                exporter->ExportBspViewCellPartition(*mBspTree, stat.maxPvs);
600                                //exporter->ExportBspViewCellPartition(*mBspTree, 0);
601                                delete exporter;
602                        }
603
604                        cout << "finished" << endl;
605                }
606
607                //-- visualization of the BSP splits
608                bool exportSplits = false;
609                environment->GetBoolValue("BspTree.Visualization.exportSplits", exportSplits);
610               
611                cout << "exporting splits ... ";
612                if (exportSplits)
613                        ExportSplits(objects);
614                cout << "finished" << endl;
615
616                // export the PVS of sample view cells
617                if (1)
618                        ExportBspPvs(objects);
619        }
620       
621  //  HoleSamplingPass();
622        if (0) {
623                Exporter *exporter = Exporter::GetExporter("ray-density.x3d");
624                exporter->SetExportRayDensity(true);
625                exporter->ExportKdTree(*mKdTree);
626
627                if (mBspTree && (ViewCell::sHierarchy == ViewCell::BSP))
628                        exporter->ExportBspTree(*mBspTree);
629
630                delete exporter;
631        }
632 
633        bool exportRays = false;
634        if (exportRays) {
635                Exporter *exporter = NULL;
636                exporter = Exporter::GetExporter("sample-rays.x3d");
637                exporter->SetWireframe();
638                exporter->ExportKdTree(*mKdTree);
639                exporter->ExportBspTree(*mBspTree);
640
641                for (i=0; i < pvsOut; i++)
642                        exporter->ExportRays(rays[i], 1000, RgbColor(1, 0, 0));
643                exporter->SetFilled();
644               
645                delete exporter;
646        }
647
648        //-- several visualizations and statistics
649        if (1) {
650       
651   for (int k=0; k < pvsOut; k++) {
652                 Intersectable *object = objects[k];
653                 char s[64];
654                 sprintf(s, "sample-pvs%04d.x3d", k);
655                 Exporter *exporter = Exporter::GetExporter(s);
656                 exporter->SetWireframe();
657                 
658                 
659                 KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
660                 Intersectable::NewMail();
661                 
662                 // avoid adding the object to the list
663                 object->Mail();
664                 ObjectContainer visibleObjects;
665                 
666                 for (; i != object->mKdPvs.mEntries.end(); i++)
667                         {
668                                 KdNode *node = (*i).first;
669                                 exporter->ExportBox(mKdTree->GetBox(node));
670                                 mKdTree->CollectObjects(node, visibleObjects);
671                         }
672                 
673                 exporter->ExportRays(rays[k], 1000, RgbColor(0, 1, 0));
674                 exporter->SetFilled();
675                 
676                 for (int j = 0; j < visibleObjects.size(); j++)
677                         exporter->ExportIntersectable(visibleObjects[j]);
678                 
679                 
680                 Material m;
681                 m.mDiffuseColor = RgbColor(1, 0, 0);
682                 exporter->SetForcedMaterial(m);
683                 exporter->ExportIntersectable(object);
684                 
685                 delete exporter;
686         }
687  }
688 
689  return true;
690}
691
692void SamplingPreprocessor::ProcessBspViewCells(const Ray &ray,
693                                               Intersectable *object,
694                                                                                           const int faceIndex,
695                                                                                           int &contributingSamples,
696                                                                                           int &sampleContributions)
697{
698        // save rays for bsp tree construction
699        if (!mBspTree)
700        {
701                if ((BspTree::sConstructionMethod == BspTree::FROM_RAYS) &&
702                        ((int)mSampleRays.size() < mBspConstructionSamples))
703                {
704                        MeshInstance *mi = dynamic_cast<MeshInstance *>(object);
705                       
706                        Ray *sRay = new Ray(ray);
707                        mSampleRays.push_back(sRay);
708               
709                        // also add origin to sample
710                        sRay->sourceObject = Ray::Intersection(0.0, object, faceIndex);
711                }
712                else
713                {
714                        // construct BSP tree using the collected samples
715                        cout << "building bsp tree from " << (int)mSampleRays.size() << " samples " << endl;
716                        BuildBspTree();
717               
718                        // add contributions of saved samples to PVS
719                        contributingSamples += mBspTree->GetStat().contributingSamples;
720                        sampleContributions += mBspTree->GetStat().sampleContributions;
721
722                        BspTreeStatistics(Debug);       
723
724                        if (0) Export("vc_bsptree.x3d", false, false, true);
725
726                        // throw away samples because BSP leaves not stored in order
727                        // Need ordered rays for post processing => collect new rays
728                        //CLEAR_CONTAINER(mSampleRays);
729                }
730        }
731        // save rays for post processing
732        else if (((int)mSampleRays.size() < mPostProcessSamples) ||
733                         ((int)mSampleRays.size() < mVisualizationSamples))
734        {
735                mSampleRays.push_back(new Ray(ray));
736        }
737}
738
739// merge or subdivide view cells
740int SamplingPreprocessor::PostprocessViewCells(const RayContainer &rays)
741{
742        int merged = 0;
743
744        RayContainer::const_iterator rit, rit_end = rays.end();
745        vector<Ray::BspIntersection>::const_iterator iit;
746
747        int limit = min((int)mSampleRays.size(), mPostProcessSamples);
748
749        for (int i = 0; i < limit; ++i)
750        { 
751                Ray *ray = mSampleRays[i];
752
753                // traverse leaves stored in the rays and compare and merge consecutive
754                // leaves (i.e., the neighbors in the tree)
755                if (ray->bspIntersections.empty())
756                        continue;
757
758                iit = ray->bspIntersections.begin();
759
760                BspLeaf *previousLeaf = (*iit).mLeaf;
761                ++ iit;
762               
763                for (; iit != (*rit)->bspIntersections.end(); ++ iit)
764                {
765                        BspLeaf *leaf = (*iit).mLeaf;
766
767                        if (mBspTree->ShouldMerge(leaf, previousLeaf))
768                        {                       
769                                mBspTree->MergeViewCells(leaf, previousLeaf);
770
771                                ++ merged;
772                        }
773                        previousLeaf = leaf;
774                }
775        }
776
777        return merged;
778}
779
780void SamplingPreprocessor::ExportSplits(const ObjectContainer &objects)
781{
782        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
783
784        if (exporter)
785        {       
786                Material m;
787                m.mDiffuseColor = RgbColor(1, 0, 0);
788                exporter->SetForcedMaterial(m);
789                exporter->SetWireframe();
790                exporter->ExportBspSplits(*mBspTree, true);
791
792                // take forced material, else big scenes cannot be viewed
793                m.mDiffuseColor = RgbColor(0, 1, 0);
794                exporter->SetForcedMaterial(m);
795                exporter->SetFilled();
796
797                exporter->ResetForcedMaterial();
798               
799                // export rays
800                if (0)
801                {
802                        RayContainer outRays;
803               
804                        for (int i = 0; i < mSampleRays.size(); ++ i)
805                        {
806                                // only rays piercing geometry
807                                if (!mSampleRays[i]->intersections.empty())
808                                        outRays.push_back(mSampleRays[i]);
809                        }
810                        if (BspTree::sConstructionMethod == BspTree::FROM_RAYS)
811                        {
812                                // export rays
813                                exporter->ExportRays(outRays, 1000, RgbColor(1, 1, 0));
814                        }
815                }
816
817                // export scene geometry
818                if (0)
819                {
820                        Material m;//= RandomMaterial();
821                        m.mDiffuseColor = RgbColor(0, 1, 0);
822                        exporter->SetForcedMaterial(m);
823            exporter->SetWireframe();
824
825                        for (int j = 0; j < objects.size(); ++ j)
826                                exporter->ExportIntersectable(objects[j]);
827                }
828
829                delete exporter;
830        }
831}
832
833inline bool vc_gt(ViewCell *a, ViewCell *b)
834{
835        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
836}
837
838void SamplingPreprocessor::ExportBspPvs(const ObjectContainer &objects)
839{
840        const int leafOut = 10;
841       
842        ViewCell::NewMail();
843
844        //-- some rays for output
845        const int raysOut = min((int)mSampleRays.size(), mVisualizationSamples);
846        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
847        vector<Ray *> vcRays[leafOut];
848
849        if (0){
850                //-- some random view cells and rays for output
851                vector<BspLeaf *> bspLeaves;
852
853                for (int i = 0; i < leafOut; ++ i)
854                        bspLeaves.push_back(mBspTree->GetRandomLeaf());
855               
856                for (int i = 0; i < bspLeaves.size(); ++ i)
857                {
858                        cout << "creating output for view cell " << i << " ... ";
859                        // check whether we can add the current ray to the output rays
860                        for (int k = 0; k < raysOut; ++ k)
861                        {
862                                Ray *ray = mSampleRays[k];
863
864                                for     (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
865                                {
866                                        BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
867
868                                        if (bspLeaves[i]->GetViewCell() == leaf->GetViewCell())
869                                        {
870                                                vcRays[i].push_back(ray);
871                                        }
872                                }
873                        }
874
875                        Intersectable::NewMail();
876
877                        BspViewCell *vc = dynamic_cast<BspViewCell *>(bspLeaves[i]->GetViewCell());
878
879                        //bspLeaves[j]->Mail();
880                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
881
882                        Exporter *exporter = Exporter::GetExporter(s);
883                        exporter->SetFilled();
884
885                        ViewCellPvsMap::iterator it = vc->GetPvs().mEntries.begin();
886
887                        //exporter->SetWireframe();
888                        exporter->SetFilled();
889
890                        Material m;//= RandomMaterial();
891                        m.mDiffuseColor = RgbColor(0, 1, 0);
892                        exporter->SetForcedMaterial(m);
893
894                        if (vc->GetMesh())
895                                exporter->ExportViewCell(vc);
896                        else
897                        {
898                                PolygonContainer cell;
899                                // export view cell geometry
900                                mBspTree->ConstructGeometry(vc, cell);
901                                exporter->ExportPolygons(cell);
902                                CLEAR_CONTAINER(cell);
903                        }
904
905                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
906                                        << ", piercing rays=" << (int)vcRays[i].size() << endl;
907
908                        // export rays piercing this view cell
909                        exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0));
910
911                        m.mDiffuseColor = RgbColor(1, 0, 0);
912                        exporter->SetForcedMaterial(m);
913
914                        //exporter->SetWireframe();
915
916                        // output PVS of view cell
917                        for (; it != vc->GetPvs().mEntries.end(); ++ it)
918                        {
919                                Intersectable *intersect = (*it).first;
920                                if (!intersect->Mailed())
921                                {
922                                        exporter->ExportIntersectable(intersect);
923                                        intersect->Mail();
924                                }                       
925                        }
926                               
927                        // output rest of the objects
928                        if (0)
929                        {
930                                Material m;//= RandomMaterial();
931                                m.mDiffuseColor = RgbColor(0, 0, 1);
932                                exporter->SetForcedMaterial(m);
933
934                                for (int j = 0; j < objects.size(); ++ j)
935                                        if (!objects[j]->Mailed())
936                                        {
937                                                exporter->SetForcedMaterial(m);
938                                                exporter->ExportIntersectable(objects[j]);
939                                                objects[j]->Mail();
940                                        }
941                        }
942                        DEL_PTR(exporter);
943                        cout << "finished" << endl;
944                }
945        }
946        else
947        {
948                ViewCellContainer viewCells;
949
950                mBspTree->CollectViewCells(viewCells);
951                stable_sort(viewCells.begin(), viewCells.end(), vc_gt);
952
953                int limit = min(leafOut, (int)viewCells.size());
954               
955                for (int i = 0; i < limit; ++ i)
956                {
957                        cout << "creating output for view cell " << i << " ... ";
958                       
959            Intersectable::NewMail();
960                        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]);
961
962                        cout << "creating output for view cell " << i << " ... ";
963                        // check whether we can add the current ray to the output rays
964                        for (int k = 0; k < raysOut; ++ k)
965                        {
966                                Ray *ray = mSampleRays[k];
967
968                                for     (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
969                                {
970                                        BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
971
972                                        if (vc == leaf->GetViewCell())
973                                        {
974                                                vcRays[i].push_back(ray);
975                                        }
976                                }
977                        }
978
979                        //bspLeaves[j]->Mail();
980                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
981
982                        Exporter *exporter = Exporter::GetExporter(s);
983                        exporter->SetFilled();
984
985                        ViewCellPvsMap::iterator it = vc->GetPvs().mEntries.begin();
986
987                        exporter->SetFilled();//Wireframe();
988
989                        Material m;//= RandomMaterial();
990                        m.mDiffuseColor = RgbColor(0, 1, 0);
991                        exporter->SetForcedMaterial(m);
992
993                        if (vc->GetMesh())
994                                exporter->ExportViewCell(vc);
995                        else
996                        {
997                                PolygonContainer cell;
998                                // export view cell
999                                mBspTree->ConstructGeometry(vc, cell);
1000                                exporter->ExportPolygons(cell);
1001                                CLEAR_CONTAINER(cell);
1002                        }
1003
1004                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize() << endl;
1005
1006                       
1007                        // export rays piercing this view cell
1008                        exporter->ExportRays(vcRays[i], 10000, RgbColor(0, 1, 0));
1009
1010                        m.mDiffuseColor = RgbColor(1, 0, 0);
1011                        exporter->SetForcedMaterial(m);
1012
1013                        // output PVS of view cell
1014                        for (; it != vc->GetPvs().mEntries.end(); ++ it)
1015                        {
1016                                Intersectable *intersect = (*it).first;
1017                                if (!intersect->Mailed())
1018                                {
1019                                        exporter->ExportIntersectable(intersect);
1020                                        intersect->Mail();
1021                                }                       
1022                        }
1023                               
1024                        DEL_PTR(exporter);
1025                        cout << "finished" << endl;
1026                }
1027        }
1028}
1029
1030
1031Real SamplingPreprocessor::RenderPvs(ViewCell &viewCell,
1032                                                                         const float objRenderTime) const
1033{
1034        return viewCell.GetPvs().GetSize() * objRenderTime;
1035}
1036
1037Real SamplingPreprocessor::SimulateRendering()
1038{
1039        Real renderTime = 0;
1040
1041        // render time for 1 object of PVS
1042        const float objRt = 1.0f;
1043         // const overhead for crossing a view cell border
1044        const float vcOverhead = 0;//0.01f;
1045       
1046        // total area of view cells
1047        float totalArea = 0;//= mKdTree->GetBox().SurfaceArea();
1048
1049        ViewCellContainer viewCells;
1050
1051        mBspTree->CollectViewCells(viewCells);
1052
1053        ViewCellContainer::const_iterator it, it_end = viewCells.end();
1054       
1055        for (it = viewCells.begin(); it != it_end; ++ it)
1056        {
1057                // surface area substitute for probability
1058                PolygonContainer cell;
1059                float area = 0;
1060
1061                mBspTree->ConstructGeometry(dynamic_cast<BspViewCell *>(*it), cell);
1062
1063                area = Polygon3::GetArea(cell);
1064               
1065                renderTime += area * RenderPvs(*(*it), objRt) + vcOverhead;
1066                totalArea += area;
1067                CLEAR_CONTAINER(cell);
1068        }
1069
1070        renderTime /= totalArea;
1071
1072        //Debug << "render time without overhead: " << renderTime * 1e-3 << endl;
1073        //renderTime += (float)viewCells.size() * vcOverhead;
1074
1075        return renderTime;
1076}
Note: See TracBrowser for help on using the repository browser.