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

Revision 859, 53.5 KB checked in by bittner, 18 years ago (diff)

apply filter routine for working modules

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