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

Revision 811, 53.4 KB checked in by bittner, 18 years ago (diff)

first merge after the svn server crash

  • Property svn:executable set to *
Line 
1#include "Mesh.h"
2#include "GlRenderer.h"
3#include "ViewCellsManager.h"
4#include "SceneGraph.h"
5#include "Pvs.h"
6#include "Viewcell.h"
7#include "Beam.h"
8#include "KdTree.h"
9#include "Environment.h"
10
11//#define GL_GLEXT_PROTOTYPES
12#include <GL/glext.h>
13#include <Cg/cg.h>
14#include <Cg/cgGL.h>
15
16#include <QVBoxLayout>
17
18static CGcontext sCgContext = NULL;
19static CGprogram sCgFragmentProgram = NULL;
20static CGprofile sCgFragmentProfile;
21
22GLuint frontDepthMap;
23GLuint backDepthMap;
24
25const int depthMapSize = 512;
26static vector<int> sQueries;
27
28GlRendererWidget *rendererWidget = NULL;
29GlDebuggerWidget *debuggerWidget = NULL;
30
31
32#ifdef _WIN32
33PFNGLGENOCCLUSIONQUERIESNVPROC glGenOcclusionQueriesNV;
34PFNGLBEGINOCCLUSIONQUERYNVPROC glBeginOcclusionQueryNV;
35PFNGLENDOCCLUSIONQUERYNVPROC glEndOcclusionQueryNV;
36PFNGLGETOCCLUSIONQUERYUIVNVPROC glGetOcclusionQueryuivNV;
37
38//PFNGLGENQUERIESARBPROC glGenQueriesARB;
39//PFNGLBEGINQUERYARBPROC glBeginQueryARB;
40//PFNGLENDQUERYARBPROC glEndQueryARB;
41//PFNGLGETQUERYUIVARBPROC glGetQueryuivARB;
42#endif
43
44GlRenderer::GlRenderer(SceneGraph *sceneGraph,
45                                           ViewCellsManager *viewCellsManager,
46                                           KdTree *tree):
47  Renderer(sceneGraph, viewCellsManager),
48  mKdTree(tree)
49{
50  mSceneGraph->CollectObjects(&mObjects);
51  mViewPoint = mSceneGraph->GetBox().Center();
52  mViewDirection = Vector3(0,0,1);
53
54  //  timerId = startTimer(10);
55  // debug coords for atlanta
56  //  mViewPoint = Vector3(3473, 6.778, -1699);
57  //  mViewDirection = Vector3(-0.2432, 0, 0.97);
58 
59  mFrame = 0;
60  mWireFrame = false;
61  environment->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace);
62  mSnapErrorFrames = true;
63  mSnapPrefix = "snap/";
64  mUseForcedColors = false;
65
66  mUseGlLists = true;
67 
68}
69
70GlRenderer::~GlRenderer()
71{
72  cerr<<"gl renderer destructor..\n";
73  if (sCgFragmentProgram)
74        cgDestroyProgram(sCgFragmentProgram);
75  if (sCgContext)
76        cgDestroyContext(sCgContext);
77  cerr<<"done."<<endl;
78}
79
80
81static void handleCgError()
82{
83    Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl;
84    exit(1);
85}
86
87void
88GlRenderer::RenderIntersectable(Intersectable *object)
89{
90
91  glPushAttrib(GL_CURRENT_BIT);
92  if (mUseFalseColors)
93        SetupFalseColor(object->mId);
94 
95
96  switch (object->Type()) {
97  case Intersectable::MESH_INSTANCE:
98        RenderMeshInstance((MeshInstance *)object);
99        break;
100  case Intersectable::VIEW_CELL:
101          RenderViewCell(dynamic_cast<ViewCell *>(object));
102          break;
103  default:
104        cerr<<"Rendering this object not yet implemented\n";
105        break;
106  }
107
108  glPopAttrib();
109}
110
111
112void
113GlRenderer::RenderViewCell(ViewCell *vc)
114{
115  if (vc->GetMesh()) {
116
117        if (!mUseFalseColors) {
118          if (vc->GetValid())
119                glColor3f(0,1,0);
120          else
121                glColor3f(0,0,1);
122        }
123       
124        RenderMesh(vc->GetMesh());
125  } else {
126        // render viewcells in the subtree
127        if (!vc->IsLeaf()) {
128          ViewCellInterior *vci = (ViewCellInterior *) vc;
129
130          ViewCellContainer::iterator it = vci->mChildren.begin();
131          for (; it != vci->mChildren.end(); ++it) {
132                RenderViewCell(*it);
133          }
134        } else {
135          //      cerr<<"Empty viewcell mesh\n";
136        }
137  }
138}
139
140
141void
142GlRenderer::RenderMeshInstance(MeshInstance *mi)
143{
144  RenderMesh(mi->GetMesh());
145}
146
147void
148GlRenderer::SetupFalseColor(const int id)
149{
150  // swap bits of the color
151  glColor3ub(id&255, (id>>8)&255, (id>>16)&255);
152}
153
154
155int GlRenderer::GetId(int r, int g, int b) const
156{
157        return r + (g << 8) + (b << 16);
158}
159
160void
161GlRenderer::SetupMaterial(Material *m)
162{
163  if (m)
164        glColor3fv(&(m->mDiffuseColor.r));
165}
166
167void
168GlRenderer::RenderMesh(Mesh *mesh)
169{
170  int i = 0;
171
172  if (!mUseFalseColors && !mUseForcedColors)
173        SetupMaterial(mesh->mMaterial);
174 
175  for (i=0; i < mesh->mFaces.size(); i++) {
176        if (mWireFrame)
177          glBegin(GL_LINE_LOOP);
178        else
179          glBegin(GL_POLYGON);
180
181        Face *face = mesh->mFaces[i];
182        for (int j = 0; j < face->mVertexIndices.size(); j++) {
183          glVertex3fv(&mesh->mVertices[face->mVertexIndices[j]].x);
184        }
185        glEnd();
186  }
187}
188       
189void
190GlRenderer::InitGL()
191{
192  glMatrixMode(GL_PROJECTION);
193  glLoadIdentity();
194 
195  glMatrixMode(GL_MODELVIEW);
196  glLoadIdentity();
197
198  glEnable(GL_CULL_FACE);
199  glShadeModel(GL_FLAT);
200  glEnable(GL_DEPTH_TEST);
201  glEnable(GL_CULL_FACE);
202 
203  glGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC)
204        wglGetProcAddress("glGenOcclusionQueriesNV");
205  glBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC)
206        wglGetProcAddress("glBeginOcclusionQueryNV");
207  glEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC)
208        wglGetProcAddress("glEndOcclusionQueryNV");
209  glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)
210        wglGetProcAddress("glGetOcclusionQueryuivNV");
211
212
213#if 0
214  glGenQueriesARB = (PFNGLGENDQUERIESARBPROC)
215        wglGetProcAddress("glGenQueriesARB");
216  glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)
217        wglGetProcAddress("glBeginQueryARB");
218  glEndQueryARB = (PFNGLENDQUERYARBPROC)
219        wglGetProcAddress("glEndQueryARB");
220  glGetQueryuivARB = (PFNGLGETQUERYUIVARBPROC)
221        wglGetProcAddress("glGetQueryuivARB");
222
223#endif
224 
225
226#if 0
227  GLfloat mat_ambient[]   = {  0.5, 0.5, 0.5, 1.0  };
228  /*  mat_specular and mat_shininess are NOT default values     */
229  GLfloat mat_diffuse[]   = {  1.0, 1.0, 1.0, 1.0  };
230  GLfloat mat_specular[]  = {  0.3, 0.3, 0.3, 1.0  };
231  GLfloat mat_shininess[] = {  1.0  };
232 
233  GLfloat light_ambient[]  = {  0.2, 0.2, 0.2, 1.0  };
234  GLfloat light_diffuse[]  = {  0.4, 0.4, 0.4, 1.0  };
235  GLfloat light_specular[] = {  0.3, 0.3, 0.3, 1.0  };
236 
237  GLfloat lmodel_ambient[] = {  0.3, 0.3, 0.3, 1.0  };
238 
239 
240  // default Material
241  glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
242  glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
243  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
244  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
245
246  // a light
247  glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
248  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
249  glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
250 
251  glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
252  glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
253  glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
254 
255  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
256 
257  glEnable(GL_LIGHTING);
258  glEnable(GL_LIGHT0);
259  glEnable(GL_LIGHT1);
260 
261 
262  // set position of the light
263  GLfloat infinite_light[] = {  1.0, 0.8, 1.0, 0.0  };
264  glLightfv (GL_LIGHT0, GL_POSITION, infinite_light);
265 
266  // set position of the light2
267  GLfloat infinite_light2[] = {  -0.3, 1.5, 1.0, 0.0  };
268  glLightfv (GL_LIGHT1, GL_POSITION, infinite_light2);
269 
270  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
271  //   glColorMaterial( GL_FRONT_AND_BACK, GL_SPECULAR);
272  glEnable(GL_COLOR_MATERIAL);
273 
274  glShadeModel( GL_FLAT );
275 
276  glDepthFunc( GL_LESS );
277  glEnable( GL_DEPTH_TEST );
278#endif
279
280  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
281
282  glEnable( GL_NORMALIZE );
283 
284  glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
285}
286
287void
288GlRendererWidget::RenderInfo()
289{
290  QString s;
291  int vc = 0;
292  if (mViewCellsManager)
293        vc = mViewCellsManager->GetViewCells().size();
294  int filter = 0;
295  if (mViewCellsManager)
296        filter = mViewCellsManager->GetMaxFilterSize();
297
298  s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f) viewcells:%04d filter:%04d pvs:%04d error:%5.5f\%",
299                        mFrame,
300                        mViewPoint.x,
301                        mViewPoint.y,
302                        mViewPoint.z,
303                        mViewDirection.x,
304                        mViewDirection.y,
305                        mViewDirection.z,
306                        vc,
307
308                        filter,
309                        mPvsSize,
310                        mRenderError*100.0f
311                        );
312 
313  glColor3f(0.0f,0.0f,0.0f);
314  renderText(0,20,s);
315 
316  if (mShowRenderCost) {
317        static vector<float> costFunction;
318        static float maxCost = -1;
319        if (costFunction.size()==0) {
320          ViewCellsTree *tree = mViewCellsManager->GetViewCellsTree();
321          if (tree) {
322                tree->GetCostFunction(costFunction);
323                maxCost = -1;
324                for (int i=0;  i < costFunction.size(); i++) {
325                  //              cout<<i<<":"<<costFunction[i]<<" ";
326                  if (costFunction[i] > maxCost)
327                        maxCost = costFunction[i];
328                }
329          }
330        }
331
332       
333        int currentPos = mViewCellsManager->GetViewCells().size();
334        float currentCost=-1;
335
336        if (currentPos < costFunction.size())
337          currentCost = costFunction[currentPos];
338#if 0   
339        cout<<"costFunction.size()="<<costFunction.size()<<endl;
340        cout<<"CP="<<currentPos<<endl;
341        cout<<"MC="<<maxCost<<endl;
342        cout<<"CC="<<currentCost<<endl;
343#endif
344        if (costFunction.size()) {
345          glDisable(GL_DEPTH_TEST);
346          // init ortographic projection
347          glMatrixMode(GL_PROJECTION);
348          glPushMatrix();
349         
350          glLoadIdentity();
351          gluOrtho2D(0, 1.0f, 0, 1.0f);
352         
353          glTranslatef(0.1f, 0.1f, 0.0f);
354          glScalef(0.8f, 0.8f, 1.0f);
355          glMatrixMode(GL_MODELVIEW);
356          glLoadIdentity();
357         
358          glColor3f(1.0f,0,0);
359          glBegin(GL_LINE_STRIP);
360          //      glVertex3f(0,0,0);
361         
362          for (int i=0;  i < costFunction.size(); i++) {
363                float x =  i/(float)costFunction.size();
364                float y = costFunction[i]/(maxCost*0.5f);
365                glVertex3f(x,y,0.0f);
366          }
367          glEnd();
368         
369          glColor3f(1.0f,0,0);
370          glBegin(GL_LINES);
371          float x =  currentPos/(float)costFunction.size();
372          glVertex3f(x,0.0,0.0f);
373          glVertex3f(x,1.0f,0.0f);
374          glEnd();
375         
376          glColor3f(0.0f,0,0);
377          // show a grid
378          glBegin(GL_LINE_LOOP);
379          glVertex3f(0,0,0.0f);
380          glVertex3f(1,0,0.0f);
381          glVertex3f(1,1,0.0f);
382          glVertex3f(0,1,0.0f);
383          glEnd();
384
385          glBegin(GL_LINES);
386          for (int i=0;  i < 50000 && i < costFunction.size(); i+=10000) {
387                float x =  i/(float)costFunction.size();
388                glVertex3f(x,0.0,0.0f);
389                glVertex3f(x,1.0f,0.0f);
390          }
391
392          for (int i=0;  i < maxCost; i+=100) {
393                float y = i/(maxCost*0.5f);
394                glVertex3f(0,y,0.0f);
395                glVertex3f(1,y,0.0f);
396          }
397
398          glEnd();
399
400         
401          // restore the projection matrix
402          glMatrixMode(GL_PROJECTION);
403          glPopMatrix();
404          glMatrixMode(GL_MODELVIEW);
405          glEnable(GL_DEPTH_TEST);
406
407        }
408  }
409}
410
411
412void
413GlRenderer::SetupProjection(const int w, const int h, const float angle)
414{
415  glViewport(0, 0, w, h);
416  glMatrixMode(GL_PROJECTION);
417  glLoadIdentity();
418  gluPerspective(angle, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
419  glMatrixMode(GL_MODELVIEW);
420}
421
422void
423GlRenderer::SetupCamera()
424{
425  Vector3 target = mViewPoint + mViewDirection;
426
427  Vector3 up(0,1,0);
428 
429  if (abs(DotProd(mViewDirection, up)) > 0.99f)
430        up = Vector3(1, 0, 0);
431 
432  glLoadIdentity();
433  gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z,
434                        target.x, target.y, target.z,
435                        up.x, up.y, up.z);
436}
437
438
439void
440GlRendererBuffer::EvalRenderCostSample(
441                                                                           RenderCostSample &sample
442                                                                           )
443{
444  mViewCellsManager->GetViewPoint(mViewPoint);
445  cout<<mViewPoint<<endl;
446 
447  // take a render cost sample by rendering a cube
448  Vector3 directions[6];
449  directions[0] = Vector3(1,0,0);
450  directions[1] = Vector3(0,1,0);
451  directions[2] = Vector3(0,0,1);
452  directions[3] = Vector3(-1,0,0);
453  directions[4] = Vector3(0,-1,0);
454  directions[5] = Vector3(0,0,-1);
455
456  sample.mVisibleObjects = 0;
457
458  int i, j;
459 
460  // reset object visibility
461  for (i=0; i < mObjects.size(); i++) {
462        mObjects[i]->mCounter = 0;
463  }
464  mFrame++;
465  for (i=0; i < 6; i++) {
466        mViewDirection = directions[i];
467        SetupCamera();
468        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
469        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
470       
471        glDepthFunc( GL_LESS );
472
473        mUseFalseColors = true;
474
475        RenderScene();
476
477        if (1) {
478          char filename[256];
479          sprintf(filename, "snap/frame-%04d-%d.png", mFrame, i);
480          QImage im = toImage();
481          im.save(filename, "PNG");
482        }
483       
484        bool useItemBuffer = false;
485       
486        if (useItemBuffer) {
487          // read back the texture
488          glReadPixels(0, 0,
489                                   GetWidth(), GetHeight(),
490                                   GL_RGBA,
491                                   GL_UNSIGNED_BYTE,
492                                   mPixelBuffer);
493         
494          int x, y;
495          unsigned int *p = mPixelBuffer;
496          for (y = 0; y < GetHeight(); y++)
497                for (x = 0; x < GetWidth(); x++, p++) {
498                  unsigned int id = (*p) & 0xFFFFFF;
499                  if (id != 0xFFFFFF)
500                        mObjects[id]->mCounter++;
501                }
502         
503        } else {
504       
505          //      glDepthFunc( GL_LEQUAL );
506          glDepthFunc( GL_LEQUAL );
507         
508          glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
509          glDepthMask(GL_FALSE);
510         
511          // now issue queries for all objects
512          for (j = 0; j < mObjects.size(); j++) {
513                int q;
514                for (q = 0; j + q < mObjects.size() && q < mOcclusionQueries.size(); q++) {
515                  glBeginOcclusionQueryNV(mOcclusionQueries[q]);
516                  RenderIntersectable(mObjects[j+q]);
517                  glEndOcclusionQueryNV();
518                }
519               
520               
521                // collect results of the queries
522                for (q = 0; j + q < mObjects.size() && q < mOcclusionQueries.size(); q++) {
523                  unsigned int pixelCount;
524                  // reenable other state
525
526#if 1
527                  do {
528                        glGetOcclusionQueryuivNV(mOcclusionQueries[q],
529                                                                         GL_PIXEL_COUNT_AVAILABLE_NV,
530                                                                         &pixelCount);
531                        if (!pixelCount)
532                          cout<<"W";
533                  } while(!pixelCount);
534#endif
535
536                  glGetOcclusionQueryuivNV(mOcclusionQueries[q],
537                                                                   GL_PIXEL_COUNT_NV,
538                                                                   &pixelCount);
539                  //            if (pixelCount)
540                  //              cout<<"q="<<mOcclusionQueries[q]<<" pc="<<pixelCount<<" ";
541                  mObjects[j+q]->mCounter += pixelCount;
542                }
543                j += q;
544          }
545         
546          glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
547          glDepthMask(GL_TRUE);
548        }
549         
550       
551  } 
552  // now evaluate the statistics over that sample
553  // currently only the number of visible objects is taken into account
554  sample.Reset();
555  for (j = 0; j < mObjects.size(); j++) {
556        if (mObjects[j]->mCounter) {
557          sample.mVisibleObjects++;
558          sample.mVisiblePixels += mObjects[j]->mCounter;
559        }
560  }
561  cout<<"RS="<<sample.mVisibleObjects<<" ";
562}
563
564void
565GlRendererBuffer::SampleRenderCost(
566                                                                   const int n,
567                                                                   vector<RenderCostSample> &samples
568                                                                   )
569{
570  makeCurrent();
571
572  if (mPixelBuffer == NULL)
573        mPixelBuffer = new unsigned int[GetWidth()*GetHeight()];
574 
575  SetupProjection(GetHeight(), GetHeight(), 90.0f);
576
577  samples.resize(n);
578  halton.Reset();
579 
580  int i;
581  int numQ = 500;
582 
583  if (mOcclusionQueries.size() < numQ) {
584        cout<<"allocating occ queries..."<<endl;
585       
586        numQ;
587        unsigned int *queries = new unsigned int[numQ];
588        for (i=0; i < numQ; i++)
589          queries[i] = 111;
590       
591        glGenOcclusionQueriesNV(numQ, queries);
592       
593        mOcclusionQueries.resize(numQ);
594       
595        for (i=0; i < numQ; i++)
596          mOcclusionQueries[i] = queries[i];
597       
598        delete queries;
599  }
600 
601  for (i=0; i < n; i++)
602        EvalRenderCostSample(
603                                                 samples[i]
604                                                 );
605
606  doneCurrent();
607
608}
609 
610
611void
612GlRendererBuffer::RandomViewPoint()
613{
614 
615 
616  // do not use this function since it could return different viewpoints for
617  // different executions of the algorithm
618
619  //mViewCellsManager->GetViewPoint(mViewPoint);
620
621  while (1) {
622        Vector3 pVector = Vector3(halton.GetNumber(1),
623                                                          halton.GetNumber(2),
624                                                          halton.GetNumber(3));
625       
626        mViewPoint =  mSceneGraph->GetBox().GetPoint(pVector);
627        ViewCell *v = mViewCellsManager->GetViewCell(mViewPoint);
628        if (v && v->GetValid())
629          break;
630        // generate a new vector
631        halton.GenerateNext();
632  }
633 
634 
635  Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4),
636                                                        M_PI*halton.GetNumber(5),
637                                                        0.0f);
638 
639  mViewDirection = Normalize(Vector3(sin(dVector.x),
640                                                                         //                                                                      cos(dVector.y),
641                                                                         0.0f,
642                                                                         cos(dVector.x)));
643  halton.GenerateNext();
644}
645
646
647GlRendererBuffer::GlRendererBuffer(const int w,
648                                                                   const int h,
649                                                                   SceneGraph *sceneGraph,
650                                                                   ViewCellsManager *viewcells,
651                                                                   KdTree *tree):
652QGLPixelBuffer(QSize(w, h)), GlRenderer(sceneGraph, viewcells, tree) {
653 
654  environment->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames);
655  mPvsErrorBuffer.resize(mPvsStatFrames);
656  ClearErrorBuffer();
657
658  mPixelBuffer = NULL;
659 
660  makeCurrent();
661  InitGL();
662  doneCurrent();
663 
664}
665
666float
667GlRendererBuffer::GetPixelError(int &pvsSize)
668{
669  float pErrorPixels = -1.0f;
670 
671  glReadBuffer(GL_BACK);
672 
673  //  mUseFalseColors = true;
674 
675  mUseFalseColors = false;
676
677  static int query = -1;
678  unsigned int pixelCount;
679
680  if (query == -1)
681        glGenOcclusionQueriesNV(1, (unsigned int *)&query);
682
683  if (mDetectEmptyViewSpace) {
684        // now check whether any backfacing polygon would pass the depth test
685        SetupCamera();
686        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
687        glEnable( GL_CULL_FACE );
688       
689        RenderScene();
690       
691        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
692        glDepthMask(GL_FALSE);
693        glDisable( GL_CULL_FACE );
694       
695        glBeginOcclusionQueryNV(query);
696       
697        RenderScene();
698       
699        glEndOcclusionQueryNV();
700       
701        // at this point, if possible, go and do some other computation
702        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
703        glDepthMask(GL_TRUE);
704        glEnable( GL_CULL_FACE );
705       
706        // reenable other state
707        glGetOcclusionQueryuivNV(query,
708                                                         GL_PIXEL_COUNT_NV,
709                                                         &pixelCount);
710       
711        if (pixelCount > 0)
712          return -1.0f; // backfacing polygon found -> not a valid viewspace sample
713  } else
714        glDisable( GL_CULL_FACE );
715       
716
717  ViewCell *viewcell = NULL;
718 
719  PrVs prvs;
720  //  mViewCellsManager->SetMaxFilterSize(1);
721  mViewCellsManager->GetPrVS(mViewPoint, prvs);
722  viewcell = prvs.mViewCell;
723 
724  //  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
725  pvsSize = 0;
726  if (viewcell) {
727        SetupCamera();
728        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
729
730        glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
731       
732        // Render PVS
733        std::map<Intersectable *,
734          PvsData<Intersectable *>,
735          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
736
737        pvsSize = viewcell->GetPvs().mEntries.size();
738       
739        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
740          Intersectable *object = (*it).first;
741          RenderIntersectable(object);
742        }
743
744        //      glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
745        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
746        mUseFalseColors = true;
747
748        glBeginOcclusionQueryNV(query);
749
750        SetupCamera();
751
752        RenderScene();
753       
754        glEndOcclusionQueryNV();
755       
756
757        unsigned int pixelCount;
758        // reenable other state
759        glGetOcclusionQueryuivNV(query,
760                                                         GL_PIXEL_COUNT_NV,
761                                                         &pixelCount);
762       
763        pErrorPixels = ((float)pixelCount)/(GetWidth()*GetHeight());
764        if (mSnapErrorFrames && pErrorPixels > 0.01) {
765         
766          char filename[256];
767          sprintf(filename, "error-frame-%04d-%0.5f.png", mFrame, pErrorPixels);
768          QImage im = toImage();
769          im.save(mSnapPrefix + filename, "PNG");
770          if (1) { //0 && mFrame == 1543) {
771                int x,y;
772                int lastIndex = -1;
773                for (y=0; y < im.height(); y++)
774                  for (x=0; x < im.width(); x++) {
775                        QRgb p = im.pixel(x,y);
776                        int index = qRed(p) + (qGreen(p)<<8) + (qBlue(p)<<16);
777                        if (qGreen(p) != 255 && index!=0) {
778                          if (index != lastIndex) {
779                                Debug<<"ei="<<index<<" ";
780                                lastIndex = index;
781                          }
782                        }
783                  }
784          }
785
786
787          mUseFalseColors = false;
788          glPushAttrib(GL_CURRENT_BIT);
789          glColor3f(0,1,0);
790          glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
791          SetupCamera();
792          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
793         
794          // Render PVS
795          std::map<Intersectable *,
796                PvsData<Intersectable *>,
797                LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
798         
799          for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
800                Intersectable *object = (*it).first;
801                RenderIntersectable(object);
802          }
803
804          im = toImage();
805          sprintf(filename, "error-frame-%04d-%0.5f-pvs.png", mFrame, pErrorPixels);
806          im.save(mSnapPrefix + filename, "PNG");
807          glPopAttrib();
808        }
809        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
810  }
811
812  if (viewcell)
813        mViewCellsManager->DeleteLocalMergeTree(viewcell);
814 
815  return pErrorPixels;
816}
817
818
819void
820GlRendererWidget::SetupProjection(const int w, const int h)
821{
822  if (!mTopView)
823        GlRenderer::SetupProjection(w, h);
824  else {
825        glViewport(0, 0, w, h);
826        glMatrixMode(GL_PROJECTION);
827        glLoadIdentity();
828        gluPerspective(50.0, 1.0, 0.1, 20.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
829        glMatrixMode(GL_MODELVIEW);
830  }
831}
832
833void
834GlRendererWidget::RenderPvs()
835{
836  SetupCamera();
837  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
838 
839  ViewCell *viewcell;
840  //  viewcell = mViewCellsManager->GetViewCell(mViewPoint);
841
842  PrVs prvs;
843  //  mViewCellsManager->SetMaxFilterSize(1);
844  mViewCellsManager->GetPrVS(mViewPoint, prvs);
845  viewcell = prvs.mViewCell;
846 
847  if (viewcell) {
848        ObjectPvs &pvs = viewcell->GetPvs();
849
850        // read back the texture
851        std::map<Intersectable *,
852          PvsData<Intersectable *>,
853          LtSample<Intersectable *> >::const_iterator it = pvs.mEntries.begin();
854
855        mPvsSize = pvs.mEntries.size();
856         
857        for (; it != pvs.mEntries.end(); ++ it) {
858          Intersectable *object = (*it).first;
859          float visibility = log10((*it).second.mSumPdf + 1)/5.0f;
860          glColor3f(visibility, 0.0f, 0.0f);
861          mUseForcedColors = true;
862          RenderIntersectable(object);
863          mUseForcedColors = false;
864        }
865
866        if (mRenderFilter) {
867          mWireFrame = true;
868          RenderIntersectable(viewcell);
869          mWireFrame = false;
870        }
871        mViewCellsManager->DeleteLocalMergeTree(viewcell);
872  } else {
873        ObjectContainer::const_iterator oi = mObjects.begin();
874        for (; oi != mObjects.end(); oi++)
875          RenderIntersectable(*oi);
876  }
877}
878
879float
880GlRendererWidget::RenderErrors()
881{
882  float pErrorPixels = -1.0f;
883
884  glReadBuffer(GL_BACK);
885 
886  mUseFalseColors = true;
887
888  SetupCamera();
889  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
890 
891  double eq[4];
892  eq[0] = mSceneCutPlane.mNormal.x;
893  eq[1] = mSceneCutPlane.mNormal.y;
894  eq[2] = mSceneCutPlane.mNormal.z;
895  eq[3] = mSceneCutPlane.mD;
896 
897  if (mCutScene) {
898        glClipPlane(GL_CLIP_PLANE0, eq);
899    glEnable(GL_CLIP_PLANE0);
900  }
901 
902  if (mDetectEmptyViewSpace)
903        glEnable( GL_CULL_FACE );
904  else
905        glDisable( GL_CULL_FACE );
906
907  ObjectContainer::const_iterator oi = mObjects.begin();
908  for (; oi != mObjects.end(); oi++)
909        RenderIntersectable(*oi);
910
911  ViewCell *viewcell;
912  //  viewcell = mViewCellsManager->GetViewCell(mViewPoint);
913
914  PrVs prvs;
915  //  mViewCellsManager->SetMaxFilterSize(1);
916  mViewCellsManager->GetPrVS(mViewPoint, prvs);
917  viewcell = prvs.mViewCell;
918 
919  QImage im1, im2;
920  QImage diff;
921 
922  if (viewcell) {
923        // read back the texture
924        im1 = grabFrameBuffer(true);
925       
926        SetupCamera();
927        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
928       
929        std::map<Intersectable *,
930          PvsData<Intersectable *>,
931          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
932
933        mPvsSize = viewcell->GetPvs().mEntries.size();
934
935        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
936          Intersectable *object = (*it).first;
937          RenderIntersectable(object);
938        }
939
940        // read back the texture
941        im2 = grabFrameBuffer(true);
942       
943        diff = im1;
944        int x, y;
945        int errorPixels = 0;
946       
947        for (y = 0; y < im1.height(); y++)
948          for (x = 0; x < im1.width(); x++)
949                if (im1.pixel(x, y) == im2.pixel(x, y))
950                  diff.setPixel(x, y, qRgba(0,0,0,0));
951                else {
952                  diff.setPixel(x, y, qRgba(255,128,128,255));
953                  errorPixels++;
954                }
955        pErrorPixels = ((float)errorPixels)/(im1.height()*im1.width());
956  }
957
958  // now render the pvs again
959  SetupCamera();
960  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
961  mUseFalseColors = false;
962       
963  oi = mObjects.begin();
964  for (; oi != mObjects.end(); oi++)
965        RenderIntersectable(*oi);
966
967  // now render im1
968  if (viewcell) {
969        if (0 && mTopView) {
970          mWireFrame = true;
971          RenderIntersectable(viewcell);
972          mWireFrame = false;
973        }
974       
975        // init ortographic projection
976        glMatrixMode(GL_PROJECTION);
977        glPushMatrix();
978       
979        glLoadIdentity();
980        gluOrtho2D(0, 1.0f, 0, 1.0f);
981       
982        glMatrixMode(GL_MODELVIEW);
983        glLoadIdentity();
984       
985        bindTexture(diff);
986       
987        glPushAttrib(GL_ENABLE_BIT);
988        glEnable( GL_ALPHA_TEST );
989        glDisable( GL_CULL_FACE );
990        glAlphaFunc( GL_GREATER, 0.5 );
991       
992        glEnable( GL_TEXTURE_2D );
993        glBegin(GL_QUADS);
994       
995        glTexCoord2f(0,0);
996        glVertex3f(0,0,0);
997       
998        glTexCoord2f(1,0);
999        glVertex3f( 1, 0, 0);
1000       
1001        glTexCoord2f(1,1);
1002        glVertex3f( 1, 1, 0);
1003       
1004        glTexCoord2f(0,1);
1005        glVertex3f(0, 1, 0);
1006        glEnd();
1007       
1008        glPopAttrib();
1009       
1010        // restore the projection matrix
1011        glMatrixMode(GL_PROJECTION);
1012        glPopMatrix();
1013        glMatrixMode(GL_MODELVIEW);
1014  }
1015
1016  glDisable(GL_CLIP_PLANE0);
1017
1018  if (viewcell)
1019        mViewCellsManager->DeleteLocalMergeTree(viewcell);
1020
1021  mRenderError = pErrorPixels;
1022  return pErrorPixels;
1023}
1024
1025void
1026GlRenderer::_RenderScene()
1027{
1028  ObjectContainer::const_iterator oi = mObjects.begin();
1029  for (; oi != mObjects.end(); oi++)
1030        RenderIntersectable(*oi);
1031}
1032
1033bool
1034GlRenderer::RenderScene()
1035{
1036  static int glList = -1;
1037  if (mUseGlLists) {
1038        if (glList == -1) {
1039          glList = glGenLists(1);
1040          glNewList(glList, GL_COMPILE);
1041          _RenderScene();
1042          glEndList();
1043        }
1044        glCallList(glList);
1045  } else
1046        _RenderScene();
1047       
1048 
1049  return true;
1050}
1051
1052
1053void
1054GlRendererBuffer::ClearErrorBuffer()
1055{
1056  for (int i=0; i < mPvsStatFrames; i++) {
1057        mPvsErrorBuffer[i].mError = 1.0f;
1058  }
1059}
1060
1061
1062void
1063GlRendererBuffer::EvalPvsStat()
1064{
1065  mPvsStat.Reset();
1066  halton.Reset();
1067
1068  makeCurrent();
1069  SetupProjection(GetWidth(), GetHeight());
1070 
1071  for (int i=0; i < mPvsStatFrames; i++) {
1072        float err;
1073        // set frame id for saving the error buffer
1074        mFrame = i;
1075        RandomViewPoint();
1076
1077        // atlanta problematic frames: 325 525 691 1543
1078#if 0
1079        if (mFrame != 325 &&
1080                mFrame != 525 &&
1081                mFrame != 691 &&
1082                mFrame != 1543)
1083          mPvsErrorBuffer[i] = -1;
1084        else {
1085          Debug<<"frame ="<<mFrame<<" vp="<<mViewPoint<<" vd="<<mViewDirection<<endl;
1086        }
1087#endif
1088        if (mPvsErrorBuffer[i].mError > 0.0f) {
1089          int pvsSize;
1090          float error = GetPixelError(pvsSize);
1091          mPvsErrorBuffer[i].mError = error;
1092          mPvsErrorBuffer[i].mPvsSize = pvsSize;
1093
1094          emit UpdatePvsErrorItem(i,
1095                                                          mPvsErrorBuffer[i]);
1096         
1097          cout<<"("<<i<<","<<mPvsErrorBuffer[i].mError<<")";
1098          //      swapBuffers();
1099        }
1100       
1101        err = mPvsErrorBuffer[i].mError;
1102       
1103        if (err >= 0.0f) {
1104          if (err > mPvsStat.maxError)
1105                mPvsStat.maxError = err;
1106          mPvsStat.sumError += err;
1107          mPvsStat.sumPvsSize += mPvsErrorBuffer[i].mPvsSize;
1108         
1109          if (err == 0.0f)
1110                mPvsStat.errorFreeFrames++;
1111          mPvsStat.frames++;
1112        }
1113  }
1114
1115  glFinish();
1116  doneCurrent();
1117
1118  cout<<endl<<flush;
1119  //  mRenderingFinished.wakeAll();
1120}
1121
1122
1123
1124
1125
1126void
1127GlRendererWidget::mousePressEvent(QMouseEvent *e)
1128{
1129  int x = e->pos().x();
1130  int y = e->pos().y();
1131
1132  mousePoint.x = x;
1133  mousePoint.y = y;
1134 
1135}
1136
1137void
1138GlRendererWidget::mouseMoveEvent(QMouseEvent *e)
1139{
1140  float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3;
1141  float TURN_SENSITIVITY=0.1f;
1142  float TILT_SENSITIVITY=32.0 ;
1143  float TURN_ANGLE= M_PI/36.0 ;
1144
1145  int x = e->pos().x();
1146  int y = e->pos().y();
1147 
1148  if (e->modifiers() & Qt::ControlModifier) {
1149        mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0;
1150        mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0;
1151  } else {
1152        mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY);
1153        float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY;
1154        float angle = atan2(mViewDirection.x, mViewDirection.z);
1155        mViewDirection.x = sin(angle+adiff);
1156        mViewDirection.z = cos(angle+adiff);
1157  }
1158 
1159  mousePoint.x = x;
1160  mousePoint.y = y;
1161 
1162  updateGL();
1163}
1164
1165void
1166GlRendererWidget::mouseReleaseEvent(QMouseEvent *)
1167{
1168
1169
1170}
1171
1172void
1173GlRendererWidget::resizeGL(int w, int h)
1174{
1175  SetupProjection(w, h);
1176  updateGL();
1177}
1178
1179void
1180GlRendererWidget::paintGL()
1181{
1182  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1183
1184 
1185  if (!mRenderViewCells) {
1186        if (mRenderErrors)
1187          RenderErrors();
1188        else
1189          RenderPvs();
1190        RenderInfo();
1191  } else {
1192        RenderViewCells();
1193       
1194        mWireFrame = true;
1195        RenderScene();
1196        mWireFrame = false;
1197       
1198        RenderInfo();
1199  }
1200
1201  mFrame++;
1202}
1203
1204
1205void
1206GlRendererWidget::SetupCamera()
1207{
1208  if (!mTopView)
1209        GlRenderer::SetupCamera();
1210  else {
1211        if (0) {
1212          float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05;
1213          Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x,
1214                                                                                          -1,
1215                                                                                          mViewDirection.y);
1216         
1217          Vector3 target = mViewPoint + dist*mViewDirection;
1218          Vector3 up(0,1,0);
1219         
1220          glLoadIdentity();
1221          gluLookAt(pos.x, pos.y, pos.z,
1222                                target.x, target.y, target.z,
1223                                up.x, up.y, up.z);
1224        } else {
1225          float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*mTopDistance;
1226          Vector3 pos = mViewPoint  + dist*Vector3(0,
1227                                                                                           1,
1228                                                                                           0);
1229         
1230          Vector3 target = mViewPoint;
1231          Vector3 up(mViewDirection.x, 0, mViewDirection.z);
1232         
1233          glLoadIdentity();
1234          gluLookAt(pos.x, pos.y, pos.z,
1235                                target.x, target.y, target.z,
1236                                up.x, up.y, up.z);
1237         
1238        }
1239  }
1240
1241}
1242
1243void
1244GlRendererWidget::keyPressEvent ( QKeyEvent * e )
1245{
1246  switch (e->key()) {
1247  case Qt::Key_T:
1248        mTopView = !mTopView;
1249        SetupProjection(width(), height());
1250        updateGL();
1251        break;
1252  case Qt::Key_V:
1253        mRenderViewCells = !mRenderViewCells;
1254        updateGL();
1255        break;
1256  default:
1257        e->ignore();
1258        break;
1259  }
1260}
1261
1262 
1263RendererControlWidget::RendererControlWidget(QWidget * parent, Qt::WFlags f):
1264  QWidget(parent, f)
1265{
1266
1267  QVBoxLayout *vl = new QVBoxLayout;
1268  setLayout(vl);
1269 
1270  QWidget *vbox = new QGroupBox("ViewCells", this);
1271  layout()->addWidget(vbox);
1272 
1273  vl = new QVBoxLayout;
1274  vbox->setLayout(vl);
1275
1276  QLabel *label = new QLabel("Granularity");
1277  vbox->layout()->addWidget(label);
1278
1279  QSlider *slider = new QSlider(Qt::Horizontal, vbox);
1280  vl->addWidget(slider);
1281  slider->show();
1282  slider->setRange(1, 10000);
1283  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1284  slider->setValue(200);
1285
1286  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetViewCellGranularity(int)));
1287
1288  label = new QLabel("Filter size");
1289  vbox->layout()->addWidget(label);
1290 
1291  slider = new QSlider(Qt::Horizontal, vbox);
1292  vbox->layout()->addWidget(slider);
1293  slider->show();
1294  slider->setRange(1, 100);
1295  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1296  slider->setValue(3);
1297 
1298  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetVisibilityFilterSize(int)));
1299
1300
1301
1302  QWidget *hbox = new QWidget(vbox);
1303  vl->addWidget(hbox);
1304  QHBoxLayout *hlayout = new QHBoxLayout;
1305  hbox->setLayout(hlayout);
1306 
1307  QCheckBox *cb = new QCheckBox("Show viewcells", hbox);
1308  hlayout->addWidget(cb);
1309  cb->setChecked(false);
1310  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowViewCells(bool)));
1311
1312  cb = new QCheckBox("Show render cost", hbox);
1313  hlayout->addWidget(cb);
1314  cb->setChecked(false);
1315  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowRenderCost(bool)));
1316
1317  cb = new QCheckBox("Show pvs sizes", hbox);
1318  hlayout->addWidget(cb);
1319  cb->setChecked(false);
1320  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowPvsSizes(bool)));
1321
1322  vbox->resize(800,100);
1323
1324 
1325  vbox = new QGroupBox("Rendering", this);
1326  layout()->addWidget(vbox);
1327 
1328  vl = new QVBoxLayout;
1329  vbox->setLayout(vl);
1330
1331
1332
1333  slider = new QSlider(Qt::Horizontal, vbox);
1334  vbox->layout()->addWidget(slider);
1335  slider->show();
1336  slider->setRange(0, 1000);
1337  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1338  slider->setValue(1000);
1339
1340  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSceneCut(int)));
1341
1342  cb = new QCheckBox("Render errors", vbox);
1343  vbox->layout()->addWidget(cb);
1344  cb->setChecked(false);
1345  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderErrors(bool)));
1346
1347  cb = new QCheckBox("Render filter", vbox);
1348  vbox->layout()->addWidget(cb);
1349  cb->setChecked(true);
1350  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderFilter(bool)));
1351
1352  cb = new QCheckBox("Cut view cells", vbox);
1353  vbox->layout()->addWidget(cb);
1354  cb->setChecked(false);
1355  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutViewCells(bool)));
1356
1357  cb = new QCheckBox("Cut scene", vbox);
1358  vbox->layout()->addWidget(cb);
1359  cb->setChecked(false);
1360  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutScene(bool)));
1361
1362 
1363  slider = new QSlider(Qt::Horizontal, vbox);
1364  vbox->layout()->addWidget(slider);
1365  slider->show();
1366  slider->setRange(1, 1000);
1367  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1368  slider->setValue(500);
1369 
1370  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetTopDistance(int)));
1371 
1372  cb = new QCheckBox("Top View", vbox);
1373  vbox->layout()->addWidget(cb);
1374  cb->setChecked(false);
1375  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetTopView(bool)));
1376
1377  vbox = new QGroupBox("PVS Errors", this);
1378  layout()->addWidget(vbox);
1379
1380  vl = new QVBoxLayout;
1381  vbox->setLayout(vl);
1382
1383  mPvsErrorWidget = new QListWidget(vbox);
1384  vbox->layout()->addWidget(mPvsErrorWidget);
1385 
1386  connect(mPvsErrorWidget,
1387                  SIGNAL(doubleClicked(const QModelIndex &)),
1388                  this,
1389                  SLOT(PvsErrorClicked(const QModelIndex &)));
1390 
1391  QPushButton *button = new QPushButton("Next Error Frame", vbox);
1392  vbox->layout()->addWidget(button);
1393  connect(button, SIGNAL(clicked(void)), SLOT(FocusNextPvsErrorFrame(void)));
1394
1395  setWindowTitle("Preprocessor Control Widget");
1396  adjustSize();
1397}
1398
1399
1400
1401void
1402RendererControlWidget::FocusNextPvsErrorFrame(void)
1403{
1404 
1405 
1406}
1407
1408void
1409RendererControlWidget::UpdatePvsErrorItem(int row,
1410                                                                                  GlRendererBuffer::PvsErrorEntry &pvsErrorEntry)
1411{
1412
1413  QListWidgetItem *i = mPvsErrorWidget->item(row);
1414  QString s;
1415  s.sprintf("%5.5f", pvsErrorEntry.mError);
1416  if (i) {
1417        i->setText(s);
1418  } else {
1419        new QListWidgetItem(s, mPvsErrorWidget);
1420  }
1421  mPvsErrorWidget->update();
1422}
1423
1424GlRendererWidget::GlRendererWidget(SceneGraph *sceneGraph,
1425                                                                   ViewCellsManager *viewcells,
1426                                                                   KdTree *tree,
1427                                                                   QWidget * parent,
1428                                                                   const QGLWidget * shareWidget,
1429                                                                   Qt::WFlags f
1430                                                                   )
1431  :
1432  GlRenderer(sceneGraph, viewcells, tree), QGLWidget(parent, shareWidget, f)
1433{
1434  mTopView = false;
1435  mRenderViewCells = false;
1436  mTopDistance = 1.0f;
1437  mCutViewCells = false;
1438  mCutScene = false;
1439  mRenderErrors = false;
1440  mRenderFilter = true;
1441  mShowRenderCost = false;
1442  mShowPvsSizes = false;
1443
1444  mPvsSize = 0;
1445  mRenderError = 0.0f;
1446  mControlWidget = new RendererControlWidget(NULL);
1447 
1448  connect(mControlWidget, SIGNAL(SetViewCellGranularity(int)), this, SLOT(SetViewCellGranularity(int)));
1449  connect(mControlWidget, SIGNAL(SetSceneCut(int)), this, SLOT(SetSceneCut(int)));
1450  connect(mControlWidget, SIGNAL(SetTopDistance(int)), this, SLOT(SetTopDistance(int)));
1451
1452  connect(mControlWidget, SIGNAL(SetVisibilityFilterSize(int)), this, SLOT(SetVisibilityFilterSize(int)));
1453
1454  connect(mControlWidget, SIGNAL(SetShowViewCells(bool)), this, SLOT(SetShowViewCells(bool)));
1455  connect(mControlWidget, SIGNAL(SetShowRenderCost(bool)), this, SLOT(SetShowRenderCost(bool)));
1456  connect(mControlWidget, SIGNAL(SetShowPvsSizes(bool)), this, SLOT(SetShowPvsSizes(bool)));
1457  connect(mControlWidget, SIGNAL(SetTopView(bool)), this, SLOT(SetTopView(bool)));
1458  connect(mControlWidget, SIGNAL(SetCutViewCells(bool)), this, SLOT(SetCutViewCells(bool)));
1459  connect(mControlWidget, SIGNAL(SetCutScene(bool)), this, SLOT(SetCutScene(bool)));
1460  connect(mControlWidget, SIGNAL(SetRenderErrors(bool)), this, SLOT(SetRenderErrors(bool)));
1461  connect(mControlWidget, SIGNAL(SetRenderFilter(bool)), this, SLOT(SetRenderFilter(bool)));
1462
1463 
1464  mControlWidget->show();
1465}
1466
1467void
1468GlRendererWidget::SetViewCellGranularity(int number)
1469{
1470  if (mViewCellsManager)
1471        //      mViewCellsManager->SetMaxFilterSize(number);
1472    mViewCellsManager->CollectViewCells(number);
1473  updateGL();
1474}
1475
1476void
1477GlRendererWidget::SetVisibilityFilterSize(int number)
1478{
1479  if (mViewCellsManager)
1480        mViewCellsManager->SetMaxFilterSize(number);
1481  updateGL();
1482}
1483
1484void
1485GlRendererWidget::SetSceneCut(int number)
1486{
1487  // assume the cut plane can only be aligned with xz plane
1488  // shift it along y according to number, which is percentage of the bounding
1489  // box position
1490  if (mViewCellsManager) {
1491        AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
1492        Vector3 p = box.Min() + (number/1000.0f)*box.Max();
1493        mSceneCutPlane.mNormal = Vector3(0,-1,0);
1494        mSceneCutPlane.mD = -DotProd(mSceneCutPlane.mNormal, p);
1495        updateGL();
1496  }
1497}
1498
1499void
1500GlRendererWidget::SetTopDistance(int number)
1501{
1502  mTopDistance = number/1000.0f;
1503  updateGL();
1504}
1505
1506void
1507GlRendererWidget::RenderViewCells()
1508{
1509  mUseFalseColors = true;
1510
1511  SetupCamera();
1512  glEnable(GL_CULL_FACE);
1513  //glDisable(GL_CULL_FACE);
1514  glCullFace(GL_FRONT);
1515  double eq[4];
1516  eq[0] = mSceneCutPlane.mNormal.x;
1517  eq[1] = mSceneCutPlane.mNormal.y;
1518  eq[2] = mSceneCutPlane.mNormal.z;
1519  eq[3] = mSceneCutPlane.mD;
1520
1521  if (mCutViewCells) {
1522        glClipPlane(GL_CLIP_PLANE0, eq);
1523        glEnable(GL_CLIP_PLANE0);
1524  }
1525 
1526  int i;
1527  ViewCellContainer &viewcells = mViewCellsManager->GetViewCells();
1528  int maxPvs = -1;
1529  for (i=0; i < viewcells.size(); i++) {
1530        ViewCell *vc = viewcells[i];
1531        int p = vc->GetPvs().GetSize();
1532        if (p > maxPvs)
1533          maxPvs = p;
1534  }
1535
1536
1537  for (i=0; i < viewcells.size(); i++) {
1538        ViewCell *vc = viewcells[i];
1539        //      Mesh *m = vc->GetMesh();
1540
1541
1542        RgbColor c;
1543
1544        if (!mShowPvsSizes)
1545          c = vc->GetColor();
1546        else {
1547          float importance = (float)vc->GetPvs().GetSize() / (float)maxPvs;
1548          c = RgbColor(importance, 1.0f - importance, 0.0f);
1549        }
1550        glColor3f(c.r, c.g, c.b);
1551       
1552        RenderViewCell(vc);
1553  }
1554
1555  glDisable(GL_CLIP_PLANE0);
1556
1557}
1558
1559void GlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject,
1560                                                                                           Beam &beam,
1561                                                                                           const int desiredSamples,
1562                                                                                           BeamSampleStatistics &stat)
1563{
1564        // TODO: should be moved out of here (not to be done every time)
1565        // only back faces are interesting for the depth pass
1566        glShadeModel(GL_FLAT);
1567        glDisable(GL_LIGHTING);
1568
1569        // needed to kill the fragments for the front buffer
1570        glEnable(GL_ALPHA_TEST);
1571        glAlphaFunc(GL_GREATER, 0);
1572
1573        // assumes that the beam is constructed and contains kd-tree nodes
1574        // and viewcells which it intersects
1575 
1576 
1577        // Get the number of viewpoints to be sampled
1578        // Now it is a sqrt but in general a wiser decision could be made.
1579        // The less viewpoints the better for rendering performance, since less passes
1580        // over the beam is needed.
1581        // The viewpoints could actually be generated outside of the bounding box which
1582        // would distribute the 'efective viewpoints' of the object surface and thus
1583        // with a few viewpoints better sample the viewpoint space....
1584
1585        //TODO: comment in
1586        //int viewPointSamples = sqrt((float)desiredSamples);
1587        int viewPointSamples = max(desiredSamples / (GetWidth() * GetHeight()), 1);
1588       
1589        // the number of direction samples per pass is given by the number of viewpoints
1590        int directionalSamples = desiredSamples / viewPointSamples;
1591       
1592        Debug << "directional samples: " << directionalSamples << endl;
1593        for (int i = 0; i < viewPointSamples; ++ i)
1594        {
1595                Vector3 viewPoint = beam.mBox.GetRandomPoint();
1596               
1597                // perhaps the viewpoint should be shifted back a little bit so that it always lies
1598                // inside the source object
1599                // 'ideally' the viewpoints would be distributed on the soureObject surface, but this
1600        // would require more complicated sampling (perhaps hierarchical rejection sampling of
1601                // the object surface is an option here - only the mesh faces which are inside the box
1602                // are considered as candidates)
1603               
1604                SampleViewpointContributions(sourceObject,
1605                                                                         viewPoint,
1606                                                                         beam,
1607                                                                         directionalSamples,
1608                                                                         stat);
1609        }
1610
1611
1612        // note:
1613        // this routine would be called only if the number of desired samples is sufficiently
1614        // large - for other rss tree cells the cpu based sampling is perhaps more efficient
1615        // distributing the work between cpu and gpu would also allow us to place more sophisticated
1616        // sample distributions (silhouette ones) using the cpu and the jittered once on the GPU
1617        // in order that thios scheme is working well the gpu render buffer should run in a separate
1618        // thread than the cpu sampler, which would not be such a big problem....
1619
1620        // disable alpha test again
1621        glDisable(GL_ALPHA_TEST);
1622}
1623
1624
1625void GlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject,
1626                                                                                                        const Vector3 viewPoint,
1627                                                                                                        Beam &beam,
1628                                                                                                        const int samples,
1629                                                    BeamSampleStatistics &stat)
1630{
1631    // 1. setup the view port to match the desired samples
1632        glViewport(0, 0, samples, samples);
1633
1634        // 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox
1635        SetupProjectionForViewPoint(viewPoint, beam, sourceObject);
1636
1637
1638        // 3. reset z-buffer to 0 and render the source object for the beam
1639        //    with glCullFace(Enabled) and glFrontFace(GL_CW)
1640        //    save result to the front depth map
1641        //    the front depth map holds ray origins
1642
1643
1644        // front depth buffer must be initialised to 0
1645        float clearDepth;
1646       
1647        glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
1648        glClearDepth(0.0f);
1649        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1650
1651
1652        //glFrontFace(GL_CW);
1653        glEnable(GL_CULL_FACE);
1654        glCullFace(GL_FRONT);
1655        glColorMask(0, 0, 0, 0);
1656       
1657
1658        // stencil is increased where the source object is located
1659        glEnable(GL_STENCIL_TEST);     
1660        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
1661        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1662
1663
1664#if 0
1665        static int glSourceObjList = -1;         
1666        if (glSourceObjList != -1)
1667        {
1668                glSourceObjList = glGenLists(1);
1669                glNewList(glSourceObjList, GL_COMPILE);
1670
1671                RenderIntersectable(sourceObject);
1672       
1673                glEndList();
1674        }
1675        glCallList(glSourceObjList);
1676
1677#else
1678        RenderIntersectable(sourceObject);
1679
1680#endif 
1681
1682         // copy contents of the front depth buffer into depth texture
1683        glBindTexture(GL_TEXTURE_2D, frontDepthMap);   
1684        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
1685
1686
1687        // reset clear function
1688        glClearDepth(clearDepth);
1689
1690       
1691       
1692        // 4. set up the termination depth buffer (= standard depth buffer)
1693        //    only rays which have non-zero entry in the origin buffer are valid since
1694        //    they realy start on the object surface (this is tagged by setting a
1695        //    stencil buffer bit at step 3).
1696       
1697        glStencilFunc(GL_EQUAL, 0x1, 0x1);
1698        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1699
1700        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1701        glDepthMask(1);
1702
1703        glEnable(GL_DEPTH_TEST);
1704               
1705        glEnable(GL_CULL_FACE);
1706        glCullFace(GL_BACK);
1707
1708        // setup front depth buffer
1709        glEnable(GL_TEXTURE_2D);
1710       
1711        // bind pixel shader implementing the front depth buffer functionality
1712        cgGLBindProgram(sCgFragmentProgram);
1713        cgGLEnableProfile(sCgFragmentProfile);
1714
1715
1716        // 5. render all objects inside the beam
1717        //    we can use id based false color to read them back for gaining the pvs
1718
1719        glColorMask(1, 1, 1, 1);
1720
1721       
1722        // if objects not stored in beam => extract objects
1723        if (beam.mFlags & !Beam::STORE_OBJECTS)
1724        {
1725                vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
1726
1727                Intersectable::NewMail();
1728                for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
1729                {
1730                        mKdTree->CollectObjects(*it, beam.mObjects);
1731                }
1732        }
1733
1734
1735        //    (objects can be compiled to a gl list now so that subsequent rendering for
1736        //    this beam is fast - the same hold for step 3)
1737        //    Afterwards we have two depth buffers defining the ray origin and termination
1738       
1739
1740#if 0
1741        static int glObjList = -1;
1742        if (glObjList != -1)
1743        {
1744                glObjList = glGenLists(1);
1745                glNewList(glObjList, GL_COMPILE);
1746       
1747                ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
1748                for (it = beam.mObjects.begin(); it != it_end; ++ it)
1749                {
1750                        // render all objects except the source object
1751                        if (*it != sourceObject)
1752                                RenderIntersectable(*it);
1753                }
1754               
1755                glEndList();
1756        }
1757
1758        glCallList(glObjList);
1759#else
1760        ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
1761        for (it = beam.mObjects.begin(); it != it_end; ++ it)
1762        {       
1763                // render all objects except the source object
1764                if (*it != sourceObject)
1765                        RenderIntersectable(*it);
1766        }
1767#endif
1768       
1769   
1770
1771        // 6. Use occlusion queries for all viewcell meshes associated with the beam ->
1772        //     a fragment passes if the corresponding stencil fragment is set and its depth is
1773        //     between origin and termination buffer
1774
1775        // create new queries if necessary
1776        GenQueries((int)beam.mViewCells.size());
1777
1778        // check whether any backfacing polygon would pass the depth test?
1779        // matt: should check both back /front facing because of dual depth buffer
1780        // and danger of cutting the near plane with front facing polys.
1781       
1782        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1783        glDepthMask(GL_FALSE);
1784        glDisable(GL_CULL_FACE);
1785
1786 
1787        ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end();
1788
1789        int queryIdx = 0;
1790
1791        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
1792        {
1793                glBeginOcclusionQueryNV(sQueries[queryIdx ++]);
1794
1795                RenderIntersectable(*vit);
1796               
1797                glEndOcclusionQueryNV();
1798        }
1799
1800
1801
1802        // at this point, if possible, go and do some other computation
1803
1804
1805       
1806        // 7. The number of visible pixels is the number of sample rays which see the source
1807        //    object from the corresponding viewcell -> remember these values for later update
1808        //   of the viewcell pvs - or update immediately?
1809
1810        queryIdx = 0;
1811        unsigned int pixelCount;
1812
1813        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
1814        {
1815                // fetch queries
1816                glGetOcclusionQueryuivNV(sQueries[queryIdx ++],
1817                                                                 GL_PIXEL_COUNT_NV,
1818                                                                 &pixelCount);
1819                if (pixelCount)
1820                        Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl;
1821        }
1822       
1823
1824        // 8. Copmpute rendering statistics
1825        // In general it is not neccessary to remember to extract all the rays cast. I hope it
1826        // would be sufficient to gain only the intergral statistics about the new contributions
1827        // and so the rss tree would actually store no new rays (only the initial ones)
1828        // the subdivision of the tree would only be driven by the statistics (the glrender could
1829        // evaluate the contribution entropy for example)
1830        // However might be an option to extract/store only those the rays which made a contribution
1831        // (new viewcell has been discovered) or relative contribution greater than a threshold ...
1832
1833        ObjectContainer pvsObj;
1834        stat.pvsSize = ComputePvs(beam.mObjects, pvsObj);
1835       
1836        // to gain ray source and termination
1837        // copy contents of ray termination buffer into depth texture
1838        // and compare with ray source buffer
1839#if 0
1840        VssRayContainer rays;
1841
1842        glBindTexture(GL_TEXTURE_2D, backDepthMap);     
1843        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
1844
1845        ComputeRays(Intersectable *sourceObj, rays);
1846
1847#endif
1848
1849
1850
1851        //-- cleanup
1852
1853
1854        // reset gl state
1855        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1856        glDepthMask(GL_TRUE);
1857        glEnable(GL_CULL_FACE);
1858        glDisable(GL_STENCIL_TEST);
1859        cgGLDisableProfile(sCgFragmentProfile);
1860        glDisable(GL_TEXTURE_2D);
1861
1862        // remove objects from beam
1863        if (beam.mFlags & !Beam::STORE_OBJECTS)
1864                beam.mObjects.clear();
1865}
1866
1867
1868void GlRendererBuffer::GenQueries(const int numQueries)
1869{
1870        if ((int)sQueries.size() < numQueries)
1871        {
1872                const int n = numQueries - (int)sQueries.size();
1873                unsigned int *newQueries = new unsigned int[n];
1874
1875                glGenOcclusionQueriesNV(n, (unsigned int *)newQueries);
1876
1877                for (int i = 0; i < n; ++ i)
1878                {
1879                        sQueries.push_back(newQueries[i]);
1880                }
1881
1882                delete [] newQueries;
1883        }
1884}
1885
1886
1887void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint,
1888                                                                                                   const Beam &beam,
1889                                                                                                   Intersectable *sourceObject)
1890{
1891        float left, right, bottom, top, znear, zfar;
1892
1893        beam.ComputePerspectiveFrustum(left, right, bottom, top, znear, zfar,
1894                                                                   mSceneGraph->GetBox());
1895
1896        //Debug << left << " " << right << " " << bottom << " " << top << " " << znear << " " << zfar << endl;
1897        glMatrixMode(GL_PROJECTION);
1898        glLoadIdentity();
1899        glFrustum(left, right, bottom, top, znear, zfar);
1900        //glFrustum(-1, 1, -1, 1, 1, 20000);
1901
1902    const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3f;
1903        const Vector3 up =
1904                Normalize(CrossProd(beam.mPlanes[0].mNormal, beam.mPlanes[4].mNormal));
1905
1906#ifdef _DEBUG
1907        Debug << "view point: " << viewPoint << endl;
1908        Debug << "eye: " << center << endl;
1909        Debug << "up: " << up << endl;
1910#endif
1911
1912        glMatrixMode(GL_MODELVIEW);
1913        glLoadIdentity();
1914        gluLookAt(viewPoint.x, viewPoint.y, viewPoint.z,
1915                          center.x, center.y, center.z,                   
1916                          up.x, up.y, up.z);
1917}               
1918
1919 
1920void GlRendererBuffer::InitGL()
1921{
1922 makeCurrent();
1923 GlRenderer::InitGL();
1924
1925#if 1
1926        // initialise dual depth buffer textures
1927        glGenTextures(1, &frontDepthMap);
1928        glBindTexture(GL_TEXTURE_2D, frontDepthMap);
1929       
1930        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
1931                depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
1932        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1933        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1934        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1935        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1936
1937        glGenTextures(1, &backDepthMap);
1938        glBindTexture(GL_TEXTURE_2D, backDepthMap);
1939       
1940        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
1941                depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
1942        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1943        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1944        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1945        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1946
1947        // cg initialization
1948        cgSetErrorCallback(handleCgError);
1949        sCgContext = cgCreateContext();
1950       
1951        if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
1952                sCgFragmentProfile = CG_PROFILE_ARBFP1;
1953        else
1954        {
1955          // try FP30
1956          if (cgGLIsProfileSupported(CG_PROFILE_FP30))
1957            sCgFragmentProfile = CG_PROFILE_FP30;
1958          else
1959          {
1960                  Debug << "Neither arbfp1 or fp30 fragment profiles supported on this system" << endl;
1961                  exit(1);
1962          }
1963  }
1964
1965
1966 sCgFragmentProgram = cgCreateProgramFromFile(sCgContext,
1967                                                                                           CG_SOURCE, "../src/dual_depth.cg",
1968                                                                                           sCgFragmentProfile,
1969                                                                                           NULL,
1970                                                                                           NULL);
1971
1972  if (!cgIsProgramCompiled(sCgFragmentProgram))
1973          cgCompileProgram(sCgFragmentProgram);
1974
1975  cgGLLoadProgram(sCgFragmentProgram);
1976  cgGLBindProgram(sCgFragmentProgram);
1977
1978  Debug << "---- PROGRAM BEGIN ----\n" <<
1979          cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
1980
1981#endif
1982  doneCurrent();
1983}
1984
1985
1986void GlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays)
1987{
1988        for (int i = 0; i < depthMapSize * depthMapSize; ++ i)
1989        {
1990                //todo glGetTexImage()
1991        }
1992}
1993
1994
1995
1996inline bool ilt(Intersectable *obj1, Intersectable *obj2)
1997{
1998        return obj1->mId < obj2->mId;
1999}
2000
2001
2002int GlRendererBuffer::ComputePvs(ObjectContainer &objects,
2003                                                                 ObjectContainer &pvs) const
2004{
2005        int pvsSize = 0;
2006        QImage image = toImage();
2007        Intersectable::NewMail();
2008
2009        std::stable_sort(objects.begin(), objects.end(), ilt);
2010
2011        MeshInstance dummy(NULL);
2012
2013        Intersectable *obj = NULL;
2014                       
2015        for (int x = 0; x < image.width(); ++ x)
2016        {
2017                for (int y = 0; y < image.height(); ++ y)
2018                {
2019                        QRgb pix = image.pixel(x, y);
2020                        const int id = GetId(qRed(pix), qGreen(pix), qBlue(pix));
2021
2022                        dummy.SetId(id);
2023
2024                        ObjectContainer::iterator oit =
2025                                lower_bound(objects.begin(), objects.end(), &dummy, ilt);
2026                       
2027                       
2028                        if (//(oit != oit.end()) &&
2029                                ((*oit)->GetId() == id) &&
2030                                !obj->Mailed())
2031                        {
2032                                obj = *oit;
2033                                obj->Mail();
2034                                ++ pvsSize;
2035                                pvs.push_back(obj);
2036                        }
2037                }
2038        }
2039
2040        return pvsSize;
2041}
2042
2043/***********************************************************************/
2044/*                     GlDebuggerWidget implementation                             */
2045/***********************************************************************/
2046
2047
2048GlDebuggerWidget::GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent)
2049      : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf)
2050{
2051        // create the pbuffer
2052    //pbuffer = new QGLPixelBuffer(QSize(512, 512), format(), this);
2053    timerId = startTimer(20);
2054    setWindowTitle(("OpenGL pbuffers"));
2055}
2056
2057
2058GlDebuggerWidget::~GlDebuggerWidget()
2059{
2060 mRenderBuffer->releaseFromDynamicTexture();
2061   glDeleteTextures(1, &dynamicTexture);
2062         
2063         DEL_PTR(mRenderBuffer);
2064}
2065
2066
2067void GlDebuggerWidget::initializeGL()
2068{
2069        glMatrixMode(GL_PROJECTION);
2070        glLoadIdentity();
2071
2072        glFrustum(-1, 1, -1, 1, 10, 100);
2073        glTranslatef(-0.5f, -0.5f, -0.5f);
2074        glTranslatef(0.0f, 0.0f, -15.0f);
2075        glMatrixMode(GL_MODELVIEW);
2076
2077        glEnable(GL_CULL_FACE);
2078        initCommon();
2079        initPbuffer();
2080
2081}
2082
2083
2084void GlDebuggerWidget::resizeGL(int w, int h)
2085{
2086        glViewport(0, 0, w, h);
2087}
2088
2089
2090void GlDebuggerWidget::paintGL()
2091{
2092        // draw a spinning cube into the pbuffer..
2093        mRenderBuffer->makeCurrent();
2094       
2095        BeamSampleStatistics stats;
2096        mRenderBuffer->SampleBeamContributions(mSourceObject, mBeam, mSamples, stats);
2097
2098        glFlush();
2099
2100        // rendering directly to a texture is not supported on X11, unfortunately
2101    mRenderBuffer->updateDynamicTexture(dynamicTexture);
2102   
2103    // and use the pbuffer contents as a texture when rendering the
2104    // background and the bouncing cubes
2105    makeCurrent();
2106    glBindTexture(GL_TEXTURE_2D, dynamicTexture);
2107    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2108
2109    // draw the background
2110    glMatrixMode(GL_MODELVIEW);
2111    glPushMatrix();
2112    glLoadIdentity();
2113    glMatrixMode(GL_PROJECTION);
2114    glPushMatrix();
2115    glLoadIdentity();
2116
2117        glPopMatrix();
2118        glMatrixMode(GL_MODELVIEW);
2119        glPopMatrix();
2120}
2121
2122
2123void GlDebuggerWidget::initPbuffer()
2124{
2125        // set up the pbuffer context
2126    mRenderBuffer->makeCurrent();
2127        /*mRenderBuffer->InitGL();
2128
2129        glViewport(0, 0, mRenderBuffer->size().width(), mRenderBuffer->size().height());
2130        glMatrixMode(GL_PROJECTION);
2131        glLoadIdentity();
2132        glOrtho(-1, 1, -1, 1, -99, 99);
2133        glTranslatef(-0.5f, -0.5f, 0.0f);
2134        glMatrixMode(GL_MODELVIEW);
2135        glLoadIdentity();
2136
2137        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/
2138       
2139        // generate a texture that has the same size/format as the pbuffer
2140    dynamicTexture = mRenderBuffer->generateDynamicTexture();
2141
2142        // bind the dynamic texture to the pbuffer - this is a no-op under X11
2143        mRenderBuffer->bindToDynamicTexture(dynamicTexture);
2144        makeCurrent();
2145}
2146
2147void GlDebuggerWidget::initCommon()
2148{
2149        glEnable(GL_TEXTURE_2D);
2150        glEnable(GL_DEPTH_TEST);
2151
2152        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
2153}
Note: See TracBrowser for help on using the repository browser.