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

Revision 538, 23.7 KB checked in by mattausch, 18 years ago (diff)
  • Property svn:executable set to *
Line 
1#include "Mesh.h"
2#include "GlRenderer.h"
3#include "ViewCellsManager.h"
4#include "SceneGraph.h"
5#include "Pvs.h"
6#include "Viewcell.h"
7#include "Beam.h"
8#include "KdTree.h"
9
10#include <GL/glext.h>
11#include <Cg/cg.h>
12#include <Cg/cgGL.h>
13
14static CGcontext sCgContext = NULL;
15static CGprogram sCgFragmentProgram = NULL;
16static CGprofile sCgFragmentProfile;
17
18GLuint depthMap;
19const int depthMapSize = 512;
20static vector<int> sQueries;
21
22GlRendererWidget *rendererWidget = NULL;
23GlDebuggerWidget *debuggerWidget = NULL;
24
25
26#ifdef _WIN32
27PFNGLGENOCCLUSIONQUERIESNVPROC glGenOcclusionQueriesNV;
28PFNGLBEGINOCCLUSIONQUERYNVPROC glBeginOcclusionQueryNV;
29PFNGLENDOCCLUSIONQUERYNVPROC glEndOcclusionQueryNV;
30PFNGLGETOCCLUSIONQUERYUIVNVPROC glGetOcclusionQueryuivNV;
31#endif
32
33GlRenderer::GlRenderer(SceneGraph *sceneGraph,
34                                           ViewCellsManager *viewCellsManager,
35                                           KdTree *tree):
36  Renderer(sceneGraph, viewCellsManager),
37  mKdTree(tree)
38{
39  mSceneGraph->CollectObjects(&mObjects);
40  mViewPoint = mSceneGraph->GetBox().Center();
41  mViewDirection = Vector3(0,0,1);
42  //  timerId = startTimer(10);
43  mFrame = 0;
44  mWireFrame = false;
45}
46
47GlRenderer::~GlRenderer()
48{
49        cgDestroyProgram(sCgFragmentProgram);
50        cgDestroyContext(sCgContext);
51}
52
53
54static void handleCgError()
55{
56    Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl;
57    exit(1);
58}
59
60void
61GlRenderer::RenderIntersectable(Intersectable *object)
62{
63
64  SetupFalseColor(object->mId);
65
66  switch (object->Type()) {
67  case Intersectable::MESH_INSTANCE:
68        RenderMeshInstance((MeshInstance *)object);
69        break;
70  case Intersectable::VIEW_CELL:
71          RenderViewCell(dynamic_cast<ViewCell *>(object));
72          break;
73  default:
74        cerr<<"Rendering this object not yet implemented\n";
75        break;
76  }
77}
78
79
80void
81GlRenderer::RenderViewCell(ViewCell *vc)
82{
83        if (vc->GetMesh())
84                RenderMesh(vc->GetMesh());
85}
86
87void
88GlRenderer::RenderMeshInstance(MeshInstance *mi)
89{
90  RenderMesh(mi->GetMesh());
91}
92
93void
94GlRenderer::SetupFalseColor(const int id)
95{
96  // swap bits of the color
97 
98  glColor3ub(id&255, (id>>8)&255, (id>>16)&255);
99}
100
101void
102GlRenderer::SetupMaterial(Material *m)
103{
104  if (m)
105        glColor3fv(&(m->mDiffuseColor.r));
106  else
107        glColor3f(1.0f, 1.0f, 1.0f);
108}
109
110void
111GlRenderer::RenderMesh(Mesh *mesh)
112{
113  int i = 0;
114
115  if (!mUseFalseColors)
116        SetupMaterial(mesh->mMaterial);
117 
118  for (i=0; i < mesh->mFaces.size(); i++) {
119        if (mWireFrame)
120          glBegin(GL_LINE_LOOP);
121        else
122          glBegin(GL_POLYGON);
123
124        Face *face = mesh->mFaces[i];
125        for (int j = 0; j < face->mVertexIndices.size(); j++) {
126          glVertex3fv(&mesh->mVertices[face->mVertexIndices[j]].x);
127        }
128        glEnd();
129  }
130}
131       
132void
133GlRenderer::InitGL()
134{
135  glMatrixMode(GL_PROJECTION);
136  glLoadIdentity();
137 
138  glMatrixMode(GL_MODELVIEW);
139  glLoadIdentity();
140
141  glEnable(GL_CULL_FACE);
142  glShadeModel(GL_FLAT);
143  glEnable(GL_DEPTH_TEST);
144  glEnable(GL_CULL_FACE);
145 
146  glGenOcclusionQueriesNV = (PFNGLGENOCCLUSIONQUERIESNVPROC)
147        wglGetProcAddress("glGenOcclusionQueriesNV");
148  glBeginOcclusionQueryNV = (PFNGLBEGINOCCLUSIONQUERYNVPROC)
149        wglGetProcAddress("glBeginOcclusionQueryNV");
150  glEndOcclusionQueryNV = (PFNGLENDOCCLUSIONQUERYNVPROC)
151        wglGetProcAddress("glEndOcclusionQueryNV");
152  glGetOcclusionQueryuivNV = (PFNGLGETOCCLUSIONQUERYUIVNVPROC)
153        wglGetProcAddress("glGetOcclusionQueryuivNV");
154
155  // initialise second depth buffer texture
156  glGenTextures(1, &depthMap);
157  glBindTexture(GL_TEXTURE_2D, depthMap);
158 
159  glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
160                           depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
161  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
162  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
163  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
164  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
165
166  // cg initialization
167  cgSetErrorCallback(handleCgError);
168  sCgContext = cgCreateContext();
169
170  if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
171          sCgFragmentProfile = CG_PROFILE_ARBFP1;
172  else {
173          // try FP30
174          if (cgGLIsProfileSupported(CG_PROFILE_FP30))
175            sCgFragmentProfile = CG_PROFILE_FP30;
176          else {
177                  fprintf(stderr, "Neither arbfp1 or fp30 fragment profiles supported on this system.\n");
178                  exit(1);
179          }
180  }
181
182  sCgFragmentProgram = cgCreateProgramFromFile(sCgContext,             
183                                                                                           CG_SOURCE, "../src/dual_depth.cg",
184                                                                                           sCgFragmentProfile,
185                                                                                           NULL,
186                                                                                           NULL);
187
188  if (!cgIsProgramCompiled(sCgFragmentProgram))
189          cgCompileProgram(sCgFragmentProgram);
190
191  cgGLLoadProgram(sCgFragmentProgram);
192  cgGLBindProgram(sCgFragmentProgram);
193 // Debug << "LAST LISTING----" << cgGetLastListing(sCgContext) << "----\n";
194
195  Debug << "---- PROGRAM BEGIN ----\n" <<
196          cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
197}
198
199
200
201void
202GlRenderer::SetupProjection(const int w, const int h)
203{
204  glViewport(0, 0, w, h);
205  glMatrixMode(GL_PROJECTION);
206  glLoadIdentity();
207  gluPerspective(70.0, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
208  glMatrixMode(GL_MODELVIEW);
209}
210
211void
212GlRenderer::SetupCamera()
213{
214  Vector3 target = mViewPoint + mViewDirection;
215  Vector3 up(0,1,0);
216 
217  glLoadIdentity();
218  gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z,
219                        target.x, target.y, target.z,
220                        up.x, up.y, up.z);
221}
222
223void
224GlRenderer::RandomViewPoint()
225{
226  Vector3 pVector = Vector3(halton.GetNumber(1),
227                                                        halton.GetNumber(2),
228                                                        halton.GetNumber(3));
229 
230  Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4),
231                                                        M_PI*halton.GetNumber(5),
232                                                        0.0f);
233 
234  mViewPoint = mSceneGraph->GetBox().GetPoint(pVector);
235 
236  mViewDirection = Normalize(Vector3(sin(dVector.x),
237                                                                         //                                                                      cos(dVector.y),
238                                                                         0.0f,
239                                                                         cos(dVector.x)));
240
241  halton.GenerateNext();
242}
243
244
245float
246GlRenderer::GetPixelError()
247{
248  float pErrorPixels = -1.0f;
249
250  glReadBuffer(GL_BACK);
251 
252  mUseFalseColors = true;
253
254  SetupCamera();
255  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
256  glEnable( GL_CULL_FACE );
257 
258  RenderScene();
259
260  // now check whether any backfacing polygon would pass the depth test
261  static int query = -1;
262  if (query == -1)
263        glGenOcclusionQueriesNV(1, (unsigned int *)&query);
264 
265  glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
266  glDepthMask(GL_FALSE);
267  glDisable( GL_CULL_FACE );
268 
269  glBeginOcclusionQueryNV(query);
270 
271  RenderScene();
272 
273  glEndOcclusionQueryNV();
274
275  // at this point, if possible, go and do some other computation
276  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
277  glDepthMask(GL_TRUE);
278  glEnable( GL_CULL_FACE );
279 
280  unsigned int pixelCount;
281  // reenable other state
282  glGetOcclusionQueryuivNV(query,
283                                                   GL_PIXEL_COUNT_NV,
284                                                   &pixelCount);
285
286  if (pixelCount > 0)
287        return -1.0f; // backfacing polygon found -> not a valid viewspace sample
288
289  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
290 
291  if (viewcell) {
292        SetupCamera();
293        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
294
295        // Render PVS
296        std::map<Intersectable *,
297          PvsData<Intersectable *>,
298          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
299       
300        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
301          Intersectable *object = (*it).first;
302          RenderIntersectable(object);
303        }
304
305        glBeginOcclusionQueryNV(query);
306
307        SetupCamera();
308
309        RenderScene();
310       
311        glEndOcclusionQueryNV();
312       
313
314        unsigned int pixelCount;
315        // reenable other state
316        glGetOcclusionQueryuivNV(query,
317                                                         GL_PIXEL_COUNT_NV,
318                                                         &pixelCount);
319       
320        pErrorPixels = (100.f*pixelCount)/(GetWidth()*GetHeight());
321  }
322 
323  return pErrorPixels;
324}
325
326
327float
328GlRendererWidget::RenderErrors()
329{
330  float pErrorPixels = -1.0f;
331
332  glReadBuffer(GL_BACK);
333 
334  mUseFalseColors = true;
335
336  SetupCamera();
337  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
338  glEnable( GL_CULL_FACE );
339 
340  ObjectContainer::const_iterator oi = mObjects.begin();
341  for (; oi != mObjects.end(); oi++)
342        RenderIntersectable(*oi);
343
344  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
345 
346  QImage im1, im2;
347  QImage diff;
348 
349  if (viewcell) {
350        // read back the texture
351        im1 = grabFrameBuffer(true);
352       
353        SetupCamera();
354        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
355       
356        std::map<Intersectable *,
357          PvsData<Intersectable *>,
358          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
359       
360        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
361          Intersectable *object = (*it).first;
362          RenderIntersectable(object);
363        }
364
365        // read back the texture
366        im2 = grabFrameBuffer(true);
367       
368        diff = im1;
369        int x, y;
370        int errorPixels = 0;
371       
372        for (y = 0; y < im1.height(); y++)
373          for (x = 0; x < im1.width(); x++)
374                if (im1.pixel(x, y) == im2.pixel(x, y))
375                  diff.setPixel(x, y, qRgba(0,0,0,0));
376                else {
377                  diff.setPixel(x, y, qRgba(255,128,128,255));
378                  errorPixels++;
379                }
380        pErrorPixels = (100.f*errorPixels)/(im1.height()*im1.width());
381  }
382
383  // now render the pvs again
384  SetupCamera();
385  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
386  mUseFalseColors = false;
387       
388  oi = mObjects.begin();
389  for (; oi != mObjects.end(); oi++)
390        RenderIntersectable(*oi);
391
392  // now render im1
393  if (viewcell) {
394        if (mTopView) {
395          mWireFrame = true;
396          RenderMeshInstance(viewcell);
397          mWireFrame = false;
398        }
399       
400        // init ortographic projection
401        glMatrixMode(GL_PROJECTION);
402        glPushMatrix();
403       
404        glLoadIdentity();
405        gluOrtho2D(0, 1.0f, 0, 1.0f);
406       
407        glMatrixMode(GL_MODELVIEW);
408        glLoadIdentity();
409       
410        bindTexture(diff);
411       
412        glPushAttrib(GL_ENABLE_BIT);
413        glEnable( GL_ALPHA_TEST );
414        glDisable( GL_CULL_FACE );
415        glAlphaFunc( GL_GREATER, 0.5 );
416       
417        glEnable( GL_TEXTURE_2D );
418        glBegin(GL_QUADS);
419       
420        glTexCoord2f(0,0);
421        glVertex3f(0,0,0);
422       
423        glTexCoord2f(1,0);
424        glVertex3f( 1, 0, 0);
425       
426        glTexCoord2f(1,1);
427        glVertex3f( 1, 1, 0);
428       
429        glTexCoord2f(0,1);
430        glVertex3f(0, 1, 0);
431        glEnd();
432       
433        glPopAttrib();
434       
435        // restore the projection matrix
436        glMatrixMode(GL_PROJECTION);
437        glPopMatrix();
438        glMatrixMode(GL_MODELVIEW);
439  }
440
441  return pErrorPixels;
442}
443
444
445bool
446GlRenderer::RenderScene()
447{
448  static int glList = -1;
449  if (glList == -1)
450  {
451        glList = glGenLists(1);
452        glNewList(glList, GL_COMPILE);
453        ObjectContainer::const_iterator oi = mObjects.begin();
454        for (; oi != mObjects.end(); oi++)
455          RenderIntersectable(*oi);
456        glEndList();
457  }
458 
459  glCallList(glList);
460 
461  return true;
462}
463
464
465void
466GlRendererBuffer::ClearErrorBuffer()
467{
468  for (int i=0; i < mPvsStatFrames; i++) {
469        mPvsErrorBuffer[i] = 1.0f;
470  }
471}
472
473
474void
475GlRendererBuffer::EvalPvsStat()
476{
477  mPvsStat.Reset();
478  halton.Reset();
479
480  makeCurrent();
481  SetupProjection(GetWidth(), GetHeight());
482 
483  for (int i=0; i < mPvsStatFrames; i++) {
484        float err;
485        RandomViewPoint();
486        if (mPvsErrorBuffer[i] > 0.0f) {
487          mPvsErrorBuffer[i] = GetPixelError();
488          cout<<"("<<i<<","<<mPvsErrorBuffer[i]<<")";
489          //      swapBuffers();
490        }
491       
492        err = mPvsErrorBuffer[i];
493       
494        if (err >= 0.0f) {
495          if (err > mPvsStat.maxError)
496                mPvsStat.maxError = err;
497          mPvsStat.sumError += err;
498          if (err == 0.0f)
499                mPvsStat.errorFreeFrames++;
500          mPvsStat.frames++;
501        }
502  }
503 
504  doneCurrent();
505
506  cout<<endl<<flush;
507  mRenderingFinished.wakeAll();
508}
509
510
511
512
513
514void
515GlRendererWidget::mousePressEvent(QMouseEvent *e)
516{
517  int x = e->pos().x();
518  int y = e->pos().y();
519
520  mousePoint.x = x;
521  mousePoint.y = y;
522 
523}
524
525void
526GlRendererWidget::mouseMoveEvent(QMouseEvent *e)
527{
528  float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3;
529  float TURN_SENSITIVITY=0.1f;
530  float TILT_SENSITIVITY=32.0 ;
531  float TURN_ANGLE= M_PI/36.0 ;
532
533  int x = e->pos().x();
534  int y = e->pos().y();
535 
536  if (e->modifiers() & Qt::ControlModifier) {
537        mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0;
538        mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0;
539  } else {
540        mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY);
541        float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY;
542        float angle = atan2(mViewDirection.x, mViewDirection.z);
543        mViewDirection.x = sin(angle+adiff);
544        mViewDirection.z = cos(angle+adiff);
545  }
546 
547  mousePoint.x = x;
548  mousePoint.y = y;
549 
550  updateGL();
551}
552
553void
554GlRendererWidget::mouseReleaseEvent(QMouseEvent *)
555{
556
557
558}
559
560void
561GlRendererWidget::resizeGL(int w, int h)
562{
563  SetupProjection(w, h);
564  updateGL();
565}
566
567void
568GlRendererWidget::paintGL()
569{
570        RenderErrors();
571       
572        mFrame++;
573}
574
575
576void
577GlRendererWidget::SetupCamera()
578{
579  if (!mTopView)
580        GlRenderer::SetupCamera();
581  else {
582        float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05;
583        Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x,
584                                                                                        -1,
585                                                                                        mViewDirection.y);
586       
587        Vector3 target = mViewPoint + dist*mViewDirection;
588        Vector3 up(0,1,0);
589       
590        glLoadIdentity();
591        gluLookAt(pos.x, pos.y, pos.z,
592                          target.x, target.y, target.z,
593                          up.x, up.y, up.z);
594  }
595
596}
597
598void
599GlRendererWidget::keyPressEvent ( QKeyEvent * e )
600{
601  switch (e->key()) {
602  case Qt::Key_T:
603        mTopView = !mTopView;
604        updateGL();
605        break;
606  default:
607        e->ignore();
608        break;
609  }
610 
611}
612
613
614void GlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject,
615                                                                                           Beam &beam,
616                                                                                           const int desiredSamples,
617                                                                                           BeamSampleStatistics &stat)
618{
619        // TODO: should not be done every time here
620        // only back faces are interesting for the depth pass
621        glShadeModel(GL_FLAT);
622        glDisable(GL_LIGHTING);
623        // needed to kill the fragments for the front buffer
624        glEnable(GL_ALPHA_TEST);
625        glAlphaFunc(GL_GREATER, 0);
626
627        // assumes that the beam is constructed and contains kd-tree nodes
628        // and viewcells which it intersects
629 
630 
631        // Get the number of viewpoints to be sampled
632        // Now it is a sqrt but in general a wiser decision could be made.
633        // The less viewpoints the better for rendering performance, since less passes
634        // over the beam is needed.
635        // The viewpoints could actually be generated outside of the bounding box which
636        // would distribute the 'efective viewpoints' of the object surface and thus
637        // with a few viewpoints better sample the vipoint space....
638 
639        int viewPointSamples = sqrt((float)desiredSamples);
640
641        // the number of direction samples per pass is given by the number of viewpoints
642        int directionalSamples = desiredSamples/viewPointSamples;
643       
644        for (int i = 0; i < viewPointSamples; ++ i)
645        {
646                Vector3 viewPoint = beam.mBox.GetRandomPoint();
647               
648                // perhaps the viewpoint should be shifted back a little bit so that it always lies
649                // inside the source object
650                // 'ideally' the viewpoints would be distributed on the soureObject surface, but this
651        // would require more complicated sampling (perhaps hierarchical rejection sampling of
652                // the object surface is an option here - only the mesh faces which are inside the box
653                // are considered as candidates)
654               
655                SampleViewpointContributions(sourceObject,
656                                                                         viewPoint,
657                                                                         beam,
658                                                                         directionalSamples,
659                                                                         stat);
660        }
661
662
663        // note:
664        // this routine would be called only if the number of desired samples is sufficiently
665        // large - for other rss tree cells the cpu based sampling is perhaps more efficient
666        // distributing the work between cpu and gpu would also allow us to place more sophisticated
667        // sample distributions (silhouette ones) using the cpu and the jittered once on the GPU
668        // in order that thios scheme is working well the gpu render buffer should run in a separate
669        // thread than the cpu sampler, which would not be such a big problem....
670}
671
672
673void GlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject,
674                                                                                                        const Vector3 viewPoint,
675                                                                                                        Beam &beam,
676                                                                                                        const int desiredSamples,
677                                                    BeamSampleStatistics &stat)
678{
679        // 1. setup the view port to match the desired samples
680        glViewport(0, 0, desiredSamples, desiredSamples);
681
682        // 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox
683        SetupProjectionForViewPoint(viewPoint, beam, sourceObject);
684       
685        // 3. reset z-buffer to 0 and render the source object for the beam
686        //    with glCullFace(Enabled) and glFrontFace(GL_CW)
687        //    save result to depth map
688        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
689        glEnable(GL_CULL_FACE);
690        glEnable(GL_STENCIL_TEST);
691        glCullFace(GL_FRONT);
692        glColorMask(0, 0, 0, 0);
693       
694        // stencil is increased where the source object is located
695        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
696        glStencilOp(GL_INCR, GL_INCR, GL_INCR);
697
698#if 0
699        static int glSourceObjList = -1;         
700        if (glSourceObjList != -1)
701        {
702                glSourceObjList = glGenLists(1);
703                glNewList(glSourceObjList, GL_COMPILE);
704
705                RenderIntersectable(sourceObject);
706       
707                glEndList();
708        }
709        glCallList(glSourceObjList);
710
711#else
712        RenderIntersectable(sourceObject);
713
714#endif 
715
716        // 4. set back to normal rendering and clear the ray termination depth buffer
717        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
718        glColorMask(1, 1, 1, 1);
719       
720        // 5. render all objects inside the beam using id based false color
721        //    (objects can be compiled to a gl list now so that subsequent rendering for
722        //     this beam is fast - the same hold for step 3)
723
724        if (beam.mFlags & !Beam::STORE_OBJECTS)
725        {
726                vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
727
728                Intersectable::NewMail();
729                for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
730                {
731                        mKdTree->CollectObjects(*it, beam.mObjects);
732                }
733        }
734
735        // list of objects intersected by the frustum
736#if 0
737        static int glObjList = -1;
738        if (glObjList != -1)
739        {
740                glObjList = glGenLists(1);
741                glNewList(glObjList, GL_COMPILE);
742       
743                ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
744                for (it = beam.mObjects.begin(); it != it_end; ++ it)
745                        RenderIntersectable(*it);
746               
747                glEndList();
748        }
749        glCallList(glObjList);
750#else
751        ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
752                for (it = beam.mObjects.begin(); it != it_end; ++ it)
753                        RenderIntersectable(*it);
754#endif
755
756        // remove objects again
757        if (beam.mFlags & !Beam::STORE_OBJECTS)
758                beam.mObjects.clear();
759
760        // bind ray origin depth buffer
761        glBindTexture(GL_TEXTURE_2D, depthMap);
762    glEnable(GL_TEXTURE_2D);
763       
764
765        //Read the depth buffer into the shadow map texture
766        glBindTexture(GL_TEXTURE_2D, depthMap);
767        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
768
769       
770        // 6. Now we have a two depth buffers defining the ray origin and termination
771        //    only rays which have non-zero entry in the origin buffer are valid since
772        //    they realy start on the object surface (this can also be tagged by setting a
773        //    stencil buffer bit at step 3)
774        glStencilFunc(GL_EQUAL, 0x1, 0x1);
775 
776        //cgGLBindProgram(sCgFragmentProgram);
777        cgGLEnableProfile(sCgFragmentProfile);
778
779        // 7. Use occlusion queries for all viewcell meshes associated with the beam ->
780        // a fragment passes if the corresponding stencil fragment is set and its depth is
781        // between origin and termination buffer
782
783        // create new queries if necessary
784        GenQueries((int)beam.mViewCells.size());
785
786        // now check whether any backfacing polygon would pass the depth test?
787        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
788        glDepthMask(GL_FALSE);
789        glDisable(GL_CULL_FACE);
790 
791        ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end();
792
793        int queryIdx = 0;
794
795        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
796        {
797                glBeginOcclusionQueryNV(sQueries[queryIdx ++]);
798
799                RenderIntersectable(*vit);
800               
801                glEndOcclusionQueryNV();
802        }
803
804        // at this point, if possible, go and do some other computation
805
806        queryIdx = 0;
807        unsigned int pixelCount;
808
809        // 8. The number of visible pixels is the number of sample rays which see the source
810        //    object from the corresponding viewcell -> remember these values for later update
811        //   of the viewcell pvs - or update immediately?
812
813        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
814        {
815                // fetch queries
816                glGetOcclusionQueryuivNV(sQueries[queryIdx ++],
817                                                                 GL_PIXEL_COUNT_NV,
818                                                                 &pixelCount);
819
820                Debug << "visble pixels: " << pixelCount << endl;
821        }
822       
823
824        //  In general it is not neccessary to remember to extract all the rays cast. I hope it
825        // would be sufficient to gain only the intergral statistics about the new contributions
826        // and so the rss tree would actually store no new rays (only the initial ones)
827        // the subdivision of the tree would only be driven by the statistics (the glrender could
828        // evaluate the contribution entropy for example)
829        // However might be an option to extract/store only those the rays which made a contribution
830        // (new viewcell has been discovered) or relative contribution greater than a threashold ...
831
832        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
833        glDepthMask(GL_TRUE);
834        glEnable(GL_CULL_FACE);
835
836
837        cgGLDisableProfile(sCgFragmentProfile);
838        glDisable(GL_TEXTURE_2D);
839}
840
841
842void GlRendererBuffer::GenQueries(const int numQueries)
843{
844        if ((int)sQueries.size() < numQueries)
845        {
846                const int n = numQueries - (int)sQueries.size();
847                int *newQueries = new int[n];
848
849                glGenOcclusionQueriesNV(n, (unsigned int *)&newQueries);
850
851                for (int i = 0; i < n; ++ i)
852                {
853                        sQueries.push_back(newQueries[i]);
854                }
855
856                delete newQueries;
857        }
858}
859
860
861void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint,
862                                                                                                 const Beam &beam,
863                                                                                                 Intersectable *sourceObject)
864{
865        float left, right, bottom, top, znear, zfar;
866
867        beam.ComputeFrustum(left, right, bottom, top, znear, zfar,
868                                                mSceneGraph->GetBox());
869
870        glFrustum(left, right, bottom, top, znear, zfar);
871
872    const Vector3 eye = viewPoint + beam.GetMainDirection();
873        const Vector3 up;//AbitraryNormal(eye);
874
875        gluLookAt(eye.x, eye.y, eye.z,
876                          viewPoint.x, viewPoint.y, viewPoint.z,
877                          up.x, up.y, up.z);
878}               
879
880 
881 
882
883/***************************************************************/
884/*             GlDebuggerWidget implementation                             */
885/***************************************************************/
886
887
888GlDebuggerWidget::GlDebuggerWidget(QWidget *parent, GlRendererBuffer *buf)
889      : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf)
890{
891        // create the pbuffer
892    //pbuffer = new QGLPixelBuffer(QSize(512, 512), format(), this);
893    timerId = startTimer(20);
894    setWindowTitle(("OpenGL pbuffers"));
895}
896
897
898GlDebuggerWidget::~GlDebuggerWidget()
899{
900        mRenderBuffer->releaseFromDynamicTexture();
901        glDeleteTextures(1, &dynamicTexture);
902       
903        DEL_PTR(mRenderBuffer);
904}
905
906
907void GlDebuggerWidget::initializeGL()
908{
909        glMatrixMode(GL_PROJECTION);
910        glLoadIdentity();
911
912        glFrustum(-1, 1, -1, 1, 10, 100);
913        glTranslatef(-0.5f, -0.5f, -0.5f);
914        glTranslatef(0.0f, 0.0f, -15.0f);
915        glMatrixMode(GL_MODELVIEW);
916
917        glEnable(GL_CULL_FACE);
918        initCommon();
919        initPbuffer();
920
921}
922
923
924void GlDebuggerWidget::resizeGL(int w, int h)
925{
926        glViewport(0, 0, w, h);
927}
928
929
930void GlDebuggerWidget::paintGL()
931{
932        // draw a spinning cube into the pbuffer..
933        mRenderBuffer->makeCurrent();
934        //mRenderBuffer->SampleBeamContributions();
935        glFlush();
936
937    // rendering directly to a texture is not supported on X11, unfortunately
938    mRenderBuffer->updateDynamicTexture(dynamicTexture);
939   
940    // ..and use the pbuffer contents as a texture when rendering the
941    // background and the bouncing cubes
942    makeCurrent();
943    glBindTexture(GL_TEXTURE_2D, dynamicTexture);
944    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
945
946    // draw the background
947    glMatrixMode(GL_MODELVIEW);
948    glPushMatrix();
949    glLoadIdentity();
950    glMatrixMode(GL_PROJECTION);
951    glPushMatrix();
952    glLoadIdentity();
953
954        glPopMatrix();
955        glMatrixMode(GL_MODELVIEW);
956        glPopMatrix();
957}
958
959
960void GlDebuggerWidget::initPbuffer()
961{
962        // set up the pbuffer context
963    mRenderBuffer->makeCurrent();
964        initCommon();
965
966        glViewport(0, 0, mRenderBuffer->size().width(), mRenderBuffer->size().height());
967        glMatrixMode(GL_PROJECTION);
968        glLoadIdentity();
969        glOrtho(-1, 1, -1, 1, -99, 99);
970        glTranslatef(-0.5f, -0.5f, 0.0f);
971        glMatrixMode(GL_MODELVIEW);
972        glLoadIdentity();
973
974        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
975
976        // generate a texture that has the same size/format as the pbuffer
977    dynamicTexture = mRenderBuffer->generateDynamicTexture();
978
979        // bind the dynamic texture to the pbuffer - this is a no-op under X11
980        mRenderBuffer->bindToDynamicTexture(dynamicTexture);
981        makeCurrent();
982}
983
984void GlDebuggerWidget::initCommon()
985{
986        glEnable(GL_TEXTURE_2D);
987        glEnable(GL_DEPTH_TEST);
988
989        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
990}
Note: See TracBrowser for help on using the repository browser.