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

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