00001
00023 #ifdef __APPLE__
00024 #include "panoinc_WX.h"
00025 #endif
00026
00027 #include "hugin_utils/utils.h"
00028
00029 #include "panoinc.h"
00030 #include <config.h>
00031 #if !defined Hugin_shared || !defined _WINDOWS
00032 #define GLEW_STATIC
00033 #endif
00034 #include <GL/glew.h>
00035 #include <base_wx/platform.h>
00036 #include <wx/settings.h>
00037 #include <wx/dcclient.h>
00038 #include <wx/event.h>
00039
00040 #include "GLViewer.h"
00041 #include "GLRenderer.h"
00042 #include "TextureManager.h"
00043 #include "MeshManager.h"
00044 #include "ToolHelper.h"
00045 #include "GLPreviewFrame.h"
00046 #include "hugin/huginApp.h"
00047
00048 #if wxCHECK_VERSION(2,9,0)
00049 #include "wx/textwrapper.h"
00050 #else
00051
00052
00053 class wxTextWrapper
00054 {
00055 public:
00056 wxTextWrapper() { m_eol = false; }
00057
00058
00059
00060 void Wrap(wxWindow *win, const wxString& text, int widthMax)
00061 {
00062 const wxChar *lastSpace = NULL;
00063 wxString line;
00064
00065 const wxChar *lineStart = text.c_str();
00066 for ( const wxChar *p = lineStart; ; p++ )
00067 {
00068 if ( IsStartOfNewLine() )
00069 {
00070 OnNewLine();
00071
00072 lastSpace = NULL;
00073 line.clear();
00074 lineStart = p;
00075 }
00076
00077 if ( *p == _T('\n') || *p == _T('\0') )
00078 {
00079 DoOutputLine(line);
00080
00081 if ( *p == _T('\0') )
00082 break;
00083 }
00084 else
00085 {
00086 if ( *p == _T(' ') )
00087 lastSpace = p;
00088
00089 line += *p;
00090
00091 if ( widthMax >= 0 && lastSpace )
00092 {
00093 int width;
00094 win->GetTextExtent(line, &width, NULL);
00095
00096 if ( width > widthMax )
00097 {
00098
00099 line.erase(lastSpace - lineStart, p + 1 - lineStart);
00100 DoOutputLine(line);
00101
00102
00103
00104 p = lastSpace;
00105 }
00106 }
00107
00108 }
00109 }
00110 }
00111
00112
00113 virtual ~wxTextWrapper() { }
00114
00115 protected:
00116
00117 virtual void OnOutputLine(const wxString& line) = 0;
00118
00119
00120 virtual void OnNewLine() { }
00121
00122 private:
00123
00124 void DoOutputLine(const wxString& line)
00125 {
00126 OnOutputLine(line);
00127
00128 m_eol = true;
00129 }
00130
00131
00132
00133
00134 bool IsStartOfNewLine()
00135 {
00136 if ( !m_eol )
00137 return false;
00138
00139 m_eol = false;
00140
00141 return true;
00142 }
00143
00144
00145 bool m_eol;
00146 };
00147 #endif
00148
00149
00150 wxString WrapText(wxWindow *win, const wxString& text, int widthMax)
00151 {
00152 class HardBreakWrapper : public wxTextWrapper
00153 {
00154 public:
00155 HardBreakWrapper(wxWindow *win, const wxString& text, int widthMax)
00156 {
00157 Wrap(win, text, widthMax);
00158 }
00159
00160 wxString const& GetWrapped() const { return m_wrapped; }
00161
00162 protected:
00163 virtual void OnOutputLine(const wxString& line)
00164 {
00165 m_wrapped += line;
00166 }
00167
00168 virtual void OnNewLine()
00169 {
00170 m_wrapped += '\n';
00171 }
00172
00173 private:
00174 wxString m_wrapped;
00175 };
00176
00177 HardBreakWrapper wrapper(win, text, widthMax);
00178 return wrapper.GetWrapped();
00179 }
00180
00181 bool GLViewer::initialised_glew=false;
00182 ViewState * GLViewer::m_view_state = NULL;
00183
00184 BEGIN_EVENT_TABLE(GLViewer, wxGLCanvas)
00185 EVT_PAINT (GLViewer::RedrawE)
00186 EVT_SIZE (GLViewer::Resized)
00187 EVT_ERASE_BACKGROUND(GLViewer::OnEraseBackground)
00188
00189 EVT_MOTION (GLViewer::MouseMotion)
00190
00191 EVT_LEAVE_WINDOW(GLViewer::MouseLeave)
00192
00193 EVT_MOUSEWHEEL(GLViewer::MouseWheel)
00194 EVT_MOUSE_EVENTS(GLViewer::MouseButtons)
00195
00196 EVT_KEY_DOWN(GLViewer::KeyDown)
00197 EVT_KEY_UP(GLViewer::KeyUp)
00198 END_EVENT_TABLE()
00199
00200
00201 GLViewer::GLViewer(
00202 wxWindow* parent,
00203 PT::Panorama &pano,
00204 int args[],
00205 GLPreviewFrame *frame_in,
00206 wxGLContext * shared_context
00207 ) :
00208 #if defined __WXGTK__ || wxCHECK_VERSION(2,9,0)
00209 wxGLCanvas(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
00210 0, wxT("GLPreviewCanvas"), args, wxNullPalette)
00211 #else
00212 wxGLCanvas(parent,shared_context,wxID_ANY,wxDefaultPosition,
00213 wxDefaultSize,0,wxT("GLPreviewCanvas"),args,wxNullPalette)
00214 #endif
00215 {
00216
00217
00218
00219
00220 #if defined __WXGTK__ || wxCHECK_VERSION(2,9,0)
00221 m_glContext = new wxGLContext(this, shared_context);
00222 #endif
00223
00224 m_renderer = 0;
00225 m_visualization_state = 0;
00226
00227 m_pano = &pano;
00228 m_overlay=false;
00229
00230 frame = frame_in;
00231
00232 m_background_color = frame->GetPreviewBackgroundColor();
00233
00234 started_creation = false;
00235 redrawing = false;
00236
00237 active = true;
00238 }
00239
00240 GLViewer::~GLViewer()
00241 {
00242 #if defined __WXGTK__ || wxCHECK_VERSION(2,9,0)
00243 delete m_glContext;
00244 #endif
00245 if (m_renderer)
00246 {
00247 delete m_tool_helper;
00248 delete m_renderer;
00249
00250
00251 if(m_view_state)
00252 {
00253 delete m_view_state;
00254 m_view_state=NULL;
00255 }
00256 }
00257 }
00258
00259 void GLViewer::SetUpContext()
00260 {
00261
00262 DEBUG_INFO("Setting rendering context...");
00263 Show();
00264 #if defined __WXGTK__ || wxCHECK_VERSION(2,9,0)
00265 m_glContext->SetCurrent(*this);
00266 #else
00267 SetCurrent();
00268 #endif
00269 DEBUG_INFO("...got a rendering context.");
00270 if (!started_creation)
00271 {
00272
00273 started_creation = true;
00274
00275 if (!initialised_glew)
00276 {
00277
00278 GLenum error_state = glewInit();
00279 initialised_glew = true;
00280 if (error_state != GLEW_OK)
00281 {
00282
00283 started_creation=false;
00284 DEBUG_ERROR("Error initialising GLEW: "
00285 << glewGetErrorString(error_state) << ".");
00286 frame->Close();
00287 wxMessageBox(_("Error initializing GLEW\nFast preview window can not be opened."),_("Error"), wxOK | wxICON_ERROR,wxTheApp->GetTopWindow());
00288 return;
00289 }
00290 }
00291
00292 if (!(GLEW_VERSION_1_1 && GLEW_ARB_multitexture))
00293 {
00294 started_creation=false;
00295 wxConfigBase::Get()->Write(wxT("DisableOpenGL"), 1l);
00296 wxConfigBase::Get()->Flush();
00297 DEBUG_ERROR("Sorry, OpenGL 1.1 + GL_ARB_multitexture extension required.");
00298 frame->Close();
00299 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,wxTheApp->GetTopWindow());
00300 return;
00301 }
00302
00303 setUp();
00304 }
00305 }
00306
00307 void GLPreview::setUp()
00308 {
00309 DEBUG_DEBUG("Preview Setup");
00310
00311 if (!m_view_state) {
00312 GLint countMultiTexture;
00313 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&countMultiTexture);
00314 m_view_state = new ViewState(m_pano, countMultiTexture>1);
00315 }
00316 m_visualization_state = new VisualizationState(m_pano, m_view_state, this, RefreshWrapper, this, (PreviewMeshManager*) NULL);
00317
00318 PreviewToolHelper *helper = new PreviewToolHelper(m_pano, m_visualization_state, frame);
00319 m_tool_helper = (ToolHelper*) helper;
00320 frame->MakePreviewTools(helper);
00321
00322 m_renderer = new GLPreviewRenderer(m_pano, m_view_state->GetTextureManager(),
00323 m_visualization_state->GetMeshManager(),
00324 m_visualization_state, helper, m_background_color);
00325 }
00326
00327 void GLOverview::setUp()
00328 {
00329 DEBUG_DEBUG("Overview Setup");
00330
00331 if (!m_view_state) {
00332 GLint countMultiTexture;
00333 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,&countMultiTexture);
00334 m_view_state = new ViewState(m_pano, countMultiTexture>1);
00335 }
00336
00337 panosphere_m_visualization_state = new PanosphereOverviewVisualizationState(m_pano, m_view_state, this, RefreshWrapper, this);
00338 plane_m_visualization_state = new PlaneOverviewVisualizationState(m_pano, m_view_state, this, RefreshWrapper, this);
00339
00340 m_visualization_state = panosphere_m_visualization_state;
00341
00342
00343 panosphere_m_tool_helper = new PanosphereOverviewToolHelper(m_pano, panosphere_m_visualization_state, frame);
00344 frame->MakePanosphereOverviewTools(panosphere_m_tool_helper);
00345
00346 plane_m_tool_helper = new PlaneOverviewToolHelper(m_pano, plane_m_visualization_state, frame);
00347 frame->MakePlaneOverviewTools(plane_m_tool_helper);
00348
00349
00350 panosphere_m_renderer = new GLPanosphereOverviewRenderer(m_pano, m_view_state->GetTextureManager(),
00351 panosphere_m_visualization_state->GetMeshManager(),
00352 panosphere_m_visualization_state, panosphere_m_tool_helper, m_background_color);
00353 plane_m_renderer = new GLPlaneOverviewRenderer(m_pano, m_view_state->GetTextureManager(),
00354 plane_m_visualization_state->GetMeshManager(),
00355 plane_m_visualization_state, plane_m_tool_helper, m_background_color);
00356
00357 switch(mode) {
00358 case PANOSPHERE:
00359 m_visualization_state = panosphere_m_visualization_state;
00360 m_tool_helper = panosphere_m_tool_helper;
00361 m_renderer = panosphere_m_renderer;
00362 break;
00363 case PLANE:
00364 m_visualization_state = plane_m_visualization_state;
00365 m_tool_helper = plane_m_tool_helper;
00366 m_renderer = plane_m_renderer;
00367 break;
00368 }
00369 }
00370
00371 void GLViewer::SetPhotometricCorrect(bool state)
00372 {
00373 m_view_state->GetTextureManager()->SetPhotometricCorrect(state);
00374 Refresh();
00375 }
00376
00377 void GLViewer::SetLayoutMode(bool state)
00378 {
00379 m_visualization_state->GetMeshManager()->SetLayoutMode(state);
00380 Refresh();
00381 }
00382
00383 void GLViewer::SetLayoutScale(double scale)
00384 {
00385 m_visualization_state->GetMeshManager()->SetLayoutScale(scale);
00386 Refresh();
00387 }
00388
00389 void GLOverview::SetLayoutMode(bool state)
00390 {
00391 panosphere_m_visualization_state->GetMeshManager()->SetLayoutMode(state);
00392 plane_m_visualization_state->GetMeshManager()->SetLayoutMode(state);
00393 Refresh();
00394 }
00395
00396 void GLOverview::SetLayoutScale(double scale)
00397 {
00398 panosphere_m_visualization_state->GetMeshManager()->SetLayoutScale(scale*MeshManager::PanosphereOverviewMeshInfo::scale_diff);
00399 plane_m_visualization_state->GetMeshManager()->SetLayoutScale(scale);
00400 Refresh();
00401 }
00402
00403
00404 void GLViewer::RedrawE(wxPaintEvent& e)
00405 {
00406 if (!IsActive()) {
00407 return;
00408 }
00409
00410
00411 DEBUG_DEBUG("REDRAW_E");
00412 if(!IsShown()) return;
00413
00414 if (!(frame->CanResize())) {
00415 DEBUG_DEBUG("RESIZE IN REDRAW");
00416 frame->ContinueResize();
00417 return;
00418 }
00419
00420 if (!redrawing)
00421 {
00422 DEBUG_DEBUG("REDRAW_E IN");
00423 redrawing = true;
00424 SetUpContext();
00425 wxPaintDC dc(this);
00426 Redraw();
00427 redrawing = false;
00428 }
00429 DEBUG_DEBUG("END OF REDRAW_E");
00430 }
00431
00432 void GLViewer::RefreshWrapper(void * obj)
00433 {
00434 DEBUG_DEBUG("REFRESH WRAPPER");
00435 GLViewer* self = (GLViewer*) obj;
00436 self->Refresh();
00437 }
00438
00439 void GLViewer::Resized(wxSizeEvent& e)
00440 {
00441
00442 if (!IsActive()) {
00443 return;
00444 }
00445
00446 DEBUG_DEBUG("RESIZED_OUT");
00447
00448 if (frame->CanResize()) {
00449 DEBUG_DEBUG("RESIZED_IN");
00450 wxGLCanvas::OnSize(e);
00451 if(!IsShown()) return;
00452
00453 DEBUG_DEBUG("RESIZED_IN_SHOWN");
00454 if (m_renderer)
00455 {
00456 int w, h;
00457 DEBUG_DEBUG("RESIZED_IN_RENDERER");
00458 GetClientSize(&w, &h);
00459 SetUpContext();
00460 offset = m_renderer->Resize(w, h);
00461 Redraw();
00462 };
00463 }
00464 }
00465
00466 void GLViewer::Redraw()
00467 {
00468
00469 if(!m_renderer) return;
00470 DEBUG_INFO("Rendering.");
00471
00472
00473
00474 wxColour col = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
00475 m_renderer->SetBackground(col.Red(), col.Green(), col.Blue());
00476 if (m_visualization_state->RequireRecalculateViewport())
00477 {
00478
00479 int w, h;
00480 GetClientSize(&w, &h);
00481 offset = m_renderer->Resize(w, h);
00482 }
00483 m_visualization_state->DoUpdates();
00484 m_renderer->Redraw();
00485 glFlush();
00486 SwapBuffers();
00487
00488 m_visualization_state->FinishedDraw();
00489
00490 if(m_overlay && !m_overlayText.IsEmpty())
00491 {
00492 int w, h;
00493 GetClientSize(&w, &h);
00494 wxClientDC dc(this);
00495 PrepareDC(dc);
00496 dc.SetBackgroundMode(wxSOLID);
00497 dc.DrawLabel(WrapText(this,m_overlayText,w/4),wxRect(0,0,w,h),wxALIGN_RIGHT|wxALIGN_TOP);
00498 };
00499 DEBUG_INFO("Finished Rendering.");
00500 }
00501
00502 void GLViewer::OnEraseBackground(wxEraseEvent& e)
00503 {
00504
00505 }
00506
00507 void GLViewer::MouseMotion(wxMouseEvent& e)
00508 {
00509 if(m_renderer)
00510 m_tool_helper->MouseMoved((int) e.m_x - offset.x,
00511 (int) e.m_y - offset.y, e);
00512 }
00513
00514 void GLViewer::MouseLeave(wxMouseEvent & e)
00515 {
00516 if(m_renderer)
00517 m_tool_helper->MouseLeave();
00518 }
00519
00520 void GLViewer::MouseButtons(wxMouseEvent& e)
00521 {
00522 if(m_renderer) {
00523
00524 if (e.IsButton()) {
00525 m_tool_helper->MouseButtonEvent(e);
00526 }
00527 }
00528 #ifdef __WXMSW__
00529
00530
00531 e.Skip();
00532 #endif
00533 }
00534
00535 void GLViewer::MouseWheel(wxMouseEvent& e)
00536 {
00537 if(m_renderer) {
00538 m_tool_helper->MouseWheelEvent(e);
00539 }
00540 }
00541
00542
00543 void GLViewer::KeyDown(wxKeyEvent& e)
00544 {
00545 if(m_renderer)
00546 m_tool_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
00547 }
00548
00549 void GLViewer::KeyUp(wxKeyEvent& e)
00550 {
00551 if(m_renderer)
00552 m_tool_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
00553 }
00554
00555 void GLViewer::SetViewerBackground(wxColour col)
00556 {
00557 this->m_background_color = col;
00558 if(m_renderer)
00559 m_renderer->SetPreviewBackgroundColor(col);
00560 }
00561
00562 void GLOverview::SetMode(OverviewMode mode)
00563 {
00564 this->mode = mode;
00565 if (panosphere_m_renderer != 0 && plane_m_renderer != 0) {
00566 switch(mode) {
00567 case PANOSPHERE:
00568 m_visualization_state = panosphere_m_visualization_state;
00569 m_tool_helper = panosphere_m_tool_helper;
00570 m_renderer = panosphere_m_renderer;
00571 break;
00572 case PLANE:
00573 m_visualization_state = plane_m_visualization_state;
00574 m_tool_helper = plane_m_tool_helper;
00575 m_renderer = plane_m_renderer;
00576 break;
00577 }
00578 this->Refresh();
00579 }
00580 }
00581
00582 void GLViewer::SetOverlayText(const wxString text)
00583 {
00584 m_overlayText=text;
00585 };
00586
00587 void GLViewer::SetOverlayVisibility(const bool isVisible)
00588 {
00589 m_overlay=isVisible;
00590 };
00591