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

Revision 746, 48.7 KB checked in by bittner, 18 years ago (diff)

visualization of the render cost and pvs sizes for viewcells

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