source: GTP/trunk/Lib/Vis/QtRenderer/QtGlRenderer.cpp @ 1151

Revision 1151, 46.1 KB checked in by mattausch, 18 years ago (diff)

worded on dll loading

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