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

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