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

Revision 2690, 46.9 KB checked in by mattausch, 16 years ago (diff)

strange errors!!

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