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

Revision 1004, 56.1 KB checked in by mattausch, 18 years ago (diff)

environment as a singleton

  • Property svn:executable set to *
Line 
1#include "Mesh.h"
2#include "glInterface.h"
3#include "OcclusionQuery.h"
4#include "GlRenderer.h"
5#include "ViewCellsManager.h"
6#include "SceneGraph.h"
7#include "Pvs.h"
8#include "Viewcell.h"
9#include "Beam.h"
10#include "KdTree.h"
11#include "Environment.h"
12
13
14//#define GL_GLEXT_PROTOTYPES
15
16
17#include <Cg/cg.h>
18#include <Cg/cgGL.h>
19
20
21#include <QVBoxLayout>
22
23namespace GtpVisibilityPreprocessor {
24
25static CGcontext sCgContext = NULL;
26static CGprogram sCgFragmentProgram = NULL;
27static CGprofile sCgFragmentProfile;
28
29GLuint frontDepthMap;
30GLuint backDepthMap;
31
32const int depthMapSize = 512;
33static vector<OcclusionQuery *> sQueries;
34
35GlRendererWidget *rendererWidget = NULL;
36GlDebuggerWidget *debuggerWidget = NULL;
37
38static bool arbQuerySupport = false;
39static bool nvQuerySupport = false;
40
41
42static void InitExtensions()
43{
44        GLenum err = glewInit();
45
46        if (GLEW_OK != err)
47        {
48                // problem: glewInit failed, something is seriously wrong
49                cerr << "Error: " << glewGetErrorString(err) << endl;
50                exit(1);
51        }
52
53        if (GLEW_ARB_occlusion_query)
54                arbQuerySupport = true;
55       
56        if (GLEW_NV_occlusion_query)
57                nvQuerySupport = true;
58       
59
60        if  (!arbQuerySupport && !nvQuerySupport)
61        {
62                cout << "I require the GL_ARB_occlusion_query or the GL_NV_occlusion_query OpenGL extension to work.\n";
63                exit(1);
64        }
65}
66
67
68GlRenderer::GlRenderer(SceneGraph *sceneGraph,
69                                           ViewCellsManager *viewCellsManager,
70                                           KdTree *tree):
71  Renderer(sceneGraph, viewCellsManager),
72  mKdTree(tree)
73{
74  mSceneGraph->CollectObjects(&mObjects);
75  mViewPoint = mSceneGraph->GetBox().Center();
76  mViewDirection = Vector3(0,0,1);
77
78  mViewPoint = Vector3(991.7, 187.8, -271);
79  mViewDirection = Vector3(0.9, 0, -0.4);
80
81  //  timerId = startTimer(10);
82  // debug coords for atlanta
83  //  mViewPoint = Vector3(3473, 6.778, -1699);
84  //  mViewDirection = Vector3(-0.2432, 0, 0.97);
85 
86  mFrame = 0;
87  mWireFrame = false;
88  Environment::GetSingleton()->GetBoolValue("Preprocessor.detectEmptyViewSpace", mDetectEmptyViewSpace);
89  mSnapErrorFrames = true;
90  mSnapPrefix = "snap/";
91  mUseForcedColors = false;
92
93  mUseGlLists = true;
94  //mUseGlLists = false;
95}
96
97GlRenderer::~GlRenderer()
98{
99  cerr<<"gl renderer destructor..\n";
100  if (sCgFragmentProgram)
101        cgDestroyProgram(sCgFragmentProgram);
102  if (sCgContext)
103        cgDestroyContext(sCgContext);
104  cerr<<"done."<<endl;
105   
106  CLEAR_CONTAINER(sQueries);
107  CLEAR_CONTAINER(mOcclusionQueries);
108}
109
110
111static void handleCgError()
112{
113    Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl;
114    exit(1);
115}
116
117void
118GlRenderer::RenderIntersectable(Intersectable *object)
119{
120
121  glPushAttrib(GL_CURRENT_BIT);
122  if (mUseFalseColors)
123        SetupFalseColor(object->mId);
124 
125
126  switch (object->Type()) {
127  case Intersectable::MESH_INSTANCE:
128        RenderMeshInstance((MeshInstance *)object);
129        break;
130  case Intersectable::VIEW_CELL:
131          RenderViewCell(dynamic_cast<ViewCell *>(object));
132          break;
133  case Intersectable::TRANSFORMED_MESH_INSTANCE:
134          RenderTransformedMeshInstance(dynamic_cast<TransformedMeshInstance *>(object));
135          break;
136  default:
137        cerr<<"Rendering this object not yet implemented\n";
138        break;
139  }
140
141  glPopAttrib();
142}
143
144
145void
146GlRenderer::RenderViewCell(ViewCell *vc)
147{
148  if (vc->GetMesh()) {
149
150        if (!mUseFalseColors) {
151          if (vc->GetValid())
152                glColor3f(0,1,0);
153          else
154                glColor3f(0,0,1);
155        }
156       
157        RenderMesh(vc->GetMesh());
158  } else {
159        // render viewcells in the subtree
160        if (!vc->IsLeaf()) {
161          ViewCellInterior *vci = (ViewCellInterior *) vc;
162
163          ViewCellContainer::iterator it = vci->mChildren.begin();
164          for (; it != vci->mChildren.end(); ++it) {
165                RenderViewCell(*it);
166          }
167        } else {
168          //      cerr<<"Empty viewcell mesh\n";
169        }
170  }
171}
172
173
174void
175GlRenderer::RenderMeshInstance(MeshInstance *mi)
176{
177  RenderMesh(mi->GetMesh());
178}
179
180
181void
182GlRenderer::RenderTransformedMeshInstance(TransformedMeshInstance *mi)
183{
184        // apply world transform before rendering
185        Matrix4x4 m;
186        mi->GetWorldTransform(m);
187
188        glPushMatrix();
189/* cout << "\n";
190        for (int i = 0; i < 4; ++ i)
191                for (int j = 0; j < 4; ++ j)
192                        cout << m.x[i][j] << " "; cout << "\n"*/
193
194        glMultMatrixf((float *)m.x);
195
196        /*GLfloat dummy[16];
197        glGetFloatv(GL_MODELVIEW_MATRIX, dummy);
198        for (int i = 0; i < 16; ++ i)
199                cout << dummy[i] << " ";
200        cout << endl;*/
201        RenderMesh(mi->GetMesh());
202       
203        glPopMatrix();
204}
205
206
207void
208GlRenderer::SetupFalseColor(const int id)
209{
210  // swap bits of the color
211  glColor3ub(id&255, (id>>8)&255, (id>>16)&255);
212}
213
214
215int GlRenderer::GetId(int r, int g, int b) const
216{
217        return r + (g << 8) + (b << 16);
218}
219
220void
221GlRenderer::SetupMaterial(Material *m)
222{
223  if (m)
224        glColor3fv(&(m->mDiffuseColor.r));
225}
226
227void
228GlRenderer::RenderMesh(Mesh *mesh)
229{
230  int i = 0;
231
232  if (!mUseFalseColors && !mUseForcedColors)
233        SetupMaterial(mesh->mMaterial);
234 
235  for (i=0; i < mesh->mFaces.size(); i++) {
236        if (mWireFrame)
237          glBegin(GL_LINE_LOOP);
238        else
239          glBegin(GL_POLYGON);
240
241        Face *face = mesh->mFaces[i];
242        for (int j = 0; j < face->mVertexIndices.size(); j++) {
243          glVertex3fv(&mesh->mVertices[face->mVertexIndices[j]].x);
244        }
245        glEnd();
246  }
247}
248       
249void
250GlRenderer::InitGL()
251{
252  glMatrixMode(GL_PROJECTION);
253  glLoadIdentity();
254 
255  glMatrixMode(GL_MODELVIEW);
256  glLoadIdentity();
257
258  glEnable(GL_CULL_FACE);
259  glShadeModel(GL_FLAT);
260  glEnable(GL_DEPTH_TEST);
261  glEnable(GL_CULL_FACE);
262 
263  // HACK!! but using glew keeps crashing for some reason ...
264  InitExtensions();
265 
266#if 0
267  GLfloat mat_ambient[]   = {  0.5, 0.5, 0.5, 1.0  };
268  /*  mat_specular and mat_shininess are NOT default values     */
269  GLfloat mat_diffuse[]   = {  1.0, 1.0, 1.0, 1.0  };
270  GLfloat mat_specular[]  = {  0.3, 0.3, 0.3, 1.0  };
271  GLfloat mat_shininess[] = {  1.0  };
272 
273  GLfloat light_ambient[]  = {  0.2, 0.2, 0.2, 1.0  };
274  GLfloat light_diffuse[]  = {  0.4, 0.4, 0.4, 1.0  };
275  GLfloat light_specular[] = {  0.3, 0.3, 0.3, 1.0  };
276 
277  GLfloat lmodel_ambient[] = {  0.3, 0.3, 0.3, 1.0  };
278 
279 
280  // default Material
281  glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
282  glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
283  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
284  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
285
286  // a light
287  glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
288  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
289  glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
290 
291  glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
292  glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
293  glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
294 
295  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
296 
297  glEnable(GL_LIGHTING);
298  glEnable(GL_LIGHT0);
299  glEnable(GL_LIGHT1);
300 
301 
302  // set position of the light
303  GLfloat infinite_light[] = {  1.0, 0.8, 1.0, 0.0  };
304  glLightfv (GL_LIGHT0, GL_POSITION, infinite_light);
305 
306  // set position of the light2
307  GLfloat infinite_light2[] = {  -0.3, 1.5, 1.0, 0.0  };
308  glLightfv (GL_LIGHT1, GL_POSITION, infinite_light2);
309 
310  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
311  //   glColorMaterial( GL_FRONT_AND_BACK, GL_SPECULAR);
312  glEnable(GL_COLOR_MATERIAL);
313 
314  glShadeModel( GL_FLAT );
315 
316  glDepthFunc( GL_LESS );
317  glEnable( GL_DEPTH_TEST );
318#endif
319
320  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
321
322  glEnable( GL_NORMALIZE );
323 
324  glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
325}
326
327void
328GlRendererWidget::RenderInfo()
329{
330  QString s;
331  int vc = 0;
332  if (mViewCellsManager)
333        vc = mViewCellsManager->GetViewCells().size();
334  int filter = 0;
335  if (mViewCellsManager)
336        filter = mViewCellsManager->GetMaxFilterSize();
337
338  s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f) viewcells:%04d filter:%04d pvs:%04d error:%5.5f\%",
339                        mFrame,
340                        mViewPoint.x,
341                        mViewPoint.y,
342                        mViewPoint.z,
343                        mViewDirection.x,
344                        mViewDirection.y,
345                        mViewDirection.z,
346                        vc,
347
348                        filter,
349                        mPvsSize,
350                        mRenderError*100.0f
351                        );
352 
353  glColor3f(0.0f,0.0f,0.0f);
354  renderText(0,20,s);
355 
356  if (mShowRenderCost) {
357        static vector<float> costFunction;
358        static float maxCost = -1;
359        if (costFunction.size()==0) {
360          ViewCellsTree *tree = mViewCellsManager->GetViewCellsTree();
361          if (tree) {
362                tree->GetCostFunction(costFunction);
363                maxCost = -1;
364                for (int i=0;  i < costFunction.size(); i++) {
365                  //              cout<<i<<":"<<costFunction[i]<<" ";
366                  if (costFunction[i] > maxCost)
367                        maxCost = costFunction[i];
368                }
369          }
370        }
371
372       
373        int currentPos = mViewCellsManager->GetViewCells().size();
374        float currentCost=-1;
375
376        if (currentPos < costFunction.size())
377          currentCost = costFunction[currentPos];
378#if 0   
379        cout<<"costFunction.size()="<<costFunction.size()<<endl;
380        cout<<"CP="<<currentPos<<endl;
381        cout<<"MC="<<maxCost<<endl;
382        cout<<"CC="<<currentCost<<endl;
383#endif
384        if (costFunction.size()) {
385          glDisable(GL_DEPTH_TEST);
386          // init ortographic projection
387          glMatrixMode(GL_PROJECTION);
388          glPushMatrix();
389         
390          glLoadIdentity();
391          gluOrtho2D(0, 1.0f, 0, 1.0f);
392         
393          glTranslatef(0.1f, 0.1f, 0.0f);
394          glScalef(0.8f, 0.8f, 1.0f);
395          glMatrixMode(GL_MODELVIEW);
396          glLoadIdentity();
397         
398          glColor3f(1.0f,0,0);
399          glBegin(GL_LINE_STRIP);
400          //      glVertex3f(0,0,0);
401         
402          for (int i=0;  i < costFunction.size(); i++) {
403                float x =  i/(float)costFunction.size();
404                float y = costFunction[i]/(maxCost*0.5f);
405                glVertex3f(x,y,0.0f);
406          }
407          glEnd();
408         
409          glColor3f(1.0f,0,0);
410          glBegin(GL_LINES);
411          float x =  currentPos/(float)costFunction.size();
412          glVertex3f(x,0.0,0.0f);
413          glVertex3f(x,1.0f,0.0f);
414          glEnd();
415         
416          glColor3f(0.0f,0,0);
417          // show a grid
418          glBegin(GL_LINE_LOOP);
419          glVertex3f(0,0,0.0f);
420          glVertex3f(1,0,0.0f);
421          glVertex3f(1,1,0.0f);
422          glVertex3f(0,1,0.0f);
423          glEnd();
424
425          glBegin(GL_LINES);
426          for (int i=0;  i < 50000 && i < costFunction.size(); i+=10000) {
427                float x =  i/(float)costFunction.size();
428                glVertex3f(x,0.0,0.0f);
429                glVertex3f(x,1.0f,0.0f);
430          }
431
432          for (int i=0;  i < maxCost; i+=100) {
433                float y = i/(maxCost*0.5f);
434                glVertex3f(0,y,0.0f);
435                glVertex3f(1,y,0.0f);
436          }
437
438          glEnd();
439
440         
441          // restore the projection matrix
442          glMatrixMode(GL_PROJECTION);
443          glPopMatrix();
444          glMatrixMode(GL_MODELVIEW);
445          glEnable(GL_DEPTH_TEST);
446
447        }
448  }
449}
450
451
452void
453GlRenderer::SetupProjection(const int w, const int h, const float angle)
454{
455  glViewport(0, 0, w, h);
456  glMatrixMode(GL_PROJECTION);
457  glLoadIdentity();
458  gluPerspective(angle, 1.0, 0.1, 2.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
459  glMatrixMode(GL_MODELVIEW);
460}
461
462void
463GlRenderer::SetupCamera()
464{
465  Vector3 target = mViewPoint + mViewDirection;
466
467  Vector3 up(0,1,0);
468 
469  if (abs(DotProd(mViewDirection, up)) > 0.99f)
470        up = Vector3(1, 0, 0);
471 
472  glLoadIdentity();
473  gluLookAt(mViewPoint.x, mViewPoint.y, mViewPoint.z,
474                        target.x, target.y, target.z,
475                        up.x, up.y, up.z);
476}
477
478
479void
480GlRendererBuffer::EvalQueryWithItemBuffer(
481                                                                                  //RenderCostSample &sample
482                                                                           )
483{
484        // read back the texture
485        glReadPixels(0, 0,
486                                GetWidth(), GetHeight(),
487                                GL_RGBA,
488                                GL_UNSIGNED_BYTE,
489                                mPixelBuffer);
490               
491                       
492        unsigned int *p = mPixelBuffer;
493                       
494        for (int y = 0; y < GetHeight(); y++)
495        {
496                for (int x = 0; x < GetWidth(); x++, p++)
497                {
498                        unsigned int id = (*p) & 0xFFFFFF;
499
500                        if (id != 0xFFFFFF)
501                                ++ mObjects[id]->mCounter;
502                }
503        }
504}
505
506//std::ofstream outfile("try_arb.txt");
507void
508GlRendererBuffer::EvalQueryWithOcclusionQueries(
509                                                                           //RenderCostSample &sample
510                                                                           )
511{
512        glDepthFunc(GL_LEQUAL);
513               
514        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
515        glDepthMask(GL_FALSE);
516
517
518        // simulate detectemptyviewspace using backface culling
519        if (mDetectEmptyViewSpace)
520        {
521                glEnable(GL_CULL_FACE);
522                //cout << "culling" << endl;
523        }
524        else
525        {
526                //cout << "not culling" << endl;
527                glDisable(GL_CULL_FACE);
528        }
529
530       
531        //const int numQ = 1;
532        const int numQ = (int)mOcclusionQueries.size();
533       
534        //glFinish();
535#if 0
536        //-- now issue queries for all objects
537        for (int j = 0; j < (int)mObjects.size(); ++ j)
538        {
539                mOcclusionQueries[j]->BeginQuery();
540                RenderIntersectable(mObjects[j]);
541                mOcclusionQueries[j]->EndQuery();
542
543                unsigned int pixelCount;
544
545                pixelCount = mOcclusionQueries[j]->GetQueryResult();
546                mObjects[j]->mCounter += pixelCount;
547        }
548#else
549
550        int q = 0;
551
552        //-- now issue queries for all objects
553        for (int j = 0; j < (int)mObjects.size(); j += q)
554        {       
555                for (q = 0; ((j + q) < (int)mObjects.size()) && (q < numQ); ++ q)
556                {
557                        //glFinish();
558                        mOcclusionQueries[q]->BeginQuery();
559                       
560                        RenderIntersectable(mObjects[j + q]);
561               
562                        mOcclusionQueries[q]->EndQuery();
563                        //glFinish();
564                }
565                //cout << "q: " << q << endl;
566                // collect results of the queries
567                for (int t = 0; t < q; ++ t)
568                {
569                        unsigned int pixelCount;
570               
571                        //-- reenable other state
572#if 0
573                        bool available;
574
575                        do
576                        {
577                                available = mOcclusionQueries[t]->ResultAvailable();
578                               
579                                if (!available) cout << "W";
580                        }
581                        while (!available);
582#endif
583
584                        pixelCount = mOcclusionQueries[t]->GetQueryResult();
585
586                        //if (pixelCount > 0)
587                        //      cout <<"o="<<j+q<<" q="<<mOcclusionQueries[q]->GetQueryId()<<" pc="<<pixelCount<<" ";
588                        mObjects[j + t]->mCounter += pixelCount;
589                }
590
591                //j += q;
592        }
593#endif
594        //glFinish();
595        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
596        glDepthMask(GL_TRUE);
597       
598        glEnable(GL_CULL_FACE);
599}
600
601
602void
603GlRendererBuffer::EvalRenderCostSample(RenderCostSample &sample,
604                                                                           const bool useOcclusionQueries,
605                                                                           const int threshold
606                                                                           )
607{
608        // choose a random view point
609        mViewCellsManager->GetViewPoint(mViewPoint);
610        sample.mPosition = mViewPoint;
611        //cout << "viewpoint: " << mViewPoint << endl;
612
613        // take a render cost sample by rendering a cube
614        Vector3 directions[6];
615
616        directions[0] = Vector3(1,0,0);
617        directions[1] = Vector3(0,1,0);
618        directions[2] = Vector3(0,0,1);
619        directions[3] = Vector3(-1,0,0);
620        directions[4] = Vector3(0,-1,0);
621        directions[5] = Vector3(0,0,-1);
622
623        sample.mVisibleObjects = 0;
624
625        // reset object counters
626        ObjectContainer::const_iterator it, it_end = mObjects.end();
627
628        for (it = mObjects.begin(); it != it_end; ++ it)
629        {
630                (*it)->mCounter = 0;
631        }
632
633        ++ mFrame;
634
635        //glCullFace(GL_FRONT);
636        glCullFace(GL_BACK);
637        glDisable(GL_CULL_FACE);
638       
639
640        // query all 6 directions for a full point sample
641        for (int i = 0; i < 6; ++ i)
642        {
643                mViewDirection = directions[i];
644                SetupCamera();
645
646                glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
647                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
648                //glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);      glDepthMask(GL_TRUE);
649                glDepthFunc(GL_LESS);
650
651                mUseFalseColors = true;
652
653                // the actual scene rendering fills the depth (for occlusion queries)
654                // and the frame buffer (for item buffer)
655                RenderScene();
656
657
658                if (0)
659                {
660                        char filename[256];
661                        sprintf(filename, "snap/frame-%04d-%d.png", mFrame, i);
662                        QImage im = toImage();
663                        im.save(filename, "PNG");
664                }
665         
666                // evaluate the sample
667                if (useOcclusionQueries)
668                {
669                        EvalQueryWithOcclusionQueries();
670                }
671                else
672                {
673                        EvalQueryWithItemBuffer();
674                }
675        } 
676
677        // now evaluate the statistics over that sample
678        // currently only the number of visible objects is taken into account
679        sample.Reset();
680
681        for (it = mObjects.begin(); it != it_end; ++ it)
682        {
683                Intersectable *obj = *it;
684                if (obj->mCounter >= threshold)
685                {
686                        ++ sample.mVisibleObjects;
687                        sample.mVisiblePixels += obj->mCounter;
688                }
689        }
690
691        //cout << "RS=" << sample.mVisibleObjects << " ";
692}
693
694
695void
696GlRendererBuffer::SampleRenderCost(const int numSamples,
697                                                                   vector<RenderCostSample> &samples,
698                                                                   const bool useOcclusionQueries,
699                                                                   const int threshold
700                                                                   )
701{
702  makeCurrent();
703
704  if (mPixelBuffer == NULL)
705          mPixelBuffer = new unsigned int[GetWidth()*GetHeight()];
706 
707  // using 90 degree projection to capture 360 view with 6 samples
708  SetupProjection(GetHeight(), GetHeight(), 90.0f);
709
710  //samples.resize(numSamples);
711  halton.Reset();
712 
713  // the number of queries queried in batch mode
714  const int numQ = 500;
715
716  //const int numQ = (int)mObjects.size();
717  if (useOcclusionQueries)
718  {
719          cout << "\ngenerating " << numQ << " queries ... ";
720          OcclusionQuery::GenQueries(mOcclusionQueries, numQ);
721          cout << "finished" << endl;
722  }
723
724  // sampling queries
725  for (int i = 0; i < numSamples; ++ i)
726  {
727          cout << ".";
728          EvalRenderCostSample(samples[i], useOcclusionQueries, threshold);
729  }
730
731  doneCurrent();
732
733}
734 
735
736void
737GlRendererBuffer::RandomViewPoint()
738{
739  // do not use this function since it could return different viewpoints for
740  // different executions of the algorithm
741
742  //mViewCellsManager->GetViewPoint(mViewPoint);
743
744  while (1) {
745        Vector3 pVector = Vector3(halton.GetNumber(1),
746                                                          halton.GetNumber(2),
747                                                          halton.GetNumber(3));
748       
749        mViewPoint =  mSceneGraph->GetBox().GetPoint(pVector);
750        ViewCell *v = mViewCellsManager->GetViewCell(mViewPoint);
751        if (v && v->GetValid())
752          break;
753        // generate a new vector
754        halton.GenerateNext();
755  }
756 
757 
758  Vector3 dVector = Vector3(2*M_PI*halton.GetNumber(4),
759                                                        M_PI*halton.GetNumber(5),
760                                                        0.0f);
761 
762  mViewDirection = Normalize(Vector3(sin(dVector.x),
763                                                                         //                                                                      cos(dVector.y),
764                                                                         0.0f,
765                                                                         cos(dVector.x)));
766  halton.GenerateNext();
767}
768
769
770GlRendererBuffer::GlRendererBuffer(const int w,
771                                                                   const int h,
772                                                                   SceneGraph *sceneGraph,
773                                                                   ViewCellsManager *viewcells,
774                                                                   KdTree *tree):
775QGLPixelBuffer(QSize(w, h)), GlRenderer(sceneGraph, viewcells, tree) {
776 
777  Environment::GetSingleton()->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames);
778  mPvsErrorBuffer.resize(mPvsStatFrames);
779  ClearErrorBuffer();
780
781  mPixelBuffer = NULL;
782 
783  makeCurrent();
784  InitGL();
785  doneCurrent();
786 
787}
788
789float
790GlRendererBuffer::GetPixelError(int &pvsSize)
791{
792  float pErrorPixels = -1.0f;
793 
794  glReadBuffer(GL_BACK);
795 
796  //  mUseFalseColors = true;
797 
798  mUseFalseColors = false;
799  unsigned int pixelCount;
800
801  //static int query = -1;
802  //if (query == -1)
803//        glGenOcclusionQueriesNV(1, (unsigned int *)&query);
804
805  OcclusionQuery query;
806
807  if (mDetectEmptyViewSpace) {
808        // now check whether any backfacing polygon would pass the depth test
809        SetupCamera();
810        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
811        glEnable( GL_CULL_FACE );
812       
813        RenderScene();
814       
815        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
816        glDepthMask(GL_FALSE);
817        glDisable( GL_CULL_FACE );
818       
819        query.BeginQuery();
820       
821        RenderScene();
822       
823        query.EndQuery();
824       
825        // at this point, if possible, go and do some other computation
826        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
827        glDepthMask(GL_TRUE);
828        glEnable( GL_CULL_FACE );
829       
830        // reenable other state
831        pixelCount = query.GetQueryResult();
832       
833        if (pixelCount > 0)
834          return -1.0f; // backfacing polygon found -> not a valid viewspace sample
835  } else
836        glDisable( GL_CULL_FACE );
837       
838
839  ViewCell *viewcell = NULL;
840 
841  PrVs prvs;
842  //  mViewCellsManager->SetMaxFilterSize(1);
843  mViewCellsManager->GetPrVS(mViewPoint, prvs, mViewCellsManager->GetFilterWidth());
844  viewcell = prvs.mViewCell;
845 
846  //  ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
847  pvsSize = 0;
848  if (viewcell) {
849        SetupCamera();
850        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
851
852        glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
853       
854        // Render PVS
855        std::map<Intersectable *,
856          PvsData<Intersectable *>,
857          LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
858
859        pvsSize = viewcell->GetPvs().mEntries.size();
860       
861        for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
862          Intersectable *object = (*it).first;
863          RenderIntersectable(object);
864        }
865
866        //      glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
867        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
868        mUseFalseColors = true;
869
870        query.BeginQuery();
871
872        SetupCamera();
873
874        RenderScene();
875       
876        query.EndQuery();
877       
878
879        unsigned int pixelCount;
880        // reenable other state
881        pixelCount = query.GetQueryResult();
882       
883       
884        pErrorPixels = ((float)pixelCount)/(GetWidth()*GetHeight());
885        if (mSnapErrorFrames && pErrorPixels > 0.01) {
886         
887          char filename[256];
888          sprintf(filename, "error-frame-%04d-%0.5f.png", mFrame, pErrorPixels);
889          QImage im = toImage();
890          im.save(mSnapPrefix + filename, "PNG");
891          if (1) { //0 && mFrame == 1543) {
892                int x,y;
893                int lastIndex = -1;
894                for (y=0; y < im.height(); y++)
895                  for (x=0; x < im.width(); x++) {
896                        QRgb p = im.pixel(x,y);
897                        int index = qRed(p) + (qGreen(p)<<8) + (qBlue(p)<<16);
898                        if (qGreen(p) != 255 && index!=0) {
899                          if (index != lastIndex) {
900                                Debug<<"ei="<<index<<" ";
901                                lastIndex = index;
902                          }
903                        }
904                  }
905          }
906
907
908          mUseFalseColors = false;
909          glPushAttrib(GL_CURRENT_BIT);
910          glColor3f(0,1,0);
911          glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
912          SetupCamera();
913          glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
914         
915          // Render PVS
916          std::map<Intersectable *,
917                PvsData<Intersectable *>,
918                LtSample<Intersectable *> >::const_iterator it = viewcell->GetPvs().mEntries.begin();
919         
920          for (; it != viewcell->GetPvs().mEntries.end(); ++ it) {
921                Intersectable *object = (*it).first;
922                RenderIntersectable(object);
923          }
924
925          im = toImage();
926          sprintf(filename, "error-frame-%04d-%0.5f-pvs.png", mFrame, pErrorPixels);
927          im.save(mSnapPrefix + filename, "PNG");
928          glPopAttrib();
929        }
930        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
931  }
932
933  if (viewcell)
934        mViewCellsManager->DeleteLocalMergeTree(viewcell);
935 
936  return pErrorPixels;
937}
938
939
940void
941GlRendererWidget::SetupProjection(const int w, const int h, const float angle)
942{
943  if (!mTopView)
944        GlRenderer::SetupProjection(w, h, angle);
945  else {
946        glViewport(0, 0, w, h);
947        glMatrixMode(GL_PROJECTION);
948        glLoadIdentity();
949        gluPerspective(50.0, 1.0, 0.1, 20.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
950        glMatrixMode(GL_MODELVIEW);
951  }
952}
953
954void
955GlRendererWidget::RenderPvs()
956{
957  SetupCamera();
958  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
959 
960  ViewCell *viewcell = NULL;
961
962  PrVs prvs;
963 
964  if (!mUseFilter) {
965        viewcell = mViewCellsManager->GetViewCell(mViewPoint, true);
966  } else {
967        //  mViewCellsManager->SetMaxFilterSize(1);
968        mViewCellsManager->GetPrVS(mViewPoint, prvs, mViewCellsManager->GetFilterWidth());
969        viewcell = prvs.mViewCell;
970  }
971 
972  if (viewcell) {
973        // copy the pvs so that it can be filtered...
974        ObjectPvs pvs = viewcell->GetPvs();
975
976        if (mUseSpatialFilter) {
977          mViewCellsManager->ApplySpatialFilter(mKdTree,
978                                                                                        mSpatialFilterSize*
979                                                                                        Magnitude(mViewCellsManager->GetViewSpaceBox().Size()),
980                                                                                        pvs);
981        }
982       
983       
984        // read back the texture
985        std::map<Intersectable *,
986          PvsData<Intersectable *>,
987          LtSample<Intersectable *> >::const_iterator it = pvs.mEntries.begin();
988
989        mPvsSize = pvs.mEntries.size();
990         
991        for (; it != pvs.mEntries.end(); ++ it) {
992          Intersectable *object = (*it).first;
993          float visibility = log10((*it).second.mSumPdf + 1)/5.0f;
994          glColor3f(visibility, 0.0f, 0.0f);
995          mUseForcedColors = true;
996          RenderIntersectable(object);
997          mUseForcedColors = false;
998        }
999
1000        if (mRenderFilter) {
1001          mWireFrame = true;
1002          RenderIntersectable(viewcell);
1003          mWireFrame = false;
1004        }
1005       
1006        if (mUseFilter)
1007          mViewCellsManager->DeleteLocalMergeTree(viewcell);
1008  } else {
1009        ObjectContainer::const_iterator oi = mObjects.begin();
1010        for (; oi != mObjects.end(); oi++)
1011          RenderIntersectable(*oi);
1012  }
1013}
1014
1015float
1016GlRendererWidget::RenderErrors()
1017{
1018  float pErrorPixels = -1.0f;
1019
1020  glReadBuffer(GL_BACK);
1021 
1022  mUseFalseColors = true;
1023
1024  SetupCamera();
1025  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1026 
1027  double eq[4];
1028  eq[0] = mSceneCutPlane.mNormal.x;
1029  eq[1] = mSceneCutPlane.mNormal.y;
1030  eq[2] = mSceneCutPlane.mNormal.z;
1031  eq[3] = mSceneCutPlane.mD;
1032 
1033  if (mCutScene) {
1034        glClipPlane(GL_CLIP_PLANE0, eq);
1035    glEnable(GL_CLIP_PLANE0);
1036  }
1037 
1038  if (mDetectEmptyViewSpace)
1039        glEnable( GL_CULL_FACE );
1040  else
1041        glDisable( GL_CULL_FACE );
1042
1043  ObjectContainer::const_iterator oi = mObjects.begin();
1044  for (; oi != mObjects.end(); oi++)
1045        RenderIntersectable(*oi);
1046
1047  ViewCell *viewcell = NULL;
1048
1049  QImage im1, im2;
1050  QImage diff;
1051 
1052  if (viewcell) {
1053        // read back the texture
1054        im1 = grabFrameBuffer(true);
1055       
1056        RenderPvs();
1057
1058        // read back the texture
1059        im2 = grabFrameBuffer(true);
1060       
1061        diff = im1;
1062        int x, y;
1063        int errorPixels = 0;
1064       
1065        for (y = 0; y < im1.height(); y++)
1066          for (x = 0; x < im1.width(); x++)
1067                if (im1.pixel(x, y) == im2.pixel(x, y))
1068                  diff.setPixel(x, y, qRgba(0,0,0,0));
1069                else {
1070                  diff.setPixel(x, y, qRgba(255,128,128,255));
1071                  errorPixels++;
1072                }
1073        pErrorPixels = ((float)errorPixels)/(im1.height()*im1.width());
1074  }
1075
1076  // now render the pvs again
1077  SetupCamera();
1078  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1079  mUseFalseColors = false;
1080 
1081  oi = mObjects.begin();
1082  for (; oi != mObjects.end(); oi++)
1083        RenderIntersectable(*oi);
1084
1085  // now render im1
1086  if (viewcell) {
1087        if (0 && mTopView) {
1088          mWireFrame = true;
1089          RenderIntersectable(viewcell);
1090          mWireFrame = false;
1091        }
1092       
1093        // init ortographic projection
1094        glMatrixMode(GL_PROJECTION);
1095        glPushMatrix();
1096       
1097        glLoadIdentity();
1098        gluOrtho2D(0, 1.0f, 0, 1.0f);
1099       
1100        glMatrixMode(GL_MODELVIEW);
1101        glLoadIdentity();
1102       
1103        bindTexture(diff);
1104       
1105        glPushAttrib(GL_ENABLE_BIT);
1106        glEnable( GL_ALPHA_TEST );
1107        glDisable( GL_CULL_FACE );
1108        glAlphaFunc( GL_GREATER, 0.5 );
1109       
1110        glEnable( GL_TEXTURE_2D );
1111        glBegin(GL_QUADS);
1112       
1113        glTexCoord2f(0,0);
1114        glVertex3f(0,0,0);
1115       
1116        glTexCoord2f(1,0);
1117        glVertex3f( 1, 0, 0);
1118       
1119        glTexCoord2f(1,1);
1120        glVertex3f( 1, 1, 0);
1121       
1122        glTexCoord2f(0,1);
1123        glVertex3f(0, 1, 0);
1124        glEnd();
1125       
1126        glPopAttrib();
1127       
1128        // restore the projection matrix
1129        glMatrixMode(GL_PROJECTION);
1130        glPopMatrix();
1131        glMatrixMode(GL_MODELVIEW);
1132  }
1133
1134  glDisable(GL_CLIP_PLANE0);
1135 
1136  mRenderError = pErrorPixels;
1137  return pErrorPixels;
1138}
1139
1140void
1141GlRenderer::_RenderScene()
1142{
1143  ObjectContainer::const_iterator oi = mObjects.begin();
1144
1145  for (; oi != mObjects.end(); oi++)
1146        RenderIntersectable(*oi);
1147}
1148
1149bool
1150GlRenderer::RenderScene()
1151{
1152  static int glList = -1;
1153  if (mUseGlLists) {
1154        if (glList == -1) {
1155          glList = glGenLists(1);
1156          glNewList(glList, GL_COMPILE);
1157          _RenderScene();
1158          glEndList();
1159        }
1160        glCallList(glList);
1161  } else
1162        _RenderScene();
1163       
1164 
1165  return true;
1166}
1167
1168
1169void
1170GlRendererBuffer::ClearErrorBuffer()
1171{
1172  for (int i=0; i < mPvsStatFrames; i++) {
1173        mPvsErrorBuffer[i].mError = 1.0f;
1174  }
1175}
1176
1177
1178void
1179GlRendererBuffer::EvalPvsStat()
1180{
1181  mPvsStat.Reset();
1182  halton.Reset();
1183
1184  makeCurrent();
1185  SetupProjection(GetWidth(), GetHeight());
1186 
1187  for (int i=0; i < mPvsStatFrames; i++) {
1188        float err;
1189        // set frame id for saving the error buffer
1190        mFrame = i;
1191        RandomViewPoint();
1192
1193        // atlanta problematic frames: 325 525 691 1543
1194#if 0
1195        if (mFrame != 325 &&
1196                mFrame != 525 &&
1197                mFrame != 691 &&
1198                mFrame != 1543)
1199          mPvsErrorBuffer[i] = -1;
1200        else {
1201          Debug<<"frame ="<<mFrame<<" vp="<<mViewPoint<<" vd="<<mViewDirection<<endl;
1202        }
1203#endif
1204        if (mPvsErrorBuffer[i].mError > 0.0f) {
1205          int pvsSize;
1206          float error = GetPixelError(pvsSize);
1207          mPvsErrorBuffer[i].mError = error;
1208          mPvsErrorBuffer[i].mPvsSize = pvsSize;
1209
1210          emit UpdatePvsErrorItem(i,
1211                                                          mPvsErrorBuffer[i]);
1212         
1213          cout<<"("<<i<<","<<mPvsErrorBuffer[i].mError<<")";
1214          //      swapBuffers();
1215        }
1216       
1217        err = mPvsErrorBuffer[i].mError;
1218       
1219        if (err >= 0.0f) {
1220          if (err > mPvsStat.maxError)
1221                mPvsStat.maxError = err;
1222          mPvsStat.sumError += err;
1223          mPvsStat.sumPvsSize += mPvsErrorBuffer[i].mPvsSize;
1224         
1225          if (err == 0.0f)
1226                mPvsStat.errorFreeFrames++;
1227          mPvsStat.frames++;
1228        }
1229  }
1230
1231  glFinish();
1232  doneCurrent();
1233
1234  cout<<endl<<flush;
1235  //  mRenderingFinished.wakeAll();
1236}
1237
1238
1239
1240
1241
1242void
1243GlRendererWidget::mousePressEvent(QMouseEvent *e)
1244{
1245  int x = e->pos().x();
1246  int y = e->pos().y();
1247
1248  mousePoint.x = x;
1249  mousePoint.y = y;
1250 
1251}
1252
1253void
1254GlRendererWidget::mouseMoveEvent(QMouseEvent *e)
1255{
1256  float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3;
1257  float TURN_SENSITIVITY=0.1f;
1258  float TILT_SENSITIVITY=32.0 ;
1259  float TURN_ANGLE= M_PI/36.0 ;
1260
1261  int x = e->pos().x();
1262  int y = e->pos().y();
1263 
1264  if (e->modifiers() & Qt::ControlModifier) {
1265        mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0;
1266        mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0;
1267  } else {
1268        mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY);
1269        float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY;
1270        float angle = atan2(mViewDirection.x, mViewDirection.z);
1271        mViewDirection.x = sin(angle+adiff);
1272        mViewDirection.z = cos(angle+adiff);
1273  }
1274 
1275  mousePoint.x = x;
1276  mousePoint.y = y;
1277 
1278  updateGL();
1279}
1280
1281void
1282GlRendererWidget::mouseReleaseEvent(QMouseEvent *)
1283{
1284
1285
1286}
1287
1288void
1289GlRendererWidget::resizeGL(int w, int h)
1290{
1291  SetupProjection(w, h);
1292  updateGL();
1293}
1294
1295void
1296GlRendererWidget::paintGL()
1297{
1298  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1299
1300 
1301  if (!mRenderViewCells) {
1302        if (mRenderErrors)
1303          RenderErrors();
1304        else
1305          RenderPvs();
1306        RenderInfo();
1307  } else {
1308        RenderViewCells();
1309       
1310        mWireFrame = true;
1311        RenderScene();
1312        mWireFrame = false;
1313       
1314        RenderInfo();
1315  }
1316
1317  mFrame++;
1318}
1319
1320
1321void
1322GlRendererWidget::SetupCamera()
1323{
1324  if (!mTopView)
1325        GlRenderer::SetupCamera();
1326  else {
1327        if (0) {
1328          float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05;
1329          Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x,
1330                                                                                          -1,
1331                                                                                          mViewDirection.y);
1332         
1333          Vector3 target = mViewPoint + dist*mViewDirection;
1334          Vector3 up(0,1,0);
1335         
1336          glLoadIdentity();
1337          gluLookAt(pos.x, pos.y, pos.z,
1338                                target.x, target.y, target.z,
1339                                up.x, up.y, up.z);
1340        } else {
1341          float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*mTopDistance;
1342          Vector3 pos = mViewPoint  + dist*Vector3(0,
1343                                                                                           1,
1344                                                                                           0);
1345         
1346          Vector3 target = mViewPoint;
1347          Vector3 up(mViewDirection.x, 0, mViewDirection.z);
1348         
1349          glLoadIdentity();
1350          gluLookAt(pos.x, pos.y, pos.z,
1351                                target.x, target.y, target.z,
1352                                up.x, up.y, up.z);
1353         
1354        }
1355  }
1356
1357}
1358
1359void
1360GlRendererWidget::keyPressEvent ( QKeyEvent * e )
1361{
1362  switch (e->key()) {
1363  case Qt::Key_T:
1364        mTopView = !mTopView;
1365        SetupProjection(width(), height());
1366        updateGL();
1367        break;
1368  case Qt::Key_V:
1369        mRenderViewCells = !mRenderViewCells;
1370        updateGL();
1371        break;
1372  default:
1373        e->ignore();
1374        break;
1375  }
1376}
1377
1378 
1379RendererControlWidget::RendererControlWidget(QWidget * parent, Qt::WFlags f):
1380  QWidget(parent, f)
1381{
1382
1383  QVBoxLayout *vl = new QVBoxLayout;
1384  setLayout(vl);
1385 
1386  QWidget *vbox = new QGroupBox("ViewCells", this);
1387  layout()->addWidget(vbox);
1388 
1389  vl = new QVBoxLayout;
1390  vbox->setLayout(vl);
1391
1392  QLabel *label = new QLabel("Granularity");
1393  vbox->layout()->addWidget(label);
1394
1395  QSlider *slider = new QSlider(Qt::Horizontal, vbox);
1396  vl->addWidget(slider);
1397  slider->show();
1398  slider->setRange(1, 10000);
1399  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1400  slider->setValue(200);
1401
1402  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetViewCellGranularity(int)));
1403
1404  label = new QLabel("Filter size");
1405  vbox->layout()->addWidget(label);
1406 
1407  slider = new QSlider(Qt::Horizontal, vbox);
1408  vbox->layout()->addWidget(slider);
1409  slider->show();
1410  slider->setRange(1, 100);
1411  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1412  slider->setValue(3);
1413 
1414  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetVisibilityFilterSize(int)));
1415
1416
1417  label = new QLabel("Spatial Filter size");
1418  vbox->layout()->addWidget(label);
1419 
1420  slider = new QSlider(Qt::Horizontal, vbox);
1421  vbox->layout()->addWidget(slider);
1422  slider->show();
1423  slider->setRange(1, 100);
1424  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1425  slider->setValue(10);
1426 
1427  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSpatialFilterSize(int)));
1428
1429
1430
1431  QWidget *hbox = new QWidget(vbox);
1432  vl->addWidget(hbox);
1433  QHBoxLayout *hlayout = new QHBoxLayout;
1434  hbox->setLayout(hlayout);
1435 
1436  QCheckBox *cb = new QCheckBox("Show viewcells", hbox);
1437  hlayout->addWidget(cb);
1438  cb->setChecked(false);
1439  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowViewCells(bool)));
1440
1441  cb = new QCheckBox("Show render cost", hbox);
1442  hlayout->addWidget(cb);
1443  cb->setChecked(false);
1444  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowRenderCost(bool)));
1445
1446  cb = new QCheckBox("Show pvs sizes", hbox);
1447  hlayout->addWidget(cb);
1448  cb->setChecked(false);
1449  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowPvsSizes(bool)));
1450
1451  vbox->resize(800,100);
1452
1453 
1454  vbox = new QGroupBox("Rendering", this);
1455  layout()->addWidget(vbox);
1456 
1457  vl = new QVBoxLayout;
1458  vbox->setLayout(vl);
1459
1460
1461
1462  slider = new QSlider(Qt::Horizontal, vbox);
1463  vbox->layout()->addWidget(slider);
1464  slider->show();
1465  slider->setRange(0, 1000);
1466  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1467  slider->setValue(1000);
1468
1469  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSceneCut(int)));
1470
1471  cb = new QCheckBox("Render errors", vbox);
1472  vbox->layout()->addWidget(cb);
1473  cb->setChecked(false);
1474  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderErrors(bool)));
1475
1476  cb = new QCheckBox("Use filter", vbox);
1477  vbox->layout()->addWidget(cb);
1478  cb->setChecked(true);
1479  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseFilter(bool)));
1480
1481  cb = new QCheckBox("Use spatial filter", vbox);
1482  vbox->layout()->addWidget(cb);
1483  cb->setChecked(true);
1484  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseSpatialFilter(bool)));
1485
1486  cb = new QCheckBox("Render filter", vbox);
1487  vbox->layout()->addWidget(cb);
1488  cb->setChecked(true);
1489  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderFilter(bool)));
1490
1491
1492  cb = new QCheckBox("Cut view cells", vbox);
1493  vbox->layout()->addWidget(cb);
1494  cb->setChecked(false);
1495  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutViewCells(bool)));
1496
1497  cb = new QCheckBox("Cut scene", vbox);
1498  vbox->layout()->addWidget(cb);
1499  cb->setChecked(false);
1500  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutScene(bool)));
1501
1502 
1503  slider = new QSlider(Qt::Horizontal, vbox);
1504  vbox->layout()->addWidget(slider);
1505  slider->show();
1506  slider->setRange(1, 1000);
1507  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1508  slider->setValue(500);
1509 
1510  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetTopDistance(int)));
1511 
1512  cb = new QCheckBox("Top View", vbox);
1513  vbox->layout()->addWidget(cb);
1514  cb->setChecked(false);
1515  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetTopView(bool)));
1516
1517  vbox = new QGroupBox("PVS Errors", this);
1518  layout()->addWidget(vbox);
1519
1520  vl = new QVBoxLayout;
1521  vbox->setLayout(vl);
1522
1523  mPvsErrorWidget = new QListWidget(vbox);
1524  vbox->layout()->addWidget(mPvsErrorWidget);
1525 
1526  connect(mPvsErrorWidget,
1527                  SIGNAL(doubleClicked(const QModelIndex &)),
1528                  this,
1529                  SLOT(PvsErrorClicked(const QModelIndex &)));
1530 
1531  QPushButton *button = new QPushButton("Next Error Frame", vbox);
1532  vbox->layout()->addWidget(button);
1533  connect(button, SIGNAL(clicked(void)), SLOT(FocusNextPvsErrorFrame(void)));
1534
1535  setWindowTitle("Preprocessor Control Widget");
1536  adjustSize();
1537}
1538
1539
1540
1541void
1542RendererControlWidget::FocusNextPvsErrorFrame(void)
1543{
1544 
1545 
1546}
1547
1548void
1549RendererControlWidget::UpdatePvsErrorItem(int row,
1550                                                                                  GlRendererBuffer::PvsErrorEntry &pvsErrorEntry)
1551{
1552
1553  QListWidgetItem *i = mPvsErrorWidget->item(row);
1554  QString s;
1555  s.sprintf("%5.5f", pvsErrorEntry.mError);
1556  if (i) {
1557        i->setText(s);
1558  } else {
1559        new QListWidgetItem(s, mPvsErrorWidget);
1560  }
1561  mPvsErrorWidget->update();
1562}
1563
1564GlRendererWidget::GlRendererWidget(SceneGraph *sceneGraph,
1565                                                                   ViewCellsManager *viewcells,
1566                                                                   KdTree *tree,
1567                                                                   QWidget * parent,
1568                                                                   const QGLWidget * shareWidget,
1569                                                                   Qt::WFlags f
1570                                                                   )
1571  :
1572  GlRenderer(sceneGraph, viewcells, tree), QGLWidget(parent, shareWidget, f)
1573{
1574  mTopView = false;
1575  mRenderViewCells = false;
1576  mTopDistance = 1.0f;
1577  mCutViewCells = false;
1578  mCutScene = false;
1579  mRenderErrors = false;
1580  mRenderFilter = true;
1581  mUseFilter = true;
1582  mUseSpatialFilter = true;
1583  mShowRenderCost = false;
1584  mShowPvsSizes = false;
1585  mSpatialFilterSize = 0.01;
1586  mPvsSize = 0;
1587  mRenderError = 0.0f;
1588  mControlWidget = new RendererControlWidget(NULL);
1589 
1590  connect(mControlWidget, SIGNAL(SetViewCellGranularity(int)), this, SLOT(SetViewCellGranularity(int)));
1591  connect(mControlWidget, SIGNAL(SetSceneCut(int)), this, SLOT(SetSceneCut(int)));
1592  connect(mControlWidget, SIGNAL(SetTopDistance(int)), this, SLOT(SetTopDistance(int)));
1593
1594  connect(mControlWidget, SIGNAL(SetVisibilityFilterSize(int)), this, SLOT(SetVisibilityFilterSize(int)));
1595  connect(mControlWidget, SIGNAL(SetSpatialFilterSize(int)), this, SLOT(SetSpatialFilterSize(int)));
1596
1597  connect(mControlWidget, SIGNAL(SetShowViewCells(bool)), this, SLOT(SetShowViewCells(bool)));
1598  connect(mControlWidget, SIGNAL(SetShowRenderCost(bool)), this, SLOT(SetShowRenderCost(bool)));
1599  connect(mControlWidget, SIGNAL(SetShowPvsSizes(bool)), this, SLOT(SetShowPvsSizes(bool)));
1600  connect(mControlWidget, SIGNAL(SetTopView(bool)), this, SLOT(SetTopView(bool)));
1601  connect(mControlWidget, SIGNAL(SetCutViewCells(bool)), this, SLOT(SetCutViewCells(bool)));
1602  connect(mControlWidget, SIGNAL(SetCutScene(bool)), this, SLOT(SetCutScene(bool)));
1603  connect(mControlWidget, SIGNAL(SetRenderErrors(bool)), this, SLOT(SetRenderErrors(bool)));
1604  connect(mControlWidget, SIGNAL(SetRenderFilter(bool)), this, SLOT(SetRenderFilter(bool)));
1605  connect(mControlWidget, SIGNAL(SetUseFilter(bool)), this, SLOT(SetUseFilter(bool)));
1606  connect(mControlWidget, SIGNAL(SetUseSpatialFilter(bool)),
1607                  this, SLOT(SetUseSpatialFilter(bool)));
1608
1609 
1610  mControlWidget->show();
1611}
1612
1613void
1614GlRendererWidget::SetViewCellGranularity(int number)
1615{
1616  if (mViewCellsManager)
1617        //      mViewCellsManager->SetMaxFilterSize(number);
1618    mViewCellsManager->CollectViewCells(number);
1619
1620  updateGL();
1621}
1622
1623void
1624GlRendererWidget::SetVisibilityFilterSize(int number)
1625{
1626  if (mViewCellsManager)
1627        mViewCellsManager->SetMaxFilterSize(number);
1628  updateGL();
1629}
1630
1631void
1632GlRendererWidget::SetSpatialFilterSize(int number)
1633{
1634  mSpatialFilterSize = 1e-3*number;
1635  updateGL();
1636}
1637
1638void
1639GlRendererWidget::SetSceneCut(int number)
1640{
1641  // assume the cut plane can only be aligned with xz plane
1642  // shift it along y according to number, which is percentage of the bounding
1643  // box position
1644  if (mViewCellsManager) {
1645        AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
1646        Vector3 p = box.Min() + (number/1000.0f)*box.Max();
1647        mSceneCutPlane.mNormal = Vector3(0,-1,0);
1648        mSceneCutPlane.mD = -DotProd(mSceneCutPlane.mNormal, p);
1649        updateGL();
1650  }
1651}
1652
1653void
1654GlRendererWidget::SetTopDistance(int number)
1655{
1656  mTopDistance = number/1000.0f;
1657  updateGL();
1658}
1659
1660void
1661GlRendererWidget::RenderViewCells()
1662{
1663  mUseFalseColors = true;
1664
1665  SetupCamera();
1666  glEnable(GL_CULL_FACE);
1667  //glDisable(GL_CULL_FACE);
1668  glCullFace(GL_FRONT);
1669  double eq[4];
1670  eq[0] = mSceneCutPlane.mNormal.x;
1671  eq[1] = mSceneCutPlane.mNormal.y;
1672  eq[2] = mSceneCutPlane.mNormal.z;
1673  eq[3] = mSceneCutPlane.mD;
1674
1675  if (mCutViewCells) {
1676        glClipPlane(GL_CLIP_PLANE0, eq);
1677        glEnable(GL_CLIP_PLANE0);
1678  }
1679 
1680  int i;
1681  ViewCellContainer &viewcells = mViewCellsManager->GetViewCells();
1682  int maxPvs = -1;
1683  for (i=0; i < viewcells.size(); i++) {
1684        ViewCell *vc = viewcells[i];
1685        int p = vc->GetPvs().GetSize();
1686        if (p > maxPvs)
1687          maxPvs = p;
1688  }
1689
1690
1691  for (i=0; i < viewcells.size(); i++) {
1692        ViewCell *vc = viewcells[i];
1693        //      Mesh *m = vc->GetMesh();
1694
1695
1696        RgbColor c;
1697
1698        if (!mShowPvsSizes)
1699          c = vc->GetColor();
1700        else {
1701          float importance = (float)vc->GetPvs().GetSize() / (float)maxPvs;
1702          c = RgbColor(importance, 1.0f - importance, 0.0f);
1703        }
1704        glColor3f(c.r, c.g, c.b);
1705       
1706        RenderViewCell(vc);
1707  }
1708
1709  glDisable(GL_CLIP_PLANE0);
1710
1711}
1712
1713void GlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject,
1714                                                                                           Beam &beam,
1715                                                                                           const int desiredSamples,
1716                                                                                           BeamSampleStatistics &stat)
1717{
1718        // TODO: should be moved out of here (not to be done every time)
1719        // only back faces are interesting for the depth pass
1720        glShadeModel(GL_FLAT);
1721        glDisable(GL_LIGHTING);
1722
1723        // needed to kill the fragments for the front buffer
1724        glEnable(GL_ALPHA_TEST);
1725        glAlphaFunc(GL_GREATER, 0);
1726
1727        // assumes that the beam is constructed and contains kd-tree nodes
1728        // and viewcells which it intersects
1729 
1730 
1731        // Get the number of viewpoints to be sampled
1732        // Now it is a sqrt but in general a wiser decision could be made.
1733        // The less viewpoints the better for rendering performance, since less passes
1734        // over the beam is needed.
1735        // The viewpoints could actually be generated outside of the bounding box which
1736        // would distribute the 'efective viewpoints' of the object surface and thus
1737        // with a few viewpoints better sample the viewpoint space....
1738
1739        //TODO: comment in
1740        //int viewPointSamples = sqrt((float)desiredSamples);
1741        int viewPointSamples = max(desiredSamples / (GetWidth() * GetHeight()), 1);
1742       
1743        // the number of direction samples per pass is given by the number of viewpoints
1744        int directionalSamples = desiredSamples / viewPointSamples;
1745       
1746        Debug << "directional samples: " << directionalSamples << endl;
1747        for (int i = 0; i < viewPointSamples; ++ i)
1748        {
1749                Vector3 viewPoint = beam.mBox.GetRandomPoint();
1750               
1751                // perhaps the viewpoint should be shifted back a little bit so that it always lies
1752                // inside the source object
1753                // 'ideally' the viewpoints would be distributed on the soureObject surface, but this
1754        // would require more complicated sampling (perhaps hierarchical rejection sampling of
1755                // the object surface is an option here - only the mesh faces which are inside the box
1756                // are considered as candidates)
1757               
1758                SampleViewpointContributions(sourceObject,
1759                                                                         viewPoint,
1760                                                                         beam,
1761                                                                         directionalSamples,
1762                                                                         stat);
1763        }
1764
1765
1766        // note:
1767        // this routine would be called only if the number of desired samples is sufficiently
1768        // large - for other rss tree cells the cpu based sampling is perhaps more efficient
1769        // distributing the work between cpu and gpu would also allow us to place more sophisticated
1770        // sample distributions (silhouette ones) using the cpu and the jittered once on the GPU
1771        // in order that thios scheme is working well the gpu render buffer should run in a separate
1772        // thread than the cpu sampler, which would not be such a big problem....
1773
1774        // disable alpha test again
1775        glDisable(GL_ALPHA_TEST);
1776}
1777
1778
1779void GlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject,
1780                                                                                                        const Vector3 viewPoint,
1781                                                                                                        Beam &beam,
1782                                                                                                        const int samples,
1783                                                    BeamSampleStatistics &stat)
1784{
1785    // 1. setup the view port to match the desired samples
1786        glViewport(0, 0, samples, samples);
1787
1788        // 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox
1789        SetupProjectionForViewPoint(viewPoint, beam, sourceObject);
1790
1791
1792        // 3. reset z-buffer to 0 and render the source object for the beam
1793        //    with glCullFace(Enabled) and glFrontFace(GL_CW)
1794        //    save result to the front depth map
1795        //    the front depth map holds ray origins
1796
1797
1798        // front depth buffer must be initialised to 0
1799        float clearDepth;
1800       
1801        glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
1802        glClearDepth(0.0f);
1803        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1804
1805
1806        //glFrontFace(GL_CW);
1807        glEnable(GL_CULL_FACE);
1808        glCullFace(GL_FRONT);
1809        glColorMask(0, 0, 0, 0);
1810       
1811
1812        // stencil is increased where the source object is located
1813        glEnable(GL_STENCIL_TEST);     
1814        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
1815        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1816
1817
1818#if 0
1819        static int glSourceObjList = -1;         
1820        if (glSourceObjList != -1)
1821        {
1822                glSourceObjList = glGenLists(1);
1823                glNewList(glSourceObjList, GL_COMPILE);
1824
1825                RenderIntersectable(sourceObject);
1826       
1827                glEndList();
1828        }
1829        glCallList(glSourceObjList);
1830
1831#else
1832        RenderIntersectable(sourceObject);
1833
1834#endif 
1835
1836         // copy contents of the front depth buffer into depth texture
1837        glBindTexture(GL_TEXTURE_2D, frontDepthMap);   
1838        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
1839
1840
1841        // reset clear function
1842        glClearDepth(clearDepth);
1843
1844       
1845       
1846        // 4. set up the termination depth buffer (= standard depth buffer)
1847        //    only rays which have non-zero entry in the origin buffer are valid since
1848        //    they realy start on the object surface (this is tagged by setting a
1849        //    stencil buffer bit at step 3).
1850       
1851        glStencilFunc(GL_EQUAL, 0x1, 0x1);
1852        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1853
1854        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1855        glDepthMask(1);
1856
1857        glEnable(GL_DEPTH_TEST);
1858               
1859        glEnable(GL_CULL_FACE);
1860        glCullFace(GL_BACK);
1861
1862        // setup front depth buffer
1863        glEnable(GL_TEXTURE_2D);
1864       
1865        // bind pixel shader implementing the front depth buffer functionality
1866        cgGLBindProgram(sCgFragmentProgram);
1867        cgGLEnableProfile(sCgFragmentProfile);
1868
1869
1870        // 5. render all objects inside the beam
1871        //    we can use id based false color to read them back for gaining the pvs
1872
1873        glColorMask(1, 1, 1, 1);
1874
1875       
1876        // if objects not stored in beam => extract objects
1877        if (beam.mFlags & !Beam::STORE_OBJECTS)
1878        {
1879                vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
1880
1881                Intersectable::NewMail();
1882                for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
1883                {
1884                        mKdTree->CollectObjects(*it, beam.mObjects);
1885                }
1886        }
1887
1888
1889        //    (objects can be compiled to a gl list now so that subsequent rendering for
1890        //    this beam is fast - the same hold for step 3)
1891        //    Afterwards we have two depth buffers defining the ray origin and termination
1892       
1893
1894#if 0
1895        static int glObjList = -1;
1896        if (glObjList != -1)
1897        {
1898                glObjList = glGenLists(1);
1899                glNewList(glObjList, GL_COMPILE);
1900       
1901                ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
1902                for (it = beam.mObjects.begin(); it != it_end; ++ it)
1903                {
1904                        // render all objects except the source object
1905                        if (*it != sourceObject)
1906                                RenderIntersectable(*it);
1907                }
1908               
1909                glEndList();
1910        }
1911
1912        glCallList(glObjList);
1913#else
1914        ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
1915        for (it = beam.mObjects.begin(); it != it_end; ++ it)
1916        {       
1917                // render all objects except the source object
1918                if (*it != sourceObject)
1919                        RenderIntersectable(*it);
1920        }
1921#endif
1922       
1923   
1924
1925        // 6. Use occlusion queries for all viewcell meshes associated with the beam ->
1926        //     a fragment passes if the corresponding stencil fragment is set and its depth is
1927        //     between origin and termination buffer
1928
1929        // create new queries if necessary
1930        OcclusionQuery::GenQueries(sQueries, (int)beam.mViewCells.size());
1931
1932        // check whether any backfacing polygon would pass the depth test?
1933        // matt: should check both back /front facing because of dual depth buffer
1934        // and danger of cutting the near plane with front facing polys.
1935       
1936        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1937        glDepthMask(GL_FALSE);
1938        glDisable(GL_CULL_FACE);
1939
1940 
1941        ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end();
1942
1943        int queryIdx = 0;
1944
1945        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
1946        {
1947                sQueries[queryIdx ++]->BeginQuery();
1948
1949                RenderIntersectable(*vit);
1950               
1951                sQueries[queryIdx]->EndQuery();
1952
1953                ++ queryIdx;
1954        }
1955
1956
1957
1958        // at this point, if possible, go and do some other computation
1959
1960
1961       
1962        // 7. The number of visible pixels is the number of sample rays which see the source
1963        //    object from the corresponding viewcell -> remember these values for later update
1964        //   of the viewcell pvs - or update immediately?
1965
1966        queryIdx = 0;
1967
1968        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
1969        {
1970                // fetch queries
1971                unsigned int pixelCount = sQueries[queryIdx ++]->GetQueryResult();
1972
1973                if (pixelCount)
1974                        Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl;
1975        }
1976       
1977
1978        // 8. Copmpute rendering statistics
1979        // In general it is not neccessary to remember to extract all the rays cast. I hope it
1980        // would be sufficient to gain only the intergral statistics about the new contributions
1981        // and so the rss tree would actually store no new rays (only the initial ones)
1982        // the subdivision of the tree would only be driven by the statistics (the glrender could
1983        // evaluate the contribution entropy for example)
1984        // However might be an option to extract/store only those the rays which made a contribution
1985        // (new viewcell has been discovered) or relative contribution greater than a threshold ...
1986
1987        ObjectContainer pvsObj;
1988        stat.pvsSize = ComputePvs(beam.mObjects, pvsObj);
1989       
1990        // to gain ray source and termination
1991        // copy contents of ray termination buffer into depth texture
1992        // and compare with ray source buffer
1993#if 0
1994        VssRayContainer rays;
1995
1996        glBindTexture(GL_TEXTURE_2D, backDepthMap);     
1997        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
1998
1999        ComputeRays(Intersectable *sourceObj, rays);
2000
2001#endif
2002
2003
2004
2005        //-- cleanup
2006
2007
2008        // reset gl state
2009        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2010        glDepthMask(GL_TRUE);
2011        glEnable(GL_CULL_FACE);
2012        glDisable(GL_STENCIL_TEST);
2013        cgGLDisableProfile(sCgFragmentProfile);
2014        glDisable(GL_TEXTURE_2D);
2015
2016        // remove objects from beam
2017        if (beam.mFlags & !Beam::STORE_OBJECTS)
2018                beam.mObjects.clear();
2019}
2020
2021
2022void GlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint,
2023                                                                                                   const Beam &beam,
2024                                                                                                   Intersectable *sourceObject)
2025{
2026        float left, right, bottom, top, znear, zfar;
2027
2028        beam.ComputePerspectiveFrustum(left, right, bottom, top, znear, zfar,
2029                                                                   mSceneGraph->GetBox());
2030
2031        //Debug << left << " " << right << " " << bottom << " " << top << " " << znear << " " << zfar << endl;
2032        glMatrixMode(GL_PROJECTION);
2033        glLoadIdentity();
2034        glFrustum(left, right, bottom, top, znear, zfar);
2035        //glFrustum(-1, 1, -1, 1, 1, 20000);
2036
2037    const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3f;
2038        const Vector3 up =
2039                Normalize(CrossProd(beam.mPlanes[0].mNormal, beam.mPlanes[4].mNormal));
2040
2041#ifdef _DEBUG
2042        Debug << "view point: " << viewPoint << endl;
2043        Debug << "eye: " << center << endl;
2044        Debug << "up: " << up << endl;
2045#endif
2046
2047        glMatrixMode(GL_MODELVIEW);
2048        glLoadIdentity();
2049        gluLookAt(viewPoint.x, viewPoint.y, viewPoint.z,
2050                          center.x, center.y, center.z,                   
2051                          up.x, up.y, up.z);
2052}               
2053
2054 
2055void GlRendererBuffer::InitGL()
2056{
2057 makeCurrent();
2058 GlRenderer::InitGL();
2059
2060#if 1
2061        // initialise dual depth buffer textures
2062        glGenTextures(1, &frontDepthMap);
2063        glBindTexture(GL_TEXTURE_2D, frontDepthMap);
2064       
2065        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
2066                depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
2067        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2068        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2069        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2070        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2071
2072        glGenTextures(1, &backDepthMap);
2073        glBindTexture(GL_TEXTURE_2D, backDepthMap);
2074       
2075        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
2076                depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
2077        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2078        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2079        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
2080        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
2081
2082        // cg initialization
2083        cgSetErrorCallback(handleCgError);
2084        sCgContext = cgCreateContext();
2085       
2086        if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
2087                sCgFragmentProfile = CG_PROFILE_ARBFP1;
2088        else
2089        {
2090          // try FP30
2091          if (cgGLIsProfileSupported(CG_PROFILE_FP30))
2092            sCgFragmentProfile = CG_PROFILE_FP30;
2093          else
2094          {
2095                  Debug << "Neither arbfp1 or fp30 fragment profiles supported on this system" << endl;
2096                  exit(1);
2097          }
2098  }
2099
2100
2101 sCgFragmentProgram = cgCreateProgramFromFile(sCgContext,
2102                                                                                           CG_SOURCE, "../src/dual_depth.cg",
2103                                                                                           sCgFragmentProfile,
2104                                                                                           NULL,
2105                                                                                           NULL);
2106
2107  if (!cgIsProgramCompiled(sCgFragmentProgram))
2108          cgCompileProgram(sCgFragmentProgram);
2109
2110  cgGLLoadProgram(sCgFragmentProgram);
2111  cgGLBindProgram(sCgFragmentProgram);
2112
2113  Debug << "---- PROGRAM BEGIN ----\n" <<
2114          cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
2115
2116#endif
2117  doneCurrent();
2118}
2119
2120
2121void GlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays)
2122{
2123        for (int i = 0; i < depthMapSize * depthMapSize; ++ i)
2124        {
2125                //todo glGetTexImage()
2126        }
2127}
2128
2129
2130
2131inline bool ilt(Intersectable *obj1, Intersectable *obj2)
2132{
2133        return obj1->mId < obj2->mId;
2134}
2135
2136
2137int GlRendererBuffer::ComputePvs(ObjectContainer &objects,
2138                                                                 ObjectContainer &pvs) const
2139{
2140        int pvsSize = 0;
2141        QImage image = toImage();
2142        Intersectable::NewMail();
2143
2144        std::stable_sort(objects.begin(), objects.end(), ilt);
2145
2146        MeshInstance dummy(NULL);
2147
2148        Intersectable *obj = NULL;
2149                       
2150        for (int x = 0; x < image.width(); ++ x)
2151        {
2152                for (int y = 0; y < image.height(); ++ y)
2153                {
2154                        QRgb pix = image.pixel(x, y);
2155                        const int id = GetId(qRed(pix), qGreen(pix), qBlue(pix));
2156
2157                        dummy.SetId(id);
2158
2159                        ObjectContainer::iterator oit =
2160                                lower_bound(objects.begin(), objects.end(), &dummy, ilt);
2161                       
2162                       
2163                        if (//(oit != oit.end()) &&
2164                                ((*oit)->GetId() == id) &&
2165                                !obj->Mailed())
2166                        {
2167                                obj = *oit;
2168                                obj->Mail();
2169                                ++ pvsSize;
2170                                pvs.push_back(obj);
2171                        }
2172                }
2173        }
2174
2175        return pvsSize;
2176}
2177
2178/***********************************************************************/
2179/*                     GlDebuggerWidget implementation                             */
2180/***********************************************************************/
2181
2182
2183GlDebuggerWidget::GlDebuggerWidget(GlRendererBuffer *buf, QWidget *parent)
2184      : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf)
2185{
2186        // create the pbuffer
2187    //pbuffer = new QGLPixelBuffer(QSize(512, 512), format(), this);
2188    timerId = startTimer(20);
2189    setWindowTitle(("OpenGL pbuffers"));
2190}
2191
2192
2193GlDebuggerWidget::~GlDebuggerWidget()
2194{
2195 mRenderBuffer->releaseFromDynamicTexture();
2196   glDeleteTextures(1, &dynamicTexture);
2197         
2198         DEL_PTR(mRenderBuffer);
2199}
2200
2201
2202void GlDebuggerWidget::initializeGL()
2203{
2204        glMatrixMode(GL_PROJECTION);
2205        glLoadIdentity();
2206
2207        glFrustum(-1, 1, -1, 1, 10, 100);
2208        glTranslatef(-0.5f, -0.5f, -0.5f);
2209        glTranslatef(0.0f, 0.0f, -15.0f);
2210        glMatrixMode(GL_MODELVIEW);
2211
2212        glEnable(GL_CULL_FACE);
2213        initCommon();
2214        initPbuffer();
2215
2216}
2217
2218
2219void GlDebuggerWidget::resizeGL(int w, int h)
2220{
2221        glViewport(0, 0, w, h);
2222}
2223
2224
2225void GlDebuggerWidget::paintGL()
2226{
2227        // draw a spinning cube into the pbuffer..
2228        mRenderBuffer->makeCurrent();
2229       
2230        BeamSampleStatistics stats;
2231        mRenderBuffer->SampleBeamContributions(mSourceObject, mBeam, mSamples, stats);
2232
2233        glFlush();
2234
2235        // rendering directly to a texture is not supported on X11, unfortunately
2236    mRenderBuffer->updateDynamicTexture(dynamicTexture);
2237   
2238    // and use the pbuffer contents as a texture when rendering the
2239    // background and the bouncing cubes
2240    makeCurrent();
2241    glBindTexture(GL_TEXTURE_2D, dynamicTexture);
2242    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2243
2244    // draw the background
2245    glMatrixMode(GL_MODELVIEW);
2246    glPushMatrix();
2247    glLoadIdentity();
2248    glMatrixMode(GL_PROJECTION);
2249    glPushMatrix();
2250    glLoadIdentity();
2251
2252        glPopMatrix();
2253        glMatrixMode(GL_MODELVIEW);
2254        glPopMatrix();
2255}
2256
2257
2258void GlDebuggerWidget::initPbuffer()
2259{
2260        // set up the pbuffer context
2261    mRenderBuffer->makeCurrent();
2262        /*mRenderBuffer->InitGL();
2263
2264        glViewport(0, 0, mRenderBuffer->size().width(), mRenderBuffer->size().height());
2265        glMatrixMode(GL_PROJECTION);
2266        glLoadIdentity();
2267        glOrtho(-1, 1, -1, 1, -99, 99);
2268        glTranslatef(-0.5f, -0.5f, 0.0f);
2269        glMatrixMode(GL_MODELVIEW);
2270        glLoadIdentity();
2271
2272        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/
2273       
2274        // generate a texture that has the same size/format as the pbuffer
2275    dynamicTexture = mRenderBuffer->generateDynamicTexture();
2276
2277        // bind the dynamic texture to the pbuffer - this is a no-op under X11
2278        mRenderBuffer->bindToDynamicTexture(dynamicTexture);
2279        makeCurrent();
2280}
2281
2282void GlDebuggerWidget::initCommon()
2283{
2284        glEnable(GL_TEXTURE_2D);
2285        glEnable(GL_DEPTH_TEST);
2286
2287        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
2288}
2289
2290}
Note: See TracBrowser for help on using the repository browser.