From: <jl...@us...> - 2008-06-22 14:14:32
|
Revision: 3139 http://hugin.svn.sourceforge.net/hugin/?rev=3139&view=rev Author: jlegg Date: 2008-06-22 07:14:23 -0700 (Sun, 22 Jun 2008) Log Message: ----------- Fixed some bugs in the mesh remapper, adaptive subdivision based on screen-space edge lengths, automatic update when needed, and while dragging sliders in the preview window (there is abug in this, undo history broken), and frame the preview properly. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MainFrame.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/preview_frame.xrc hugin/branches/gsoc2008_opengl_preview/src/hugin_base/algorithms/MeshRemapper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin_base/algorithms/MeshRemapper.h Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-06-22 14:14:23 UTC (rev 3139) @@ -66,22 +66,20 @@ ID_EXPOSURE_TEXT, ID_EXPOSURE_SPIN, ID_EXPOSURE_DEFAULT, - ID_TOGGLE_BUT = wxID_HIGHEST+101, - PROJ_PARAM_NAMES_ID = wxID_HIGHEST+1001, - PROJ_PARAM_VAL_ID = wxID_HIGHEST+1101, - PROJ_PARAM_SLIDER_ID = wxID_HIGHEST+1201 + ID_TOGGLE_BUT = wxID_HIGHEST+500, + PROJ_PARAM_NAMES_ID = wxID_HIGHEST+1300, + PROJ_PARAM_VAL_ID = wxID_HIGHEST+1400, + PROJ_PARAM_SLIDER_ID = wxID_HIGHEST+1500 }; BEGIN_EVENT_TABLE(GLPreviewFrame, wxFrame) EVT_CLOSE(GLPreviewFrame::OnClose) -// EVT_CHECKBOX(-1, PreviewFrame::OnAutoPreviewToggle) EVT_TOOL(XRCID("preview_center_tool"), GLPreviewFrame::OnCenterHorizontally) EVT_TOOL(XRCID("preview_fit_pano_tool"), GLPreviewFrame::OnFitPano) EVT_TOOL(XRCID("preview_straighten_pano_tool"), GLPreviewFrame::OnStraighten) - EVT_TOOL(XRCID("preview_auto_update_tool"), GLPreviewFrame::OnAutoPreviewToggle) - EVT_TOOL(XRCID("preview_update_tool"), GLPreviewFrame::OnUpdate) EVT_TOOL(XRCID("preview_show_all_tool"), GLPreviewFrame::OnShowAll) EVT_TOOL(XRCID("preview_show_none_tool"), GLPreviewFrame::OnShowNone) + EVT_TOOL(XRCID("preview_photometric_tool"), GLPreviewFrame::OnPhotometric) EVT_TOOL(XRCID("preview_num_transform"), GLPreviewFrame::OnNumTransform) EVT_TEXT_ENTER( -1 , GLPreviewFrame::OnTextCtrlChanged) @@ -97,9 +95,9 @@ EVT_CHECKBOX(-1, GLPreviewFrame::OnChangeDisplayedImgs) #endif EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV) -// EVT_SCROLL_THUMBRELEASE(PreviewFrame::OnChangeFOV) -// EVT_SCROLL_ENDSCROLL(PreviewFrame::OnChangeFOV) -// EVT_SCROLL_THUMBTRACK(PreviewFrame::OnChangeFOV) +// EVT_SCROLL_THUMBRELEASE(GLPreviewFrame::OnChangeFOV) +// EVT_SCROLL_ENDSCROLL(GLPreviewFrame::OnChangeFOV) + EVT_SCROLL_THUMBTRACK(GLPreviewFrame::OnTrackChangeFOV) END_EVENT_TABLE() #define PF_STYLE (wxMAXIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN) @@ -112,7 +110,7 @@ DEBUG_TRACE(""); m_oldProjFormat = -1; - m_ToolBar = wxXmlResource::Get()->LoadToolBar(this, wxT("preview_toolbar")); + m_ToolBar = wxXmlResource::Get()->LoadToolBar(this, wxT("fast_preview_toolbar")); DEBUG_ASSERT(m_ToolBar); // create tool bar SetToolBar(m_ToolBar); @@ -140,7 +138,7 @@ flexSizer->AddGrowableCol(0); flexSizer->AddGrowableRow(0); - // create our preview panel + // create our Viewer int args[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0}; m_GLViewer = new GLViewer(this, pano, args); @@ -369,11 +367,6 @@ // TODO tell renderer // m_PreviewPanel->SetBlendMode((PreviewPanel::BlendMode)oldMode ); - long aup = config->Read(wxT("/PreviewFrame/autoUpdate"),0l); - // m_PreviewPanel->SetAutoUpdate(aup != 0); - - m_ToolBar->ToggleTool(XRCID("preview_auto_update_tool"), aup !=0); - #ifdef __WXMSW__ // wxFrame does have a strange background color on Windows.. this->SetBackgroundColour(m_PreviewPanel->GetBackgroundColour()); @@ -399,8 +392,6 @@ config->Write(wxT("/PreviewFrame/isShown"), 0l); } - bool checked = m_ToolBar->GetToolState(XRCID("preview_auto_update_tool")); - config->Write(wxT("/PreviewFrame/autoUpdate"), checked ? 1l: 0l); config->Write(wxT("/PreviewFrame/blendMode"), m_BlendModeChoice->GetSelection()); m_pano.removeObserver(this); DEBUG_TRACE("dtor end"); @@ -456,7 +447,6 @@ bool activeImgs = pano.getActiveImages().size() > 0; m_ToolBar->EnableTool(XRCID("preview_center_tool"), activeImgs); m_ToolBar->EnableTool(XRCID("preview_fit_pano_tool"), activeImgs); - m_ToolBar->EnableTool(XRCID("preview_update_tool"), activeImgs); m_ToolBar->EnableTool(XRCID("preview_num_transform"), activeImgs); m_ToolBar->EnableTool(XRCID("preview_straighten_pano_tool"), pano.getNrOfImages() > 0); @@ -598,15 +588,6 @@ } } -void GLPreviewFrame::OnAutoPreviewToggle(wxCommandEvent & e) -{ - // TODO - tell renderer, or remove auto update - // m_PreviewPanel->SetAutoUpdate(e.IsChecked()); - if (e.IsChecked()) {; - m_GLViewer->Redraw(); - } -} - #if 0 // need to add the wxChoice somewhere void PreviewFrame::OnProjectionChanged() @@ -656,18 +637,6 @@ } } -void GLPreviewFrame::OnUpdate(wxCommandEvent& event) -{ - m_GLViewer->Redraw(); -} - -void GLPreviewFrame::updatePano() -{ - if (m_ToolBar->GetToolState(XRCID("preview_auto_update_tool"))) { - m_GLViewer->Redraw(); - } -} - void GLPreviewFrame::OnFitPano(wxCommandEvent & e) { if (m_pano.getActiveImages().size() == 0) return; @@ -685,7 +654,6 @@ ); DEBUG_INFO ( "new fov: [" << opt.getHFOV() << " "<< opt.getVFOV() << "] => height: " << opt.getHeight() ); - updatePano(); } void GLPreviewFrame::OnShowAll(wxCommandEvent & e) @@ -700,7 +668,6 @@ GlobalCmdHist::getInstance().addCommand( new PT::SetActiveImagesCmd(m_pano, displayedImgs) ); - updatePano(); } void GLPreviewFrame::OnShowNone(wxCommandEvent & e) @@ -715,7 +682,6 @@ GlobalCmdHist::getInstance().addCommand( new PT::SetActiveImagesCmd(m_pano, displayedImgs) ); - updatePano(); } void GLPreviewFrame::OnNumTransform(wxCommandEvent & e) @@ -746,8 +712,6 @@ GlobalCmdHist::getInstance().addCommand( new PT::RotatePanoCmd(m_pano, y, p, r) ); - // update preview panel - updatePano(); } else { DEBUG_DEBUG("Numerical transform canceled"); } @@ -792,9 +756,6 @@ GlobalCmdHist::getInstance().addCommand( new PT::SetPanoOptionsCmd( m_pano, opts ) ); - // update preview panel - updatePano(); - } void GLPreviewFrame::OnChangeFOV(wxScrollEvent & e) @@ -825,9 +786,40 @@ GlobalCmdHist::getInstance().addCommand( new PT::SetPanoOptionsCmd( m_pano, opt ) - ); + ); } +void GLPreviewFrame::OnTrackChangeFOV(wxScrollEvent & e) +{ + DEBUG_TRACE(""); + + PanoramaOptions opt = m_pano.getOptions(); + + if (e.GetEventObject() == m_HFOVSlider) { + opt.setHFOV(e.GetInt()); + } else if (e.GetEventObject() == m_VFOVSlider) { + opt.setVFOV(e.GetInt()); + } else { +#ifdef HasPANO13 + int nParam = opt.m_projFeatures.numberOfParameters; + std::vector<double> para = opt.getProjectionParameters(); + for (int i = 0; i < nParam; i++) { + if (e.GetEventObject() == m_projParamSlider[i]) { + // update + para[i] = e.GetInt(); + } + } + opt.setProjectionParameters(para); +#endif + } + // we only actually update the panorama fully when the mouse is released. + // as we are dragging it we don't want to create undo events, but we would + // like to update the display as if the panormama change was complete. + // FIXME breaks undo /redo for FOV sliders anyway. + m_pano.setOptions(opt); + m_GLViewer->panoramaChanged(m_pano); +} + void GLPreviewFrame::OnBlendChoice(wxCommandEvent & e) { if (e.GetEventObject() == m_BlendModeChoice) { @@ -857,7 +849,6 @@ GlobalCmdHist::getInstance().addCommand( new PT::SetPanoOptionsCmd( m_pano, opt ) ); - updatePano(); } } @@ -868,7 +859,6 @@ GlobalCmdHist::getInstance().addCommand( new PT::SetPanoOptionsCmd( m_pano, opt ) ); - updatePano(); } void GLPreviewFrame::OnDecreaseExposure( wxSpinEvent & e ) @@ -878,7 +868,6 @@ GlobalCmdHist::getInstance().addCommand( new PT::SetPanoOptionsCmd( m_pano, opt ) ); - updatePano(); } void GLPreviewFrame::OnProjectionChoice( wxCommandEvent & e ) @@ -892,7 +881,6 @@ new PT::SetPanoOptionsCmd( m_pano, opt ) ); DEBUG_DEBUG ("Projection changed: " << lt); - updatePano(); } else { // FIXME DEBUG_WARN("wxChoice event from unknown object received"); @@ -909,7 +897,6 @@ GlobalCmdHist::getInstance().addCommand( new PT::SetPanoOptionsCmd( m_pano, opt ) ); - updatePano(); } else { // FIXME DEBUG_WARN("wxChoice event from unknown object received"); @@ -955,3 +942,8 @@ #endif } +void GLPreviewFrame::OnPhotometric(wxCommandEvent & e) +{ + m_GLViewer->SetPhotometricCorrect(e.IsChecked()); +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-06-22 14:14:23 UTC (rev 3139) @@ -49,21 +49,21 @@ void panoramaChanged(PT::Panorama &pano); void panoramaImagesChanged(PT::Panorama &pano, const PT::UIntSet &changed); - void OnUpdate(wxCommandEvent& event); void updateProgressDisplay(); protected: void OnClose(wxCloseEvent& e); void OnChangeDisplayedImgs(wxCommandEvent & e); - void OnAutoPreviewToggle(wxCommandEvent & e); void OnCenterHorizontally(wxCommandEvent & e); void OnFitPano(wxCommandEvent& e); void OnStraighten(wxCommandEvent & e); void OnShowAll(wxCommandEvent & e); void OnShowNone(wxCommandEvent & e); + void OnPhotometric(wxCommandEvent & e); void OnNumTransform(wxCommandEvent & e); void OnChangeFOV(wxScrollEvent & e); + void OnTrackChangeFOV(wxScrollEvent & e); void OnTextCtrlChanged(wxCommandEvent & e); void OnDefaultExposure( wxCommandEvent & e ); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.cpp 2008-06-22 14:14:23 UTC (rev 3139) @@ -27,18 +27,8 @@ #include <config.h> -// #include "panoinc_WX.h" #include "panoinc.h" -// #include <vigra/basicimageview.hxx> -// #include "vigra_ext/blend.h" -// #include "PT/Stitcher.h" - - -// #include "hugin/MainFrame.h" -// #include "hugin/CommandHistory.h" -// #include "hugin/config_defaults.h" -// #include "hugin/huginApp.h" #include "TextureManager.h" #include "MeshManager.h" #include "GLRenderer.h" @@ -49,67 +39,78 @@ m_pano = pano; m_tex_man = tex_man; m_mesh_man = mesh_man; - - glDisable(GL_CULL_FACE); - rot = 0.0; } GLRenderer::~GLRenderer() { - } -double width_o, height_o; -void GLRenderer::Resize(int in_width, int in_height) +float GLRenderer::Resize(int in_width, int in_height) { width = in_width; height = in_height; + glViewport(0, 0, width, height); const HuginBase::PanoramaOptions options = m_pano->getOptions(); - // TODO aspect correction - /*double*/ width_o = options.getWidth();//, - height_o = options.getHeight(); + width_o = options.getWidth(); + height_o = options.getHeight(); + float aspect_screen = float(width) / float (height), + aspect_pano = width_o / height_o; glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0, width_o, height_o, 0.0, -1.0, 1.0); + glLoadIdentity(); + float scale; + if (aspect_screen < aspect_pano) + { + // the panorama is wider than the screen + scale = width_o / width; + } else { + // the screen is wider than the panorama + scale = height_o / height; + } + float x_offs = (scale * float(width) - width_o) / 2.0, + y_offs = (scale * float(height) - height_o) / 2.0; + // set up the projection, so we can use panorama coordinates. + glOrtho(-x_offs, width * scale - x_offs, + height * scale - y_offs, -y_offs, + -1.0, 1.0); + // scissor to the panorama. + glScissor(x_offs / scale, y_offs / scale, + width_o / scale, height_o / scale); glMatrixMode(GL_MODELVIEW); - glViewport(0, 0, width, height); + return 1.0 / scale; } -void GLRenderer::panoramaChanged(PT::Panorama &pano) +void GLRenderer::SetBackground(unsigned char red, unsigned char green, unsigned char blue) { + glClearColor((float) red / 255.0, (float) green / 255.0, (float) blue / 255.0, 1.0); } -void GLRenderer::panoramaImagesChanged(PT::Panorama &pano, const PT::UIntSet & imgNr) -{ -} - void GLRenderer::Redraw() { + // draw the box around the panorma in black, with a white background. glClear(GL_COLOR_BUFFER_BIT); + glEnable(GL_SCISSOR_TEST); glDisable(GL_TEXTURE_2D); - glBegin(GL_LINES); - glVertex2d(0.0, 0.0); - glVertex2d(width_o, height_o); + glColor3f(0.0, 0.0, 0.0); + glBegin(GL_QUADS); + glVertex2f(0.0, 0.0); + glVertex2f(width_o, 0.0); + glVertex2f(width_o, height_o); + glVertex2f(0.0, height_o); glEnd(); + glColor3f(1.0, 1.0, 1.0); + // draw each active image. + int imgs = m_pano->getNrOfImages(); glEnable(GL_TEXTURE_2D); - int imgs = m_pano->getNrOfImages(); + m_tex_man->Begin(); for (int img = 0; img < imgs; img++) { if (m_pano->getImage(img).getOptions().active) { m_tex_man->BindTexture(img); m_mesh_man->RenderMesh(img); - /*glPushMatrix(); - float ang = float(img) / float(imgs) * M_PI * 2.0; - glTranslatef(cos(ang)*0.7, sin(ang)*0.7, 0.0); - glBegin(GL_QUADS); - glTexCoord2f(0.0, 1.0); glVertex2f(-0.3, -0.3); - glTexCoord2f(1.0, 1.0); glVertex2f(0.3, -0.3); - glTexCoord2f(1.0, 0.0); glVertex2f(0.3, 0.3); - glTexCoord2f(0.0, 0.0); glVertex2f(-0.3, 0.3); - glEnd(); - glPopMatrix(); // breaks here */ } } + m_tex_man->End(); + glDisable(GL_SCISSOR_TEST); } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h 2008-06-22 14:14:23 UTC (rev 3139) @@ -20,7 +20,9 @@ */ /* The renderer handles drawing the preview. It is used by a GLViewer, which is - * a wxWidget. + * a wxWidget. The work of generating textures to represent the image is done by + * a TextureManager, and the remappings are made in display lists by a + * MeshManager. The GLViewer gives us instances of those objects to use. */ #ifndef _GLRENDERER_H @@ -45,17 +47,19 @@ /** dtor. */ virtual ~GLRenderer(); - - void Resize(int width, int height); - void panoramaChanged(PT::Panorama &pano); - void panoramaImagesChanged(PT::Panorama &pano, const PT::UIntSet & imgNr); + // resize the viewport, because the window's dimensions have changed. + // returns the nnumber of screen pixels for a panorama pixel. + float Resize(int width, int height); + // void panoramaChanged(PT::Panorama &pano); + // void panoramaImagesChanged(PT::Panorama &pano, const PT::UIntSet & imgNr); void Redraw(); + void SetBackground(unsigned char red, unsigned char green, unsigned char blue); + float width_o, height_o; private: PT::Panorama * m_pano; TextureManager * m_tex_man; MeshManager * m_mesh_man; int width, height; - float rot; }; #endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-06-22 14:14:23 UTC (rev 3139) @@ -28,14 +28,17 @@ #include "TextureManager.h" #include "MeshManager.h" +#include <wx/settings.h> + BEGIN_EVENT_TABLE(GLViewer, wxGLCanvas) EVT_PAINT (GLViewer::RedrawE) EVT_SIZE (GLViewer::Resized) END_EVENT_TABLE() GLViewer::GLViewer(wxFrame* parent, PT::Panorama &pano, int args[]) : - wxGLCanvas(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, wxT("GLPreviewCanvas"), args, wxNullPalette) + wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize, + 0, wxT("GLPreviewCanvas"), wxNullPalette) { m_glContext = new wxGLContext(this, 0); @@ -47,6 +50,7 @@ update_images = true; update_meshes = true; + started_creation = false; } GLViewer::~GLViewer() @@ -64,11 +68,12 @@ { // set the context std::cout << "Setting rendering context:\n"; - wxGLCanvas::SetCurrent(*m_glContext); + Show(); + //SetCurrent(*m_glContext); + m_glContext->SetCurrent(*this); std::cout << "OK\n"; // a rendering context isn't much use without a renderer and texture manager // that use it... so create those if necessary as well. - static bool started_creation = false; if (!started_creation) { started_creation = true; @@ -84,10 +89,18 @@ } } +void GLViewer::SetPhotometricCorrect(bool state) +{ + m_tex_manager->SetPhotometricCorrect(state); + update_images = true; + Refresh(); +} + void GLViewer::RedrawE(wxPaintEvent& e) { if(!IsShown()) return; SetUpContext(); + wxPaintDC dc(this); Redraw(); } @@ -103,44 +116,53 @@ if (m_renderer) { SetUpContext(); - m_renderer->Resize(w, h); + scale = m_renderer->Resize(w, h); }; } void GLViewer::panoramaImagesChanged(PT::Panorama &pano, const PT::UIntSet &changed) { update_images = true; + update_meshes = true; + Refresh(); } void GLViewer::panoramaChanged(PT::Panorama &pano) { update_meshes = true; + Refresh(); } void GLViewer::Redraw() { - if(!IsShown()) return; - - wxPaintDC dc(this); // get the renderer to redraw the OpenGL stuff - SetUpContext(); if(!m_renderer) return; std::cout << "Rendering.\n"; + + wxColour col = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + m_renderer->SetBackground(col.Red(), col.Green(), col.Blue()); + if (update_images) { m_tex_manager->panoramaImagesChanged(*m_pano); update_images = false; } + if (update_meshes) { + // resize the viewport in case the panorama dimensions have changed. + int w, h; + GetClientSize(&w, &h); + scale = m_renderer->Resize(w, h); // TODO work out which images need to change unsigned int num_images = m_pano->getNrOfImages(); for (unsigned int img = 0; img < num_images; img++) { - m_mesh_manager->UpdateMesh(img); + m_mesh_manager->UpdateMesh(img, scale); } update_meshes = false; } + m_renderer->Redraw(); glFlush(); SwapBuffers(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-06-22 14:14:23 UTC (rev 3139) @@ -41,6 +41,7 @@ void panoramaChanged(PT::Panorama &pano); void panoramaImagesChanged(PT::Panorama &pano, const PT::UIntSet &changed); void SetUpContext(); + void SetPhotometricCorrect(bool state); protected: DECLARE_EVENT_TABLE() GLRenderer *m_renderer; @@ -50,6 +51,8 @@ PT::Panorama * m_pano; bool update_images; bool update_meshes; + bool started_creation; + float scale; }; #endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MainFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MainFrame.cpp 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MainFrame.cpp 2008-06-22 14:14:23 UTC (rev 3139) @@ -669,10 +669,11 @@ } // force update of GL preview window - if ( !(gl_preview_frame->IsIconized() ||(! gl_preview_frame->IsShown()) ) ) { + // TODO decide if needed - James + /*if ( !(gl_preview_frame->IsIconized() ||(! gl_preview_frame->IsShown()) ) ) { wxCommandEvent dummy; gl_preview_frame->OnUpdate(dummy); - } + } */ } #ifdef __WXMAC__ @@ -727,7 +728,8 @@ pano.clearDirty(); wxCommandEvent dummy; preview_frame->OnUpdate(dummy); - gl_preview_frame->OnUpdate(dummy); + // TODO Decide if needed - James + //gl_preview_frame->OnUpdate(dummy); } void MainFrame::OnAddImages( wxCommandEvent& event ) @@ -1126,9 +1128,9 @@ } gl_preview_frame->Show(); gl_preview_frame->Raise(); - - wxCommandEvent (dummy); - gl_preview_frame->OnUpdate(dummy); + // TODO - decide if needed - James +/* wxCommandEvent (dummy); + gl_preview_frame->OnUpdate(dummy);*/ } void MainFrame::OnShowCPFrame(wxCommandEvent & e) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.cpp 2008-06-22 14:14:23 UTC (rev 3139) @@ -40,17 +40,17 @@ meshes.clear(); } -void MeshManager::UpdateMesh(unsigned int image_number) +void MeshManager::UpdateMesh(unsigned int image_number, float scale) { // try to find if it is already here std::map<unsigned int, MeshInfo>::iterator mesh_info = meshes.find(image_number); if (mesh_info != meshes.end()) { - mesh_info->second.Update(); + mesh_info->second.Update(scale); } else { // not found, make a new one std::cout << "Making new mesh remapper for image " << image_number << ".\n"; - meshes[image_number].SetSource(m_pano, image_number); + meshes[image_number].SetSource(m_pano, image_number, scale); } } @@ -76,12 +76,13 @@ display_list_number = glGenLists(1); } -void MeshManager::MeshInfo::SetSource(PT::Panorama *m_pano_in, unsigned int image_number_in) +void MeshManager::MeshInfo::SetSource(PT::Panorama *m_pano_in, + unsigned int image_number_in, float scale) { image_number = image_number_in; m_pano = m_pano_in; remap = new MeshRemapper(m_pano, image_number); - CompileList(); + CompileList(scale); } MeshManager::MeshInfo::~MeshInfo() @@ -90,9 +91,9 @@ if (remap) delete remap; } -void MeshManager::MeshInfo::Update() +void MeshManager::MeshInfo::Update(float scale) { - CompileList(); + CompileList(scale); } void MeshManager::MeshInfo::CallList() @@ -101,20 +102,23 @@ } -void MeshManager::MeshInfo::CompileList() +void MeshManager::MeshInfo::CompileList(float scale) { // build the display list from the coordinates generated by the remapper std::cout << "Preparing to compile a display list for " << image_number << ".\n"; glNewList(display_list_number, GL_COMPILE); - remap->UpdateAndResetIndex(); + remap->UpdateAndResetIndex(scale); std::cout << "Specifying faces.\n"; glBegin(GL_QUADS); // get each face's coordinates from the remapper MeshRemapper::Coords coords; + // currently using line loops instead of quads so I can examine the + // adaptive subdivision. while (remap->GetNextFaceCoordinates(&coords)) { // go in an anticlockwise direction + //glBegin(GL_LINE_LOOP); glTexCoord2dv(coords.tex_c[0][0]); glVertex2dv(coords.vertex_c[0][0]); glTexCoord2dv(coords.tex_c[0][1]); @@ -123,10 +127,7 @@ glVertex2dv(coords.vertex_c[1][1]); glTexCoord2dv(coords.tex_c[1][0]); glVertex2dv(coords.vertex_c[1][0]); - std::cout << "(" << coords.tex_c[0][0][0] << ", " - << coords.tex_c[0][0][1] << ") |-> (" - << coords.vertex_c[0][0][0] << ", " - << coords.vertex_c[0][0][1] << ")\n"; + //glEnd(); } glEnd(); glEndList(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.h 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshManager.h 2008-06-22 14:14:23 UTC (rev 3139) @@ -23,6 +23,8 @@ * by creating OpenGL display lists that draw a remapped image. * The coordinates used in the display list are calculated by a MeshRemapper */ + + // TODO replace "float scale" with complete view information #ifndef _MESHMANAGER_H #define _MESHMANAGER_H @@ -34,7 +36,8 @@ public: MeshManager(PT::Panorama *pano); ~MeshManager(); - void UpdateMesh(unsigned int image_number); + // scale is the number of screen pixels that make a panorma pixel + void UpdateMesh(unsigned int image_number, float scale); void RenderMesh(unsigned int image_number); // remove meshes for images that have been deleted. void CleanMeshes(); @@ -43,17 +46,18 @@ class MeshInfo { public: - MeshInfo(); // we shouldn't use this, but needed for map. - void SetSource(PT::Panorama *m_pano, unsigned int image_number); + MeshInfo(); + void SetSource(PT::Panorama *m_pano, unsigned int image_number, + float scale); ~MeshInfo(); void CallList(); - void Update(); + void Update(float scale); private: unsigned int image_number; PT::Panorama *m_pano; MeshRemapper *remap; unsigned int display_list_number; - void CompileList(); + void CompileList(float scale); }; std::map<unsigned int, MeshInfo> meshes; }; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-06-22 14:14:23 UTC (rev 3139) @@ -45,6 +45,7 @@ TextureManager::TextureManager(PT::Panorama &pano) { m_pano = &pano; + photometric_correct = false; } TextureManager::~TextureManager() @@ -58,10 +59,34 @@ void TextureManager::BindTexture(unsigned int image_number) { // bind the texture that represents the given image number. - glBindTexture(GL_TEXTURE_2D, - textures[m_pano->getImage(image_number).getFilename()].num); + HuginBase::SrcPanoImage img = m_pano->getSrcImage(image_number); + TextureInfo *tex = &textures[img.getFilename()]; + glBindTexture(GL_TEXTURE_2D, tex->num); + // we should adjust the lighting to match the exposure and white balance + float es = tex->exposure; + float scale[4] = {es / img.getWhiteBalanceRed(), + es, + es / img.getWhiteBalanceBlue(), + 1.0}; + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, scale); } +void TextureManager::Begin() +{ + // we change the exposure and white balance using the scene's ambient light. + glEnable(GL_LIGHTING); + // make the material properties use the ambient light fully. + // find the exposure factor to scale by. + viewer_exposure = pow(2.0, m_pano->getOptions().outputExposureValue); + float exp[4] = {viewer_exposure, viewer_exposure, viewer_exposure, 1.0}; + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, exp); +}; + +void TextureManager::End() +{ + glDisable(GL_LIGHTING); +} + void TextureManager::panoramaImagesChanged(PT::Panorama &pano/*, const PT::UIntSet &changed*/) { // The images or their lenses have changed. @@ -134,7 +159,7 @@ { texinfo = &(it->second); } - + // find the highest mipmap we want to use. double hfov = pano.getLens(pano.getImage(image_index).getLensNr()).getHFOV(), aspect = double (texinfo->height) / double (texinfo->width), @@ -169,14 +194,27 @@ if (mip_width_p < 0) mip_width_p = 0; if (mip_height_p < 0) mip_height_p = 0; - // now count these texels as used- we are ignoring the smaller mip levels, they add 1/3 on to the size. + // now count these texels as used- we are ignoring the smaller mip + // levels, they add 1/3 on to the size. texels_used += 1 << (mip_width_p + mip_height_p); std::cout << "biggest mipmap of image " << image_index << " is " << (1 << mip_width_p) << " by " << (1 << mip_height_p) << " (level " << mip_level <<").\n"; std::cout << "Ideal texels used " << int(ideal_texels_used) << ", actually used " << texels_used << ".\n\n"; - + + // update the exposure of the stored texture. + // if we are doing photometric correction, we will need to rebuild the + // texture. + float new_exposure = pano.getSrcImage(image_index).getExposure(); + if (texinfo->exposure != new_exposure) + { + texinfo->exposure = new_exposure; + if (photometric_correct) + { + texinfo->min_lod = 1000; + } + } // now we have a new desired level of detail, is it different? if (texinfo->min_lod != mip_level) { @@ -190,23 +228,29 @@ // add more detail textures. We need to get the biggest one first. // find the original image to scale down. // TODO cache mipmaps generated to disk for future use? - ImageCache::EntryPtr entry = ImageCache::getInstance().getImage(pano.getImage(image_index).getFilename()); + ImageCache::EntryPtr entry = ImageCache::getInstance().getImage( + pano.getImage(image_index).getFilename()); vigra::BRGBImage img = *(entry->get8BitImage()); // first make the biggest mip level. unsigned int wo = 1 << mip_width_p, ho = 1 << mip_height_p; // use Vigra to resize image vigra::BRGBImage out_img(wo, ho); // TODO check img is bigger than 1 px in both directions - // vigra::resizeImageLinearInterpolation(srcImageRange(img), destImageRange(out_img)); // I think this takes to long, although it should be prettier. - vigra::resizeImageNoInterpolation(srcImageRange(img), destImageRange(out_img)); // much faster - // make all of the one smaller ones until we are done. + // I think this takes to long, although it should be prettier. + // vigra::resizeImageLinearInterpolation(srcImageRange(img), destImageRange(out_img)); + // much faster + vigra::resizeImageNoInterpolation(srcImageRange(img), + destImageRange(out_img)); + // make all of the smaller ones until we are done. // this will use a box filter. // dependent on OpenGL 1.3. Might need an alternative for 1.2. // TODO use texture compresion? gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGB8, wo, ho, GL_RGB, GL_UNSIGNED_BYTE, - mip_level, mip_level, texinfo->min_lod > max_mip_level ? max_mip_level : texinfo->min_lod, + mip_level, mip_level, + texinfo->min_lod > max_mip_level ? + max_mip_level : texinfo->min_lod, (unsigned char *) out_img.data()); if (texinfo->min_lod > max_mip_level) { @@ -277,13 +321,25 @@ texinfo->min_lod = mip_level; } } - std::cout << "---- we now have " << textures.size() << " textures.\n"; - - + // We should remove any images' texture when it is no longer in the panorama CleanTextures(); } +void TextureManager::SetPhotometricCorrect(bool state) +{ + if (state != photometric_correct) + { + photometric_correct = state; + // make all the textures rebuild next time. + for (std::map<std::string, TextureInfo>::iterator + it = textures.begin(); it != textures.end(); it++) + { + it->second.min_lod = 1000; + } + } +} + unsigned int TextureManager::GetMaxTotalTexels() { // TODO: cut off at a sensible value for available hardware, otherwise set Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h 2008-06-22 14:14:23 UTC (rev 3139) @@ -53,8 +53,14 @@ // react to the images & fields of view changing. We can update the // textures here. void panoramaImagesChanged(PT::Panorama &pano/*, const PT::UIntSet &changed*/); + // change the OpenGL state for rendering the textures. + void Begin(); + void End(); + // set to true if we aer doing photmetric correction + void SetPhotometricCorrect(bool state); protected: PT::Panorama * m_pano; + float viewer_exposure; // remove textures for deleted images. void CleanTextures(); // FIXME TextureInfo should probably take care of the texture completely, @@ -73,8 +79,13 @@ unsigned int width, height; // log base 2 of the above, cached. unsigned int width_p, height_p; - unsigned int min_lod; // min_lod is the most detailed mipmap level defined - unsigned int num; // num is the openGL texture name + // min_lod is the most detailed mipmap level defined + unsigned int min_lod; + unsigned int num; // num is the openGL texture name + // this is the exposure the texture content is stored as. For real time + // correction it should be the same of the original file, for + // precalculated correction it is what ever it was last updated to. + double exposure; // TODO same for white balance, vignetting and response curve? }; // we map filenames to TexturesInfos, so we can keep track of // images' textures when the numbers change. @@ -84,6 +95,7 @@ // this is the maximum size a single texture is supported on the hardware. unsigned int GetMaxTextureSizePower(); float texel_density; // multiply by angles to get optimal size. + bool photometric_correct; }; #endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/preview_frame.xrc =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/preview_frame.xrc 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/xrc/preview_frame.xrc 2008-06-22 14:14:23 UTC (rev 3139) @@ -365,6 +365,50 @@ <packing>3</packing> <style>wxTB_DOCKABLE</style> </object> + <object class="wxToolBar" name="fast_preview_toolbar"> + <style>wxTB_FLAT|wxTB_TEXT</style> + <object class="tool" name="preview_center_tool"> + <bitmap>data/center_pano.xpm</bitmap> + <tooltip>Center the preview horizontally</tooltip> + <label>Center</label> + </object> + <object class="tool" name="preview_fit_pano_tool"> + <bitmap>data/fit_pano.xpm</bitmap> + <longhelp>Show the whole panorama</longhelp> + <tooltip>Estimate field of view</tooltip> + <label>Fit</label> + </object> + <object class="tool" name="preview_straighten_pano_tool"> + <bitmap>data/straighten_pano.xpm</bitmap> + <tooltip>Automatically straighten a wavy horizon.</tooltip> + <label>Straighten</label> + </object> + <object class="tool" name="preview_num_transform"> + <bitmap>data/preview_num_transform.png</bitmap> + <tooltip>Numerical Transform</tooltip> + <label>Num. Transf.</label> + </object> + <object class="separator"/> + <object class="tool" name="preview_show_all_tool"> + <bitmap>data/preview_show_all.png</bitmap> + <tooltip>Show all images</tooltip> + <label>All</label> + </object> + <object class="tool" name="preview_show_none_tool"> + <bitmap>data/preview_show_none.png</bitmap> + <tooltip>Show none of the images</tooltip> + <label>None</label> + </object> + <object class="separator"/> + <object class="tool" name="preview_photometric_tool"> + <bitmap>data/find.png</bitmap> + <tooltip>Use photometric correction (slow)</tooltip> + <label>Photometric</label> + </object> + <bitmapsize>22,22</bitmapsize> + <packing>3</packing> + <style>wxTB_DOCKABLE</style> + </object> <object class="wxDialog" name="dlg_numtrans"> <title>Numerical Transform</title> <object class="wxBoxSizer"> @@ -552,4 +596,4 @@ </object> </object> </object> -</resource> \ No newline at end of file +</resource> Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin_base/algorithms/MeshRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin_base/algorithms/MeshRemapper.cpp 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin_base/algorithms/MeshRemapper.cpp 2008-06-22 14:14:23 UTC (rev 3139) @@ -34,7 +34,7 @@ // do not set to high for memory usage, and when adjusting also adjust the // definition of Tree's nodes to account for the extra memory required. const unsigned int max_depth = 5; -const double min_length = 2.0; +const double min_length = 8.0; const double min_angle = 0.1; template <class T> @@ -50,14 +50,14 @@ image_number = image_number_in; } -void MeshRemapper::UpdateAndResetIndex() +void MeshRemapper::UpdateAndResetIndex(float scale_in) { const HuginBase::SrcPanoImage src = m_pano->getSrcImage(image_number); width = (double) src.getSize().width(); height = (double) src.getSize().height(); img2pano.createInvTransform(src, m_pano->getOptions()); - std::cout << "Transforming an image of size " << width << " by " << height << ".\n"; + scale = scale_in; RecursiveUpdate(0, 0, 0); tree.ResetIndex(); } @@ -89,7 +89,6 @@ tree.GetInputCoordinates(node_num, tex_coords); // TODO fix for edges where subdivision changes // TODO reuse values calculated for top and left edge. - // FIXME? are image coordinates relative to image size? TreeNode *node = &tree.nodes[node_num]; for (unsigned short int i = 0; i < 2; i++) { @@ -99,7 +98,7 @@ node->verts[i][j][1], tex_coords[i][j][0] * width, tex_coords[i][j][1] * height); - std::cout << "(" << tex_coords[i][j][0] << ", " << tex_coords[i][j][1] << ") |-> (" << node->verts[i][j][0] << ", " << node->verts[i][j][1] << ")\n"; + //std::cout << "(" << tex_coords[i][j][0] << ", " << tex_coords[i][j][1] << ") |-> (" << node->verts[i][j][0] << ", " << node->verts[i][j][1] << ")\n"; } } @@ -153,7 +152,8 @@ { // std::cout << "Testing subdivision for node " << node_id <<".\n"; TreeNode *node = &tree.nodes[node_id]; - unsigned int depth = tree.GetDepth(node_id); + unsigned int x, y, row_size, depth; + tree.GetPosition(node_id, x, y, row_size, depth); if (depth < min_depth) { // subdivide at least min_depth times @@ -168,14 +168,17 @@ node->flags = 0; return; } - // minimum length check - double length_x = sqrt(sqr(node->verts[0][0][0] - node->verts[1][0][0]) + - sqr(node->verts[0][0][1] - node->verts[1][0][1])), - length_y = sqrt(sqr(node->verts[0][1][0] - node->verts[0][1][0]) + - sqr(node->verts[0][1][1] - node->verts[0][1][1])); - bool do_not_split_x = length_x < min_length, - do_not_split_y = length_y < min_length; - // if we have stoped splitting in some direction, don't consider splitting + // minimum length check. We use the length of the top edge to test for + // subdivision in x, and the length of the left edge for subdivision in y. + float xdx = node->verts[0][0][0] - node->verts[1][0][0], + xdy = node->verts[0][0][1] - node->verts[1][0][1], + ydx = node->verts[0][0][0] - node->verts[0][1][0], + ydy = node->verts[0][0][1] - node->verts[0][1][1]; + float length_x = sqrt(sqr(xdx) + sqr(xdy)), + length_y = sqrt(sqr(ydx) + sqr(ydy)); + bool do_not_split_x = length_x * scale < min_length, + do_not_split_y = length_y * scale < min_length; + // if we have stopped splitting in some direction, don't consider splitting // in that direction again. unsigned int parent = tree.GetParentId(node_id); if (!(tree.nodes[parent].flags & split_flag_x)) @@ -186,14 +189,22 @@ { do_not_split_y = true; } + // check if the angles made are too large. + /*if (x) + { + // find the gradient + float mx = xdx ? xdy/xdx : MAX_FLOAT; + // access the node to the left to get line to compare with + TreeNode *left + float m = + don_not_split_x &= ( + }*/ if (do_not_split_x && do_not_split_y) { // too small, don't subdivide at all node->flags = 0; return; } - // check if the angles made are too large. - // TODO unsigned short int flags = 0; if (!do_not_split_x) flags |= split_flag_x; if (!do_not_split_y) flags |= split_flag_y; @@ -286,14 +297,14 @@ unsigned int x, y, row_size, depth; GetPosition(node_num, x, y, row_size, depth); // now we can locate the upper right corner - double row_spacing = 1.0 / double(row_size); - coords[0][0][0] = row_spacing * double(x); - coords[0][0][1] = row_spacing * double(y); + double row_spacing = 1.0 / (double) row_size; + coords[0][0][0] = row_spacing * (double) x; + coords[0][0][1] = row_spacing * (double) y; // the extent is dependent on the direction of the subdivisions. // at least one direction has an extent of row_spacing. It can double up // if the parent did not subdivide in a direction, recursively up the tree. bool scale_x = false; - double scale = 1.0; + double opp = 1.0; if (node_num != 0) { unsigned int parent_id = GetParentId(x, y, row_size, depth); @@ -302,24 +313,25 @@ while (!(nodes[parent_id].flags & split_flag_x)) { parent_id = GetParentId(parent_id); + opp *= 2.0; } scale_x = true; } else { while (!(nodes[parent_id].flags & split_flag_y)) { parent_id = GetParentId(parent_id); + opp *= 2.0; } } - // now we use the scale to scale the appropriate lengths and deduce the - // remaining coordinates. - scale = double (1 << (depth - GetDepth(parent_id))); } - coords[1][0][0] = coords[0][0][0] + scale_x ? row_spacing*scale:row_spacing; + opp *= row_spacing; + coords[1][0][0] = coords[0][0][0] + (scale_x ? opp : row_spacing); coords[1][0][1] = coords[0][0][1]; coords[0][1][0] = coords[0][0][0]; - coords[0][1][1] = coords[0][0][1] + scale_x ? row_spacing:row_spacing*scale; + coords[0][1][1] = coords[0][0][1] + (scale_x ? row_spacing : opp); coords[1][1][0] = coords[1][0][0]; coords[1][1][1] = coords[0][1][1]; + // std::cout << "Node " << node_num << " covers reactangle from (" << coords[0][0][0] << ", " << coords[0][0][1] << ") to (" << coords[1][1][0] << ", " << coords[1][1][1] << ").\n"; } void MeshRemapper::Tree::ResetIndex() Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin_base/algorithms/MeshRemapper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin_base/algorithms/MeshRemapper.h 2008-06-21 03:20:03 UTC (rev 3138) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin_base/algorithms/MeshRemapper.h 2008-06-22 14:14:23 UTC (rev 3139) @@ -65,7 +65,7 @@ { public: MeshRemapper(HuginBase::Panorama *m_pano, unsigned int image_number); - void UpdateAndResetIndex(); + void UpdateAndResetIndex(float scale); class Coords { public: @@ -76,6 +76,7 @@ // are ordered [left / right][top / bottom][x coord / y coord]. bool GetNextFaceCoordinates(Coords *result); private: + float scale; double height, width; double tex_coords[2][2][2]; HuginBase::Panorama *m_pano; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |