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

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