source: GTP/trunk/Lib/Vis/Preprocessing/src/GlRenderer.cpp @ 1972

Revision 1972, 37.8 KB checked in by mattausch, 17 years ago (diff)

implemented improved ray casting

  • Property svn:executable set to *
Line 
1#include "Mesh.h"
2#include "glInterface.h"
3#include "OcclusionQuery.h"
4#include "GlRenderer.h"
5#include "ViewCellsManager.h"
6#include "SceneGraph.h"
7#include "Pvs.h"
8#include "Viewcell.h"
9#include "Beam.h"
10#include "KdTree.h"
11#include "Environment.h"
12#include "Triangle3.h"
13#include "IntersectableWrapper.h"
14#include "BvHierarchy.h"
15#include "KdTree.h"
16
17//#include <Cg/cg.h>
18//#include <Cg/cgGL.h>
19
20
21namespace GtpVisibilityPreprocessor {
22
23
24static bool arbQuerySupport = false;
25static bool nvQuerySupport = false;
26
27static GLuint frontDepthMap;
28static GLuint backDepthMap;
29
30const int depthMapSize = 512;
31
32static void InitExtensions()
33{
34        GLenum err = glewInit();
35
36        if (GLEW_OK != err)
37        {
38                // problem: glewInit failed, something is seriously wrong
39                cerr << "Error: " << glewGetErrorString(err) << endl;
40                exit(1);
41        }
42
43        if (GLEW_ARB_occlusion_query)
44                arbQuerySupport = true;
45       
46        if (GLEW_NV_occlusion_query)
47                nvQuerySupport = true;
48       
49
50        if  (!arbQuerySupport && !nvQuerySupport)
51        {
52                cout << "I require the GL_ARB_occlusion_query or the GL_NV_occlusion_query OpenGL extension to work.\n";
53                exit(1);
54        }
55}
56
57
58GlRenderer::GlRenderer(SceneGraph *sceneGraph,
59                                           ViewCellsManager *viewCellsManager,
60                                           KdTree *tree):
61  Renderer(sceneGraph, viewCellsManager),
62  mKdTree(tree)
63{
64  mSceneGraph->CollectObjects(&mObjects);
65
66  //  mViewCellsManager->GetViewPoint(mViewPoint);
67
68  viewCellsManager->GetViewPoint(mViewPoint);
69        //mSceneGraph->GetBox().Center();
70  mViewDirection = Vector3(0,0,1);
71
72  //  mViewPoint = Vector3(991.7, 187.8, -271);
73  //  mViewDirection = Vector3(0.9, 0, -0.4);
74
75  //  timerId = startTimer(10);
76  // debug coords for atlanta
77  //  mViewPoint = Vector3(3473, 6.778, -1699);
78  //  mViewDirection = Vector3(-0.2432, 0, 0.97);
79 
80  mFrame = 0;
81  mWireFrame = false;
82  Environment::GetSingleton()->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace);
83  mSnapErrorFrames = true;
84  mSnapPrefix = "snap/";
85  mUseForcedColors = false;
86  mRenderBoxes = false;
87  mUseGlLists = true;
88  //mUseGlLists = false;
89
90  Environment::GetSingleton()->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames);
91  mPvsErrorBuffer.resize(mPvsStatFrames);
92  ClearErrorBuffer();
93 
94}
95
96GlRenderer::~GlRenderer()
97{
98  cerr<<"gl renderer destructor..\n";
99 
100  //CLEAR_CONTAINER(sQueries);
101  CLEAR_CONTAINER(mOcclusionQueries);
102
103  cerr<<"done."<<endl;
104}
105
106
107void
108GlRenderer::RenderTriangle(TriangleIntersectable *object)
109{
110  Triangle3 &t = object->GetItem();
111 
112  glBegin(GL_TRIANGLES);
113  glVertex3f(t.mVertices[0].x, t.mVertices[0].y, t.mVertices[0].z);
114  glVertex3f(t.mVertices[1].x, t.mVertices[1].y, t.mVertices[1].z);
115  glVertex3f(t.mVertices[2].x, t.mVertices[2].y, t.mVertices[2].z);
116  glEnd();
117}
118
119void
120GlRenderer::RenderIntersectable(Intersectable *object)
121{
122  if (object->Mailed())
123        return;
124  object->Mail();
125 
126  glPushAttrib(GL_CURRENT_BIT);
127  if (mUseFalseColors)
128        SetupFalseColor(object->mId);
129 
130  switch (object->Type()) {
131  case Intersectable::MESH_INSTANCE:
132        RenderMeshInstance((MeshInstance *)object);
133        break;
134  case Intersectable::VIEW_CELL:
135        RenderViewCell(dynamic_cast<ViewCell *>(object));
136        break;
137  case Intersectable::TRANSFORMED_MESH_INSTANCE:
138        RenderTransformedMeshInstance(dynamic_cast<TransformedMeshInstance *>(object));
139        break;
140  case Intersectable::TRIANGLE_INTERSECTABLE:
141        RenderTriangle(dynamic_cast<TriangleIntersectable *>(object));
142        break;
143  case Intersectable::BVH_INTERSECTABLE: {
144
145        BvhNode *node = dynamic_cast<BvhNode *>(object);
146       
147        if (mRenderBoxes)
148          RenderBox(node->GetBoundingBox());
149        else
150          RenderBvhNode(node);
151        break;
152  }
153  case Intersectable::KD_INTERSECTABLE: {
154        KdNode *node = (dynamic_cast<KdIntersectable *>(object))->GetItem();
155       
156        if (mRenderBoxes)
157          RenderBox(mKdTree->GetBox(node));
158        else
159          RenderKdNode(node);
160        break;
161  }
162       
163  default:
164        cerr<<"Rendering this object not yet implemented\n";
165        break;
166  }
167
168  glPopAttrib();
169}
170
171void
172GlRenderer::RenderRays(const VssRayContainer &rays)
173{
174  VssRayContainer::const_iterator it = rays.begin(), it_end = rays.end();
175
176  glBegin(GL_LINES);
177  for (; it != it_end; ++it) {
178        VssRay *ray = *it;
179        float importance = log10(1e3*ray->mWeightedPvsContribution)/3.0f;
180        //      cout<<"w="<<ray->mWeightedPvsContribution<<" r="<<ray->mWeightedPvsContribution;
181        glColor3f(importance, importance, importance);
182        glVertex3fv(&ray->mOrigin.x);
183        glVertex3fv(&ray->mTermination.x);
184  }
185  glEnd();
186}
187
188
189
190void
191GlRenderer::RenderViewCell(ViewCell *vc)
192{
193  if (vc->GetMesh()) {
194
195        if (!mUseFalseColors) {
196          if (vc->GetValid())
197                glColor3f(0,1,0);
198          else
199                glColor3f(0,0,1);
200        }
201       
202        RenderMesh(vc->GetMesh());
203  } else {
204        // render viewcells in the subtree
205        if (!vc->IsLeaf()) {
206          ViewCellInterior *vci = (ViewCellInterior *) vc;
207
208          ViewCellContainer::iterator it = vci->mChildren.begin();
209          for (; it != vci->mChildren.end(); ++it) {
210                RenderViewCell(*it);
211          }
212        } else {
213          //      cerr<<"Empty viewcell mesh\n";
214        }
215  }
216}
217
218
219void
220GlRenderer::RenderMeshInstance(MeshInstance *mi)
221{
222  RenderMesh(mi->GetMesh());
223}
224
225
226void
227GlRenderer::RenderTransformedMeshInstance(TransformedMeshInstance *mi)
228{
229        // apply world transform before rendering
230        Matrix4x4 m;
231        mi->GetWorldTransform(m);
232
233        glPushMatrix();
234/* cout << "\n";
235        for (int i = 0; i < 4; ++ i)
236                for (int j = 0; j < 4; ++ j)
237                        cout << m.x[i][j] << " "; cout << "\n"*/
238
239        glMultMatrixf((float *)m.x);
240
241        /*GLfloat dummy[16];
242        glGetFloatv(GL_MODELVIEW_MATRIX, dummy);
243        for (int i = 0; i < 16; ++ i)
244                cout << dummy[i] << " ";
245        cout << endl;*/
246        RenderMesh(mi->GetMesh());
247       
248        glPopMatrix();
249}
250
251
252void
253GlRenderer::SetupFalseColor(const unsigned int id)
254{
255        // swap bits of the color
256        glColor3ub(id&255, (id>>8)&255, (id>>16)&255);
257}
258
259
260unsigned int GlRenderer::GetId(const unsigned char r,
261                                                           const unsigned char g,
262                                                           const unsigned char b) const
263{
264        return r + (g << 8) + (b << 16);
265}
266
267
268void
269GlRenderer::SetupMaterial(Material *m)
270{
271  if (m)
272        glColor3fv(&(m->mDiffuseColor.r));
273}
274
275
276void
277GlRenderer::RenderMesh(Mesh *mesh)
278{
279  int i = 0;
280
281  if (!mUseFalseColors && !mUseForcedColors)
282          SetupMaterial(mesh->mMaterial);
283 
284  for (i=0; i < mesh->mFaces.size(); i++) {
285        if (mWireFrame)
286          glBegin(GL_LINE_LOOP);
287        else
288          glBegin(GL_POLYGON);
289
290        Face *face = mesh->mFaces[i];
291        for (int j = 0; j < face->mVertexIndices.size(); j++) {
292          glVertex3fv(&mesh->mVertices[face->mVertexIndices[j]].x);
293        }
294        glEnd();
295  }
296}
297       
298void
299GlRenderer::InitGL()
300{
301  mSphere = (GLUquadric *)gluNewQuadric();
302 
303  glMatrixMode(GL_PROJECTION);
304  glLoadIdentity();
305 
306  glMatrixMode(GL_MODELVIEW);
307  glLoadIdentity();
308
309  glFrontFace(GL_CCW);
310  glCullFace(GL_BACK);
311  glEnable(GL_CULL_FACE);
312  glShadeModel(GL_FLAT);
313  glEnable(GL_DEPTH_TEST);
314  glEnable(GL_CULL_FACE);
315 
316  InitExtensions();
317 
318#if 0
319  GLfloat mat_ambient[]   = {  0.5, 0.5, 0.5, 1.0  };
320  /*  mat_specular and mat_shininess are NOT default values     */
321  GLfloat mat_diffuse[]   = {  1.0, 1.0, 1.0, 1.0  };
322  GLfloat mat_specular[]  = {  0.3, 0.3, 0.3, 1.0  };
323  GLfloat mat_shininess[] = {  1.0  };
324 
325  GLfloat light_ambient[]  = {  0.2, 0.2, 0.2, 1.0  };
326  GLfloat light_diffuse[]  = {  0.4, 0.4, 0.4, 1.0  };
327  GLfloat light_specular[] = {  0.3, 0.3, 0.3, 1.0  };
328 
329  GLfloat lmodel_ambient[] = {  0.3, 0.3, 0.3, 1.0  };
330 
331 
332  // default Material
333  glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
334  glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
335  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
336  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
337
338  // a light
339  glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
340  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
341  glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
342 
343  glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
344  glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
345  glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
346 
347  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
348 
349  glEnable(GL_LIGHTING);
350  glEnable(GL_LIGHT0);
351  glEnable(GL_LIGHT1);
352 
353 
354  // set position of the light
355  GLfloat infinite_light[] = {  1.0, 0.8, 1.0, 0.0  };
356  glLightfv (GL_LIGHT0, GL_POSITION, infinite_light);
357 
358  // set position of the light2
359  GLfloat infinite_light2[] = {  -0.3, 1.5, 1.0, 0.0  };
360  glLightfv (GL_LIGHT1, GL_POSITION, infinite_light2);
361 
362  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
363  //   glColorMaterial( GL_FRONT_AND_BACK, GL_SPECULAR);
364  glEnable(GL_COLOR_MATERIAL);
365 
366  glShadeModel( GL_FLAT );
367 
368  glDepthFunc( GL_LESS );
369  glEnable( GL_DEPTH_TEST );
370#endif
371
372  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
373
374  glEnable( GL_NORMALIZE );
375 
376  glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
377}
378
379
380void
381GlRenderer::SetupProjection(const int w, const int h, const float angle)
382{
383  glViewport(0, 0, w, h);
384  glMatrixMode(GL_PROJECTION);
385  glLoadIdentity();
386  gluPerspective(angle, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
387  glMatrixMode(GL_MODELVIEW);
388}
389
390
391
392void
393GlRenderer::SetupCamera()
394{
395  Vector3 target = mViewPoint + mViewDirection;
396
397  Vector3 up(0,1,0);
398 
399  if (abs(DotProd(mViewDirection, up)) > 0.99f)
400        up = Vector3(1, 0, 0);
401 
402  glLoadIdentity();
403  gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z,
404                        target.x, target.y, target.z,
405                        up.x, up.y, up.z);
406}
407
408void
409GlRenderer::_RenderScene()
410{
411  ObjectContainer::const_iterator oi = mObjects.begin();
412
413  for (; oi != mObjects.end(); oi++)
414        RenderIntersectable(*oi);
415}
416
417bool
418GlRenderer::RenderScene()
419{
420  Intersectable::NewMail();
421  static int glList = -1;
422  if (mUseGlLists) {
423        if (glList == -1) {
424          glList = glGenLists(1);
425          glNewList(glList, GL_COMPILE);
426          _RenderScene();
427          glEndList();
428        }
429       
430        glCallList(glList);
431  } else
432        _RenderScene();
433       
434 
435  return true;
436}
437
438
439void
440GlRendererBuffer::EvalQueryWithItemBuffer(
441                                                                                  //RenderCostSample &sample
442                                                                           )
443{
444        // read back the texture
445        glReadPixels(0, 0,
446                                GetWidth(), GetHeight(),
447                                GL_RGBA,
448                                GL_UNSIGNED_BYTE,
449                                mPixelBuffer);
450               
451                       
452        unsigned int *p = mPixelBuffer;
453                       
454        for (int y = 0; y < GetHeight(); y++)
455        {
456                for (int x = 0; x < GetWidth(); x++, p++)
457                {
458                        unsigned int id = (*p) & 0xFFFFFF;
459
460                        if (id != 0xFFFFFF)
461                                ++ mObjects[id]->mCounter;
462                }
463        }
464}
465
466
467
468/****************************************************************/
469/*               GlRendererBuffer implementation                */
470/****************************************************************/
471
472
473
474GlRendererBuffer::GlRendererBuffer(SceneGraph *sceneGraph,
475                                                                   ViewCellsManager *viewcells,
476                                                                   KdTree *tree):
477GlRenderer(sceneGraph, viewcells, tree) 
478{
479 
480  mPixelBuffer = NULL;
481 
482  // implement width and height in subclasses
483}
484
485
486void
487GlRendererBuffer::EvalQueryWithOcclusionQueries(
488                                                                           //RenderCostSample &sample
489                                                                           )
490{
491        glDepthFunc(GL_LEQUAL);
492               
493        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
494        glDepthMask(GL_FALSE);
495
496
497        // simulate detectemptyviewspace using backface culling
498        if (mDetectEmptyViewSpace)
499        {
500                glEnable(GL_CULL_FACE);
501                //cout << "culling" << endl;
502        }
503        else
504        {
505                //cout << "not culling" << endl;
506                glDisable(GL_CULL_FACE);
507        }
508
509       
510        //const int numQ = 1;
511        const int numQ = (int)mOcclusionQueries.size();
512       
513        //glFinish();
514#if 0
515        //-- now issue queries for all objects
516        for (int j = 0; j < (int)mObjects.size(); ++ j)
517        {
518                mOcclusionQueries[j]->BeginQuery();
519                RenderIntersectable(mObjects[j]);
520                mOcclusionQueries[j]->EndQuery();
521
522                unsigned int pixelCount;
523
524                pixelCount = mOcclusionQueries[j]->GetQueryResult();
525                mObjects[j]->mCounter += pixelCount;
526        }
527#else
528
529        int q = 0;
530
531        //-- now issue queries for all objects
532        for (int j = 0; j < (int)mObjects.size(); j += q)
533        {       
534                for (q = 0; ((j + q) < (int)mObjects.size()) && (q < numQ); ++ q)
535                {
536                        //glFinish();
537                        mOcclusionQueries[q]->BeginQuery();
538                       
539                        RenderIntersectable(mObjects[j + q]);
540               
541                        mOcclusionQueries[q]->EndQuery();
542                        //glFinish();
543                }
544                //cout << "q: " << q << endl;
545                // collect results of the queries
546                for (int t = 0; t < q; ++ t)
547                {
548                        unsigned int pixelCount;
549               
550                        //-- reenable other state
551#if 0
552                        bool available;
553
554                        do
555                        {
556                                available = mOcclusionQueries[t]->ResultAvailable();
557                               
558                                if (!available) cout << "W";
559                        }
560                        while (!available);
561#endif
562
563                        pixelCount = mOcclusionQueries[t]->GetQueryResult();
564
565                        //if (pixelCount > 0)
566                        //      cout <<"o="<<j+q<<" q="<<mOcclusionQueries[q]->GetQueryId()<<" pc="<<pixelCount<<" ";
567                        mObjects[j + t]->mCounter += pixelCount;
568                }
569
570                //j += q;
571        }
572#endif
573        //glFinish();
574        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
575        glDepthMask(GL_TRUE);
576       
577        glEnable(GL_CULL_FACE);
578}
579
580
581void
582GlRenderer::RandomViewPoint()
583{
584  // do not use this function since it could return different viewpoints for
585  // different executions of the algorithm
586
587  //  mViewCellsManager->GetViewPoint(mViewPoint);
588
589  while (1) {
590        Vector3 pVector = Vector3(halton.GetNumber(1),
591                                                          halton.GetNumber(2),
592                                                          halton.GetNumber(3));
593       
594        mViewPoint =  mViewCellsManager->GetViewSpaceBox().GetPoint(pVector);
595        ViewCell *v = mViewCellsManager->GetViewCell(mViewPoint);
596        if (v && v->GetValid())
597          break;
598        // generate a new vector
599        halton.GenerateNext();
600  }
601 
602  Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4),
603                                                        M_PI*halton.GetNumber(5),
604                                                        0.0f);
605 
606  mViewDirection = Normalize(Vector3(sin(dVector.x),
607                                                                         //                                                                      cos(dVector.y),
608                                                                         0.0f,
609                                                                         cos(dVector.x)));
610  halton.GenerateNext();
611}
612
613
614void
615GlRenderer::RenderBox(const AxisAlignedBox3 &box)
616{
617
618  glBegin(GL_LINE_LOOP);
619  glVertex3d(box.Min().x, box.Max().y, box.Min().z );
620  glVertex3d(box.Max().x, box.Max().y, box.Min().z );
621  glVertex3d(box.Max().x, box.Min().y, box.Min().z );
622  glVertex3d(box.Min().x, box.Min().y, box.Min().z );
623  glEnd();
624
625  glBegin(GL_LINE_LOOP);
626  glVertex3d(box.Min().x, box.Min().y, box.Max().z );
627  glVertex3d(box.Max().x, box.Min().y, box.Max().z );
628  glVertex3d(box.Max().x, box.Max().y, box.Max().z );
629  glVertex3d(box.Min().x, box.Max().y, box.Max().z );
630  glEnd();
631
632  glBegin(GL_LINE_LOOP);
633  glVertex3d(box.Max().x, box.Min().y, box.Min().z );
634  glVertex3d(box.Max().x, box.Min().y, box.Max().z );
635  glVertex3d(box.Max().x, box.Max().y, box.Max().z );
636  glVertex3d(box.Max().x, box.Max().y, box.Min().z );
637  glEnd();
638
639  glBegin(GL_LINE_LOOP);
640  glVertex3d(box.Min().x, box.Min().y, box.Min().z );
641  glVertex3d(box.Min().x, box.Min().y, box.Max().z );
642  glVertex3d(box.Min().x, box.Max().y, box.Max().z );
643  glVertex3d(box.Min().x, box.Max().y, box.Min().z );
644  glEnd();
645
646  glBegin(GL_LINE_LOOP);
647  glVertex3d(box.Min().x, box.Min().y, box.Min().z );
648  glVertex3d(box.Max().x, box.Min().y, box.Min().z );
649  glVertex3d(box.Max().x, box.Min().y, box.Max().z );
650  glVertex3d(box.Min().x, box.Min().y, box.Max().z );
651  glEnd();
652
653  glBegin(GL_LINE_LOOP);
654  glVertex3d(box.Min().x, box.Max().y, box.Min().z );
655  glVertex3d(box.Max().x, box.Max().y, box.Min().z );
656  glVertex3d(box.Max().x, box.Max().y, box.Max().z );
657  glVertex3d(box.Min().x, box.Max().y, box.Max().z );
658
659  glEnd();
660
661}
662
663void
664GlRenderer::RenderBvhNode(BvhNode *node)
665{
666  if (node->IsLeaf()) {
667        BvhLeaf *leaf = (BvhLeaf *) node;
668
669#if 0
670        if (leaf->mGlList == 0) {
671          leaf->mGlList = glGenLists(1);
672          if (leaf->mGlList != 0)
673                glNewList(leaf->mGlList, GL_COMPILE);
674         
675          for (int i=0; i < leaf->mObjects.size(); i++)
676                RenderIntersectable(leaf->mObjects[i]);
677         
678          if (leaf->mGlList != 0)
679                glEndList();
680        }
681       
682        if (leaf->mGlList != 0)
683          glCallList(leaf->mGlList);
684#else
685          for (int i=0; i < leaf->mObjects.size(); i++)
686                RenderIntersectable(leaf->mObjects[i]);
687#endif
688  } else {
689        BvhInterior *in = (BvhInterior *)node;
690        RenderBvhNode(in->GetBack());
691        RenderBvhNode(in->GetFront());
692  }
693
694  //cout << "leaf obj " << i << endl;
695
696}
697
698void
699GlRenderer::RenderKdNode(KdNode *node)
700{
701  if (node->IsLeaf()) {
702        KdLeaf *leaf = (KdLeaf *) node;
703        for (int i=0; i < leaf->mObjects.size(); i++) {
704          RenderIntersectable(leaf->mObjects[i]);
705        }
706  } else {
707        KdInterior *in = (KdInterior *)node;
708        RenderKdNode(in->mBack);
709        RenderKdNode(in->mFront);
710  }
711 
712}
713
714
715
716
717
718
719
720void
721GlRendererBuffer::EvalRenderCostSample(RenderCostSample &sample,
722                                                                           const bool useOcclusionQueries,
723                                                                           const int threshold
724                                                                           )
725{
726  // choose a random view point
727  mViewCellsManager->GetViewPoint(mViewPoint);
728  sample.mPosition = mViewPoint;
729  //cout << "viewpoint: " << mViewPoint << endl;
730 
731  // take a render cost sample by rendering a cube
732  Vector3 directions[6];
733 
734  directions[0] = Vector3(1,0,0);
735  directions[1] = Vector3(0,1,0);
736  directions[2] = Vector3(0,0,1);
737  directions[3] = Vector3(-1,0,0);
738  directions[4] = Vector3(0,-1,0);
739  directions[5] = Vector3(0,0,-1);
740 
741  sample.mVisibleObjects = 0;
742 
743  // reset object counters
744  ObjectContainer::const_iterator it, it_end = mObjects.end();
745 
746  for (it = mObjects.begin(); it != it_end; ++ it)
747        {
748          (*it)->mCounter = 0;
749        }
750
751  ++ mFrame;
752 
753  //glCullFace(GL_FRONT);
754  glCullFace(GL_BACK);
755  glDisable(GL_CULL_FACE);
756 
757 
758        // query all 6 directions for a full point sample
759  for (int i = 0; i < 6; ++ i)
760        {
761          mViewDirection = directions[i];
762          SetupCamera();
763         
764          glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
765          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
766          //glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);    glDepthMask(GL_TRUE);
767          glDepthFunc(GL_LESS);
768         
769          mUseFalseColors = true;
770         
771          // the actual scene rendering fills the depth (for occlusion queries)
772          // and the frame buffer (for item buffer)
773          RenderScene();
774         
775         
776          if (0)
777                {
778                  char filename[256];
779                  sprintf(filename, "snap/frame-%04d-%d.png", mFrame, i);
780                  //              QImage im = toImage();
781                  //              im.save(filename, "PNG");
782                }
783         
784          // evaluate the sample
785          if (useOcclusionQueries)
786                {
787                  EvalQueryWithOcclusionQueries();
788                }
789          else
790                {
791                  EvalQueryWithItemBuffer();
792                }
793        } 
794 
795  // now evaluate the statistics over that sample
796  // currently only the number of visible objects is taken into account
797  sample.Reset();
798 
799  for (it = mObjects.begin(); it != it_end; ++ it)
800        {
801          Intersectable *obj = *it;
802          if (obj->mCounter >= threshold)
803                {
804                  ++ sample.mVisibleObjects;
805                  sample.mVisiblePixels += obj->mCounter;
806                }
807        }
808 
809  //cout << "RS=" << sample.mVisibleObjects << " ";
810}
811
812
813GlRendererBuffer::~GlRendererBuffer()
814{
815#if USE_CG
816  if (sCgFragmentProgram)
817                cgDestroyProgram(sCgFragmentProgram);
818        if (sCgContext)
819                cgDestroyContext(sCgContext);
820#endif
821}
822
823
824void
825GlRendererBuffer::SampleRenderCost(const int numSamples,
826                                                                   vector<RenderCostSample> &samples,
827                                                                   const bool useOcclusionQueries,
828                                                                   const int threshold
829                                                                   )
830{
831  MakeCurrent();
832
833  if (mPixelBuffer == NULL)
834          mPixelBuffer = new unsigned int[GetWidth()*GetHeight()];
835 
836  // using 90 degree projection to capture 360 view with 6 samples
837  SetupProjection(GetHeight(), GetHeight(), 90.0f);
838
839  //samples.resize(numSamples);
840  halton.Reset();
841 
842  // the number of queries queried in batch mode
843  const int numQ = 500;
844
845  //const int numQ = (int)mObjects.size();
846  if (useOcclusionQueries)
847  {
848          cout << "\ngenerating " << numQ << " queries ... ";
849          OcclusionQuery::GenQueries(mOcclusionQueries, numQ);
850          cout << "finished" << endl;
851  }
852
853  // sampling queries
854  for (int i = 0; i < numSamples; ++ i)
855  {
856          cout << ".";
857          EvalRenderCostSample(samples[i], useOcclusionQueries, threshold);
858  }
859
860  DoneCurrent();
861}
862 
863
864
865
866
867void
868GlRenderer::ClearErrorBuffer()
869{
870  for (int i=0; i < mPvsStatFrames; i++) {
871        mPvsErrorBuffer[i].mError = 1.0f;
872  }
873}
874
875
876void
877GlRendererBuffer::EvalPvsStat()
878{
879
880  MakeCurrent();
881
882  GlRenderer::EvalPvsStat();
883 
884  DoneCurrent();
885 
886  //  mRenderingFinished.wakeAll();
887}
888
889
890void GlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject,
891                                                                                           Beam &beam,
892                                                                                           const int desiredSamples,
893                                                                                           BeamSampleStatistics &stat)
894{
895        // TODO: should be moved out of here (not to be done every time)
896        // only back faces are interesting for the depth pass
897        glShadeModel(GL_FLAT);
898        glDisable(GL_LIGHTING);
899
900        // needed to kill the fragments for the front buffer
901        glEnable(GL_ALPHA_TEST);
902        glAlphaFunc(GL_GREATER, 0);
903
904        // assumes that the beam is constructed and contains kd-tree nodes
905        // and viewcells which it intersects
906 
907 
908        // Get the number of viewpoints to be sampled
909        // Now it is a sqrt but in general a wiser decision could be made.
910        // The less viewpoints the better for rendering performance, since less passes
911        // over the beam is needed.
912        // The viewpoints could actually be generated outside of the bounding box which
913        // would distribute the 'efective viewpoints' of the object surface and thus
914        // with a few viewpoints better sample the viewpoint space....
915
916        //TODO: comment in
917        //int viewPointSamples = sqrt((float)desiredSamples);
918        int viewPointSamples = max(desiredSamples / (GetWidth() * GetHeight()), 1);
919       
920        // the number of direction samples per pass is given by the number of viewpoints
921        int directionalSamples = desiredSamples / viewPointSamples;
922       
923        Debug << "directional samples: " << directionalSamples << endl;
924        for (int i = 0; i < viewPointSamples; ++ i)
925        {
926                Vector3 viewPoint = beam.mBox.GetRandomPoint();
927               
928                // perhaps the viewpoint should be shifted back a little bit so that it always lies
929                // inside the source object
930                // 'ideally' the viewpoints would be distributed on the soureObject surface, but this
931        // would require more complicated sampling (perhaps hierarchical rejection sampling of
932                // the object surface is an option here - only the mesh faces which are inside the box
933                // are considered as candidates)
934               
935                SampleViewpointContributions(sourceObject,
936                                                                         viewPoint,
937                                                                         beam,
938                                                                         directionalSamples,
939                                                                         stat);
940        }
941
942
943        // note:
944        // this routine would be called only if the number of desired samples is sufficiently
945        // large - for other rss tree cells the cpu based sampling is perhaps more efficient
946        // distributing the work between cpu and gpu would also allow us to place more sophisticated
947        // sample distributions (silhouette ones) using the cpu and the jittered once on the GPU
948        // in order that thios scheme is working well the gpu render buffer should run in a separate
949        // thread than the cpu sampler, which would not be such a big problem....
950
951        // disable alpha test again
952        glDisable(GL_ALPHA_TEST);
953}
954
955
956
957void GlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject,
958                                                                                                        const Vector3 viewPoint,
959                                                                                                        Beam &beam,
960                                                                                                        const int samples,
961                                                    BeamSampleStatistics &stat)
962{
963    // 1. setup the view port to match the desired samples
964        glViewport(0, 0, samples, samples);
965
966        // 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox
967        SetupProjectionForViewPoint(viewPoint, beam, sourceObject);
968
969
970        // 3. reset z-buffer to 0 and render the source object for the beam
971        //    with glCullFace(Enabled) and glFrontFace(GL_CW)
972        //    save result to the front depth map
973        //    the front depth map holds ray origins
974
975
976        // front depth buffer must be initialised to 0
977        float clearDepth;
978       
979        glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
980        glClearDepth(0.0f);
981        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
982
983
984        // glFrontFace(GL_CCW);
985        glEnable(GL_CULL_FACE);
986        glCullFace(GL_FRONT);
987        glColorMask(0, 0, 0, 0);
988       
989
990        // stencil is increased where the source object is located
991        glEnable(GL_STENCIL_TEST);     
992        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
993        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
994
995
996#if 0
997        static int glSourceObjList = -1;         
998        if (glSourceObjList != -1)
999        {
1000                glSourceObjList = glGenLists(1);
1001                glNewList(glSourceObjList, GL_COMPILE);
1002
1003                RenderIntersectable(sourceObject);
1004       
1005                glEndList();
1006        }
1007        glCallList(glSourceObjList);
1008
1009#else
1010        RenderIntersectable(sourceObject);
1011
1012#endif 
1013
1014         // copy contents of the front depth buffer into depth texture
1015        glBindTexture(GL_TEXTURE_2D, frontDepthMap);   
1016        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
1017
1018        // reset clear function
1019        glClearDepth(clearDepth);
1020       
1021       
1022        // 4. set up the termination depth buffer (= standard depth buffer)
1023        //    only rays which have non-zero entry in the origin buffer are valid since
1024        //    they realy start on the object surface (this is tagged by setting a
1025        //    stencil buffer bit at step 3).
1026       
1027        glStencilFunc(GL_EQUAL, 0x1, 0x1);
1028        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1029
1030        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1031        glDepthMask(1);
1032
1033        glEnable(GL_DEPTH_TEST);
1034               
1035        glEnable(GL_CULL_FACE);
1036        glCullFace(GL_BACK);
1037
1038        // setup front depth buffer
1039        glEnable(GL_TEXTURE_2D);
1040       
1041#if USE_CG
1042        // bind pixel shader implementing the front depth buffer functionality
1043        cgGLBindProgram(sCgFragmentProgram);
1044        cgGLEnableProfile(sCgFragmentProfile);
1045#endif
1046
1047        // 5. render all objects inside the beam
1048        //    we can use id based false color to read them back for gaining the pvs
1049
1050        glColorMask(1, 1, 1, 1);
1051
1052       
1053        // if objects not stored in beam => extract objects
1054        if (beam.mFlags & !Beam::STORE_OBJECTS)
1055        {
1056                vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
1057
1058                Intersectable::NewMail();
1059                for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
1060                {
1061                        mKdTree->CollectObjects(*it, beam.mObjects);
1062                }
1063        }
1064
1065
1066        //    (objects can be compiled to a gl list now so that subsequent rendering for
1067        //    this beam is fast - the same hold for step 3)
1068        //    Afterwards we have two depth buffers defining the ray origin and termination
1069       
1070
1071#if 0
1072        static int glObjList = -1;
1073        if (glObjList != -1)
1074        {
1075                glObjList = glGenLists(1);
1076                glNewList(glObjList, GL_COMPILE);
1077       
1078                ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
1079                for (it = beam.mObjects.begin(); it != it_end; ++ it)
1080                {
1081                        // render all objects except the source object
1082                        if (*it != sourceObject)
1083                                RenderIntersectable(*it);
1084                }
1085               
1086                glEndList();
1087        }
1088
1089        glCallList(glObjList);
1090#else
1091        ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
1092        for (it = beam.mObjects.begin(); it != it_end; ++ it)
1093        {       
1094                // render all objects except the source object
1095                if (*it != sourceObject)
1096                        RenderIntersectable(*it);
1097        }
1098#endif
1099       
1100        // 6. Use occlusion queries for all viewcell meshes associated with the beam ->
1101        //     a fragment passes if the corresponding stencil fragment is set and its depth is
1102        //     between origin and termination buffer
1103
1104        // create new queries if necessary
1105        OcclusionQuery::GenQueries(mOcclusionQueries, (int)beam.mViewCells.size());
1106
1107        // check whether any backfacing polygon would pass the depth test?
1108        // matt: should check both back /front facing because of dual depth buffer
1109        // and danger of cutting the near plane with front facing polys.
1110       
1111        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1112        glDepthMask(GL_FALSE);
1113        glDisable(GL_CULL_FACE);
1114
1115 
1116        ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end();
1117
1118        int queryIdx = 0;
1119
1120        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
1121        {
1122                mOcclusionQueries[queryIdx ++]->BeginQuery();
1123
1124                RenderIntersectable(*vit);
1125               
1126                mOcclusionQueries[queryIdx]->EndQuery();
1127
1128                ++ queryIdx;
1129        }
1130
1131        // at this point, if possible, go and do some other computation
1132
1133        // 7. The number of visible pixels is the number of sample rays which see the source
1134        //    object from the corresponding viewcell -> remember these values for later update
1135        //   of the viewcell pvs - or update immediately?
1136
1137        queryIdx = 0;
1138
1139        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
1140        {
1141                // fetch queries
1142                unsigned int pixelCount = mOcclusionQueries[queryIdx ++]->GetQueryResult();
1143
1144                if (pixelCount)
1145                        Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl;
1146        }
1147       
1148
1149        // 8. Copmpute rendering statistics
1150        // In general it is not neccessary to remember to extract all the rays cast. I hope it
1151        // would be sufficient to gain only the intergral statistics about the new contributions
1152        // and so the rss tree would actually store no new rays (only the initial ones)
1153        // the subdivision of the tree would only be driven by the statistics (the glrender could
1154        // evaluate the contribution entropy for example)
1155        // However might be an option to extract/store only those the rays which made a contribution
1156        // (new viewcell has been discovered) or relative contribution greater than a threshold ...
1157
1158        ObjectContainer pvsObj;
1159        stat.pvsSize = ComputePvs(beam.mObjects, pvsObj);
1160       
1161        // to gain ray source and termination
1162        // copy contents of ray termination buffer into depth texture
1163        // and compare with ray source buffer
1164#if 0
1165        VssRayContainer rays;
1166
1167        glBindTexture(GL_TEXTURE_2D, backDepthMap);     
1168        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
1169
1170        ComputeRays(Intersectable *sourceObj, rays);
1171
1172#endif
1173
1174        //-- cleanup
1175
1176        // reset gl state
1177        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1178        glDepthMask(GL_TRUE);
1179        glEnable(GL_CULL_FACE);
1180        glDisable(GL_STENCIL_TEST);
1181
1182#if USE_CG
1183        cgGLDisableProfile(sCgFragmentProfile);
1184#endif
1185        glDisable(GL_TEXTURE_2D);
1186
1187        // remove objects from beam
1188        if (beam.mFlags & !Beam::STORE_OBJECTS)
1189                beam.mObjects.clear();
1190}
1191
1192
1193void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint,
1194                                                                                                   const Beam &beam,
1195                                                                                                   Intersectable *sourceObject)
1196{
1197        float left, right, bottom, top, znear, zfar;
1198
1199        beam.ComputePerspectiveFrustum(left, right, bottom, top, znear, zfar,
1200                                                                   mSceneGraph->GetBox());
1201
1202        //Debug << left << " " << right << " " << bottom << " " << top << " " << znear << " " << zfar << endl;
1203        glMatrixMode(GL_PROJECTION);
1204        glLoadIdentity();
1205        glFrustum(left, right, bottom, top, znear, zfar);
1206        //glFrustum(-1, 1, -1, 1, 1, 20000);
1207
1208    const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3f;
1209        const Vector3 up =
1210                Normalize(CrossProd(beam.mPlanes[0].mNormal, beam.mPlanes[4].mNormal));
1211
1212#ifdef GTP_DEBUG
1213        Debug << "view point: " << viewPoint << endl;
1214        Debug << "eye: " << center << endl;
1215        Debug << "up: " << up << endl;
1216#endif
1217
1218        glMatrixMode(GL_MODELVIEW);
1219        glLoadIdentity();
1220        gluLookAt(viewPoint.x, viewPoint.y, viewPoint.z,
1221                          center.x, center.y, center.z,                   
1222                          up.x, up.y, up.z);
1223}               
1224
1225 
1226void GlRendererBuffer::InitGL()
1227{
1228  MakeCurrent();
1229  GlRenderer::InitGL();
1230
1231#if 1
1232        // initialise dual depth buffer textures
1233        glGenTextures(1, &frontDepthMap);
1234        glBindTexture(GL_TEXTURE_2D, frontDepthMap);
1235       
1236        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
1237                                 depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
1238
1239        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1240        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1241        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1242        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1243
1244        glGenTextures(1, &backDepthMap);
1245        glBindTexture(GL_TEXTURE_2D, backDepthMap);
1246       
1247        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
1248                                 depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
1249        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1250        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1251        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1252        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1253
1254       
1255#if USE_CG
1256        // cg initialization
1257        cgSetErrorCallback(handleCgError);
1258        sCgContext = cgCreateContext();
1259       
1260        if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
1261                sCgFragmentProfile = CG_PROFILE_ARBFP1;
1262        else
1263        {
1264          // try FP30
1265          if (cgGLIsProfileSupported(CG_PROFILE_FP30))
1266            sCgFragmentProfile = CG_PROFILE_FP30;
1267          else
1268          {
1269                  Debug << "Neither arbfp1 or fp30 fragment profiles supported on this system" << endl;
1270                  exit(1);
1271          }
1272  }
1273
1274 sCgFragmentProgram = cgCreateProgramFromFile(sCgContext,
1275                                                                                           CG_SOURCE, "../src/dual_depth.cg",
1276                                                                                           sCgFragmentProfile,
1277                                                                                           NULL,
1278                                                                                           NULL);
1279
1280  if (!cgIsProgramCompiled(sCgFragmentProgram))
1281          cgCompileProgram(sCgFragmentProgram);
1282
1283  cgGLLoadProgram(sCgFragmentProgram);
1284  cgGLBindProgram(sCgFragmentProgram);
1285
1286  Debug << "---- PROGRAM BEGIN ----\n" <<
1287          cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
1288
1289#endif
1290
1291#endif
1292  DoneCurrent();
1293}
1294
1295
1296void GlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays)
1297{
1298        for (int i = 0; i < depthMapSize * depthMapSize; ++ i)
1299        {
1300                //todo glGetTexImage()
1301        }
1302}
1303
1304
1305void
1306GlRenderer::EvalPvsStat()
1307{
1308
1309  mPvsStat.Reset();
1310  halton.Reset();
1311
1312
1313  SetupProjection(GetWidth(), GetHeight());
1314
1315  cout<<"mPvsStatFrames="<<mPvsStatFrames<<endl;
1316 
1317  for (int i=0; i < mPvsStatFrames; i++) {
1318        float err;
1319        // set frame id for saving the error buffer
1320        mFrame = i;
1321        RandomViewPoint();
1322
1323        // atlanta problematic frames: 325 525 691 1543
1324#if 0
1325        if (mFrame != 325 &&
1326                mFrame != 525 &&
1327                mFrame != 691 &&
1328                mFrame != 1543)
1329          mPvsErrorBuffer[i] = -1;
1330        else {
1331          Debug<<"frame ="<<mFrame<<" vp="<<mViewPoint<<" vd="<<mViewDirection<<endl;
1332        }
1333#endif
1334       
1335        if (mPvsErrorBuffer[i].mError > 0.0f) {
1336          int pvsSize;
1337
1338
1339          float error = GetPixelError(pvsSize);
1340          mPvsErrorBuffer[i].mError = error;
1341          mPvsErrorBuffer[i].mPvsSize = pvsSize;
1342
1343          //      emit UpdatePvsErrorItem(i,
1344          //                                                      mPvsErrorBuffer[i]);
1345
1346          cout<<"("<<i<<","<<mPvsErrorBuffer[i].mError<<")";
1347          //      swapBuffers();
1348        }
1349       
1350        err = mPvsErrorBuffer[i].mError;
1351       
1352        if (err >= 0.0f) {
1353          if (err > mPvsStat.maxError)
1354                mPvsStat.maxError = err;
1355          mPvsStat.sumError += err;
1356          mPvsStat.sumPvsSize += mPvsErrorBuffer[i].mPvsSize;
1357         
1358          if (err == 0.0f)
1359                mPvsStat.errorFreeFrames++;
1360          mPvsStat.frames++;
1361        }
1362  }
1363
1364  glFinish();
1365  cout<<endl<<flush;
1366
1367}
1368
1369
1370float
1371GlRenderer::GetPixelError(int &pvsSize)
1372{
1373  float pErrorPixels = -1.0f;
1374 
1375  glReadBuffer(GL_BACK);
1376 
1377  //  mUseFalseColors = true;
1378 
1379  mUseFalseColors = false;
1380  unsigned int pixelCount;
1381
1382  //static int query = -1;
1383  //if (query == -1)
1384  //      glGenOcclusionQueriesNV(1, (unsigned int *)&query);
1385
1386  OcclusionQuery query;
1387
1388  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
1389  if (viewcell == NULL)
1390        return 0.0f;
1391
1392  if (mDetectEmptyViewSpace) {
1393        // now check whether any backfacing polygon would pass the depth test
1394        SetupCamera();
1395        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1396        glEnable( GL_CULL_FACE );
1397        glCullFace(GL_BACK);
1398
1399        cout<<"RS ";
1400        RenderScene();
1401       
1402        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1403        glDepthMask(GL_FALSE);
1404        glDisable( GL_CULL_FACE );
1405
1406        query.BeginQuery();
1407       
1408        cout<<"RS ";
1409        RenderScene();
1410        cout<<"RS3 ";
1411       
1412        query.EndQuery();
1413       
1414        // at this point, if possible, go and do some other computation
1415        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1416        glDepthMask(GL_TRUE);
1417        glEnable( GL_CULL_FACE );
1418       
1419        // reenable other state
1420        pixelCount = query.GetQueryResult();
1421        cout<<"RS4 ";
1422       
1423        if (pixelCount > 0)
1424          return -1.0f; // backfacing polygon found -> not a valid viewspace sample
1425
1426  } else
1427        glDisable( GL_CULL_FACE );
1428       
1429
1430  //  ViewCell *viewcell = NULL;
1431 
1432  //  PrVs prvs;
1433 
1434  //  mViewCellsManager->SetMaxFilterSize(0);
1435  //  mViewCellsManager->GetPrVS(mViewPoint, prvs, mViewCellsManager->GetFilterWidth());
1436  //  viewcell = prvs.mViewCell;
1437 
1438  ObjectPvs pvs;
1439  if (1) {
1440        pvs = viewcell->GetPvs();
1441  } else {
1442        mViewCellsManager->ApplyFilter2(viewcell,
1443                                                                        false,
1444                                                                        1.0f,
1445                                                                        pvs);
1446  }
1447 
1448  SetupCamera();
1449  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1450  glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
1451 
1452 
1453  //    // Render PVS
1454  ObjectPvsIterator it = pvs.GetIterator();
1455 
1456  pvsSize = pvs.GetSize();
1457  Intersectable::NewMail();
1458  for (; it.HasMoreEntries(); ) {
1459        ObjectPvsEntry entry = it.Next();
1460        Intersectable *object = entry.mObject;
1461        RenderIntersectable(object);
1462  }
1463 
1464  //    glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
1465  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1466 
1467  mUseFalseColors = true;
1468 
1469  query.BeginQuery();
1470 
1471  SetupCamera();
1472 
1473  RenderScene();
1474 
1475  query.EndQuery();
1476 
1477 
1478  // reenable other state
1479  pixelCount = query.GetQueryResult();
1480 
1481 
1482  pErrorPixels = ((float)pixelCount)/(GetWidth()*GetHeight());
1483
1484#if 0 
1485  if (mSnapErrorFrames && pErrorPixels > 0.001f) {
1486       
1487        char filename[256];
1488        sprintf(filename, "error-frame-%04d-%0.5f.png", mFrame, pErrorPixels);
1489        QImage im = toImage();
1490        string str = mSnapPrefix + filename;
1491        QString qstr(str.c_str());
1492       
1493        im.save(qstr, "PNG");
1494        if (1) { //0 && mFrame == 1543) {
1495          int x,y;
1496          int lastIndex = -1;
1497          for (y=0; y < im.height(); y++)
1498                for (x=0; x < im.width(); x++) {
1499                  QRgb p = im.pixel(x,y);
1500                  int index = qRed(p) + (qGreen(p)<<8) + (qBlue(p)<<16);
1501                  if (qGreen(p) != 255 && index!=0) {
1502                        if (index != lastIndex) {
1503                          //                            Debug<<"ei="<<index<<" ";
1504                          lastIndex = index;
1505                        }
1506                  }
1507                }
1508        }
1509       
1510       
1511        mUseFalseColors = false;
1512        glPushAttrib(GL_CURRENT_BIT);
1513        glColor3f(0,1,0);
1514        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1515        SetupCamera();
1516        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1517       
1518        // Render PVS
1519        Intersectable::NewMail();
1520
1521        ObjectPvsIterator it = pvs.GetIterator();
1522        for (; it.HasMoreEntries(); ) {
1523          ObjectPvsEntry entry = it.Next();
1524          Intersectable *object = entry.mObject;
1525          RenderIntersectable(object);
1526        }
1527       
1528        im = toImage();
1529        sprintf(filename, "error-frame-%04d-%0.5f-pvs.png", mFrame, pErrorPixels);
1530        str = mSnapPrefix + filename;
1531        qstr = str.c_str();
1532        im.save(qstr, "PNG");
1533        glPopAttrib();
1534  }
1535#endif
1536 
1537  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1538 
1539  return pErrorPixels;
1540}
1541
1542
1543
1544
1545
1546
1547
1548}
Note: See TracBrowser for help on using the repository browser.