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

Revision 411, 29.1 KB checked in by mattausch, 19 years ago (diff)

worked on view space partition kd tree

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