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

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