GLViewer.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00023 #ifdef __APPLE__
00024 #include "panoinc_WX.h"
00025 #endif
00026 
00027 #include "base_wx/wxutils.h"
00028 
00029 #include "panoinc.h"
00030 #include <config.h>
00031 #include <GL/glew.h>
00032 #include <base_wx/platform.h>
00033 #include <wx/settings.h>
00034 #include <wx/dcclient.h>
00035 #include <wx/event.h>
00036 
00037 #include "GLViewer.h"
00038 #include "GLRenderer.h"
00039 #include "TextureManager.h"
00040 #include "MeshManager.h"
00041 #include "ToolHelper.h"
00042 #include "GLPreviewFrame.h"
00043 #include "hugin/huginApp.h"
00044 
00045 bool GLViewer::initialised_glew=false;
00046 ViewState * GLViewer::m_view_state = NULL;
00047 size_t GLViewer::m_view_state_observer = 0;
00048 
00049 BEGIN_EVENT_TABLE(GLViewer, wxGLCanvas)
00050     EVT_PAINT (GLViewer::RedrawE)
00051     EVT_SIZE  (GLViewer::Resized)
00052     EVT_ERASE_BACKGROUND(GLViewer::OnEraseBackground)
00053     // mouse motion
00054     EVT_MOTION (GLViewer::MouseMotion)
00055     // mouse entered or left the preview
00056     EVT_ENTER_WINDOW(GLViewer::MouseEnter)
00057     EVT_LEAVE_WINDOW(GLViewer::MouseLeave)
00058     // mouse buttons
00059     EVT_MOUSEWHEEL(GLViewer::MouseWheel)
00060     EVT_MOUSE_EVENTS(GLViewer::MouseButtons)
00061     // keyboard events
00062     EVT_KEY_DOWN(GLViewer::KeyDown)
00063     EVT_KEY_UP(GLViewer::KeyUp)
00064 END_EVENT_TABLE()
00065 
00066 
00067 GLViewer::GLViewer(
00068             wxWindow* parent, 
00069             HuginBase::Panorama &pano, 
00070             int args[], 
00071             GLPreviewFrame *frame_in,
00072             wxGLContext * shared_context
00073             ) :
00074 #if defined __WXGTK__ || wxCHECK_VERSION(2,9,0)
00075           wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize,
00076                      0, wxT("GLPreviewCanvas"), wxNullPalette)
00077 #else
00078           wxGLCanvas(parent,shared_context,wxID_ANY,wxDefaultPosition,
00079                      wxDefaultSize,0,wxT("GLPreviewCanvas"),args,wxNullPalette)
00080 #endif
00081 {
00082     /* The openGL display context doesn't seem to be created automatically on
00083      * wxGTK, (wxMSW and wxMac 2.8 does implicit create wxGLContext,
00084      * wxWidgets 2.9 requires to explicit create wxGLContext, 
00085      * so I create a new context... */
00086 #if defined __WXGTK__ || wxCHECK_VERSION(2,9,0)
00087     m_glContext = new wxGLContext(this, shared_context);
00088 #endif
00089   
00090     m_renderer = 0;
00091     m_visualization_state = 0;
00092     
00093     m_pano = &pano;
00094 
00095     frame = frame_in;
00096 
00097     m_background_color = frame->GetPreviewBackgroundColor();
00098     
00099     started_creation = false;
00100     redrawing = false;
00101     m_toolsInitialized = false;
00102 
00103     active = true;
00104 }
00105 
00106 GLViewer::~GLViewer()
00107 {
00108 #if defined __WXGTK__ || wxCHECK_VERSION(2,9,0)
00109     delete m_glContext;
00110 #endif
00111     if (m_renderer)
00112     {
00113       delete m_tool_helper;
00114       delete m_renderer;
00115       delete m_visualization_state;
00116       // because m_view_state is a static member variable we need to check
00117       // if other class has already deleted it
00118       --m_view_state_observer;
00119       if (m_view_state_observer == 0)
00120       {
00121         delete m_view_state;
00122         m_view_state=NULL;
00123       }
00124     }
00125 }
00126 
00127 void GLViewer::SetUpContext()
00128 {
00129     // set the context
00130     DEBUG_INFO("Setting rendering context...");
00131     Show();
00132 #if defined __WXGTK__ || wxCHECK_VERSION(2,9,0)
00133     m_glContext->SetCurrent(*this);
00134 #else
00135     SetCurrent();
00136 #endif
00137     DEBUG_INFO("...got a rendering context.");
00138     if (!started_creation)
00139     {
00140         // It appears we are setting up for the first time.
00141         started_creation = true;
00142         
00143         if (!initialised_glew)
00144         {
00145             // initialise the glew library, if not done it before.
00146             GLenum error_state = glewInit();
00147             initialised_glew = true;
00148             if (error_state != GLEW_OK)
00149             {
00150                 // glewInit failed
00151                 started_creation=false;
00152                 DEBUG_ERROR("Error initialising GLEW: "
00153                         << glewGetErrorString(error_state) << ".");
00154                 frame->Close();
00155                 wxMessageBox(_("Error initializing GLEW\nFast preview window can not be opened."),_("Error"), wxOK | wxICON_ERROR);
00156                 return;
00157             }
00158         }
00159         // check the openGL capabilities.
00160         if (!(GLEW_VERSION_1_1 && GLEW_ARB_multitexture))
00161         {
00162             started_creation=false;
00163             wxConfigBase::Get()->Write(wxT("DisableOpenGL"), 1l);
00164             wxConfigBase::Get()->Flush();
00165             DEBUG_ERROR("Sorry, OpenGL 1.1 + GL_ARB_multitexture extension required.");
00166             frame->Close();
00167             wxMessageBox(_("Sorry, the fast preview window requires a system which supports OpenGL version 1.1 with the GL_ARB_multitexture extension.\nThe fast preview cannot be opened.\n\nHugin has been configured to start without fast preview.\nPlease restart Hugin."),_("Error"), wxOK | wxICON_ERROR);
00168             return;
00169         }
00170 
00171         setUp();
00172 #ifdef __WXGTK__
00173         if(this==frame->getPreview())
00174         {
00175             frame->getOverview()->setUp();
00176         }
00177         else
00178         {
00179             frame->getPreview()->setUp();
00180         };
00181 #endif
00182     }
00183 }
00184 
00185 void GLPreview::setUp()
00186 {
00187     DEBUG_DEBUG("Preview Setup");
00188     if (m_toolsInitialized)
00189     {
00190         return;
00191     };
00192     m_toolsInitialized = true;
00193     // we need something to store the state of the view and control updates
00194     if (!m_view_state)
00195     {
00196         GLint countMultiTexture;
00197         glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&countMultiTexture);
00198         m_view_state = new ViewState(m_pano, countMultiTexture>1);
00199     }
00200     ++m_view_state_observer;
00201     m_visualization_state = new VisualizationState(m_pano, m_view_state, this, RefreshWrapper, this, (PreviewMeshManager*) NULL);
00202     //Start the tools going:
00203     PreviewToolHelper *helper = new PreviewToolHelper(m_pano, m_visualization_state, frame);
00204     m_tool_helper = static_cast<ToolHelper*>(helper);
00205     frame->MakePreviewTools(helper);
00206     // now make a renderer
00207     m_renderer =  new GLPreviewRenderer(m_pano, m_view_state->GetTextureManager(),
00208                                  m_visualization_state->GetMeshManager(),
00209                                  m_visualization_state, helper, m_background_color);
00210 }
00211 
00212 GLOverview::~GLOverview()
00213 {
00214     if (m_renderer)
00215     {
00216         if (m_renderer == plane_m_renderer)
00217         {
00218             delete panosphere_m_tool_helper;
00219             delete panosphere_m_renderer;
00220             delete panosphere_m_visualization_state;
00221         }
00222         else
00223         {
00224             delete plane_m_tool_helper;
00225             delete plane_m_renderer;
00226             delete plane_m_visualization_state;
00227         };
00228     };
00229 }
00230 
00231 void GLOverview::setUp()
00232 {
00233     DEBUG_DEBUG("Overview Setup");
00234     if (m_toolsInitialized)
00235     {
00236         return;
00237     };
00238     m_toolsInitialized = true;
00239     // we need something to store the state of the view and control updates
00240     if (!m_view_state)
00241     {
00242         GLint countMultiTexture;
00243         glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&countMultiTexture);
00244         m_view_state = new ViewState(m_pano, countMultiTexture>1);
00245     }
00246     ++m_view_state_observer;
00247 
00248     panosphere_m_visualization_state = new PanosphereOverviewVisualizationState(m_pano, m_view_state, this, RefreshWrapper, this);
00249     plane_m_visualization_state = new PlaneOverviewVisualizationState(m_pano, m_view_state, this, RefreshWrapper, this);
00250 
00251     m_visualization_state = panosphere_m_visualization_state;
00252 
00253     //Start the tools going:
00254     panosphere_m_tool_helper = new PanosphereOverviewToolHelper(m_pano, panosphere_m_visualization_state, frame);
00255     frame->MakePanosphereOverviewTools(panosphere_m_tool_helper);
00256 
00257     plane_m_tool_helper = new PlaneOverviewToolHelper(m_pano, plane_m_visualization_state, frame);
00258     frame->MakePlaneOverviewTools(plane_m_tool_helper);
00259 
00260     // now make a renderer
00261     panosphere_m_renderer =  new GLPanosphereOverviewRenderer(m_pano, m_view_state->GetTextureManager(),
00262                                  panosphere_m_visualization_state->GetMeshManager(),
00263                                  panosphere_m_visualization_state, panosphere_m_tool_helper, m_background_color);
00264     plane_m_renderer =  new GLPlaneOverviewRenderer(m_pano, m_view_state->GetTextureManager(),
00265                                  plane_m_visualization_state->GetMeshManager(),
00266                                  plane_m_visualization_state, plane_m_tool_helper, m_background_color);
00267                                  
00268     switch(mode) {
00269         case PANOSPHERE:
00270             m_visualization_state = panosphere_m_visualization_state;
00271             m_tool_helper = panosphere_m_tool_helper;
00272             m_renderer = panosphere_m_renderer;
00273             break;
00274         case PLANE:
00275             m_visualization_state = plane_m_visualization_state;
00276             m_tool_helper = plane_m_tool_helper;
00277             m_renderer = plane_m_renderer;
00278             break;
00279     }
00280 }
00281 
00282 void GLViewer::SetPhotometricCorrect(bool state)
00283 {
00284     m_view_state->GetTextureManager()->SetPhotometricCorrect(state);
00285     Refresh();
00286 }
00287 
00288 void GLViewer::SetLayoutMode(bool state)
00289 {
00290     m_visualization_state->GetMeshManager()->SetLayoutMode(state);
00291     Refresh();
00292 }
00293 
00294 void GLViewer::SetLayoutScale(double scale)
00295 {
00296     m_visualization_state->GetMeshManager()->SetLayoutScale(scale);
00297     Refresh();
00298 }
00299 
00300 void GLOverview::SetLayoutMode(bool state)
00301 {
00302     panosphere_m_visualization_state->GetMeshManager()->SetLayoutMode(state);
00303     plane_m_visualization_state->GetMeshManager()->SetLayoutMode(state);
00304     Refresh();
00305 }
00306 
00307 void GLOverview::SetLayoutScale(double scale)
00308 {
00309     panosphere_m_visualization_state->GetMeshManager()->SetLayoutScale(scale*MeshManager::PanosphereOverviewMeshInfo::scale_diff);
00310     plane_m_visualization_state->GetMeshManager()->SetLayoutScale(scale);
00311     Refresh();
00312 }
00313 
00314 
00315 void GLViewer::RedrawE(wxPaintEvent& e)
00316 {
00317     if (!IsActive()) {
00318         return;
00319     }
00320     
00321     //TODO: CanResize specific to a viewer?
00322     DEBUG_DEBUG("REDRAW_E");
00323     if(!IsShown()) return;
00324     // don't redraw during a redraw.
00325     if (!(frame->CanResize())) {
00326         DEBUG_DEBUG("RESIZE IN REDRAW");
00327         frame->ContinueResize();
00328         return;
00329     }
00330         
00331     if (!redrawing)
00332     {
00333         DEBUG_DEBUG("REDRAW_E IN");
00334         redrawing = true;
00335         SetUpContext();
00336         wxPaintDC dc(this); // we need this object on the stack to draw.
00337         Redraw();
00338         redrawing = false;
00339     }
00340     DEBUG_DEBUG("END OF REDRAW_E");
00341 }
00342 
00343 void GLViewer::RefreshWrapper(void * obj)
00344 {
00345     DEBUG_DEBUG("REFRESH WRAPPER");
00346     GLViewer* self = static_cast<GLViewer*>(obj);
00347     self->Refresh();
00348 }
00349 
00350 void GLViewer::Resized(wxSizeEvent& e)
00351 {
00352 
00353     if (!IsActive()) {
00354         return;
00355     }
00356 
00357     DEBUG_DEBUG("RESIZED_OUT");
00358    
00359     if (frame->CanResize()) {
00360         DEBUG_DEBUG("RESIZED_IN");
00361 #if !wxCHECK_VERSION(3,0,0)
00362         wxGLCanvas::OnSize(e);
00363 #endif
00364         if(!IsShown()) return;
00365         // if we have a render at this point, tell it the new size.
00366         DEBUG_DEBUG("RESIZED_IN_SHOWN");
00367         if (m_renderer)
00368         {
00369           int w, h;
00370           DEBUG_DEBUG("RESIZED_IN_RENDERER");
00371           GetClientSize(&w, &h);    
00372           SetUpContext();
00373           offset = m_renderer->Resize(w, h);
00374           Redraw();
00375         };
00376     }
00377 }
00378 
00379 void GLViewer::Redraw()
00380 {
00381     // get the renderer to redraw the OpenGL stuff
00382     if(!m_renderer) return;
00383     // don't redraw if we are in middle of a pending change of the panorama object
00384     if(m_pano->hasPendingChanges()) return;
00385     DEBUG_INFO("Rendering.");
00386     
00387     // we should use the window background colour outside the panorama
00388     // FIXME shouldn't this work on textured backrounds?
00389     wxColour col = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
00390     m_renderer->SetBackground(col.Red(), col.Green(), col.Blue());
00391     if (m_visualization_state->RequireRecalculateViewport())
00392     {
00393         // resize the viewport in case the panorama dimensions have changed.
00394         int w, h;
00395         GetClientSize(&w, &h);
00396         offset = m_renderer->Resize(w, h);
00397     }
00398     m_visualization_state->DoUpdates();
00399     m_renderer->Redraw();
00400     glFlush();
00401     SwapBuffers();
00402     // tell the view state we did all the updates and redrew.
00403     m_visualization_state->FinishedDraw();
00404     DEBUG_INFO("Finished Rendering.");
00405 }
00406 
00407 void GLViewer::OnEraseBackground(wxEraseEvent& e)
00408 {
00409     // Do nothing, to avoid flashing on MSW
00410 }
00411 
00412 void GLViewer::MouseMotion(wxMouseEvent& e)
00413 {
00414     if(m_renderer)
00415         m_tool_helper->MouseMoved((int) e.m_x - offset.x,
00416                               (int) e.m_y - offset.y, e);
00417 }
00418 
00419 void GLViewer::MouseEnter(wxMouseEvent & e)
00420 {
00421     if(m_renderer)
00422         m_tool_helper->MouseEnter((int) e.m_x - offset.x,
00423                               (int) e.m_y - offset.y, e);
00424 }
00425 
00426 void GLViewer::MouseLeave(wxMouseEvent & e)
00427 {
00428     if(m_renderer)
00429         m_tool_helper->MouseLeave();
00430 }
00431 
00432 void GLViewer::MouseButtons(wxMouseEvent& e)
00433 {
00434     if(m_renderer) {
00435         //disregard non button events
00436         if (e.IsButton()) {
00437             m_tool_helper->MouseButtonEvent(e);
00438         }
00439     }
00440 #ifdef __WXMSW__
00441     //use normal mouse button processing of GLCanvas 
00442     //otherwise the mouse wheel is not working
00443     e.Skip();
00444 #endif
00445 }
00446 
00447 void GLViewer::MouseWheel(wxMouseEvent& e)
00448 {
00449     if(m_renderer) {
00450         m_tool_helper->MouseWheelEvent(e);
00451     }
00452 }
00453 
00454 
00455 void GLViewer::KeyDown(wxKeyEvent& e)
00456 {
00457     if(m_renderer)
00458         m_tool_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
00459 }
00460 
00461 void GLViewer::KeyUp(wxKeyEvent& e)
00462 {
00463     if(m_renderer)
00464         m_tool_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
00465 }
00466 
00467 void GLViewer::SetViewerBackground(wxColour col)
00468 {
00469     this->m_background_color = col;
00470     if(m_renderer)
00471         m_renderer->SetPreviewBackgroundColor(col);
00472 }
00473 
00474 void GLOverview::SetMode(OverviewMode mode)
00475 {
00476     this->mode = mode;
00477     if (panosphere_m_renderer != 0 && plane_m_renderer != 0) {
00478         switch(mode) {
00479             case PANOSPHERE:
00480                 m_visualization_state = panosphere_m_visualization_state;
00481                 m_tool_helper = panosphere_m_tool_helper;
00482                 m_renderer = panosphere_m_renderer;
00483                 break;
00484             case PLANE:
00485                 m_visualization_state = plane_m_visualization_state;
00486                 m_tool_helper = plane_m_tool_helper;
00487                 m_renderer = plane_m_renderer;
00488                 break;
00489         }
00490         this->Refresh();
00491     }
00492 }
00493 
00494 

Generated on 27 May 2016 for Hugintrunk by  doxygen 1.4.7