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

Revision 406, 27.3 KB checked in by mattausch, 19 years ago (diff)

started kd based bottom-up view cells

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 << "#totalPvsSize=" << mKdTree->CollectLeafPvs() << endl;
540 
541        if (mBspTree)
542        {
543                //-- render simulation
544                cout << "\nevaluating 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   for (int k=0; k < pvsOut; k++) {
655                 Intersectable *object = objects[k];
656                 char s[64];
657                 sprintf(s, "sample-pvs%04d.x3d", k);
658                 Exporter *exporter = Exporter::GetExporter(s);
659                 exporter->SetWireframe();
660                 
661                 
662                 KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
663                 Intersectable::NewMail();
664                 
665                 // avoid adding the object to the list
666                 object->Mail();
667                 ObjectContainer visibleObjects;
668                 
669                 for (; i != object->mKdPvs.mEntries.end(); i++)
670                         {
671                                 KdNode *node = (*i).first;
672                                 exporter->ExportBox(mKdTree->GetBox(node));
673                                 mKdTree->CollectObjects(node, visibleObjects);
674                         }
675                 
676                 exporter->ExportRays(rays[k], 1000, RgbColor(0, 1, 0));
677                 exporter->SetFilled();
678                 
679                 for (int j = 0; j < visibleObjects.size(); j++)
680                         exporter->ExportIntersectable(visibleObjects[j]);
681                 
682                 
683                 Material m;
684                 m.mDiffuseColor = RgbColor(1, 0, 0);
685                 exporter->SetForcedMaterial(m);
686                 exporter->ExportIntersectable(object);
687                 
688                 delete exporter;
689         }
690  }
691 
692  return true;
693}
694
695void SamplingPreprocessor::ProcessBspViewCells(const Ray &ray,
696                                               Intersectable *object,
697                                                                                           const int faceIndex,
698                                                                                           int &contributingSamples,
699                                                                                           int &sampleContributions)
700{
701        // save rays for bsp tree construction
702        if (!mBspTree)
703        {
704                if ((BspTree::sConstructionMethod == BspTree::FROM_RAYS) &&
705                        ((int)mSampleRays.size() < mBspConstructionSamples))
706                {
707                        MeshInstance *mi = dynamic_cast<MeshInstance *>(object);
708                       
709                        Ray *sRay = new Ray(ray);
710                        mSampleRays.push_back(sRay);
711               
712                        // also add origin to sample
713                        sRay->sourceObject = Ray::Intersection(0.0, object, faceIndex);
714                }
715                else
716                {
717                        // construct BSP tree using the collected samples
718                        cout << "building bsp tree from " << (int)mSampleRays.size() << " samples " << endl;
719                        BuildBspTree();
720               
721                        // add contributions of saved samples to PVS
722                        contributingSamples += mBspTree->GetStat().contributingSamples;
723                        sampleContributions += mBspTree->GetStat().sampleContributions;
724
725                        BspTreeStatistics(Debug);       
726
727                        if (0) Export("vc_bsptree.x3d", false, false, true);
728
729                        // throw away samples because BSP leaves not stored in order
730                        // Need ordered rays for post processing => collect new rays
731                        CLEAR_CONTAINER(mSampleRays);
732                }
733        }
734        // save rays for post processing
735        else if (((int)mSampleRays.size() < mPostProcessSamples) ||
736                         ((int)mSampleRays.size() < mVisualizationSamples))
737        {
738                mSampleRays.push_back(new Ray(ray));
739        }
740}
741
742// merge or subdivide view cells
743int SamplingPreprocessor::PostprocessViewCells(const RayContainer &rays)
744{
745        int merged = 0;
746
747        RayContainer::const_iterator rit, rit_end = rays.end();
748        vector<Ray::BspIntersection>::const_iterator iit;
749
750        int limit = min((int)mSampleRays.size(), mPostProcessSamples);
751
752        for (int i = 0; i < limit; ++i)
753        { 
754                Ray *ray = mSampleRays[i];
755
756                // traverse leaves stored in the rays and compare and merge consecutive
757                // leaves (i.e., the neighbors in the tree)
758                if (ray->bspIntersections.empty())
759                        continue;
760
761                iit = ray->bspIntersections.begin();
762
763                BspLeaf *previousLeaf = (*iit).mLeaf;
764                ++ iit;
765               
766                for (; iit != (*rit)->bspIntersections.end(); ++ iit)
767                {
768                        BspLeaf *leaf = (*iit).mLeaf;
769
770                        if (mBspTree->ShouldMerge(leaf, previousLeaf))
771                        {                       
772                                mBspTree->MergeViewCells(leaf, previousLeaf);
773
774                                ++ merged;
775                        }
776                        previousLeaf = leaf;
777                }
778        }
779
780        return merged;
781}
782
783void SamplingPreprocessor::ExportSplits(const ObjectContainer &objects)
784{
785        Exporter *exporter = Exporter::GetExporter("bsp_splits.x3d");
786
787        if (exporter)
788        {       
789                Material m;
790                m.mDiffuseColor = RgbColor(1, 0, 0);
791                exporter->SetForcedMaterial(m);
792                exporter->SetWireframe();
793                exporter->ExportBspSplits(*mBspTree, true);
794
795                // take forced material, else big scenes cannot be viewed
796                m.mDiffuseColor = RgbColor(0, 1, 0);
797                exporter->SetForcedMaterial(m);
798                exporter->SetFilled();
799
800                exporter->ResetForcedMaterial();
801               
802                // export rays
803                if (0)
804                {
805                        RayContainer outRays;
806               
807                        for (int i = 0; i < mSampleRays.size(); ++ i)
808                        {
809                                // only rays piercing geometry
810                                if (!mSampleRays[i]->intersections.empty())
811                                        outRays.push_back(mSampleRays[i]);
812                        }
813                        if (BspTree::sConstructionMethod == BspTree::FROM_RAYS)
814                        {
815                                // export rays
816                                exporter->ExportRays(outRays, 1000, RgbColor(1, 1, 0));
817                        }
818                }
819
820                // export scene geometry
821                if (0)
822                {
823                        Material m;//= RandomMaterial();
824                        m.mDiffuseColor = RgbColor(0, 1, 0);
825                        exporter->SetForcedMaterial(m);
826            exporter->SetWireframe();
827
828                        for (int j = 0; j < objects.size(); ++ j)
829                                exporter->ExportIntersectable(objects[j]);
830                }
831
832                delete exporter;
833        }
834}
835
836inline bool vc_gt(ViewCell *a, ViewCell *b)
837{
838        return a->GetPvs().GetSize() > b->GetPvs().GetSize();
839}
840
841void SamplingPreprocessor::ExportBspPvs(const ObjectContainer &objects)
842{
843        const int leafOut = 10;
844       
845        ViewCell::NewMail();
846
847        //-- some rays for output
848        const int raysOut = min((int)mSampleRays.size(), mVisualizationSamples);
849        cout << "visualization using " << mVisualizationSamples << " samples" << endl;
850        vector<Ray *> vcRays[leafOut];
851
852        if (0){
853                //-- some random view cells and rays for output
854                vector<BspLeaf *> bspLeaves;
855
856                for (int i = 0; i < leafOut; ++ i)
857                        bspLeaves.push_back(mBspTree->GetRandomLeaf());
858               
859                for (int i = 0; i < bspLeaves.size(); ++ i)
860                {
861                        cout << "creating output for view cell " << i << " ... ";
862                        // check whether we can add the current ray to the output rays
863                        for (int k = 0; k < raysOut; ++ k)
864                        {
865                                Ray *ray = mSampleRays[k];
866
867                                for     (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
868                                {
869                                        BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
870
871                                        if (bspLeaves[i]->GetViewCell() == leaf->GetViewCell())
872                                        {
873                                                vcRays[i].push_back(ray);
874                                        }
875                                }
876                        }
877
878                        Intersectable::NewMail();
879
880                        BspViewCell *vc = dynamic_cast<BspViewCell *>(bspLeaves[i]->GetViewCell());
881
882                        //bspLeaves[j]->Mail();
883                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
884
885                        Exporter *exporter = Exporter::GetExporter(s);
886                        exporter->SetFilled();
887
888                        ViewCellPvsMap::iterator it = vc->GetPvs().mEntries.begin();
889
890                        exporter->SetWireframe();
891                        //exporter->SetFilled();
892
893                        Material m;//= RandomMaterial();
894                        m.mDiffuseColor = RgbColor(0, 1, 0);
895                        exporter->SetForcedMaterial(m);
896
897                        if (vc->GetMesh())
898                                exporter->ExportViewCell(vc);
899                        else
900                        {
901                                PolygonContainer cell;
902                                // export view cell geometry
903                                mBspTree->ConstructGeometry(vc, cell);
904                                exporter->ExportPolygons(cell);
905                                CLEAR_CONTAINER(cell);
906                        }
907
908                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
909                                        << ", piercing rays=" << (int)vcRays[i].size() << endl;
910
911                        // export rays piercing this view cell
912                        exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0));
913
914                        m.mDiffuseColor = RgbColor(1, 0, 0);
915                        exporter->SetForcedMaterial(m);
916
917                        // exporter->SetWireframe();
918                        exporter->SetFilled();
919
920                        // output PVS of view cell
921                        for (; it != vc->GetPvs().mEntries.end(); ++ it)
922                        {
923                                Intersectable *intersect = (*it).first;
924                                if (!intersect->Mailed())
925                                {
926                                        exporter->ExportIntersectable(intersect);
927                                        intersect->Mail();
928                                }                       
929                        }
930                               
931                        // output rest of the objects
932                        if (0)
933                        {
934                                Material m;//= RandomMaterial();
935                                m.mDiffuseColor = RgbColor(0, 0, 1);
936                                exporter->SetForcedMaterial(m);
937
938                                for (int j = 0; j < objects.size(); ++ j)
939                                        if (!objects[j]->Mailed())
940                                        {
941                                                exporter->SetForcedMaterial(m);
942                                                exporter->ExportIntersectable(objects[j]);
943                                                objects[j]->Mail();
944                                        }
945                        }
946                        DEL_PTR(exporter);
947                        cout << "finished" << endl;
948                }
949        }
950        else
951        {
952                ViewCellContainer viewCells;
953
954                mBspTree->CollectViewCells(viewCells);
955                stable_sort(viewCells.begin(), viewCells.end(), vc_gt);
956
957                int limit = min(leafOut, (int)viewCells.size());
958               
959                for (int i = 0; i < limit; ++ i)
960                {
961                        cout << "creating output for view cell " << i << " ... ";
962                       
963            Intersectable::NewMail();
964                        BspViewCell *vc = dynamic_cast<BspViewCell *>(viewCells[i]);
965
966                        cout << "creating output for view cell " << i << " ... ";
967                        // check whether we can add the current ray to the output rays
968                        for (int k = 0; k < raysOut; ++ k)
969                        {
970                                Ray *ray = mSampleRays[k];
971
972                                for     (int j = 0; j < (int)ray->bspIntersections.size(); ++ j)
973                                {
974                                        BspLeaf *leaf = ray->bspIntersections[j].mLeaf;
975
976                                        if (vc == leaf->GetViewCell())
977                                        {
978                                                vcRays[i].push_back(ray);
979                                        }
980                                }
981                        }
982
983                        //bspLeaves[j]->Mail();
984                        char s[64]; sprintf(s, "bsp-pvs%04d.x3d", i);
985
986                        Exporter *exporter = Exporter::GetExporter(s);
987                       
988                        exporter->SetWireframe();
989
990                        Material m;//= RandomMaterial();
991                        m.mDiffuseColor = RgbColor(0, 1, 0);
992                        exporter->SetForcedMaterial(m);
993
994                        if (vc->GetMesh())
995                                exporter->ExportViewCell(vc);
996                        else
997                        {
998                                PolygonContainer cell;
999                                // export view cell
1000                                mBspTree->ConstructGeometry(vc, cell);
1001                                exporter->ExportPolygons(cell);
1002                                CLEAR_CONTAINER(cell);
1003                        }
1004
1005                       
1006                        Debug << i << ": pvs size=" << (int)vc->GetPvs().GetSize()
1007                                        << ", piercing rays=" << (int)vcRays[i].size() << endl;
1008
1009                       
1010                        // export rays piercing this view cell
1011                        exporter->ExportRays(vcRays[i], 1000, RgbColor(0, 1, 0));
1012       
1013                        m.mDiffuseColor = RgbColor(1, 0, 0);
1014                        exporter->SetForcedMaterial(m);
1015
1016                        ViewCellPvsMap::const_iterator it,
1017                                it_end = vc->GetPvs().mEntries.end();
1018
1019                        // output PVS of view cell
1020                        for (it = vc->GetPvs().mEntries.begin(); it != it_end; ++ it)
1021                        {
1022                                Intersectable *intersect = (*it).first;
1023                                if (!intersect->Mailed())
1024                                {
1025                                        Material m = RandomMaterial();
1026                       
1027                                        exporter->SetForcedMaterial(m);
1028
1029                                        exporter->ExportIntersectable(intersect);
1030                                        intersect->Mail();
1031                                }                       
1032                        }
1033                               
1034                        DEL_PTR(exporter);
1035                        cout << "finished" << endl;
1036                }
1037        }
1038}
Note: See TracBrowser for help on using the repository browser.