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

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