00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <OgreViewport.h>
00031 #include <OgreCamera.h>
00032 #include <OgreSceneNode.h>
00033 #include <OgreSceneManager.h>
00034 #include <OgrePass.h>
00035 #include <OgreMaterial.h>
00036 #include <OgreEntity.h>
00037 #include <OgreSubEntity.h>
00038 #include <OgreSharedPtr.h>
00039 #include <OgreTechnique.h>
00040
00041 #include "rviz/display_context.h"
00042 #include "rviz/selection/selection_manager.h"
00043 #include "rviz/render_panel.h"
00044 #include "rviz/load_resource.h"
00045 #include "rviz/window_manager_interface.h"
00046 #include "rviz/geometry.h"
00047 #include "rviz/frame_manager.h"
00048
00049 #include "rviz/ogre_helpers/line.h"
00050
00051 #include "rviz/default_plugin/markers/shape_marker.h"
00052 #include "rviz/default_plugin/markers/arrow_marker.h"
00053 #include "rviz/default_plugin/markers/line_list_marker.h"
00054 #include "rviz/default_plugin/markers/line_strip_marker.h"
00055 #include "rviz/default_plugin/markers/points_marker.h"
00056 #include "rviz/default_plugin/markers/text_view_facing_marker.h"
00057 #include "rviz/default_plugin/markers/mesh_resource_marker.h"
00058 #include "rviz/default_plugin/markers/triangle_list_marker.h"
00059 #include "rviz/default_plugin/markers/marker_base.h"
00060
00061 #include "rviz/default_plugin/interactive_markers/interactive_marker_control.h"
00062 #include "rviz/default_plugin/interactive_markers/interactive_marker.h"
00063
00064 #define NO_HIGHLIGHT_VALUE 0.0
00065 #define ACTIVE_HIGHLIGHT_VALUE 0.5
00066 #define HOVER_HIGHLIGHT_VALUE 0.3
00067
00068 namespace rviz
00069 {
00070
00071 InteractiveMarkerControl::InteractiveMarkerControl( DisplayContext* context,
00072 Ogre::SceneNode *reference_node,
00073 InteractiveMarker *parent )
00074 : mouse_dragging_(false)
00075 , drag_viewport_( NULL )
00076 , context_( context )
00077 , reference_node_(reference_node)
00078 , control_frame_node_(reference_node_->createChildSceneNode())
00079 , markers_node_(reference_node_->createChildSceneNode())
00080 , parent_(parent)
00081 , rotation_(0)
00082 , grab_point_in_reference_frame_(0,0,0)
00083 , interaction_enabled_(false)
00084 , visible_(true)
00085 , view_facing_( false )
00086 , mouse_down_(false)
00087 , show_visual_aids_(false)
00088 , line_(new Line(context->getSceneManager(),control_frame_node_))
00089 {
00090 line_->setVisible(false);
00091 }
00092
00093 void InteractiveMarkerControl::makeMarkers( const visualization_msgs::InteractiveMarkerControl& message )
00094 {
00095 for (unsigned i = 0; i < message.markers.size(); i++)
00096 {
00097 MarkerBasePtr marker;
00098
00099
00100 switch (message.markers[i].type)
00101 {
00102 case visualization_msgs::Marker::CUBE:
00103 case visualization_msgs::Marker::CYLINDER:
00104 case visualization_msgs::Marker::SPHERE:
00105 {
00106 marker.reset(new ShapeMarker(0, context_, markers_node_));
00107 }
00108 break;
00109
00110 case visualization_msgs::Marker::ARROW:
00111 {
00112 marker.reset(new ArrowMarker(0, context_, markers_node_));
00113 }
00114 break;
00115
00116 case visualization_msgs::Marker::LINE_STRIP:
00117 {
00118 marker.reset(new LineStripMarker(0, context_, markers_node_));
00119 }
00120 break;
00121 case visualization_msgs::Marker::LINE_LIST:
00122 {
00123 marker.reset(new LineListMarker(0, context_, markers_node_));
00124 }
00125 break;
00126 case visualization_msgs::Marker::SPHERE_LIST:
00127 case visualization_msgs::Marker::CUBE_LIST:
00128 case visualization_msgs::Marker::POINTS:
00129 {
00130 PointsMarkerPtr points_marker;
00131 points_marker.reset(new PointsMarker(0, context_, markers_node_));
00132 points_markers_.push_back( points_marker );
00133 marker = points_marker;
00134 }
00135 break;
00136 case visualization_msgs::Marker::TEXT_VIEW_FACING:
00137 {
00138 marker.reset(new TextViewFacingMarker(0, context_, markers_node_));
00139 }
00140 break;
00141 case visualization_msgs::Marker::MESH_RESOURCE:
00142 {
00143 marker.reset(new MeshResourceMarker(0, context_, markers_node_));
00144 }
00145 break;
00146
00147 case visualization_msgs::Marker::TRIANGLE_LIST:
00148 {
00149 marker.reset(new TriangleListMarker(0, context_, markers_node_));
00150 }
00151 break;
00152 default:
00153 ROS_ERROR( "Unknown marker type: %d", message.markers[i].type );
00154 break;
00155 }
00156
00157 visualization_msgs::MarkerPtr marker_msg( new visualization_msgs::Marker(message.markers[ i ]) );
00158
00159 if ( marker_msg->header.frame_id.empty() )
00160 {
00161
00162
00163
00164 marker_msg->header.frame_id = context_->getFrameManager()->getFixedFrame();
00165 marker->setMessage( marker_msg );
00166 }
00167 else
00168 {
00169 marker->setMessage( marker_msg );
00170
00171
00172
00173 marker->setPosition( markers_node_->convertWorldToLocalPosition( marker->getPosition() ) );
00174 marker->setOrientation( markers_node_->convertWorldToLocalOrientation( marker->getOrientation() ) );
00175 }
00176 marker->setInteractiveObject( shared_from_this() );
00177
00178 addHighlightPass(marker->getMaterials());
00179
00180 markers_.push_back(marker);
00181 }
00182 }
00183
00184 InteractiveMarkerControl::~InteractiveMarkerControl()
00185 {
00186 context_->getSceneManager()->destroySceneNode(control_frame_node_);
00187 context_->getSceneManager()->destroySceneNode(markers_node_);
00188
00189 if( view_facing_ )
00190 {
00191 context_->getSceneManager()->removeListener(this);
00192 }
00193 }
00194
00195 void InteractiveMarkerControl::processMessage( const visualization_msgs::InteractiveMarkerControl &message )
00196 {
00197 name_ = message.name;
00198 description_ = QString::fromStdString( message.description );
00199 interaction_mode_ = message.interaction_mode;
00200 always_visible_ = message.always_visible;
00201 orientation_mode_ = message.orientation_mode;
00202
00203 control_orientation_ = Ogre::Quaternion(message.orientation.w,
00204 message.orientation.x, message.orientation.y, message.orientation.z);
00205 control_orientation_.normalise();
00206
00207 bool new_view_facingness = (message.orientation_mode == visualization_msgs::InteractiveMarkerControl::VIEW_FACING);
00208 if( new_view_facingness != view_facing_ )
00209 {
00210 if( new_view_facingness )
00211 {
00212 context_->getSceneManager()->addListener(this);
00213 }
00214 else
00215 {
00216 context_->getSceneManager()->removeListener(this);
00217 }
00218 view_facing_ = new_view_facingness;
00219 }
00220
00221 independent_marker_orientation_ = message.independent_marker_orientation;
00222
00223
00224
00225 highlight_passes_.clear();
00226 markers_.clear();
00227 points_markers_.clear();
00228
00229
00230
00231 control_frame_node_->setPosition(parent_->getPosition());
00232 markers_node_->setPosition(parent_->getPosition());
00233
00234 if ( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::INHERIT )
00235 {
00236 control_frame_node_->setOrientation(parent_->getOrientation());
00237 markers_node_->setOrientation(parent_->getOrientation());
00238 }
00239 else
00240 {
00241 control_frame_node_->setOrientation( Ogre::Quaternion::IDENTITY );
00242 markers_node_->setOrientation( Ogre::Quaternion::IDENTITY );
00243 }
00244
00245 makeMarkers( message );
00246
00247 status_msg_ = description_+" ";
00248
00249 Ogre::Vector3 control_dir = control_orientation_.xAxis()*10000.0;
00250 line_->setPoints( control_dir, -1*control_dir );
00251 line_->setVisible(false);
00252
00253
00254 switch( interaction_mode_ )
00255 {
00256 case visualization_msgs::InteractiveMarkerControl::NONE:
00257 cursor_ = rviz::getDefaultCursor();
00258 break;
00259 case visualization_msgs::InteractiveMarkerControl::MENU:
00260 cursor_ = rviz::makeIconCursor( "package://rviz/icons/menu.svg" );
00261 status_msg_ += "<b>Left-Click:</b> Show menu.";
00262 break;
00263 case visualization_msgs::InteractiveMarkerControl::BUTTON:
00264 cursor_ = rviz::getDefaultCursor();
00265 status_msg_ += "<b>Left-Click:</b> Activate. ";
00266 break;
00267 case visualization_msgs::InteractiveMarkerControl::MOVE_AXIS:
00268 cursor_ = rviz::makeIconCursor( "package://rviz/icons/move1d.svg" );
00269 status_msg_ += "<b>Left-Click:</b> Move. ";
00270 break;
00271 case visualization_msgs::InteractiveMarkerControl::MOVE_PLANE:
00272 cursor_ = rviz::makeIconCursor( "package://rviz/icons/move2d.svg" );
00273 status_msg_ += "<b>Left-Click:</b> Move. ";
00274 break;
00275 case visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS:
00276 cursor_ = rviz::makeIconCursor( "package://rviz/icons/rotate.svg" );
00277 status_msg_ += "<b>Left-Click:</b> Rotate. ";
00278 break;
00279 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE:
00280 cursor_ = rviz::makeIconCursor( "package://rviz/icons/moverotate.svg" );
00281 status_msg_ += "<b>Left-Click:</b> Move / Rotate. ";
00282 break;
00283 case visualization_msgs::InteractiveMarkerControl::MOVE_3D:
00284 cursor_ = rviz::makeIconCursor( "package://rviz/icons/move2d.svg" );
00285 status_msg_ += "<b>Left-Click:</b> Move X/Y. <b>Shift + Left-Click / Left-Click + Wheel:</b> Move Z. ";
00286 break;
00287 case visualization_msgs::InteractiveMarkerControl::ROTATE_3D:
00288 cursor_ = rviz::makeIconCursor( "package://rviz/icons/rotate.svg" );
00289 status_msg_ += "<b>Left-Click:</b> Rotate around X/Y. <b>Shift-Left-Click:</b> Rotate around Z. ";
00290 break;
00291 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE_3D:
00292 cursor_ = rviz::makeIconCursor( "package://rviz/icons/moverotate.svg" );
00293 status_msg_ += "<b>Left-Click:</b> Move X/Y. <b>Shift + Left-Click / Left-Click + Wheel:</b> Move Z. <b>Ctrl + Left-Click:</b> Rotate around X/Y. <b>Ctrl + Shift + Left-Click:</b> Rotate around Z. ";
00294 break;
00295 }
00296
00297 if ( parent_->hasMenu() && interaction_mode_ != visualization_msgs::InteractiveMarkerControl::MENU )
00298 {
00299 status_msg_ += "<b>Right-Click:</b> Show context menu.";
00300 }
00301
00302
00303
00304
00305
00306 if( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::VIEW_FACING &&
00307 independent_marker_orientation_ )
00308 {
00309 markers_node_->setOrientation( parent_->getOrientation() );
00310 }
00311
00312 enableInteraction(context_->getSelectionManager()->getInteractionEnabled());
00313 }
00314
00315
00316
00317 void InteractiveMarkerControl::preFindVisibleObjects(
00318 Ogre::SceneManager *source,
00319 Ogre::SceneManager::IlluminationRenderStage irs, Ogre::Viewport *v )
00320 {
00321 updateControlOrientationForViewFacing( v );
00322 }
00323
00324 void InteractiveMarkerControl::updateControlOrientationForViewFacing( Ogre::Viewport* v )
00325 {
00326 Ogre::Quaternion x_view_facing_rotation =
00327 control_orientation_.xAxis().getRotationTo( v->getCamera()->getDerivedDirection());
00328
00329
00330 Ogre::Vector3 z_axis_2 = x_view_facing_rotation * control_orientation_.zAxis();
00331 Ogre::Quaternion align_yz_rotation = z_axis_2.getRotationTo(v->getCamera()->getDerivedUp());
00332
00333
00334 Ogre::Quaternion rotate_around_x = Ogre::Quaternion(rotation_, v->getCamera()->getDerivedDirection());
00335
00336 Ogre::Quaternion rotation = reference_node_->convertWorldToLocalOrientation(
00337 rotate_around_x * align_yz_rotation * x_view_facing_rotation );
00338
00339 control_frame_node_->setOrientation( rotation );
00340
00341 if ( !independent_marker_orientation_ )
00342 {
00343 markers_node_->setOrientation( rotation );
00344
00345
00346 markers_node_->_update(true, false);
00347 }
00348 }
00349
00350 bool InteractiveMarkerControl::getVisible()
00351 {
00352 return visible_ || always_visible_;
00353 }
00354
00355 void InteractiveMarkerControl::setVisible( bool visible )
00356 {
00357 visible_ = visible;
00358
00359 if (always_visible_)
00360 {
00361 markers_node_->setVisible(visible_);
00362 } else
00363 {
00364 markers_node_->setVisible(interaction_enabled_ && visible_);
00365 }
00366 }
00367
00368 void InteractiveMarkerControl::update()
00369 {
00370 if( mouse_dragging_ )
00371 {
00372 handleMouseMovement( dragging_in_place_event_ );
00373 }
00374 }
00375
00376 void InteractiveMarkerControl::enableInteraction( bool enable )
00377 {
00378 if (mouse_down_)
00379 {
00380 return;
00381 }
00382
00383 interaction_enabled_ = enable;
00384 setVisible(visible_);
00385 if (!enable)
00386 {
00387 setHighlight(NO_HIGHLIGHT_VALUE);
00388 }
00389 }
00390
00391 void InteractiveMarkerControl::interactiveMarkerPoseChanged(
00392 Ogre::Vector3 int_marker_position, Ogre::Quaternion int_marker_orientation )
00393 {
00394 control_frame_node_->setPosition(int_marker_position);
00395 markers_node_->setPosition(int_marker_position);
00396
00397 switch (orientation_mode_)
00398 {
00399 case visualization_msgs::InteractiveMarkerControl::INHERIT:
00400 control_frame_node_->setOrientation(int_marker_orientation);
00401 markers_node_->setOrientation(control_frame_node_->getOrientation());
00402 break;
00403
00404 case visualization_msgs::InteractiveMarkerControl::FIXED:
00405 {
00406 control_frame_node_->setOrientation( Ogre::Quaternion( rotation_, control_orientation_.xAxis() ));
00407 markers_node_->setOrientation(control_frame_node_->getOrientation());
00408 break;
00409 }
00410
00411 case visualization_msgs::InteractiveMarkerControl::VIEW_FACING:
00412 if( drag_viewport_ )
00413 {
00414 updateControlOrientationForViewFacing( drag_viewport_ );
00415 }
00416 if ( independent_marker_orientation_ )
00417 {
00418 markers_node_->setOrientation(int_marker_orientation);
00419 }
00420 break;
00421
00422 default:
00423 break;
00424 }
00425 }
00426
00427 Ogre::Vector3 InteractiveMarkerControl::closestPointOnLineToPoint( const Ogre::Vector3& line_start,
00428 const Ogre::Vector3& line_dir,
00429 const Ogre::Vector3& test_point )
00430 {
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 double factor = ( test_point - line_start ).dotProduct( line_dir ) / line_dir.dotProduct( line_dir );
00441 Ogre::Vector3 closest_point = line_start + line_dir * factor;
00442 return closest_point;
00443 }
00444
00445 void InteractiveMarkerControl::rotate( Ogre::Ray &mouse_ray )
00446 {
00447 Ogre::Vector3 intersection_3d;
00448 Ogre::Vector2 intersection_2d;
00449 float ray_t;
00450
00451 Ogre::Vector3 rotation_axis = control_frame_orientation_at_mouse_down_ * control_orientation_.xAxis();
00452
00453
00454
00455 Ogre::Vector3 rotation_center = closestPointOnLineToPoint( control_frame_node_->getPosition(),
00456 rotation_axis,
00457 grab_point_in_reference_frame_ );
00458
00459
00460 if( intersectSomeYzPlane( mouse_ray, rotation_center, control_frame_orientation_at_mouse_down_,
00461 intersection_3d, intersection_2d, ray_t ))
00462 {
00463
00464 rotate(intersection_3d);
00465 }
00466 }
00467
00468 void InteractiveMarkerControl::rotate( const Ogre::Vector3& cursor_in_reference_frame )
00469 {
00470 Ogre::Vector3 rotation_axis = control_frame_orientation_at_mouse_down_ * control_orientation_.xAxis();
00471
00472
00473
00474 Ogre::Vector3 rotation_center = closestPointOnLineToPoint( control_frame_node_->getPosition(),
00475 rotation_axis,
00476 grab_point_in_reference_frame_ );
00477
00478
00479 Ogre::Vector3 grab_rel_center = grab_point_in_reference_frame_ - rotation_center;
00480 Ogre::Vector3 center_to_cursor = cursor_in_reference_frame - rotation_center;
00481 Ogre::Vector3 center_to_cursor_radial = center_to_cursor - center_to_cursor.dotProduct(rotation_axis)*rotation_axis;
00482
00483 Ogre::Quaternion orientation_change_since_mouse_down =
00484 grab_rel_center.getRotationTo( center_to_cursor_radial, rotation_axis );
00485
00486 Ogre::Radian rot;
00487 Ogre::Vector3 axis;
00488 orientation_change_since_mouse_down.ToAngleAxis( rot, axis );
00489
00490
00491
00492
00493
00494 Ogre::Radian rotation_since_mouse_down = rot * axis.dotProduct( rotation_axis );
00495
00496 rotation_ = rotation_at_mouse_down_ + rotation_since_mouse_down;
00497 parent_->setPose( parent_->getPosition(),
00498 orientation_change_since_mouse_down * parent_orientation_at_mouse_down_,
00499 name_ );
00500 }
00501
00502 Ogre::Ray InteractiveMarkerControl::getMouseRayInReferenceFrame( const ViewportMouseEvent& event, int x, int y )
00503 {
00504 float width = event.viewport->getActualWidth() - 1;
00505 float height = event.viewport->getActualHeight() - 1;
00506
00507 Ogre::Ray mouse_ray = event.viewport->getCamera()->getCameraToViewportRay( (x + .5) / width,
00508 (y + .5) / height );
00509
00510
00511 mouse_ray.setOrigin( reference_node_->convertWorldToLocalPosition( mouse_ray.getOrigin() ) );
00512 mouse_ray.setDirection( reference_node_->convertWorldToLocalOrientation( Ogre::Quaternion::IDENTITY ) * mouse_ray.getDirection() );
00513
00514 return mouse_ray;
00515 }
00516
00517 void InteractiveMarkerControl::beginRelativeMouseMotion( const ViewportMouseEvent& event )
00518 {
00519 mouse_x_at_drag_begin_ = event.x;
00520 mouse_y_at_drag_begin_ = event.y;
00521 modifiers_at_drag_begin_ = event.modifiers;
00522
00523 mouse_ray_at_drag_begin_ = getMouseRayInReferenceFrame( event, event.x, event.y );
00524
00525
00526 mouse_ray_at_drag_begin_.setDirection(mouse_ray_at_drag_begin_.getDirection().normalisedCopy());
00527 }
00528
00529 bool InteractiveMarkerControl::getRelativeMouseMotion( const ViewportMouseEvent& event, int& dx, int& dy )
00530 {
00531 dx = event.x - mouse_x_at_drag_begin_;
00532 dy = event.y - mouse_y_at_drag_begin_;
00533 if (dx == 0 && dy == 0)
00534 return false;
00535
00536 QCursor::setPos( mouse_x_at_drag_begin_ + mouse_relative_to_absolute_x_,
00537 mouse_y_at_drag_begin_ + mouse_relative_to_absolute_y_ );
00538 return true;
00539 }
00540
00541 void InteractiveMarkerControl::rotateXYRelative( const ViewportMouseEvent& event )
00542 {
00543 int dx;
00544 int dy;
00545
00546 if (!getRelativeMouseMotion( event, dx, dy ))
00547 return;
00548
00549 static const double MOUSE_SCALE = 2 * 3.14 / 300;
00550 Ogre::Radian rx(dx * MOUSE_SCALE);
00551 Ogre::Radian ry(dy * MOUSE_SCALE);
00552
00553 Ogre::Quaternion up_rot(rx, event.viewport->getCamera()->getRealUp());
00554 Ogre::Quaternion right_rot(ry, event.viewport->getCamera()->getRealRight());
00555
00556 parent_->setPose( parent_->getPosition(),
00557 up_rot * right_rot * parent_->getOrientation(),
00558 name_ );
00559 }
00560
00561 void InteractiveMarkerControl::rotateZRelative( const ViewportMouseEvent& event )
00562 {
00563 int dx;
00564 int dy;
00565
00566 getRelativeMouseMotion( event, dx, dy );
00567 if (std::abs(dy) > std::abs(dx))
00568 dx = dy;
00569 if (dx == 0)
00570 return;
00571
00572 static const double MOUSE_SCALE = 2 * 3.14 / 300;
00573 Ogre::Radian rx(dx * MOUSE_SCALE);
00574
00575 Ogre::Quaternion rot(rx, event.viewport->getCamera()->getRealDirection());
00576
00577 parent_->setPose( parent_->getPosition(),
00578 rot * parent_->getOrientation(),
00579 name_ );
00580 }
00581
00582 void InteractiveMarkerControl::moveZAxisRelative( const ViewportMouseEvent& event )
00583 {
00584 int dx;
00585 int dy;
00586
00587 getRelativeMouseMotion( event, dx, dy );
00588 if (std::abs(dx) > std::abs(dy))
00589 dy = -dx;
00590 if (dy == 0)
00591 return;
00592
00593 double distance = -dy * mouse_z_scale_;
00594 Ogre::Vector3 delta = distance * mouse_ray_at_drag_begin_.getDirection();
00595
00596 parent_->setPose( parent_->getPosition() + delta,
00597 parent_->getOrientation(),
00598 name_ );
00599
00600 parent_position_at_mouse_down_ = parent_->getPosition();
00601 }
00602
00603 void InteractiveMarkerControl::moveZAxisWheel( const ViewportMouseEvent& event )
00604 {
00605
00606 static const double WHEEL_TO_PIXEL_SCALE = (1.0/8.0) * (2.0/15.0);
00607
00608 double distance = event.wheel_delta * WHEEL_TO_PIXEL_SCALE;
00609 Ogre::Vector3 delta = distance * mouse_ray_at_drag_begin_.getDirection();
00610
00611 parent_->setPose( parent_->getPosition() + delta,
00612 parent_->getOrientation(),
00613 name_ );
00614
00615 parent_position_at_mouse_down_ = parent_->getPosition();
00616 }
00617
00618 void InteractiveMarkerControl::moveViewPlane( Ogre::Ray &mouse_ray, const ViewportMouseEvent& event )
00619 {
00620
00621 Ogre::Plane plane( event.viewport->getCamera()->getRealDirection(),
00622 parent_position_at_mouse_down_ + parent_to_grab_position_);
00623
00624
00625 std::pair<bool, Ogre::Real> intersection = mouse_ray.intersects(plane);
00626 if (!intersection.first)
00627 return;
00628 Ogre::Vector3 mouse_position_on_plane = mouse_ray.getPoint(intersection.second);
00629
00630
00631 parent_->setPose( mouse_position_on_plane - parent_to_grab_position_,
00632 parent_->getOrientation(),
00633 name_ );
00634 }
00635
00636 void InteractiveMarkerControl::movePlane( Ogre::Ray &mouse_ray )
00637 {
00638 if( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::VIEW_FACING &&
00639 drag_viewport_ )
00640 {
00641 updateControlOrientationForViewFacing( drag_viewport_ );
00642 }
00643
00644 Ogre::Vector3 intersection_3d;
00645 Ogre::Vector2 intersection_2d;
00646 float ray_t;
00647
00648 if( intersectSomeYzPlane( mouse_ray, grab_point_in_reference_frame_, control_frame_node_->getOrientation(),
00649 intersection_3d, intersection_2d, ray_t ))
00650 {
00651 parent_->setPose( intersection_3d - grab_point_in_reference_frame_ + parent_position_at_mouse_down_, parent_->getOrientation(), name_ );
00652 }
00653 }
00654
00655 void InteractiveMarkerControl::movePlane( const Ogre::Vector3& cursor_position_in_reference_frame )
00656 {
00657 if( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::VIEW_FACING &&
00658 drag_viewport_ )
00659 {
00660 updateControlOrientationForViewFacing( drag_viewport_ );
00661 }
00662
00663 Ogre::Vector3 plane_normal = (control_frame_node_->getOrientation() * control_orientation_.xAxis());
00664 Ogre::Vector3 displacement = (cursor_position_in_reference_frame - grab_point_in_reference_frame_);
00665 Ogre::Vector3 displacement_on_plane = displacement - displacement.dotProduct(plane_normal) * plane_normal;
00666
00667
00668 parent_->setPose( parent_position_at_mouse_down_ + displacement_on_plane,
00669 parent_->getOrientation(), name_ );
00670 }
00671
00674 void InteractiveMarkerControl::worldToScreen( const Ogre::Vector3& pos_rel_reference,
00675 const Ogre::Viewport* viewport,
00676 Ogre::Vector2& screen_pos )
00677 {
00678 Ogre::Vector3 world_pos = reference_node_->convertLocalToWorldPosition( pos_rel_reference );
00679
00680 const Ogre::Camera* cam = viewport->getCamera();
00681 Ogre::Vector3 homogeneous_screen_position = cam->getProjectionMatrix() * (cam->getViewMatrix() * world_pos);
00682
00683 double half_width = viewport->getActualWidth() / 2.0;
00684 double half_height = viewport->getActualHeight() / 2.0;
00685
00686 screen_pos.x = half_width + (half_width * homogeneous_screen_position.x) - .5;
00687 screen_pos.y = half_height + (half_height * -homogeneous_screen_position.y) - .5;
00688 }
00689
00693 bool InteractiveMarkerControl::findClosestPoint( const Ogre::Ray& target_ray,
00694 const Ogre::Ray& mouse_ray,
00695 Ogre::Vector3& closest_point )
00696 {
00697
00698
00699
00700
00701
00702
00703 Ogre::Vector3 v13 = target_ray.getOrigin() - mouse_ray.getOrigin();
00704 Ogre::Vector3 v43 = mouse_ray.getDirection();
00705 Ogre::Vector3 v21 = target_ray.getDirection();
00706 double d1343 = v13.dotProduct( v43 );
00707 double d4321 = v43.dotProduct( v21 );
00708 double d1321 = v13.dotProduct( v21 );
00709 double d4343 = v43.dotProduct( v43 );
00710 double d2121 = v21.dotProduct( v21 );
00711
00712 double denom = d2121 * d4343 - d4321 * d4321;
00713 if( fabs( denom ) <= Ogre::Matrix3::EPSILON )
00714 {
00715 return false;
00716 }
00717 double numer = d1343 * d4321 - d1321 * d4343;
00718
00719 double mua = numer / denom;
00720 closest_point = target_ray.getPoint( mua );
00721 return true;
00722 }
00723
00724 void InteractiveMarkerControl::moveAxis( const Ogre::Ray& mouse_ray, const ViewportMouseEvent& event )
00725 {
00726
00727 Ogre::Ray control_ray;
00728 control_ray.setOrigin( grab_point_in_reference_frame_ );
00729 control_ray.setDirection( control_frame_node_->getOrientation() * control_orientation_.xAxis() );
00730
00731
00732 Ogre::Vector2 control_ray_screen_start, control_ray_screen_end;
00733 worldToScreen( control_ray.getOrigin(), event.viewport, control_ray_screen_start );
00734 worldToScreen( control_ray.getPoint( 1 ), event.viewport, control_ray_screen_end );
00735
00736 Ogre::Vector2 mouse_point( event.x, event.y );
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747 Ogre::Vector2 control_ray_screen_dir = control_ray_screen_end - control_ray_screen_start;
00748 double denominator = control_ray_screen_dir.dotProduct( control_ray_screen_dir );
00749 if( fabs( denominator ) > Ogre::Matrix3::EPSILON )
00750 {
00751 double factor =
00752 ( mouse_point - control_ray_screen_start ).dotProduct( control_ray_screen_dir ) / denominator;
00753
00754 Ogre::Vector2 closest_screen_point = control_ray_screen_start + control_ray_screen_dir * factor;
00755
00756
00757 Ogre::Ray new_mouse_ray = getMouseRayInReferenceFrame( event, closest_screen_point.x, closest_screen_point.y );
00758
00759
00760 Ogre::Vector3 closest_point;
00761 if( findClosestPoint( control_ray, new_mouse_ray, closest_point ))
00762 {
00763
00764 parent_->setPose( closest_point - grab_point_in_reference_frame_ + parent_position_at_mouse_down_,
00765 parent_->getOrientation(), name_ );
00766 }
00767 }
00768 }
00769
00770 void InteractiveMarkerControl::moveAxis( const Ogre::Vector3& cursor_position_in_reference_frame )
00771 {
00772 Ogre::Vector3 control_unit_direction = (control_frame_node_->getOrientation() * control_orientation_.xAxis());
00773 Ogre::Vector3 displacement_along_axis = (cursor_position_in_reference_frame - grab_point_in_reference_frame_).dotProduct(control_unit_direction) * control_unit_direction;
00774
00775
00776 parent_->setPose( parent_position_at_mouse_down_ + displacement_along_axis,
00777 parent_->getOrientation(), name_ );
00778
00779 }
00780
00781 void InteractiveMarkerControl::moveRotate( Ogre::Ray &mouse_ray )
00782 {
00783 if( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::VIEW_FACING &&
00784 drag_viewport_ )
00785 {
00786 updateControlOrientationForViewFacing( drag_viewport_ );
00787 }
00788
00789 Ogre::Vector3 new_drag_rel_ref;
00790 Ogre::Vector2 intersection_2d;
00791 float ray_t;
00792
00793
00794
00795
00796
00797
00798
00799 Ogre::Matrix4 control_rel_ref;
00800 control_rel_ref.makeTransform( control_frame_node_->getPosition(),
00801 Ogre::Vector3::UNIT_SCALE,
00802 control_frame_node_->getOrientation() );
00803 Ogre::Vector3 rotation_center = control_rel_ref * rotation_center_rel_control_;
00804
00805
00806
00807
00808 Ogre::Vector3 prev_drag_rel_ref = control_rel_ref * grab_point_rel_control_;
00809
00810
00811
00812 if( intersectSomeYzPlane( mouse_ray, rotation_center, control_frame_node_->getOrientation(),
00813 new_drag_rel_ref, intersection_2d, ray_t ))
00814 {
00815
00816
00817
00818
00819
00820
00821
00822 Ogre::Vector3 prev_rel_center = prev_drag_rel_ref - rotation_center;
00823 Ogre::Vector3 new_rel_center = new_drag_rel_ref - rotation_center;
00824 if( new_rel_center.length() > Ogre::Matrix3::EPSILON )
00825 {
00826 Ogre::Quaternion rotation_change = prev_rel_center.getRotationTo( new_rel_center, rotation_axis_ );
00827 Ogre::Radian rot;
00828 Ogre::Vector3 axis;
00829 rotation_change.ToAngleAxis( rot, axis );
00830
00831
00832
00833
00834
00835 Ogre::Radian angle_change = rot * axis.dotProduct( rotation_axis_ );
00836 rotation_ += angle_change;
00837 parent_->rotate( rotation_change, name_ );
00838
00839
00840
00841
00842 parent_->translate( new_rel_center * (1.0 - prev_rel_center.length() / new_rel_center.length()), name_ );
00843 }
00844 }
00845 }
00846
00847 void InteractiveMarkerControl::moveRotate( const Ogre::Vector3& cursor_position_in_reference_frame, bool lock_axis )
00848 {
00849 if( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::VIEW_FACING &&
00850 drag_viewport_ )
00851 {
00852 updateControlOrientationForViewFacing( drag_viewport_ );
00853 }
00854
00855
00856
00857
00858
00859
00860
00861 Ogre::Matrix4 control_rel_ref;
00862 control_rel_ref.makeTransform( control_frame_node_->getPosition(),
00863 Ogre::Vector3::UNIT_SCALE,
00864 control_frame_node_->getOrientation() );
00865 Ogre::Vector3 rotation_center = control_rel_ref * rotation_center_rel_control_;
00866
00867
00868
00869
00870 Ogre::Vector3 prev_drag_rel_ref = control_rel_ref * grab_point_rel_control_;
00871
00872
00873 Ogre::Vector3 new_drag_rel_ref = cursor_position_in_reference_frame;
00874 if (lock_axis)
00875 {
00876 Ogre::Vector3 plane_normal = (control_frame_node_->getOrientation() * control_orientation_.xAxis());
00877 Ogre::Vector3 perpendicular_offset = (new_drag_rel_ref - prev_drag_rel_ref)
00878 .dotProduct(plane_normal)*plane_normal;
00879 new_drag_rel_ref -= perpendicular_offset;
00880 }
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 Ogre::Vector3 prev_rel_center = prev_drag_rel_ref - rotation_center;
00891 Ogre::Vector3 new_rel_center = new_drag_rel_ref - rotation_center;
00892 if( new_rel_center.length() > Ogre::Matrix3::EPSILON )
00893 {
00894 Ogre::Quaternion rotation_change = prev_rel_center.getRotationTo( new_rel_center, rotation_axis_ );
00895 Ogre::Radian rot;
00896 Ogre::Vector3 axis;
00897 rotation_change.ToAngleAxis( rot, axis );
00898
00899
00900
00901
00902
00903 Ogre::Radian angle_change = rot * axis.dotProduct( rotation_axis_ );
00904 rotation_ += angle_change;
00905 parent_->rotate( rotation_change, name_ );
00906
00907
00908
00909
00910 parent_->translate( new_rel_center * (1.0 - prev_rel_center.length() / new_rel_center.length()), name_ );
00911 }
00912 }
00913
00914 void InteractiveMarkerControl::move3D( const Ogre::Vector3& cursor_position_in_reference_frame,
00915 const Ogre::Quaternion& cursor_orientation_in_reference_frame )
00916 {
00917 if( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::VIEW_FACING &&
00918 drag_viewport_ )
00919 {
00920 updateControlOrientationForViewFacing( drag_viewport_ );
00921 }
00922
00923
00924
00925
00926
00927 Ogre::Vector3 world_to_cursor_in_world_frame = reference_node_->convertLocalToWorldPosition(cursor_position_in_reference_frame);
00928 Ogre::Quaternion rotation_world_to_cursor = reference_node_->convertLocalToWorldOrientation(cursor_orientation_in_reference_frame);
00929
00930
00931
00932 Ogre::Vector3 world_to_cursor_in_cursor_frame = rotation_world_to_cursor.Inverse()*world_to_cursor_in_world_frame;
00933 Ogre::Vector3 world_to_marker_in_world_frame = rotation_world_to_cursor*(world_to_cursor_in_cursor_frame - parent_to_cursor_in_cursor_frame_at_grab_);
00934 Ogre::Vector3 marker_position_in_reference_frame = reference_node_->convertWorldToLocalPosition(world_to_marker_in_world_frame);
00935
00936
00937 parent_->setPose( marker_position_in_reference_frame,
00938 parent_->getOrientation(), name_ );
00939 }
00940
00941 void InteractiveMarkerControl::rotate3D( const Ogre::Vector3& cursor_position_in_reference_frame,
00942 const Ogre::Quaternion& cursor_orientation_in_reference_frame )
00943 {
00944 if( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::VIEW_FACING &&
00945 drag_viewport_ )
00946 {
00947 updateControlOrientationForViewFacing( drag_viewport_ );
00948 }
00949
00950
00951
00952
00953
00954 Ogre::Vector3 world_to_cursor_in_world_frame = reference_node_->convertLocalToWorldPosition(cursor_position_in_reference_frame);
00955 Ogre::Quaternion rotation_world_to_cursor = reference_node_->convertLocalToWorldOrientation(cursor_orientation_in_reference_frame);
00956
00957
00958
00959 Ogre::Vector3 world_to_cursor_in_cursor_frame = rotation_world_to_cursor.Inverse()*world_to_cursor_in_world_frame;
00960 Ogre::Vector3 world_to_marker_in_world_frame = rotation_world_to_cursor*(world_to_cursor_in_cursor_frame - parent_to_cursor_in_cursor_frame_at_grab_);
00961 Ogre::Vector3 marker_position_in_reference_frame = reference_node_->convertWorldToLocalPosition(world_to_marker_in_world_frame);
00962 Ogre::Quaternion marker_orientation_in_reference_frame = reference_node_->convertWorldToLocalOrientation(rotation_world_to_cursor*rotation_cursor_to_parent_at_grab_);
00963
00964 parent_->setPose( parent_->getPosition(),
00965 marker_orientation_in_reference_frame, name_ );
00966 }
00967
00968
00969 void InteractiveMarkerControl::moveRotate3D( const Ogre::Vector3& cursor_position_in_reference_frame,
00970 const Ogre::Quaternion& cursor_orientation_in_reference_frame )
00971 {
00972 if( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::VIEW_FACING &&
00973 drag_viewport_ )
00974 {
00975 updateControlOrientationForViewFacing( drag_viewport_ );
00976 }
00977
00978
00979
00980
00981
00982 Ogre::Vector3 world_to_cursor_in_world_frame = reference_node_->convertLocalToWorldPosition(cursor_position_in_reference_frame);
00983 Ogre::Quaternion rotation_world_to_cursor = reference_node_->convertLocalToWorldOrientation(cursor_orientation_in_reference_frame);
00984
00985
00986
00987 Ogre::Vector3 world_to_cursor_in_cursor_frame = rotation_world_to_cursor.Inverse()*world_to_cursor_in_world_frame;
00988 Ogre::Vector3 world_to_marker_in_world_frame = rotation_world_to_cursor*(world_to_cursor_in_cursor_frame - parent_to_cursor_in_cursor_frame_at_grab_);
00989 Ogre::Vector3 marker_position_in_reference_frame = reference_node_->convertWorldToLocalPosition(world_to_marker_in_world_frame);
00990 Ogre::Quaternion marker_orientation_in_reference_frame = reference_node_->convertWorldToLocalOrientation(rotation_world_to_cursor*rotation_cursor_to_parent_at_grab_);
00991
00992 parent_->setPose( marker_position_in_reference_frame,
00993 marker_orientation_in_reference_frame, name_ );
00994 }
00995
00996 void InteractiveMarkerControl::setHighlight( const ControlHighlight &hl ){
00997 if(hl == NO_HIGHLIGHT) setHighlight(NO_HIGHLIGHT_VALUE);
00998 if(hl == HOVER_HIGHLIGHT) setHighlight(HOVER_HIGHLIGHT_VALUE);
00999 if(hl == ACTIVE_HIGHLIGHT) setHighlight(ACTIVE_HIGHLIGHT_VALUE);
01000 }
01001
01002 void InteractiveMarkerControl::setHighlight( float a )
01003 {
01004 std::set<Ogre::Pass*>::iterator it;
01005 for (it = highlight_passes_.begin(); it != highlight_passes_.end(); it++)
01006 {
01007 (*it)->setAmbient(a,a,a);
01008 }
01009
01010 std::vector<PointsMarkerPtr>::iterator pm_it;
01011 for( pm_it = points_markers_.begin(); pm_it != points_markers_.end(); pm_it++ )
01012 {
01013 (*pm_it)->setHighlightColor( a, a, a );
01014 }
01015 }
01016
01017 void InteractiveMarkerControl::recordDraggingInPlaceEvent( ViewportMouseEvent& event )
01018 {
01019 dragging_in_place_event_ = event;
01020 dragging_in_place_event_.type = QEvent::MouseMove;
01021 }
01022
01023 void InteractiveMarkerControl::stopDragging( bool force )
01024 {
01025
01026
01027
01028
01029 if ( mouse_dragging_ || force )
01030 {
01031 line_->setVisible(false);
01032 mouse_dragging_ = false;
01033 drag_viewport_ = NULL;
01034 parent_->stopDragging();
01035 }
01036 }
01037
01038
01039 void InteractiveMarkerControl::handle3DCursorEvent( ViewportMouseEvent event,
01040 const Ogre::Vector3& cursor_3D_pos,
01041 const Ogre::Quaternion& cursor_3D_orientation)
01042 {
01043
01044 switch( interaction_mode_ )
01045 {
01046 case visualization_msgs::InteractiveMarkerControl::BUTTON:
01047 if( event.leftUp() )
01048 {
01049 Ogre::Vector3 point_rel_world = cursor_3D_pos;
01050 bool got_3D_point = true;
01051
01052 visualization_msgs::InteractiveMarkerFeedback feedback;
01053 feedback.event_type = visualization_msgs::InteractiveMarkerFeedback::BUTTON_CLICK;
01054 feedback.control_name = name_;
01055 feedback.marker_name = parent_->getName();
01056 parent_->publishFeedback( feedback, got_3D_point, point_rel_world );
01057 }
01058 break;
01059
01060 case visualization_msgs::InteractiveMarkerControl::MENU:
01061 if( event.leftUp() )
01062 {
01063
01064 Ogre::Vector3 three_d_point = cursor_3D_pos;
01065 bool valid_point = true;
01066 Ogre::Vector2 mouse_pos = project3DPointToViewportXY(event.viewport, three_d_point);
01067 QCursor::setPos(event.panel->mapToGlobal(QPoint(mouse_pos.x, mouse_pos.y)));
01068 parent_->showMenu( event, name_, three_d_point, valid_point );
01069 }
01070 break;
01071
01072 case visualization_msgs::InteractiveMarkerControl::MOVE_AXIS:
01073 case visualization_msgs::InteractiveMarkerControl::MOVE_PLANE:
01074 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE:
01075 case visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS:
01076 case visualization_msgs::InteractiveMarkerControl::MOVE_3D:
01077 case visualization_msgs::InteractiveMarkerControl::ROTATE_3D:
01078 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE_3D:
01079 if( event.leftDown() )
01080 {
01081 parent_->startDragging();
01082 drag_viewport_ = event.viewport;
01083
01084
01085 grab_point_in_reference_frame_ = reference_node_->convertWorldToLocalPosition( cursor_3D_pos );
01086 grab_orientation_in_reference_frame_ = reference_node_->convertWorldToLocalOrientation( cursor_3D_orientation );
01087
01088 parent_to_cursor_in_cursor_frame_at_grab_ = cursor_3D_orientation.Inverse()*(cursor_3D_pos - reference_node_->convertLocalToWorldPosition(parent_->getPosition()));
01089 rotation_cursor_to_parent_at_grab_ = cursor_3D_orientation.Inverse()*reference_node_->convertLocalToWorldOrientation(parent_->getOrientation());
01090
01091 parent_position_at_mouse_down_ = parent_->getPosition();
01092 parent_orientation_at_mouse_down_ = parent_->getOrientation();
01093
01094 if( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::VIEW_FACING &&
01095 drag_viewport_ )
01096 {
01097 updateControlOrientationForViewFacing( drag_viewport_ );
01098 }
01099 control_frame_orientation_at_mouse_down_ = control_frame_node_->getOrientation();
01100 rotation_at_mouse_down_ = rotation_;
01101
01102 rotation_axis_ = control_frame_node_->getOrientation() * control_orientation_.xAxis();
01103
01104
01105
01106 Ogre::Vector3 rotation_center_rel_ref = closestPointOnLineToPoint( parent_->getPosition(),
01107 rotation_axis_,
01108 grab_point_in_reference_frame_ );
01109 Ogre::Matrix4 reference_rel_control_frame;
01110 reference_rel_control_frame.makeInverseTransform( control_frame_node_->getPosition(),
01111 Ogre::Vector3::UNIT_SCALE,
01112 control_frame_node_->getOrientation() );
01113 rotation_center_rel_control_ = reference_rel_control_frame * rotation_center_rel_ref;
01114 grab_point_rel_control_ = reference_rel_control_frame * grab_point_in_reference_frame_;
01115 }
01116 if( event.leftUp() )
01117 {
01118
01119 stopDragging( true );
01120 }
01121 break;
01122
01123 default:
01124 break;
01125 }
01126
01127 if( event.leftDown() )
01128 {
01129 setHighlight( ACTIVE_HIGHLIGHT_VALUE );
01130 }
01131 else if( event.leftUp() )
01132 {
01133 setHighlight( HOVER_HIGHLIGHT_VALUE );
01134 }
01135
01136 if (!parent_->handle3DCursorEvent(event, cursor_3D_pos, cursor_3D_orientation, name_))
01137 {
01138 if( event.type == QEvent::MouseMove && event.left())
01139 {
01140 Ogre::Vector3 cursor_position_in_reference_frame = reference_node_->convertWorldToLocalPosition( cursor_3D_pos );
01141 Ogre::Quaternion cursor_orientation_in_reference_frame = reference_node_->convertWorldToLocalOrientation( cursor_3D_orientation );
01142
01143 switch (interaction_mode_)
01144 {
01145 case visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS:
01146 rotate( cursor_position_in_reference_frame );
01147 break;
01148
01149 case visualization_msgs::InteractiveMarkerControl::MOVE_AXIS:
01150 moveAxis( cursor_position_in_reference_frame );
01151 break;
01152
01153 case visualization_msgs::InteractiveMarkerControl::MOVE_PLANE:
01154 movePlane( cursor_position_in_reference_frame );
01155 break;
01156
01157 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE:
01158 moveRotate( cursor_position_in_reference_frame, true );
01159 break;
01160
01161 case visualization_msgs::InteractiveMarkerControl::MOVE_3D:
01162 move3D( cursor_position_in_reference_frame, cursor_orientation_in_reference_frame );
01163 break;
01164
01165 case visualization_msgs::InteractiveMarkerControl::ROTATE_3D:
01166 rotate3D( cursor_position_in_reference_frame, cursor_orientation_in_reference_frame );
01167 break;
01168
01169 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE_3D:
01170 moveRotate3D( cursor_position_in_reference_frame, cursor_orientation_in_reference_frame );
01171 break;
01172
01173 default:
01174 break;
01175 }
01176 }
01177 }
01178 }
01179
01180 void InteractiveMarkerControl::handleMouseEvent( ViewportMouseEvent& event )
01181 {
01182
01183
01184
01185
01186
01187
01188 if( event.type == QEvent::FocusIn )
01189 {
01190 has_focus_ = true;
01191 std::set<Ogre::Pass*>::iterator it;
01192 setHighlight( HOVER_HIGHLIGHT_VALUE );
01193 context_->setStatus( status_msg_ );
01194 }
01195 else if( event.type == QEvent::FocusOut )
01196 {
01197 stopDragging();
01198 has_focus_ = false;
01199 setHighlight(0.0);
01200 return;
01201 }
01202
01203 mouse_down_ = event.left() || event.middle() || event.right();
01204
01205
01206 switch( interaction_mode_ )
01207 {
01208 case visualization_msgs::InteractiveMarkerControl::BUTTON:
01209 if( event.leftUp() )
01210 {
01211 Ogre::Vector3 point_rel_world;
01212 bool got_3D_point = context_->getSelectionManager()->get3DPoint( event.viewport, event.x, event.y, point_rel_world );
01213
01214 visualization_msgs::InteractiveMarkerFeedback feedback;
01215 feedback.event_type = visualization_msgs::InteractiveMarkerFeedback::BUTTON_CLICK;
01216 feedback.control_name = name_;
01217 feedback.marker_name = parent_->getName();
01218 parent_->publishFeedback( feedback, got_3D_point, point_rel_world );
01219 }
01220 break;
01221
01222 case visualization_msgs::InteractiveMarkerControl::MENU:
01223 if( event.leftUp() )
01224 {
01225 Ogre::Vector3 point_rel_world;
01226 bool got_3D_point = context_->getSelectionManager()->get3DPoint( event.viewport, event.x, event.y, point_rel_world );
01227 parent_->showMenu( event, name_, point_rel_world, got_3D_point );
01228 }
01229 break;
01230
01231 case visualization_msgs::InteractiveMarkerControl::MOVE_AXIS:
01232 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE:
01233 case visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS:
01234 if ( event.leftDown() )
01235 beginMouseMovement( event,
01236 show_visual_aids_ &&
01237 orientation_mode_ != visualization_msgs::InteractiveMarkerControl::VIEW_FACING);
01238 break;
01239
01240 case visualization_msgs::InteractiveMarkerControl::MOVE_PLANE:
01241 if( event.leftDown() )
01242 beginMouseMovement( event, false);
01243 break;
01244
01245 case visualization_msgs::InteractiveMarkerControl::MOVE_3D:
01246 case visualization_msgs::InteractiveMarkerControl::ROTATE_3D:
01247 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE_3D:
01248 if ( event.leftDown() )
01249 {
01250
01251
01252 beginMouseMovement( event, false );
01253 }
01254 else if ( event.left() &&
01255 ((modifiers_at_drag_begin_ ^ event.modifiers) & (Qt::ShiftModifier | Qt::ControlModifier)) )
01256 {
01257
01258 beginRelativeMouseMotion( event );
01259 }
01260 break;
01261
01262 default:
01263 break;
01264 }
01265
01266 if (!parent_->handleMouseEvent(event, name_))
01267 {
01268 if( event.type == QEvent::MouseMove && event.left() && mouse_dragging_)
01269 {
01270 recordDraggingInPlaceEvent( event );
01271 handleMouseMovement( event );
01272 }
01273 else if( event.type == QEvent::Wheel && event.left() && mouse_dragging_)
01274 {
01275 handleMouseWheelMovement( event );
01276 }
01277 }
01278
01279 if( event.leftDown() )
01280 {
01281 setHighlight( ACTIVE_HIGHLIGHT_VALUE );
01282 }
01283 else if( event.leftUp() )
01284 {
01285 setHighlight( HOVER_HIGHLIGHT_VALUE );
01286 stopDragging();
01287 }
01288 }
01289
01290 void InteractiveMarkerControl::beginMouseMovement( ViewportMouseEvent& event, bool line_visible )
01291 {
01292 line_->setVisible(line_visible);
01293
01294 parent_->startDragging();
01295 mouse_dragging_ = true;
01296 drag_viewport_ = event.viewport;
01297
01298 recordDraggingInPlaceEvent( event );
01299 Ogre::Vector3 grab_point_in_world_frame;
01300 if( ! context_->getSelectionManager()->get3DPoint( event.viewport, event.x, event.y, grab_point_in_world_frame ))
01301 {
01302
01303
01304 grab_point_in_reference_frame_ = control_frame_node_->getPosition();
01305 parent_to_grab_position_ = Ogre::Vector3(0,0,0);
01306 }
01307 else
01308 {
01309
01310
01311 grab_point_in_reference_frame_ = reference_node_->convertWorldToLocalPosition(grab_point_in_world_frame);
01312 parent_to_grab_position_ = grab_point_in_world_frame - parent_->getPosition();
01313 }
01314 parent_position_at_mouse_down_ = parent_->getPosition();
01315 parent_orientation_at_mouse_down_ = parent_->getOrientation();
01316
01317 QPoint absolute_mouse = QCursor::pos();
01318 mouse_relative_to_absolute_x_ = absolute_mouse.x() - event.x;
01319 mouse_relative_to_absolute_y_ = absolute_mouse.y() - event.y;
01320 beginRelativeMouseMotion( event );
01321
01322 if( orientation_mode_ == visualization_msgs::InteractiveMarkerControl::VIEW_FACING &&
01323 drag_viewport_ )
01324 {
01325 updateControlOrientationForViewFacing( drag_viewport_ );
01326 }
01327 control_frame_orientation_at_mouse_down_ = control_frame_node_->getOrientation();
01328 rotation_at_mouse_down_ = rotation_;
01329
01330 rotation_axis_ = control_frame_node_->getOrientation() * control_orientation_.xAxis();
01331
01332
01333
01334 Ogre::Vector3 rotation_center_rel_ref = closestPointOnLineToPoint( parent_->getPosition(),
01335 rotation_axis_,
01336 grab_point_in_reference_frame_ );
01337 Ogre::Matrix4 reference_rel_control_frame;
01338 reference_rel_control_frame.makeInverseTransform( control_frame_node_->getPosition(),
01339 Ogre::Vector3::UNIT_SCALE,
01340 control_frame_node_->getOrientation() );
01341 rotation_center_rel_control_ = reference_rel_control_frame * rotation_center_rel_ref;
01342 grab_point_rel_control_ = reference_rel_control_frame * grab_point_in_reference_frame_;
01343
01344
01345
01346 static const double DEFAULT_MOUSE_Z_SCALE = 0.001;
01347 mouse_z_scale_ = DEFAULT_MOUSE_Z_SCALE;
01348
01349 Ogre::Ray mouse_ray = getMouseRayInReferenceFrame( event, event.x, event.y );
01350 Ogre::Ray mouse_ray_10 = getMouseRayInReferenceFrame( event, event.x, event.y + 10 );
01351
01352 Ogre::Vector3 intersection_3d;
01353 Ogre::Vector3 intersection_3d_10;
01354 Ogre::Vector2 intersection_2d;
01355 float ray_t;
01356
01357 if( intersectSomeYzPlane( mouse_ray,
01358 grab_point_in_reference_frame_,
01359 control_frame_node_->getOrientation(),
01360 intersection_3d,
01361 intersection_2d,
01362 ray_t ))
01363 {
01364 if( intersectSomeYzPlane( mouse_ray_10,
01365 grab_point_in_reference_frame_,
01366 control_frame_node_->getOrientation(),
01367 intersection_3d_10,
01368 intersection_2d,
01369 ray_t ))
01370 {
01371 mouse_z_scale_ = (intersection_3d_10 - intersection_3d).length() / 10.0;
01372 if (mouse_z_scale_ < std::numeric_limits<float>::min() * 100.0)
01373 mouse_z_scale_ = DEFAULT_MOUSE_Z_SCALE;
01374 }
01375 }
01376 }
01377
01378 void InteractiveMarkerControl::handleMouseMovement( ViewportMouseEvent& event )
01379 {
01380 Ogre::Ray mouse_ray = getMouseRayInReferenceFrame( event, event.x, event.y );
01381 Ogre::Ray last_mouse_ray = getMouseRayInReferenceFrame( event, event.last_x, event.last_y );
01382
01383 bool do_rotation = false;
01384 switch (interaction_mode_)
01385 {
01386 case visualization_msgs::InteractiveMarkerControl::MOVE_AXIS:
01387 moveAxis( mouse_ray, event );
01388 break;
01389
01390 case visualization_msgs::InteractiveMarkerControl::MOVE_PLANE:
01391 movePlane( mouse_ray );
01392 break;
01393
01394 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE:
01395 moveRotate( mouse_ray );
01396 break;
01397
01398 case visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS:
01399 rotate( mouse_ray );
01400 break;
01401
01402 case visualization_msgs::InteractiveMarkerControl::ROTATE_3D:
01403 do_rotation = true;
01404
01405 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE_3D:
01406 if ( event.control() )
01407 do_rotation = true;
01408
01409 case visualization_msgs::InteractiveMarkerControl::MOVE_3D:
01410 if ( do_rotation )
01411 {
01412 if (event.shift())
01413 rotateZRelative( event );
01414 else
01415 rotateXYRelative( event );
01416 }
01417 else
01418 {
01419 if (event.shift())
01420 moveZAxisRelative( event );
01421 else
01422 moveViewPlane( mouse_ray, event );
01423 }
01424 break;
01425
01426 default:
01427 break;
01428 }
01429 }
01430
01431 void InteractiveMarkerControl::handleMouseWheelMovement( ViewportMouseEvent& event )
01432 {
01433 switch (interaction_mode_)
01434 {
01435 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE_3D:
01436 case visualization_msgs::InteractiveMarkerControl::MOVE_3D:
01437 moveZAxisWheel( event );
01438 break;
01439
01440 default:
01441 break;
01442 }
01443 }
01444
01445 bool InteractiveMarkerControl::intersectYzPlane( const Ogre::Ray& mouse_ray,
01446 Ogre::Vector3& intersection_3d,
01447 Ogre::Vector2& intersection_2d,
01448 float &ray_t )
01449 {
01450 return intersectSomeYzPlane( mouse_ray,
01451 control_frame_node_->getPosition(),
01452 control_frame_node_->getOrientation(),
01453 intersection_3d, intersection_2d, ray_t );
01454 }
01455
01456 bool InteractiveMarkerControl::intersectSomeYzPlane( const Ogre::Ray& mouse_ray,
01457 const Ogre::Vector3& point_on_plane,
01458 const Ogre::Quaternion& plane_orientation,
01459 Ogre::Vector3& intersection_3d,
01460 Ogre::Vector2& intersection_2d,
01461 float& ray_t )
01462 {
01463 Ogre::Vector3 normal = plane_orientation * control_orientation_.xAxis();
01464 Ogre::Vector3 axis_1 = plane_orientation * control_orientation_.yAxis();
01465 Ogre::Vector3 axis_2 = plane_orientation * control_orientation_.zAxis();
01466
01467 Ogre::Plane plane(normal, point_on_plane);
01468
01469 Ogre::Vector2 origin_2d(point_on_plane.dotProduct(axis_1), point_on_plane.dotProduct(axis_2));
01470
01471 std::pair<bool, Ogre::Real> intersection = mouse_ray.intersects(plane);
01472 if (intersection.first)
01473 {
01474 intersection_3d = mouse_ray.getPoint(intersection.second);
01475 intersection_2d = Ogre::Vector2(intersection_3d.dotProduct(axis_1), intersection_3d.dotProduct(axis_2));
01476 intersection_2d -= origin_2d;
01477
01478 ray_t = intersection.second;
01479 return true;
01480 }
01481
01482 ray_t = 0;
01483 return false;
01484 }
01485
01486 void InteractiveMarkerControl::addHighlightPass( S_MaterialPtr materials )
01487 {
01488 S_MaterialPtr::iterator it;
01489
01490 for (it = materials.begin(); it != materials.end(); it++)
01491 {
01492 Ogre::MaterialPtr material = *it;
01493 Ogre::Pass *original_pass = material->getTechnique(0)->getPass(0);
01494 Ogre::Pass *pass = material->getTechnique(0)->createPass();
01495
01496 pass->setSceneBlending(Ogre::SBT_ADD);
01497 pass->setDepthWriteEnabled(false);
01498 pass->setDepthCheckEnabled(true);
01499 pass->setLightingEnabled(true);
01500 pass->setAmbient(0, 0, 0);
01501 pass->setDiffuse(0, 0, 0, 0);
01502 pass->setSpecular(0, 0, 0, 0);
01503 pass->setCullingMode(original_pass->getCullingMode());
01504
01505 highlight_passes_.insert(pass);
01506 }
01507 }
01508
01509 }