From: <jl...@us...> - 2008-08-05 17:57:54
|
Revision: 3273 http://hugin.svn.sourceforge.net/hugin/?rev=3273&view=rev Author: jlegg Date: 2008-08-05 17:57:49 +0000 (Tue, 05 Aug 2008) Log Message: ----------- Fixed the point to point dragging of the drag tool. Changed modifier keys for the drag tool so that shift now constrains the direction to either yaw or pitch (from the point dragged), picking whichever movement is bigger. This is a little confusing under some projections (yaw and pitch are curved through the output projection) so the preview draws lines to help. The Identification tool now shows image indicators when the mouse is moved over image's show/hide toggle buttons correctly. Removed a couple of assertions in computing intersections for polygon clipping. When they were triggered I didn't think clipping would work, but I haven't an example of anywhere it causes noticable mistakes. Modified Paths: -------------- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp 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/GLViewer.cpp hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.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/PreviewIdentifyTool.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/VertexCoordRemapper.cpp Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/ChoosyRemapper.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -111,7 +111,7 @@ if (selected_remapper) { delete selected_remapper; - selected_remapper = NULL; + selected_remapper = 0; } selected_remapper = new TexCoordRemapper(m_pano, image_number, @@ -130,7 +130,7 @@ if (selected_remapper) { delete selected_remapper; - selected_remapper = NULL; + selected_remapper = 0; } selected_remapper = new VertexCoordRemapper(m_pano, image_number, Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -75,7 +75,8 @@ 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 + PROJ_PARAM_SLIDER_ID = wxID_HIGHEST+1500, + ID_TOGGLE_BUT_LEAVE = wxID_HIGHEST+1600 }; BEGIN_EVENT_TABLE(GLPreviewFrame, wxFrame) @@ -99,19 +100,20 @@ EVT_CHOICE(ID_BLEND_CHOICE, GLPreviewFrame::OnBlendChoice) EVT_CHOICE(ID_PROJECTION_CHOICE, GLPreviewFrame::OnProjectionChoice) EVT_CHOICE(ID_OUTPUTMODE_CHOICE, GLPreviewFrame::OnOutputChoice) -#ifdef USE_TOGGLE_BUTTON - EVT_TOGGLEBUTTON(-1, GLPreviewFrame::OnChangeDisplayedImgs) -#else - EVT_CHECKBOX(-1, GLPreviewFrame::OnChangeDisplayedImgs) -#endif - //EVT_ENTER_WINDOW(-1, GLPreviewFrame::MouseEnter) - EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV) -// EVT_SCROLL_THUMBRELEASE(GLPreviewFrame::OnChangeFOV) -// EVT_SCROLL_ENDSCROLL(GLPreviewFrame::OnChangeFOV) EVT_SCROLL_THUMBTRACK(GLPreviewFrame::OnTrackChangeFOV) END_EVENT_TABLE() +BEGIN_EVENT_TABLE(ImageToogleButtonEventHandler, wxEvtHandler) + EVT_ENTER_WINDOW(ImageToogleButtonEventHandler::OnEnter) + EVT_LEAVE_WINDOW(ImageToogleButtonEventHandler::OnLeave) +#ifdef USE_TOGGLE_BUTTON + EVT_TOGGLEBUTTON(-1, ImageToogleButtonEventHandler::OnChange) +#else + EVT_CHECKBOX(-1, ImageToogleButtonEventHandler::OnChange) +#endif +END_EVENT_TABLE() + #define PF_STYLE (wxMAXIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN) #include <iostream> GLPreviewFrame::GLPreviewFrame(wxFrame * frame, PT::Panorama &pano) @@ -363,7 +365,7 @@ 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(_("Left click to define new center point, right click to move point to horizon."),0); SetStatusText(wxT(""),1); SetStatusText(wxT(""),2); @@ -381,7 +383,7 @@ m_pano.addObserver(this); - RestoreFramePosition(this, wxT("PreviewFrame")); + RestoreFramePosition(this, wxT("GLPreviewFrame")); // TODO tell renderer // m_PreviewPanel->SetBlendMode((PreviewPanel::BlendMode)oldMode ); @@ -391,7 +393,7 @@ this->SetBackgroundColour(m_GLViewer->GetBackgroundColour()); #endif - if (config->Read(wxT("/PreviewFrame/isShown"), 0l) != 0) { + if (config->Read(wxT("/GLPreviewFrame/isShown"), 0l) != 0) { Show(); } SetStatusText(_("Center panorama with left mouse button, set horizon with right button"),0); @@ -403,40 +405,19 @@ wxConfigBase * config = wxConfigBase::Get(); wxSize sz = GetClientSize(); - StoreFramePosition(this, wxT("PreviewFrame")); + StoreFramePosition(this, wxT("GLPreviewFrame")); if ( (!this->IsIconized()) && (! this->IsMaximized()) && this->IsShown()) { - config->Write(wxT("/PreviewFrame/isShown"), 1l); + config->Write(wxT("/GLPreviewFrame/isShown"), 1l); } else { - config->Write(wxT("/PreviewFrame/isShown"), 0l); + config->Write(wxT("/GLPreviewFrame/isShown"), 0l); } - config->Write(wxT("/PreviewFrame/blendMode"), m_BlendModeChoice->GetSelection()); + config->Write(wxT("/GLPreviewFrame/blendMode"), m_BlendModeChoice->GetSelection()); m_pano.removeObserver(this); DEBUG_TRACE("dtor end"); } -void GLPreviewFrame::OnChangeDisplayedImgs(wxCommandEvent & e) -{ - int id = e.GetId() - ID_TOGGLE_BUT; - int nImg = m_pano.getNrOfImages(); - UIntSet activeImages = m_pano.getActiveImages(); - DEBUG_DEBUG("toggle_button_id: " << id << " nImg:" << nImg << " m_ToggleButtons.size(): " << m_ToggleButtons.size()); - if (id >= 0 && id < nImg) { - if (e.IsChecked()) { - activeImages.insert(id); - } else { - activeImages.erase(id); - } -// m_PreviewPanel->SetDisplayedImages(m_displayedImgs); - GlobalCmdHist::getInstance().addCommand( - new PT::SetActiveImagesCmd(m_pano, activeImages) - ); - } else { - // FIXME DEBUG_ERROR("invalid Togglebutton ID"); - } -} - void GLPreviewFrame::panoramaChanged(Panorama &pano) { const PanoramaOptions & opts = pano.getOptions(); @@ -538,6 +519,8 @@ m_ButtonSizer->Detach(m_ToggleButtons[i]); delete m_ToggleButtons[i]; m_ToggleButtons.pop_back(); + delete toogle_button_event_handlers[i]; + toogle_button_event_handlers.pop_back(); dirty = true; } @@ -561,6 +544,15 @@ #endif wxFileName tFilename(wxString (pano.getImage(imgNr).getFilename().c_str(), HUGIN_CONV_FILENAME)); but->SetToolTip(tFilename.GetFullName()); + // for the identification tool to work, we need to find when the + // mouse enters and exits the button. We use a custom event + // handler, which will also toggle the images: + ImageToogleButtonEventHandler * event_handler = new + ImageToogleButtonEventHandler(*it, &identify_tool, + identify_tool_id, m_ToolBar, + &m_pano); + toogle_button_event_handlers.push_back(event_handler); + but->PushEventHandler(event_handler); wxSize sz = but->GetSize(); // but->SetSize(res.GetWidth(),sz.GetHeight()); // HACK.. set fixed width. that should work @@ -1074,3 +1066,65 @@ } } +ImageToogleButtonEventHandler::ImageToogleButtonEventHandler( + unsigned int image_number_in, + PreviewIdentifyTool **identify_tool_in, + unsigned int identify_tool_id_in, + wxToolBar *tool_bar_in, + PT::Panorama * m_pano_in) +{ + image_number = image_number_in; + identify_tool = identify_tool_in; + identify_tool_id = identify_tool_id_in; + tool_bar = tool_bar_in; + m_pano = m_pano_in; +} + +void ImageToogleButtonEventHandler::OnEnter(wxMouseEvent & e) +{ + // When using the identify tool, we want to identify image locations when + // the user moves the mouse over the image buttons, but only if the image + // is being shown. + if ( tool_bar->GetToolState(identify_tool_id) + && m_pano->getActiveImages().count(image_number)) + { + (*identify_tool)->ShowImageNumber(image_number); + } + e.Skip(); +} + +void ImageToogleButtonEventHandler::OnLeave(wxMouseEvent & e) +{ + // if the mouse left one of the image toggle buttons with the identification + // tool active, we should stop showing the image indicator for that button. + if (tool_bar->GetToolState(identify_tool_id) + && m_pano->getActiveImages().count(image_number)) + { + (*identify_tool)->StopShowingImages(); + } + e.Skip(); +} + +void ImageToogleButtonEventHandler::OnChange(wxCommandEvent & e) +{ + // the user is turning on or off an image using its button. We want to turn + // the indicators on and off if appropriate correctly to. We use OnEnter + // and OnLeave for the indicators, but these only work when the image is + // showing, so we are carefull of the order: + UIntSet activeImages = m_pano->getActiveImages(); + wxMouseEvent null_event; + if (e.IsChecked()) { + activeImages.insert(image_number); + GlobalCmdHist::getInstance().addCommand( + new PT::SetActiveImagesCmd(*m_pano, activeImages) + ); + OnEnter(null_event); + } else { + OnLeave(null_event); + activeImages.erase(image_number); + GlobalCmdHist::getInstance().addCommand( + new PT::SetActiveImagesCmd(*m_pano, activeImages) + ); + } +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLPreviewFrame.h 2008-08-05 17:57:49 UTC (rev 3273) @@ -34,6 +34,30 @@ class PreviewDragTool; class PreviewIdentifyTool; +// the image toggle buttons need a special event handler to trap mouse enter and +// leave events. + +class ImageToogleButtonEventHandler : public wxEvtHandler +{ +public: + ImageToogleButtonEventHandler(unsigned int image_number, + PreviewIdentifyTool **identify_tool, + unsigned int identify_tool_id, + wxToolBar *tool_bar, + PT::Panorama * m_pano); + void OnChange(wxCommandEvent &e); +protected: + void OnEnter(wxMouseEvent & e); + void OnLeave(wxMouseEvent & e); +private: + DECLARE_EVENT_TABLE() + unsigned int image_number; + PreviewIdentifyTool **identify_tool; + unsigned int identify_tool_id; + wxToolBar *tool_bar; + PT::Panorama * m_pano; +}; + /** The OpenGL preview frame * * Contains the GLViewer and various controls for it. @@ -64,7 +88,6 @@ protected: void OnClose(wxCloseEvent& e); - void OnChangeDisplayedImgs(wxCommandEvent & e); void OnCenterHorizontally(wxCommandEvent & e); void OnFitPano(wxCommandEvent& e); void OnStraighten(wxCommandEvent & e); @@ -123,7 +146,7 @@ #else std::vector<wxCheckBox *> m_ToggleButtons; #endif - + std::vector<ImageToogleButtonEventHandler *> toogle_button_event_handlers; DECLARE_EVENT_TABLE() // tools @@ -136,5 +159,4 @@ }; - #endif // _GLPREVIEWFRAME_H Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -40,6 +40,8 @@ EVT_SIZE (GLViewer::Resized) // mouse motion EVT_MOTION (GLViewer::MouseMotion) + // mouse entered or left the preview + EVT_LEAVE_WINDOW(GLViewer::MouseLeave) // mouse buttons EVT_LEFT_DOWN (GLViewer::LeftDown) EVT_LEFT_UP (GLViewer::LeftUp) @@ -183,6 +185,11 @@ (int) e.m_y - offset.y); } +void GLViewer::MouseLeave(wxMouseEvent & e) +{ + m_tool_helper->MouseLeave(); +} + void GLViewer::LeftDown(wxMouseEvent& e) { m_tool_helper->MouseButtonEvent(e); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/GLViewer.h 2008-08-05 17:57:49 UTC (rev 3273) @@ -50,6 +50,7 @@ ViewState * m_view_state; protected: void MouseMotion(wxMouseEvent& e); + void MouseLeave(wxMouseEvent & e); void LeftDown(wxMouseEvent& e); void LeftUp(wxMouseEvent& e); void RightDown(wxMouseEvent& e); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/MeshRemapper.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -162,7 +162,6 @@ const unsigned int v2_index, const double cl[3]) const { - DEBUG_ASSERT(Inside(v1_index, cl) != Inside(v2_index, cl)); // find the point of intersection from the given edge with a clip plane. // the edge is the vertex with the same number and the one before it. // Get pointers to the vertecies we will use @@ -182,7 +181,8 @@ // t * (cl[0] * dx + cl[1] * dy) + cl[0] * v1_x + cl[1] * v1_y + cl[2] = 0 // t * (cl[0] * dx + cl[1] * dy) = -cl[0] * v1_x - cl[1] * v1_y - cl[2] // so we get: - /* FIXME this assertion sometimes fails. t should always be between 0 and 1. + /* FIXME this assertion sometimes fails. t should always be between 0 and 1, + * but sometimes isn't even when this one passes: */ DEBUG_ASSERT(cl[0] * dx + cl[1] * dy); double t = (-cl[0] * v1->tex_c[0] - cl[1] * v1->tex_c[1] - cl[2]) / @@ -195,7 +195,7 @@ td1 = 1.0 - t, xc = v1->vertex_c[0] * td1 + v2->vertex_c[0] * t, yc = v1->vertex_c[1] * td1 + v2->vertex_c[1] * t; - DEBUG_ASSERT(0.0 <= t && t <= 1.0); + // DEBUG_ASSERT(-0.1 <= t && t <= 1.1); return Vertex(xc, yc, x, y); } Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -38,11 +38,10 @@ void PreviewDragTool::Activate() { drag_yaw = false; drag_pitch = false; drag_roll = false; - shift = false; control = false; alt = false; + shift = false; control = false; // register notifications helper->NotifyMe(PreviewToolHelper::MOUSE_MOVE, this); helper->NotifyMe(PreviewToolHelper::MOUSE_PRESS, this); - helper->NotifyMe(PreviewToolHelper::KEY_PRESS, this); helper->NotifyMe(PreviewToolHelper::DRAW_OVER_IMAGES, this); } @@ -53,33 +52,39 @@ // how far are we moving? if (drag_yaw || drag_pitch) { - /* TODO to the user, it would make more sense if the point they - * started dragging followed the mouse pointer. This doesn't work - * if the user drags from a point other than the centre. */ + double yaw, pitch; helper->GetViewStatePtr()->GetProjectionInfo()->ImageToAngular(yaw, pitch, x, y); shift_coordinates.x = yaw; shift_coordinates.y = pitch; - if (!drag_yaw) shift_coordinates.x = start_coordinates.x; - if (!drag_pitch) shift_coordinates.y = start_coordinates.y; + if (shift) + { + if (abs(shift_coordinates.x - start_coordinates.x) + < abs(shift_coordinates.y - start_coordinates.y)) + { + shift_coordinates.x = start_coordinates.x; + } else { + shift_coordinates.y = start_coordinates.y; + } + } } if (drag_roll) { - shift_angle = RAD_TO_DEG(atan2(y - centre.y, x- centre.x) - - start_angle); + shift_angle = atan2(y - centre.y, x- centre.x) - start_angle; } // move the selected images on the tempory copies for display. + // first calculate a matrix representing the transformation + SetRotationMatrix(shift_coordinates.x, shift_coordinates.y, shift_angle, + start_coordinates.x, start_coordinates.y, 0.0); + // now transform the images in the ViewState (not the panorama yet) std::map<unsigned int, AngleStore>::iterator i; for (i = image_angles.begin(); i != image_angles.end(); i++ ) { HuginBase::SrcPanoImage img = *helper->GetViewStatePtr()-> GetSrcImage(i->first); double new_yaw, new_pitch, new_roll; - i->second.Move(shift_coordinates.x, shift_coordinates.y, - shift_angle, - start_coordinates.x, start_coordinates.y, 0.0, - new_yaw, new_pitch, new_roll); + i->second.Move(&rotation_matrix, new_yaw, new_pitch, new_roll); img.setYaw(new_yaw); img.setPitch(new_pitch); img.setRoll(new_roll); helper->GetViewStatePtr()->SetSrcImage(i->first, &img); } @@ -92,7 +97,6 @@ { if (e.ButtonDown()) { - alt = e.m_altDown | e.m_metaDown; control = e.m_controlDown; shift = e.m_shiftDown; switch (e.GetButton()) @@ -100,38 +104,27 @@ // primary button case wxMOUSE_BTN_LEFT: // different things depending on modifier keys. - if (!(alt || shift || control)) + if (!control) { - // no keys + // Either no key modifiers we care about, or shift. + // With shift we determine an adaptive constraint based on + // movement in both directions. drag_yaw = true; drag_pitch = true; } - else if (shift && !(control || alt)) + else if (control && !(shift)) { - drag_pitch = true; - } - else if (control && !(alt || shift)) - { drag_roll = true; } - else if (alt && !(control || shift)) - { - drag_yaw = true; - } break; case wxMOUSE_BTN_RIGHT: - if (!(alt || shift || control)) - { - drag_roll = true; - } + drag_roll = true; break; } if (drag_roll) { // set centre and angle - HuginBase::PanoramaOptions *opts - = helper->GetViewStatePtr()->GetOptions(); - centre.x = double (opts->getSize().width()) / 2.0; - centre.y = double (opts->getSize().height()) / 2.0; + helper->GetViewStatePtr()->GetProjectionInfo()->AngularToImage( + centre.x, centre.y, 0.0, 0.0); hugin_utils::FDiff2D angular = helper->GetMousePosition() - centre; start_angle = atan2(angular.y, angular.x); shift_angle = 0.0; @@ -156,8 +149,6 @@ pitch, mouse_pos.x, mouse_pos.y); start_coordinates.x = yaw; start_coordinates.y = pitch; shift_coordinates.x = yaw; shift_coordinates.y = pitch; - // find the base transformation - base_rot[0] = yaw; base_rot[1] = pitch; base_rot[2] = 0.0; } if (drag_roll || drag_yaw || drag_pitch) { @@ -177,7 +168,10 @@ for (unsigned int i = 0; i < imgs; i++) { image_angles[i].Set(helper->GetViewStatePtr()->GetSrcImage(i)); - } + }; + SetRotationMatrix(shift_coordinates.x, shift_coordinates.y, + shift_angle, + start_coordinates.x, start_coordinates.y, 0.0); } } else { // apply rotations permanently @@ -188,30 +182,20 @@ panorama.updateVariable( i, Variable("r", r) ); panorama.imageChanged(i);*/ // TODO rotate the right stuff when not rotating the entire panorama. - // TODO use a single command, not two. + double yaw, pitch, roll; + rotation_matrix.GetRotationPT(yaw, pitch, roll); + yaw = RAD_TO_DEG(yaw); + pitch = RAD_TO_DEG(pitch); + roll = RAD_TO_DEG(roll); GlobalCmdHist::getInstance().addCommand( new PT::RotatePanoCmd(*helper->GetPanoramaPtr(), - -start_coordinates.x, start_coordinates.y, - -shift_angle), - true); - GlobalCmdHist::getInstance().addCommand( - new PT::RotatePanoCmd(*helper->GetPanoramaPtr(), - shift_coordinates.x, -shift_coordinates.y, - shift_angle), - true); + yaw, pitch, roll), true); // stop dragging image_angles.clear(); drag_yaw = false; drag_pitch = false; drag_roll = false; } } -void PreviewDragTool::KeypressEvent(int keycode, int modifiers, bool pressed) -{ - alt = modifiers & (wxMOD_ALT | wxMOD_META); - shift = modifiers & wxMOD_SHIFT; - control = modifiers & wxMOD_CONTROL; -} - void PreviewDragTool::AfterDrawImagesEvent() { // draw guide lines down the middle. @@ -220,17 +204,56 @@ height = (double) opts->getSize().height(); // Invert the color underneath. glDisable(GL_TEXTURE_2D); - glPushMatrix(); - glTranslatef(-0.5, -0.5, -0.5); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); + glEnable(GL_BLEND); glColor3f(1.0, 1.0, 1.0); + glPushMatrix(); + glTranslatef(-0.5, -0.5, -0.5); glBegin(GL_LINES); glVertex2f(width / 2.0, 0.0); glVertex2f(width / 2.0, height); glVertex2f(0.0, height / 2.0); - glVertex2f(width, height / 2.0); + glVertex2f(width, height / 2.0); glEnd(); + // draw lines if we are dragging + if (drag_roll) + { + // when rolling, a line from the centre (where we rotate around) in the + // direction of the mouse pointer should help the user. + double distance = width * width + height * height, + angle = start_angle; + glPushMatrix(); + glTranslatef(centre.x, centre.y, 0.0); + glBegin(GL_LINES); + // starting angle + glVertex2d(0.0, 0.0); + glVertex2f(distance * cos(angle), distance * sin(angle)); + // angle now used + angle += shift_angle; + glVertex2d(0.0, 0.0); + glVertex2f(distance * cos(angle), distance * sin(angle)); + glEnd(); + glPopMatrix(); + } + if (drag_pitch || drag_yaw) + { + // Draw a straight line in the spherical space, from the start point to + // under the mouse. It only appears straight when using a cylinderical + // projection or similar though, so we draw it as many line segments. + glBegin(GL_LINE_STRIP); + for (double t = 0.0; t <= 1.0; t+= 0.005) + { + double x, y, ti = 1.0 - t; + helper->GetViewStatePtr()->GetProjectionInfo()->AngularToImage( + x, y, + t * start_coordinates.x + ti *shift_coordinates.x, + t * start_coordinates.y + ti *shift_coordinates.y); + glVertex2d(x, y); + } + glEnd(); + } glPopMatrix(); + glDisable(GL_BLEND); glEnable(GL_TEXTURE_2D); } @@ -242,34 +265,37 @@ roll = img->getRoll(); } -void PreviewDragTool::AngleStore::Move(double yaw_shift, double pitch_shift, - double roll_shift, - double yaw_start, double pitch_start, - double roll_start, +void PreviewDragTool::AngleStore::Move(Matrix3 *matrix, double &yaw_out, double &pitch_out, double &roll_out) { - // rotate the start point to the centre - Matrix3 base_rot_matrix, shift_rot_matrix, base_rot_inverse_matrix, - original_matrix, output_matrix; - original_matrix.SetRotationPT(DEG_TO_RAD(yaw), - DEG_TO_RAD(pitch), - DEG_TO_RAD(roll)); - base_rot_matrix.SetRotationPT(-DEG_TO_RAD(yaw_start), - DEG_TO_RAD(pitch_start), - -DEG_TO_RAD(roll_start)); - shift_rot_matrix.SetRotationPT(DEG_TO_RAD(yaw_shift), - -DEG_TO_RAD(pitch_shift), - DEG_TO_RAD(roll_shift)); - /*base_rot_inverse_matrix.SetRotationPT(-DEG_TO_RAD(yaw_start), - DEG_TO_RAD(pitch_start), - DEG_TO_RAD(roll_start));*/ - output_matrix = /*base_rot_inverse_matrix **/ base_rot_matrix * - shift_rot_matrix * original_matrix; - //output_matrix = shift_rot_matrix * original_matrix; - // collect the resultant rotations + Matrix3 start, output_matrix; + // convert the location of this image to a matrix. + start.SetRotationPT(DEG_TO_RAD(yaw), DEG_TO_RAD(pitch), DEG_TO_RAD(roll)); + // move it by the matrix specified. + output_matrix = *matrix * start; + // get the angles from the matrix output_matrix.GetRotationPT(yaw_out, pitch_out, roll_out); yaw_out = RAD_TO_DEG(yaw_out); pitch_out = RAD_TO_DEG(pitch_out); roll_out = RAD_TO_DEG(roll_out); } + +void PreviewDragTool::SetRotationMatrix(double yaw_shift, double pitch_shift, + double roll_shift, + double yaw_start, double pitch_start, + double roll_start) +{ + Matrix3 y1_mat, r_mat, y2_mat, p1_mat, p2_mat; + // rotates the start point to the centre + y1_mat.SetRotationPT(-DEG_TO_RAD(yaw_start), 0.0, 0.0); + p1_mat.SetRotationPT(0.0, DEG_TO_RAD(pitch_start), 0.0); + // rolls the image + r_mat.SetRotationPT(0.0, 0.0, roll_shift); + // rotates the centre to the destination point + p2_mat.SetRotationPT(0.0, -DEG_TO_RAD(pitch_shift), 0.0); + y2_mat.SetRotationPT(DEG_TO_RAD(yaw_shift), 0.0, 0.0); + + rotation_matrix = y2_mat * p2_mat * r_mat *p1_mat * y1_mat; +} + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewDragTool.h 2008-08-05 17:57:49 UTC (rev 3273) @@ -26,16 +26,15 @@ * * Modifiers | Variables changed * none | yaw and pitch - * shift | pitch + * shift | yaw or pitch, depending on biggest difference. * control | roll - * alt or meta | yaw * - * You can also change only pitch by using the secondary mouse button (if there + * You can also change only roll by using the secondary mouse button (if there * is one). * *(Reasoning: control click on mac is equivalent right click on other platforms, - * no modifiers should be close to old behaviour, where modifiers were not used, - * shift and alt chosen arbitrarily but more portable than meta or the like.) + * no modifiers should be close to old behaviour (where no modifiers were used), + * and shift was chosen arbitrarily.) */ #ifndef _PREVIEWDRAGTOOL_H @@ -44,6 +43,7 @@ #include "PreviewTool.h" #include <map> +#include <hugin_math/Matrix3.h> class PreviewDragTool : public PreviewTool { @@ -52,15 +52,13 @@ void Activate(); void MouseMoveEvent(double x, double y); void MouseButtonEvent(wxMouseEvent &e); - void KeypressEvent(int keycode, int modifiers, bool pressed); void AfterDrawImagesEvent(); class AngleStore { public: double yaw, pitch, roll; void Set(HuginBase::SrcPanoImage *img); - void Move(double yaw_shift, double pitch_shift, double roll_shift, - double yaw_start, double pitch_start, double roll_start, + void Move(Matrix3 *matrix, double &yaw_out, double &pitch_out, double &roll_out); }; private: @@ -68,8 +66,13 @@ bool drag_yaw, drag_pitch, drag_roll; double start_angle, shift_angle; hugin_utils::FDiff2D centre, start_coordinates, shift_coordinates; - double base_rot[3]; - bool shift, control, alt; + bool shift, control; + Matrix3 rotation_matrix; + void SetRotationMatrix(double yaw_shift, double pitch_shift, + double roll_shift, + double yaw_start, double pitch_start, + double roll_start); }; #endif + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -156,6 +156,7 @@ // activated. This should be fine if the user clicks the button to activate // the tool. image_set.clear(); + mouse_is_over_button = false; /* 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. */ @@ -167,24 +168,47 @@ // to work out which ones are not in the new set, so we can set their // buttons back to the system colour. std::set<unsigned int> new_image_set = helper->GetImageNumbersUnderMouse(); - std::vector<unsigned int> difference(image_set.size()); std::vector<unsigned int>::iterator end; - end = std::set_difference (image_set.begin(), image_set.end(), - new_image_set.begin(), new_image_set.end(), - difference.begin()); - DEBUG_ASSERT(end >= difference.begin() && end <= difference.end()); - std::vector<unsigned int>::iterator iterator; - if (iterator != end) { - for (iterator = difference.begin(); iterator < end; iterator++) + std::vector<unsigned int> difference(image_set.size()); + end = difference.begin(); + end = std::set_difference (image_set.begin(), image_set.end(), + new_image_set.begin(), new_image_set.end(), + difference.begin()); + DEBUG_ASSERT(end >= difference.begin() && end <= difference.end()); + if (difference.begin() != end) { - DEBUG_ASSERT(*iterator < helper->GetPanoramaPtr()->getNrOfImages()); - // reset this button to its default system colour. - preview_frame->SetImageButtonColour(*iterator, 0, 0, 0); - // remove the notification - helper->DoNotNotifyMeBeforeDrawing(*iterator, this); + std::vector<unsigned int>::iterator iterator; + for (iterator = difference.begin(); iterator != end; iterator++) + { + DEBUG_ASSERT(*iterator < helper->GetPanoramaPtr()->getNrOfImages()); + // reset this button to its default system colour. + preview_frame->SetImageButtonColour(*iterator, 0, 0, 0); + // remove the notification + helper->DoNotNotifyMeBeforeDrawing(*iterator, this); + } } } + // now request to be notified when drawing the new ones. + { + std::vector<unsigned int> difference(new_image_set.size()); + end = difference.begin(); + end = std::set_difference (new_image_set.begin(), new_image_set.end(), + image_set.begin(), image_set.end(), + difference.begin()); + DEBUG_ASSERT(end >= difference.begin() && end <= difference.end()); + if (difference.begin() != end) + { + std::vector<unsigned int>::iterator iterator; + for (iterator = difference.begin(); iterator != end; iterator++) + { + DEBUG_ASSERT(*iterator < helper->GetPanoramaPtr()->getNrOfImages()); + // get notification of when this is about to be drawn. + helper->NotifyMeBeforeDrawing(*iterator, this); + } + } + } + // remember the new set. image_set.swap(new_image_set); // Redraw with new indicators. Since the indicators aren't part of the @@ -201,8 +225,10 @@ // background are clearly marked. unsigned int num_images = image_set.size(); // draw the actual images - std::set<unsigned int>::iterator it; - for (it = image_set.begin(); it != image_set.end(); it++) + // the preview draws them in reverse order, so the lowest numbered appears + // on top. We will folow this convention to avoid confusion. + std::set<unsigned int>::reverse_iterator it; + for (it = image_set.rbegin(); it != image_set.rend(); it++) { DEBUG_ASSERT(*it < helper->GetPanoramaPtr()->getNrOfImages()); helper->GetViewStatePtr()->GetTextureManager()-> @@ -214,7 +240,7 @@ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glMatrixMode(GL_TEXTURE); unsigned int image_counter = 0; - for (it = image_set.begin(); it != image_set.end(); it++) + for (it = image_set.rbegin(); it != image_set.rend(); it++) { // we want to shift the texture so it lines up with the cropped region. glPushMatrix(); @@ -294,20 +320,33 @@ { DEBUG_ASSERT(image < helper->GetPanoramaPtr()->getNrOfImages()); // Add this image to the set of images drawn. - image_set.insert(image); - // now we want a redraw. - helper->GetViewStatePtr()->ForceRequireRedraw(); - helper->GetViewStatePtr()->Redraw(); + if (!image_set.count(image)) + { + // it is not already in the set. Add it now + image_set.insert(image); + // we want notification of when it is drawn so we can delay drawing. + helper->NotifyMeBeforeDrawing(image, this); + // now we want a redraw. + helper->GetViewStatePtr()->ForceRequireRedraw(); + helper->GetViewStatePtr()->Redraw(); + } + mouse_over_image = image; + mouse_is_over_button = true; } void PreviewIdentifyTool::StopShowingImages() { - // set the colour to the image the user just moused off to the default. - preview_frame->SetImageButtonColour(*image_set.begin(), 0, 0, 0); - image_set.clear(); - // now redraw without the indicator. - helper->GetViewStatePtr()->ForceRequireRedraw(); - helper->GetViewStatePtr()->Redraw(); + if (mouse_is_over_button) + { + // set the colour to the image the user just moused off to the default. + preview_frame->SetImageButtonColour(mouse_over_image, 0, 0, 0); + helper->DoNotNotifyMeBeforeDrawing(mouse_over_image, this); + image_set.erase(mouse_over_image); + // now redraw without the indicator. + helper->GetViewStatePtr()->ForceRequireRedraw(); + helper->GetViewStatePtr()->Redraw(); + mouse_is_over_button = false; + } } // generate a colour given how many colours we need and an index. Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewIdentifyTool.h 2008-08-05 17:57:49 UTC (rev 3273) @@ -59,6 +59,9 @@ // the set of image numbers of the images we are displaying. std::set<unsigned int> image_set; GLPreviewFrame *preview_frame; + // the image the use last placed their mouse over the toggle button for: + unsigned int mouse_over_image; + bool mouse_is_over_button; }; #endif Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -33,6 +33,7 @@ mouse_button_notified_tool = 0; keypress_notified_tool = 0; images_under_mouse_current = false; + mouse_over_pano = true; } PreviewToolHelper::~PreviewToolHelper() @@ -61,6 +62,7 @@ void PreviewToolHelper::MouseMoved(int x, int y) { + mouse_over_pano = true; // work out where the pointer is in the panorama. vigra::Rect2D visible = view_state->GetVisibleArea(); mouse_x = (double) x / view_state->GetScale() + (double) visible.left(); @@ -126,8 +128,13 @@ { (*iterator)->BeforeDrawImagesEvent(); } - // Since we are drawing a new frame, lets assume something has changed. - InvalidateImagesUnderMouse(); + // Since we are drawing a new frame, lets assume something has changed, + // however we want to keep with no images under the mouse if the mouse is + // not on the panorama. + if (mouse_over_pano) + { + InvalidateImagesUnderMouse(); + } } void PreviewToolHelper::AfterDrawImages() @@ -164,6 +171,27 @@ } } +void PreviewToolHelper::MouseLeave() +{ + // if the mouse leaves the preview, there are no images under the mouse + // pointer anymore. + mouse_over_pano = false; + images_under_mouse.clear(); + images_under_mouse_current = true; + if (!images_under_mouse_notified_tools.empty()) + { + // notify tools that the set has changed. + std::set<PreviewTool *>::iterator iterator; + for (iterator = images_under_mouse_notified_tools.begin(); + iterator != images_under_mouse_notified_tools.end(); + iterator++) + { + (*iterator)->ImagesUnderMouseChangedEvent(); + } + } +} + + std::set<unsigned int> PreviewToolHelper::GetImageNumbersUnderMouse() { if (!images_under_mouse_current) @@ -330,7 +358,7 @@ std::vector<PreviewTool *> *vector, unsigned int index) { - if (vector->size() < index) + if (vector->size() < index + 1) { // increase the size of the vector to handle enough elements for index // to exist @@ -347,20 +375,30 @@ void PreviewToolHelper::UpdateImagesUnderMouse() { + // We want to find out which images cover the point underneath the mouse + // pointer. images_under_mouse.clear(); unsigned int num_images = pano->getNrOfImages(); + std::set<unsigned int> displayedImages = pano->getActiveImages(); for (unsigned int image_index = 0; image_index < num_images; image_index++) { - HuginBase::PTools::Transform transform; - transform.createTransform(*view_state->GetSrcImage(image_index), - *view_state->GetOptions()); - double image_x, image_y; - transform.transformImgCoord(image_x, image_y, mouse_x, mouse_y); - if (view_state->GetSrcImage(image_index)->isInside( - vigra::Point2D(int(image_x), int (image_y)))) + // don't try any images that are turned off + if (displayedImages.count(image_index)) { - images_under_mouse.insert(image_index); + // work out if the image covers the point under the mouse. + HuginBase::PTools::Transform transform; + transform.createTransform(*view_state->GetSrcImage(image_index), + *view_state->GetOptions()); + double image_x, image_y; + transform.transformImgCoord(image_x, image_y, mouse_x, mouse_y); + if (view_state->GetSrcImage(image_index)->isInside(vigra::Point2D( + int(image_x), int (image_y)))) + { + // this image is under the mouse, add it to the set. + images_under_mouse.insert(image_index); + } } } images_under_mouse_current = true; } + Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/PreviewToolHelper.h 2008-08-05 17:57:49 UTC (rev 3273) @@ -90,6 +90,7 @@ // tools specify otherwise. bool BeforeDrawImageNumber(unsigned int image); void AfterDrawImageNumber(unsigned int image); + void MouseLeave(); // Get information std::set<unsigned int> GetImageNumbersUnderMouse(); @@ -133,7 +134,7 @@ unsigned int index); // is the set of images under the mouse up to date? - bool images_under_mouse_current; + bool images_under_mouse_current, mouse_over_pano; // which images are under the mouse? std::set<unsigned int> images_under_mouse; void UpdateImagesUnderMouse(); Modified: hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp =================================================================== --- hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-08-05 16:36:22 UTC (rev 3272) +++ hugin/branches/gsoc2008_opengl_preview/src/hugin1/hugin/VertexCoordRemapper.cpp 2008-08-05 17:57:49 UTC (rev 3273) @@ -1105,8 +1105,8 @@ // requested stopping node. Anything at a higher depth is after it. if (depth > max_depth) return 0; node_id = GetIndex(no_x, no_y, row_size, depth); + if (depth == max_depth && no_x >= stop_x && no_y >= stop_y) return 0; } - if (depth == max_depth && no_x >= stop_x && no_y >= stop_y) return 0; // if any of the vertices we are want to use are invalid (e.g. behind the // viewer in a rectilinear projection) we don't want to risk using them: if (nodes[node_id].flags & (transform_fail_flag * 15)) return 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |