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

Revision 2017, 29.0 KB checked in by mattausch, 17 years ago (diff)

changed to static cast

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