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

Revision 713, 40.6 KB checked in by bittner, 18 years ago (diff)

visibility filter used in glrenderer

  • 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 = false;
57  mSnapPrefix = "";
58
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)
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        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
205
206}
207
208void
209GlRendererWidget::RenderInfo()
210{
211  QString s;
212  int vc = 0;
213  if (mViewCellsManager)
214        vc = mViewCellsManager->GetViewCells().size();
215  s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f) viewcells:%04d",
216                        mFrame,
217                        mViewPoint.x,
218                        mViewPoint.y,
219                        mViewPoint.z,
220                        mViewDirection.x,
221                        mViewDirection.y,
222                        mViewDirection.z,
223                        vc
224                        );
225  renderText(0,20,s);
226}
227
228
229void
230GlRenderer::SetupProjection(const int w, const int h)
231{
232  glViewport(0, 0, w, h);
233  glMatrixMode(GL_PROJECTION);
234  glLoadIdentity();
235  gluPerspective(70.0, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
236  glMatrixMode(GL_MODELVIEW);
237}
238
239void
240GlRenderer::SetupCamera()
241{
242  Vector3 target = mViewPoint + mViewDirection;
243  Vector3 up(0,1,0);
244 
245  glLoadIdentity();
246  gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z,
247                        target.x, target.y, target.z,
248                        up.x, up.y, up.z);
249}
250
251void
252GlRendererBuffer::RandomViewPoint()
253{
254 
255 
256  // do not use this function since it could return different viewpoints for
257  // different executions of the algorithm
258
259  //mViewCellsManager->GetViewPoint(mViewPoint);
260
261  while (1) {
262        Vector3 pVector = Vector3(halton.GetNumber(1),
263                                                          halton.GetNumber(2),
264                                                          halton.GetNumber(3));
265       
266        mViewPoint =  mSceneGraph->GetBox().GetPoint(pVector);
267        ViewCell *v = mViewCellsManager->GetViewCell(mViewPoint);
268        if (v && v->GetValid())
269          break;
270        // generate a new vector
271        halton.GenerateNext();
272  }
273 
274 
275  Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4),
276                                                        M_PI*halton.GetNumber(5),
277                                                        0.0f);
278 
279  mViewDirection = Normalize(Vector3(sin(dVector.x),
280                                                                         //                                                                      cos(dVector.y),
281                                                                         0.0f,
282                                                                         cos(dVector.x)));
283  halton.GenerateNext();
284}
285
286
287GlRendererBuffer::GlRendererBuffer(const int w,
288                                                                   const int h,
289                                                                   SceneGraph *sceneGraph,
290                                                                   ViewCellsManager *viewcells,
291                                                                   KdTree *tree):
292QGLPixelBuffer(QSize(w, h)), GlRenderer(sceneGraph, viewcells, tree) {
293 
294 environment->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames);
295   mPvsErrorBuffer.resize(mPvsStatFrames);
296         ClearErrorBuffer();
297           
298           InitGL();
299                 
300                 }
301
302float
303GlRendererBuffer::GetPixelError(int &pvsSize)
304{
305  float pErrorPixels = -1.0f;
306 
307  glReadBuffer(GL_BACK);
308 
309  //  mUseFalseColors = true;
310 
311  mUseFalseColors = false;
312
313  static int query = -1;
314  unsigned int pixelCount;
315
316  if (query == -1)
317        glGenOcclusionQueriesNV(1, (unsigned int *)&query);
318
319  if (mDetectEmptyViewSpace) {
320        // now check whether any backfacing polygon would pass the depth test
321        SetupCamera();
322        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
323        glEnable( GL_CULL_FACE );
324       
325        RenderScene();
326       
327        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
328        glDepthMask(GL_FALSE);
329        glDisable( GL_CULL_FACE );
330       
331        glBeginOcclusionQueryNV(query);
332       
333        RenderScene();
334       
335        glEndOcclusionQueryNV();
336       
337        // at this point, if possible, go and do some other computation
338        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
339        glDepthMask(GL_TRUE);
340        glEnable( GL_CULL_FACE );
341       
342        // reenable other state
343        glGetOcclusionQueryuivNV(query,
344                                                         GL_PIXEL_COUNT_NV,
345                                                         &pixelCount);
346       
347        if (pixelCount > 0)
348          return -1.0f; // backfacing polygon found -> not a valid viewspace sample
349  } else
350        glDisable( GL_CULL_FACE );
351       
352
353  ViewCell *viewcell = NULL;
354 
355  PrVs prvs;
356  //  mViewCellsManager->SetMaxFilterSize(1);
357  mViewCellsManager->GetPrVS(mViewPoint, prvs);
358  viewcell = prvs.mViewCell;
359 
360  //  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
361  pvsSize = 0;
362  if (viewcell) {
363        SetupCamera();
364        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
365
366        glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
367
368        // Render PVS
369        std::map<Intersectable *,
370          PvsData<Intersectable *>,
371          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
372
373        pvsSize = viewcell->GetPvs().mEntries.size();
374       
375        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
376          Intersectable *object = (*it).first;
377          RenderIntersectable(object);
378        }
379
380        //      glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
381        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
382        mUseFalseColors = true;
383
384        glBeginOcclusionQueryNV(query);
385
386        SetupCamera();
387
388        RenderScene();
389       
390        glEndOcclusionQueryNV();
391       
392
393        unsigned int pixelCount;
394        // reenable other state
395        glGetOcclusionQueryuivNV(query,
396                                                         GL_PIXEL_COUNT_NV,
397                                                         &pixelCount);
398       
399        pErrorPixels = ((float)pixelCount)/(GetWidth()*GetHeight());
400        if (mSnapErrorFrames && pErrorPixels > 0.01) {
401         
402          char filename[256];
403          sprintf(filename, "error-frame-%04d-%0.5f.png", mFrame, pErrorPixels);
404          QImage im = toImage();
405          im.save(mSnapPrefix + filename, "PNG");
406          if (1) { //0 && mFrame == 1543) {
407                int x,y;
408                int lastIndex = -1;
409                for (y=0; y < im.height(); y++)
410                  for (x=0; x < im.width(); x++) {
411                        QRgb p = im.pixel(x,y);
412                        int index = qRed(p) + (qGreen(p)<<8) + (qBlue(p)<<16);
413                        if (qGreen(p) != 255 && index!=0) {
414                          if (index != lastIndex) {
415                                Debug<<"ei="<<index<<" ";
416                                lastIndex = index;
417                          }
418                        }
419                  }
420          }
421
422
423          mUseFalseColors = false;
424          glPushAttrib(GL_CURRENT_BIT);
425          glColor3f(0,1,0);
426          glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
427          SetupCamera();
428          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
429         
430          // Render PVS
431          std::map<Intersectable *,
432                PvsData<Intersectable *>,
433                LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
434         
435          for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
436                Intersectable *object = (*it).first;
437                RenderIntersectable(object);
438          }
439
440          im = toImage();
441          sprintf(filename, "error-frame-%04d-%0.5f-pvs.png", mFrame, pErrorPixels);
442          im.save(mSnapPrefix + filename, "PNG");
443          glPopAttrib();
444        }
445        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
446  }
447
448  if (viewcell)
449        mViewCellsManager->DeleteLocalMergeTree(viewcell);
450 
451  return pErrorPixels;
452}
453
454
455void
456GlRendererWidget::SetupProjection(const int w, const int h)
457{
458  if (!mTopView)
459        GlRenderer::SetupProjection(w, h);
460  else {
461        glViewport(0, 0, w, h);
462        glMatrixMode(GL_PROJECTION);
463        glLoadIdentity();
464        gluPerspective(50.0, 1.0, 0.1, 20.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
465        glMatrixMode(GL_MODELVIEW);
466  }
467}
468
469float
470GlRendererWidget::RenderErrors()
471{
472  float pErrorPixels = -1.0f;
473
474  glReadBuffer(GL_BACK);
475 
476  mUseFalseColors = true;
477
478  SetupCamera();
479  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
480 
481  double eq[4];
482  eq[0] = mSceneCutPlane.mNormal.x;
483  eq[1] = mSceneCutPlane.mNormal.y;
484  eq[2] = mSceneCutPlane.mNormal.z;
485  eq[3] = mSceneCutPlane.mD;
486 
487  if (mCutScene) {
488        glClipPlane(GL_CLIP_PLANE0, eq);
489    glEnable(GL_CLIP_PLANE0);
490  }
491 
492  if (mDetectEmptyViewSpace)
493        glEnable( GL_CULL_FACE );
494  else
495        glDisable( GL_CULL_FACE );
496
497  ObjectContainer::const_iterator oi = mObjects.begin();
498  for (; oi != mObjects.end(); oi++)
499        RenderIntersectable(*oi);
500
501  ViewCell *viewcell;
502  //  viewcell = mViewCellsManager->GetViewCell(mViewPoint);
503
504  PrVs prvs;
505  //  mViewCellsManager->SetMaxFilterSize(1);
506  mViewCellsManager->GetPrVS(mViewPoint, prvs);
507  viewcell = prvs.mViewCell;
508 
509  QImage im1, im2;
510  QImage diff;
511 
512  if (viewcell) {
513        // read back the texture
514        im1 = grabFrameBuffer(true);
515       
516        SetupCamera();
517        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
518       
519        std::map<Intersectable *,
520          PvsData<Intersectable *>,
521          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
522       
523        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
524          Intersectable *object = (*it).first;
525          RenderIntersectable(object);
526        }
527
528        // read back the texture
529        im2 = grabFrameBuffer(true);
530       
531        diff = im1;
532        int x, y;
533        int errorPixels = 0;
534       
535        for (y = 0; y < im1.height(); y++)
536          for (x = 0; x < im1.width(); x++)
537                if (im1.pixel(x, y) == im2.pixel(x, y))
538                  diff.setPixel(x, y, qRgba(0,0,0,0));
539                else {
540                  diff.setPixel(x, y, qRgba(255,128,128,255));
541                  errorPixels++;
542                 
543                }
544        pErrorPixels = ((float)errorPixels)/(im1.height()*im1.width());
545  }
546
547  // now render the pvs again
548  SetupCamera();
549  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
550  mUseFalseColors = false;
551       
552  oi = mObjects.begin();
553  for (; oi != mObjects.end(); oi++)
554        RenderIntersectable(*oi);
555
556  // now render im1
557  if (viewcell) {
558        if (1 || mTopView) {
559          mWireFrame = true;
560          RenderIntersectable(viewcell);
561          mWireFrame = false;
562        }
563       
564        // init ortographic projection
565        glMatrixMode(GL_PROJECTION);
566        glPushMatrix();
567       
568        glLoadIdentity();
569        gluOrtho2D(0, 1.0f, 0, 1.0f);
570       
571        glMatrixMode(GL_MODELVIEW);
572        glLoadIdentity();
573       
574        bindTexture(diff);
575       
576        glPushAttrib(GL_ENABLE_BIT);
577        glEnable( GL_ALPHA_TEST );
578        glDisable( GL_CULL_FACE );
579        glAlphaFunc( GL_GREATER, 0.5 );
580       
581        glEnable( GL_TEXTURE_2D );
582        glBegin(GL_QUADS);
583       
584        glTexCoord2f(0,0);
585        glVertex3f(0,0,0);
586       
587        glTexCoord2f(1,0);
588        glVertex3f( 1, 0, 0);
589       
590        glTexCoord2f(1,1);
591        glVertex3f( 1, 1, 0);
592       
593        glTexCoord2f(0,1);
594        glVertex3f(0, 1, 0);
595        glEnd();
596       
597        glPopAttrib();
598       
599        // restore the projection matrix
600        glMatrixMode(GL_PROJECTION);
601        glPopMatrix();
602        glMatrixMode(GL_MODELVIEW);
603  }
604
605  glDisable(GL_CLIP_PLANE0);
606
607  if (viewcell)
608        mViewCellsManager->DeleteLocalMergeTree(viewcell);
609
610  return pErrorPixels;
611}
612
613
614bool
615GlRenderer::RenderScene()
616{
617  static int glList = -1;
618  if (glList == -1)
619  {
620        glList = glGenLists(1);
621        glNewList(glList, GL_COMPILE);
622        ObjectContainer::const_iterator oi = mObjects.begin();
623        for (; oi != mObjects.end(); oi++)
624          RenderIntersectable(*oi);
625        glEndList();
626  }
627 
628  glCallList(glList);
629 
630  return true;
631}
632
633
634void
635GlRendererBuffer::ClearErrorBuffer()
636{
637  for (int i=0; i < mPvsStatFrames; i++) {
638        mPvsErrorBuffer[i].mError = 1.0f;
639  }
640}
641
642
643void
644GlRendererBuffer::EvalPvsStat()
645{
646  mPvsStat.Reset();
647  halton.Reset();
648
649  makeCurrent();
650  SetupProjection(GetWidth(), GetHeight());
651 
652  for (int i=0; i < mPvsStatFrames; i++) {
653        float err;
654        // set frame id for saving the error buffer
655        mFrame = i;
656        RandomViewPoint();
657
658        // atlanta problematic frames: 325 525 691 1543
659#if 0
660        if (mFrame != 325 &&
661                mFrame != 525 &&
662                mFrame != 691 &&
663                mFrame != 1543)
664          mPvsErrorBuffer[i] = -1;
665        else {
666          Debug<<"frame ="<<mFrame<<" vp="<<mViewPoint<<" vd="<<mViewDirection<<endl;
667        }
668#endif
669        if (mPvsErrorBuffer[i].mError > 0.0f) {
670          int pvsSize;
671          float error = GetPixelError(pvsSize);
672          mPvsErrorBuffer[i].mError = error;
673          mPvsErrorBuffer[i].mPvsSize = pvsSize;
674
675          cout<<"("<<i<<","<<mPvsErrorBuffer[i].mError<<")";
676          //      swapBuffers();
677        }
678       
679        err = mPvsErrorBuffer[i].mError;
680       
681        if (err >= 0.0f) {
682          if (err > mPvsStat.maxError)
683                mPvsStat.maxError = err;
684          mPvsStat.sumError += err;
685          mPvsStat.sumPvsSize += mPvsErrorBuffer[i].mPvsSize;
686         
687          if (err == 0.0f)
688                mPvsStat.errorFreeFrames++;
689          mPvsStat.frames++;
690        }
691  }
692
693  glFinish();
694  doneCurrent();
695
696  cout<<endl<<flush;
697  //  mRenderingFinished.wakeAll();
698}
699
700
701
702
703
704void
705GlRendererWidget::mousePressEvent(QMouseEvent *e)
706{
707  int x = e->pos().x();
708  int y = e->pos().y();
709
710  mousePoint.x = x;
711  mousePoint.y = y;
712 
713}
714
715void
716GlRendererWidget::mouseMoveEvent(QMouseEvent *e)
717{
718  float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3;
719  float TURN_SENSITIVITY=0.1f;
720  float TILT_SENSITIVITY=32.0 ;
721  float TURN_ANGLE= M_PI/36.0 ;
722
723  int x = e->pos().x();
724  int y = e->pos().y();
725 
726  if (e->modifiers() & Qt::ControlModifier) {
727        mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0;
728        mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0;
729  } else {
730        mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY);
731        float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY;
732        float angle = atan2(mViewDirection.x, mViewDirection.z);
733        mViewDirection.x = sin(angle+adiff);
734        mViewDirection.z = cos(angle+adiff);
735  }
736 
737  mousePoint.x = x;
738  mousePoint.y = y;
739 
740  updateGL();
741}
742
743void
744GlRendererWidget::mouseReleaseEvent(QMouseEvent *)
745{
746
747
748}
749
750void
751GlRendererWidget::resizeGL(int w, int h)
752{
753  SetupProjection(w, h);
754  updateGL();
755}
756
757void
758GlRendererWidget::paintGL()
759{
760  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
761
762 
763  if (!mRenderViewCells) {
764        RenderErrors();
765        RenderInfo();
766  } else {
767        RenderViewCells();
768
769        mWireFrame = true;
770        RenderScene();
771        mWireFrame = false;
772        RenderInfo();
773  }
774
775  mFrame++;
776}
777
778
779void
780GlRendererWidget::SetupCamera()
781{
782  if (!mTopView)
783        GlRenderer::SetupCamera();
784  else {
785        if (0) {
786          float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05;
787          Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x,
788                                                                                          -1,
789                                                                                          mViewDirection.y);
790         
791          Vector3 target = mViewPoint + dist*mViewDirection;
792          Vector3 up(0,1,0);
793         
794          glLoadIdentity();
795          gluLookAt(pos.x, pos.y, pos.z,
796                                target.x, target.y, target.z,
797                                up.x, up.y, up.z);
798        } else {
799          float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*mTopDistance;
800          Vector3 pos = mViewPoint  + dist*Vector3(0,
801                                                                                           1,
802                                                                                           0);
803         
804          Vector3 target = mViewPoint;
805          Vector3 up(mViewDirection.x, 0, mViewDirection.z);
806         
807          glLoadIdentity();
808          gluLookAt(pos.x, pos.y, pos.z,
809                                target.x, target.y, target.z,
810                                up.x, up.y, up.z);
811         
812        }
813  }
814
815}
816
817void
818GlRendererWidget::keyPressEvent ( QKeyEvent * e )
819{
820  switch (e->key()) {
821  case Qt::Key_T:
822        mTopView = !mTopView;
823        SetupProjection(width(), height());
824        updateGL();
825        break;
826  case Qt::Key_V:
827        mRenderViewCells = !mRenderViewCells;
828        updateGL();
829        break;
830  default:
831        e->ignore();
832        break;
833  }
834}
835
836 
837RendererControlWidget::RendererControlWidget(QWidget * parent, Qt::WFlags f):
838  QWidget(parent, f)
839{
840
841  QVBoxLayout *vl = new QVBoxLayout;
842  setLayout(vl);
843 
844  QWidget *vbox = new QGroupBox("ViewCells", this);
845  layout()->addWidget(vbox);
846 
847  vl = new QVBoxLayout;
848  vbox->setLayout(vl);
849
850  QLabel *label = new QLabel("Granularity");
851  vbox->layout()->addWidget(label);
852
853  QSlider *slider = new QSlider(Qt::Horizontal, vbox);
854  vl->addWidget(slider);
855  slider->show();
856  slider->setRange(1, 200);
857  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
858  slider->setValue(200);
859
860  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetViewCellGranularity(int)));
861
862  label = new QLabel("Filter size");
863  vbox->layout()->addWidget(label);
864 
865  slider = new QSlider(Qt::Horizontal, vbox);
866  vbox->layout()->addWidget(slider);
867  slider->show();
868  slider->setRange(1, 100);
869  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
870  slider->setValue(3);
871 
872  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetVisibilityFilterSize(int)));
873
874
875
876  QWidget *hbox = new QWidget(vbox);
877  vl->addWidget(hbox);
878  QHBoxLayout *hlayout = new QHBoxLayout;
879  hbox->setLayout(hlayout);
880 
881  QCheckBox *cb = new QCheckBox("Show viewcells", hbox);
882  hlayout->addWidget(cb);
883  cb->setChecked(false);
884  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowViewCells(bool)));
885
886  vbox->resize(800,100);
887
888 
889  vbox = new QGroupBox("Rendering", this);
890  layout()->addWidget(vbox);
891 
892  vl = new QVBoxLayout;
893  vbox->setLayout(vl);
894 
895  slider = new QSlider(Qt::Horizontal, vbox);
896  vbox->layout()->addWidget(slider);
897  slider->show();
898  slider->setRange(0, 1000);
899  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
900  slider->setValue(1000);
901
902  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSceneCut(int)));
903
904
905  cb = new QCheckBox("Cut view cells", vbox);
906  vbox->layout()->addWidget(cb);
907  cb->setChecked(false);
908  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutViewCells(bool)));
909
910  cb = new QCheckBox("Cut scene", vbox);
911  vbox->layout()->addWidget(cb);
912  cb->setChecked(false);
913  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutScene(bool)));
914
915 
916  slider = new QSlider(Qt::Horizontal, vbox);
917  vbox->layout()->addWidget(slider);
918  slider->show();
919  slider->setRange(1, 1000);
920  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
921  slider->setValue(500);
922 
923  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetTopDistance(int)));
924
925
926
927 
928  cb = new QCheckBox("Top View", vbox);
929  vbox->layout()->addWidget(cb);
930  cb->setChecked(false);
931  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetTopView(bool)));
932 
933  setWindowTitle("Preprocessor Control Widget");
934  adjustSize();
935}
936
937GlRendererWidget::GlRendererWidget(SceneGraph *sceneGraph,
938                                                                   ViewCellsManager *viewcells,
939                                                                   KdTree *tree,
940                                                                   QWidget * parent,
941                                                                   const QGLWidget * shareWidget,
942                                                                   Qt::WFlags f
943                                                                   )
944  :
945  GlRenderer(sceneGraph, viewcells, tree), QGLWidget(parent, shareWidget, f)
946{
947  mTopView = false;
948  mRenderViewCells = false;
949  mTopDistance = 1.0f;
950  mCutViewCells = false;
951  mCutScene = false;
952 
953  RendererControlWidget *cw = new RendererControlWidget(NULL);
954  connect(cw, SIGNAL(SetViewCellGranularity(int)), this, SLOT(SetViewCellGranularity(int)));
955  connect(cw, SIGNAL(SetSceneCut(int)), this, SLOT(SetSceneCut(int)));
956  connect(cw, SIGNAL(SetTopDistance(int)), this, SLOT(SetTopDistance(int)));
957
958  //connect(cw, SIGNAL(SetViewCellGranularity(int)), this, SLOT(SetMaxFilterSize(int)));
959  //  connect(cw, SIGNAL(SetVisibilityFilterSize(int)), this, SLOT(SetVisibilityFilterSize(int)));
960  //connect(cw, SIGNAL(SetVisibilityFilterSize(int)), this, SLOT(SetViewCellGranularity(int)));
961
962  connect(cw, SIGNAL(SetShowViewCells(bool)), this, SLOT(SetShowViewCells(bool)));
963  connect(cw, SIGNAL(SetTopView(bool)), this, SLOT(SetTopView(bool)));
964  connect(cw, SIGNAL(SetCutViewCells(bool)), this, SLOT(SetCutViewCells(bool)));
965  connect(cw, SIGNAL(SetCutScene(bool)), this, SLOT(SetCutScene(bool)));
966 
967  cw->show();
968}
969
970void
971GlRendererWidget::SetViewCellGranularity(int number)
972{
973  if (mViewCellsManager)
974        mViewCellsManager->SetMaxFilterSize(number);
975  //  mViewCellsManager->CollectViewCells(number);
976  updateGL();
977}
978
979void
980GlRendererWidget::SetVisibilityFilterSize(int number)
981{
982  if (mViewCellsManager)
983        mViewCellsManager->SetMaxFilterSize(number);
984  updateGL();
985}
986
987void
988GlRendererWidget::SetSceneCut(int number)
989{
990  // assume the cut plane can only be aligned with xz plane
991  // shift it along y according to number, which is percentage of the bounding
992  // box position
993  if (mViewCellsManager) {
994        AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
995        Vector3 p = box.Min() + (number/1000.0f)*box.Max();
996        mSceneCutPlane.mNormal = Vector3(0,-1,0);
997        mSceneCutPlane.mD = -DotProd(mSceneCutPlane.mNormal, p);
998        updateGL();
999  }
1000}
1001
1002void
1003GlRendererWidget::SetTopDistance(int number)
1004{
1005  mTopDistance = number/1000.0f;
1006  updateGL();
1007}
1008
1009void
1010GlRendererWidget::RenderViewCells()
1011{
1012  mUseFalseColors = true;
1013
1014  SetupCamera();
1015  glEnable(GL_CULL_FACE);
1016  //glDisable(GL_CULL_FACE);
1017  glCullFace(GL_FRONT);
1018  double eq[4];
1019  eq[0] = mSceneCutPlane.mNormal.x;
1020  eq[1] = mSceneCutPlane.mNormal.y;
1021  eq[2] = mSceneCutPlane.mNormal.z;
1022  eq[3] = mSceneCutPlane.mD;
1023
1024  if (mCutViewCells) {
1025        glClipPlane(GL_CLIP_PLANE0, eq);
1026        glEnable(GL_CLIP_PLANE0);
1027  }
1028 
1029  int i;
1030  ViewCellContainer &viewcells = mViewCellsManager->GetViewCells();
1031  for (i=0; i < viewcells.size(); i++) {
1032        ViewCell *vc = viewcells[i];
1033        //      Mesh *m = vc->GetMesh();
1034        RgbColor c = vc->GetColor();
1035        glColor3f(c.r, c.g, c.b);
1036        RenderViewCell(vc);
1037  }
1038
1039  glDisable(GL_CLIP_PLANE0);
1040
1041}
1042
1043void GlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject,
1044                                                                                           Beam &beam,
1045                                                                                           const int desiredSamples,
1046                                                                                           BeamSampleStatistics &stat)
1047{
1048        // TODO: should be moved out of here (not to be done every time)
1049        // only back faces are interesting for the depth pass
1050        glShadeModel(GL_FLAT);
1051        glDisable(GL_LIGHTING);
1052
1053        // needed to kill the fragments for the front buffer
1054        glEnable(GL_ALPHA_TEST);
1055        glAlphaFunc(GL_GREATER, 0);
1056
1057        // assumes that the beam is constructed and contains kd-tree nodes
1058        // and viewcells which it intersects
1059 
1060 
1061        // Get the number of viewpoints to be sampled
1062        // Now it is a sqrt but in general a wiser decision could be made.
1063        // The less viewpoints the better for rendering performance, since less passes
1064        // over the beam is needed.
1065        // The viewpoints could actually be generated outside of the bounding box which
1066        // would distribute the 'efective viewpoints' of the object surface and thus
1067        // with a few viewpoints better sample the viewpoint space....
1068
1069        //TODO: comment in
1070        //int viewPointSamples = sqrt((float)desiredSamples);
1071        int viewPointSamples = max(desiredSamples / (GetWidth() * GetHeight()), 1);
1072       
1073        // the number of direction samples per pass is given by the number of viewpoints
1074        int directionalSamples = desiredSamples / viewPointSamples;
1075       
1076        Debug << "directional samples: " << directionalSamples << endl;
1077        for (int i = 0; i < viewPointSamples; ++ i)
1078        {
1079                Vector3 viewPoint = beam.mBox.GetRandomPoint();
1080               
1081                // perhaps the viewpoint should be shifted back a little bit so that it always lies
1082                // inside the source object
1083                // 'ideally' the viewpoints would be distributed on the soureObject surface, but this
1084        // would require more complicated sampling (perhaps hierarchical rejection sampling of
1085                // the object surface is an option here - only the mesh faces which are inside the box
1086                // are considered as candidates)
1087               
1088                SampleViewpointContributions(sourceObject,
1089                                                                         viewPoint,
1090                                                                         beam,
1091                                                                         directionalSamples,
1092                                                                         stat);
1093        }
1094
1095
1096        // note:
1097        // this routine would be called only if the number of desired samples is sufficiently
1098        // large - for other rss tree cells the cpu based sampling is perhaps more efficient
1099        // distributing the work between cpu and gpu would also allow us to place more sophisticated
1100        // sample distributions (silhouette ones) using the cpu and the jittered once on the GPU
1101        // in order that thios scheme is working well the gpu render buffer should run in a separate
1102        // thread than the cpu sampler, which would not be such a big problem....
1103
1104        // disable alpha test again
1105        glDisable(GL_ALPHA_TEST);
1106}
1107
1108
1109void GlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject,
1110                                                                                                        const Vector3 viewPoint,
1111                                                                                                        Beam &beam,
1112                                                                                                        const int samples,
1113                                                    BeamSampleStatistics &stat)
1114{
1115    // 1. setup the view port to match the desired samples
1116        glViewport(0, 0, samples, samples);
1117
1118        // 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox
1119        SetupProjectionForViewPoint(viewPoint, beam, sourceObject);
1120
1121
1122        // 3. reset z-buffer to 0 and render the source object for the beam
1123        //    with glCullFace(Enabled) and glFrontFace(GL_CW)
1124        //    save result to the front depth map
1125        //    the front depth map holds ray origins
1126
1127
1128        // front depth buffer must be initialised to 0
1129        float clearDepth;
1130       
1131        glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
1132        glClearDepth(0.0f);
1133        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1134
1135
1136        //glFrontFace(GL_CW);
1137        glEnable(GL_CULL_FACE);
1138        glCullFace(GL_FRONT);
1139        glColorMask(0, 0, 0, 0);
1140       
1141
1142        // stencil is increased where the source object is located
1143        glEnable(GL_STENCIL_TEST);     
1144        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
1145        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1146
1147
1148#if 0
1149        static int glSourceObjList = -1;         
1150        if (glSourceObjList != -1)
1151        {
1152                glSourceObjList = glGenLists(1);
1153                glNewList(glSourceObjList, GL_COMPILE);
1154
1155                RenderIntersectable(sourceObject);
1156       
1157                glEndList();
1158        }
1159        glCallList(glSourceObjList);
1160
1161#else
1162        RenderIntersectable(sourceObject);
1163
1164#endif 
1165
1166         // copy contents of the front depth buffer into depth texture
1167        glBindTexture(GL_TEXTURE_2D, frontDepthMap);   
1168        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
1169
1170
1171        // reset clear function
1172        glClearDepth(clearDepth);
1173
1174       
1175       
1176        // 4. set up the termination depth buffer (= standard depth buffer)
1177        //    only rays which have non-zero entry in the origin buffer are valid since
1178        //    they realy start on the object surface (this is tagged by setting a
1179        //    stencil buffer bit at step 3).
1180       
1181        glStencilFunc(GL_EQUAL, 0x1, 0x1);
1182        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1183
1184        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1185        glDepthMask(1);
1186
1187        glEnable(GL_DEPTH_TEST);
1188               
1189        glEnable(GL_CULL_FACE);
1190        glCullFace(GL_BACK);
1191
1192        // setup front depth buffer
1193        glEnable(GL_TEXTURE_2D);
1194       
1195        // bind pixel shader implementing the front depth buffer functionality
1196        cgGLBindProgram(sCgFragmentProgram);
1197        cgGLEnableProfile(sCgFragmentProfile);
1198
1199
1200        // 5. render all objects inside the beam
1201        //    we can use id based false color to read them back for gaining the pvs
1202
1203        glColorMask(1, 1, 1, 1);
1204
1205       
1206        // if objects not stored in beam => extract objects
1207        if (beam.mFlags & !Beam::STORE_OBJECTS)
1208        {
1209                vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
1210
1211                Intersectable::NewMail();
1212                for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
1213                {
1214                        mKdTree->CollectObjects(*it, beam.mObjects);
1215                }
1216        }
1217
1218
1219        //    (objects can be compiled to a gl list now so that subsequent rendering for
1220        //    this beam is fast - the same hold for step 3)
1221        //    Afterwards we have two depth buffers defining the ray origin and termination
1222       
1223
1224#if 0
1225        static int glObjList = -1;
1226        if (glObjList != -1)
1227        {
1228                glObjList = glGenLists(1);
1229                glNewList(glObjList, GL_COMPILE);
1230       
1231                ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
1232                for (it = beam.mObjects.begin(); it != it_end; ++ it)
1233                {
1234                        // render all objects except the source object
1235                        if (*it != sourceObject)
1236                                RenderIntersectable(*it);
1237                }
1238               
1239                glEndList();
1240        }
1241
1242        glCallList(glObjList);
1243#else
1244        ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
1245        for (it = beam.mObjects.begin(); it != it_end; ++ it)
1246        {       
1247                // render all objects except the source object
1248                if (*it != sourceObject)
1249                        RenderIntersectable(*it);
1250        }
1251#endif
1252       
1253   
1254
1255        // 6. Use occlusion queries for all viewcell meshes associated with the beam ->
1256        //     a fragment passes if the corresponding stencil fragment is set and its depth is
1257        //     between origin and termination buffer
1258
1259        // create new queries if necessary
1260        GenQueries((int)beam.mViewCells.size());
1261
1262        // check whether any backfacing polygon would pass the depth test?
1263        // matt: should check both back /front facing because of dual depth buffer
1264        // and danger of cutting the near plane with front facing polys.
1265       
1266        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1267        glDepthMask(GL_FALSE);
1268        glDisable(GL_CULL_FACE);
1269
1270 
1271        ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end();
1272
1273        int queryIdx = 0;
1274
1275        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
1276        {
1277                glBeginOcclusionQueryNV(sQueries[queryIdx ++]);
1278
1279                RenderIntersectable(*vit);
1280               
1281                glEndOcclusionQueryNV();
1282        }
1283
1284
1285
1286        // at this point, if possible, go and do some other computation
1287
1288
1289       
1290        // 7. The number of visible pixels is the number of sample rays which see the source
1291        //    object from the corresponding viewcell -> remember these values for later update
1292        //   of the viewcell pvs - or update immediately?
1293
1294        queryIdx = 0;
1295        unsigned int pixelCount;
1296
1297        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
1298        {
1299                // fetch queries
1300                glGetOcclusionQueryuivNV(sQueries[queryIdx ++],
1301                                                                 GL_PIXEL_COUNT_NV,
1302                                                                 &pixelCount);
1303                if (pixelCount)
1304                        Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl;
1305        }
1306       
1307
1308        // 8. Copmpute rendering statistics
1309        // In general it is not neccessary to remember to extract all the rays cast. I hope it
1310        // would be sufficient to gain only the intergral statistics about the new contributions
1311        // and so the rss tree would actually store no new rays (only the initial ones)
1312        // the subdivision of the tree would only be driven by the statistics (the glrender could
1313        // evaluate the contribution entropy for example)
1314        // However might be an option to extract/store only those the rays which made a contribution
1315        // (new viewcell has been discovered) or relative contribution greater than a threshold ...
1316
1317        ObjectContainer pvsObj;
1318        stat.pvsSize = ComputePvs(beam.mObjects, pvsObj);
1319       
1320        // to gain ray source and termination
1321        // copy contents of ray termination buffer into depth texture
1322        // and compare with ray source buffer
1323#if 0
1324        VssRayContainer rays;
1325
1326        glBindTexture(GL_TEXTURE_2D, backDepthMap);     
1327        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
1328
1329        ComputeRays(Intersectable *sourceObj, rays);
1330
1331#endif
1332
1333
1334
1335        //-- cleanup
1336
1337
1338        // reset gl state
1339        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1340        glDepthMask(GL_TRUE);
1341        glEnable(GL_CULL_FACE);
1342        glDisable(GL_STENCIL_TEST);
1343        cgGLDisableProfile(sCgFragmentProfile);
1344        glDisable(GL_TEXTURE_2D);
1345
1346        // remove objects from beam
1347        if (beam.mFlags & !Beam::STORE_OBJECTS)
1348                beam.mObjects.clear();
1349}
1350
1351
1352void GlRendererBuffer::GenQueries(const int numQueries)
1353{
1354        if ((int)sQueries.size() < numQueries)
1355        {
1356                const int n = numQueries - (int)sQueries.size();
1357                unsigned int *newQueries = new unsigned int[n];
1358
1359                glGenOcclusionQueriesNV(n, (unsigned int *)newQueries);
1360
1361                for (int i = 0; i < n; ++ i)
1362                {
1363                        sQueries.push_back(newQueries[i]);
1364                }
1365
1366                delete [] newQueries;
1367        }
1368}
1369
1370
1371void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint,
1372                                                                                                   const Beam &beam,
1373                                                                                                   Intersectable *sourceObject)
1374{
1375        float left, right, bottom, top, znear, zfar;
1376
1377        beam.ComputePerspectiveFrustum(left, right, bottom, top, znear, zfar,
1378                                                                   mSceneGraph->GetBox());
1379
1380        //Debug << left << " " << right << " " << bottom << " " << top << " " << znear << " " << zfar << endl;
1381        glMatrixMode(GL_PROJECTION);
1382        glLoadIdentity();
1383        glFrustum(left, right, bottom, top, znear, zfar);
1384        //glFrustum(-1, 1, -1, 1, 1, 20000);
1385
1386    const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3f;
1387        const Vector3 up =
1388                Normalize(CrossProd(beam.mPlanes[0].mNormal, beam.mPlanes[4].mNormal));
1389
1390#ifdef _DEBUG
1391        Debug << "view point: " << viewPoint << endl;
1392        Debug << "eye: " << center << endl;
1393        Debug << "up: " << up << endl;
1394#endif
1395
1396        glMatrixMode(GL_MODELVIEW);
1397        glLoadIdentity();
1398        gluLookAt(viewPoint.x, viewPoint.y, viewPoint.z,
1399                          center.x, center.y, center.z,                   
1400                          up.x, up.y, up.z);
1401}               
1402
1403 
1404void GlRendererBuffer::InitGL()
1405{
1406 makeCurrent();
1407 GlRenderer::InitGL();
1408#if 1
1409        // initialise dual depth buffer textures
1410        glGenTextures(1, &frontDepthMap);
1411        glBindTexture(GL_TEXTURE_2D, frontDepthMap);
1412       
1413        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
1414                depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
1415        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1416        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1417        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1418        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1419
1420        glGenTextures(1, &backDepthMap);
1421        glBindTexture(GL_TEXTURE_2D, backDepthMap);
1422       
1423        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
1424                depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
1425        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1426        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1427        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
1428        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1429
1430        // cg initialization
1431        cgSetErrorCallback(handleCgError);
1432        sCgContext = cgCreateContext();
1433       
1434        if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
1435                sCgFragmentProfile = CG_PROFILE_ARBFP1;
1436        else
1437        {
1438          // try FP30
1439          if (cgGLIsProfileSupported(CG_PROFILE_FP30))
1440            sCgFragmentProfile = CG_PROFILE_FP30;
1441          else
1442          {
1443                  Debug << "Neither arbfp1 or fp30 fragment profiles supported on this system" << endl;
1444                  exit(1);
1445          }
1446  }
1447
1448
1449 sCgFragmentProgram = cgCreateProgramFromFile(sCgContext,
1450                                                                                           CG_SOURCE, "../src/dual_depth.cg",
1451                                                                                           sCgFragmentProfile,
1452                                                                                           NULL,
1453                                                                                           NULL);
1454
1455  if (!cgIsProgramCompiled(sCgFragmentProgram))
1456          cgCompileProgram(sCgFragmentProgram);
1457
1458  cgGLLoadProgram(sCgFragmentProgram);
1459  cgGLBindProgram(sCgFragmentProgram);
1460
1461  Debug << "---- PROGRAM BEGIN ----\n" <<
1462          cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
1463
1464#endif
1465  doneCurrent();
1466}
1467
1468
1469void GlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays)
1470{
1471        for (int i = 0; i < depthMapSize * depthMapSize; ++ i)
1472        {
1473                //todo glGetTexImage()
1474        }
1475}
1476
1477
1478
1479inline bool ilt(Intersectable *obj1, Intersectable *obj2)
1480{
1481        return obj1->mId < obj2->mId;
1482}
1483
1484
1485int GlRendererBuffer::ComputePvs(ObjectContainer &objects,
1486                                                                 ObjectContainer &pvs) const
1487{
1488        int pvsSize = 0;
1489        QImage image = toImage();
1490        Intersectable::NewMail();
1491
1492        std::stable_sort(objects.begin(), objects.end(), ilt);
1493
1494        MeshInstance dummy(NULL);
1495
1496        Intersectable *obj = NULL;
1497                       
1498        for (int x = 0; x < image.width(); ++ x)
1499        {
1500                for (int y = 0; y < image.height(); ++ y)
1501                {
1502                        QRgb pix = image.pixel(x, y);
1503                        const int id = GetId(qRed(pix), qGreen(pix), qBlue(pix));
1504
1505                        dummy.SetId(id);
1506
1507                        ObjectContainer::iterator oit =
1508                                lower_bound(objects.begin(), objects.end(), &dummy, ilt);
1509                       
1510                       
1511                        if (//(oit != oit.end()) &&
1512                                ((*oit)->GetId() == id) &&
1513                                !obj->Mailed())
1514                        {
1515                                obj = *oit;
1516                                obj->Mail();
1517                                ++ pvsSize;
1518                                pvs.push_back(obj);
1519                        }
1520                }
1521        }
1522
1523        return pvsSize;
1524}
1525
1526/***********************************************************************/
1527/*                     GlDebuggerWidget implementation                             */
1528/***********************************************************************/
1529
1530
1531GlDebuggerWidget::GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent)
1532      : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf)
1533{
1534        // create the pbuffer
1535    //pbuffer = new QGLPixelBuffer(QSize(512, 512), format(), this);
1536    timerId = startTimer(20);
1537    setWindowTitle(("OpenGL pbuffers"));
1538}
1539
1540
1541GlDebuggerWidget::~GlDebuggerWidget()
1542{
1543 mRenderBuffer->releaseFromDynamicTexture();
1544   glDeleteTextures(1, &dynamicTexture);
1545         
1546         DEL_PTR(mRenderBuffer);
1547}
1548
1549
1550void GlDebuggerWidget::initializeGL()
1551{
1552        glMatrixMode(GL_PROJECTION);
1553        glLoadIdentity();
1554
1555        glFrustum(-1, 1, -1, 1, 10, 100);
1556        glTranslatef(-0.5f, -0.5f, -0.5f);
1557        glTranslatef(0.0f, 0.0f, -15.0f);
1558        glMatrixMode(GL_MODELVIEW);
1559
1560        glEnable(GL_CULL_FACE);
1561        initCommon();
1562        initPbuffer();
1563
1564}
1565
1566
1567void GlDebuggerWidget::resizeGL(int w, int h)
1568{
1569        glViewport(0, 0, w, h);
1570}
1571
1572
1573void GlDebuggerWidget::paintGL()
1574{
1575        // draw a spinning cube into the pbuffer..
1576        mRenderBuffer->makeCurrent();
1577       
1578        BeamSampleStatistics stats;
1579        mRenderBuffer->SampleBeamContributions(mSourceObject, mBeam, mSamples, stats);
1580
1581        glFlush();
1582
1583        // rendering directly to a texture is not supported on X11, unfortunately
1584    mRenderBuffer->updateDynamicTexture(dynamicTexture);
1585   
1586    // and use the pbuffer contents as a texture when rendering the
1587    // background and the bouncing cubes
1588    makeCurrent();
1589    glBindTexture(GL_TEXTURE_2D, dynamicTexture);
1590    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1591
1592    // draw the background
1593    glMatrixMode(GL_MODELVIEW);
1594    glPushMatrix();
1595    glLoadIdentity();
1596    glMatrixMode(GL_PROJECTION);
1597    glPushMatrix();
1598    glLoadIdentity();
1599
1600        glPopMatrix();
1601        glMatrixMode(GL_MODELVIEW);
1602        glPopMatrix();
1603}
1604
1605
1606void GlDebuggerWidget::initPbuffer()
1607{
1608        // set up the pbuffer context
1609    mRenderBuffer->makeCurrent();
1610        /*mRenderBuffer->InitGL();
1611
1612        glViewport(0, 0, mRenderBuffer->size().width(), mRenderBuffer->size().height());
1613        glMatrixMode(GL_PROJECTION);
1614        glLoadIdentity();
1615        glOrtho(-1, 1, -1, 1, -99, 99);
1616        glTranslatef(-0.5f, -0.5f, 0.0f);
1617        glMatrixMode(GL_MODELVIEW);
1618        glLoadIdentity();
1619
1620        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/
1621       
1622        // generate a texture that has the same size/format as the pbuffer
1623    dynamicTexture = mRenderBuffer->generateDynamicTexture();
1624
1625        // bind the dynamic texture to the pbuffer - this is a no-op under X11
1626        mRenderBuffer->bindToDynamicTexture(dynamicTexture);
1627        makeCurrent();
1628}
1629
1630void GlDebuggerWidget::initCommon()
1631{
1632        glEnable(GL_TEXTURE_2D);
1633        glEnable(GL_DEPTH_TEST);
1634
1635        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1636}
Note: See TracBrowser for help on using the repository browser.