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

Revision 2006, 35.0 KB checked in by bittner, 17 years ago (diff)

merge

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