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

Revision 1189, 45.9 KB checked in by mattausch, 18 years ago (diff)

changed osp partition to something taking mult references into account

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