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

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

using large address space

  • 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),
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{
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) || (Magnitude(p1 - p2) <= MIN_DIST))
296        {
297                return castRays;
298        }
299       
300        // the new subdivision point
301        const Vector3 p = (p1 + p2) * 0.5f;
302
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 = dynamic_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
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 = dynamic_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
831                        mViewCells.push_back(viewCell);
832                }
833
834                if (i == tries)
835                {
836                        cerr << "big error! no view cell found" << endl;
837                        return;
838                }
839        }
840}
841
842
843void GvsPreprocessor::IntersectWithViewCell()
844{
845        mCurrentViewCell->GetMesh()->ComputeBoundingBox();
846        AxisAlignedBox3 box = mCurrentViewCell->GetMesh()->mBox;
847        //cout << "box: " << box << endl;
848        vector<KdLeaf *> leaves;
849
850        mKdTree->GetBoxIntersections(box, leaves);
851
852        vector<KdLeaf *>::const_iterator lit, lit_end = leaves.end();
853
854        for (lit = leaves.begin(); lit != leaves.end(); ++ lit)
855        {
856                KdLeaf *leaf = *lit;
857                ObjectContainer::const_iterator oit, oit_end = leaf->mObjects.end();
858
859                for (oit = leaf->mObjects.begin(); oit != oit_end; ++ oit)
860                {
861                        TriangleIntersectable *triObj = dynamic_cast<TriangleIntersectable *>(*oit);
862
863                        if (box.Intersects(triObj->GetItem()))
864                        {
865                                if (!triObj->mCounter)
866                                {
867                                        triObj->mCounter = 1;
868                                        mTrianglePvs.push_back(triObj);
869                                }
870                        }
871                }
872        }
873}
874
875
876void GvsPreprocessor::PerViewCellComputation()
877{
878        // hack: reset counter
879        ObjectContainer::const_iterator oit, oit_end = mObjects.end();
880
881        for (oit = mObjects.begin(); oit != oit_end; ++ oit)
882        {
883                (*oit)->mCounter = 0;
884        }
885        long lastTime = GetTime();
886
887        while (NextViewCell())
888        {
889                cout << "\n***********************\n"
890                         << "processing view cell " << mProcessedViewCells
891                         << " (id: " << mCurrentViewCell->GetId() << ")" << endl;
892
893                // compute the pvs of the current view cell
894                ProcessViewCell();
895
896                //mGvsStats.mTrianglePvs = mCurrentViewCell->GetPvs().GetSize();
897                mGvsStats.mTrianglePvs = (int)mTrianglePvs.size();
898                mGvsStats.mTotalTrianglePvs += mGvsStats.mTrianglePvs;
899
900                ObjectContainer objectPvs;
901
902                // exchange triangle pvs with objects
903                //UpdatePvs(mCurrentViewCell);
904                GetObjectPvs(objectPvs);
905
906                cout << "triangle pvs of " << (int)mTrianglePvs.size() << " was converted to object pvs of " << (int)objectPvs.size() << endl;
907
908                ////////
909                //-- stats
910               
911                mGvsStats.mViewCells = mProcessedViewCells;//mPass;
912                //mGvsStats.mPerViewCellPvs = mCurrentViewCell->GetPvs().GetSize();
913                mGvsStats.mPerViewCellPvs = (int)objectPvs.size();
914
915                mGvsStats.mTotalPvs += mGvsStats.mPerViewCellPvs;
916                mGvsStats.mTotalSamples += mGvsStats.mPerViewCellSamples;
917
918                // timing
919                const long currentTime = GetTime();
920       
921                mGvsStats.mTimePerViewCell = TimeDiff(lastTime, currentTime) * 1e-3f;
922                mGvsStats.mTotalTime += mGvsStats.mTimePerViewCell;
923
924                lastTime = currentTime;
925
926                mGvsStats.Stop();
927                mGvsStats.Print(mGvsStatsStream);
928
929        mTrianglePvs.clear();
930
931                if (GVS_DEBUG)
932                {
933                        //VisualizeViewCell(mCurrentViewCell);
934                        VisualizeViewCell(objectPvs);
935                        CLEAR_CONTAINER(mVssRays);
936                }
937
938                // is this really necessary?
939                ClearRayQueue();
940        }
941}
942
943
944void GvsPreprocessor::UpdatePvs(ViewCell *currentViewCell)
945{
946        ObjectPvs newPvs;
947        BvhLeaf::NewMail();
948
949        ObjectPvsIterator pit = currentViewCell->GetPvs().GetIterator();
950
951        // output PVS of view cell
952        while (pit.HasMoreEntries())
953        {               
954                ObjectPvsEntry entry = pit.Next();
955
956                Intersectable *intersect = entry.mObject;
957       
958                BvhLeaf *bv = intersect->mBvhLeaf;
959
960                if (!bv || bv->Mailed())
961                        continue;
962               
963                bv->Mail();
964
965                //m.mDiffuseColor = RgbColor(1, 0, 0);
966                newPvs.AddSampleDirty(bv, 1.0f);
967        }
968
969        newPvs.SimpleSort();
970
971        currentViewCell->SetPvs(newPvs);
972}
973
974 
975void GvsPreprocessor::GetObjectPvs(ObjectContainer &objectPvs) const
976{
977        BvhLeaf::NewMail();
978
979        ObjectContainer::const_iterator oit, oit_end = mTrianglePvs.end();
980
981        for (oit = mTrianglePvs.begin(); oit != oit_end; ++ oit)
982        {
983                Intersectable *intersect = *oit;
984       
985                BvhLeaf *bv = intersect->mBvhLeaf;
986
987                if (!bv || bv->Mailed())
988                        continue;
989               
990                bv->Mail();
991
992                objectPvs.push_back(bv);
993                // hack: reset counter
994                (*oit)->mCounter = 0;
995        }
996}
997
998
999void GvsPreprocessor::GlobalComputation()
1000{
1001        int passSamples = 0;
1002        int oldContribution = 0;
1003
1004        while (mGvsStats.mTotalSamples < mTotalSamples)
1005        {
1006                // Ray queue empty =>
1007                // cast a number of uniform samples to fill ray queue
1008                int newSamples = CastInitialSamples(mInitialSamples, mSamplingType);
1009
1010                if (!mOnlyRandomSampling)
1011                        newSamples += ProcessQueue();
1012
1013                passSamples += newSamples;
1014                mGvsStats.mTotalSamples += newSamples;
1015
1016                if (passSamples % (mSamplesPerPass + 1) == mSamplesPerPass)
1017                {
1018                        ++ mPass;
1019
1020                        mGvsStats.mPassContribution = mGvsStats.mTotalContribution - oldContribution;
1021
1022                        ////////
1023                        //-- stats
1024
1025                        //cout << "\nPass " << mPass << " #samples: " << mGvsStats.mTotalSamples << " of " << mTotalSamples << endl;
1026                        mGvsStats.mPass = mPass;
1027                        mGvsStats.Stop();
1028                        mGvsStats.Print(mGvsStatsStream);
1029
1030                        // reset
1031                        oldContribution = mGvsStats.mTotalContribution;
1032                        mGvsStats.mPassContribution = 0;
1033                        passSamples = 0;
1034
1035                        if (GVS_DEBUG)
1036                                VisualizeViewCells();
1037                }
1038        }
1039}
1040
1041
1042bool GvsPreprocessor::ComputeVisibility()
1043{
1044        cout << "Gvs Preprocessor started\n" << flush;
1045        const long startTime = GetTime();
1046
1047        //Randomize(0);
1048        mGvsStats.Reset();
1049        mGvsStats.Start();
1050
1051        if (!mLoadViewCells)
1052        {       
1053                /// construct the view cells from the scratch
1054                ConstructViewCells();
1055                // reset pvs already gathered during view cells construction
1056                mViewCellsManager->ResetPvs();
1057                cout << "finished view cell construction" << endl;
1058        }
1059        else if (0)
1060        {       
1061                //-- test successful view cells loading by exporting them again
1062                VssRayContainer dummies;
1063                mViewCellsManager->Visualize(mObjects, dummies);
1064                mViewCellsManager->ExportViewCells("test.xml.gz", mViewCellsManager->GetExportPvs(), mObjects);
1065        }
1066
1067        cout << "here4 " << mKdTree->GetBox() << endl;
1068        cout << "here5 " << mViewCellsManager->GetViewSpaceBox() << endl;
1069        mGvsStats.Stop();
1070        mGvsStats.Print(mGvsStatsStream);
1071
1072        if (mPerViewCell)
1073        {
1074                // list of view cells to compute
1075                CompileViewCellsList();
1076
1077                PerViewCellComputation();
1078        }
1079        else
1080        {
1081                GlobalComputation();
1082        }
1083
1084        cout << "cast " << 2 * mGvsStats.mTotalSamples / (1e3f * TimeDiff(startTime, GetTime())) << "M rays/s" << endl;
1085
1086        if (GVS_DEBUG)
1087        {
1088                Visualize();
1089                CLEAR_CONTAINER(mVssRays);
1090        }
1091
1092        return true;
1093}
1094
1095
1096void GvsPreprocessor::Visualize()
1097{
1098        Exporter *exporter = Exporter::GetExporter("gvs.wrl");
1099
1100        if (!exporter)
1101                return;
1102       
1103        vector<VizStruct>::const_iterator vit, vit_end = vizContainer.end();
1104       
1105        for (vit = vizContainer.begin(); vit != vit_end; ++ vit)
1106        {
1107                exporter->SetWireframe();
1108                exporter->ExportPolygon((*vit).enlargedTriangle);
1109                //Material m;
1110                exporter->SetFilled();
1111                Polygon3 poly = Polygon3((*vit).originalTriangle);
1112                exporter->ExportPolygon(&poly);
1113        }
1114
1115        VssRayContainer::const_iterator rit, rit_end = mVssRays.end();
1116
1117        for (rit = mVssRays.begin(); rit != rit_end; ++ rit)
1118        {
1119                Intersectable *obj = (*rit)->mTerminationObject;
1120                exporter->ExportIntersectable(obj);
1121        }
1122
1123        ExportVssRays(exporter, mVssRays);
1124       
1125        delete exporter;
1126}
1127
1128
1129void GvsStatistics::Print(ostream &app) const
1130{
1131        app << "#ViewCells\n" << mViewCells << endl;
1132        app << "#ViewCellId\n" << mViewCellId << endl;
1133        app << "#TotalTime\n" << mTotalTime << endl;
1134        app << "#TimePerViewCell\n" << mTimePerViewCell << endl;;
1135
1136        app << "#RaysPerSec\n" << RaysPerSec() << endl;
1137
1138        app << "#TrianglePvs\n" << mTrianglePvs << endl;
1139        app << "#TotalTrianglePvs\n" << mTotalTrianglePvs << endl;
1140
1141        app << "#PerViewCellPvs\n" << mPerViewCellPvs << endl;
1142        app << "#TotalPvs\n" << mTotalPvs << endl;
1143       
1144        app << "#PerViewCellSamples\n" << mPerViewCellSamples << endl;
1145        app << "#TotalSamples\n" << mTotalSamples << endl;
1146        app     << "#SamplesContri\n" << mTotalContribution << endl;
1147               
1148        //app << "#ReverseSamples\n" << mReverseSamples << endl;
1149        //app << "#BorderSamples\n" << mBorderSamples << endl;
1150
1151        //app << "#Pass\n" << mPass << endl;
1152        //app << "#ScDiff\n" << mPassContribution << endl;
1153        //app << "#GvsRuns\n" << mGvsPass << endl;     
1154
1155        app << endl;
1156}
1157
1158
1159}
Note: See TracBrowser for help on using the repository browser.