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

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