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

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