source: GTP/trunk/Lib/Vis/Preprocessing/src/QtGlRenderer/QtGlRenderer.cpp @ 1935

Revision 1935, 47.6 KB checked in by mattausch, 18 years ago (diff)

started depth peeling

Line 
1#include "Mesh.h"
2#include "glInterface.h"
3#include "OcclusionQuery.h"
4#include "QtGlRenderer.h"
5#include "ViewCellsManager.h"
6#include "SceneGraph.h"
7#include "Pvs.h"
8#include "Viewcell.h"
9#include "Beam.h"
10#include "KdTree.h"
11#include "Environment.h"
12#include <Cg/cg.h>
13#include <Cg/cgGL.h>
14
15#include <QVBoxLayout>
16
17namespace GtpVisibilityPreprocessor {
18
19class ViewCellsManager;
20
21static CGcontext sCgContext = NULL;
22static CGprogram sCgFragmentProgram = NULL;
23static CGprogram sCgDepthPeelingProgram = NULL;
24static CGprofile sCgFragmentProfile;
25
26static GLuint frontDepthMap;
27static GLuint backDepthMap;
28
29const int depthMapSize = 512;
30
31QtGlRendererWidget *rendererWidget = NULL;
32QtGlDebuggerWidget *debuggerWidget = NULL;
33
34
35static inline bool ilt(Intersectable *obj1, Intersectable *obj2)
36{
37        return obj1->mId < obj2->mId;
38}
39
40
41static void handleCgError()
42{
43    Debug << "Cg error: " << cgGetErrorString(cgGetError()) << endl;
44    exit(1);
45}
46
47void
48QtGlRendererBuffer::EvalRenderCostSample(RenderCostSample &sample,
49                                                                                 const bool useOcclusionQueries,
50                                                                                 const int threshold
51                                                                                 )
52{
53        // choose a random view point
54        mViewCellsManager->GetViewPoint(mViewPoint);
55        sample.mPosition = mViewPoint;
56
57        // take a render cost sample by rendering a cube
58        Vector3 directions[6];
59
60        directions[0] = Vector3(1,0,0);
61        directions[1] = Vector3(0,1,0);
62        directions[2] = Vector3(0,0,1);
63        directions[3] = Vector3(-1,0,0);
64        directions[4] = Vector3(0,-1,0);
65        directions[5] = Vector3(0,0,-1);
66
67        sample.mVisibleObjects = 0;
68
69        // reset object counters
70        ObjectContainer::const_iterator it, it_end = mObjects.end();
71
72        for (it = mObjects.begin(); it != it_end; ++ it)
73        {
74                (*it)->mCounter = 0;
75        }
76
77        ++ mFrame;
78
79        //glCullFace(GL_FRONT);
80        glCullFace(GL_BACK);
81        glDisable(GL_CULL_FACE);
82       
83
84        // query all 6 directions for a full point sample
85        for (int i = 0; i < 6; ++ i)
86        {
87                mViewDirection = directions[i];
88                SetupCamera();
89
90                glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
91                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
92                //glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);      glDepthMask(GL_TRUE);
93                glDepthFunc(GL_LESS);
94
95                mUseFalseColors = true;
96
97                // the actual scene rendering fills the depth (for occlusion queries)
98                // and the frame buffer (for item buffer)
99                RenderScene();
100
101
102                if (0)
103                {
104                        char filename[256];
105                        sprintf(filename, "snap/frame-%04d-%d.png", mFrame, i);
106                        QImage im = toImage();
107                        im.save(filename, "PNG");
108                }
109         
110                // evaluate the sample
111                if (useOcclusionQueries)
112                {
113                        EvalQueryWithOcclusionQueries();
114                }
115                else
116                {
117                        EvalQueryWithItemBuffer();
118                }
119        } 
120
121        // now evaluate the statistics over that sample
122        // currently only the number of visible objects is taken into account
123        sample.Reset();
124
125        for (it = mObjects.begin(); it != it_end; ++ it)
126        {
127                Intersectable *obj = *it;
128                if (obj->mCounter >= threshold)
129                {
130                        ++ sample.mVisibleObjects;
131                        sample.mVisiblePixels += obj->mCounter;
132                }
133        }
134
135        //cout << "RS=" << sample.mVisibleObjects << " ";
136}
137
138
139QtGlRendererBuffer::~QtGlRendererBuffer()
140{
141        if (sCgFragmentProgram)
142                cgDestroyProgram(sCgFragmentProgram);
143        if (sCgDepthPeelingProgram)
144                cgDestroyProgram(sCgDepthPeelingProgram);
145        if (sCgContext)
146                cgDestroyContext(sCgContext);
147}
148
149
150void
151QtGlRendererBuffer::SampleRenderCost(const int numSamples,
152                                                                         vector<RenderCostSample> &samples,
153                                                                         const bool useOcclusionQueries,
154                                                                         const int threshold
155                                                                         )
156{
157  makeCurrent();
158
159  if (mPixelBuffer == NULL)
160          mPixelBuffer = new unsigned int[GetWidth()*GetHeight()];
161 
162  // using 90 degree projection to capture 360 view with 6 samples
163  SetupProjection(GetHeight(), GetHeight(), 90.0f);
164
165  //samples.resize(numSamples);
166  halton.Reset();
167 
168  // the number of queries queried in batch mode
169  const int numQ = 500;
170
171  //const int numQ = (int)mObjects.size();
172  if (useOcclusionQueries)
173  {
174          cout << "\ngenerating " << numQ << " queries ... ";
175          OcclusionQuery::GenQueries(mOcclusionQueries, numQ);
176          cout << "finished" << endl;
177  }
178
179  // sampling queries
180  for (int i = 0; i < numSamples; ++ i)
181  {
182          cout << ".";
183          EvalRenderCostSample(samples[i], useOcclusionQueries, threshold);
184  }
185
186  doneCurrent();
187
188}
189 
190
191
192QtGlRendererBuffer::QtGlRendererBuffer(const int w,
193                                                                           const int h,
194                                                                           SceneGraph *sceneGraph,
195                                                                           ViewCellsManager *viewcells,
196                                                                           KdTree *tree):
197  QGLPixelBuffer(QSize(w, h)),
198GlRendererBuffer(sceneGraph, viewcells, tree) {
199 
200  Environment::GetSingleton()->GetIntValue("Preprocessor.pvsRenderErrorSamples", mPvsStatFrames);
201  mPvsErrorBuffer.resize(mPvsStatFrames);
202  ClearErrorBuffer();
203
204  mPixelBuffer = NULL;
205 
206  makeCurrent();
207  InitGL();
208  doneCurrent();
209 
210}
211
212float
213QtGlRendererBuffer::GetPixelError(int &pvsSize)
214{
215        float pErrorPixels = -1.0f;
216
217        glReadBuffer(GL_BACK);
218
219        mUseFalseColors = false;
220        unsigned int pixelCount;
221
222        OcclusionQuery query;
223
224        if (mDetectEmptyViewSpace)
225        {
226                // now check whether any backfacing polygon would pass the depth test
227                SetupCamera();
228                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
229                glEnable( GL_CULL_FACE );
230
231                RenderScene();
232
233                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
234                glDepthMask(GL_FALSE);
235                glDisable( GL_CULL_FACE );
236
237
238                query.BeginQuery();
239
240                RenderScene();
241
242                query.EndQuery();
243
244                // at this point, if possible, go and do some other computation
245                glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
246                glDepthMask(GL_TRUE);
247                glEnable( GL_CULL_FACE );
248
249                // reenable other state
250                pixelCount = query.GetQueryResult();
251
252                if (pixelCount > 0)
253                        return -1.0f; // backfacing polygon found -> not a valid viewspace sample
254        }
255        else
256        {
257                glDisable( GL_CULL_FACE );
258        }
259
260        ViewCell *viewcell = NULL;
261
262        PrVs prvs;
263
264        mViewCellsManager->SetMaxFilterSize(0);
265        mViewCellsManager->GetPrVS(mViewPoint, prvs, mViewCellsManager->GetFilterWidth());
266        viewcell = prvs.mViewCell;
267
268        // ViewCell *viewcell = mViewCellsManager->GetViewCell(mViewPoint);
269        pvsSize = 0;
270        if (viewcell)
271        {
272                SetupCamera();
273                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
274
275                glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_FALSE);
276
277                // Render PVS
278                ObjectPvsIterator pit = viewcell->GetPvs().GetIterator();
279
280                while (pit.HasMoreEntries())
281                {               
282                        const ObjectPvsEntry &entry = pit.Next();
283                        Intersectable *obj = entry.mObject;
284
285                        RenderIntersectable(obj);
286                }
287
288                // glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_FALSE);
289                glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
290                mUseFalseColors = true;
291
292                query.BeginQuery();
293
294                SetupCamera();
295
296                RenderScene();
297
298                query.EndQuery();
299
300                unsigned int pixelCount;
301                // reenable other state
302                pixelCount = query.GetQueryResult();
303
304                pErrorPixels = ((float)pixelCount)/(GetWidth()*GetHeight());
305                if (mSnapErrorFrames && pErrorPixels > 0.01)
306                {
307            char filename[256];
308
309                        sprintf(filename, "error-frame-%04d-%0.5f.png", mFrame, pErrorPixels);
310                        QImage im = toImage();
311                        string str = mSnapPrefix + filename;
312                        QString qstr(str.c_str());
313
314                        im.save(qstr, "PNG");
315                        if (1)
316                        {
317                                int x,y;
318                                int lastIndex = -1;
319                                for (y=0; y < im.height(); y++)
320                                {
321                                        for (x=0; x < im.width(); x++)
322                                        {
323                                                QRgb p = im.pixel(x,y);
324
325                                                int index = qRed(p) + (qGreen(p)<<8) + (qBlue(p)<<16);
326                                               
327                                                if (qGreen(p) != 255 && index!=0)
328                                                {
329                                                        if (index != lastIndex)
330                                                        {
331                                                                lastIndex = index;
332                                                        }
333                                                }
334                                        }
335                                }
336                        }
337
338                        mUseFalseColors = false;
339                        glPushAttrib(GL_CURRENT_BIT);
340                        glColor3f(0,1,0);
341                        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
342                        SetupCamera();
343                        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
344
345                        // Render PVS
346                        ObjectPvsIterator pit = viewcell->GetPvs().GetIterator();
347
348                        while (pit.HasMoreEntries())
349                        {               
350                                const ObjectPvsEntry &entry = pit.Next();
351                                Intersectable *obj = entry.mObject;
352
353                                RenderIntersectable(obj);
354                        }
355
356                        im = toImage();
357                        sprintf(filename, "error-frame-%04d-%0.5f-pvs.png", mFrame, pErrorPixels);
358                        str = mSnapPrefix + filename;
359                        qstr = str.c_str();
360                        im.save(qstr, "PNG");
361                        glPopAttrib();
362                }
363                glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
364        }
365
366        if (viewcell && mViewCellsManager->GetMaxFilterSize() > 0)
367                mViewCellsManager->DeleteLocalMergeTree(viewcell);
368
369        return pErrorPixels;
370}
371
372
373void
374QtGlRendererBuffer::ClearErrorBuffer()
375{
376  for (int i=0; i < mPvsStatFrames; i++) {
377        mPvsErrorBuffer[i].mError = 1.0f;
378  }
379}
380
381
382void
383QtGlRendererBuffer::EvalPvsStat()
384{
385  mPvsStat.Reset();
386  halton.Reset();
387
388  makeCurrent();
389
390
391  SetupProjection(GetWidth(), GetHeight());
392
393 
394  for (int i=0; i < mPvsStatFrames; i++) {
395        float err;
396        // set frame id for saving the error buffer
397        mFrame = i;
398        RandomViewPoint();
399
400        // atlanta problematic frames: 325 525 691 1543
401#if 0
402        if (mFrame != 325 &&
403                mFrame != 525 &&
404                mFrame != 691 &&
405                mFrame != 1543)
406          mPvsErrorBuffer[i] = -1;
407        else {
408          Debug<<"frame ="<<mFrame<<" vp="<<mViewPoint<<" vd="<<mViewDirection<<endl;
409        }
410#endif
411        if (mPvsErrorBuffer[i].mError > 0.0f) {
412          int pvsSize;
413
414
415          float error = GetPixelError(pvsSize);
416          mPvsErrorBuffer[i].mError = error;
417          mPvsErrorBuffer[i].mPvsSize = pvsSize;
418
419          emit UpdatePvsErrorItem(i,
420                                                          mPvsErrorBuffer[i]);
421         
422          cout<<"("<<i<<","<<mPvsErrorBuffer[i].mError<<")";
423          //      swapBuffers();
424        }
425       
426        err = mPvsErrorBuffer[i].mError;
427       
428        if (err >= 0.0f) {
429          if (err > mPvsStat.maxError)
430                mPvsStat.maxError = err;
431          mPvsStat.sumError += err;
432          mPvsStat.sumPvsSize += mPvsErrorBuffer[i].mPvsSize;
433         
434          if (err == 0.0f)
435                mPvsStat.errorFreeFrames++;
436          mPvsStat.frames++;
437        }
438  }
439
440  glFinish();
441  doneCurrent();
442
443  cout<<endl<<flush;
444  //  mRenderingFinished.wakeAll();
445}
446
447
448
449
450
451
452
453void QtGlRendererBuffer::SampleBeamContributions(Intersectable *sourceObject,
454                                                                                           Beam &beam,
455                                                                                           const int desiredSamples,
456                                                                                           BeamSampleStatistics &stat)
457{
458        // TODO: should be moved out of here (not to be done every time)
459        // only back faces are interesting for the depth pass
460        glShadeModel(GL_FLAT);
461        glDisable(GL_LIGHTING);
462
463        // needed to kill the fragments for the front buffer
464        glEnable(GL_ALPHA_TEST);
465        glAlphaFunc(GL_GREATER, 0);
466
467        // assumes that the beam is constructed and contains kd-tree nodes
468        // and viewcells which it intersects
469 
470 
471        // Get the number of viewpoints to be sampled
472        // Now it is a sqrt but in general a wiser decision could be made.
473        // The less viewpoints the better for rendering performance, since less passes
474        // over the beam is needed.
475        // The viewpoints could actually be generated outside of the bounding box which
476        // would distribute the 'efective viewpoints' of the object surface and thus
477        // with a few viewpoints better sample the viewpoint space....
478
479        //TODO: comment in
480        //int viewPointSamples = sqrt((float)desiredSamples);
481        int viewPointSamples = max(desiredSamples / (GetWidth() * GetHeight()), 1);
482       
483        // the number of direction samples per pass is given by the number of viewpoints
484        int directionalSamples = desiredSamples / viewPointSamples;
485       
486        Debug << "directional samples: " << directionalSamples << endl;
487        for (int i = 0; i < viewPointSamples; ++ i)
488        {
489                Vector3 viewPoint = beam.mBox.GetRandomPoint();
490               
491                // perhaps the viewpoint should be shifted back a little bit so that it always lies
492                // inside the source object
493                // 'ideally' the viewpoints would be distributed on the soureObject surface, but this
494        // would require more complicated sampling (perhaps hierarchical rejection sampling of
495                // the object surface is an option here - only the mesh faces which are inside the box
496                // are considered as candidates)
497               
498                SampleViewpointContributions(sourceObject,
499                                                                         viewPoint,
500                                                                         beam,
501                                                                         directionalSamples,
502                                                                         stat);
503        }
504
505
506        // note:
507        // this routine would be called only if the number of desired samples is sufficiently
508        // large - for other rss tree cells the cpu based sampling is perhaps more efficient
509        // distributing the work between cpu and gpu would also allow us to place more sophisticated
510        // sample distributions (silhouette ones) using the cpu and the jittered once on the GPU
511        // in order that thios scheme is working well the gpu render buffer should run in a separate
512        // thread than the cpu sampler, which would not be such a big problem....
513
514        // disable alpha test again
515        glDisable(GL_ALPHA_TEST);
516}
517
518
519
520void QtGlRendererBuffer::SampleViewpointContributions(Intersectable *sourceObject,
521                                                                                                          const Vector3 viewPoint,
522                                                                                                          Beam &beam,
523                                                                                                          const int samples,
524                                                                                                          BeamSampleStatistics &stat)
525{
526    // 1. setup the view port to match the desired samples
527        glViewport(0, 0, samples, samples);
528
529        // 2. setup the projection matrix and view matrix to match the viewpoint + beam.mDirBox
530        SetupProjectionForViewPoint(viewPoint, beam, sourceObject);
531
532
533        // 3. reset z-buffer to 0 and render the source object for the beam
534        //    with glCullFace(Enabled) and glFrontFace(GL_CW)
535        //    save result to the front depth map
536        //    the front depth map holds ray origins
537
538
539        // front depth buffer must be initialised to 0
540        float clearDepth;
541       
542        glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
543        glClearDepth(0.0f);
544        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
545
546
547        //glFrontFace(GL_CW);
548        glEnable(GL_CULL_FACE);
549        glCullFace(GL_FRONT);
550        glColorMask(0, 0, 0, 0);
551       
552
553        // stencil is increased where the source object is located
554        glEnable(GL_STENCIL_TEST);     
555        glStencilFunc(GL_ALWAYS, 0x1, 0x1);
556        glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
557
558
559#if 0
560        static int glSourceObjList = -1;         
561        if (glSourceObjList != -1)
562        {
563                glSourceObjList = glGenLists(1);
564                glNewList(glSourceObjList, GL_COMPILE);
565
566                RenderIntersectable(sourceObject);
567       
568                glEndList();
569        }
570        glCallList(glSourceObjList);
571
572#else
573        RenderIntersectable(sourceObject);
574
575#endif 
576
577         // copy contents of the front depth buffer into depth texture
578        glBindTexture(GL_TEXTURE_2D, frontDepthMap);   
579        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
580
581
582        // reset clear function
583        glClearDepth(clearDepth);
584
585       
586       
587        // 4. set up the termination depth buffer (= standard depth buffer)
588        //    only rays which have non-zero entry in the origin buffer are valid since
589        //    they realy start on the object surface (this is tagged by setting a
590        //    stencil buffer bit at step 3).
591       
592        glStencilFunc(GL_EQUAL, 0x1, 0x1);
593        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
594
595        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
596        glDepthMask(1);
597
598        glEnable(GL_DEPTH_TEST);
599               
600        glEnable(GL_CULL_FACE);
601        glCullFace(GL_BACK);
602
603        // setup front depth buffer
604        glEnable(GL_TEXTURE_2D);
605       
606        // bind pixel shader implementing the front depth buffer functionality
607        cgGLBindProgram(sCgFragmentProgram);
608        cgGLEnableProfile(sCgFragmentProfile);
609
610
611        // 5. render all objects inside the beam
612        //    we can use id based false color to read them back for gaining the pvs
613
614        glColorMask(1, 1, 1, 1);
615
616       
617        // if objects not stored in beam => extract objects
618        if (beam.mFlags & !Beam::STORE_OBJECTS)
619        {
620                vector<KdNode *>::const_iterator it, it_end = beam.mKdNodes.end();
621
622                Intersectable::NewMail();
623                for (it = beam.mKdNodes.begin(); it != it_end; ++ it)
624                {
625                        mKdTree->CollectObjects(*it, beam.mObjects);
626                }
627        }
628
629
630        //    (objects can be compiled to a gl list now so that subsequent rendering for
631        //    this beam is fast - the same hold for step 3)
632        //    Afterwards we have two depth buffers defining the ray origin and termination
633       
634
635#if 0
636        static int glObjList = -1;
637        if (glObjList != -1)
638        {
639                glObjList = glGenLists(1);
640                glNewList(glObjList, GL_COMPILE);
641       
642                ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
643                for (it = beam.mObjects.begin(); it != it_end; ++ it)
644                {
645                        // render all objects except the source object
646                        if (*it != sourceObject)
647                                RenderIntersectable(*it);
648                }
649               
650                glEndList();
651        }
652
653        glCallList(glObjList);
654#else
655        ObjectContainer::const_iterator it, it_end = beam.mObjects.end();
656        for (it = beam.mObjects.begin(); it != it_end; ++ it)
657        {       
658                // render all objects except the source object
659                if (*it != sourceObject)
660                        RenderIntersectable(*it);
661        }
662#endif
663       
664   
665
666        // 6. Use occlusion queries for all viewcell meshes associated with the beam ->
667        //     a fragment passes if the corresponding stencil fragment is set and its depth is
668        //     between origin and termination buffer
669
670        // create new queries if necessary
671        OcclusionQuery::GenQueries(mOcclusionQueries, (int)beam.mViewCells.size());
672
673        // check whether any backfacing polygon would pass the depth test?
674        // matt: should check both back /front facing because of dual depth buffer
675        // and danger of cutting the near plane with front facing polys.
676       
677        glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
678        glDepthMask(GL_FALSE);
679        glDisable(GL_CULL_FACE);
680
681 
682        ViewCellContainer::const_iterator vit, vit_end = beam.mViewCells.end();
683
684        int queryIdx = 0;
685
686        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
687        {
688                mOcclusionQueries[queryIdx ++]->BeginQuery();
689
690                RenderIntersectable(*vit);
691               
692                mOcclusionQueries[queryIdx]->EndQuery();
693
694                ++ queryIdx;
695        }
696
697        // at this point, if possible, go and do some other computation
698       
699        // 7. The number of visible pixels is the number of sample rays which see the source
700        //    object from the corresponding viewcell -> remember these values for later update
701        //   of the viewcell pvs - or update immediately?
702
703        queryIdx = 0;
704
705        for (vit = beam.mViewCells.begin(); vit != vit_end; ++ vit)
706        {
707                // fetch queries
708                unsigned int pixelCount = mOcclusionQueries[queryIdx ++]->GetQueryResult();
709
710                if (pixelCount)
711                        Debug << "view cell " << (*vit)->GetId() << " visible pixels: " << pixelCount << endl;
712        }
713       
714
715        // 8. Copmpute rendering statistics
716        // In general it is not neccessary to remember to extract all the rays cast. I hope it
717        // would be sufficient to gain only the intergral statistics about the new contributions
718        // and so the rss tree would actually store no new rays (only the initial ones)
719        // the subdivision of the tree would only be driven by the statistics (the glrender could
720        // evaluate the contribution entropy for example)
721        // However might be an option to extract/store only those the rays which made a contribution
722        // (new viewcell has been discovered) or relative contribution greater than a threshold ...
723
724        ObjectContainer pvsObj;
725        stat.pvsSize = ComputePvs(beam.mObjects, pvsObj);
726       
727        // to gain ray source and termination
728        // copy contents of ray termination buffer into depth texture
729        // and compare with ray source buffer
730#if 0
731        VssRayContainer rays;
732
733        glBindTexture(GL_TEXTURE_2D, backDepthMap);     
734        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, depthMapSize, depthMapSize);
735
736        ComputeRays(Intersectable *sourceObj, rays);
737
738#endif
739
740        ////////
741        //-- cleanup
742
743        // reset gl state
744        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
745        glDepthMask(GL_TRUE);
746        glEnable(GL_CULL_FACE);
747        glDisable(GL_STENCIL_TEST);
748        cgGLDisableProfile(sCgFragmentProfile);
749        glDisable(GL_TEXTURE_2D);
750
751        // remove objects from beam
752        if (beam.mFlags & !Beam::STORE_OBJECTS)
753                beam.mObjects.clear();
754}
755
756
757void QtGlRendererBuffer::SetupProjectionForViewPoint(const Vector3 &viewPoint,
758                                                                                                   const Beam &beam,
759                                                                                                   Intersectable *sourceObject)
760{
761        float left, right, bottom, top, znear, zfar;
762
763        beam.ComputePerspectiveFrustum(left, right, bottom, top, znear, zfar,
764                                                                   mSceneGraph->GetBox());
765
766        //Debug << left << " " << right << " " << bottom << " " << top << " " << znear << " " << zfar << endl;
767        glMatrixMode(GL_PROJECTION);
768        glLoadIdentity();
769        glFrustum(left, right, bottom, top, znear, zfar);
770        //glFrustum(-1, 1, -1, 1, 1, 20000);
771
772    const Vector3 center = viewPoint + beam.GetMainDirection() * (zfar - znear) * 0.3f;
773        const Vector3 up =
774                Normalize(CrossProd(beam.mPlanes[0].mNormal, beam.mPlanes[4].mNormal));
775
776#ifdef _DEBUG
777        Debug << "view point: " << viewPoint << endl;
778        Debug << "eye: " << center << endl;
779        Debug << "up: " << up << endl;
780#endif
781
782        glMatrixMode(GL_MODELVIEW);
783        glLoadIdentity();
784        gluLookAt(viewPoint.x, viewPoint.y, viewPoint.z,
785                          center.x, center.y, center.z,                   
786                          up.x, up.y, up.z);
787}               
788
789 
790void QtGlRendererBuffer::CastGlobalLine(Beam &beam, const int samples)
791{
792        // bind pixel shader implementing the front depth buffer functionality
793        cgGLBindProgram(sCgFragmentProgram);
794        cgGLEnableProfile(sCgFragmentProfile);
795
796        DepthPeeling(beam, samples);
797}
798
799
800void QtGlRendererBuffer::DepthPeeling(Beam &beam, const int samples)
801{
802/*      if (rtNew->IsDoubleBuffered())
803                glDrawBuffer(GL_BACK);
804       
805        rtNew->BeginCapture();
806        {
807                cgGLBindProgram(passthru);
808                glColor3f(0,0.0,0.0);
809                DrawGeometry();   //just random geomerty   
810        }
811        rtNew->EndCapture();
812
813        for(int l = 0; l < mCurrentDepth; l++)
814        {
815                // Peel another layer
816                pingpong(); // switch pointer between rendertextures
817     
818                rtNew->BeginCapture();
819                {
820                        if (rtNew->IsDoubleBuffered())
821                                glDrawBuffer(GL_BACK);
822       
823                        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         
824                       
825                        cgGLBindProgram(fragmentProgram);
826                        cgGLSetTextureParameter(input1, rtOld->GetDepthTextureID());
827                        cgGLEnableTextureParameter(input1);
828
829            glColor3f(0,0.0,0.0);
830                        DrawGeometry();
831                        cgGLDisableTextureParameter(input1);
832                }
833                rtNew->EndCapture();
834   }*/
835}
836
837
838void QtGlRendererBuffer::InitGL()
839{
840        makeCurrent();
841        GlRenderer::InitGL();
842
843#if 1
844        // initialise dual depth buffer textures
845        glGenTextures(1, &frontDepthMap);
846        glBindTexture(GL_TEXTURE_2D, frontDepthMap);
847       
848        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
849                depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
850        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
851        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
852        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
853        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
854
855        glGenTextures(1, &backDepthMap);
856        glBindTexture(GL_TEXTURE_2D, backDepthMap);
857       
858        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, depthMapSize,
859                depthMapSize, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
860        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
861        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
862        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
863        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
864
865        // cg initialization
866        cgSetErrorCallback(handleCgError);
867        sCgContext = cgCreateContext();
868       
869        if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1))
870                sCgFragmentProfile = CG_PROFILE_ARBFP1;
871        else
872        {
873          // try FP30
874          if (cgGLIsProfileSupported(CG_PROFILE_FP30))
875            sCgFragmentProfile = CG_PROFILE_FP30;
876          else
877          {
878                  Debug << "Neither arbfp1 or fp30 fragment profiles supported on this system" << endl;
879                  exit(1);
880          }
881  }
882
883
884 sCgFragmentProgram = cgCreateProgramFromFile(sCgContext,
885                                                                                           CG_SOURCE, "../src/dual_depth.cg",
886                                                                                           sCgFragmentProfile,
887                                                                                           NULL,
888                                                                                           NULL);
889
890  if (!cgIsProgramCompiled(sCgFragmentProgram))
891          cgCompileProgram(sCgFragmentProgram);
892
893  cgGLLoadProgram(sCgFragmentProgram);
894  cgGLBindProgram(sCgFragmentProgram);
895
896  Debug << "---- PROGRAM BEGIN ----\n" <<
897          cgGetProgramString(sCgFragmentProgram, CG_COMPILED_PROGRAM) << "---- PROGRAM END ----\n";
898
899
900  sCgDepthPeelingProgram =
901          cgCreateProgramFromFile(sCgContext,
902                                                          CG_SOURCE,
903                                                          "../src/depth_peeling.cg",
904                                                          sCgFragmentProfile,
905                                                          NULL,
906                                                          NULL);
907
908  if (!cgIsProgramCompiled(sCgDepthPeelingProgram))
909          cgCompileProgram(sCgDepthPeelingProgram);
910
911  cgGLLoadProgram(sCgDepthPeelingProgram);
912  cgGLBindProgram(sCgDepthPeelingProgram);
913
914  Debug << "---- PROGRAM BEGIN ----\n"
915            << cgGetProgramString(sCgDepthPeelingProgram, CG_COMPILED_PROGRAM)
916                << "---- PROGRAM END ----\n";
917
918#endif
919  doneCurrent();
920}
921
922
923void QtGlRendererBuffer::ComputeRays(Intersectable *sourceObj, VssRayContainer &rays)
924{
925        for (int i = 0; i < depthMapSize * depthMapSize; ++ i)
926        {
927                //todo glGetTexImage()
928        }
929}
930
931
932
933int QtGlRendererBuffer::ComputePvs(ObjectContainer &objects,
934                                                                   ObjectContainer &pvs) const
935{
936        int pvsSize = 0;
937        QImage image = toImage();
938        Intersectable::NewMail();
939
940        std::stable_sort(objects.begin(), objects.end(), ilt);
941
942        MeshInstance dummy(NULL);
943
944        Intersectable *obj = NULL;
945                       
946        for (int x = 0; x < image.width(); ++ x)
947        {
948                for (int y = 0; y < image.height(); ++ y)
949                {
950                        QRgb pix = image.pixel(x, y);
951                        const int id = GetId(qRed(pix), qGreen(pix), qBlue(pix));
952
953                        dummy.SetId(id);
954
955                        ObjectContainer::iterator oit =
956                                lower_bound(objects.begin(), objects.end(), &dummy, ilt);
957                       
958                       
959                        if (//(oit != oit.end()) &&
960                                ((*oit)->GetId() == id) &&
961                                !obj->Mailed())
962                        {
963                                obj = *oit;
964                                obj->Mail();
965                                ++ pvsSize;
966                                pvs.push_back(obj);
967                        }
968                }
969        }
970
971        return pvsSize;
972}
973
974
975
976void
977QtGlRendererWidget::SetupProjection(const int w, const int h, const float angle)
978{
979  if (!mTopView)
980        GlRenderer::SetupProjection(w, h, angle);
981  else {
982        glViewport(0, 0, w, h);
983        glMatrixMode(GL_PROJECTION);
984        glLoadIdentity();
985        gluPerspective(50.0, 1.0, 0.1, 20.0*Magnitude(mSceneGraph->GetBox().Diagonal()));
986        glMatrixMode(GL_MODELVIEW);
987  }
988}
989
990void
991QtGlRendererWidget::RenderPvs()
992{
993  SetupCamera();
994  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
995 
996  ViewCell *viewcell = NULL;
997
998  PrVs prvs;
999 
1000  if (!mUseFilter) {
1001        viewcell = mViewCellsManager->GetViewCell(mViewPoint, true);
1002  } else {
1003          //  mViewCellsManager->SetMaxFilterSize(1);
1004          mViewCellsManager->GetPrVS(mViewPoint, prvs, mViewCellsManager->GetFilterWidth());
1005          viewcell = prvs.mViewCell;
1006  }
1007
1008  if (viewcell)
1009  {
1010          // copy the pvs so that it can be filtered...
1011          ObjectPvs pvs = viewcell->GetPvs();
1012
1013          if (mUseSpatialFilter) {
1014                  mViewCellsManager->ApplySpatialFilter(mKdTree,
1015                          mSpatialFilterSize*
1016                          Magnitude(mViewCellsManager->GetViewSpaceBox().Size()),
1017                          pvs);
1018          }
1019
1020          // read back the texture
1021          mPvsSize = pvs.GetSize();
1022
1023          ObjectPvsIterator pit = pvs.GetIterator();
1024
1025          while (pit.HasMoreEntries())
1026          {             
1027                  const ObjectPvsEntry &entry = pit.Next();
1028                  Intersectable *obj = entry.mObject;
1029
1030                  float visibility = log10(entry.mData.mSumPdf + 1) / 5.0f;
1031                  glColor3f(visibility, 0.0f, 0.0f);
1032                  mUseForcedColors = true;
1033                  RenderIntersectable(obj);
1034                  mUseForcedColors = false;
1035          }
1036
1037          if (mRenderFilter)
1038          {
1039                  mWireFrame = true;
1040                  RenderIntersectable(viewcell);
1041                  mWireFrame = false;
1042          }
1043
1044          if (mUseFilter)
1045          {
1046                  mViewCellsManager->DeleteLocalMergeTree(viewcell);
1047          }
1048  }
1049  else
1050  {
1051          ObjectContainer::const_iterator oi = mObjects.begin();
1052          for (; oi != mObjects.end(); oi++)
1053                  RenderIntersectable(*oi);
1054  }
1055}
1056
1057float
1058QtGlRendererWidget::RenderErrors()
1059{
1060  float pErrorPixels = -1.0f;
1061
1062  glReadBuffer(GL_BACK);
1063 
1064  mUseFalseColors = true;
1065
1066  SetupCamera();
1067  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1068 
1069  double eq[4];
1070  eq[0] = mSceneCutPlane.mNormal.x;
1071  eq[1] = mSceneCutPlane.mNormal.y;
1072  eq[2] = mSceneCutPlane.mNormal.z;
1073  eq[3] = mSceneCutPlane.mD;
1074 
1075  if (mCutScene) {
1076        glClipPlane(GL_CLIP_PLANE0, eq);
1077    glEnable(GL_CLIP_PLANE0);
1078  }
1079 
1080  if (mDetectEmptyViewSpace)
1081        glEnable( GL_CULL_FACE );
1082  else
1083        glDisable( GL_CULL_FACE );
1084
1085  ObjectContainer::const_iterator oi = mObjects.begin();
1086  for (; oi != mObjects.end(); oi++)
1087        RenderIntersectable(*oi);
1088
1089  ViewCell *viewcell = NULL;
1090
1091  QImage im1, im2;
1092  QImage diff;
1093 
1094  if (viewcell) {
1095        // read back the texture
1096        im1 = grabFrameBuffer(true);
1097       
1098        RenderPvs();
1099
1100        // read back the texture
1101        im2 = grabFrameBuffer(true);
1102       
1103        diff = im1;
1104        int x, y;
1105        int errorPixels = 0;
1106       
1107        for (y = 0; y < im1.height(); y++)
1108          for (x = 0; x < im1.width(); x++)
1109                if (im1.pixel(x, y) == im2.pixel(x, y))
1110                  diff.setPixel(x, y, qRgba(0,0,0,0));
1111                else {
1112                  diff.setPixel(x, y, qRgba(255,128,128,255));
1113                  errorPixels++;
1114                }
1115        pErrorPixels = ((float)errorPixels)/(im1.height()*im1.width());
1116  }
1117
1118  // now render the pvs again
1119  SetupCamera();
1120  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1121  mUseFalseColors = false;
1122 
1123  oi = mObjects.begin();
1124  for (; oi != mObjects.end(); oi++)
1125        RenderIntersectable(*oi);
1126
1127  // now render im1
1128  if (viewcell) {
1129        if (0 && mTopView) {
1130          mWireFrame = true;
1131          RenderIntersectable(viewcell);
1132          mWireFrame = false;
1133        }
1134       
1135        // init ortographic projection
1136        glMatrixMode(GL_PROJECTION);
1137        glPushMatrix();
1138       
1139        glLoadIdentity();
1140        gluOrtho2D(0, 1.0f, 0, 1.0f);
1141       
1142        glMatrixMode(GL_MODELVIEW);
1143        glLoadIdentity();
1144       
1145        bindTexture(diff);
1146       
1147        glPushAttrib(GL_ENABLE_BIT);
1148        glEnable( GL_ALPHA_TEST );
1149        glDisable( GL_CULL_FACE );
1150        glAlphaFunc( GL_GREATER, 0.5 );
1151       
1152        glEnable( GL_TEXTURE_2D );
1153        glBegin(GL_QUADS);
1154       
1155        glTexCoord2f(0,0);
1156        glVertex3f(0,0,0);
1157       
1158        glTexCoord2f(1,0);
1159        glVertex3f( 1, 0, 0);
1160       
1161        glTexCoord2f(1,1);
1162        glVertex3f( 1, 1, 0);
1163       
1164        glTexCoord2f(0,1);
1165        glVertex3f(0, 1, 0);
1166        glEnd();
1167       
1168        glPopAttrib();
1169       
1170        // restore the projection matrix
1171        glMatrixMode(GL_PROJECTION);
1172        glPopMatrix();
1173        glMatrixMode(GL_MODELVIEW);
1174  }
1175
1176  glDisable(GL_CLIP_PLANE0);
1177 
1178  mRenderError = pErrorPixels;
1179  return pErrorPixels;
1180}
1181
1182
1183void
1184QtGlRendererWidget::mousePressEvent(QMouseEvent *e)
1185{
1186  int x = e->pos().x();
1187  int y = e->pos().y();
1188
1189  mousePoint.x = x;
1190  mousePoint.y = y;
1191 
1192}
1193
1194void
1195QtGlRendererWidget::mouseMoveEvent(QMouseEvent *e)
1196{
1197  float MOVE_SENSITIVITY = Magnitude(mSceneGraph->GetBox().Diagonal())*1e-3;
1198  float TURN_SENSITIVITY=0.1f;
1199  float TILT_SENSITIVITY=32.0 ;
1200  float TURN_ANGLE= M_PI/36.0 ;
1201
1202  int x = e->pos().x();
1203  int y = e->pos().y();
1204 
1205  if (e->modifiers() & Qt::ControlModifier) {
1206        mViewPoint.y += (y-mousePoint.y)*MOVE_SENSITIVITY/2.0;
1207        mViewPoint.x += (x-mousePoint.x)*MOVE_SENSITIVITY/2.0;
1208  } else {
1209        mViewPoint += mViewDirection*((mousePoint.y - y)*MOVE_SENSITIVITY);
1210        float adiff = TURN_ANGLE*(x - mousePoint.x)*-TURN_SENSITIVITY;
1211        float angle = atan2(mViewDirection.x, mViewDirection.z);
1212        mViewDirection.x = sin(angle+adiff);
1213        mViewDirection.z = cos(angle+adiff);
1214  }
1215 
1216  mousePoint.x = x;
1217  mousePoint.y = y;
1218 
1219  updateGL();
1220}
1221
1222void
1223QtGlRendererWidget::mouseReleaseEvent(QMouseEvent *)
1224{
1225
1226
1227}
1228
1229void
1230QtGlRendererWidget::resizeGL(int w, int h)
1231{
1232  SetupProjection(w, h);
1233  updateGL();
1234}
1235
1236void
1237QtGlRendererWidget::paintGL()
1238{
1239  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1240
1241 
1242  if (!mRenderViewCells) {
1243        if (mRenderErrors)
1244          RenderErrors();
1245        else
1246          RenderPvs();
1247        RenderInfo();
1248  } else {
1249        RenderViewCells();
1250       
1251        mWireFrame = true;
1252        RenderScene();
1253        mWireFrame = false;
1254       
1255        RenderInfo();
1256  }
1257
1258  mFrame++;
1259}
1260
1261
1262void
1263QtGlRendererWidget::SetupCamera()
1264{
1265  if (!mTopView)
1266        GlRenderer::SetupCamera();
1267  else {
1268        if (0) {
1269          float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*0.05;
1270          Vector3 pos = mViewPoint - dist*Vector3(mViewDirection.x,
1271                                                                                          -1,
1272                                                                                          mViewDirection.y);
1273         
1274          Vector3 target = mViewPoint + dist*mViewDirection;
1275          Vector3 up(0,1,0);
1276         
1277          glLoadIdentity();
1278          gluLookAt(pos.x, pos.y, pos.z,
1279                                target.x, target.y, target.z,
1280                                up.x, up.y, up.z);
1281        } else {
1282          float dist = Magnitude(mSceneGraph->GetBox().Diagonal())*mTopDistance;
1283          Vector3 pos = mViewPoint  + dist*Vector3(0,
1284                                                                                           1,
1285                                                                                           0);
1286         
1287          Vector3 target = mViewPoint;
1288          Vector3 up(mViewDirection.x, 0, mViewDirection.z);
1289         
1290          glLoadIdentity();
1291          gluLookAt(pos.x, pos.y, pos.z,
1292                                target.x, target.y, target.z,
1293                                up.x, up.y, up.z);
1294         
1295        }
1296  }
1297
1298}
1299
1300void
1301QtGlRendererWidget::keyPressEvent ( QKeyEvent * e )
1302{
1303  switch (e->key()) {
1304  case Qt::Key_T:
1305        mTopView = !mTopView;
1306        SetupProjection(width(), height());
1307        updateGL();
1308        break;
1309  case Qt::Key_V:
1310        mRenderViewCells = !mRenderViewCells;
1311        updateGL();
1312        break;
1313  case Qt::Key_P:
1314        // set random viewpoint
1315        mViewCellsManager->GetViewPoint(mViewPoint);
1316        updateGL();
1317        break;
1318
1319  default:
1320        e->ignore();
1321        break;
1322  }
1323}
1324
1325 
1326
1327QtGlRendererWidget::QtGlRendererWidget(SceneGraph *sceneGraph,
1328                                                                   ViewCellsManager *viewcells,
1329                                                                   KdTree *tree,
1330                                                                   QWidget * parent,
1331                                                                   const QGLWidget * shareWidget,
1332                                                                   Qt::WFlags f
1333                                                                   )
1334  :
1335  GlRendererWidget(sceneGraph, viewcells, tree), QGLWidget(parent, shareWidget, f)
1336{
1337  mTopView = false;
1338  mRenderViewCells = false;
1339  mTopDistance = 1.0f;
1340  mCutViewCells = false;
1341  mCutScene = false;
1342  mRenderErrors = false;
1343  mRenderFilter = true;
1344
1345  bool tmp;
1346
1347  Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilityFilter", tmp );
1348  mUseFilter = tmp;
1349 
1350  Environment::GetSingleton()->GetBoolValue("Preprocessor.applyVisibilitySpatialFilter",
1351                                                        tmp );
1352
1353  mUseSpatialFilter = tmp;
1354
1355  mShowRenderCost = false;
1356  mShowPvsSizes = false;
1357  mSpatialFilterSize = 0.01;
1358  mPvsSize = 0;
1359  mRenderError = 0.0f;
1360  mControlWidget = new QtRendererControlWidget(NULL);
1361 
1362  connect(mControlWidget, SIGNAL(SetViewCellGranularity(int)), this, SLOT(SetViewCellGranularity(int)));
1363  connect(mControlWidget, SIGNAL(SetSceneCut(int)), this, SLOT(SetSceneCut(int)));
1364  connect(mControlWidget, SIGNAL(SetTopDistance(int)), this, SLOT(SetTopDistance(int)));
1365
1366  connect(mControlWidget, SIGNAL(SetVisibilityFilterSize(int)), this, SLOT(SetVisibilityFilterSize(int)));
1367  connect(mControlWidget, SIGNAL(SetSpatialFilterSize(int)), this, SLOT(SetSpatialFilterSize(int)));
1368
1369  connect(mControlWidget, SIGNAL(SetShowViewCells(bool)), this, SLOT(SetShowViewCells(bool)));
1370  connect(mControlWidget, SIGNAL(SetShowRenderCost(bool)), this, SLOT(SetShowRenderCost(bool)));
1371  connect(mControlWidget, SIGNAL(SetShowPvsSizes(bool)), this, SLOT(SetShowPvsSizes(bool)));
1372  connect(mControlWidget, SIGNAL(SetTopView(bool)), this, SLOT(SetTopView(bool)));
1373  connect(mControlWidget, SIGNAL(SetCutViewCells(bool)), this, SLOT(SetCutViewCells(bool)));
1374  connect(mControlWidget, SIGNAL(SetCutScene(bool)), this, SLOT(SetCutScene(bool)));
1375  connect(mControlWidget, SIGNAL(SetRenderErrors(bool)), this, SLOT(SetRenderErrors(bool)));
1376  connect(mControlWidget, SIGNAL(SetRenderFilter(bool)), this, SLOT(SetRenderFilter(bool)));
1377  connect(mControlWidget, SIGNAL(SetUseFilter(bool)), this, SLOT(SetUseFilter(bool)));
1378  connect(mControlWidget, SIGNAL(SetUseSpatialFilter(bool)),
1379                  this, SLOT(SetUseSpatialFilter(bool)));
1380
1381 
1382  mControlWidget->show();
1383}
1384
1385
1386void
1387QtGlRendererWidget::RenderInfo()
1388{
1389  QString s;
1390  int vc = 0;
1391 
1392  if (mViewCellsManager)
1393          vc = (int)mViewCellsManager->GetViewCells().size();
1394
1395  int filter = 0;
1396  if (mViewCellsManager)
1397        filter = mViewCellsManager->GetMaxFilterSize();
1398
1399  s.sprintf("frame:%04d viewpoint:(%4.1f,%4.1f,%4.1f) dir:(%4.1f,%4.1f,%4.1f) viewcells:%04d filter:%04d pvs:%04d error:%5.5f %",
1400                        mFrame,
1401                        mViewPoint.x,
1402                        mViewPoint.y,
1403                        mViewPoint.z,
1404                        mViewDirection.x,
1405                        mViewDirection.y,
1406                        mViewDirection.z,
1407                        vc,
1408
1409                        filter,
1410                        mPvsSize,
1411                        mRenderError*100.0f
1412                        );
1413 
1414  glColor3f(0.0f,0.0f,0.0f);
1415  renderText(0,20,s);
1416 
1417  if (mShowRenderCost) {
1418        static vector<float> costFunction;
1419        static float maxCost = -1;
1420        if (costFunction.size()==0) {
1421          ViewCellsTree *tree = mViewCellsManager->GetViewCellsTree();
1422          if (tree) {
1423                tree->GetCostFunction(costFunction);
1424                maxCost = -1;
1425                for (int i=0;  i < costFunction.size(); i++) {
1426                  //              cout<<i<<":"<<costFunction[i]<<" ";
1427                  if (costFunction[i] > maxCost)
1428                        maxCost = costFunction[i];
1429                }
1430          }
1431        }
1432
1433       
1434        int currentPos = (int)mViewCellsManager->GetViewCells().size();
1435        float currentCost= -1;
1436
1437        if (currentPos < costFunction.size())
1438          currentCost = costFunction[currentPos];
1439#if 0   
1440        cout<<"costFunction.size()="<<costFunction.size()<<endl;
1441        cout<<"CP="<<currentPos<<endl;
1442        cout<<"MC="<<maxCost<<endl;
1443        cout<<"CC="<<currentCost<<endl;
1444#endif
1445        if (costFunction.size()) {
1446          glDisable(GL_DEPTH_TEST);
1447          // init ortographic projection
1448          glMatrixMode(GL_PROJECTION);
1449          glPushMatrix();
1450         
1451          glLoadIdentity();
1452          gluOrtho2D(0, 1.0f, 0, 1.0f);
1453         
1454          glTranslatef(0.1f, 0.1f, 0.0f);
1455          glScalef(0.8f, 0.8f, 1.0f);
1456          glMatrixMode(GL_MODELVIEW);
1457          glLoadIdentity();
1458         
1459          glColor3f(1.0f,0,0);
1460          glBegin(GL_LINE_STRIP);
1461          //      glVertex3f(0,0,0);
1462         
1463          for (int i=0;  i < costFunction.size(); i++) {
1464                float x =  i/(float)costFunction.size();
1465                float y = costFunction[i]/(maxCost*0.5f);
1466                glVertex3f(x,y,0.0f);
1467          }
1468          glEnd();
1469         
1470          glColor3f(1.0f,0,0);
1471          glBegin(GL_LINES);
1472          float x =  currentPos/(float)costFunction.size();
1473          glVertex3f(x,0.0,0.0f);
1474          glVertex3f(x,1.0f,0.0f);
1475          glEnd();
1476         
1477          glColor3f(0.0f,0,0);
1478          // show a grid
1479          glBegin(GL_LINE_LOOP);
1480          glVertex3f(0,0,0.0f);
1481          glVertex3f(1,0,0.0f);
1482          glVertex3f(1,1,0.0f);
1483          glVertex3f(0,1,0.0f);
1484          glEnd();
1485
1486          glBegin(GL_LINES);
1487          for (int i=0;  i < 50000 && i < costFunction.size(); i+=10000) {
1488                float x =  i/(float)costFunction.size();
1489                glVertex3f(x,0.0,0.0f);
1490                glVertex3f(x,1.0f,0.0f);
1491          }
1492
1493          for (int i=0;  i < maxCost; i+=100) {
1494                float y = i/(maxCost*0.5f);
1495                glVertex3f(0,y,0.0f);
1496                glVertex3f(1,y,0.0f);
1497          }
1498
1499          glEnd();
1500
1501         
1502          // restore the projection matrix
1503          glMatrixMode(GL_PROJECTION);
1504          glPopMatrix();
1505          glMatrixMode(GL_MODELVIEW);
1506          glEnable(GL_DEPTH_TEST);
1507
1508        }
1509  }
1510}
1511
1512
1513void
1514QtGlRendererWidget::SetViewCellGranularity(int number)
1515{
1516  if (mViewCellsManager)
1517        //      mViewCellsManager->SetMaxFilterSize(number);
1518    mViewCellsManager->CollectViewCells(number);
1519
1520  updateGL();
1521}
1522
1523void
1524QtGlRendererWidget::SetVisibilityFilterSize(int number)
1525{
1526  if (mViewCellsManager)
1527        mViewCellsManager->SetMaxFilterSize(number);
1528  updateGL();
1529}
1530
1531void
1532QtGlRendererWidget::SetSpatialFilterSize(int number)
1533{
1534  mSpatialFilterSize = 1e-3*number;
1535  updateGL();
1536}
1537
1538void
1539QtGlRendererWidget::SetSceneCut(int number)
1540{
1541  // assume the cut plane can only be aligned with xz plane
1542  // shift it along y according to number, which is percentage of the bounding
1543  // box position
1544  if (mViewCellsManager) {
1545        AxisAlignedBox3 box = mViewCellsManager->GetViewSpaceBox();
1546        Vector3 p = box.Min() + (number/1000.0f)*box.Max();
1547        mSceneCutPlane.mNormal = Vector3(0,-1,0);
1548        mSceneCutPlane.mD = -DotProd(mSceneCutPlane.mNormal, p);
1549        updateGL();
1550  }
1551}
1552
1553void
1554QtGlRendererWidget::SetTopDistance(int number)
1555{
1556  mTopDistance = number/1000.0f;
1557  updateGL();
1558}
1559
1560void
1561QtGlRendererWidget::RenderViewCells()
1562{
1563        mUseFalseColors = true;
1564
1565        SetupCamera();
1566        glEnable(GL_CULL_FACE);
1567        //glDisable(GL_CULL_FACE);
1568        glCullFace(GL_FRONT);
1569        double eq[4];
1570        eq[0] = mSceneCutPlane.mNormal.x;
1571        eq[1] = mSceneCutPlane.mNormal.y;
1572        eq[2] = mSceneCutPlane.mNormal.z;
1573        eq[3] = mSceneCutPlane.mD;
1574
1575        if (mCutViewCells)
1576        {
1577                glClipPlane(GL_CLIP_PLANE0, eq);
1578                glEnable(GL_CLIP_PLANE0);
1579        }
1580
1581        //int i;
1582        ViewCellContainer &viewCells = mViewCellsManager->GetViewCells();
1583        float maxPvs = -1;
1584        ViewCellContainer::const_iterator vit, vit_end = viewCells.end();
1585
1586        for (vit = viewCells.begin(); vit != vit_end; ++ vit)
1587        {
1588                ViewCell *vc = *vit;
1589                const float p = vc->GetPvs().EvalPvsCost();
1590                if (p > maxPvs)
1591                        maxPvs = p;
1592        }
1593
1594        for (vit = viewCells.begin(); vit != vit_end; ++ vit)
1595        {
1596                ViewCell *vc = *vit;
1597
1598                RgbColor c;
1599
1600                if (!mShowPvsSizes)
1601                {
1602                        c = vc->GetColor();
1603                }
1604                else
1605                {
1606                        const float importance = (float)vc->GetPvs().EvalPvsCost() / (float)maxPvs;
1607                        c = RgbColor(importance, 1.0f - importance, 0.0f);
1608                }
1609
1610                glColor3f(c.r, c.g, c.b);
1611
1612                RenderViewCell(vc);
1613        }
1614
1615        glDisable(GL_CLIP_PLANE0);
1616}
1617
1618
1619
1620
1621
1622/***********************************************************************/
1623/*                     QtGlDebuggerWidget implementation                           */
1624/***********************************************************************/
1625
1626
1627QtGlDebuggerWidget::QtGlDebuggerWidget(QtGlRendererBuffer *buf, QWidget *parent)
1628      : QGLWidget(QGLFormat(QGL::SampleBuffers), parent), mRenderBuffer(buf)
1629{
1630        // create the pbuffer
1631    //pbuffer = new QGLPixelBuffer(QSize(512, 512), format(), this);
1632    timerId = startTimer(20);
1633    setWindowTitle(("OpenGL pbuffers"));
1634}
1635
1636
1637QtGlDebuggerWidget::~QtGlDebuggerWidget()
1638{
1639 mRenderBuffer->releaseFromDynamicTexture();
1640   glDeleteTextures(1, &dynamicTexture);
1641         
1642         DEL_PTR(mRenderBuffer);
1643}
1644
1645
1646
1647QtRendererControlWidget::QtRendererControlWidget(QWidget * parent, Qt::WFlags f):
1648  QWidget(parent, f)
1649{
1650
1651  QVBoxLayout *vl = new QVBoxLayout;
1652  setLayout(vl);
1653 
1654  QWidget *vbox = new QGroupBox("ViewCells", this);
1655  layout()->addWidget(vbox);
1656 
1657  vl = new QVBoxLayout;
1658  vbox->setLayout(vl);
1659
1660  QLabel *label = new QLabel("Granularity");
1661  vbox->layout()->addWidget(label);
1662
1663  QSlider *slider = new QSlider(Qt::Horizontal, vbox);
1664  vl->addWidget(slider);
1665  slider->show();
1666  slider->setRange(1, 10000);
1667  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1668  slider->setValue(200);
1669
1670  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetViewCellGranularity(int)));
1671
1672  label = new QLabel("Filter size");
1673  vbox->layout()->addWidget(label);
1674 
1675  slider = new QSlider(Qt::Horizontal, vbox);
1676  vbox->layout()->addWidget(slider);
1677  slider->show();
1678  slider->setRange(1, 100);
1679  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1680  slider->setValue(3);
1681 
1682  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetVisibilityFilterSize(int)));
1683
1684
1685  label = new QLabel("Spatial Filter size");
1686  vbox->layout()->addWidget(label);
1687 
1688  slider = new QSlider(Qt::Horizontal, vbox);
1689  vbox->layout()->addWidget(slider);
1690  slider->show();
1691  slider->setRange(1, 100);
1692  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1693  slider->setValue(10);
1694 
1695  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSpatialFilterSize(int)));
1696
1697
1698
1699  QWidget *hbox = new QWidget(vbox);
1700  vl->addWidget(hbox);
1701  QHBoxLayout *hlayout = new QHBoxLayout;
1702  hbox->setLayout(hlayout);
1703 
1704  QCheckBox *cb = new QCheckBox("Show viewcells", hbox);
1705  hlayout->addWidget(cb);
1706  cb->setChecked(false);
1707  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowViewCells(bool)));
1708
1709  cb = new QCheckBox("Show render cost", hbox);
1710  hlayout->addWidget(cb);
1711  cb->setChecked(false);
1712  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowRenderCost(bool)));
1713
1714  cb = new QCheckBox("Show pvs sizes", hbox);
1715  hlayout->addWidget(cb);
1716  cb->setChecked(false);
1717  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetShowPvsSizes(bool)));
1718
1719  vbox->resize(800,100);
1720
1721 
1722  vbox = new QGroupBox("Rendering", this);
1723  layout()->addWidget(vbox);
1724 
1725  vl = new QVBoxLayout;
1726  vbox->setLayout(vl);
1727
1728
1729
1730  slider = new QSlider(Qt::Horizontal, vbox);
1731  vbox->layout()->addWidget(slider);
1732  slider->show();
1733  slider->setRange(0, 1000);
1734  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1735  slider->setValue(1000);
1736
1737  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetSceneCut(int)));
1738
1739  cb = new QCheckBox("Render errors", vbox);
1740  vbox->layout()->addWidget(cb);
1741  cb->setChecked(false);
1742  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderErrors(bool)));
1743
1744  cb = new QCheckBox("Use filter", vbox);
1745  vbox->layout()->addWidget(cb);
1746  cb->setChecked(true);
1747  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseFilter(bool)));
1748
1749  cb = new QCheckBox("Use spatial filter", vbox);
1750  vbox->layout()->addWidget(cb);
1751  cb->setChecked(true);
1752  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetUseSpatialFilter(bool)));
1753
1754  cb = new QCheckBox("Render filter", vbox);
1755  vbox->layout()->addWidget(cb);
1756  cb->setChecked(true);
1757  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetRenderFilter(bool)));
1758
1759
1760  cb = new QCheckBox("Cut view cells", vbox);
1761  vbox->layout()->addWidget(cb);
1762  cb->setChecked(false);
1763  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutViewCells(bool)));
1764
1765  cb = new QCheckBox("Cut scene", vbox);
1766  vbox->layout()->addWidget(cb);
1767  cb->setChecked(false);
1768  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetCutScene(bool)));
1769
1770 
1771  slider = new QSlider(Qt::Horizontal, vbox);
1772  vbox->layout()->addWidget(slider);
1773  slider->show();
1774  slider->setRange(1, 1000);
1775  slider->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
1776  slider->setValue(500);
1777 
1778  connect(slider, SIGNAL(valueChanged(int)), SIGNAL(SetTopDistance(int)));
1779 
1780  cb = new QCheckBox("Top View", vbox);
1781  vbox->layout()->addWidget(cb);
1782  cb->setChecked(false);
1783  connect(cb, SIGNAL(toggled(bool)), SIGNAL(SetTopView(bool)));
1784
1785  vbox = new QGroupBox("PVS Errors", this);
1786  layout()->addWidget(vbox);
1787
1788  vl = new QVBoxLayout;
1789  vbox->setLayout(vl);
1790
1791  mPvsErrorWidget = new QListWidget(vbox);
1792  vbox->layout()->addWidget(mPvsErrorWidget);
1793 
1794  connect(mPvsErrorWidget,
1795                  SIGNAL(doubleClicked(const QModelIndex &)),
1796                  this,
1797                  SLOT(PvsErrorClicked(const QModelIndex &)));
1798 
1799  QPushButton *button = new QPushButton("Next Error Frame", vbox);
1800  vbox->layout()->addWidget(button);
1801  connect(button, SIGNAL(clicked(void)), SLOT(FocusNextPvsErrorFrame(void)));
1802
1803  setWindowTitle("Preprocessor Control Widget");
1804  adjustSize();
1805}
1806
1807
1808void
1809QtRendererControlWidget::FocusNextPvsErrorFrame(void)
1810{
1811 
1812 
1813}
1814
1815void
1816QtRendererControlWidget::UpdatePvsErrorItem(int row,
1817                                                                                        GlRendererBuffer::PvsErrorEntry &pvsErrorEntry)
1818{
1819
1820  QListWidgetItem *i = mPvsErrorWidget->item(row);
1821  QString s;
1822  s.sprintf("%5.5f", pvsErrorEntry.mError);
1823  if (i) {
1824        i->setText(s);
1825  } else {
1826        new QListWidgetItem(s, mPvsErrorWidget);
1827  }
1828  mPvsErrorWidget->update();
1829}
1830
1831
1832void QtGlDebuggerWidget::initializeGL()
1833{
1834        glMatrixMode(GL_PROJECTION);
1835        glLoadIdentity();
1836
1837        glFrustum(-1, 1, -1, 1, 10, 100);
1838        glTranslatef(-0.5f, -0.5f, -0.5f);
1839        glTranslatef(0.0f, 0.0f, -15.0f);
1840        glMatrixMode(GL_MODELVIEW);
1841
1842        glEnable(GL_CULL_FACE);
1843        initCommon();
1844        initPbuffer();
1845
1846}
1847
1848
1849void QtGlDebuggerWidget::resizeGL(int w, int h)
1850{
1851        glViewport(0, 0, w, h);
1852}
1853
1854
1855void QtGlDebuggerWidget::paintGL()
1856{
1857        // draw a spinning cube into the pbuffer..
1858        mRenderBuffer->makeCurrent();
1859       
1860        BeamSampleStatistics stats;
1861        mRenderBuffer->SampleBeamContributions(mSourceObject, mBeam, mSamples, stats);
1862
1863        glFlush();
1864
1865        // rendering directly to a texture is not supported on X11, unfortunately
1866    mRenderBuffer->updateDynamicTexture(dynamicTexture);
1867   
1868    // and use the pbuffer contents as a texture when rendering the
1869    // background and the bouncing cubes
1870    makeCurrent();
1871    glBindTexture(GL_TEXTURE_2D, dynamicTexture);
1872    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1873
1874    // draw the background
1875    glMatrixMode(GL_MODELVIEW);
1876    glPushMatrix();
1877    glLoadIdentity();
1878    glMatrixMode(GL_PROJECTION);
1879    glPushMatrix();
1880    glLoadIdentity();
1881
1882        glPopMatrix();
1883        glMatrixMode(GL_MODELVIEW);
1884        glPopMatrix();
1885}
1886
1887
1888void QtGlDebuggerWidget::initPbuffer()
1889{
1890        // set up the pbuffer context
1891    mRenderBuffer->makeCurrent();
1892        /*mRenderBuffer->InitGL();
1893
1894        glViewport(0, 0, mRenderBuffer->size().width(), mRenderBuffer->size().height());
1895        glMatrixMode(GL_PROJECTION);
1896        glLoadIdentity();
1897        glOrtho(-1, 1, -1, 1, -99, 99);
1898        glTranslatef(-0.5f, -0.5f, 0.0f);
1899        glMatrixMode(GL_MODELVIEW);
1900        glLoadIdentity();
1901
1902        glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);*/
1903       
1904        // generate a texture that has the same size/format as the pbuffer
1905    dynamicTexture = mRenderBuffer->generateDynamicTexture();
1906
1907        // bind the dynamic texture to the pbuffer - this is a no-op under X11
1908        mRenderBuffer->bindToDynamicTexture(dynamicTexture);
1909        makeCurrent();
1910}
1911
1912void QtGlDebuggerWidget::initCommon()
1913{
1914        glEnable(GL_TEXTURE_2D);
1915        glEnable(GL_DEPTH_TEST);
1916
1917        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1918}
1919
1920
1921
1922}
Note: See TracBrowser for help on using the repository browser.