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

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