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

Revision 2743, 57.0 KB checked in by mattausch, 16 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#include "Polygon3.h"
14#include "IntersectableWrapper.h"
15#include "Timer/PerfTimer.h"
16#include "Vector2.h"
17#include "RndGauss.h"
18
19
20
21namespace GtpVisibilityPreprocessor
22{
23 
24#define GVS_DEBUG 1
25#define NOT_ACCOUNTED_OBJECT 0
26#define ACCOUNTED_OBJECT 2
27#define USE_REVERSE_SAMPLING 1
28#define USE_SUBDIVISION 1
29
30static const float MIN_DIST = 1e-8f;
31
32static ObjectContainer myobjects;
33static int sInvalidSamples = 0;
34static VizStruct currentViz;
35
36
37///////////
38//-- timers
39
40
41static PerfTimer rayTimer;
42static PerfTimer kdPvsTimer;
43static PerfTimer gvsTimer;
44static PerfTimer initialTimer;
45static PerfTimer intersectionTimer;
46static PerfTimer preparationTimer;
47static PerfTimer mainLoopTimer;
48static PerfTimer contributionTimer;
49static PerfTimer castTimer;
50static PerfTimer generationTimer;
51
52
53/////////////////////
54
55
56
57
58
59GvsPreprocessor::GvsPreprocessor():
60Preprocessor(),
61mProcessedViewCells(0),
62mCurrentViewCell(NULL),
63mCurrentViewPoint(Vector3(0.0f, 0.0f, 0.0f)),
64mOnlyRandomSampling(false),
65//mOnlyRandomSampling(true),
66mUseProbablyVisibleSampling(false)
67{
68        Environment::GetSingleton()->GetIntValue("GvsPreprocessor.totalSamples", mTotalSamples);
69        Environment::GetSingleton()->GetIntValue("GvsPreprocessor.initialSamples", mInitialSamples);
70        Environment::GetSingleton()->GetIntValue("GvsPreprocessor.gvsSamplesPerPass", mGvsSamplesPerPass);
71        Environment::GetSingleton()->GetIntValue("GvsPreprocessor.minContribution", mMinContribution);
72        Environment::GetSingleton()->GetFloatValue("GvsPreprocessor.epsilon", mEps);
73        Environment::GetSingleton()->GetFloatValue("GvsPreprocessor.threshold", mThreshold);   
74        Environment::GetSingleton()->GetBoolValue("GvsPreprocessor.perViewCell", mPerViewCell);
75        Environment::GetSingleton()->GetIntValue("GvsPreprocessor.maxViewCells", mMaxViewCells);
76
77        Environment::GetSingleton()->GetBoolValue("Preprocessor.evaluatePixelError", mEvaluatePixelError);
78
79        Environment::GetSingleton()->GetBoolValue("ViewCells.useKdPvs", mUseKdPvs);
80
81        Environment::GetSingleton()->GetFloatValue("GvsPreprocessor.initialJitter", mInitialJitter);
82        Environment::GetSingleton()->GetBoolValue("GvsPreprocessor.useDeterministicGvs", mUseDeterministicGvs);
83
84        Environment::GetSingleton()->GetFloatValue("GvsPreprocessor.radiusOfInfluence", mRadiusOfInfluence);
85
86        char gvsStatsLog[100];
87        Environment::GetSingleton()->GetStringValue("GvsPreprocessor.stats", gvsStatsLog);
88        mGvsStatsStream.open(gvsStatsLog);
89
90        cout << "number of gvs samples per pass: " << mGvsSamplesPerPass << endl;
91        cout << "number of samples per pass: " << mSamplesPerPass << endl;
92        cout << "only random sampling: " << mOnlyRandomSampling << endl;
93
94        Debug << "Gvs preprocessor options" << endl;
95        Debug << "number of total samples: " << mTotalSamples << endl;
96        Debug << "number of initial samples: " << mInitialSamples << endl;
97        Debug << "threshold: " << mThreshold << endl;
98        Debug << "epsilon: " << mEps << endl;
99        Debug << "stats: " << gvsStatsLog << endl;
100        Debug << "per view cell: " << mPerViewCell << endl;
101        Debug << "max view cells: " << mMaxViewCells << endl;
102        Debug << "min contribution: " << mMinContribution << endl;
103
104        mDistribution = new ViewCellBasedDistribution(*this, NULL);
105
106        mGvsStats.Reset();
107
108        // hack: some generic statistical values that can be used
109        // by an application using the preprocessor
110        for (int i = 0; i < 2; ++ i)
111                mGenericStats[i] = 0;
112}
113
114
115GvsPreprocessor::~GvsPreprocessor()
116{
117        delete mDistribution;
118        ClearRayQueue();
119}
120
121
122void GvsPreprocessor::ClearRayQueue()
123{
124        // clean ray queue
125        while (!mRayQueue.empty())
126        {
127                // handle next ray
128                VssRay *ray = mRayQueue.top();
129                mRayQueue.pop();
130
131                // note: deletion of the ray is handled by ray pool
132                mRayCaster->SheduleRayForDeletion(ray);
133        }
134}
135
136
137ViewCell *GvsPreprocessor::NextViewCell()
138{
139        if (mProcessedViewCells == (int)mViewCells.size())
140                return NULL; // no more view cells
141
142        ViewCell *vc = mViewCells[mProcessedViewCells];
143
144   if (!vc->GetMesh())
145                mViewCellsManager->CreateMesh(vc);
146
147        mGvsStats.mViewCellId = vc->GetId();
148
149        Debug << "vc: " << vc->GetId() << endl;
150
151        ++ mProcessedViewCells;
152   
153        return vc;
154}
155
156
157int GvsPreprocessor::CheckDiscontinuity(const VssRay &currentRay,
158                                                                                const Triangle3 &hitTriangle,
159                                                                                const VssRay &oldRay)
160{
161        // the predicted hitpoint is the point where the ray would have intersected the hit triangle
162        Vector3 predictedHit = CalcPredictedHitPoint(currentRay, hitTriangle, oldRay);
163
164        float predictedLen = Magnitude(predictedHit - currentRay.mOrigin);
165        float len = Magnitude(currentRay.mTermination - currentRay.mOrigin);
166       
167        // discrepancy between predicted and actual hit point large => this is likely to be a discontinuity
168
169        // matt: problem: this only finds CLOSER discontinuities, but not discontinuities which are FARTHER away
170        if ((predictedLen - len) < mThreshold)
171        // q: rather use relative distance?
172        //if ((predictedLen / len) < mThreshold)
173                return 0;
174
175        SimpleRay simpleRay;
176
177        // apply reverse sampling to find the gap
178        if (!ComputeReverseRay(currentRay, hitTriangle, oldRay, simpleRay))
179                return 0;
180
181        static VssRayContainer reverseRays;
182        reverseRays.clear();
183
184        if (mUseDeterministicGvs)
185        {
186                VssRay *reverseRay =
187                        mRayCaster->CastRay(simpleRay, mViewCellsManager->GetViewSpaceBox(), !mPerViewCell);
188
189                reverseRays.push_back(reverseRay);
190        }
191        else
192        {
193                float scale = 0.01f;
194
195                if (0)
196                        CastRayBundle4(simpleRay, reverseRays, mViewCellsManager->GetViewSpaceBox());
197                else
198                        CastRayBundle16(simpleRay, reverseRays, scale);
199        }
200
201        mGvsStats.mReverseSamples += (int)reverseRays.size();
202        EnqueueRays(reverseRays);
203
204        return (int)reverseRays.size();
205}
206
207
208bool GvsPreprocessor::CheckDiscontinuity2(const VssRay &currentRay,
209                                                                                  const Triangle3 &hitTriangle,
210                                                                                  const VssRay &oldRay,
211                                                                                  SimpleRay &reverseRay)
212{
213        // the predicted hitpoint is the point where the ray would have intersected the hit triangle
214        Vector3 predictedHit = CalcPredictedHitPoint(currentRay, hitTriangle, oldRay);
215
216        float predictedLen = Magnitude(predictedHit - currentRay.mOrigin);
217        float len = Magnitude(currentRay.mTermination - currentRay.mOrigin);
218       
219        // discrepancy between predicted and actual hit point large
220        // => this is likely to be a discontinuity
221        if (fabs(predictedLen - len) < mThreshold)
222                return false;
223
224        return CreateRandomizedReverseRay(currentRay, predictedHit, reverseRay, hitTriangle);
225}
226
227
228int GvsPreprocessor::CountObject(Intersectable *triObj)
229{
230        int numObjects = 0;
231
232        if ((triObj->mCounter != (NOT_ACCOUNTED_OBJECT + 1)) &&
233                (triObj->mCounter != (ACCOUNTED_OBJECT + 1)))
234        {
235                ++ triObj->mCounter;
236                ++ numObjects;
237        }
238
239        mGenericStats[1] += numObjects;
240
241        return numObjects;
242}
243
244
245void GvsPreprocessor::UpdateStatsForVisualization(KdIntersectable *kdInt)
246{
247        int numObj = 0;
248
249        // count new objects in pvs due to kd node conversion   
250        myobjects.clear();
251        // also gather duplicates to avoid mailing
252        mKdTree->CollectObjectsWithDublicates(kdInt->GetItem(), myobjects);
253
254        ObjectContainer::const_iterator oit, oit_end = myobjects.end();
255
256        for (oit = myobjects.begin(); oit != oit_end; ++ oit)
257                numObj += CountObject(*oit);
258
259        mViewCellsManager->UpdateStatsForViewCell(mCurrentViewCell, kdInt, numObj);
260}       
261
262
263void GvsPreprocessor::AddKdNodeToPvs(const Vector3 &termination)
264{
265        kdPvsTimer.Entry();
266
267        // exchange the triangle with the node in the pvs for kd pvs
268        KdNode *node = mKdTree->GetPvsNode(termination);
269
270        //KdNode *node = mKdTree->GetPvsNodeCheck(ray.mTermination, obj);
271        //if (!node) cerr << "e " << obj->GetBox() << " " << ray.mTermination << endl; else
272        if (!node->Mailed())
273        {
274                // add to pvs
275                node->Mail();
276                KdIntersectable *kdInt = mKdTree->GetOrCreateKdIntersectable(node);
277                mCurrentViewCell->GetPvs().AddSampleDirty(kdInt, 1.0f);
278
279                if (QT_VISUALIZATION_SHOWN) UpdateStatsForVisualization(kdInt);
280        }
281
282        kdPvsTimer.Exit();
283}
284
285
286bool GvsPreprocessor::HasContribution(VssRay &ray)
287{
288        if (!ray.mTerminationObject)
289                return false;
290
291        contributionTimer.Entry();
292
293        bool result;
294
295        if (!mPerViewCell)
296        {
297                // store the rays + the intersected view cells
298                const bool storeViewCells = false;
299
300                mViewCellsManager->ComputeSampleContribution(ray,
301                                                                                                         true,
302                                                                                                         storeViewCells,
303                                                                                                         true);
304
305                result = ray.mPvsContribution > 0;
306        }
307        else // original per view cell gvs
308        {
309                // test if triangle was accounted for yet
310                result = AddTriangleObject(ray.mTerminationObject);
311               
312                if (mUseKdPvs)
313                        AddKdNodeToPvs(ray.mTermination);
314        }
315
316        contributionTimer.Exit();
317
318        return result;
319}
320
321
322bool GvsPreprocessor::HandleRay(VssRay *vssRay)
323{
324        if (!vssRay)
325                return false;
326
327        if (!HasContribution(*vssRay))
328        {
329                mRayCaster->SheduleRayForDeletion(vssRay);
330                return false;
331        }
332       
333        if (GVS_DEBUG)
334        {
335                if (mVssRays.size() < 1000)
336                        mVssRays.push_back(new VssRay(*vssRay));
337        }
338
339        // add new ray to ray queue
340        mRayQueue.push(vssRay);
341
342        ++ mGvsStats.mTotalContribution;
343
344        if (mRayQueue.size() % 50000 == 0)
345                cout << "ray queue size: " << mRayQueue.size() << endl;
346
347        if (mGvsStats.mTotalContribution % 10000 == 0)
348                cout << "contri: " << mGvsStats.mTotalContribution << endl;
349
350        return true;
351}
352
353
354/** Creates 3 new vertices for triangle vertex with specified index.
355*/
356void GvsPreprocessor::CreateDisplacedVertices(VertexContainer &vertices,
357                                                                                          const Triangle3 &hitTriangle,
358                                                                                          const VssRay &ray,
359                                                                                          int index) const
360{
361        const int indexU = (index + 1) % 3;
362        const int indexL = (index - 1) % 3; //(index == 0) ? 2 : index - 1;
363
364        const Vector3 v  = hitTriangle.mVertices[index];
365        const Vector3 vu = hitTriangle.mVertices[indexU];
366        const Vector3 vl = hitTriangle.mVertices[indexL];
367
368        const Vector3 a = v - ray.GetOrigin();
369        const Vector3 b = vu - v;
370        const Vector3 c = v - vl;
371       
372        const float len = Magnitude(a);
373        //if (len > Limits::Small) a /= len;
374
375        const Vector3 dir1 = Normalize(CrossProd(a, b)); // N((pi-xp)×(pi+1 - pi));
376        const Vector3 dir2 = Normalize(CrossProd(a, c)); // N((pi-xp)×(pi - pi-1))
377        const Vector3 dir3 = DotProd(dir2, dir1) > 0 ? // N((pi-xp)×di,i-1+di,i+1×(pi-xp))
378                Normalize(dir2 + dir1) : Normalize(CrossProd(a, dir1) + CrossProd(dir2, a));
379#if 1
380
381        // compute the new three hit points
382        // pi, i + 1:  pi + e·|pi-xp|·di, j
383        const Vector3 pt1 = v + mEps * len * dir1;
384        // pi, i - 1:  pi + e·|pi-xp|·di, j
385    const Vector3 pt2 = v + mEps * len * dir2;
386        // pi, i:      pi + e·|pi-xp|·di, j
387        const Vector3 pt3 = v + mEps * len * dir3;
388
389#else
390
391        const Vector3 pt1 = v + mEps * dir1;
392        // pi, i - 1:  pi + e·|pi-xp|·di, j
393    const Vector3 pt2 = v + mEps * dir2;
394        // pi, i:      pi + e·|pi-xp|·di, j
395        const Vector3 pt3 = v + mEps * dir3;
396
397#endif
398
399        vertices.push_back(pt2);
400        vertices.push_back(pt3);
401        vertices.push_back(pt1);
402}
403
404
405void GvsPreprocessor::EnlargeTriangle(VertexContainer &vertices,
406                                                                          const Triangle3 &hitTriangle,
407                                                                          const VssRay &ray) const
408{
409        CreateDisplacedVertices(vertices, hitTriangle, ray, 0);
410        CreateDisplacedVertices(vertices, hitTriangle, ray, 1);
411        CreateDisplacedVertices(vertices, hitTriangle, ray, 2);
412}
413
414
415Vector3 GvsPreprocessor::CalcPredictedHitPoint(const VssRay &newRay,
416                                                                                           const Triangle3 &hitTriangle,
417                                                                                           const VssRay &oldRay) const
418{
419        // find the intersection of the plane induced by the
420        // hit triangle with the new ray
421        Plane3 plane(hitTriangle.GetNormal(), hitTriangle.mVertices[0]);
422
423        const Vector3 hitPt =
424                plane.FindIntersection(newRay.mTermination, newRay.mOrigin);
425       
426        return hitPt;
427}
428
429
430bool EqualVisibility(const VssRay &a, const VssRay &b)
431{
432        return a.mTerminationObject == b.mTerminationObject;
433}
434
435
436int GvsPreprocessor::SubdivideEdge(const Triangle3 &hitTriangle,
437                                                                   const Vector3 &p1,
438                                                                   const Vector3 &p2,
439                                                                   const VssRay &ray1,
440                                                                   const VssRay &ray2,
441                                                                   const VssRay &oldRay,
442                                                                   int level)
443{
444        int castRays = 0;
445       
446        if (EqualVisibility(ray1, ray2) || (SqrDistance(p1, p2) <= MIN_DIST)  || (level ++ > 10))
447        {
448                //if (SqrMagnitude(p1 - p2) <= MIN_DIST)
449                //      cerr << "min dist reached!! " << SqrMagnitude(p1 - p2) << " " << MIN_DIST << " " << ray1.mTerminationObject << " " << ray2.mTerminationObject << " level: " << level << " " << EqualVisibility(ray1, ray2) << endl;
450
451                return castRays;
452        }
453
454        // the new subdivision point
455        const Vector3 p = (p1 + p2) * 0.5f;
456       
457        SimpleRay sray(oldRay.mOrigin, p - oldRay.mOrigin, SamplingStrategy::GVS, 1.0f);
458
459        VssRay *newRay;
460
461        // cast single ray
462        castTimer.Entry();
463
464        // cast single ray to check if a triangle was missed. note: not efficient!!
465        newRay = mRayCaster->CastRay(sray, mViewCellsManager->GetViewSpaceBox(), !mPerViewCell);
466        ++ castRays;
467       
468        castTimer.Exit();
469
470        if (!newRay)
471        {
472                //cout<<"w";
473                return castRays;
474        }
475
476        //newRay->mFlags |= VssRay::BorderSample;
477
478        // cast reverse rays if necessary
479        if (USE_REVERSE_SAMPLING) castRays += CheckDiscontinuity(*newRay, hitTriangle, oldRay);
480       
481        if (GVS_DEBUG)
482                currentViz.enlargedTriangle.push_back(p);
483
484        // subdivide further
485        castRays += SubdivideEdge(hitTriangle, p1, p, ray1, *newRay, oldRay, level);
486        castRays += SubdivideEdge(hitTriangle, p, p2, *newRay, ray2, oldRay, level);
487
488        rayTimer.Entry();
489
490        // new triangle discovered? => add new ray to queue
491        HandleRay(newRay);
492
493        rayTimer.Exit();
494
495        return castRays;
496}
497
498
499int GvsPreprocessor::AdaptiveBorderSampling(const VssRay &currentRay)
500{
501        Intersectable *tObj = currentRay.mTerminationObject;
502
503        // question matt: can this be possible?
504        if (!tObj) return 0;
505
506        Triangle3 hitTriangle;
507
508        // other types not implemented yet
509        if (tObj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
510                hitTriangle = static_cast<TriangleIntersectable *>(tObj)->GetItem();
511        else
512                cout << "border sampling: " << Intersectable::GetTypeName(tObj) << " not yet implemented" << endl;
513
514        //cout << "type: " << Intersectable::GetTypeName(tObj) << endl;
515        generationTimer.Entry();
516
517        static VertexContainer enlargedTriangle;
518        enlargedTriangle.clear();
519
520        /// create 3 new hit points for each vertex
521        EnlargeTriangle(enlargedTriangle, hitTriangle, currentRay);
522       
523        /// create rays from sample points and handle them
524        static SimpleRayContainer simpleRays;
525        simpleRays.clear();
526
527        VertexContainer::const_iterator vit, vit_end = enlargedTriangle.end();
528
529        for (vit = enlargedTriangle.begin(); vit != vit_end; ++ vit)
530        {
531                const Vector3 rayDir = (*vit) - currentRay.GetOrigin();
532
533                SimpleRay sr(currentRay.GetOrigin(), rayDir, SamplingStrategy::GVS, 1.0f);
534                simpleRays.AddRay(sr);
535        }
536
537        //if (rand() < RAND_MAX / 10)   cout << "o: " << currentRay.GetOrigin() << endl;
538
539        //////////
540        //-- fill up simple rays with random rays so we can cast 16 rays at a time
541
542        const int numRandomRays = 16 - (int)simpleRays.size();
543        GenerateRays(numRandomRays, *mDistribution, simpleRays, sInvalidSamples);
544
545        generationTimer.Exit();
546
547
548        /////////////////////
549        //-- cast rays to vertices and determine visibility
550       
551        static VssRayContainer vssRays;
552        vssRays.clear();
553
554        // for the original implementation we don't cast double rays
555        const bool castDoubleRays = !mPerViewCell;
556        // cannot prune invalid rays because we have to compare adjacent rays
557        const bool pruneInvalidRays = false;
558
559        //gvsTimer.Entry();
560        castTimer.Entry();
561
562        CastRays(simpleRays, vssRays, castDoubleRays, pruneInvalidRays);
563       
564        castTimer.Exit();
565        //gvsTimer.Exit();
566
567        const int numBorderSamples = (int)vssRays.size() - numRandomRays;
568        int castRays = (int)simpleRays.size();
569
570        if (GVS_DEBUG)
571        {
572                /*visTriangles.push_back(tObj);
573
574                for (int i = 0; i < 3; ++ i)
575                {
576                        Triangle3 t1(hitTriangle.mVertices[i], enlargedTriangle[3 * i + 0], enlargedTriangle[3 * i + 1]);
577                        Triangle3 t2(hitTriangle.mVertices[i], enlargedTriangle[3 * i + 1], enlargedTriangle[3 * i + 2]);
578
579                        TriangleIntersectable *to1 = new TriangleIntersectable(t1); to1->SetId(tObj->GetId());
580                        TriangleIntersectable *to2 = new TriangleIntersectable(t2); to2->SetId(tObj->GetId());
581
582                        visTriangles.push_back(to1);
583                        visTriangles.push_back(to2);
584                }
585               
586                // set flags
587                VssRayContainer::const_iterator rit, rit_end = vssRays.end();
588
589                for (rit = vssRays.begin(); rit != rit_end; ++ rit)
590                        (*rit)->mFlags |= VssRay::BorderSample;
591                */
592
593                // visualize enlarged triangles
594                currentViz.enlargedTriangle = enlargedTriangle;
595                currentViz.originalTriangle = static_cast<TriangleIntersectable *>(tObj);
596        }
597       
598        if (USE_SUBDIVISION)
599        {
600                //int oldsize = mTrianglePvs.size();
601
602                // recursivly subdivide each edge
603                for (int i = 0; i < numBorderSamples; ++ i)
604                {
605                        if (USE_REVERSE_SAMPLING)
606                                castRays += CheckDiscontinuity(*vssRays[i], hitTriangle, currentRay);
607
608                        castRays += SubdivideEdge(hitTriangle,
609                                                      enlargedTriangle[i],
610                                                                          enlargedTriangle[(i + 1) % numBorderSamples],
611                                                                          *vssRays[i],
612                                                                          *vssRays[(i + 1) % numBorderSamples],
613                                                                          currentRay,
614                                                                          0);
615                }
616
617                //int newsize = mTrianglePvs.size();if(newsize - oldsize) mcout<<"found with subdiv: " << newsize - oldsize << endl;
618        }
619
620        if (GVS_DEBUG)
621                visTriangles.push_back(currentViz);
622
623        mGvsStats.mBorderSamples += castRays;
624       
625        // handle cast rays
626        EnqueueRays(vssRays);
627
628        return castRays;
629}
630
631
632int GvsPreprocessor::AdaptiveBorderSamplingOpt(const VssRay &currentRay)
633{
634        Intersectable *tObj = currentRay.mTerminationObject;
635
636        // question matt: can this be possible?
637        if (!tObj) return 0;
638
639        Triangle3 hitTriangle;
640
641        // other types not implemented yet
642        if (tObj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
643                hitTriangle = static_cast<TriangleIntersectable *>(tObj)->GetItem();
644        else
645                cout << "error: gvs sampling for " << Intersectable::GetTypeName(tObj) << " not implemented" << endl;
646
647       
648        static SimpleRayContainer simpleRays;
649        simpleRays.clear();
650       
651
652        generationTimer.Entry();
653#if 0
654        static VertexContainer enlargedTriangle;
655        enlargedTriangle.clear();
656       
657        /// create 3 new hit points for each vertex
658        EnlargeTriangle(enlargedTriangle, hitTriangle, currentRay);
659
660        static VertexContainer subdivEnlargedTri;       
661        subdivEnlargedTri.clear();
662
663        for (size_t i = 0; i < enlargedTriangle.size(); ++ i)
664        {
665                const Vector3 p1 = enlargedTriangle[i];
666                const Vector3 p2 = enlargedTriangle[(i + 1) % enlargedTriangle.size()];
667
668                // the new subdivision point
669                const Vector3 p = (p1 + p2) * 0.5f;
670
671                subdivEnlargedTri.push_back(p1);
672                subdivEnlargedTri.push_back(p);
673        }
674
675        VertexContainer::const_iterator vit, vit_end = subdivEnlargedTri.end();
676
677        for (vit = subdivEnlargedTri.begin(); vit != vit_end; ++ vit)
678        {
679                const Vector3 rayDir = (*vit) - currentRay.GetOrigin();
680
681                SimpleRay sr(currentRay.GetOrigin(), rayDir, SamplingStrategy::GVS, 1.0f);
682                simpleRays.AddRay(sr); 
683        }
684
685#endif 
686
687        //////////
688        //-- fill up simple rays with random rays so we can cast 16 rays at a time
689
690        const int numRandomRays = 128;//16 - ((int)simpleRays.size() % 16);
691
692        GenerateImportanceSamples(currentRay, hitTriangle, numRandomRays, simpleRays);
693       
694        generationTimer.Exit();
695
696
697
698        /////////////////////
699        //-- cast rays to vertices and determine visibility
700       
701        static VssRayContainer vssRays;
702        vssRays.clear();
703
704        // for the original implementation we don't cast double rays
705        const bool castDoubleRays = !mPerViewCell;
706        // cannot prune invalid rays because we have to compare adjacent rays
707        const bool pruneInvalidRays = false;
708
709        //if ((simpleRays.size() % 16) != 0) cerr << "ray size not aligned" << endl;
710       
711        //gvsTimer.Entry();
712        castTimer.Entry();
713
714        CastRays(simpleRays, vssRays, castDoubleRays, pruneInvalidRays);
715       
716        castTimer.Exit();
717        //gvsTimer.Exit();
718
719        const int numBorderSamples = (int)vssRays.size() - numRandomRays;
720        int castRays = (int)simpleRays.size();
721
722        mGvsStats.mBorderSamples += castRays;
723
724        if (USE_REVERSE_SAMPLING)
725        {
726                static SimpleRayContainer simpleRays;
727                simpleRays.clear();
728
729                SimpleRay simpleRay;
730                for (size_t i = 0; i < vssRays.size(); ++ i)
731                {
732                        // check for discontinuity and cast reverse rays if necessary
733                        //castRays += CheckDiscontinuity2(*vssRays[i], hitTriangle, currentRay);
734                        if (CheckDiscontinuity2(*vssRays[i], hitTriangle, currentRay, simpleRay))
735                                simpleRays.push_back(simpleRay);
736                }
737               
738                static VssRayContainer reverseRays;
739                reverseRays.clear();
740                CastRays(simpleRays, reverseRays, false, false);
741
742                mGvsStats.mReverseSamples += (int)reverseRays.size();
743       
744                castRays +=(int)reverseRays.size();
745        }
746
747#if 0
748
749    // recursivly subdivide each edge
750        for (int i = 0; i < numBorderSamples; ++ i)
751        {
752                castRays += SubdivideEdge(hitTriangle,
753                                                                  subdivEnlargedTri[i],
754                                                                  subdivEnlargedTri[(i + 1) % numBorderSamples],
755                                                                  *vssRays[i],
756                                                                  *vssRays[(i + 1) % numBorderSamples],
757                                                                  currentRay, 0);
758        }
759       
760#endif
761
762        // handle cast rays
763        EnqueueRays(vssRays);
764
765        return castRays;
766}
767
768
769bool GvsPreprocessor::GetPassingPoint(const VssRay &currentRay,
770                                                                          const Triangle3 &occluder,
771                                                                          const VssRay &oldRay,
772                                                                          Vector3 &newPoint) const
773{
774        /////////////////////////
775        //-- We interserct the plane p = (xp, hit(x), hit(xold))
776        //-- with the newly found occluder (xold is the previous ray from
777        //-- which x was generated). On the intersecting line, we select a point
778        //-- pnew which lies just outside of the new triangle so the ray
779        //-- just passes through the gap
780
781        const Plane3 plane(currentRay.GetOrigin(),
782                                           currentRay.GetTermination(),
783                                           oldRay.GetTermination());
784       
785        Vector3 pt1, pt2;
786
787        if (!occluder.GetPlaneIntersection(plane, pt1, pt2))
788                return false;
789
790        // get the intersection point on the old ray
791        const Plane3 triPlane(occluder.GetNormal(), occluder.mVertices[0]);
792
793        const float t = triPlane.FindT(oldRay.mOrigin, oldRay.mTermination);
794        const Vector3 pt3 = oldRay.mOrigin + t * (oldRay.mTermination - oldRay.mOrigin);
795
796        // evaluate new hitpoint just outside the triangle
797        // the point is chosen to be on the side closer to the original ray
798        if (SqrDistance(pt1, pt3) < SqrDistance(pt2, pt3))
799                newPoint = pt1 + mEps * (pt1 - pt2);
800        else
801                newPoint = pt2 + mEps * (pt2 - pt1);
802
803        //cout << "passing point: " << newPoint << endl << endl;
804        return true;
805}
806
807
808bool GvsPreprocessor::ComputeReverseRay(const VssRay &currentRay,
809                                                                                const Triangle3 &hitTriangle,
810                                                                                const VssRay &oldRay,
811                                                                                SimpleRay &reverseRay)
812{
813        // optain triangle that occludes the path to the currently processed mesh
814        Triangle3 occluder;
815        Intersectable *tObj = currentRay.mTerminationObject;
816
817        // q: why can this happen?
818        if (!tObj)
819                return false;
820
821        // other types not implemented yet
822        if (tObj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
823                occluder = static_cast<TriangleIntersectable *>(tObj)->GetItem();
824        else
825                cout << "reverse sampling: " << tObj->Type() << " not yet implemented" << endl;
826       
827        // get a point which is passing just outside of the occluder
828    Vector3 newPoint;
829
830        // q: why is there sometimes no intersecton found?
831        if (!GetPassingPoint(currentRay, occluder, oldRay, newPoint))
832                return false;
833
834        const Vector3 predicted = CalcPredictedHitPoint(currentRay, hitTriangle, oldRay);
835
836        //////////////
837        //-- Construct the mutated ray with xnew,
838        //-- dir = predicted(x)- pnew as direction vector
839
840        Vector3 newDir = newDir = predicted - newPoint;
841
842        // take xnew, p = intersect(viewcell, line(pnew, predicted(x)) as origin ?
843        // difficult to say!!
844        const float offset = 0.5f;
845        Vector3 newOrigin = newPoint - newDir * offset;
846       
847
848        //////////////
849        //-- for per view cell sampling, we must intersect
850        //-- with the current view cell
851
852    if (mPerViewCell)
853        {
854                if (!IntersectsViewCell(newOrigin, -newDir))
855                        return false;
856        }
857
858        reverseRay = SimpleRay(newOrigin, newDir, SamplingStrategy::GVS, 1.0f);
859
860        return true;
861}
862
863
864bool GvsPreprocessor::IntersectsViewCell(Vector3 &origin, const Vector3 &dir) const
865{
866        AxisAlignedBox3 box = mCurrentViewCell->GetBox();
867
868        if (box.IsInside(origin))
869        {
870                //cout<<"z";
871                return true;
872        }
873       
874        // intersect ray with view cell and
875        SimpleRay ray(origin, dir, 0, 1.0f);
876
877        float tnear, tfar;
878       
879        // check if ray intersects view cell
880        if (!mCurrentViewCell->GetBox().Intersects(ray, tnear, tfar))
881                return false;
882
883        origin = origin + dir * tnear;
884        //cout<<"r";
885        return true;
886}
887
888
889int GvsPreprocessor::CastInitialSamples(int numSamples)
890{       
891        initialTimer.Entry();
892
893        // generate simple rays
894        static SimpleRayContainer simpleRays;
895        simpleRays.clear();
896
897        generationTimer.Entry();
898
899        if (mUseProbablyVisibleSampling)// && (RandomValue(0, 1) > 0.5))
900        {
901                ProbablyVisibleDistribution distr(*this, mCurrentViewCell, &mProbablyVisibleTriangles);
902                GenerateRays(numSamples, distr, simpleRays, sInvalidSamples);
903        }
904        else
905        {
906                GenerateRays(mUseDeterministicGvs ?
907                        numSamples : numSamples / 16, *mDistribution, simpleRays, sInvalidSamples);
908        }
909
910        generationTimer.Exit();
911
912        // cast generated samples
913        static VssRayContainer vssRays;
914        vssRays.clear();
915
916        castTimer.Entry();
917
918        if (mUseDeterministicGvs)
919        {
920                const bool castDoubleRays = !mPerViewCell;
921                const bool pruneInvalidRays = false;
922                //const bool pruneInvalidRays = true;
923
924                CastRays(simpleRays, vssRays, castDoubleRays, pruneInvalidRays);
925        }
926        else
927        {
928                if (0)
929                        // casting bundles of 4 rays generated from the simple rays
930                        CastRayBundles4(simpleRays, vssRays);
931                else
932                        CastRayBundles16(simpleRays, vssRays, mInitialJitter);
933        }
934
935        castTimer.Exit();
936//for (int i = 0; i< simpleRays.size();++ i)
937//      if (rand() < RAND_MAX / 10)     cout << "o: " << simpleRays[i].mOrigin << endl;
938
939        // add to ray queue
940        EnqueueRays(vssRays);
941
942        initialTimer.Exit();
943
944        return (int)vssRays.size();
945}
946
947
948void GvsPreprocessor::EnqueueRays(const VssRayContainer &samples)
949{
950        rayTimer.Entry();
951
952        // add samples to ray queue
953        VssRayContainer::const_iterator vit, vit_end = samples.end();
954        for (vit = samples.begin(); vit != vit_end; ++ vit)
955        {
956                VssRay *ray = *vit;
957                HandleRay(ray);
958        }
959
960        rayTimer.Exit();
961}
962
963
964int GvsPreprocessor::ProcessQueue()
965{
966        gvsTimer.Entry();
967
968        ++ mGvsStats.mGvsRuns;
969
970        int castSamples = 0;
971
972        while (!mRayQueue.empty())
973        {
974                size_t oldContri = mTrianglePvs.size();
975                // handle next ray
976                VssRay *ray = mRayQueue.top();
977                mRayQueue.pop();
978               
979                if (mUseDeterministicGvs)
980                {
981                        castSamples += AdaptiveBorderSampling(*ray);
982                        mRayCaster->SheduleRayForDeletion(ray);
983                }
984                else
985                {
986                        castSamples += AdaptiveBorderSamplingOpt(*ray);
987
988                        // ray still gives contribution => enqeue again
989                        if ((mTrianglePvs.size() - oldContri) > 0)
990                        {
991                                mRayQueue.push(ray);
992                        }
993                        else
994                        {
995                                mRayCaster->SheduleRayForDeletion(ray);
996                        }
997                }
998
999
1000        }
1001
1002        gvsTimer.Exit();
1003
1004        return castSamples;
1005}
1006
1007
1008void ExportVssRays(Exporter *exporter, const VssRayContainer &vssRays)
1009{
1010        VssRayContainer vcRays, vcRays2, vcRays3;
1011
1012        VssRayContainer::const_iterator rit, rit_end = vssRays.end();
1013
1014        // prepare some rays for output
1015        for (rit = vssRays.begin(); rit != rit_end; ++ rit)
1016        {
1017                //const float p = RandomValue(0.0f, (float)vssRays.size());
1018
1019                if (1)//(p < raysOut)
1020                {
1021                        if ((*rit)->mFlags & VssRay::BorderSample)
1022                                vcRays.push_back(*rit);
1023                        else if ((*rit)->mFlags & VssRay::ReverseSample)
1024                                vcRays2.push_back(*rit);
1025                        else
1026                                vcRays3.push_back(*rit);
1027                }
1028        }
1029
1030        exporter->ExportRays(vcRays, RgbColor(1, 0, 0));
1031        exporter->ExportRays(vcRays2, RgbColor(0, 1, 0));
1032        exporter->ExportRays(vcRays3, RgbColor(1, 1, 1));
1033}
1034
1035
1036void GvsPreprocessor::VisualizeViewCell(const ObjectContainer &objects)
1037{
1038    Intersectable::NewMail();
1039        Material m;
1040       
1041        char str[64]; sprintf_s(str, "pass%06d.wrl", mProcessedViewCells);
1042
1043        Exporter *exporter = Exporter::GetExporter(str);
1044        if (!exporter)
1045                return;
1046
1047        ObjectContainer::const_iterator oit, oit_end = objects.end();
1048
1049        for (oit = objects.begin(); oit != oit_end; ++ oit)
1050        {
1051                Intersectable *intersect = *oit;
1052               
1053                m = RandomMaterial();
1054                exporter->SetForcedMaterial(m);
1055                exporter->ExportIntersectable(intersect);
1056        }
1057
1058        cout << "vssrays: " << (int)mVssRays.size() << endl;
1059        ExportVssRays(exporter, mVssRays);
1060
1061
1062        /////////////////
1063        //-- export view cell geometry
1064
1065        //exporter->SetWireframe();
1066
1067        m.mDiffuseColor = RgbColor(0, 1, 0);
1068        exporter->SetForcedMaterial(m);
1069
1070        AxisAlignedBox3 bbox = mCurrentViewCell->GetMesh()->mBox;
1071        exporter->ExportBox(bbox);
1072        //exporter->SetFilled();
1073
1074        delete exporter;
1075}
1076
1077
1078void GvsPreprocessor::VisualizeViewCells()
1079{
1080        char str[64]; sprintf_s(str, "tmp/pass%06d_%04d-", mProcessedViewCells, mPass);
1081                       
1082        // visualization
1083        if (mGvsStats.mPassContribution > 0)
1084        {
1085                const bool exportRays = true;
1086                const bool exportPvs = true;
1087
1088                mViewCellsManager->ExportSingleViewCells(mObjects,
1089                                                                                                 10,
1090                                                                                                 false,
1091                                                                                                 exportPvs,
1092                                                                                                 exportRays,
1093                                                                                                 1000,
1094                                                                                                 str);
1095        }
1096
1097        // remove pass samples
1098        ViewCellContainer::const_iterator vit, vit_end = mViewCellsManager->GetViewCells().end();
1099
1100        for (vit = mViewCellsManager->GetViewCells().begin(); vit != vit_end; ++ vit)
1101        {
1102                (*vit)->DelRayRefs();
1103        }
1104}
1105
1106
1107void GvsPreprocessor::CompileViewCellsFromPointList()
1108{
1109        ViewCell::NewMail();
1110
1111        // Receive list of view cells from view cells manager
1112        ViewCellPointsList *vcPoints = mViewCellsManager->GetViewCellPointsList();
1113
1114        vector<ViewCellPoints *>::const_iterator vit, vit_end = vcPoints->end();
1115
1116        for (vit = vcPoints->begin(); vit != vit_end; ++ vit)
1117        {
1118                ViewCellPoints *vp = *vit;
1119
1120                if (vp->first) // view cell  specified
1121                {
1122                        ViewCell *viewCell = vp->first;
1123
1124                        if (!viewCell->Mailed())
1125                        {
1126                                viewCell->Mail();
1127                                mViewCells.push_back(viewCell);
1128
1129                                if (mViewCells.size() >= mMaxViewCells)
1130                                        break;
1131                        }
1132                }
1133                else // no view cell specified => compute view cells using view point
1134                {
1135                        SimpleRayContainer::const_iterator rit, rit_end = vp->second.end();
1136
1137                        for (rit = vp->second.begin(); rit != rit_end; ++ rit)
1138                        {
1139                                SimpleRay ray = *rit;
1140
1141                                ViewCell *viewCell = mViewCellsManager->GetViewCell(ray.mOrigin);
1142
1143                                if (viewCell && !viewCell->Mailed())
1144                                {
1145                                        viewCell->Mail();
1146                                        mViewCells.push_back(viewCell);
1147
1148                                        if (mViewCells.size() >= mMaxViewCells)
1149                                                break;
1150                                }
1151                        }
1152                }
1153        }
1154}
1155
1156
1157void GvsPreprocessor::CompileViewCellsList()
1158{
1159        if (!mViewCellsManager->GetViewCellPointsList()->empty())
1160        {
1161                cout << "processing view point list" << endl;
1162                CompileViewCellsFromPointList();
1163        }
1164        else
1165        {
1166                ViewCell::NewMail();
1167
1168                while ((int)mViewCells.size() < mMaxViewCells)
1169                {
1170                        const int tries = 10000;
1171                        int i = 0;
1172
1173                        for (i = 0; i < tries; ++ i)
1174                        {
1175                                const int idx = (int)RandomValue(0.0f, (float)mViewCellsManager->GetNumViewCells() - 0.5f);
1176
1177                                ViewCell *viewCell = mViewCellsManager->GetViewCell(idx);
1178
1179                                if (!viewCell->Mailed())
1180                                {
1181                                        viewCell->Mail();
1182                                        break;
1183                                }
1184
1185                                mViewCells.push_back(viewCell);
1186                        }
1187
1188                        if (i == tries)
1189                        {
1190                                cerr << "big error! no view cell found" << endl;
1191                                break;
1192                        }
1193                }
1194        }
1195
1196        cout << "\ncomputing list of " << mViewCells.size() << " view cells" << endl;
1197}
1198
1199
1200void GvsPreprocessor::ComputeViewCellGeometryIntersection()
1201{
1202        intersectionTimer.Entry();
1203
1204        AxisAlignedBox3 box = mCurrentViewCell->GetBox();
1205
1206        int oldTrianglePvs = (int)mTrianglePvs.size();
1207        int newKdObj = 0;
1208
1209        // compute pvs kd nodes that intersect view cell
1210        ObjectContainer kdobjects;
1211
1212        // find intersecting objects not in pvs (i.e., only unmailed)
1213        mKdTree->CollectKdObjects(box, kdobjects);
1214
1215        ObjectContainer pvsKdObjects;
1216
1217        ObjectContainer::const_iterator oit, oit_end = kdobjects.end();
1218
1219        for (oit = kdobjects.begin(); oit != oit_end; ++ oit)
1220        {
1221        KdIntersectable *kdInt = static_cast<KdIntersectable *>(*oit);
1222       
1223                myobjects.clear();
1224                mKdTree->CollectObjectsWithDublicates(kdInt->GetItem(), myobjects);
1225
1226                // account for kd object pvs
1227                bool addkdobj = false;
1228
1229                ObjectContainer::const_iterator oit, oit_end = myobjects.end();
1230
1231                for (oit = myobjects.begin(); oit != oit_end; ++ oit)
1232                {
1233                        TriangleIntersectable *triObj = static_cast<TriangleIntersectable *>(*oit);
1234             
1235                        // test if the triangle itself intersects
1236                        if (box.Intersects(triObj->GetItem()))
1237                                addkdobj = AddTriangleObject(triObj);
1238                }
1239               
1240                // add node to kd pvs
1241                if (1 && addkdobj)
1242                {
1243                        ++ newKdObj;
1244                        mCurrentViewCell->GetPvs().AddSampleDirty(kdInt, 1.0f);
1245                        //mCurrentViewCell->GetPvs().AddSampleDirtyCheck(kdInt, 1.0f);
1246                        if (QT_VISUALIZATION_SHOWN) UpdateStatsForVisualization(kdInt);
1247                }
1248        }
1249
1250        cout << "added " << (int)mTrianglePvs.size() - oldTrianglePvs << " triangles (" << newKdObj << " objects) by intersection" << endl;
1251
1252        intersectionTimer.Exit();
1253}
1254
1255
1256void GvsPreprocessor::PerViewCellComputation()
1257{
1258        while (mCurrentViewCell = NextViewCell())
1259        {
1260                preparationTimer.Entry();
1261
1262                // hack: reset counters (could be done with a mailing-like approach
1263                ObjectContainer::const_iterator oit, oit_end = mObjects.end();
1264                for (oit = mObjects.begin(); oit != oit_end; ++ oit)
1265                        (*oit)->mCounter = NOT_ACCOUNTED_OBJECT;
1266
1267                preparationTimer.Exit();
1268
1269                mDistribution->SetViewCell(mCurrentViewCell);
1270
1271        ComputeViewCell();
1272        }
1273}
1274
1275
1276void GvsPreprocessor::PerViewCellComputation2()
1277{
1278        while (1)
1279        {
1280                if (!mRendererWidget)
1281                        continue;
1282
1283        mCurrentViewCell = mViewCellsManager->GetViewCell(mRendererWidget->GetViewPoint());
1284
1285                // no valid view cell or view cell already computed
1286                if (!mCurrentViewCell || !mCurrentViewCell->GetPvs().Empty() || !mRendererWidget->mComputeGVS)
1287                        continue;
1288
1289                mRendererWidget->mComputeGVS = false;
1290                // hack: reset counters
1291                ObjectContainer::const_iterator oit, oit_end = mObjects.end();
1292
1293                for (oit = mObjects.begin(); oit != oit_end; ++ oit)
1294                        (*oit)->mCounter = NOT_ACCOUNTED_OBJECT;
1295
1296                ComputeViewCell();
1297                ++ mProcessedViewCells;
1298        }
1299}
1300
1301
1302void GvsPreprocessor::StorePvs(const ObjectContainer &objectPvs)
1303{
1304        ObjectContainer::const_iterator oit, oit_end = objectPvs.end();
1305
1306        for (oit = objectPvs.begin(); oit != oit_end; ++ oit)
1307        {
1308                mCurrentViewCell->GetPvs().AddSample(*oit, 1);
1309        }
1310}
1311
1312
1313void GvsPreprocessor::UpdatePvs(ViewCell *currentViewCell)
1314{
1315        ObjectPvs newPvs;
1316        BvhLeaf::NewMail();
1317
1318        ObjectPvsIterator pit = currentViewCell->GetPvs().GetIterator();
1319
1320        // output PVS of view cell
1321        while (pit.HasMoreEntries())
1322        {               
1323                Intersectable *intersect = pit.Next();
1324
1325                BvhLeaf *bv = intersect->mBvhLeaf;
1326
1327                if (!bv || bv->Mailed())
1328                        continue;
1329               
1330                bv->Mail();
1331
1332                //m.mDiffuseColor = RgbColor(1, 0, 0);
1333                newPvs.AddSampleDirty(bv, 1.0f);
1334        }
1335
1336        newPvs.SimpleSort();
1337
1338        currentViewCell->SetPvs(newPvs);
1339}
1340
1341 
1342void GvsPreprocessor::GetObjectPvs(ObjectContainer &objectPvs) const
1343{
1344        BvhLeaf::NewMail();
1345
1346        objectPvs.reserve((int)mTrianglePvs.size());
1347
1348        ObjectContainer::const_iterator oit, oit_end = mTrianglePvs.end();
1349
1350        for (oit = mTrianglePvs.begin(); oit != oit_end; ++ oit)
1351        {
1352                Intersectable *intersect = *oit;
1353       
1354                BvhLeaf *bv = intersect->mBvhLeaf;
1355
1356                // hack: reset counter
1357                (*oit)->mCounter = NOT_ACCOUNTED_OBJECT;
1358
1359                if (!bv || bv->Mailed())
1360                        continue;
1361
1362                bv->Mail();
1363                objectPvs.push_back(bv);
1364        }
1365}
1366
1367
1368void GvsPreprocessor::GlobalComputation()
1369{
1370        int passSamples = 0;
1371        int randomSamples = 0;
1372        int gvsSamples = 0;
1373        int oldContribution = 0;
1374
1375        while (mGvsStats.mTotalSamples < mTotalSamples)
1376        {
1377                mRayCaster->InitPass();
1378
1379                int newRandomSamples, newGvsSamples;
1380
1381                // Ray queue empty =>
1382                // cast a number of uniform samples to fill ray queue
1383                newRandomSamples = CastInitialSamples(mInitialSamples);
1384               
1385                if (!mOnlyRandomSampling)
1386                        newGvsSamples = ProcessQueue();
1387
1388                passSamples += newRandomSamples + newGvsSamples;
1389                mGvsStats.mTotalSamples += newRandomSamples + newGvsSamples;
1390
1391                mGvsStats.mRandomSamples += newRandomSamples;
1392                mGvsStats.mGvsSamples += newGvsSamples;
1393
1394
1395                if (passSamples % (mGvsSamplesPerPass + 1) == mGvsSamplesPerPass)
1396                {
1397                        ++ mPass;
1398
1399                        mGvsStats.mPassContribution = mGvsStats.mTotalContribution - oldContribution;
1400                       
1401                        ////////
1402                        //-- stats
1403
1404                        //cout << "\nPass " << mPass << " #samples: " << mGvsStats.mTotalSamples << " of " << mTotalSamples << endl;
1405                        mGvsStats.mPass = mPass;
1406                        mGvsStats.Stop();
1407                        mGvsStats.Print(mGvsStatsStream);
1408
1409                        // reset
1410                        oldContribution = mGvsStats.mTotalContribution;
1411                        mGvsStats.mPassContribution = 0;
1412                        passSamples = 0;
1413
1414                        if (GVS_DEBUG)
1415                                VisualizeViewCells();
1416                }
1417        }
1418}
1419
1420
1421bool GvsPreprocessor::ComputeVisibility()
1422{
1423        cout << "Gvs Preprocessor started\n" << flush;
1424        const long startTime = GetTime();
1425
1426        //Randomize(0);
1427        mGvsStats.Reset();
1428        mGvsStats.Start();
1429
1430        if (!mLoadViewCells)
1431        {       
1432                /// construct the view cells from the scratch
1433                ConstructViewCells();
1434                // reset pvs already gathered during view cells construction
1435                mViewCellsManager->ResetPvs();
1436                cout << "finished view cell construction" << endl;
1437        }
1438
1439        if (mPerViewCell)
1440        {
1441#if 1
1442                // provide list of view cells to compute
1443                CompileViewCellsList();
1444                // start per view cell gvs
1445                PerViewCellComputation();
1446#else
1447                PerViewCellComputation2();
1448
1449#endif
1450        }
1451        else
1452        {
1453                GlobalComputation();
1454        }
1455
1456        cout << "cast " << mGvsStats.mTotalSamples / (1e3f * TimeDiff(startTime, GetTime())) << "M single rays/s" << endl;
1457
1458        if (GVS_DEBUG)
1459        {
1460                CLEAR_CONTAINER(mVssRays);
1461        }
1462       
1463        // export the preprocessed information to a file
1464        if (0 && mExportVisibility)
1465                ExportPreprocessedData(mVisibilityFileName);
1466       
1467        // compute the pixel error of this visibility solution
1468        if (0 && mEvaluatePixelError)
1469                ComputeRenderError();
1470
1471        return true;
1472}
1473
1474
1475void GvsPreprocessor::DeterminePvsObjects(VssRayContainer &rays)
1476{
1477        // store triangle directly
1478        mViewCellsManager->DeterminePvsObjects(rays, true);
1479}
1480
1481
1482void GvsStatistics::Print(ostream &app) const
1483{
1484        app << "#ViewCells\n" << mViewCells << endl;
1485        app << "#Id\n" << mViewCellId << endl;
1486        app << "#Time\n" << mTimePerViewCell << endl;;
1487        app << "#TriPvs\n" << mTrianglePvs << endl;
1488        app << "#ObjectPvs\n" << mPerViewCellPvs << endl;
1489        app << "#UpdatedPvs\n" << (int)mPvsCost << endl;
1490
1491        app << "#PerViewCellSamples\n" << mPerViewCellSamples << endl;
1492        app << "#RaysPerSec\n" << RaysPerSec() << endl;
1493       
1494        app << "#TotalPvs\n" << mTotalPvs << endl;
1495        app << "#TotalTime\n" << mTotalTime << endl;
1496        app << "#TotalSamples\n" << mTotalSamples << endl;
1497
1498        app << "#AvgPvs: " << mPvsCost / mViewCells << endl;
1499        app << "#TotalTrianglePvs\n" << mTotalTrianglePvs << endl;
1500       
1501        if (0)
1502        {
1503                app << "#ReverseSamples\n" << mReverseSamples << endl;
1504                app << "#BorderSamples\n" << mBorderSamples << endl;
1505
1506                app << "#Pass\n" << mPass << endl;
1507                app << "#ScDiff\n" << mPassContribution << endl;
1508                app << "#GvsRuns\n" << mGvsRuns << endl;       
1509
1510                app     << "#SamplesContri\n" << mTotalContribution << endl;
1511        }
1512
1513        app << endl;
1514}
1515
1516
1517void GvsPreprocessor::ComputeViewCell()
1518{
1519        const long startTime = GetTime();
1520
1521        // initialise
1522        mGvsStats.mPerViewCellSamples = 0;
1523        mGvsStats.mRandomSamples = 0;
1524        mGvsStats.mGvsSamples = 0;
1525        mUseProbablyVisibleSampling = false;
1526        //renderer->mPvsStat.currentPass = 0;
1527
1528        mPass = 0;
1529
1530        int oldContribution = 0;
1531        int passSamples = 0;
1532
1533        for (int i = 0; i < 2; ++ i)
1534                mGenericStats[i] = 0;
1535
1536        mTrianglePvs.clear();
1537
1538
1539        // hack: take bounding box of view cell as view cell bounds
1540        mCurrentViewCell->GetMesh()->ComputeBoundingBox();
1541
1542        // use mailing for kd node pvs
1543        KdNode::NewMail();
1544
1545        cout << "\n***********************\n"
1546                << "computing view cell " << mProcessedViewCells
1547                << " (id: " << mCurrentViewCell->GetId() << ")" << endl;
1548        cout << "bb: " << mCurrentViewCell->GetBox() << endl;
1549
1550        mainLoopTimer.Entry();
1551
1552        while (1)
1553        {
1554                sInvalidSamples = 0;
1555                int oldPvsSize = mCurrentViewCell->GetPvs().GetSize();
1556               
1557                mRayCaster->InitPass();
1558
1559                int newRandomSamples, newGvsSamples, newSamples;
1560
1561                // Ray queue empty =>
1562                // cast a number of uniform samples to fill ray queue
1563                newRandomSamples = CastInitialSamples(mInitialSamples);
1564               
1565                //if (!mUseProbablyVisibleSampling && !mOnlyRandomSampling)
1566                if (!mOnlyRandomSampling)
1567                        newGvsSamples = ProcessQueue();
1568
1569                newSamples = newRandomSamples + newGvsSamples;
1570
1571                passSamples += newSamples;
1572                mGvsStats.mPerViewCellSamples += newSamples;
1573
1574                mGvsStats.mRandomSamples += newRandomSamples;
1575                mGvsStats.mGvsSamples += newGvsSamples;
1576
1577
1578                if (passSamples >= mGvsSamplesPerPass)
1579                {
1580                        if (0 && GVS_DEBUG) VisualizeViewCell(mTrianglePvs);
1581
1582                        //const bool convertPerPass = true;
1583                        const bool convertPerPass = false;
1584
1585                        if (convertPerPass)
1586                        {       
1587                                int newObjects = ConvertObjectPvs();
1588
1589                                cout << "added " << newObjects << " triangles to triangle pvs" << endl;
1590                                mGvsStats.mTotalContribution += newObjects;
1591                        }
1592
1593                        ++ mPass;
1594                        mGvsStats.mPassContribution = mGvsStats.mTotalContribution - oldContribution;
1595
1596                        if (!mUseDeterministicGvs && (mGvsStats.mPassContribution < 2000))
1597                                mUseProbablyVisibleSampling = true;
1598                       
1599                        if (mUseProbablyVisibleSampling)
1600                                PrepareProbablyVisibleSampling();
1601
1602
1603                        ////////
1604                        //-- stats
1605
1606                        mGvsStats.mPass = mPass;
1607
1608                        cout << "\nPass " << mPass << " #samples: " << mGvsStats.mPerViewCellSamples << endl;
1609                        cout << "contribution=" << mGvsStats.mPassContribution << " (of " << mMinContribution << ")" << endl;
1610                        cout << "obj contri=" << mCurrentViewCell->GetPvs().GetSize() - oldPvsSize << " (of " << mMinContribution << ")" << endl;
1611
1612                        // termination criterium
1613                        if (mGvsStats.mPassContribution < mMinContribution)
1614                                break;
1615
1616                        // reset stats
1617                        oldContribution = mGvsStats.mTotalContribution;
1618                        mGvsStats.mPassContribution = 0;
1619                        passSamples = 0;
1620                       
1621                        // compute the pixel error of this visibility solution
1622                        if (1 && mEvaluatePixelError)
1623                                ComputeRenderError();
1624                }
1625        }
1626       
1627        mainLoopTimer.Exit();
1628
1629        // at last compute objects that directly intersect view cell
1630        ComputeViewCellGeometryIntersection();
1631               
1632        // compute the pixel error of this visibility solution
1633        if (mEvaluatePixelError)
1634                ComputeRenderError();
1635
1636        ////////
1637        //-- stats
1638
1639        // timing
1640        mGvsStats.mTimePerViewCell = TimeDiff(startTime, GetTime()) * 1e-3f;
1641
1642        ComputeStats();
1643}
1644
1645
1646void GvsPreprocessor::ComputeStats()
1647{
1648        // compute pvs size using larger (bvh objects)
1649        // note: for kd pvs we had to do this during gvs computation
1650        if (!mUseKdPvs)
1651        {
1652                ObjectContainer objectPvs;
1653
1654                // optain object pvs
1655                GetObjectPvs(objectPvs);
1656
1657                // add pvs
1658                ObjectContainer::const_iterator it, it_end = objectPvs.end();
1659
1660                for (it = objectPvs.begin(); it != it_end; ++ it)
1661                {
1662                        mCurrentViewCell->GetPvs().AddSampleDirty(*it, 1.0f);
1663                }
1664
1665                cout << "triangle pvs of " << (int)mTrianglePvs.size()
1666                        << " was converted to object pvs of " << (int)objectPvs.size() << endl;
1667
1668                mGvsStats.mPerViewCellPvs = (int)objectPvs.size();
1669                mGvsStats.mPvsCost = 0; // todo objectPvs.EvalPvsCost();
1670        }
1671        else
1672        {
1673                 if (0) // compute pvs kd nodes that intersect view cell
1674                 {
1675                         ObjectContainer mykdobjects;
1676
1677                         // extract kd pvs
1678                         ObjectContainer::const_iterator it, it_end = mTrianglePvs.end();
1679
1680                         for (it = mTrianglePvs.begin(); it != it_end; ++ it)
1681                         {
1682                                 Intersectable *obj = *it;
1683                                 // find intersecting objects not yet in pvs (i.e., only unmailed)
1684                                 mKdTree->CollectKdObjects(obj->GetBox(), mykdobjects);
1685                         }
1686
1687                         // add pvs
1688                         it_end = mykdobjects.end();
1689
1690                         for (it = mykdobjects.begin(); it != it_end; ++ it)
1691                         {
1692                                 mCurrentViewCell->GetPvs().AddSampleDirty(*it, 1.0f);
1693                         }
1694                 
1695                         cout << "added " << (int)mykdobjects.size() << " new objects " << endl;
1696                 }
1697
1698                 mGvsStats.mPerViewCellPvs = mCurrentViewCell->GetPvs().GetSize();
1699                 mGvsStats.mPvsCost = mCurrentViewCell->GetPvs().EvalPvsCost();
1700
1701        }
1702
1703        mGvsStats.mTrianglePvs = (int)mTrianglePvs.size();
1704
1705
1706        ////////////////
1707        // global values
1708
1709        mGvsStats.mViewCells = mProcessedViewCells;
1710        mGvsStats.mTotalTrianglePvs += mGvsStats.mTrianglePvs;
1711        mGvsStats.mTotalTime += mGvsStats.mTimePerViewCell;
1712    mGvsStats.mTotalPvs += mGvsStats.mPerViewCellPvs;
1713        mGvsStats.mTotalSamples += mGvsStats.mPerViewCellSamples;
1714
1715        cout << "id: " << mCurrentViewCell->GetId() << endl;
1716        cout << "pvs cost "  << mGvsStats.mPvsCost / 1000000 << " M" << endl;
1717        cout << "pvs tri: " << mTrianglePvs.size() << endl;
1718        cout << "samples: " << mGvsStats.mTotalSamples / 1000000 << " M" << endl;
1719        printf("contri: %f tri / K rays\n", 1000.0f * (float)mTrianglePvs.size() / mGvsStats.mTotalSamples);
1720
1721        //cout << "invalid samples ratio: " << (float)sInvalidSamples / mGvsStats.mPerViewCellSamples << endl;
1722
1723        double rayTime = rayTimer.TotalTime();
1724        double kdPvsTime = kdPvsTimer.TotalTime();
1725        double gvsTime = gvsTimer.TotalTime();
1726        double initialTime = initialTimer.TotalTime();
1727        double intersectionTime = intersectionTimer.TotalTime();
1728        double preparationTime = preparationTimer.TotalTime();
1729        double mainLoopTime = mainLoopTimer.TotalTime();
1730        double contributionTime = contributionTimer.TotalTime();
1731        double castTime = castTimer.TotalTime();
1732        double generationTime = generationTimer.TotalTime();
1733        double rawCastTime = mRayCaster->rawCastTimer.TotalTime();
1734
1735        cout << "handleRay              : " << rayTime << endl;
1736        cout << "kd pvs                 : " << kdPvsTime << endl;
1737        cout << "gvs sampling           : " << gvsTime << endl;
1738        cout << "initial sampling       : " << initialTime << endl;
1739        cout << "view cell intersection : " << intersectionTime << endl;
1740        cout << "preparation            : " << preparationTime << endl;
1741        cout << "main loop              : " << mainLoopTime << endl;
1742        cout << "has contribution       : " << contributionTime << endl;
1743        cout << "cast time              : " << castTime << endl;
1744        cout << "generation time        : " << generationTime << endl;
1745        cout << "raw cast time          : " << rawCastTime << endl;
1746
1747        double randomRaysPerSec = mGvsStats.mRandomSamples / (1e6 * initialTime);
1748        double gvsRaysPerSec = mGvsStats.mGvsSamples / (1e6 * gvsTime);
1749        double rawRaysPerSec = mGvsStats.mPerViewCellSamples / (1e6 * rawCastTime);
1750
1751        cout << "cast " << randomRaysPerSec << " M random rays/s: " << endl;
1752        cout << "cast " << gvsRaysPerSec << " M gvs rays/s: " << endl;
1753        cout << "cast " << rawRaysPerSec << " M raw rays/s: " << endl;
1754
1755        mGvsStats.Stop();
1756        mGvsStats.Print(mGvsStatsStream);
1757}
1758
1759
1760int GvsPreprocessor::ConvertObjectPvs()
1761{
1762        static ObjectContainer triangles;
1763
1764        int newObjects = 0;
1765
1766        ObjectPvsIterator pit = mCurrentViewCell->GetPvs().GetIterator();
1767
1768        triangles.clear();
1769
1770        // output PVS of view cell
1771        while (pit.HasMoreEntries())
1772        {               
1773                KdIntersectable *kdInt = static_cast<KdIntersectable *>(pit.Next());
1774
1775                mKdTree->CollectObjectsWithDublicates(kdInt->GetItem(), triangles);
1776
1777                ObjectContainer::const_iterator oit, oit_end = triangles.end();
1778
1779                for (oit = triangles.begin(); oit != oit_end; ++ oit)
1780                {
1781                        if (AddTriangleObject(*oit))
1782                                ++ newObjects;
1783                }
1784        }
1785
1786        return newObjects;
1787}
1788
1789
1790bool GvsPreprocessor::AddTriangleObject(Intersectable *triObj)
1791{
1792        if ((triObj->mCounter < ACCOUNTED_OBJECT))
1793        {
1794                triObj->mCounter += ACCOUNTED_OBJECT;
1795
1796                mTrianglePvs.push_back(triObj);
1797                mGenericStats[0] = (int)mTrianglePvs.size();
1798
1799                return true;
1800        }
1801
1802        return false;
1803}
1804
1805
1806void GvsPreprocessor::CastRayBundles4(const SimpleRayContainer &rays, VssRayContainer &vssRays)
1807{
1808        AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
1809
1810        SimpleRayContainer::const_iterator it, it_end = rays.end();
1811
1812        for (it = rays.begin(); it != it_end; ++ it)
1813                CastRayBundle4(*it, vssRays, box);
1814}
1815
1816
1817void GvsPreprocessor::CastRayBundle4(const SimpleRay &ray,
1818                                                                         VssRayContainer &vssRays,
1819                                                                         const AxisAlignedBox3 &box)
1820{
1821        const float pertubDir = 0.01f;
1822        static Vector3 pertub;
1823
1824        static int hit_triangles[4];
1825        static float dist[4];
1826        static Vector3 dirs[4];
1827        static Vector3 origs[4];
1828
1829        origs[0] = ray.mOrigin;
1830        dirs[0] = ray.mDirection;
1831
1832        for (int i = 1; i < 4; ++ i)
1833        {
1834                origs[i] = ray.mOrigin;
1835
1836                pertub.x = RandomValue(-pertubDir, pertubDir);
1837                pertub.y = RandomValue(-pertubDir, pertubDir);
1838                pertub.z = RandomValue(-pertubDir, pertubDir);
1839
1840                dirs[i] = ray.mDirection + pertub;
1841                dirs[i] *= 1.0f / Magnitude(dirs[i]);
1842        }
1843
1844        Cast4Rays(dist, dirs, origs, vssRays, box);
1845}
1846
1847
1848void GvsPreprocessor::CastRays4(const SimpleRayContainer &rays, VssRayContainer &vssRays)
1849{
1850        SimpleRayContainer::const_iterator it, it_end = rays.end();
1851       
1852        static float dist[4];
1853        static Vector3 dirs[4];
1854        static Vector3 origs[4];
1855
1856        AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
1857
1858        for (it = rays.begin(); it != it_end; ++ it)
1859        {
1860                for (int i = 1; i < 4; ++ i)
1861                {
1862                        origs[i] = rays[i].mOrigin;
1863                        dirs[i] = rays[i].mDirection;
1864                }
1865        }
1866
1867        Cast4Rays(dist, dirs, origs, vssRays, box);
1868}
1869
1870
1871void GvsPreprocessor::Cast4Rays(float *dist,
1872                                                                Vector3 *dirs,
1873                                                                Vector3 *origs,
1874                                                                VssRayContainer &vssRays,
1875                                                                const AxisAlignedBox3 &box)
1876{
1877        static int hit_triangles[4];
1878
1879        mRayCaster->CastRaysPacket4(box.Min(), box.Max(), origs, dirs, hit_triangles,   dist);       
1880
1881        VssRay *ray;
1882
1883        for (int i = 0; i < 4; ++ i)
1884        {
1885                if (hit_triangles[i] != -1)
1886                {
1887                        TriangleIntersectable *triObj = static_cast<TriangleIntersectable *>(mObjects[hit_triangles[i]]);
1888
1889                        if (DotProd(triObj->GetItem().GetNormal(), dirs[i] >= 0))
1890                                ray = NULL;
1891                        else
1892                                ray = mRayCaster->RequestRay(origs[i], origs[i] + dirs[i] * dist[i], NULL, triObj, mPass, 1.0f);
1893                }
1894                else
1895                {
1896                        ray = NULL;
1897                }
1898
1899                vssRays.push_back(ray);
1900        }
1901}
1902
1903
1904void GvsPreprocessor::CastRayBundle16(const SimpleRay &ray, VssRayContainer &vssRays, float scale)
1905{
1906        static SimpleRayContainer simpleRays;
1907        simpleRays.clear();
1908
1909        simpleRays.push_back(ray);
1910        GenerateJitteredRays(simpleRays, ray, 15, 0, scale);
1911
1912        CastRays(simpleRays, vssRays, false, false);
1913}
1914
1915
1916void GvsPreprocessor::CastRayBundles16(const SimpleRayContainer &rays, VssRayContainer &vssRays, float scale)
1917{
1918        SimpleRayContainer::const_iterator it, it_end = rays.end();
1919
1920        for (it = rays.begin(); it != it_end; ++ it)
1921                CastRayBundle16(*it, vssRays, scale);
1922}
1923
1924
1925void GvsPreprocessor::ComputeRenderError()
1926{
1927        // compute rendering error     
1928        if (renderer && renderer->mPvsStatFrames)
1929        {
1930                if (!mViewCellsManager->GetViewCellPointsList()->empty())
1931                {
1932                        ViewCellPointsList *vcPoints = mViewCellsManager->GetViewCellPointsList();
1933                        ViewCellPointsList::const_iterator vit = vcPoints->begin(),     vit_end = vcPoints->end();
1934
1935                        SimpleRayContainer viewPoints;
1936
1937                        for (; vit != vit_end; ++ vit)
1938                        {
1939                                ViewCellPoints *vp = *vit;
1940                               
1941                                SimpleRayContainer::const_iterator rit = vp->second.begin(), rit_end = vp->second.end();
1942                       
1943                                for (; rit!=rit_end; ++rit)
1944                                {
1945                                        ViewCell *vc = mViewCellsManager->GetViewCell((*rit).mOrigin);
1946                                        if (vc == mCurrentViewCell)
1947                                                viewPoints.push_back(*rit);
1948                                }
1949                        }
1950
1951                        renderer->mPvsErrorBuffer.clear();
1952
1953                        if (viewPoints.size() != renderer->mPvsErrorBuffer.size())
1954                        {
1955                                renderer->mPvsErrorBuffer.resize(viewPoints.size());
1956                                renderer->ClearErrorBuffer();
1957                        }
1958
1959                        cout << "evaluating list of " << viewPoints.size() << " pts" << endl;
1960                        renderer->EvalPvsStat(viewPoints);
1961                }
1962                else
1963                {
1964                        cout << "evaluating random points" << endl;
1965                        renderer->EvalPvsStat();
1966                }
1967
1968                mStats <<
1969                        "#AvgPvsRenderError\n" <<renderer->mPvsStat.GetAvgError()<<endl<<
1970                        "#AvgPixelError\n" <<renderer->GetAvgPixelError()<<endl<<
1971                        "#MaxPixelError\n" <<renderer->GetMaxPixelError()<<endl<<
1972                        "#MaxPvsRenderError\n" <<renderer->mPvsStat.GetMaxError()<<endl<<
1973                        "#ErrorFreeFrames\n" <<renderer->mPvsStat.GetErrorFreeFrames()<<endl<<
1974                        "#AvgRenderPvs\n" <<renderer->mPvsStat.GetAvgPvs()<<endl;
1975        }
1976}
1977
1978
1979void GvsPreprocessor::GenerateImportanceSamples(const VssRay &ray,
1980                                                                                                const Triangle3 &triangle,
1981                                                                                                int numSamples,
1982                                                                                                SimpleRayContainer &simpleRays)
1983{
1984        const size_t samplesSize = simpleRays.size();
1985
1986        while (simpleRays.size() < (samplesSize + numSamples))
1987        {
1988                SimpleRay sray;
1989                if (GenerateImportanceSample(ray, triangle, sray))
1990                        simpleRays.push_back(sray);
1991        }
1992}
1993
1994
1995bool GvsPreprocessor::GenerateImportanceSample(const VssRay &ray,
1996                                                                                           const Triangle3 &triangle,
1997                                                                                           SimpleRay &sray)
1998{
1999        Vector3 d = ray.GetDir();
2000 
2001        // Compute right handed coordinate system from direction
2002        Vector3 U, V;
2003
2004        Vector3 nd = Normalize(d);
2005        nd.RightHandedBase(U, V);
2006       
2007        Vector3 origin = ray.mOrigin;
2008        Vector3 termination = ray.mTermination;
2009
2010        float rr[2];
2011
2012        rr[0] = RandomValue(0, 1);
2013        rr[1] = RandomValue(0, 1);
2014
2015        Vector2 vr2(rr[0], rr[1]);
2016        const float sigma = triangle.GetBoundingBox().Radius() * mRadiusOfInfluence;
2017        Vector2 gaussvec2;
2018
2019        GaussianOn2D(vr2, sigma, // input
2020                         gaussvec2); // output
2021       
2022        const Vector3 shift = gaussvec2.xx * U + gaussvec2.yy * V;
2023
2024        //cout << "t: " << termination;
2025        termination += shift;
2026        //cout << " new t: " << termination << endl;
2027        Vector3 direction = termination - origin;
2028
2029        const float len = Magnitude(direction);
2030       
2031        if (len < Limits::Small)
2032                return false;
2033 
2034        direction /= len;
2035
2036        // $$ jb the pdf is yet not correct for all sampling methods!
2037        const float pdf = 1.0f;
2038        sray = SimpleRay(origin, direction, SamplingStrategy::GVS, pdf);
2039       
2040        return true;
2041}
2042
2043
2044void GvsPreprocessor::PrepareProbablyVisibleSampling()
2045{
2046        // warning: using mailing!
2047        Intersectable::NewMail();
2048
2049        mProbablyVisibleTriangles.clear();
2050        CollectProbablyVisibleTriangles(mProbablyVisibleTriangles);
2051}
2052
2053
2054void GvsPreprocessor::CollectProbablyVisibleTriangles(ObjectContainer &triangles)
2055{
2056        ObjectPvsIterator pit = mCurrentViewCell->GetPvs().GetIterator();
2057
2058        static ObjectContainer tmpTriangles;
2059
2060        while (pit.HasMoreEntries())
2061        {       
2062                tmpTriangles.clear();
2063
2064                KdIntersectable *kdObj = static_cast<KdIntersectable *>(pit.Next());
2065                mKdTree->CollectObjectsWithDublicates(kdObj->GetItem(), tmpTriangles);
2066
2067                ObjectContainer::const_iterator oit, oit_end = tmpTriangles.end();
2068
2069                for (oit = tmpTriangles.begin(); oit != oit_end; ++ oit)
2070                {
2071                        TriangleIntersectable *triObj = static_cast<TriangleIntersectable *>(*oit);
2072
2073                        // find objects which are not yet accounted for yet contained in kd pvs objects
2074                        if (!triObj->Mailed() && (triObj->mCounter < ACCOUNTED_OBJECT))
2075                        {
2076                                triObj->Mail();
2077                                triangles.push_back(triObj);
2078                        }
2079                }
2080        }
2081}
2082
2083
2084void GvsPreprocessor::CollectProbablyVisibleItems(ProbablyVisibleQueue &vqueue)
2085{
2086        ObjectPvsIterator pit = mCurrentViewCell->GetPvs().GetIterator();
2087        static ObjectContainer tmpTriangles;
2088
2089        while (pit.HasMoreEntries())
2090        {
2091                tmpTriangles.clear();
2092
2093                Intersectable::NewMail();
2094
2095                ProbablyVisibleItem *item = new ProbablyVisibleItem();
2096
2097                KdIntersectable *kdObj = static_cast<KdIntersectable *>(pit.Next());
2098                mKdTree->CollectObjects(kdObj->GetItem(), tmpTriangles);
2099                item->mNode = kdObj->GetItem();
2100
2101                ObjectContainer::const_iterator oit, oit_end = tmpTriangles.end();
2102
2103                for (oit = tmpTriangles.begin(); oit != oit_end; ++ oit)
2104                {
2105                        TriangleIntersectable *triObj = static_cast<TriangleIntersectable *>(*oit);
2106
2107                        // find objects which are not yet accounted for yet contained in kd pvs objects
2108                        if (triObj->mCounter < ACCOUNTED_OBJECT)
2109                        {
2110                                item->mTriangles.push_back(triObj);
2111                        }
2112                }
2113        }
2114}
2115
2116
2117void GvsPreprocessor::CreateRandomizedReverseRays(const VssRay &ray,
2118                                                                                                  const Vector3 &predictedPoint,
2119                                                                                                  SimpleRayContainer &rays,
2120                                                                                                  int number,
2121                                                                                                  const Triangle3 &triangle)
2122{
2123        size_t currentNumber = rays.size();
2124
2125        int tries = 0;
2126
2127        while (((rays.size() - currentNumber) < number) && (tries ++ < 20))
2128        {
2129                SimpleRay simpleRay;
2130                if (CreateRandomizedReverseRay(ray, predictedPoint, simpleRay, triangle))
2131                        rays.push_back(simpleRay);
2132        }
2133
2134        if (rays.size() != 16)
2135                cout << "x";
2136        //else cout <<"y";
2137        //cout << "generated " << rays.size() << " rays" << endl;
2138}
2139
2140
2141bool GvsPreprocessor::CreateRandomizedReverseRay(const VssRay &ray,
2142                                                                                                 const Vector3 &predictedPoint,
2143                                                                                                 SimpleRay &simpleRay,
2144                                                                                                 const Triangle3 &triangle)
2145{
2146        /*Vector3 nd = ray.GetNormalizedDir();
2147        const AxisAlignedBox3 box = mCurrentViewCell->GetBox();
2148        //Vector3 nd = box.GetNearestFace(origin).GetNormal();
2149        //cout << "pt: " << origin << " face: " << box.GetNearestFace(origin) << endl;
2150
2151        // Compute right handed coordinate system from direction
2152        Vector3 U, V;
2153        nd.RightHandedBase(U, V);
2154       
2155        float rr[2];
2156
2157        rr[0] = RandomValue(0, 1);
2158        rr[1] = RandomValue(0, 1);
2159
2160        Vector2 vr2(rr[0], rr[1]);
2161        const float sigma = triangle.GetBoundingBox().Radius() * 1.0f;
2162        Vector2 gaussvec2;
2163
2164        GaussianOn2D(vr2, sigma, // input
2165                         gaussvec2); // output
2166        */
2167        const Vector3 shift = 0;//gaussvec2.xx * U + gaussvec2.yy * V;
2168
2169        const Vector3 newTermination = ray.mTermination + shift;
2170       
2171        //cout << "o: " << origin << " new o: " << newOrigin << endl;
2172        Vector3 newOrigin = mCurrentViewCell->GetBox().GetRandomPoint();
2173        Vector3 direction = newTermination - newOrigin;
2174
2175        const float len = Magnitude(direction);
2176       
2177        if (len < Limits::Small)
2178                return false;
2179 
2180        direction /= len;
2181
2182        if (0 && !IntersectsViewCell(newOrigin, -direction))
2183                return false;
2184
2185        //cout << "y";
2186        // $$ jb the pdf is yet not correct for all sampling methods!
2187        const float pdf = 1.0f;
2188        simpleRay = SimpleRay(newOrigin, direction, SamplingStrategy::GVS, pdf);
2189       
2190        return true;
2191}
2192
2193}
Note: See TracBrowser for help on using the repository browser.