source: trunk/VUT/GtpVisibilityPreprocessor/src/GlRenderer.cpp @ 576

Revision 576, 31.2 KB checked in by bittner, 18 years ago (diff)

rss preprocessor debugging + merge

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