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

Revision 1983, 38.2 KB checked in by bittner, 17 years ago (diff)

merge

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