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

Revision 441, 12.8 KB checked in by mattausch, 19 years ago (diff)

added visibilitymanager
removed area computation from bsp

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