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

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