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

Revision 1387, 45.9 KB checked in by bittner, 18 years ago (diff)

updates to make qt version running again

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