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

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