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

Revision 1785, 33.8 KB checked in by bittner, 18 years ago (diff)

merge, filter update, renderebuffer made functional

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