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

Revision 608, 38.6 KB checked in by bittner, 19 years ago (diff)

slider support for viewcells

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