Basic Image AlgorithmS Library 2.8.0

OpenGLCanvasBase.cpp

00001 
00002 /* author: Jan Woetzel */
00003 
00004 #include <Base/Common/BIASpragma.hh>
00005 #include <Utils/GlutInitWrapper.hh>
00006 #include "OpenGLCanvasBase.hh"
00007 
00008 //#if defined(wxUSE_GLCANVAS) && wxUSE_GLCANVAS
00009 //#  error + OK, wx compileed in gl configuration
00010 //#else
00011 //#  error wx has not been compiled with wxUSE_GLCANVAS=1. Please set wx/setup.h wxUSE_GLCANVAS=1 and recompile WX.
00012 //#endif
00013 
00014 
00015 #include <Base/Image/ImageIO.hh>
00016 #include <Base/Math/Vector2.hh>
00017 #include <Base/Math/Vector3.hh>
00018 #include <Base/Math/Vector4.hh>
00019 #include <Base/Common/FileHandling.hh>
00020 #include <Gui/StringConv.hh>
00021 
00022 // contains simple GL calls:
00023 #include "GeometryGL.hh"
00024 
00025 // mode settings (vsync, multi sampling:
00026 #include "SettingsGL.hh"
00027 
00028 
00029 #include <string>
00030 #include <sstream>
00031 #include <iostream>
00032 #include <fstream>
00033 
00034 
00035 #include <wx/defs.h> // key code table
00036 #include <wx/log.h>
00037 
00038 // Nvidia Stereo rendering conrol API:
00039 #ifdef BIAS_HAVE_STEREOI
00040 #  include "StereoI.h"
00041 #endif // BIAS_HAVE_STEREOI
00042 
00043 
00044 // -----------------------------------------
00045 using namespace std;
00046 using namespace BIAS;
00047 // -----------------------------------------
00048 
00049 // WARNING:  if you change the event table here,
00050 // you may need to change it in the derived classes, too! (jw)
00051 BEGIN_EVENT_TABLE (OpenGLCanvasBase, wxGLCanvas)
00052 EVT_PAINT  (OpenGLCanvasBase::OnPaint)
00053 EVT_SIZE   (OpenGLCanvasBase::OnSize)
00054 EVT_ERASE_BACKGROUND (OpenGLCanvasBase::OnEraseBackground)
00055 EVT_CHAR   (OpenGLCanvasBase::OnChar)
00056 END_EVENT_TABLE()
00057 
00058 
00059 // static initialization
00060 unsigned int  OpenGLCanvasBase::instancesTotalNo_ = 0;
00061 double        OpenGLCanvasBase::time = 0.0;
00062 bool              OpenGLCanvasBase::animationUpdateEnabled = OPENGLCANVASBASE_DEFAULT_animationUpdateEnabled;
00063 
00064 #ifdef BIAS_HAVE_STEREOI
00065 // interface to nVidia consumer 3d stereo API
00066 // Please use Get_pStereoAPI()
00067 static StereoI* g_pStereoAPI = NULL;
00068 #endif // BIAS_HAVE_STEREOI
00069 
00070 // ----------------------------------
00071 
00072 // -----------------------------------------
00073 
00074 
00075 /// destructor
00076 OpenGLCanvasBase::~OpenGLCanvasBase()
00077 {
00078 #ifdef BIAS_HAVE_FONTGL
00079   delete p_font;
00080   p_font=NULL;
00081 #endif // BIAS_HAVE_FONTGL
00082 }
00083 
00084 
00085 OpenGLCanvasBase::OpenGLCanvasBase(
00086                                    wxFrame* parent
00087                                    ,wxWindowID id
00088                                    ,const wxPoint& pos
00089                                    ,const wxSize& size
00090                                    ,long style
00091                                    ,const wxString& name
00092                                    ,int* attribList
00093                                    ,const wxPalette& palette  )
00094                                    : wxGLCanvas(parent,id,pos,size,style,name,attribList,palette)
00095                                    ,p_ownerframe(NULL)
00096 #ifdef BIAS_HAVE_FONTGL
00097                                    ,p_font(NULL)
00098 #endif
00099 {
00100   //CALLINFO;
00101 
00102   instancesTotalNo_ ++;
00103   InitMembers();
00104   p_ownerframe=parent;
00105 }
00106 
00107 
00108 OpenGLCanvasBase::OpenGLCanvasBase(
00109                                    wxFrame* parent
00110                                    ,wxGLContext* sharedContext
00111                                    ,wxWindowID id
00112                                    ,const wxPoint& pos
00113                                    ,const wxSize& size
00114                                    ,long style
00115                                    ,const wxString& name
00116                                    ,int* attribList
00117                                    ,const wxPalette& palette  )
00118                                    : wxGLCanvas(parent,sharedContext,id,pos,size,style,name,attribList,palette)
00119                                    ,p_ownerframe(NULL)
00120 #ifdef BIAS_HAVE_FONTGL
00121                                    ,p_font(NULL)
00122 #endif
00123 {
00124   //CALLINFO;
00125 
00126   instancesTotalNo_ ++;
00127   InitMembers();
00128   p_ownerframe=parent;
00129 }
00130 
00131 
00132 void OpenGLCanvasBase::InitMembers()
00133 {
00134   //CALLINFO;
00135 
00136   instance_ = instancesTotalNo_;
00137   InitWithContextDone_ = false;
00138   framecount_ = 0;
00139   animationUpdateEnabled = true;
00140 }
00141 
00142 
00143 void OpenGLCanvasBase::InitWithContext()
00144 {
00145   if (InitWithContextDone_) return; /* already done */
00146 
00147   if (!GetContext())
00148   {
00149     BIASERR("skipped because GetContext failed on frame ");
00150     return; // no context available
00151   };
00152   // OK so far
00153   this->SetCurrent();
00154 
00155   if (!IsContextAvailable())
00156   {
00157     BIASERR("skipped because no context available on glGetString GL_VENDOR test");
00158     return;
00159   }
00160 
00161 
00162 #if defined(BIAS_HAVE_GLUT)
00163 #  if defined(__FREEGLUT_H__) || defined(__FREEGLUT_STD_H__)
00164   {
00165     // freeglut really wants a glutInit call no matter if we use their renderarea handler or not.
00166     int MyArgc=0;
00167     BIAS::GlutInitWrapper::GetInstance()->Init( &MyArgc, (char**)NULL );
00168   }
00169 #  endif
00170 #endif
00171 
00172 
00173 #if defined(BIAS_HAVE_GLEW)
00174   /// OK, we have a (valid) Gl Context
00175   /// run init with context once
00176 #  ifdef USE_EXPERIMENTAL_SETTING_GLEW
00177   // some exp. beta drivers don't expose their "hidden" capabilities
00178   // bypass extension query and force "on" for all extensions.
00179   BIASERR("WARNING: you are forcing bypassing glew extension query"<<endl
00180     <<"because USE_EXPERIMENTAL_SETTING_GLEW is defined."<<endl
00181     <<"This is *NOT* recommended in general (JW)");
00182   glewExperimental=GL_TRUE;
00183 #  endif // USE_EXPERIMENTAL_SETTING_GLEW
00184   // init glew symbols:
00185   int err = glewInit();
00186   if (GLEW_OK != err) {
00187     // problem: glewInit failed, something is seriously wrong
00188     BIASERR("could not init GLEW. Error: "<<glewGetErrorString(err));
00189     exit(-1);
00190   };
00191 #endif // BIAS_HAVE_GLEW
00192 
00193 
00194 #if defined(WIN32) && defined(BIAS_HAVE_GLEW)
00195   // vertical sync initialization
00196   if (WGLEW_EXT_swap_control)
00197   {
00198     SetVSync( rendermode.vsync);
00199     if (GetVSync()!=rendermode.vsync){
00200       BIASERR("could not set vsync to "<<rendermode.vsync<<endl
00201         <<"\tDoes the driver allow application controlled VSYNC/page swapping settings?"<<endl
00202         <<"\tE.g. NVStereo will and driver tab may force overriding our settings." );
00203     };
00204   };
00205 #endif // WIN32
00206 
00207 #ifdef BIAS_HAVE_FONTGL
00208   if (p_font==NULL){
00209     p_font=new DrawTextGL;
00210     BIASASSERT(p_font!=NULL);
00211 #  ifdef WIN32
00212     p_font->InitFont( GetDC(HWND(this->GetHandle())) );
00213 #  else // WIN32
00214     p_font->InitFont( this->GetHandle() );
00215 #endif // WIN32
00216 
00217   }
00218 #endif // BIAS_HAVE_FONTGL
00219 
00220   InitWithContextDone_ =true;
00221 }
00222 
00223 
00224 bool OpenGLCanvasBase::IsContextAvailable()
00225 {
00226   CHECK_GL_ERROR;
00227   if (!(GetParent()->IsShown())) {
00228     //BIASERR("Parent not yet shown err1");
00229     return false;
00230   };
00231   if (!GetContext()) {
00232     BIASERR("Context not (yet?) available.");
00233     return false; // no context available
00234   }
00235   CHECK_GL_ERROR;
00236   if (!(GetParent()->IsShown())) return false;
00237   // OK.
00238 
00239 #ifndef WIN32
00240   // conflicts with FBO:
00241   this->SetCurrent(); // get the GL rendering focus
00242 #endif
00243 
00244   CHECK_GL_ERROR;
00245   // get OpenGL info strings into std. strings:
00246   const unsigned char * p_str=NULL;
00247   p_str = glGetString(GL_VENDOR);
00248   CHECK_GL_ERROR;
00249   if ( p_str==NULL) {
00250     BIASERR("No Context available (NULL ptr)");
00251     CHECK_GL_ERROR;
00252     return false;
00253   };
00254   return true; // OK.
00255 }
00256 
00257 
00258 wxFrame* OpenGLCanvasBase::GetOwnerframe()
00259 {
00260   BIASASSERT(p_ownerframe!=NULL);
00261   return p_ownerframe;
00262 }
00263 
00264 void OpenGLCanvasBase::SetOwnerframe(wxFrame* ptr)
00265 {
00266   p_ownerframe=ptr;
00267 }
00268 
00269 
00270 /// return GL state info
00271 void OpenGLCanvasBase::GetInfoGL(std::ostream & os)
00272 {
00273   if (!GetContext()) return; // no context available
00274   this->SetCurrent(); // get the GL rendering focus
00275   // identify current instance of this canvas (or derived class)
00276   os<<"instance: "<<this->instance_<<endl;
00277 
00278   // display OpenGL status:
00279   GeometryGL::GetInfoGL(os);
00280   CHECK_GL_ERROR;
00281 
00282 #ifdef BIAS_HAVE_STEREOI
00283   // display NV StereoI status:
00284   this->StereoI_GetInfo(os);
00285 #endif //BIAS_HAVE_STEREOI
00286 }
00287 
00288 void OpenGLCanvasBase::SwapBuffers(){
00289   framecount_++;
00290   wxGLCanvas::SwapBuffers();
00291 }
00292 
00293 void
00294 OpenGLCanvasBase::Display()
00295 {
00296   //CALLINFO;
00297   CHECK_GL_ERROR;
00298   // this routine is calling SetCurrent to get rendering focus:
00299   if ( !IsContextAvailable() )
00300     return;
00301   if ( !InitWithContextDone_ )
00302     InitWithContext();
00303   if ( !InitWithContextDone_ )
00304     return;
00305 
00306   if (!(GetParent()->IsShown())) {
00307     BIASERR("Parent not yet shown.");
00308     return;
00309   };
00310 
00311   // realtime clock update (or specialized in derived classed)
00312   UpdateTime(); //< only base needs this, the drived classes use OnIdle event to update the time.
00313 
00314   // dummy catching all previous uncaught GL errors (in particular of other applications)
00315   glGetError();
00316   CHECK_GL_ERROR;
00317 
00318   // display to correct buffer for stereo rendering:
00319   DisplaySelectBuffer();
00320   CHECK_GL_ERROR;
00321 
00322   // set polygonmode, line+point size etc.
00323   DisplayRenderMode();
00324   CHECK_GL_ERROR;
00325   {
00326     /// >>> begin your fancy GL calls (scene like)
00327 
00328     DisplayCalls();
00329 
00330     /// <<< end of your GL calls
00331 
00332   }
00333   // check if we want to display FPS?
00334   CHECK_GL_ERROR;
00335 
00336   this->SwapBuffers(); // glcanvas swap
00337 }
00338 
00339 
00340 void OpenGLCanvasBase::DisplayCalls()
00341 {
00342   /// >>> begin your fancy GL calls
00343 
00344   // simple sample calls:
00345   this->DisplayClear();
00346   this->DisplaySampleScene();
00347 
00348   /// <<< end of your GL calls
00349 }
00350 
00351 
00352 // useful only for quad buffered stereo:
00353 void OpenGLCanvasBase::DisplaySelectBuffer()
00354 {
00355   CHECK_GL_ERROR;
00356   // running quad buffered stereo?
00357   static int bufferNr=0;
00358   switch (rendermode.drawbuffermode)
00359   {
00360   case STEREO_UNTOUCHED:
00361     break;
00362   case MONO:
00363   case STEREO_CONSUMER_NV:
00364     glDrawBuffer(GL_BACK);
00365     CHECK_GL_ERROR;
00366     break;
00367   case STEREO_LEFT_RIGHT:
00368     {
00369       // toggle between left and right:
00370       if (bufferNr==0) {
00371         glDrawBuffer(GL_LEFT);
00372         CHECK_GL_ERROR;
00373         bufferNr=1;
00374       } else {
00375         glDrawBuffer(GL_RIGHT);
00376         CHECK_GL_ERROR;
00377         bufferNr=0;
00378       };
00379       break;
00380     }
00381   case STEREO_QUADBUFFERED:
00382     {
00383       // supported by quadro cards:
00384       //#ifdef BIAS_DEBUG
00385       //            cout<<endl<<"displaying quadbuffered /BACK_LEFT,BACK_RIGHT), bufferNr "<<bufferNr<<endl;
00386       //#endif
00387       // toggle between left and right:
00388       if (bufferNr==0) {
00389         glDrawBuffer(GL_BACK_LEFT);
00390         CHECK_GL_ERROR;
00391         bufferNr=1;
00392       } else {
00393         glDrawBuffer(GL_BACK_RIGHT);
00394         CHECK_GL_ERROR;
00395         bufferNr=0;
00396       };
00397       break;
00398     };
00399   default:
00400     cout<<"unknown/unimplemented rendermode.stereomode"<<rendermode.drawbuffermode<<endl;
00401   };
00402   CHECK_GL_ERROR;
00403 }
00404 
00405 
00406 // static
00407 void OpenGLCanvasBase::DisplayClear(const GLbitfield & mask)
00408 {
00409   GeometryGL::DisplayClear(mask);
00410   CHECK_GL_ERROR;
00411 }
00412 
00413 
00414 void OpenGLCanvasBase::DisplayRenderMode()
00415 {
00416   GeometryGL::DisplayRenderMode(rendermode);
00417 }
00418 
00419 
00420 //static
00421 void OpenGLCanvasBase::DisplaySampleScene()
00422 {
00423   GeometryGL::DisplaySceneExampleSimple();
00424 }
00425 
00426 // static
00427 void OpenGLCanvasBase::DisplayCoordCross(const float & size, const float & linewidth)
00428 {
00429   GeometryGL::DisplayCoordCross(size, linewidth);
00430 
00431   // mark axes labels with "x,y,z"
00432 #ifdef BIAS_HAVE_FONTGL
00433   BIASASSERT(p_font!= NULL);
00434   GeometryGL::DisplayCoordCrossAxesLabel(size, *p_font);
00435   //GeometryGL::DisplayCoordCrossAxesLabel(size, *p_font
00436   //  ,"X axis"
00437   //  ,"Y axis"
00438   //  ,"Z axis"
00439   //  );
00440 
00441 #endif // BIAS_HAVE_FONTGL
00442 }
00443 
00444 
00445 void OpenGLCanvasBase::Reshape()
00446 {
00447   // adapt the viewport to cover full window (overriden in child classes)
00448   glViewport(0,0, GetWidth(), GetHeight() );
00449 
00450   // (re-)display on canvas decrease due to new viewport transformation
00451   Display();
00452 }
00453 
00454 
00455 unsigned int OpenGLCanvasBase::GetWidth() const
00456 {
00457   int w, h;
00458   //GetSize(&w, &h);
00459   GetClientSize(&w, &h); // DBG
00460   return w;
00461 }
00462 
00463 
00464 unsigned int OpenGLCanvasBase::GetHeight() const
00465 {
00466   int w, h;
00467   //GetSize(&w, &h);
00468   GetClientSize(&w, &h);
00469   return h;
00470 }
00471 
00472 
00473 /// @return aspect 'X/Y' = ratio of width being 'bigger' than reference height
00474 float OpenGLCanvasBase::GetAspectRatio() const {
00475   return ((float)GetWidth() / (float)GetHeight());
00476 }
00477 
00478 
00479 
00480 BIAS::Vector3<float>
00481 OpenGLCanvasBase::GetPixelValueRGB(const wxPoint & pos2d)
00482 {
00483   BIAS::Vector3<float> data;
00484   if (!IsContextAvailable()) {
00485     data.Set(0,0,0);
00486     BIASERR("no context");
00487     return data;
00488   };
00489   glReadPixels(
00490     (GLint)pos2d.x,
00491     (GLint)(GetHeight() -pos2d.y),
00492     (GLsizei)1,  (GLsizei)1,
00493     GL_RGB,
00494     GL_FLOAT,
00495     (GLvoid*)(&data[0]) );
00496   return data;
00497 }
00498 
00499 
00500 BIAS::Vector4<float>
00501 OpenGLCanvasBase::GetPixelValueRGBA(const wxPoint & pos2d)
00502 {
00503   BIAS::Vector4<float> data;
00504   if (!IsContextAvailable()) {
00505     data.Set(0,0,0,0);
00506     BIASERR("no context");
00507     return data;
00508   };
00509   glReadPixels((GLint)pos2d.x,
00510     (GLint)(GetHeight() -pos2d.y),
00511     (GLsizei)1,  (GLsizei)1,
00512     GL_RGBA,
00513     GL_FLOAT,
00514     (GLvoid*)(&data[0]) );
00515   return data;
00516 }
00517 
00518 
00519 float
00520 OpenGLCanvasBase::GetPixelValueDepth(const wxPoint & pos2d) const
00521 {
00522   float v=0.0;
00523   CHECK_GL_ERROR
00524     glReadPixels((GLint)pos2d.x,
00525     (GLint)(GetHeight()-pos2d.y),
00526     (GLsizei)1,  (GLsizei)1,
00527     GL_DEPTH_COMPONENT, /* GL_DEPTH */
00528     GL_FLOAT,
00529     (GLvoid*)&v );
00530   CHECK_GL_ERROR
00531     return v;
00532 }
00533 
00534 
00535 BIAS::Vector3<float>
00536 OpenGLCanvasBase::Unproject(const wxPoint & pos2d, double & d)
00537 {
00538   double pos3d[3];
00539   GLint viewport[4];
00540   GLdouble modelview[16];
00541   GLdouble projection[16];
00542   GLfloat wx=pos2d.x, wy=pos2d.y, wz=1;
00543   GLint x=pos2d.x, y=pos2d.y; // non const version of pos2d
00544 
00545   glGetIntegerv(GL_VIEWPORT, viewport);
00546   y=viewport[3]-y;
00547   wy=y;
00548   // get GL status matrices
00549   glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
00550   glGetDoublev(GL_PROJECTION_MATRIX, projection);
00551 
00552   // acces Z buffer value at (x,y)
00553   glReadPixels(x, y, 1,1, GL_DEPTH_COMPONENT, GL_FLOAT, &wz);
00554 
00555   // compute 3D pos by "unprojection":
00556   gluUnProject(wx,wy,wz,
00557     modelview,
00558     projection,
00559     viewport,
00560     &pos3d[0], &pos3d[1], &pos3d[2] );
00561 
00562   //COUT("DBG "<<" wx="<<wx<<" wy="<<wy<<" wz="<<wz" pos3d= "<<pos3d);
00563 
00564   d=wz;
00565   //d=0; // TODO: not correctly implemented !
00566 
00567   // convert to float result:
00568   BIAS::Vector3<float> result(pos3d[0], pos3d[1], pos3d[2] );
00569   return result;
00570 }
00571 
00572 
00573 void OpenGLCanvasBase::ScreenShot(const std::string & filename,
00574                                   const bool & flipY,
00575                                   const GLenum & format,
00576                                   const bool &force8Bit )
00577 {
00578   int nChannels=3;
00579   if (format==GL_RGBA){
00580     nChannels=4;
00581   }
00582 
00583   // create a temporary CPU memory image, assume three channel RGB for now.
00584   BIAS::ImageBase img(GetWidth(), GetHeight(), nChannels );
00585 
00586   this->ScreenShot(img, flipY, format, force8Bit);
00587 
00588   COUT("DBG "<<FUNCNAME<<" is writing "<<filename<<endl<<flush);
00589   int result = BIAS::ImageIO::Save(filename, img );
00590   if (result!=0)
00591   {
00592     BIASERR("could not save "<<filename<<" result="<<result );
00593   }
00594 }
00595 
00596 
00597 
00598 // JW
00599 void OpenGLCanvasBase::ScreenShot(BIAS::ImageBase & dest,
00600                                   const bool & flipY,
00601                                   const GLenum & format,
00602                                   const bool &force8Bit )
00603 {
00604   // adapt image size to screen area:
00605   // TODO: add similar "data area reesize really required" function to BIAS::Image
00606 
00607   unsigned int channels=3;
00608   GLenum type = GL_UNSIGNED_BYTE;
00609   unsigned int ByteDepth=1;
00610   BIAS::ImageBase::EStorageType st=BIAS::ImageBase::ST_unsignedchar;
00611 
00612   switch (format)
00613   {
00614   case GL_DEPTH_COMPONENT:
00615     if (!force8Bit)
00616     {
00617       // we need >=24 bits for depth maps (usually), so si use 32bit float
00618       ByteDepth=4;
00619       type=GL_FLOAT;
00620       st=BIAS::ImageBase::ST_float;
00621     }
00622   case GL_RED:
00623   case GL_GREEN:
00624   case GL_BLUE:
00625   case GL_ALPHA:
00626   case GL_LUMINANCE:
00627   case GL_STENCIL_INDEX:
00628     channels=1;
00629     break;
00630   case GL_LUMINANCE_ALPHA:
00631     channels=2;
00632     break;
00633   case GL_RGB:
00634   case GL_BGR_EXT:
00635     channels=3;
00636     break;
00637   case GL_RGBA:
00638   case GL_BGRA_EXT:
00639     channels=4;
00640     break;
00641   default:
00642     BIASERR("unsupported format");
00643   }
00644 
00645   if ( (dest.GetWidth()  != this->GetWidth())
00646     || (dest.GetHeight() != this->GetHeight())
00647     || (dest.GetChannelCount() !=  channels) /* nr. of channels */
00648     || (dest.GetDepth() !=  ByteDepth) /* Byte per channel */
00649     )
00650   {
00651     if (!dest.IsEmpty()) {
00652       dest.Release();
00653     };
00654     dest.Init( this->GetWidth(), this->GetHeight(),
00655       channels,
00656       st,
00657       true /*interleaved*/
00658       );
00659   }
00660 
00661   CHECK_GL_ERROR;
00662 
00663   // copy data from GPU to CPU:
00664   // read a block from the framebuffer back to CPU
00665 
00666   //if (!IsContextAvailable()) {
00667   //    BIASERR("skipped screenshot because no context available.");
00668   //    return;
00669   //}
00670 
00671   this->SetCurrent();
00672   glFlush();
00673   glFinish();
00674   glReadPixels( GLint(0), GLint(0), // x,y from lower left
00675     GLsizei(this->GetWidth()), GLsizei( this->GetHeight()), // width, height
00676     format, // format,
00677     type, //type
00678     (GLvoid*)dest.GetImageData()
00679     );
00680   CHECK_GL_ERROR;
00681 
00682   // flip vertically because of different texcoord systems between OpenGL and MIP?
00683   if (flipY) dest.Flip();
00684 }
00685 
00686 // JW
00687 void OpenGLCanvasBase::ScreenShot()
00688 {
00689   static unsigned int savedNr=0;
00690   // get context bits:
00691   GLint red_bits=0;
00692   GLint green_bits=0;
00693   GLint blue_bits=0;
00694   GLint alpha_bits=0;
00695   GLint depth_bits=0;
00696   GLint stencil_bits=0;
00697   glGetIntegerv(GL_RED_BITS,     &red_bits);
00698   glGetIntegerv(GL_GREEN_BITS,   &green_bits);
00699   glGetIntegerv(GL_BLUE_BITS,    &blue_bits);
00700   glGetIntegerv(GL_ALPHA_BITS,   &alpha_bits);
00701   glGetIntegerv(GL_DEPTH_BITS,   &depth_bits);
00702   glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
00703 
00704   // create unique filename
00705   stringstream ss;
00706   ss<<"out_screenshot_"
00707     <<"savedNr"<<FileHandling::LeadingZeroString(savedNr,5)
00708     <<"_framecount"<<FileHandling::LeadingZeroString(framecount_, 5)
00709     <<"_instance"<<FileHandling::LeadingZeroString(instance_,2)
00710     ;
00711 
00712   // save RGB tetxure
00713   if ((red_bits>0) || (green_bits>0) || (blue_bits>0)) {
00714     this->ScreenShot( ss.str() +string("_RGB") +string(BIAS_SCREENSHOT_DEFAULT_EXTENSION),
00715       true /*flip*/, GL_RGB );
00716   }
00717 
00718   // save alpha map (if present)
00719   if (alpha_bits>0){
00720     this->ScreenShot( ss.str() +string("_ALPHA") +string(BIAS_SCREENSHOT_DEFAULT_EXTENSION),
00721       true /*flip*/, GL_ALPHA );
00722   }
00723   // save combined rgba
00724   if (red_bits>0 && green_bits>0 && blue_bits>0 && alpha_bits>0) {
00725     this->ScreenShot( ss.str() +string("_RGBA") +string(BIAS_SCREENSHOT_DEFAULT_EXTENSION),
00726       true /*flip*/, GL_RGBA );
00727   }
00728 
00729 
00730   // save depth map (if present)
00731   if (depth_bits>0){
00732     this->ScreenShot( ss.str() +string("_DEPTH") +string(BIAS_SCREENSHOT_DEFAULT_EXTENSION),
00733       true /*flip*/, GL_DEPTH_COMPONENT );
00734   }
00735 
00736   // save stencil buffer (if present)
00737   if (stencil_bits>0){
00738     this->ScreenShot( ss.str() +string("_STENCIL") +string(BIAS_SCREENSHOT_DEFAULT_EXTENSION),
00739       true /*flip*/, GL_STENCIL_INDEX);
00740   }
00741 
00742   savedNr++;
00743 }
00744 
00745 
00746 // JW
00747 void OpenGLCanvasBase::SetStatusText(const wxString& text, int c_field )
00748 {
00749   bool statbarOK=false;
00750   int field = c_field;
00751 
00752   if (p_ownerframe!=NULL){
00753     if (p_ownerframe->GetStatusBar()!=NULL)
00754     {
00755       if (p_ownerframe->GetStatusBar()->GetFieldsCount()>field){
00756         // everything is fine
00757         statbarOK=true;
00758       } else {
00759         // status bar has not enough fields, disply to last field
00760         //#ifdef BIAS_DEBUG
00761         //        BIASERR("p_ownerframe has no only "
00762         //          <<p_ownerframe->GetStatusBar()->GetFieldsCount()
00763         //          <<" fields. could not display to field="<<field<<"!");
00764         //#endif // BIAS_DEBUG
00765         field = (p_ownerframe->GetStatusBar()->GetFieldsCount()) -1;
00766         statbarOK=true;
00767       }
00768     } else {
00769       BIASERR("p_ownerframe has no status bar!");
00770     }
00771     //} else {
00772     //  BIASERR("p_ownerframe is NULL!");
00773   };
00774 
00775   if (statbarOK)
00776   {
00777     p_ownerframe->SetStatusText(text, field);
00778   } else {
00779     // fallback output
00780     cout<<field<<": "<<text<<endl;
00781   };
00782 }
00783 
00784 
00785 void
00786 OpenGLCanvasBase::ShowValue(const wxPoint & pos)
00787 {
00788   CHECK_GL_ERROR;
00789   std::stringstream s;
00790   double d=0.0;
00791   BIAS::Vector3<float> p3d(0,0,0);
00792   p3d = Unproject(pos, d);
00793   CHECK_GL_ERROR;
00794 
00795   //get pixel value under mouse
00796   BIAS::Vector4<float> rgbGL;
00797   rgbGL = GetPixelValueRGBA(pos);
00798   CHECK_GL_ERROR;
00799   float depthGL= GetPixelValueDepth(pos);
00800   CHECK_GL_ERROR;
00801 
00802   //s<<"2d: ";
00803   s<<"("<<pos.x<<";"<<pos.y<<") ";
00804   s<<"rgba=("
00805     <<std::setprecision(5)<<rgbGL[0]<<";"
00806     <<std::setprecision(5)<<rgbGL[1]<<";"
00807     <<std::setprecision(5)<<rgbGL[2]<<";"
00808     <<std::setprecision(5)<<rgbGL[3]<<") ";
00809 
00810   s<<"depthGL="<<std::setprecision(5)<<depthGL<<" ";
00811 
00812   s<<"3d: ";
00813   s<<"["<<p3d[0]<<";"<<p3d[1]<<";"<<p3d[2]<<"] ";
00814   s<<"dist. "<<d<<" ";
00815 
00816 //#ifdef BIAS_DEBUG
00817 //  // display in console (for debugging, in small windows)
00818 //  cout<<s.str()<<endl;
00819 //#endif
00820 
00821   SetStatusText(AsciiToWx(s.str()));
00822 }
00823 
00824 
00825 // computes and displays current FPS in status bar
00826 void OpenGLCanvasBase::ShowFPS(const int & framecounter,
00827                                const float & minUpdateIntervalSec,
00828                                const unsigned int & minNewFrames,
00829                                const unsigned int nField)
00830 {
00831   static float fps=0.0f;
00832   static clock_t start=clock(); // init once
00833   static unsigned int startFrameNo = framecounter;
00834 
00835   // how many frames were drawn since last call:
00836   unsigned int nNewFrames = framecounter - startFrameNo;
00837   if (nNewFrames==0) {
00838     // no frames rendered, keep old value, do not update status bar
00839     return;
00840   } else if (nNewFrames<minNewFrames) {
00841     // too few frames for reliable measurement, keep old, do not update status bar
00842     return;
00843   };
00844 
00845   // measure time and fps since last fps display
00846   clock_t stop=clock();
00847   clock_t duration = stop -start;
00848 
00849   if (float(duration)==0){
00850     // do nothing, keep old value
00851     return;
00852   } else if (duration>=float(CLOCKS_PER_SEC)*minUpdateIntervalSec){
00853     //
00854     // OK
00855     //
00856 
00857     // compute avg fps of the last nNewFrames images
00858     fps = (float)nNewFrames * float(CLOCKS_PER_SEC)/(float)duration;
00859 
00860     //
00861     // prepare next measurement
00862     //
00863     // next start is this stop
00864     start=stop;
00865     startFrameNo = framecounter;
00866 
00867     //
00868     // update status bar
00869     //
00870     stringstream ss;
00871     ss<<fps<<" fps "
00872       <<"("<<framecounter<<")."
00873       ;
00874     SetStatusText(AsciiToWx(ss.str()), nField);
00875   };
00876 }
00877 
00878 
00879 
00880 // HACK: doing fullscreen on frame instead of canvas for now. (JW)
00881 // TODO: hide this, create frame directly around canvas, fullscreen
00882 void OpenGLCanvasBase::ToggleFullScreen()
00883 {
00884   if (p_ownerframe!=NULL) {
00885     long style=0;
00886     if (rendermode.drawbuffermode==BIAS::STEREO_CONSUMER_NV){
00887       // works only in true fullscreen,
00888       // thus all menu and statusbar need to be disabled!
00889       style = style | wxFULLSCREEN_ALL;
00890     }
00891     p_ownerframe->ShowFullScreen(
00892       !(p_ownerframe->IsFullScreen()),
00893       style
00894       |OpenGLCanvasBase_DEFAULT_FULLSCREEN_STYLE
00895       //|wxFULLSCREEN_NOMENUBAR
00896       //|wxFULLSCREEN_NOTOOLBAR
00897       //|wxFULLSCREEN_NOSTATUSBAR
00898       //|wxFULLSCREEN_NOBORDER
00899       //|wxFULLSCREEN_NOCAPTION
00900       //|wxFULLSCREEN_ALL
00901       );
00902   }
00903 }
00904 
00905 
00906 void OpenGLCanvasBase::ShowFPS()
00907 {
00908   ShowFPS(this->framecount_,
00909     3.0f, /* sec, */
00910     1, /* nr of new frames */
00911     1 /* nField in status bar */
00912     );
00913 }
00914 
00915 
00916 ///
00917 /// EVT handlers: ------------------------------------------
00918 ///
00919 
00920 void OpenGLCanvasBase::OnPaint( wxPaintEvent &WXUNUSED(event) )
00921 {
00922   // This is a dummy, to avoid an endless succession of paint messages.
00923   // OnPaint handlers must always create a wxPaintDC.
00924   wxPaintDC dc(this);
00925   Display();
00926 }
00927 
00928 
00929 void OpenGLCanvasBase::OnSize(wxSizeEvent& )
00930 {
00931   Reshape();
00932 }
00933 
00934 
00935 std::ostream & OpenGLCanvasBase::PrintHelp(std::ostream & os)
00936 {
00937   os<<"key function assignment:"<<endl
00938     <<"F1\t this help"<<endl
00939     <<"F10, INSERT, p\t Screenshot"<<endl
00940     <<"z,y\tPOINT rendering mode"<<endl
00941     <<"x\tLINE polygon rendering mode (wireframe)"<<endl
00942     <<"c\tFILL polygon rendering mode (vertices)"<<endl
00943     <<"v\tFILL front, LINE back polygon rendering mode"<<endl
00944     <<"Z,Y\tSMOOTH shading mode"<<endl
00945     <<"X\tFLAT shading mode"<<endl
00946     <<"i\tInformation, e.g. on OpenGL status"<<endl
00947     <<"k\t toggle culling back  sides"<<endl
00948     <<"K\t toggle culling front sides"<<endl
00949     <<"L\t toggle culling front and back sides, "<<endl
00950     <<" \t =draw only LINES and POINTS, no faces at all."<<endl
00951     <<"]\t increase pointsize (++)"<<endl
00952     <<"[\t decrease pointsize (--)"<<endl
00953     <<"s\tstop animation (halt)"<<endl
00954     <<"a\tanimate=run animation"<<endl
00955     <<"f,F\ttoggle Fullscreen modus (of the frame)"<<endl
00956     <<"V\ttoggle VSYNC swap control on/off"<<endl
00957     ;
00958   return os;
00959 }
00960 
00961 
00962 //JW
00963 void OpenGLCanvasBase::OnChar(wxKeyEvent& event)
00964 {
00965   switch (event.GetKeyCode())
00966   {
00967   case WXK_F1: /* popup simple help */
00968     {
00969       stringstream ss;
00970       PrintHelp(ss);
00971       ::wxMessageBox(AsciiToWx(ss.str()), wxT("Help"), wxICON_INFORMATION | wxOK );
00972       break;
00973     }
00974 #ifdef BIAS_HAVE_STEREOI
00975   case WXK_F3:
00976     //StereoI_Init();
00977     StereoI_GetInfo();
00978     break;
00979 #endif // BIAS_HAVE_STEREOI
00980   case WXK_PRINT: /* is ignored on WinXP, thus assign other keys, too. (jw) */
00981   case 'p':
00982   case WXK_F10:
00983     SetStatusText(wxT("saving screenshot."));
00984     this->ScreenShot(); break;
00985     //case WXK_F5: // toggles idleRepaintEnabled
00986     //  {
00987     //      idleRepaintEnabled = !idleRepaintEnabled ;
00988     //      stringstream ss;
00989     //      ss<<"Toggled idleRepaintEnabled="<<idleRepaintEnabled;
00990     //      // TODO: Disconnect, GetEventHandler
00991     //      this->GetEventHandler()->Disconnect( ID, wxID_ANY, EVT_IDLE);
00992     //      cout<<ss.str()<<endl;
00993     //      SetStatusText( ss.str().c_str() );
00994     //      break;
00995     //  }
00996   case 'z': /* english keyboard */
00997   case 'y': /* german keyboard */
00998     rendermode.polygonmodeFRONT=GL_POINT;
00999     rendermode.polygonmodeBACK=GL_POINT;
01000     SetStatusText(wxT("PolygonMode POINT"));
01001     Display();
01002     break;
01003   case 'x':  /* wireframe */
01004     rendermode.polygonmodeFRONT=GL_LINE;
01005     rendermode.polygonmodeBACK=GL_LINE;
01006     SetStatusText(wxT("PolygonMode LINE"));
01007     Display();
01008     break;
01009   case 'c':
01010     rendermode.polygonmodeFRONT=GL_FILL;
01011     rendermode.polygonmodeBACK=GL_FILL;
01012     SetStatusText(wxT("PolygonMode FILL"));
01013     Display();
01014     break;
01015   case 'v':
01016     // useful to debug culling
01017     rendermode.polygonmodeFRONT=GL_FILL;
01018     rendermode.polygonmodeBACK=GL_LINE;
01019     SetStatusText(wxT("PolygonMode: front=FILL, back=LINE"));
01020     Display();
01021     break;
01022   case 'Z':
01023   case 'Y':
01024     rendermode.shademodel=GL_SMOOTH;
01025     SetStatusText(wxT("SMOOTH shading"));
01026     Display();
01027     break;
01028   case 'X':
01029     rendermode.shademodel=GL_FLAT;
01030     SetStatusText(wxT("FLAT shading"));
01031     Display();
01032     break;
01033   case 'k':
01034     // backface culling = right hand order to viewer is drawn
01035     if (rendermode.cullface==GL_BACK)
01036       rendermode.enable_cullface = !(rendermode.enable_cullface); // toggle
01037     else
01038       rendermode.enable_cullface = true;
01039     rendermode.cullface=GL_BACK;
01040     if (rendermode.enable_cullface)
01041       SetStatusText(wxT("enabled culling BACK sides (clockwise ordering) "));
01042     else
01043       SetStatusText(wxT("disabled culling."));
01044     Display();
01045     break;
01046   case 'K':
01047     if (rendermode.cullface==GL_FRONT)
01048       rendermode.enable_cullface = !(rendermode.enable_cullface); // toggle
01049     else
01050       rendermode.enable_cullface = true;
01051     rendermode.cullface=GL_FRONT;
01052     if (rendermode.enable_cullface)
01053       SetStatusText(wxT("enabled culling FRONT sides (counterclockwise ordering) "));
01054     else
01055       SetStatusText(wxT("disabled culling. "));
01056     Display();
01057     break;
01058   case 'L':
01059     if (rendermode.cullface==GL_FRONT_AND_BACK)
01060       rendermode.enable_cullface = !(rendermode.enable_cullface); // toggle
01061     else
01062       rendermode.enable_cullface = true;
01063     rendermode.cullface=GL_FRONT_AND_BACK;
01064     // unusual: culling all faces, only lines and points ar drawn!
01065     if (rendermode.enable_cullface)
01066       SetStatusText(wxT("warning: Culling front and back. No faces are drawn, only LINES and POINTS are drawn, no polygones!"));
01067     else
01068       SetStatusText(wxT("disabled culling."));
01069     Display();
01070     break;
01071   case 'i': /* show information */
01072     {
01073       stringstream ss;
01074       this->GetInfoGL(ss);
01075       cout<<ss.str()<<endl;
01076       // this window is too big, add wxDialog with scrollable text control
01077       //::wxMessageBox(wxString(ss.str().c_str()), "Information", wxICON_INFORMATION | wxOK );
01078       ::wxMessageBox(wxT("see cout for information on current OpenGL status."), wxT("Information"), wxICON_INFORMATION | wxOK );
01079       break;
01080     }
01081   case ']':
01082     {
01083       if (rendermode.pointsize<63.0f) rendermode.pointsize++;
01084       BIASASSERT(rendermode.pointsize>=1.0f);
01085       BIASASSERT(rendermode.pointsize<=63.0f);
01086       stringstream ss;
01087       ss<<"increased pointsize to "<<rendermode.pointsize;
01088       SetStatusText( AsciiToWx(ss.str()) );
01089       Display();
01090       break;
01091     }
01092   case '[':
01093     {
01094       if (rendermode.pointsize>1.0f) {
01095         rendermode.pointsize--;
01096       }
01097       BIASASSERT(rendermode.pointsize>=1.0f);
01098       BIASASSERT(rendermode.pointsize<=63.0f);
01099       stringstream ss;
01100       ss<<"decreased pointsize to "<<rendermode.pointsize;
01101       SetStatusText( AsciiToWx(ss.str()) );
01102       Display();
01103       break;
01104     }
01105   case 's':
01106     animationUpdateEnabled =false;
01107     SetStatusText(wxT("stopped animation"));    break;
01108   case 'a':
01109     animationUpdateEnabled = true;
01110     SetStatusText(wxT("animation running"));    break;
01111   case 'f':
01112   case 'F':
01113     ToggleFullScreen(); break;
01114   case 'V':
01115     {
01116       string msg;
01117       if (!ToggleVSync()){
01118         // error
01119         msg="toggling failed. still: ";
01120         BIASERR("toggling VSync failed. Please verify: "<<endl
01121           <<"  -application controlled vsync should be set in driver tab on WIN32"<<endl
01122           <<"  -Nvidia Stereo driver may override vsync (for shutter glasses)"<<endl );
01123       }
01124       if (GetVSync())
01125         msg+="VSYNC enabled";
01126       else
01127         msg+="VSYNC disable";
01128       COUT(msg<<endl);
01129       SetStatusText(AsciiToWx(msg));
01130       break;
01131     }
01132   }; // end of switch keycode
01133   // always skip keycodes because parent canvases may use them, too - e.g. for menu short cuts.
01134   event.Skip();
01135 }
01136 
01137 
01138 void OpenGLCanvasBase::OnEraseBackground(wxEraseEvent& )
01139 {
01140   // do nothing (with intention) to help avoid flashing
01141 }
01142 
01143 
01144 void OpenGLCanvasBase::SetVSync( const bool & trueForOn )
01145 {
01146   if (trueForOn)
01147     SettingsGL::SetVSyncInterval( int(1) );
01148   else
01149     SettingsGL::SetVSyncInterval( int(0) );
01150 }
01151 
01152 
01153 bool OpenGLCanvasBase::GetVSync()
01154 {
01155   return (SettingsGL::GetVSyncInterval() != int(0) );
01156 }
01157 
01158 
01159 bool OpenGLCanvasBase::ToggleVSync()
01160 {
01161   bool act = GetVSync();
01162   SetVSync( !act ); // try to toggle
01163   // did the status really change?
01164   return (act!= GetVSync() );
01165 }
01166 
01167 
01168 void OpenGLCanvasBase::UpdateTime()
01169 {
01170   time = double(clock()) / double(CLOCKS_PER_SEC);
01171 }
01172 
01173 bool OpenGLCanvasBase::ToggleIP(bool & value){
01174   value = !value;
01175   return value;
01176 }
01177 
01178 
01179 // JW
01180 #ifdef BIAS_HAVE_STEREOI
01181 int OpenGLCanvasBase::StereoI_Init()
01182 {
01183   if (g_pStereoAPI!=NULL){
01184     BIASERR("StereoI API already initialized through g_pStereoAPI."<<endl
01185       <<"\tinterface creation should be called once, only. aborting." );
01186     return -1;
01187   };
01188   // must be NULL to use interface only once.
01189   BIASASSERT(g_pStereoAPI==NULL);
01190   if(!CreateStereoI(&g_pStereoAPI)){
01191     BIASERR("CreateStereoI failed. Did you install NVStereo and Nvidia GPU drivers? aborting.");
01192     g_pStereoAPI = NULL;
01193     return -2;
01194   };
01195   BIASASSERT(g_pStereoAPI!=NULL);
01196   if (g_pStereoAPI->GetStereoState() == STEREO_STATE_DISABLED){
01197     BIASERR("Stereo is currently DISABLED.  Did you install enable NVStereo in the driver control panel?");
01198     return -3;
01199   }
01200 
01201   // be verbose on current status:
01202   StereoI_GetInfo();
01203 
01204   return 0; // OK=success
01205 }
01206 
01207 
01208 /* catch missing initializations
01209 and insert assertion on NULL ptr */
01210 StereoI* Get_pStereoAPI(){
01211   if (g_pStereoAPI==NULL)
01212     OpenGLCanvasBase::StereoI_Init();
01213   if (g_pStereoAPI==NULL){
01214     BIASERR("StereoI API not avaible through g_pStereoAPI.");
01215     return NULL;
01216   }
01217   BIASASSERT(g_pStereoAPI!=NULL);
01218   return g_pStereoAPI;
01219 }
01220 
01221 
01222 void OpenGLCanvasBase::StereoI_GetInfo(std::ostream &os)
01223 {
01224   if (Get_pStereoAPI()==NULL)
01225   {
01226     StereoI_Init();
01227     BIASERR("StereoI API not avaible through g_pStereoAPI.");
01228     return;
01229   }
01230   os<<"*StereoI state is:"<<endl;
01231   int tmp=0;
01232   os<<"CheckAPIVersion >=1: "<<bool(Get_pStereoAPI()->CheckAPIVersion(1)>=0)<<endl;
01233 
01234   tmp=Get_pStereoAPI()->GetStereoState();
01235   switch (tmp){
01236     case STEREO_STATE_ENABLED:
01237       os<<"STEREO_STATE_ENABLED"<<endl;
01238       break;
01239     case STEREO_STATE_DISABLED:
01240       os<<"STEREO_STATE_DISABLED"<<endl;
01241     default:
01242       {
01243         stringstream ss;
01244         ss<<"STEREO_STATE="<<tmp<<" is unknown.";
01245         BIASERR(ss.str());
01246         break;
01247       }
01248   };
01249   os<<"Separation:  "<<Get_pStereoAPI()->GetSeparation()<<endl;
01250   os<<"Convergence: "<<Get_pStereoAPI()->GetConvergence()<<endl;
01251 }
01252 
01253 
01254 // simple wrappers:
01255 int OpenGLCanvasBase::StereoI_GetStereoState()
01256 {
01257   if (Get_pStereoAPI()==NULL)   {
01258     BIASERR("StereoI API not avaible through g_pStereoAPI.");
01259     return 0.0f;
01260   }
01261   return Get_pStereoAPI()->GetStereoState();
01262 }
01263 int OpenGLCanvasBase::StereoI_SetStereoState(const int & val)
01264 {
01265   if (Get_pStereoAPI()==NULL)   {
01266     BIASERR("StereoI API not avaible through g_pStereoAPI.");
01267     return 0.0f;
01268   }
01269   return Get_pStereoAPI()->SetStereoState(val);
01270 }
01271 float OpenGLCanvasBase::StereoI_GetSeparation()
01272 {
01273   if (Get_pStereoAPI()==NULL)   {
01274     BIASERR("StereoI API not avaible through g_pStereoAPI.");
01275     return 0.0f;
01276   }
01277   return Get_pStereoAPI()->GetSeparation();
01278 }
01279 float OpenGLCanvasBase::StereoI_SetSeparation(const float & val)
01280 {
01281   if (Get_pStereoAPI()==NULL)   {
01282     BIASERR("StereoI API not avaible through g_pStereoAPI.");
01283     return 0.0f;
01284   }
01285   return Get_pStereoAPI()->SetSeparation(val);
01286 }
01287 float OpenGLCanvasBase::StereoI_GetConvergence()
01288 {
01289   if (Get_pStereoAPI()==NULL)   {
01290     BIASERR("StereoI API not avaible through g_pStereoAPI.");
01291     return 0.0f;
01292   }
01293   return Get_pStereoAPI()->GetConvergence();
01294 }
01295 float OpenGLCanvasBase::StereoI_SetConvergence(const float & val)
01296 {
01297   if (Get_pStereoAPI()==NULL)   {
01298     BIASERR("StereoI API not avaible through g_pStereoAPI.");
01299     return 0.0f;
01300   }
01301   return Get_pStereoAPI()->SetConvergence(val);
01302 }
01303 void OpenGLCanvasBase::StereoI_CaptureStereoImage(const int & format,
01304                                                   const int & quality)
01305 {
01306   if (Get_pStereoAPI()==NULL)   {
01307     BIASERR("StereoI API not avaible through g_pStereoAPI.");
01308     return;
01309   }
01310   return Get_pStereoAPI()->CaptureStereoImage(format, quality);
01311 }
01312 #endif // BIAS_HAVE_STEREOI
01313 
01314 
01315 
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends