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

Generated on 10 Dec 2016 for Hugintrunk by  doxygen 1.4.7