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

Generated on 8 Feb 2016 for Hugintrunk by  doxygen 1.4.7