source: GTP/trunk/Lib/Vis/Preprocessing/src/GvsPreprocessor.cpp @ 1990

Revision 1990, 23.7 KB checked in by mattausch, 17 years ago (diff)
  • Property svn:executable set to *
Line 
1#include "Environment.h"
2#include "GvsPreprocessor.h"
3#include "GlRenderer.h"
4#include "VssRay.h"
5#include "ViewCellsManager.h"
6#include "Triangle3.h"
7#include "IntersectableWrapper.h"
8#include "Plane3.h"
9#include "RayCaster.h"
10#include "Exporter.h"
11#include "SamplingStrategy.h"
12#include "BvHierarchy.h"
13
14
15namespace GtpVisibilityPreprocessor
16{
17 
18#define GVS_DEBUG 1
19
20struct VizStruct
21{
22        Polygon3 *enlargedTriangle;
23        Triangle3 originalTriangle;
24        VssRay *ray;
25};
26
27static const float MIN_DIST = 0.01f;
28
29static vector<VizStruct> vizContainer;
30
31GvsPreprocessor::GvsPreprocessor():
32Preprocessor(),
33mSamplingType(SamplingStrategy::VIEWCELL_BASED_DISTRIBUTION),
34//mSamplingType(SamplingStrategy::DIRECTION_BASED_DISTRIBUTION),
35mNumViewCells(0),
36mCurrentViewCell(NULL)
37{
38        Environment::GetSingleton()->GetIntValue("GvsPreprocessor.totalSamples", mTotalSamples);
39        Environment::GetSingleton()->GetIntValue("GvsPreprocessor.initialSamples", mInitialSamples);
40        Environment::GetSingleton()->GetIntValue("GvsPreprocessor.samplesPerPass", mSamplesPerPass);
41        Environment::GetSingleton()->GetFloatValue("GvsPreprocessor.epsilon", mEps);
42        Environment::GetSingleton()->GetFloatValue("GvsPreprocessor.threshold", mThreshold);   
43        Environment::GetSingleton()->GetBoolValue("GvsPreprocessor.perViewCell", mPerViewCell);
44
45        char gvsStatsLog[100];
46        Environment::GetSingleton()->GetStringValue("GvsPreprocessor.stats", gvsStatsLog);
47        mGvsStatsStream.open(gvsStatsLog);
48
49        Debug << "Gvs preprocessor options" << endl;
50        Debug << "number of total samples: " << mTotalSamples << endl;
51        Debug << "number of initial samples: " << mInitialSamples << endl;
52        Debug << "number of samples per pass: " << mSamplesPerPass << endl;
53        Debug << "threshold: " << mThreshold << endl;
54        Debug << "epsilon: " << mEps << endl;
55        Debug << "stats: " << gvsStatsLog << endl;
56
57        if (1)
58                mOnlyRandomSampling = false;           
59        else
60                mOnlyRandomSampling = true;
61
62        mGvsStats.Reset();
63}
64
65
66GvsPreprocessor::~GvsPreprocessor()
67{
68        // clean ray queue
69        while (!mRayQueue.empty())
70        {
71                // handle next ray
72                VssRay *ray = mRayQueue.top();
73                mRayQueue.pop();
74
75                delete ray;
76        }
77}
78
79
80bool GvsPreprocessor::NextViewCell()
81{
82        if (mViewCellsManager->GetNumViewCells() == mNumViewCells)
83                return false; // no more view cells
84
85    if (1)
86                mCurrentViewCell = mViewCellsManager->GetViewCell(mNumViewCells);
87        else
88        {
89                // HACK
90                int idx = (int)RandomValue(0.0f, (float)mViewCellsManager->GetNumViewCells() - 0.5f);
91                mCurrentViewCell = mViewCellsManager->GetViewCell(idx);
92        }
93
94        if (!mCurrentViewCell->GetMesh())
95                mViewCellsManager->CreateMesh(mCurrentViewCell);
96
97        ++ mNumViewCells;
98   
99        return true;
100}
101
102
103bool GvsPreprocessor::CheckDiscontinuity(const VssRay &currentRay,
104                                                                                 const Triangle3 &hitTriangle,
105                                                                                 const VssRay &oldRay)
106{
107        // the predicted hitpoint: we expect to hit the same mesh again
108        const Vector3 predictedHit = CalcPredictedHitPoint(currentRay, hitTriangle, oldRay);
109
110        const float predictedLen = Magnitude(predictedHit - currentRay.mOrigin);
111        const float len = Magnitude(currentRay.mTermination - currentRay.mOrigin);
112       
113        // distance large => this is likely to be a discontinuity
114#if 1
115        if ((predictedLen - len) > mThreshold)
116#else // rather use relative distance
117        if ((predictedLen / len) > mThreshold)
118#endif
119        {
120                //cout << "r";
121                // apply reverse sampling to find the gap
122                VssRay *newRay = ReverseSampling(currentRay, hitTriangle, oldRay);
123
124                if (!newRay)
125                        return false;
126
127                // set flag for visualization
128                newRay->mFlags |= VssRay::ReverseSample;
129               
130                // if ray is not further processed => delete ray
131                if (!HandleRay(newRay))
132                {
133                        delete newRay;
134                }
135                else if (0 && GVS_DEBUG && (mVssRays.size() < 9))
136                {
137                        mVssRays.push_back(new VssRay(oldRay));
138                        mVssRays.push_back(new VssRay(currentRay));
139                        mVssRays.push_back(new VssRay(*newRay));
140                }
141
142                return true;
143        }
144
145        return false;
146}
147
148
149bool GvsPreprocessor::HandleRay(VssRay *vssRay)
150{
151        // store the rays + the intersected view cells
152        const bool storeRaysForViz = false; //GVS_DEBUG;
153
154        if (!mPerViewCell)
155        {
156                mViewCellsManager->ComputeSampleContribution(*vssRay,
157                                                                                                         true,
158                                                                                                         storeRaysForViz,
159                                                                                                         true);
160        }
161        else
162        {
163                mViewCellsManager->ComputeSampleContribution(*vssRay,
164                                                                                                         true,
165                                                                                                         mCurrentViewCell,
166                                                                                                         true);
167        }
168
169        // some pvs contribution for this ray?
170        if (!vssRay->mPvsContribution)
171                return false;
172
173        if (GVS_DEBUG)
174                mVssRays.push_back(new VssRay(*vssRay));
175
176        // add new ray to ray queue
177        mRayQueue.push(vssRay);
178
179        if (storeRaysForViz)
180        {
181                VssRay *nray = new VssRay(*vssRay);
182                nray->mFlags = vssRay->mFlags;
183
184                // store ray in contributing view cell
185                ViewCellContainer::const_iterator vit, vit_end = vssRay->mViewCells.end();
186                for (vit = vssRay->mViewCells.begin(); vit != vit_end; ++ vit)
187                {                       
188                        (*vit)->GetOrCreateRays()->push_back(nray);                             
189                }
190        }
191
192        ++ mGvsStats.mTotalContribution;
193
194        return true;
195}
196
197
198/** Creates 3 new vertices for triangle vertex with specified index.
199*/
200void GvsPreprocessor::CreateDisplacedVertices(VertexContainer &vertices,
201                                                                                          const Triangle3 &hitTriangle,
202                                                                                          const VssRay &ray,
203                                                                                          const int index) const
204{
205        const int indexU = (index + 1) % 3;
206        const int indexL = (index == 0) ? 2 : index - 1;
207
208        const Vector3 a = hitTriangle.mVertices[index] - ray.GetOrigin();
209        const Vector3 b = hitTriangle.mVertices[indexU] - hitTriangle.mVertices[index];
210        const Vector3 c = hitTriangle.mVertices[index] - hitTriangle.mVertices[indexL];
211       
212        const float len = Magnitude(a);
213       
214        const Vector3 dir1 = Normalize(CrossProd(a, b)); //N((pi-xp)×(pi+1- pi));
215        const Vector3 dir2 = Normalize(CrossProd(a, c)); // N((pi-xp)×(pi- pi-1))
216        const Vector3 dir3 = DotProd(dir2, dir1) > 0 ? // N((pi-xp)×di,i-1+di,i+1×(pi-xp))
217                Normalize(dir2 + dir1) : Normalize(CrossProd(a, dir1) + CrossProd(dir2, a));
218
219        // compute the new three hit points
220        // pi, i + 1:  pi+ e·|pi-xp|·di, j
221        const Vector3 pt1 = hitTriangle.mVertices[index] + mEps * len * dir1;
222        // pi, i - 1:  pi+ e·|pi-xp|·di, j
223    const Vector3 pt2 = hitTriangle.mVertices[index] + mEps * len * dir2;
224        // pi, i:  pi+ e·|pi-xp|·di, j
225        const Vector3 pt3 = hitTriangle.mVertices[index] + mEps * len * dir3;
226       
227        vertices.push_back(pt2);
228        vertices.push_back(pt3);
229        vertices.push_back(pt1);
230}
231
232
233void GvsPreprocessor::EnlargeTriangle(VertexContainer &vertices,
234                                                                          const Triangle3 &hitTriangle,
235                                                                          const VssRay &ray) const
236{
237        CreateDisplacedVertices(vertices, hitTriangle, ray, 0);
238        CreateDisplacedVertices(vertices, hitTriangle, ray, 1);
239        CreateDisplacedVertices(vertices, hitTriangle, ray, 2);
240}
241
242
243Vector3 GvsPreprocessor::CalcPredictedHitPoint(const VssRay &newRay,
244                                                                                           const Triangle3 &hitTriangle,
245                                                                                           const VssRay &oldRay) const
246{
247        // find the intersection of the plane induced by the
248        // hit triangle with the new ray
249        Plane3 plane(hitTriangle.GetNormal(), hitTriangle.mVertices[0]);
250
251        const Vector3 hitPt =
252                plane.FindIntersection(newRay.mTermination, newRay.mOrigin);
253       
254        return hitPt;
255}
256
257
258static bool EqualVisibility(const VssRay &a, const VssRay &b)
259{
260        return a.mTerminationObject == b.mTerminationObject;
261}
262
263
264int GvsPreprocessor::SubdivideEdge(const Triangle3 &hitTriangle,
265                                                                   const Vector3 &p1,
266                                                                   const Vector3 &p2,
267                                                                   const VssRay &ray1,
268                                                                   const VssRay &ray2,
269                                                                   const VssRay &oldRay)
270{
271        // cast reverse rays if necessary
272        CheckDiscontinuity(ray1, hitTriangle, oldRay);
273        CheckDiscontinuity(ray2, hitTriangle, oldRay);
274
275        if (EqualVisibility(ray1, ray2) || (Magnitude(p1 - p2) <= MIN_DIST))
276        {
277                return 0;
278        }
279       
280        // the new subdivision point
281        const Vector3 p = (p1 + p2) * 0.5f;
282
283        // cast ray into the new point
284        SimpleRay sray(oldRay.mOrigin, p - oldRay.mOrigin, SamplingStrategy::GVS, 1.0f);
285
286        VssRay *newRay = mRayCaster->CastRay(sray, mViewCellsManager->GetViewSpaceBox(), mPerViewCell);
287
288        if (!newRay) return 0;
289
290        newRay->mFlags |= VssRay::BorderSample;
291
292        // add new ray to queue
293        const bool enqueued = HandleRay(newRay);
294
295        // subdivide further
296        const int samples1 = SubdivideEdge(hitTriangle, p1, p, ray1, *newRay, oldRay);
297        const int samples2 = SubdivideEdge(hitTriangle, p, p2, *newRay, ray2, oldRay);
298
299        // this ray will not be further processed
300        if (!enqueued)
301                delete newRay;
302
303        return samples1 + samples2 + 1;
304}
305
306
307int GvsPreprocessor::AdaptiveBorderSampling(const VssRay &currentRay)
308{
309        Intersectable *tObj = currentRay.mTerminationObject;
310        Triangle3 hitTriangle;
311
312        // other types not implemented yet
313        if (tObj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
314        {
315                hitTriangle = dynamic_cast<TriangleIntersectable *>(tObj)->GetItem();
316        }
317        else
318        {
319                cout << "not yet implemented" << endl;
320        }
321
322        VertexContainer enlargedTriangle;
323       
324        /// create 3 new hit points for each vertex
325        EnlargeTriangle(enlargedTriangle, hitTriangle, currentRay);
326       
327        /// create rays from sample points and handle them
328        SimpleRayContainer simpleRays;
329        simpleRays.reserve(9);
330
331        VertexContainer::const_iterator vit, vit_end = enlargedTriangle.end();
332
333        for (vit = enlargedTriangle.begin(); vit != vit_end; ++ vit)
334        {
335                const Vector3 rayDir = (*vit) - currentRay.GetOrigin();
336
337                SimpleRay sr(currentRay.GetOrigin(), rayDir, SamplingStrategy::GVS, 1.0f);
338                simpleRays.AddRay(sr); 
339        }
340
341        if (0)
342        {
343                // visualize enlarged triangles
344                VizStruct dummy;
345                dummy.enlargedTriangle = new Polygon3(enlargedTriangle);
346                dummy.originalTriangle = hitTriangle;
347                vizContainer.push_back(dummy);
348        }
349
350        // cast rays to triangle vertices and determine visibility
351        VssRayContainer vssRays;
352
353        // don't cast double rays as we need only the forward rays
354        const bool castDoubleRays = false;
355        // cannot prune invalid rays because we have to compare adjacent  rays.
356        const bool pruneInvalidRays = false;
357
358        // keep origin for per view cell sampling
359        CastRays(simpleRays, vssRays, castDoubleRays, pruneInvalidRays, mPerViewCell);
360
361        // set flags
362        VssRayContainer::const_iterator rit, rit_end = vssRays.end();
363        for (rit = vssRays.begin(); rit != rit_end; ++ rit)
364        {
365                (*rit)->mFlags |= VssRay::BorderSample;
366        }
367
368        // handle rays
369        EnqueueRays(vssRays);
370       
371        const int n = (int)vssRays.size();
372        int castRays = n;
373       
374    // recursivly subdivide each edge
375        for (int i = 0; i < n; ++ i)
376        {
377                castRays += SubdivideEdge(hitTriangle,
378                                                                  enlargedTriangle[i],
379                                                                  enlargedTriangle[(i + 1) % n],
380                                                                  *vssRays[i],
381                                                                  *vssRays[(i + 1) % n],
382                                                                  currentRay);
383        }
384
385        mGvsStats.mBorderSamples += castRays;
386
387        return castRays;
388}
389
390
391Vector3 GvsPreprocessor::GetPassingPoint(const VssRay &currentRay,
392                                                                                 const Triangle3 &occluder,
393                                                                                 const VssRay &oldRay) const
394{
395        //-- The plane p = (xp, hit(x), hit(xold)) is intersected
396        //-- with the newly found occluder (xold is the previous ray from
397        //-- which x was generated). On the intersecting line, we select a point
398        //-- pnew which lies just outside of the new triangle so the ray
399        //-- just passes through the gap
400
401        const Plane3 plane(currentRay.GetOrigin(),
402                                           currentRay.GetTermination(),
403                                           oldRay.GetTermination());
404       
405        Vector3 pt1, pt2;
406
407        const bool intersects = occluder.GetPlaneIntersection(plane, pt1, pt2);
408
409        if (!intersects)
410                cerr << "big error!! no intersection" << endl;
411
412        // get the intersection point on the old ray
413        const Plane3 triPlane(occluder.GetNormal(), occluder.mVertices[0]);
414
415        const float t = triPlane.FindT(oldRay.mOrigin, oldRay.mTermination);
416        const Vector3 pt3 = oldRay.mOrigin + t * (oldRay.mTermination - oldRay.mOrigin);
417
418        // Evaluate new hitpoint just outside the triangle
419        Vector3 newPoint;
420
421        const float eps = mEps;
422
423        // the point is chosen to be on the side closer to the original ray
424        if (Distance(pt1, pt3) < Distance(pt2, pt3))
425        {
426                newPoint = pt1 + eps * (pt1 - pt2);
427        }       
428        else
429        {
430                newPoint = pt2 + eps * (pt2 - pt1);
431        }
432
433        //cout << "passing point: " << newPoint << endl << endl;
434        return newPoint;
435}
436
437
438VssRay *GvsPreprocessor::ReverseSampling(const VssRay &currentRay,
439                                                                                 const Triangle3 &hitTriangle,
440                                                                                 const VssRay &oldRay)
441{
442        // get triangle occluding the path to the hit mesh
443        Triangle3 occluder;
444        Intersectable *tObj = currentRay.mTerminationObject;
445
446        // q: why can this happen?
447        if (!tObj)
448                return NULL;
449
450        // other types not implemented yet
451        if (tObj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
452                occluder = dynamic_cast<TriangleIntersectable *>(tObj)->GetItem();
453        else
454                cout << "not yet implemented" << endl;
455       
456        // get a point which is passing just outside of the occluder
457    const Vector3 newPoint = GetPassingPoint(currentRay, occluder, oldRay);
458        const Vector3 predicted = CalcPredictedHitPoint(currentRay, hitTriangle, oldRay);
459
460        Vector3 newDir, newOrigin;
461
462        //-- Construct the mutated ray with xnew,
463        //-- dir = predicted(x)- pnew as direction vector
464        newDir = predicted - newPoint;
465
466        // take xnew, p = intersect(viewcell, line(pnew, predicted(x)) as origin ?
467        // difficult to say!!
468        const float offset = 0.5f;
469        newOrigin = newPoint - newDir * offset;
470       
471        //////////////
472        //-- for per view cell sampling, we must check for intersection
473        //-- with the current view cell
474
475    if (mPerViewCell)
476        {
477                // send ray to view cell
478                static Ray ray;
479                ray.Clear();
480                ray.Init(newOrigin, -newDir, Ray::LOCAL_RAY);
481                //ray.Init(newOrigin, -newDir, Ray::LINE_SEGMENT);
482               
483                //cout << "z";
484                // check if ray intersects view cell
485                if (!mCurrentViewCell->CastRay(ray))
486                        return NULL;
487
488                Ray::Intersection &hit = ray.intersections[0];
489       
490                //cout << "q";
491                // the ray starts from the view cell
492                newOrigin = ray.Extrap(hit.mT);
493        }
494
495        const SimpleRay simpleRay(newOrigin, newDir, SamplingStrategy::GVS, 1.0f);
496
497        VssRay *reverseRay =
498                mRayCaster->CastRay(simpleRay, mViewCellsManager->GetViewSpaceBox(), mPerViewCell);
499
500    ++ mGvsStats.mReverseSamples;
501
502        return reverseRay;
503}
504
505
506int GvsPreprocessor::CastInitialSamples(const int numSamples,
507                                                                                const int sampleType)
508{       
509        const long startTime = GetTime();
510
511        // generate simple rays
512        SimpleRayContainer simpleRays;
513       
514        ViewCellBasedDistribution vcStrat(*this, mCurrentViewCell);
515
516    GenerateRays(numSamples, vcStrat, simpleRays);
517
518        //cout << "sr: " << simpleRays.size() << endl;
519        // generate vss rays
520        VssRayContainer samples;
521       
522        const bool castDoubleRays = false;
523        const bool pruneInvalidRays = true;
524        const bool keepOrigin = mPerViewCell;
525
526        CastRays(simpleRays, samples, castDoubleRays, pruneInvalidRays, keepOrigin);
527       
528        // add to ray queue
529        EnqueueRays(samples);
530
531        //Debug << "generated " <<  numSamples << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
532        return (int)simpleRays.size();
533}
534
535
536void GvsPreprocessor::EnqueueRays(VssRayContainer &samples)
537{
538        // add samples to ray queue
539        VssRayContainer::const_iterator vit, vit_end = samples.end();
540        for (vit = samples.begin(); vit != vit_end; ++ vit)
541        {
542                HandleRay(*vit);
543        }
544}
545
546
547int GvsPreprocessor::ProcessQueue()
548{
549        int castSamples = 0;
550        ++ mGvsStats.mGvsPass;
551
552        while (!mRayQueue.empty()
553                )//&& (mGvsStats.mTotalSamples + castSamples < mTotalSamples) )
554        {
555                // handle next ray
556                VssRay *ray = mRayQueue.top();
557                mRayQueue.pop();
558                if (!ray) cout << "Error!!!!!" << endl;
559                const int newSamples = AdaptiveBorderSampling(*ray);
560
561                castSamples += newSamples;
562
563                //cout << newSamples << " ";   
564                delete ray;
565        }
566
567        return castSamples;
568}
569
570
571void ExportVssRays(Exporter *exporter, const VssRayContainer &vssRays)
572{
573        VssRayContainer vcRays, vcRays2, vcRays3;
574
575        VssRayContainer::const_iterator rit, rit_end = vssRays.end();
576
577        // prepare some rays for output
578        for (rit = vssRays.begin(); rit != rit_end; ++ rit)
579        {
580                //const float p = RandomValue(0.0f, (float)vssRays.size());
581
582                if (1)//(p < raysOut)
583                {
584                        if ((*rit)->mFlags & VssRay::BorderSample)
585                        {
586                                vcRays.push_back(*rit);
587                        }
588                        else if ((*rit)->mFlags & VssRay::ReverseSample)
589                        {
590                                vcRays2.push_back(*rit);
591                        }
592                        else
593                        {
594                                vcRays3.push_back(*rit);
595                        }       
596                }
597        }
598
599        //exporter->ExportRays(vcRays, RgbColor(1, 0, 0));
600        exporter->ExportRays(vcRays2, RgbColor(0, 1, 0));
601        //exporter->ExportRays(vcRays3, RgbColor(1, 1, 1));
602}
603
604
605void GvsPreprocessor::VisualizeViewCell(ViewCell *vc)
606{
607    Intersectable::NewMail();
608
609        Material m;
610       
611        char str[64]; sprintf(str, "pass%06d.wrl", mNumViewCells);
612
613        Exporter *exporter = Exporter::GetExporter(str);
614        if (!exporter)
615                return;
616
617        ObjectPvsIterator pit = vc->GetPvs().GetIterator();
618
619        // output PVS of view cell
620        while (pit.HasMoreEntries())
621        {               
622                ObjectPvsEntry entry = pit.Next();
623
624                Intersectable *intersect = entry.mObject;
625               
626                if (intersect->Mailed())
627                        continue;
628               
629                intersect->Mail();
630                //m.mDiffuseColor = RgbColor(1, 0, 0);
631                m = RandomMaterial();
632                exporter->SetForcedMaterial(m);
633
634                exporter->ExportIntersectable(intersect);
635        }
636
637        cout << "vssrays: " << (int)mVssRays.size() << endl;
638        ExportVssRays(exporter, mVssRays);
639
640        /////////////////
641        //-- export view cell geometry
642
643        exporter->SetWireframe();
644
645        m.mDiffuseColor = RgbColor(0, 1, 0);
646        exporter->SetForcedMaterial(m);
647
648        mViewCellsManager->ExportViewCellGeometry(exporter, vc, NULL, NULL);
649        //exporter->SetFilled();
650
651        DEL_PTR(exporter);
652}
653
654
655void GvsPreprocessor::VisualizeViewCells()
656{
657        char str[64]; sprintf(str, "tmp/pass%06d_%04d-", mNumViewCells, mPass);
658                       
659        // visualization
660        if (mGvsStats.mPassContribution > 0)
661        {
662                const bool exportRays = true;
663                const bool exportPvs = true;
664
665                mViewCellsManager->ExportSingleViewCells(mObjects,
666                                                                                                 10,
667                                                                                                 false,
668                                                                                                 exportPvs,
669                                                                                                 exportRays,
670                                                                                                 1000,
671                                                                                                 str);
672        }
673
674        // remove pass samples
675        ViewCellContainer::const_iterator vit, vit_end = mViewCellsManager->GetViewCells().end();
676
677        for (vit = mViewCellsManager->GetViewCells().begin(); vit != vit_end; ++ vit)
678        {
679                (*vit)->DelRayRefs();
680        }
681}
682
683
684void GvsPreprocessor::ProcessViewCell()
685{
686        mGvsStats.mPerViewCellSamples = 0;
687        int oldContribution = 0;
688        int passSamples = 0;
689
690        while (mGvsStats.mPerViewCellSamples < mTotalSamples)
691        {
692                // Ray queue empty =>
693                // cast a number of uniform samples to fill ray queue
694                int newSamples = CastInitialSamples(mInitialSamples, mSamplingType);
695
696                if (!mOnlyRandomSampling)
697                        newSamples += ProcessQueue();
698
699                passSamples += newSamples;
700                mGvsStats.mPerViewCellSamples += newSamples;
701       
702                if (0 &&
703                        passSamples % (mSamplesPerPass + 1) == mSamplesPerPass)
704                {
705                        ++ mPass;
706
707                        mGvsStats.mPassContribution = mGvsStats.mTotalContribution - oldContribution;
708
709                        ////////
710                        //-- stats
711
712                        mGvsStats.mPass = mPass;
713                        mGvsStats.Stop();
714                        mGvsStats.Print(mGvsStatsStream);
715
716                        //cout << "\nPass " << mPass << " #samples: " << mGvsStats.mTotalSamples << " of " << mTotalSamples << endl;
717
718                        // reset
719                        oldContribution = mGvsStats.mTotalContribution;
720                        mGvsStats.mPassContribution = 0;
721                        passSamples = 0;
722                }
723        }
724}
725
726
727void GvsPreprocessor::PerViewCellComputation()
728{
729        const int maxViewCells = 25;
730       
731        while (mNumViewCells < maxViewCells && NextViewCell())
732        {
733                cout << "processing view cell " << mNumViewCells << endl;
734
735                // compute the pvs of the current view cell
736                ProcessViewCell();
737
738                // exchange triangle pvs with objects
739                UpdatePvs(mCurrentViewCell);
740
741                if (GVS_DEBUG)
742                {
743                        VisualizeViewCell(mCurrentViewCell);
744                        CLEAR_CONTAINER(mVssRays);
745                }
746
747                ////////
748                //-- stats
749               
750                mGvsStats.mViewCells = mNumViewCells;//mPass;
751                mGvsStats.mTotalPvs += mCurrentViewCell->GetPvs().GetSize();
752                mGvsStats.mTotalSamples += mGvsStats.mPerViewCellSamples;
753
754                mGvsStats.Stop();
755                mGvsStats.Print(mGvsStatsStream);
756        }
757}
758
759
760void GvsPreprocessor::UpdatePvs(ViewCell *currentViewCell)
761{
762        ObjectPvs newPvs;
763        BvhLeaf::NewMail();
764
765        ObjectPvsIterator pit = currentViewCell->GetPvs().GetIterator();
766
767        // output PVS of view cell
768        while (pit.HasMoreEntries())
769        {               
770                ObjectPvsEntry entry = pit.Next();
771
772                Intersectable *intersect = entry.mObject;
773       
774                BvhLeaf *bv = intersect->mBvhLeaf;
775
776                if (!bv || bv->Mailed())
777                        continue;
778               
779                bv->Mail();
780
781                //m.mDiffuseColor = RgbColor(1, 0, 0);
782                newPvs.AddSampleDirty(bv, 1.0f);
783        }
784
785        newPvs.SimpleSort();
786
787        currentViewCell->SetPvs(newPvs);
788}
789
790
791void GvsPreprocessor::GlobalComputation()
792{
793        int passSamples = 0;
794        int oldContribution = 0;
795
796        while (mGvsStats.mTotalSamples < mTotalSamples)
797        {
798                // Ray queue empty =>
799                // cast a number of uniform samples to fill ray queue
800                int newSamples = CastInitialSamples(mInitialSamples, mSamplingType);
801
802                if (!mOnlyRandomSampling)
803                        newSamples += ProcessQueue();
804
805                passSamples += newSamples;
806                mGvsStats.mTotalSamples += newSamples;
807
808                if (passSamples % (mSamplesPerPass + 1) == mSamplesPerPass)
809                {
810                        ++ mPass;
811
812                        mGvsStats.mPassContribution = mGvsStats.mTotalContribution - oldContribution;
813
814                        ////////
815                        //-- stats
816
817                        //cout << "\nPass " << mPass << " #samples: " << mGvsStats.mTotalSamples << " of " << mTotalSamples << endl;
818                        mGvsStats.mPass = mPass;
819                        mGvsStats.Stop();
820                        mGvsStats.Print(mGvsStatsStream);
821
822                        // reset
823                        oldContribution = mGvsStats.mTotalContribution;
824                        mGvsStats.mPassContribution = 0;
825                        passSamples = 0;
826
827                        if (GVS_DEBUG)
828                                VisualizeViewCells();
829                }
830        }
831}
832
833
834bool GvsPreprocessor::ComputeVisibility()
835{
836        cout << "Gvs Preprocessor started\n" << flush;
837        const long startTime = GetTime();
838
839        //Randomize(0);
840       
841        mGvsStats.Reset();
842        mGvsStats.Start();
843
844        if (!mLoadViewCells)
845        {       
846                /// construct the view cells from the scratch
847                ConstructViewCells();
848                // reset pvs already gathered during view cells construction
849                mViewCellsManager->ResetPvs();
850                cout << "finished view cell construction" << endl;
851        }
852        else if (0)
853        {       
854                //-- test successful view cells loading by exporting them again
855                VssRayContainer dummies;
856                mViewCellsManager->Visualize(mObjects, dummies);
857                mViewCellsManager->ExportViewCells("test.xml.gz", mViewCellsManager->GetExportPvs(), mObjects);
858        }
859
860        mGvsStats.Stop();
861        mGvsStats.Print(mGvsStatsStream);
862
863        if (mPerViewCell)
864        {
865                PerViewCellComputation();
866        }
867        else
868        {
869                GlobalComputation();
870        }
871
872        cout << "cast " << 2 * mGvsStats.mTotalSamples / (1e3f * TimeDiff(startTime, GetTime())) << "M rays/s" << endl;
873
874        if (GVS_DEBUG)
875        {
876                Visualize();
877                CLEAR_CONTAINER(mVssRays);
878        }
879
880        return true;
881}
882
883
884void GvsPreprocessor::Visualize()
885{
886        Exporter *exporter = Exporter::GetExporter("gvs.wrl");
887
888        if (!exporter)
889                return;
890       
891        vector<VizStruct>::const_iterator vit, vit_end = vizContainer.end();
892        for (vit = vizContainer.begin(); vit != vit_end; ++ vit)
893        {
894                exporter->SetWireframe();
895                exporter->ExportPolygon((*vit).enlargedTriangle);
896                //Material m;
897                exporter->SetFilled();
898                Polygon3 poly = Polygon3((*vit).originalTriangle);
899                exporter->ExportPolygon(&poly);
900        }
901
902        VssRayContainer::const_iterator rit, rit_end = mVssRays.end();
903        for (rit = mVssRays.begin(); rit != rit_end; ++ rit)
904        {
905                Intersectable *obj = (*rit)->mTerminationObject;
906                exporter->ExportIntersectable(obj);
907        }
908
909        ExportVssRays(exporter, mVssRays);
910       
911        delete exporter;
912}
913
914
915void GvsStatistics::Print(ostream &app) const
916{
917        app << "#Pass\n" << mPass << endl;
918        app << "#Time\n" << Time() << endl;
919        app << "#TotalSamples\n" << mTotalSamples << endl;
920        app << "#ScDiff\n" << mPassContribution << endl;
921        app     << "#SamplesContri\n" << mTotalContribution << endl;
922        app << "#ReverseSamples\n" << mReverseSamples << endl;
923        app << "#BorderSamples\n" << mBorderSamples << endl;           
924        app << "#GvsRuns\n" << mGvsPass << endl;
925        app << "#ViewCells\n" << mViewCells << endl;
926        app << "#TotalPvs\n" << mTotalPvs << endl;
927        app << "#PerViewCellSamples\n" << mPerViewCellSamples << endl << endl;
928}
929
930
931}
Note: See TracBrowser for help on using the repository browser.