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

Revision 466, 12.2 KB checked in by bittner, 19 years ago (diff)

changed the viewcellsmanager interface to use vssrays - some functionality like the bsp merging is now restricted

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