From: <jl...@us...> - 2008-08-12 17:03:43
|
Revision: 3311 http://hugin.svn.sourceforge.net/hugin/?rev=3311&view=rev Author: jlegg Date: 2008-08-12 17:03:33 +0000 (Tue, 12 Aug 2008) Log Message: ----------- A few bug fixes and usability improvements. You can turn on or off the constraints in the drag tool by pressing and releasing shift with the mouse button held. The difference tool and identify tool are now properly mutually exclusive. The difference tool brightens the result for visibility, and subtracts the other way around (pano - image). The status bar message is changed by the tools. The texture manager previously copied images unnecessarily, that is fixed. The scaling is picked a little better, not scaling up very small images so much, and using closer to the budget of texture space. It also supports masks now, although these aren't displayed perfectly when the image is brightened due to the limitations of some OpenGL implementations. (In semi-transparent places, the previously drawn images are brightened as well.) It won't crash or do any undefined behaviour with tiny images either. (Still not using SmallImageCache though.) Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 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.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.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/VertexCoordRemapper.cpp Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/CMakeLists.txt 2008-08-12 17:03:33 UTC (rev 3311) @@ -33,7 +33,7 @@ TexCoordRemapper.cpp ChoosyRemapper.cpp MeshManager.cpp ViewState.cpp OutputProjectionInfo.cpp PreviewToolHelper.cpp PreviewTool.cpp PreviewCropTool.cpp PreviewDragTool.cpp PreviewIdentifyTool.cpp -PreviewDifferenceTool.cpp) +PreviewDifferenceTool.cpp PreviewPanoMaskTool.cpp) IF(APPLE) if (MAC_SELF_CONTAINED_BUNDLE) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -45,7 +45,8 @@ // something messed up... temporary fix :-( #include "hugin_utils/utils.h" #define DEBUG_HEADER "" -#include <vigra_ext/ImageTransforms.h> +/*#include <vigra_ext/ImageTransforms.h> +*/ extern "C" { #ifdef HasPANO13 @@ -61,6 +62,7 @@ #include "PreviewDragTool.h" #include "PreviewIdentifyTool.h" #include "PreviewDifferenceTool.h" +#include "PreviewPanoMaskTool.h" using namespace utils; @@ -248,7 +250,7 @@ 0, wxALL | wxALIGN_CENTER_VERTICAL, 5); - // TODO implement difference blend mode and hdr display in OpenGL. + ////////////////////////////////////////////////////// // Blend mode blendModeSizer->Add(new wxStaticText(this, -1, _("Blend mode:")), @@ -259,7 +261,7 @@ m_choices[0] = _("normal"); m_choices[1] = _("difference"); - int oldMode = wxConfigBase::Get()->Read(wxT("/PreviewFrame/blendMode"), 0l); + int oldMode = wxConfigBase::Get()->Read(wxT("/GLPreviewFrame/blendMode"), 0l); if (oldMode > 1) oldMode = 0; m_BlendModeChoice = new wxChoice(this, ID_BLEND_CHOICE, wxDefaultPosition, wxDefaultSize, @@ -272,6 +274,7 @@ wxALL | wxALIGN_CENTER_VERTICAL, 5); + // TODO implement hdr display in OpenGL, if possible? ////////////////////////////////////////////////////// // LDR, HDR blendModeSizer->Add(new wxStaticText(this, -1, _("Output:")), @@ -366,7 +369,6 @@ CreateStatusBar(3); int widths[3] = {-3, 150, 150}; SetStatusWidths(3, widths); - // SetStatusText(_("Left click to define new center point, right click to move point to horizon."),0); SetStatusText(wxT(""),1); SetStatusText(wxT(""),2); @@ -397,7 +399,7 @@ if (config->Read(wxT("/GLPreviewFrame/isShown"), 0l) != 0) { Show(); } - SetStatusText(_("Center panorama with left mouse button, set horizon with right button"),0); + crop_tool = 0; } GLPreviewFrame::~GLPreviewFrame() @@ -416,11 +418,16 @@ config->Write(wxT("/GLPreviewFrame/blendMode"), m_BlendModeChoice->GetSelection()); - // delete all of the tools - helper->DeactivateTool(crop_tool); delete crop_tool; - helper->DeactivateTool(drag_tool); delete drag_tool; - helper->DeactivateTool(identify_tool); delete identify_tool; - helper->DeactivateTool(difference_tool); delete difference_tool; + // delete all of the tools. When the preview is never used we never get an + // OpenGL context and therefore don't create the tools. + if (crop_tool) + { + helper->DeactivateTool(crop_tool); delete crop_tool; + helper->DeactivateTool(drag_tool); delete drag_tool; + helper->DeactivateTool(identify_tool); delete identify_tool; + helper->DeactivateTool(difference_tool); delete difference_tool; + helper->DeactivateTool(pano_mask_tool); delete pano_mask_tool; + } m_pano.removeObserver(this); DEBUG_TRACE("dtor end"); } @@ -499,8 +506,7 @@ if (relayout) { m_topsizer->Layout(); } -#endif - SetStatusText(_("Center panorama with left mouse button, set horizon with right button"),0); +#endif SetStatusText(wxString::Format(wxT("%.1f x %.1f"), opts.getHFOV(), opts.getVFOV()),2); m_HFOVSlider->SetValue(roundi(opts.getHFOV())); m_VFOVSlider->SetValue(roundi(opts.getVFOV())); @@ -847,7 +853,10 @@ helper->DeactivateTool(difference_tool); break; case 1: + helper->DeactivateTool(identify_tool); + m_ToolBar->ToggleTool(identify_tool_id, false); helper->ActivateTool(difference_tool); + CleanButtonColours(); break; default: DEBUG_WARN("Unknown blend mode selected"); @@ -959,6 +968,12 @@ #endif } +void GLPreviewFrame::SetStatusMessage(wxString message) +{ + SetStatusText(message, 0); +} + + void GLPreviewFrame::OnPhotometric(wxCommandEvent & e) { m_GLViewer->SetPhotometricCorrect(e.IsChecked()); @@ -974,11 +989,16 @@ drag_tool = new PreviewDragTool(helper); identify_tool = new PreviewIdentifyTool(helper, this); difference_tool = new PreviewDifferenceTool(helper); + pano_mask_tool = new PreviewPanoMaskTool(helper); + + // activate tools that are always active. + helper->ActivateTool(pano_mask_tool); } void GLPreviewFrame::OnCrop(wxCommandEvent & e) { // turn on or off the crop tool when its button is pressed. + SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool. if (e.IsChecked()) { // ActivateTool returns pointers to the tools that were switched off to @@ -993,6 +1013,7 @@ void GLPreviewFrame::OnDrag(wxCommandEvent & e) { + SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool. if (e.IsChecked()) { TurnOffTools(helper->ActivateTool(drag_tool)); @@ -1005,8 +1026,11 @@ void GLPreviewFrame::OnIdentify(wxCommandEvent & e) { + SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool. if (e.IsChecked()) { + m_BlendModeChoice->SetSelection(0); + helper->DeactivateTool(difference_tool); TurnOffTools(helper->ActivateTool(identify_tool)); } else { helper->DeactivateTool(identify_tool); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -26,7 +26,17 @@ class wxToolBar; class wxToggleButton; class wxCheckBox; +class wxTextCtrl; +class wxBitmapButton; +class wxSpinButton; +class wxScrolledWindow; +class wxBoxSizer; +class wxStaticBoxSizer; +class wxStaticText; +class wxSlider; class GLViewer; +class wxSpinEvent; +class wxChoice; class PreviewToolHelper; class PreviewTool; @@ -34,10 +44,14 @@ class PreviewDragTool; class PreviewIdentifyTool; class PreviewDifferenceTool; +class PreviewPanoMaskTool; +#include "common/utils.h" +#include <wx/string.h> +#include <wx/frame.h> + // the image toggle buttons need a special event handler to trap mouse enter and // leave events. - class ImageToogleButtonEventHandler : public wxEvtHandler { public: @@ -86,6 +100,7 @@ void MakeTools(PreviewToolHelper * helper); void SetImageButtonColour(unsigned int image_nr, unsigned char red, unsigned char green, unsigned char blue); + void SetStatusMessage(wxString message); protected: void OnClose(wxCloseEvent& e); @@ -156,6 +171,7 @@ PreviewDragTool *drag_tool; PreviewIdentifyTool *identify_tool; PreviewDifferenceTool *difference_tool; + PreviewPanoMaskTool *pano_mask_tool; void TurnOffTools(std::set<PreviewTool*> tools); void CleanButtonColours(); }; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLRenderer.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -31,7 +31,7 @@ // TODO needed? //#include <vector> -/* something messed up... temporary fix :-(*/ +/* something messed up... temporary fix :-( */ #include "hugin_utils/utils.h" #define DEBUG_HEADER "" #include <base_wx/ImageCache.h> Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -83,11 +83,8 @@ // set the context std::cout << "Setting rendering context:\n"; 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. if (!started_creation) { // It appears we are setting up for the first time. @@ -110,7 +107,7 @@ // we need something to store the state of the view and control updates m_view_state = new ViewState(m_pano, RefreshWrapper, this); // Start the tools going: - m_tool_helper = new PreviewToolHelper(m_pano, m_view_state); + m_tool_helper = new PreviewToolHelper(m_pano, m_view_state, frame); frame->MakeTools(m_tool_helper); // now make a renderer m_renderer = new GLRenderer(m_pano, m_view_state->GetTextureManager(), @@ -182,7 +179,7 @@ void GLViewer::MouseMotion(wxMouseEvent& e) { m_tool_helper->MouseMoved((int) e.m_x - offset.x, - (int) e.m_y - offset.y); + (int) e.m_y - offset.y, e); } void GLViewer::MouseLeave(wxMouseEvent & e) Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/OutputProjectionInfo.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -66,29 +66,13 @@ // ...or at least they can be detected from the sides (disk-likes) // I've offset the noth pole slightly as the detection rate was // not 100% - transform.transformImgCoord(x, y, 3.0, 90.0); - north_pole_x = x; + transform.transformImgCoord(x, y, 0.5, 90.0); + north_pole_x = x; north_pole_y = y; - transform.transformImgCoord(x, y, 360.0, 90.0); + transform.transformImgCoord(x, y, 359.5, 90.0); south_pole_x = x; south_pole_y = y; break; - case HuginBase::PanoramaOptions::RECTILINEAR: - // the pole and boundary like problems come at half the angle for - // rectilinear projections. - transform.transformImgCoord(x, y, 93.0, 90.0); - north_pole_x = x; - north_pole_y = y; - radius = -x + output->getSize()->x / 2.0; - transform.transformImgCoord(x, y, 270.0, 90.0); - south_pole_x = x; - south_pole_y = y; - - transform.transformImgCoord(x, y, 150.0, 90.0); - lower_x = x; - transform.transformImgCoord(x, y, 230.0, 90.0); - upper_x = x; - break; default: break; } @@ -100,7 +84,7 @@ const double OutputProjectionInfo::GetUpperX(const double y) const { double temp, pitch, result; - reverse_transform.transformImgCoord(temp, pitch, 0, y); + reverse_transform.transformImgCoord(temp, pitch, 180, y); transform.transformImgCoord(result, temp, 240.0, pitch); return result; } @@ -108,7 +92,7 @@ const double OutputProjectionInfo::GetLowerX(const double y) const { double temp, pitch, result; - reverse_transform.transformImgCoord(temp, pitch, 0, y); + reverse_transform.transformImgCoord(temp, pitch, 180, y); transform.transformImgCoord(result, temp, 120.0, pitch); return result; } @@ -117,7 +101,7 @@ const double OutputProjectionInfo::GetXAdd360(const double y) const { double temp, pitch, result; - reverse_transform.transformImgCoord(temp, pitch, 0, y); + reverse_transform.transformImgCoord(temp, pitch, 180, y); transform.transformImgCoord(result, temp, 0.0, pitch); return result * -2.0 + proj->getSize()->x; } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -45,7 +45,8 @@ moving_left = false; moving_right = false; moving_top = false; - moving_bottom = false; + moving_bottom = false; + helper->SetStatusMessage(_("Drag the inside of the cropping rectangle to adjust the crop.")); } void PreviewCropTool::AfterDrawImagesEvent() @@ -103,7 +104,7 @@ glDisable(GL_BLEND); } -void PreviewCropTool::MouseMoveEvent(double x, double y) +void PreviewCropTool::MouseMoveEvent(double x, double y, wxMouseEvent & e) { if (mouse_down) { Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewCropTool.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -34,7 +34,7 @@ PreviewCropTool(PreviewToolHelper *helper); void Activate(); void AfterDrawImagesEvent(); - void MouseMoveEvent(double x, double y); + void MouseMoveEvent(double x, double y, wxMouseEvent & e); void MouseButtonEvent(wxMouseEvent &e); private: bool moving_left, moving_right, moving_top, moving_bottom, mouse_down; Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDifferenceTool.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -23,6 +23,11 @@ #include <GL/glew.h> #include <GL/gl.h> +// This is the number of times to double the result of the difference. It should +// be between 0 and 7. Note that with values > 0 no extra colours are used +// (infact less are due to clipping), but the difference becomes easier to see. +#define DIFFERENCE_DOUBLE 2 + PreviewDifferenceTool::PreviewDifferenceTool(PreviewToolHelper *helper) : PreviewTool(helper) { @@ -81,7 +86,7 @@ texture_number = tex_m->GetTextureName(image_number); glBindTexture(GL_TEXTURE_2D, texture_number); // we will use a subtractive blend - glBlendEquation(GL_FUNC_SUBTRACT); + glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND); if (tex_m->GetPhotometricCorrect()) @@ -110,6 +115,14 @@ glColor3f(1.0, 1.0, 1.0); } glBlendEquation(GL_FUNC_ADD); + // To make the difference stand out more, multiply it a few times: + glDisable(GL_TEXTURE_2D); + glBlendFunc(GL_DST_COLOR, GL_ONE); + for (unsigned short int count = 0; count < DIFFERENCE_DOUBLE; count++) + { + glCallList(display_list); + } + glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -43,9 +43,11 @@ helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this); helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this); helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); + // a handy message for the user: + helper->SetStatusMessage(_("Drag to move images (optionally use shift to constrain), or roll with right-drag or ctrl-drag.")); } -void PreviewDragTool::MouseMoveEvent(double x, double y) +void PreviewDragTool::MouseMoveEvent(double x, double y, wxMouseEvent & e) { if (drag_yaw || drag_pitch || drag_roll) { @@ -58,16 +60,21 @@ pitch, x, y); shift_coordinates.x = yaw; shift_coordinates.y = pitch; + shift = e.m_shiftDown; if (shift) { if (abs(shift_coordinates.x - start_coordinates.x) < abs(shift_coordinates.y - start_coordinates.y)) { shift_coordinates.x = start_coordinates.x; + helper->SetStatusMessage(_("Currently constrained to moving only pitch. Make a larger movement in the opposite direction to constrain to yaw.")); + } else { shift_coordinates.y = start_coordinates.y; + helper->SetStatusMessage(_("Currently constrained to moving only yaw. Make a larger movement in the opposite direction to constrain to pitch.")); } } + } if (drag_roll) { @@ -125,12 +132,15 @@ // set centre and angle helper->GetViewStatePtr()->GetProjectionInfo()->AngularToImage( centre.x, centre.y, 0.0, 0.0); + centre.x += 0.5; + centre.y += 0.5; hugin_utils::FDiff2D angular = helper->GetMousePosition() - centre; start_angle = atan2(angular.y, angular.x); shift_angle = 0.0; // we'll always rotate around the centre of the panorama. start_coordinates.x = 0.0; start_coordinates.y = 0.0; shift_coordinates.x = 0.0; shift_coordinates.y = 0.0; + helper->SetStatusMessage(_("Rotate around the centre to roll.")); } if (drag_yaw || drag_pitch) { @@ -149,6 +159,12 @@ pitch, mouse_pos.x, mouse_pos.y); start_coordinates.x = yaw; start_coordinates.y = pitch; shift_coordinates.x = yaw; shift_coordinates.y = pitch; + // provide a helpfull message to the user via the staus bar. + if (shift) { + helper->SetStatusMessage(_("Constrained drag: make a movement and it will be snapped to the yaw or pitch.")); + } else { + helper->SetStatusMessage(_("Drag to move.")); + } } if (drag_roll || drag_yaw || drag_pitch) { @@ -193,6 +209,8 @@ // stop dragging image_angles.clear(); drag_yaw = false; drag_pitch = false; drag_roll = false; + + helper->SetStatusMessage(_("Drag to move images (optionally use shift to constrain), or roll with right-drag or ctrl-drag.")); } } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -50,7 +50,7 @@ public: PreviewDragTool(PreviewToolHelper *helper); void Activate(); - void MouseMoveEvent(double x, double y); + void MouseMoveEvent(double x, double y, wxMouseEvent & e); void MouseButtonEvent(wxMouseEvent &e); void AfterDrawImagesEvent(); class AngleStore Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -162,6 +162,8 @@ /* TODO if it becomes possible to activate the tool by a keyboard shortcut * or something, call ImagesUnderMouseChangedEvent() to make sure we display * indicators for images currently under the cursor. */ + + helper->SetStatusMessage(_("Move the mouse over the images or image buttons to identify them.")); } void PreviewIdentifyTool::ImagesUnderMouseChangedEvent() @@ -218,6 +220,14 @@ // viewstate that a redraw is required. helper->GetViewStatePtr()->ForceRequireRedraw(); helper->GetViewStatePtr()->Redraw(); + + // if there is exactly two images, tell the user they can click to edit CPs. + if (image_set.size() == 2) + { + helper->SetStatusMessage(_("Click to create or edit control points here.")); + } else { + helper->SetStatusMessage(_("Move the mouse over the images or image buttons to identify them.")); + } } void PreviewIdentifyTool::AfterDrawImagesEvent() Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewTool.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -48,7 +48,7 @@ // These are called when events happen, providing we requested notification. // The coordinates are in the space of the panorama output at full size. - virtual void MouseMoveEvent(double x, double y) {} + virtual void MouseMoveEvent(double x, double y, wxMouseEvent & e) {} virtual void MouseButtonEvent(wxMouseEvent &e) {} virtual void ImagesUnderMouseChangedEvent() {} virtual void KeypressEvent(int keycode, int modifiers, bool pressed) {} Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -23,13 +23,15 @@ #include "PreviewToolHelper.h" #include "PreviewTool.h" +#include "GLPreviewFrame.h" - PreviewToolHelper::PreviewToolHelper(PT::Panorama *pano_in, - ViewState *view_state_in) + ViewState *view_state_in, + GLPreviewFrame *frame_in) { pano = pano_in; view_state = view_state_in; + frame = frame_in; mouse_button_notified_tool = 0; keypress_notified_tool = 0; images_under_mouse_current = false; @@ -61,7 +63,7 @@ RemoveTool(tool, &images_under_mouse_notified_tools); } -void PreviewToolHelper::MouseMoved(int x, int y) +void PreviewToolHelper::MouseMoved(int x, int y, wxMouseEvent & e) { mouse_over_pano = true; // work out where the pointer is in the panorama. @@ -73,7 +75,7 @@ for (iterator = mouse_move_notified_tools.begin(); iterator != mouse_move_notified_tools.end(); iterator++) { - (*iterator)->MouseMoveEvent(mouse_x, mouse_y); + (*iterator)->MouseMoveEvent(mouse_x, mouse_y, e); } // If the mouse has moved, then we don't know what is underneath it anoymore InvalidateImagesUnderMouse(); @@ -293,6 +295,13 @@ RemoveTool(tool, &image_draw_end_tools, image_nr); } +void PreviewToolHelper::SetStatusMessage(wxString message) +{ + // get the GLPreviewFrame to set its status bar's text. + frame->SetStatusMessage(message); +} + + // These functions remove tools from various things that keep pointers to them // so that they can be notified. They are called when we don't want to notify // them anymore. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -49,6 +49,7 @@ #include <wx/defs.h> #include <wx/event.h> +#include <wx/string.h> #include <set> #include <vector> @@ -58,6 +59,7 @@ #include "PT/Panorama.h" class PreviewTool; +class GLPreviewFrame; class PreviewToolHelper { @@ -69,7 +71,8 @@ IMAGES_UNDER_MOUSE_CHANGE }; PreviewToolHelper(PT::Panorama *pano, - ViewState *view_state); + ViewState *view_state, + GLPreviewFrame * frame); ~PreviewToolHelper(); // working with tools // Activate a tool, the tool will then request notifications it needs. @@ -79,7 +82,8 @@ void DeactivateTool(PreviewTool *tool); // Events - void MouseMoved(int x, int y); + // the x and y coordinates are in pixels from the top left of the panorama. + void MouseMoved(int x, int y, wxMouseEvent & e); // pressed is true if the button is pushed down, false if let go void MouseButtonEvent(wxMouseEvent &e); // keycode is the wxWidgets keycode. @@ -104,11 +108,16 @@ void NotifyMeAfterDrawing(unsigned int image_nr, PreviewTool *tool); void DoNotNotifyMe(Event event, PreviewTool *tool); void DoNotNotifyMeBeforeDrawing(unsigned int image_nr, PreviewTool *tool); - void DoNotNotifyMeAfterDrawing(unsigned int image_nr, PreviewTool *tool); + void DoNotNotifyMeAfterDrawing(unsigned int image_nr, PreviewTool *tool); + + // status message to be something relevant for a tool. + void SetStatusMessage(wxString message); private: std::set<PreviewTool *> tools_deactivated; PT::Panorama *pano; ViewState *view_state; + GLPreviewFrame *frame; + double mouse_x, mouse_y; // What tools are notified of what events. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -69,6 +69,12 @@ TextureKey key(img_p, &photometric_correct); it = textures.find(key); it->second.Bind(); + if (it->second.GetUseAlpha()) + { + // use an alpha blend if + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + } if (!photometric_correct) { // When using real time photometric correction, we multiply the colour @@ -82,15 +88,21 @@ 1.0}; glColor3fv(scale); glCallList(display_list); - // since the intensity was clamped to 0.0 - 1.0, we might overdraw a + // Since the intensity was clamped to 0.0 - 1.0, we might overdraw a // few times to make it brighter. + // FIXME If the image has areas masked out, these will also be + // brightened. It might be better to do using the texture, but this + // way we can only add the texture to the frame buffer, (we can't double + // the intensity multiple times) and there is a cost in processing the + // texture. It also won't work properly on partially transparent places. if (scale[0] > 1.0 || scale[1] > 1.0 || scale[2] > 1.0) { glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_DST_COLOR, GL_ONE); glColor4f(1.0, 1.0, 1.0, 1.0); - // double the brightness for colour components until it is almost right + // double the brightness for colour components until it is almost + // right bool r, g, b; while ( (r = (scale[0] > 2.0)) || (g = (scale[1] > 2.0)) @@ -112,10 +124,15 @@ } glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); + glColor3f(1.0, 1.0, 1.0); } } else { // we've already corrected all the photometrics, just draw once normally glCallList(display_list); + if (it->second.GetUseAlpha()) + { + glDisable(GL_BLEND); + } } } @@ -141,12 +158,6 @@ void TextureManager::End() { - if (!photometric_correct) - { - // set the colour back to normal after using it for photometric - // correction. We expect it to be in this state for drawing other things - glColor3f(1.0, 1.0, 1.0); - } } void TextureManager::CheckUpdate() @@ -309,10 +320,16 @@ // we would like a texture this size: ideal_tex_width = sqrt(ideal_texels / aspect), ideal_tex_height = aspect * ideal_tex_width; + // shrink if bigger than the original, avoids scaling up excessively. + if (ideal_tex_width > img_p->getSize().width()) + ideal_tex_width = img_p->getSize().width(); + if (ideal_tex_height > img_p->getSize().height()) + ideal_tex_height = img_p->getSize().height(); // we will need to round up/down to a power of two + // round up first, then shrink if over budget. // store the power that 2 is raised to, not the actual size - unsigned int tex_width_p = int(log2(ideal_tex_width)), - tex_height_p = int(log2(ideal_tex_height)); + unsigned int tex_width_p = int(log2(ideal_tex_width)) + 1, + tex_height_p = int(log2(ideal_tex_height)) + 1; // check this is hardware supported. { unsigned int biggest = GetMaxTextureSizePower(); @@ -380,7 +397,7 @@ * photometric transformation. * Be warned that when turning off photometric correction, two images * with the same filename will suddenly have the same key, which will - * break the textures map. */ + * break the textures map, hence clearing now */ textures.clear(); } } @@ -395,6 +412,8 @@ // Note: since we use mipmaps, the amount of actual maximum of pixels stored // will be 4/3 of this value. It should use a maximum of 8MB of video memory // for 8 bits per channel rgb images, 12MB if we include a mask. + // Video memory is also used for two copies of the screen and any auxilary + // buffers, and the meshes, so we should do fine with ~24MB of video memory. } unsigned int TextureManager::GetMaxTextureSizePower() @@ -424,19 +443,19 @@ // TODO can this be more efficient? unsigned int num_images = m_pano->getNrOfImages(); bool retry = true; + std::map<TextureKey, TextureInfo>::iterator tex; while (retry) { retry = false; - std::map<TextureKey, TextureInfo>::iterator tex; for (tex = textures.begin(); tex != textures.end(); tex++) { bool found = false; + // try and find an image with this key for (unsigned int img = 0; img < num_images; img++) { - if (TextureKey(view_state->GetSrcImage(img), - &photometric_correct) - == tex->first) + TextureKey ik(view_state->GetSrcImage(img), &photometric_correct); + if (ik == tex->first) { found = true; break; @@ -549,38 +568,55 @@ // add more detail textures. We need to get the biggest one first. // find the original image to scale down. // TODO cache full texture to disk after scaling? - // TODO masks? // TODO use small image if don't need bigger? // It is also possible to use HDR textures, but I can't see the point using // them as the only difference on an LDR display would be spending extra // time reading the texture and converting the numbers. (float and uint16) std::cout << "Loading image\n"; ImageCache::EntryPtr entry = ImageCache::getInstance().getImage( - src_img->getFilename()); + src_img->getFilename()); std::cout << "Converting to 8 bits\n"; - vigra::BRGBImage img = *(entry->get8BitImage()); + boost::shared_ptr<vigra::BRGBImage> img = (entry->get8BitImage()); // first make the biggest mip level. int wo = 1 << (width_p - min), ho = 1 << (height_p - min); if (wo < 1) wo = 1; if (ho < 1) ho = 1; // use Vigra to resize image std::cout << "Scaling image\n"; vigra::BRGBImage out_img(wo, ho); + // also read in the mask. OpenGL requires that the mask is in the same array + // as the colour data, but the ImageCache doesn't work in this way. + vigra::UInt8Image out_alpha(wo, ho); + has_mask = entry->mask->width() != 0; if (wo < 2 || ho < 2) { // too small for vigra to scale - // we still need to define some mipmap levels though. - for (int mip = min; mip < max; mip++) + // we still need to define some mipmap levels though, so use only (0, 0) + for (int h = 0; h < ho; h++) { - // TODO - // glTexImage2D(GL_TEXURE_2D, GL_RGB8, + for (int w = 0; w < wo; w++) + { + out_img[h][w] = (*img)[0][0]; + if (has_mask) out_alpha[h][w] = (*entry->mask)[0][0]; + } } } else { // 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)); /**/ + /*vigra::resizeImageLinearInterpolation(srcImageRange(*img), + destImageRange(out_img)); + if (has_mask) + { + vigra::resizeImageLinearInterpolation(srcImageRange(*(entry->mask)), + destImageRange(out_alpha)); + }/**/ + + // much faster. It shouldn't be so bad after it + vigra::resizeImageNoInterpolation(srcImageRange(*img), + destImageRange(out_img)); + if (has_mask) + { + vigra::resizeImageNoInterpolation(srcImageRange(*(entry->mask)), + destImageRange(out_alpha)); + }/**/ // now perform photometric correction if (photometric_correct) { @@ -619,32 +655,50 @@ hugin_utils::FDiff2D(sx, sy)); } } - } - // TODO read in the masks. - // 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? - std::cout << "Defining mipmap levels " << min << " to " << max - << " of texture " << num << ", starting with a size of " - << wo << " by " << ho << ".\n"; - GLint error = gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGB8, wo, ho, - //GLint error = gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGB8, width, height, - GL_RGB, GL_UNSIGNED_BYTE, min, min, max, - (unsigned char *) out_img.data()); - if (error) + } + + // 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? + std::cout << "Defining mipmap levels " << min << " to " << max + << " of texture " << num << ", starting with a size of " + << wo << " by " << ho << ".\n"; + GLint error; + if (has_mask) + { + // combine the alpha bitmap with the red green and blue one. + unsigned char image[ho][wo][4]; + for (int h = 0; h < ho; h++) { - std::cout << "GLU Error when building mipmap levels: " - << gluErrorString(error) << ".\n"; + for (int w = 0; w < wo; w++) + { + image[h][w][0] = out_img[h][w].red(); + image[h][w][1] = out_img[h][w].green(); + image[h][w][2] = out_img[h][w].blue(); + image[h][w][3] = out_alpha[h][w]; + } } - error = glGetError(); - if (error != GL_NO_ERROR) - { - std::cout << "GL Error when bulding mipmap levels: " - << gluErrorString(error) << ".\n."; - } + error = gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGBA8, wo, ho, + GL_RGBA, GL_UNSIGNED_BYTE, min, min, max, image); + } else { + // we don't need to rearange the data in memory if there is no mask. + error = gluBuild2DMipmapLevels(GL_TEXTURE_2D, GL_RGB8, wo, ho, + GL_RGB, GL_UNSIGNED_BYTE, min, min, max, + (unsigned char *) out_img.data()); } + if (error) + { + std::cout << "GLU Error when building mipmap levels: " + << gluErrorString(error) << ".\n"; + } + error = glGetError(); + if (error != GL_NO_ERROR) + { + std::cout << "GL Error when bulding mipmap levels: " + << gluErrorString(error) << ".\n."; + } SetParameters(); std::cout << "Finsihed loading texture.\n"; } @@ -654,9 +708,8 @@ // we want to tell openGL the highest defined mip level of our texture. Bind(); // FIXME the ati graphics driver on Ubuntu is known to crash due to this - // practice. ati users should disable direct renderering for now. - // it will work if there is only one image, or if all images fit in full - // scale in the alloted space (2 megapixels, so not likely!) + // practice. ati users should disable direct renderering if using the + // #if 0'ed code above. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level); // we don't set min_lod so we can 'DefineLevels' using the old value. GLenum error = glGetError(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/TextureManager.h 2008-08-12 17:03:33 UTC (rev 3311) @@ -96,8 +96,11 @@ void SetMaxLevel(int level); void Bind(); unsigned int GetNumber() {return num;}; + // if the image has a mask, we want to use alpha blending to draw it. + bool GetUseAlpha() {return has_mask;}; private: unsigned int num; // the openGL texture name + bool has_mask; // this binds a new texture in openGL and sets the various parameters // we need for it. void CreateTexture(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-08-12 16:45:49 UTC (rev 3310) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-08-12 17:03:33 UTC (rev 3311) @@ -280,9 +280,7 @@ { vertex_c[0] += view_state->GetProjectionInfo()->GetXAdd360(vertex_c[1]); - } - else - { + } else { vertex_c[0] -= view_state->GetProjectionInfo()->GetXAdd360(vertex_c[1]); } @@ -645,7 +643,6 @@ } break; case HuginBase::PanoramaOptions::SINUSOIDAL: - case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC: // like above, but the bounds change with height if ( node->verts[0][0][0] < i->GetLowerX(node->verts[0][0][1]) || node->verts[0][0][0] > i->GetUpperX(node->verts[0][0][1]) @@ -708,6 +705,8 @@ } } break; + case HuginBase::PanoramaOptions::ALBERS_EQUAL_AREA_CONIC: + break; } if (noncontinuous) { @@ -753,90 +752,6 @@ node->flags |= split_flag_x | patch_flag_x; } } - /*if (x && !(flags & split_flag_y) && depth < max_depth) - { - // scan back up the tree until we get something with a child node on the - // left not containing this node. - unsigned int nid = node_id, depth_c = 0.0; - while ((nid % 2)) - { - nid = tree.GetParentId(nid); - depth_c ++; - } - // now go back down the tree - unsigned int x2, y2, row_size2, depth2; - tree.GetPosition(nid, x2, y2, row_size2, depth2); - bool y_split = tree.nodes[nid].flags & split_flag_y; - // take the child not containing the node we are testing - x2 *= 2; y2 *= 2; row_size2 *= 2; depth2++; - // we'll need to deduce the location in y again. - if (y_split && (y2 != (y >> (depth - depth2)))) y2++; - nid = tree.GetIndex(x2, y2, row_size2, depth2); - if (!(tree.nodes[nid].flags & split_flag_y)) y_split = false; - // now we go right child until we get to the same depth, if there is - // enough splits in y. We also change heights to find the one we want. - for (;depth_c && y_split; depth_c--) - { - x2*=2; y2*=2; - row_size2 *= 2; depth2++; - // move across in x if there is a subdivision, stick to the right: - if ((tree.nodes[nid].flags & split_flag_x)) x2++; - // there will be a split in y, so work out which child gets us - // where we want to be: - if (y2 != (y >> (depth - depth2))) y2++; - nid = tree.GetIndex(x2, y2, row_size2, depth2); - if (!(tree.nodes[nid].flags & split_flag_y)) y_split = false; - } - if (y_split && !(tree.nodes[nid].flags & patch_flag_y)) - { - // more subdivision on the left. - // we want to split just to line up with the other subdivision. - node->flags |= split_flag_y | patch_flag_y; - } - } - // same for the other direction - if (y && !(flags & split_flag_x) && depth < max_depth) - { - // scan back up the tree until we get something with a child node on the - // top not containing this node. - unsigned int nid = node_id, depth_c, row_size2 = row_size; - while ((nid / row_size) % 2) - { - nid = tree.GetParentId(nid); - depth_c ++; - row_size /= 2; - } - // now go back down the tree - unsigned int x2, y2, depth2; - tree.GetPosition(nid, x2, y2, row_size2, depth2); - bool x_split = tree.nodes[nid].flags & split_flag_x; - // take the child not containing the node we are testing - x2 *= 2; y2 *= 2; row_size2 *= 2; depth2++; - // we'll need to deduce the location in x again. - if (x_split && (x2 != (x >> (depth - depth2)))) x2++; - nid = tree.GetIndex(x2, y2, row_size2, depth2); - if (!(tree.nodes[nid].flags & split_flag_x)) x_split = false; - // now we take the downward child until we get to the same depth, if - // there is enough splits in x. We also change x location to find the - // one we want. - for (;depth_c && x_split; depth_c--) - { - x2*=2; y2*=2; - row_size2 *= 2; depth2++; - // move down in y if there is a subdivision - if ((tree.nodes[nid].flags & split_flag_y)) y2++; - // there will be a split in x, so find where we are - if (x2 != x >> (depth - depth2)) x2++; - nid = tree.GetIndex(x2, y2, row_size2, depth2); - if (!(tree.nodes[nid].flags & split_flag_x)) x_split = false; - } - if (x_split && !(tree.nodes[nid].flags & patch_flag_x)) - { - // more subdivision on the left. - // we want to split just to line up with the other subdivision. - node->flags |= split_flag_x | patch_flag_x; - } - }*/ } void VertexCoordRemapper::SetLengthAndAngle(TreeNode *node) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |