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

Revision 452, 12.7 KB checked in by mattausch, 19 years ago (diff)

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