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

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