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

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