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

Revision 2662, 47.8 KB checked in by mattausch, 16 years ago (diff)

working on gvs pixel error evaluation bugfixing

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