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

Revision 2687, 47.4 KB checked in by mattausch, 16 years ago (diff)

gvs testing

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