Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GLViewer.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
23 #include "panoinc_WX.h"
24 #include "base_wx/wxutils.h"
25 
26 #include "panoinc.h"
27 #include "hugin_config.h"
28 #if defined HAVE_EPOXY && HAVE_EPOXY
29 #include <epoxy/gl.h>
30 #ifdef __WXMSW__
31 #include <epoxy/wgl.h>
32 #endif
33 #else
34 #include <GL/glew.h>
35 #endif
36 #include <base_wx/platform.h>
37 #include <wx/settings.h>
38 #include <wx/dcclient.h>
39 #include <wx/event.h>
40 
41 #include "GLViewer.h"
42 #include "GLRenderer.h"
43 #include "TextureManager.h"
44 #include "MeshManager.h"
45 #include "ToolHelper.h"
46 #include "GLPreviewFrame.h"
47 #include "hugin/huginApp.h"
48 
49 #if !defined HAVE_EPOXY || !HAVE_EPOXY
51 #endif
54 
55 BEGIN_EVENT_TABLE(GLViewer, wxGLCanvas)
56  EVT_PAINT (GLViewer::RedrawE)
57  EVT_SIZE (GLViewer::Resized)
58  EVT_ERASE_BACKGROUND(GLViewer::OnEraseBackground)
59  // mouse motion
60  EVT_MOTION (GLViewer::MouseMotion)
61  // mouse entered or left the preview
62  EVT_ENTER_WINDOW(GLViewer::MouseEnter)
63  EVT_LEAVE_WINDOW(GLViewer::MouseLeave)
64  // mouse buttons
65  EVT_MOUSEWHEEL(GLViewer::MouseWheel)
66  EVT_MOUSE_EVENTS(GLViewer::MouseButtons)
67  // keyboard events
68  EVT_KEY_DOWN(GLViewer::KeyDown)
69  EVT_KEY_UP(GLViewer::KeyUp)
71 
72 
74  wxWindow* parent,
75  HuginBase::Panorama &pano,
76  int args[],
77  GLPreviewFrame *frame_in,
78  wxGLContext * shared_context
79  ) :
80  wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize,
81  0, wxT("GLPreviewCanvas"), wxNullPalette)
82 {
83  /* create OpenGL context... */
84  m_glContext = new wxGLContext(this, shared_context);
85 
86  m_renderer = 0;
87  m_visualization_state = 0;
88 
89  m_pano = &pano;
90 
91  frame = frame_in;
92 
93  m_background_color = frame->GetPreviewBackgroundColor();
94 
95  started_creation = false;
96  redrawing = false;
97  m_toolsInitialized = false;
98 
99  active = true;
100 }
101 
103 {
104  if (m_renderer)
105  {
106  delete m_tool_helper;
107  delete m_renderer;
108  delete m_visualization_state;
109  // because m_view_state is a static member variable we need to check
110  // if other class has already deleted it
112  if (m_view_state_observer == 0)
113  {
114  delete m_view_state;
115  m_view_state=NULL;
116  }
117  }
118  delete m_glContext;
119 }
120 
122 {
123  // set the context
124  DEBUG_INFO("Setting rendering context...");
125  Show();
126  m_glContext->SetCurrent(*this);
127  DEBUG_INFO("...got a rendering context.");
128  if (!started_creation)
129  {
130  // It appears we are setting up for the first time.
131  started_creation = true;
132 
133 #if defined HAVE_EPOXY && HAVE_EPOXY
134  // check the openGL capabilities.
135  if (!(epoxy_gl_version() > 11 && epoxy_has_gl_extension("GL_ARB_multitexture")))
136  {
137  started_creation = false;
138  wxConfigBase::Get()->Write(wxT("DisableOpenGL"), 1l);
139  wxConfigBase::Get()->Flush();
140  DEBUG_ERROR("Sorry, OpenGL 1.1 + GL_ARB_multitexture extension required.");
141  frame->Close();
142  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);
143  return;
144  }
145 #else
146  if (!initialised_glew)
147  {
148  // initialise the glew library, if not done it before.
149  GLenum error_state = glewInit();
150  initialised_glew = true;
151  if (error_state != GLEW_OK)
152  {
153  // glewInit failed
154  started_creation=false;
155  DEBUG_ERROR("Error initialising GLEW: "
156  << glewGetErrorString(error_state) << ".");
157  frame->Close();
158  wxMessageBox(_("Error initializing GLEW\nFast preview window can not be opened."),_("Error"), wxOK | wxICON_ERROR);
159  return;
160  }
161  }
162  // check the openGL capabilities.
163  if (!(GLEW_VERSION_1_1 && GLEW_ARB_multitexture))
164  {
165  started_creation=false;
166  wxConfigBase::Get()->Write(wxT("DisableOpenGL"), 1l);
167  wxConfigBase::Get()->Flush();
168  DEBUG_ERROR("Sorry, OpenGL 1.1 + GL_ARB_multitexture extension required.");
169  frame->Close();
170  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);
171  return;
172  }
173 #endif
174 
175  setUp();
176 #ifdef __WXGTK__
177  if(this==frame->getPreview())
178  {
179  frame->getOverview()->setUp();
180  }
181  else
182  {
183  frame->getPreview()->setUp();
184  };
185 #endif
186  }
187 }
188 
190 {
191  DEBUG_DEBUG("Preview Setup");
192  if (m_toolsInitialized)
193  {
194  return;
195  };
196  m_toolsInitialized = true;
197  // we need something to store the state of the view and control updates
198  if (!m_view_state)
199  {
200  GLint countMultiTexture;
201  glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&countMultiTexture);
202  m_view_state = new ViewState(m_pano, countMultiTexture>1);
203  }
206  //Start the tools going:
208  m_tool_helper = static_cast<ToolHelper*>(helper);
209  frame->MakePreviewTools(helper);
210  // now make a renderer
214 }
215 
217 {
218  if (m_renderer)
219  {
221  {
223  delete panosphere_m_renderer;
225  }
226  else
227  {
228  delete plane_m_tool_helper;
229  delete plane_m_renderer;
231  };
232  };
233 }
234 
236 {
237  DEBUG_DEBUG("Overview Setup");
238  if (m_toolsInitialized)
239  {
240  return;
241  };
242  m_toolsInitialized = true;
243  // we need something to store the state of the view and control updates
244  if (!m_view_state)
245  {
246  GLint countMultiTexture;
247  glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&countMultiTexture);
248  m_view_state = new ViewState(m_pano, countMultiTexture>1);
249  }
251 
254 
256 
257  //Start the tools going:
260 
263 
264  // now make a renderer
271 
272  switch(mode) {
273  case PANOSPHERE_OUTSIDE:
274  case PANOSPHERE_INSIDE:
279  break;
280  case PLANE:
284  break;
285  }
286 }
287 
289 {
291  Refresh();
292 }
293 
294 void GLViewer::SetLayoutMode(bool state)
295 {
297  Refresh();
298 }
299 
300 void GLViewer::SetLayoutScale(double scale)
301 {
303  Refresh();
304 }
305 
307 {
310  Refresh();
311 }
312 
313 void GLOverview::SetLayoutScale(double scale)
314 {
317  Refresh();
318 }
319 
320 
321 void GLViewer::RedrawE(wxPaintEvent& e)
322 {
323  if (!IsActive()) {
324  return;
325  }
326 
327  //TODO: CanResize specific to a viewer?
328  DEBUG_DEBUG("REDRAW_E");
329  if(!IsShown()) return;
330  // don't redraw during a redraw.
331  if (!(frame->CanResize())) {
332  DEBUG_DEBUG("RESIZE IN REDRAW");
334  return;
335  }
336 
337  if (!redrawing)
338  {
339  DEBUG_DEBUG("REDRAW_E IN");
340  redrawing = true;
341  SetUpContext();
342  Redraw();
343  redrawing = false;
344  }
345  DEBUG_DEBUG("END OF REDRAW_E");
346 }
347 
348 void GLViewer::RefreshWrapper(void * obj)
349 {
350  DEBUG_DEBUG("REFRESH WRAPPER");
351  GLViewer* self = static_cast<GLViewer*>(obj);
352  self->Refresh();
353 }
354 
355 void GLViewer::Resized(wxSizeEvent& e)
356 {
357 
358  if (!IsActive()) {
359  return;
360  }
361 
362  DEBUG_DEBUG("RESIZED_OUT");
363 
364  if (frame->CanResize()) {
365  DEBUG_DEBUG("RESIZED_IN");
366  if(!IsShown()) return;
367  // if we have a render at this point, tell it the new size.
368  DEBUG_DEBUG("RESIZED_IN_SHOWN");
369  if (m_renderer)
370  {
371  DEBUG_DEBUG("RESIZED_IN_RENDERER");
372  wxSize clientSize = GetClientSize();
373 #if defined __WXGTK3__ || defined __WXOSX__
374  m_scale = GetContentScaleFactor();
375  clientSize *= m_scale;
376 #endif
377  SetUpContext();
378  offset = m_renderer->Resize(clientSize.GetWidth(), clientSize.GetHeight());
379  Redraw();
380  };
381  }
382 }
383 
385 {
386  // get the renderer to redraw the OpenGL stuff
387  if(!m_renderer) return;
388  // don't redraw if we are in middle of a pending change of the panorama object
389  if(m_pano->hasPendingChanges()) return;
390  DEBUG_INFO("Rendering.");
391 
392  // we should use the window background colour outside the panorama
393  // FIXME shouldn't this work on textured backrounds?
394 #if defined __WXMAC__
395  wxColour col(128,128,128);
396 #else
397  wxColour col = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
398 #endif
399  m_renderer->SetBackground(col.Red(), col.Green(), col.Blue());
401  {
402  // resize the viewport in case the panorama dimensions have changed.
403  wxSize clientSize = GetClientSize();
404 #if defined __WXGTK3__ || defined __WXOSX__
405  m_scale = GetContentScaleFactor();
406  clientSize *= m_scale;
407 #endif
408  offset = m_renderer->Resize(clientSize.GetWidth(), clientSize.GetHeight());
409  }
411  m_renderer->Redraw();
412  glFlush();
413  SwapBuffers();
414  // tell the view state we did all the updates and redrew.
416  DEBUG_INFO("Finished Rendering.");
417 }
418 
419 void GLViewer::OnEraseBackground(wxEraseEvent& e)
420 {
421  // Do nothing, to avoid flashing on MSW
422 }
423 
424 void GLViewer::MouseMotion(wxMouseEvent& e)
425 {
426  if(m_renderer)
428  hugin_utils::roundi(e.m_y * m_scale - offset.y), e);
429 }
430 
431 void GLViewer::MouseEnter(wxMouseEvent & e)
432 {
433  if(m_renderer)
435  hugin_utils::roundi(e.m_y * m_scale - offset.y), e);
436 }
437 
438 void GLViewer::MouseLeave(wxMouseEvent & e)
439 {
440  if(m_renderer)
442 }
443 
444 void GLViewer::MouseButtons(wxMouseEvent& e)
445 {
446  if(m_renderer) {
447  //disregard non button events
448  if (e.IsButton()) {
450  }
451  }
452 #ifdef __WXMSW__
453  //use normal mouse button processing of GLCanvas
454  //otherwise the mouse wheel is not working
455  e.Skip();
456 #endif
457 }
458 
459 void GLViewer::MouseWheel(wxMouseEvent& e)
460 {
461  if(m_renderer) {
463  }
464 }
465 
466 
467 void GLViewer::KeyDown(wxKeyEvent& e)
468 {
469  if(m_renderer)
470  m_tool_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
471 }
472 
473 void GLViewer::KeyUp(wxKeyEvent& e)
474 {
475  if(m_renderer)
476  m_tool_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
477 }
478 
480 {
482 }
483 
485 {
486  this->m_background_color = col;
487  if(m_renderer)
489 }
490 
492 {
493  this->mode = mode;
494  if (panosphere_m_renderer != 0 && plane_m_renderer != 0) {
495  switch(mode) {
496  case PANOSPHERE_OUTSIDE:
497  case PANOSPHERE_INSIDE:
502  break;
503  case PLANE:
507  break;
508  }
509  this->Refresh();
510  }
511 }
512 
513 
#define DEBUG_INFO(msg)
Definition: utils.h:69
static size_t m_view_state_observer
Definition: GLViewer.h:73
void MouseButtons(wxMouseEvent &e)
Definition: GLViewer.cpp:444
implementation of huginApp Class
void MouseWheelEvent(wxMouseEvent &e)
Definition: ToolHelper.cpp:156
void MouseLeave(wxMouseEvent &e)
Definition: GLViewer.cpp:438
The OpenGL preview frame.
void setUp()
Definition: GLViewer.cpp:235
void KeyDown(wxKeyEvent &e)
Definition: GLViewer.cpp:467
int roundi(T x)
Definition: hugin_math.h:73
GLPreviewFrame * frame
Definition: GLViewer.h:105
PanosphereOverviewVisualizationState * panosphere_m_visualization_state
Definition: GLViewer.h:159
virtual void SetLayoutScale(double scale)
Definition: GLViewer.cpp:300
virtual vigra::Diff2D Resize(int width, int height)=0
Resize the viewport because the window&#39;s dimensions have changed.
void SetPhotometricCorrect(bool state)
Definition: GLViewer.cpp:288
PlaneOverviewToolHelper * plane_m_tool_helper
Definition: GLViewer.h:164
subclass for the preview canvas
Definition: GLRenderer.h:84
void setInsideView(bool insideView)
Definition: ViewState.cpp:586
void Resized(wxSizeEvent &e)
Definition: GLViewer.cpp:355
void MarkToolsDirty()
Definition: GLViewer.cpp:479
void setUp()
Definition: GLViewer.cpp:189
HuginBase::Panorama * m_pano
Definition: GLViewer.h:97
void SetLayoutScale(double scale)
void MouseMotion(wxMouseEvent &e)
Definition: GLViewer.cpp:424
END_EVENT_TABLE()
include file for the hugin project
bool redrawing
Definition: GLViewer.h:101
wxGLContext * m_glContext
Definition: GLViewer.h:96
void KeyUp(wxKeyEvent &e)
Definition: GLViewer.cpp:473
static void RefreshWrapper(void *obj)
Definition: GLViewer.cpp:348
virtual void Redraw()=0
GLPlaneOverviewRenderer * plane_m_renderer
Definition: GLViewer.h:165
static bool initialised_glew
Definition: GLViewer.h:102
virtual void setUp()=0
void OnEraseBackground(wxEraseEvent &e)
Definition: GLViewer.cpp:419
void SetPhotometricCorrect(bool state)
void SetMode(OverviewMode mode)
Definition: GLViewer.cpp:491
void MouseEnter(int x, int y, wxMouseEvent &e)
Definition: ToolHelper.cpp:248
PlaneOverviewVisualizationState * plane_m_visualization_state
Definition: GLViewer.h:163
void MakePreviewTools(PreviewToolHelper *helper)
MeshManager * GetMeshManager()
Definition: ViewState.h:207
subclass for the plane overview mode
Definition: GLRenderer.h:118
void MouseEnter(wxMouseEvent &e)
Definition: GLViewer.cpp:431
bool started_creation
Definition: GLViewer.h:101
EVT_ERASE_BACKGROUND(wxTreeListHeaderWindow::OnEraseBackground) void wxTreeListHeaderWindow
TextureManager * GetTextureManager()
Definition: ViewState.h:104
void MouseButtonEvent(wxMouseEvent &e)
Definition: ToolHelper.cpp:148
const bool hasPendingChanges() const
return if the panorama class has pending changes normally all controls listen to panoramaChanges noti...
Definition: Panorama.cpp:1563
virtual void SetLayoutMode(bool state)
Definition: GLViewer.cpp:294
void MakePanosphereOverviewTools(PanosphereOverviewToolHelper *helper)
bool IsActive()
Definition: GLViewer.h:76
VisualizationState * m_visualization_state
Definition: GLViewer.h:71
#define DEBUG_ERROR(msg)
Definition: utils.h:76
void KeypressEvent(int keycode, int modifiers, bool pressed)
Definition: ToolHelper.cpp:165
bool RequireRecalculateViewport()
Definition: ViewState.cpp:415
void MakePlaneOverviewTools(PlaneOverviewToolHelper *helper)
PanosphereOverviewToolHelper * panosphere_m_tool_helper
Definition: GLViewer.h:160
subclass for the panosphere overview mode
Definition: GLRenderer.h:101
virtual void SetLayoutScale(double scale)
Definition: GLViewer.cpp:313
GLRenderer * m_renderer
Definition: GLViewer.h:95
virtual ~GLViewer()
Definition: GLViewer.cpp:102
double m_scale
Definition: GLViewer.h:104
include file for the hugin project
virtual void SetLayoutMode(bool state)
Definition: GLViewer.cpp:306
void SetBackground(unsigned char red, unsigned char green, unsigned char blue)
Definition: GLRenderer.cpp:60
void Redraw()
Definition: GLViewer.cpp:384
bool m_toolsInitialized
Definition: GLViewer.h:101
static const double scale_diff
scale factor to be used for the layout mode TODO: test this for more scenarios
Definition: MeshManager.h:178
GLOverview * getOverview()
void MouseLeave()
Definition: ToolHelper.cpp:263
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
virtual void MouseMoved(int x, int y, wxMouseEvent &e)
Definition: ToolHelper.cpp:75
void SetViewerBackground(wxColour col)
Definition: GLViewer.cpp:484
GLPanosphereOverviewRenderer * panosphere_m_renderer
Definition: GLViewer.h:161
void SetPreviewBackgroundColor(const wxColour c)
sets the preview background color
Definition: GLRenderer.cpp:55
ToolHelper * m_tool_helper
Definition: GLViewer.h:94
void SetLayoutMode(bool state)
Turn layout mode on or off.
GLPreview * getPreview()
static ViewState * m_view_state
Definition: GLViewer.h:72
void RedrawE(wxPaintEvent &e)
Definition: GLViewer.cpp:321
void SetUpContext()
Definition: GLViewer.cpp:121
wxColour m_background_color
Definition: GLViewer.h:109
void MouseWheel(wxMouseEvent &e)
Definition: GLViewer.cpp:459
A wxWidget to display the fast preview.
Definition: GLViewer.h:51
OverviewMode mode
Definition: GLViewer.h:157
vigra::Diff2D offset
Definition: GLViewer.h:103
void MarkDirty()
Definition: ToolHelper.cpp:203