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

Revision 1594, 50.7 KB checked in by bittner, 18 years ago (diff)

support for kd tree based pvs

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