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

Revision 2625, 33.3 KB checked in by mattausch, 16 years ago (diff)

added new view cell
deleted other view cell generation stuff (please use generate_viewcells.sh script)
added visualizaton method for gvs

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