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

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