source: GTP/trunk/Lib/Vis/Preprocessing/src/SamplingPreprocessor.cpp @ 1112

Revision 1112, 11.4 KB checked in by bittner, 18 years ago (diff)

Merge with Olivers code

RevLine 
[372]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"
[439]9#include "ViewCellsManager.h"
[406]10#include "RenderSimulator.h"
[372]11
[860]12
[863]13namespace GtpVisibilityPreprocessor {
[860]14
15
[411]16SamplingPreprocessor::SamplingPreprocessor(): mPass(0)
[372]17{
18  // this should increase coherence of the samples
[1004]19  Environment::GetSingleton()->GetIntValue("Sampling.samplesPerPass", mSamplesPerPass);
20  Environment::GetSingleton()->GetIntValue("Sampling.totalSamples", mTotalSamples);
[409]21 
[372]22  mStats.open("stats.log");
23}
24
25SamplingPreprocessor::~SamplingPreprocessor()
26{
27        CLEAR_CONTAINER(mSampleRays);
[440]28        CLEAR_CONTAINER(mVssSampleRays);
[372]29}
30
31void
32SamplingPreprocessor::SetupRay(Ray &ray,
[441]33                                                           const Vector3 &point,
34                                                           const Vector3 &direction,
[440]35                                                           const int type,
36                                                           const Ray::Intersection &origin)
[372]37{
[466]38  ray.Clear();
[440]39 
[374]40        ray.mFlags |= Ray::STORE_KDLEAVES | Ray::STORE_BSP_INTERSECTIONS;
[444]41        //  cout<<point<<" "<<direction<<endl;
42
43        ray.Init(point, direction, type);
[440]44        ray.sourceObject = origin;
[372]45}
46
[429]47void
48SamplingPreprocessor::HoleSamplingPass()
49{
50  vector<KdLeaf *> leaves;
51  mKdTree->CollectLeaves(leaves);
52 
53  // go through all the leaves and evaluate their passing contribution
54  for (int i=0 ; i < leaves.size(); i++) {
55    KdLeaf *leaf = leaves[i];
56    cout<<leaf->mPassingRays<<endl;
57  }
58}
59
[372]60 
[441]61void
[466]62SamplingPreprocessor::CastRays(const RayContainer &rays)
[441]63{       
[466]64  // cast ray to KD tree to find intersection with other objects
65  RayContainer::const_iterator it, it_end = rays.end();
[372]66
[466]67  VssRayContainer vssRays;
68  for (it = rays.begin(); it != it_end; ++it) {
69        mKdTree->CastRay(*(*it));
70        vssRays.push_back(new VssRay(*(*it)));
71  }
72 
[574]73  mViewCellsManager->ComputeSampleContributions(vssRays, true, false);
[466]74  CLEAR_CONTAINER(vssRays);
[372]75}
76
77int
[441]78SamplingPreprocessor::CastRay(Ray &ray)
[372]79{
80        // cast ray to KD tree to find intersection with other objects
[469]81        mKdTree->CastRay(ray);
82        VssRay vssRay(ray);
83
[574]84        mViewCellsManager->ComputeSampleContributions(vssRay, true, false);
[469]85       
86        return vssRay.mPvsContribution;
[372]87}
88
89
90
91int
92SamplingPreprocessor::CastEdgeSamples(
[441]93                                                                          Intersectable *object,
94                                                                          const Vector3 &point,
95                                                                          MeshInstance *mi,
96                                                                          const int samples
97                                                                          )
[372]98{
99        Ray ray;
100        int maxTries = samples*10;
101        int i;
102        int rays = 0;
103        int edgeSamplesContributions = 0;
104        for (i=0; i < maxTries && rays < samples; i++) {
105                // pickup a random face of each mesh
106                Mesh *mesh = mi->GetMesh();
[477]107                int face = (int)RandomValue(0, (Real)((int)mesh->mFaces.size() - 1));
[372]108               
109                Polygon3 poly(mesh->mFaces[face], mesh);
[469]110                poly.Scale(1.001f);
[372]111                // now extend a random edge of the face
[477]112                int edge = (int)RandomValue(0, (Real)((int)poly.mVertices.size() - 1));
[469]113                float t = RandomValue(0.0f, 1.0f);
[372]114                Vector3 target = t*poly.mVertices[edge] + (1.0f-t)*poly.mVertices[(edge + 1)%
[441]115                        poly.mVertices.size()];
[440]116                SetupRay(ray, point, target - point, Ray::LOCAL_RAY, Ray::Intersection(0, object, 0));
[372]117                if (!mesh->CastRay(ray, mi)) {
118                        // the rays which intersect the mesh have been discarded since they are not tangent
119                        // to the mesh
120                        rays++;
[440]121                        edgeSamplesContributions += CastRay(ray);
[372]122                }
123        }
124        return edgeSamplesContributions;
125}
126
127KdNode *
128SamplingPreprocessor::GetNodeToSample(Intersectable *object)
129{
130        int pvsSize = object->mKdPvs.GetSize();
131        KdNode *nodeToSample = NULL;
132       
133        bool samplePvsBoundary = false;
134        if (pvsSize && samplePvsBoundary) {
135                // this samples the nodes from the boundary of the current PVS
136                // mail all nodes from the pvs
137                Intersectable::NewMail();
138                KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
139               
140                for (; i != object->mKdPvs.mEntries.end(); i++) {
141                        KdNode *node = (*i).first;
142                        node->Mail();
143                }
144               
145                int maxTries = 2*pvsSize;
146                Debug << "Finding random neighbour" << endl;   
147                for (int tries = 0; tries < 10; tries++) {
[477]148                        int index = (int)RandomValue(0, (Real)(pvsSize - 1));
[372]149                        KdPvsData data;
150                        KdNode *node;
151                        object->mKdPvs.GetData(index, node, data);
152                        nodeToSample = mKdTree->FindRandomNeighbor(node, true);
153                        if (nodeToSample)
154                                break;
155                }
156        } else {
157                // just pickup a random node
158                //              nodeToSample = mKdTree->GetRandomLeaf(Plane3(normal, point));
159                nodeToSample = mKdTree->GetRandomLeaf();
160        }
161        return nodeToSample;
162}
163
164void
165SamplingPreprocessor::VerifyVisibility(Intersectable *object)
166{
167        // mail all nodes from the pvs
168        Intersectable::NewMail();
169        KdPvsMap::iterator i = object->mKdPvs.mEntries.begin();
170        for (; i != object->mKdPvs.mEntries.end(); i++) {
171                KdNode *node = (*i).first;
172                node->Mail();
173        }
174        Debug << "Get all neighbours from PVS" << endl;
175        vector<KdNode *> invisibleNeighbors;
176        // get all neighbors of all PVS nodes
177        i = object->mKdPvs.mEntries.begin();
178        for (; i != object->mKdPvs.mEntries.end(); i++) {
179                KdNode *node = (*i).first;
180                mKdTree->FindNeighbors(node, invisibleNeighbors, true);
181                AxisAlignedBox3 box = object->GetBox();
182                for (int j=0; j < invisibleNeighbors.size(); j++) {
183                        int visibility = ComputeBoxVisibility(mSceneGraph,
184                                                              mKdTree,
185                                                              box,
186                                                              mKdTree->GetBox(invisibleNeighbors[j]),
187                                                              1e-6f);
188                        //            exit(0);
189                }
190                // now rank all the neighbors according to probability that a new
191                // sample creates some contribution
192        }
193}
194
195bool
196SamplingPreprocessor::ComputeVisibility()
197{
198 
[440]199  /// rays per pass
200  RayContainer passRays;
201
[372]202
[487]203  mViewCellsManager->SetViewSpaceBox(mKdTree->GetBox());
204 
[372]205  Vector3 point, normal, direction;
[440]206  //Ray ray;
[372]207
208  long startTime = GetTime();
209 
210  int i;
211  int totalSamples = 0;
212
[414]213  int pvsSize = 0;
[372]214
215  while (totalSamples < mTotalSamples) {
216                int passContributingSamples = 0;
217                int passSampleContributions = 0;
218                int passSamples = 0;
219                int index = 0;
220               
221                int reverseSamples = 0;
222               
[492]223                for (i = 0; i < mObjects.size(); i++) {
[372]224                                               
225                        KdNode *nodeToSample = NULL;
[492]226                        Intersectable *object = mObjects[i];
[372]227               
228                        int pvsSize = 0;
229                       
230                        if (0 && pvsSize && mPass == 1000 ) {
231                                VerifyVisibility(object);
232                        }
233                       
234                        int faceIndex = object->GetRandomSurfacePoint(point, normal);
235                       
236                        bool viewcellSample = true;
[440]237                        //int sampleContributions;
[372]238                        bool debug = false; //(object->GetId() >= 2199);
239                        if (viewcellSample) {
240                                //mKdTree->GetRandomLeaf(Plane3(normal, point));
241
242                                nodeToSample = GetNodeToSample(object);
243
244                                for (int k=0; k < mSamplesPerPass; k++) {
245                                        bool reverseSample = false;
[441]246                               
[372]247                                        if (nodeToSample) {
248                                                AxisAlignedBox3 box = mKdTree->GetBox(nodeToSample);
249                                                Vector3 pointToSample = box.GetRandomPoint();
250                                                //                                              pointToSample.y = 0.9*box.Min().y + 0.1*box.Max().y;
251                                                if (object->GetRandomVisibleSurfacePoint( point, normal, pointToSample, 3 )) {
252                                                        direction = pointToSample - point;
253                                                } else {
254                                                        reverseSamples++;
255                                                        reverseSample = true;
256                                                        direction = point - pointToSample;
257                                                        point = pointToSample;
[429]258                                                        //Debug << "point: " << pointToSample << endl;
[372]259                                                }
260                                        }
261                                        else {
262                                                direction = UniformRandomVector(normal);
263                                        }
264                                       
[440]265                                        Ray *ray = new Ray();
266
[372]267                                        // construct a ray
[444]268                                        SetupRay(*ray, point, direction, Ray::LOCAL_RAY,
269                                                         Ray::Intersection(0, reverseSample ? NULL : object, faceIndex));
270
[440]271                                        passRays.push_back(ray);
[372]272                                       
273                                        //-- CORR matt: put block inside loop
[440]274                                        /*if (sampleContributions) {
[372]275                                                passContributingSamples ++;
276                                                passSampleContributions += sampleContributions;
[440]277                                        }*/
[372]278                                }
279                        } else {
280                                // edge samples
281                                // get random visible mesh
282                                //                              object->GetRandomVisibleMesh(Plane3(normal, point));
283                        }
284       
285                        // CORR matt: must add all samples
286                        passSamples += mSamplesPerPass;
287                }
288       
[441]289                //-------------------
290                // cast rays for view cells construction
291                ProcessViewCells(passRays,
[492]292                                                 mObjects,
[441]293                                                 passSampleContributions,
294                                                 passContributingSamples);
295
[440]296                CLEAR_CONTAINER(passRays);
[441]297               
[372]298                totalSamples += passSamples;
299               
300                //    if (pass>10)
301                //      HoleSamplingPass();
302   
[441]303                mPass ++;
[414]304       
[441]305                pvsSize += passSampleContributions;
[440]306               
[372]307                float avgRayContrib = (passContributingSamples > 0) ?
[451]308                        passSampleContributions / (float)passContributingSamples : 0;
[372]309
310                cout << "#Pass " << mPass << " : t = " << TimeDiff(startTime, GetTime())*1e-3 << "s" << endl;
311                cout << "#TotalSamples=" << totalSamples/1000
312                                 << "k   #SampleContributions=" << passSampleContributions << " ("
313                                 << 100*passContributingSamples/(float)passSamples<<"%)" << " avgPVS="
[492]314                                 << (float)pvsSize /(float)mObjects.size() << endl
[372]315                                 << "avg ray contrib=" << avgRayContrib << endl
316                                 << "reverse samples [%]" << reverseSamples/(float)passSamples*100.0f << endl;
317
318                mStats <<
319                        "#Pass\n" <<mPass<<endl<<
320                        "#Time\n" << TimeDiff(startTime, GetTime())*1e-3 << endl<<
321                        "#TotalSamples\n" << totalSamples<< endl<<
322                        "#SampleContributions\n" << passSampleContributions << endl <<
323                        "#PContributingSamples\n"<<100*passContributingSamples/(float)passSamples<<endl <<
[492]324                        "#AvgPVS\n"<< pvsSize/(float)mObjects.size() << endl <<
[372]325                        "#AvgRayContrib\n" << avgRayContrib << endl;
326        }
327       
[440]328        //cout << "#totalKdPvsSize=" << mKdTree->CollectLeafPvs() << endl;
[372]329       
330  //  HoleSamplingPass();
331        if (0) {
332                Exporter *exporter = Exporter::GetExporter("ray-density.x3d");
333                exporter->SetExportRayDensity(true);
334                exporter->ExportKdTree(*mKdTree);
[422]335                delete exporter;
336        }
[452]337       
338        // construct view cells if not already constructed
339        if (!mViewCellsManager->ViewCellsConstructed())
[574]340          mViewCellsManager->ConstructSubdivision(mObjects, mVssSampleRays);
[372]341
[466]342        // $$JB temporary removed
343        //      mViewCellsManager->PostProcess(objects, mSampleRays);
[452]344       
345        //-- several visualizations and statistics
[475]346        Debug << "view cells after post processing: " << endl;
[452]347        mViewCellsManager->PrintStatistics(Debug);
348
[448]349        //-- render simulation after merge
350        cout << "\nevaluating bsp view cells render time after merge ... ";
351       
[468]352         mRenderSimulator->RenderScene();
353         SimulationStatistics ss;
354         mRenderSimulator->GetStatistics(ss);
355         
356         cout << " finished" << endl;
357         cout << ss << endl;
358         Debug << ss << endl;
359       
[466]360        // $$JB temporary removed
361        //mViewCellsManager->Visualize(objects, mSampleRays);   
[462]362   
[441]363        return true;
[362]364}
[349]365
[441]366void SamplingPreprocessor::ProcessViewCells(const RayContainer &newRays,
[440]367                                                                                        const ObjectContainer &objects,
[441]368                                                                                        int &sampleContributions,
369                                                                                        int &contributingSamples)
[439]370{
[466]371  // cast rays to view cells
372  CastRays(newRays);
[441]373
[466]374  // save rays for view cells construction
375  if (!mViewCellsManager->ViewCellsConstructed())
[441]376        {
[466]377          if ((int)mVssSampleRays.size() < mViewCellsManager->GetConstructionSamples())
[452]378                {
[466]379                  RayContainer::const_iterator it, it_end = newRays.end();
380                 
381                  for (it = newRays.begin(); it != it_end; ++ it)
382                        mVssSampleRays.push_back(new VssRay(*(*it)));
[441]383                }
[466]384          else
[411]385                {
[466]386                  // construct view cells
[574]387                  mViewCellsManager->ConstructSubdivision(objects, mVssSampleRays);
[466]388                 
389                  // throw away samples
390                  //CLEAR_CONTAINER(mVssSampleRays);
[411]391                }
392        }
[466]393  // Need rays (with ordered intersections) for post processing => collect new rays
394  if (((int)mSampleRays.size() < mViewCellsManager->GetPostProcessSamples()) ||
395          ((int)mSampleRays.size() < mViewCellsManager->GetVisualizationSamples()))
[372]396        {
[466]397          RayContainer::const_iterator it, it_end = newRays.end();
398         
399          for (it = newRays.begin(); it != it_end; ++ it)
400                mSampleRays.push_back(new Ray(*(*it)));
[372]401        }
[362]402}
[860]403
[1112]404}
Note: See TracBrowser for help on using the repository browser.