osgEarth 2.1.1
|
00001 /* -*-c++-*- */ 00002 /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph 00003 * Copyright 2008-2010 Pelican Mapping 00004 * http://osgearth.org 00005 * 00006 * osgEarth is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> 00018 */ 00019 #ifndef OSGEARTHUTIL_EARTHMANIPULATOR 00020 #define OSGEARTHUTIL_EARTHMANIPULATOR 00021 00022 #include <osgEarthUtil/Common> 00023 #include <osgEarth/Common> 00024 #include <osgEarthUtil/Viewpoint> 00025 #include <osgEarth/MapNode> 00026 #include <osg/Timer> 00027 #include <map> 00028 #include <list> 00029 #include <utility> 00030 00031 namespace osgEarth { namespace Util 00032 { 00040 class OSGEARTHUTIL_EXPORT EarthManipulator : public osgGA::MatrixManipulator 00041 { 00042 public: 00043 00045 enum ActionType { 00046 ACTION_NULL, 00047 ACTION_HOME, 00048 ACTION_GOTO, 00049 ACTION_PAN, 00050 ACTION_PAN_LEFT, 00051 ACTION_PAN_RIGHT, 00052 ACTION_PAN_UP, 00053 ACTION_PAN_DOWN, 00054 ACTION_ROTATE, 00055 ACTION_ROTATE_LEFT, 00056 ACTION_ROTATE_RIGHT, 00057 ACTION_ROTATE_UP, 00058 ACTION_ROTATE_DOWN, 00059 ACTION_ZOOM, 00060 ACTION_ZOOM_IN, 00061 ACTION_ZOOM_OUT, 00062 ACTION_EARTH_DRAG 00063 }; 00064 00066 enum EventType { 00067 EVENT_MOUSE_CLICK = osgGA::GUIEventAdapter::USER << 1, 00068 EVENT_MOUSE_DOUBLE_CLICK = osgGA::GUIEventAdapter::DOUBLECLICK, 00069 EVENT_MOUSE_DRAG = osgGA::GUIEventAdapter::DRAG, 00070 EVENT_KEY_DOWN = osgGA::GUIEventAdapter::KEYDOWN, 00071 EVENT_SCROLL = osgGA::GUIEventAdapter::SCROLL 00072 }; 00073 00075 enum MouseEvent { 00076 MOUSE_LEFT_BUTTON = osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON, 00077 MOUSE_MIDDLE_BUTTON = osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON, 00078 MOUSE_RIGHT_BUTTON = osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON 00079 }; 00080 00083 enum ActionOptionType { 00084 OPTION_SCALE_X, // Sensitivity multiplier for horizontal input movements 00085 OPTION_SCALE_Y, // Sensitivity multiplier for vertical input movements 00086 OPTION_CONTINUOUS, // Whether to act as long as the button or key is depressed 00087 OPTION_SINGLE_AXIS, // If true, only operate on one axis at a time (the one with the larger value) 00088 OPTION_GOTO_RANGE_FACTOR, // for ACTION_GOTO, multiply the Range by this factor (to zoom in/out) 00089 OPTION_DURATION // Time it takes to complete the action (in seconds) 00090 }; 00091 00093 enum TetherMode 00094 { 00095 TETHER_CENTER, // The camera will follow the center of the node. 00096 TETHER_CENTER_AND_ROTATION, // The camera will follow the node and all rotations made by the node 00097 TETHER_CENTER_AND_HEADING // The camera will follow the node and only follow heading rotation 00098 }; 00099 00100 struct OSGEARTHUTIL_EXPORT ActionOption { 00101 ActionOption() { } 00102 ActionOption( int option, bool value ) : _option(option), _bool_value(value) { } 00103 ActionOption( int option, int value ) : _option(option), _int_value(value) { } 00104 ActionOption( int option, double value ) : _option(option), _dbl_value(value) { } 00105 00106 int option() const { return _option; } 00107 bool boolValue() const { return _bool_value; } 00108 int intValue() const { return _int_value; } 00109 double doubleValue() const { return _dbl_value; } 00110 00111 private: 00112 int _option; 00113 union { 00114 bool _bool_value; 00115 int _int_value; 00116 double _dbl_value; 00117 }; 00118 }; 00119 00120 struct OSGEARTHUTIL_EXPORT ActionOptions : public std::vector<ActionOption> { 00121 void add( int option, bool value ) { push_back( ActionOption(option,value) ); } 00122 void add( int option, int value ) { push_back( ActionOption(option,value) ); } 00123 void add( int option, double value) { push_back( ActionOption(option,value) ); } 00124 }; 00125 00126 private: 00127 struct InputSpec 00128 { 00129 InputSpec( int event_type, int input_mask, int modkey_mask ) 00130 : _event_type(event_type), _input_mask(input_mask), _modkey_mask( modkey_mask ) { } 00131 InputSpec( const InputSpec& rhs ) 00132 : _event_type(rhs._event_type), _input_mask(rhs._input_mask), _modkey_mask(rhs._modkey_mask) { } 00133 00134 bool operator == ( const InputSpec& rhs ) const { 00135 return _event_type == rhs._event_type && 00136 _input_mask == rhs._input_mask && 00137 ((_modkey_mask|osgGA::GUIEventAdapter::MODKEY_NUM_LOCK) == (rhs._modkey_mask|osgGA::GUIEventAdapter::MODKEY_NUM_LOCK)); 00138 } 00139 00140 inline bool operator < (const InputSpec& rhs) const { 00141 if ( _event_type < rhs._event_type) return true; 00142 else if ( _event_type > rhs._event_type ) return false; 00143 else if ( _input_mask < rhs._input_mask ) return true; 00144 else if ( _input_mask > rhs._input_mask ) return false; 00145 else return ( _modkey_mask < rhs._modkey_mask ); 00146 } 00147 00148 int _event_type; 00149 int _input_mask; 00150 int _modkey_mask; 00151 }; 00152 typedef std::list<InputSpec> InputSpecs; 00153 00154 enum Direction { 00155 DIR_NA, 00156 DIR_LEFT, 00157 DIR_RIGHT, 00158 DIR_UP, 00159 DIR_DOWN 00160 }; 00161 00162 struct Action 00163 { 00164 Action( ActionType type =ACTION_NULL ); 00165 Action( ActionType type, const ActionOptions& options ); 00166 Action( const Action& rhs ); 00167 ActionType _type; 00168 Direction _dir; 00169 ActionOptions _options; 00170 bool getBoolOption( int option, bool defaultValue ) const; 00171 int getIntOption( int option, int defaultValue ) const; 00172 double getDoubleOption( int option, double defaultValue ) const; 00173 private: 00174 void init(); 00175 }; 00176 00177 void dumpActionInfo( const Action& action, osg::NotifySeverity level ) const; 00178 00179 static Action NullAction; 00180 00181 public: 00182 00183 class OSGEARTHUTIL_EXPORT Settings : public osg::Referenced 00184 { 00185 public: 00186 // construct with default settings 00187 Settings(); 00188 00189 // copy ctor 00190 Settings( const Settings& rhs ); 00191 00211 void bindMouse( 00212 ActionType action, int button_mask, 00213 int modkey_mask = 0L, 00214 const ActionOptions& options =ActionOptions() ); 00215 00234 void bindMouseClick( 00235 ActionType action, int button_mask, 00236 int modkey_mask =0L, 00237 const ActionOptions& options =ActionOptions() ); 00238 00257 void bindMouseDoubleClick( 00258 ActionType action, int button_mask, 00259 int modkey_mask =0L, 00260 const ActionOptions& options =ActionOptions() ); 00261 00280 void bindKey( 00281 ActionType action, int key, 00282 int modkey_mask =0L, 00283 const ActionOptions& options =ActionOptions() ); 00284 00303 void bindScroll( 00304 ActionType action, int scrolling_motion, 00305 int modkey_mask =0L, 00306 const ActionOptions& options =ActionOptions() ); 00307 00315 void setMouseSensitivity( double value ) { _mouse_sens = value; } 00316 00320 double getMouseSensitivity() const { return _mouse_sens; } 00321 00332 void setKeyboardSensitivity( double value ) { _keyboard_sens = value; } 00333 00337 double getKeyboardSensitivity() const { return _keyboard_sens; } 00338 00349 void setScrollSensitivity( double value ) { _scroll_sens = value; } 00350 00354 double getScrollSensitivity() const { return _scroll_sens; } 00355 00365 void setSingleAxisRotation( bool value ) { _single_axis_rotation = value; } 00366 00371 bool getSingleAxisRotation() const { return _single_axis_rotation; } 00372 00377 void setThrowingEnabled( bool value ) { _throwing = value; } 00378 00383 bool getThrowingEnabled() const { return _throwing; } 00384 00389 void setLockAzimuthWhilePanning( bool value ) { _lock_azim_while_panning = value; } 00390 00395 bool getLockAzimuthWhilePanning() const { return _lock_azim_while_panning; } 00396 00405 void setMinMaxPitch( double min_pitch, double max_pitch ); 00406 00408 double getMinPitch() const { return _min_pitch; } 00409 00411 double getMaxPitch() const { return _max_pitch; } 00412 00414 double getMaxXOffset() const { return _max_x_offset; } 00415 00417 double getMaxYOffset() const { return _max_y_offset; } 00418 00420 double getMinDistance() const {return _min_distance; } 00421 00423 double getMaxDistance() const {return _max_distance; } 00424 00426 void setMinMaxDistance( double min_distance, double max_distance); 00427 00431 void setMaxOffset(double max_x_offset, double max_y_offset); 00432 00436 TetherMode getTetherMode() const { return _tether_mode; } 00437 00441 void setTetherMode( TetherMode tether_mode ) { _tether_mode = tether_mode; } 00442 00444 void setArcViewpointTransitions( bool value ); 00445 bool getArcViewpointTransitions() const { return _arc_viewpoints; } 00446 00448 void setAutoViewpointDurationEnabled( bool value ); 00449 bool getAutoViewpointDurationEnabled() const { return _auto_vp_duration; } 00450 00451 void setAutoViewpointDurationLimits( double minSeconds, double maxSeconds ); 00452 void getAutoViewpointDurationLimits( double& out_minSeconds, double& out_maxSeconds ) const { 00453 out_minSeconds = _min_vp_duration_s; 00454 out_maxSeconds = _max_vp_duration_s; 00455 } 00456 00457 private: 00458 00459 friend class EarthManipulator; 00460 00461 typedef std::pair<InputSpec,Action> ActionBinding; 00462 //typedef std::vector<ActionBinding> ActionBindings; 00463 typedef std::map<InputSpec,Action> ActionBindings; 00464 00465 // Gets the action bound to the provided input specification, or NullAction if there is 00466 // to matching binding. 00467 const Action& getAction( int event_type, int input_mask, int modkey_mask ) const; 00468 00469 void expandSpec( const InputSpec& input, InputSpecs& output ) const; 00470 void bind( const InputSpec& spec, const Action& action ); 00471 00472 private: 00473 00474 ActionBindings _bindings; 00475 bool _single_axis_rotation; 00476 bool _throwing; 00477 bool _lock_azim_while_panning; 00478 double _mouse_sens; 00479 double _keyboard_sens; 00480 double _scroll_sens; 00481 double _min_pitch; 00482 double _max_pitch; 00483 00484 double _max_x_offset; 00485 double _max_y_offset; 00486 00487 double _min_distance; 00488 double _max_distance; 00489 00490 TetherMode _tether_mode; 00491 bool _arc_viewpoints; 00492 bool _auto_vp_duration; 00493 double _min_vp_duration_s, _max_vp_duration_s; 00494 }; 00495 00496 public: 00497 EarthManipulator(); 00498 EarthManipulator( const EarthManipulator& rhs ); 00499 00503 void applySettings( Settings* settings ); 00504 00508 Settings* getSettings() const; 00509 00513 Viewpoint getViewpoint() const; 00514 00518 virtual void setViewpoint( const Viewpoint& vp, double duration_s =0.0 ); 00519 00523 void setHomeViewpoint( const Viewpoint& vp, double duration_s = 0.0 ); 00524 00533 void setTetherNode( osg::Node* node ); 00534 00539 osg::Node* getTetherNode() const; 00540 00545 const osgEarth::SpatialReference* getSRS() const; 00546 00550 virtual void pan( double dx, double dy ); 00551 00555 virtual void rotate( double dx, double dy ); 00556 00560 virtual void zoom( double dx, double dy ); 00561 00565 virtual void drag( double dx, double dy, osg::View* view); 00566 00578 bool screenToWorld(float x, float y, osg::View* view, osg::Vec3d& out_coords ) const; 00579 00583 double getDistance() const { return _distance; } 00584 00590 void setDistance( double distance); 00591 00595 const osg::Quat& getRotation() { return _rotation; } 00596 00600 void setRotation( const osg::Quat& rotation) { _rotation = rotation; } 00601 00602 00603 public: // osgGA::MatrixManipulator 00604 00605 virtual const char* className() const { return "EarthManipulator"; } 00606 00608 virtual void setByMatrix(const osg::Matrixd& matrix); 00609 00611 virtual void setByInverseMatrix(const osg::Matrixd& matrix) { setByMatrix(osg::Matrixd::inverse(matrix)); } 00612 00614 virtual osg::Matrixd getMatrix() const; 00615 00617 virtual osg::Matrixd getInverseMatrix() const; 00618 00619 // Gets the stereo convergance mode. 00620 virtual osgUtil::SceneView::FusionDistanceMode getFusionDistanceMode() const { return osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE; } 00621 00622 // Gets the stereo convergance distance. 00623 virtual float getFusionDistanceValue() const { return _distance; } 00624 00625 // Attach a node to the manipulator. 00626 virtual void setNode(osg::Node*); 00627 00628 // Gets the node to which this manipulator is attached. 00629 virtual osg::Node* getNode(); 00630 00631 // Move the camera to the default position. 00632 virtual void home(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); 00633 00634 // Start/restart the manipulator. 00635 virtual void init(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); 00636 00637 // handle events, return true if handled, false otherwise. 00638 virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us); 00639 00640 // Get the keyboard and mouse usage of this manipulator. 00641 virtual void getUsage(osg::ApplicationUsage& usage) const; 00642 00643 virtual void computeHomePosition(); 00644 00645 00646 protected: 00647 00648 virtual ~EarthManipulator(); 00649 00650 bool intersect(const osg::Vec3d& start, const osg::Vec3d& end, osg::Vec3d& intersection) const; 00651 00652 // resets the mouse event stack and pushes the provided event. 00653 void resetMouse( osgGA::GUIActionAdapter& ); 00654 00655 // Reset the internal event stack. 00656 void flushMouseEventStack(); 00657 00658 // Add the current mouse osgGA::GUIEvent to internal stack. 00659 void addMouseEvent(const osgGA::GUIEventAdapter& ea); 00660 00661 // sets the camera position by doing a "look at" calculation. This is only used for 00662 // the "home" function at the moment -- look into depcrecation -GW 00663 void setByLookAt(const osg::Vec3d& eye, const osg::Vec3d& lv, const osg::Vec3d& up); 00664 00665 // Applies an action using the raw input parameters. 00666 bool handleAction( const Action& action, double dx, double dy, double duration ); 00667 00668 bool handleMouseAction( const Action& action, osg::View* view ); 00669 bool handleMouseClickAction( const Action& action ); 00670 bool handleKeyboardAction( const Action& action, double duration_s = DBL_MAX ); 00671 bool handleScrollAction( const Action& action, double duration_s = DBL_MAX ); 00672 bool handlePointAction( const Action& type, float mx, float my, osg::View* view ); 00673 void handleContinuousAction( const Action& action, osg::View* view ); 00674 void handleMovementAction( const ActionType& type, double dx, double dy, 00675 osg::View* view ); 00676 00677 // checks to see whether the mouse is "moving". 00678 bool isMouseMoving(); 00679 00680 // This sets the camera's roll based on your location on the globe. 00681 void recalculateRoll(); 00682 00683 private: 00684 00685 enum TaskType 00686 { 00687 TASK_NONE, 00688 TASK_PAN, 00689 TASK_ROTATE, 00690 TASK_ZOOM 00691 }; 00692 00693 struct Task : public osg::Referenced 00694 { 00695 Task() : _type(TASK_NONE) { } 00696 void set( TaskType type, double dx, double dy, double duration =DBL_MAX ) { 00697 _type = type; _dx = dx; _dy = dy; _duration_s = duration; 00698 } 00699 TaskType _type; 00700 double _dx, _dy; 00701 double _duration_s; 00702 }; 00703 00704 // "ticks" the resident Task, which allows for multi-frame animation of navigation 00705 // movements. 00706 bool serviceTask(); 00707 00708 void recalculateLocalPitchAndAzimuth(); 00709 double getAzimuth() const; 00710 00711 void recalculateCenter( const osg::CoordinateFrame& frame ); 00712 00713 osg::Matrixd getRotation(const osg::Vec3d& center) const; 00714 osg::Quat makeCenterRotation(const osg::Vec3d& center) const 00715 { 00716 return getRotation(center).getRotate().inverse(); 00717 } 00718 00719 void updateTether(); 00720 00721 void updateSetViewpoint(); 00722 00723 void updateHandCam( const osg::Timer_t& now ); 00724 00725 bool isMouseClick( const osgGA::GUIEventAdapter* mouse_up_event ) const; 00726 00727 void applyOptionsToDeltas( const Action& action, double& dx, double& dy ); 00728 00729 void configureDefaultSettings(); 00730 00731 void reinitialize(); 00732 00733 bool established(); 00734 00735 osg::CoordinateFrame getMyCoordinateFrame( const osg::Vec3d& position ) const; 00736 00737 private: 00738 // makeshift "stack" of the last 2 incoming events. 00739 osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t1; 00740 osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t0; 00741 00742 osg::ref_ptr<const osgGA::GUIEventAdapter> _mouse_down_event; 00743 00744 //osg::ref_ptr<osg::Node> _node; 00745 osg::observer_ptr<osg::Node> _node; 00746 osg::observer_ptr<osg::CoordinateSystemNode> _csn; 00747 #ifdef USE_OBSERVER_NODE_PATH 00748 osg::ObserverNodePath _csnObserverPath; 00749 #endif 00750 osg::NodePath _csnPath; 00751 00752 osg::ref_ptr<const osgEarth::SpatialReference> _cached_srs; 00753 bool _is_geocentric; 00754 bool _srs_lookup_failed; 00755 00756 osg::observer_ptr<osg::Node> _tether_node; 00757 00758 double _time_s_last_frame; 00759 double _time_s_now; 00760 osg::Timer_t _now; 00761 double _delta_t; 00762 double _t_factor; 00763 bool _thrown; 00764 // The world coordinate of the Viewpoint focal point. 00765 osg::Vec3d _center; 00766 // The rotation (heading and pitch) of the camera in the 00767 // earth-local frame. 00768 osg::Quat _rotation; 00769 // The rotation that makes the camera look down on the focal 00770 // point on the earth. This is equivalent to a rotation by 00771 // latitude, longitude. 00772 osg::Quat _centerRotation; 00773 double _distance; 00774 double _offset_x; 00775 double _offset_y; 00776 osg::Vec3d _previousUp; 00777 osg::ref_ptr<Task> _task; 00778 osg::Timer_t _time_last_frame; 00779 double _local_pitch; 00780 double _local_azim; 00781 00782 bool _continuous; 00783 double _continuous_dx; 00784 double _continuous_dy; 00785 00786 double _single_axis_x; 00787 double _single_axis_y; 00788 00789 // the "pending" viewpoint is only used to enable setting the 00790 // viewpoint before the frame loop starts 00791 bool _has_pending_viewpoint; 00792 Viewpoint _pending_viewpoint; 00793 double _pending_viewpoint_duration_s; 00794 00795 bool _setting_viewpoint; 00796 Viewpoint _start_viewpoint; 00797 double _delta_heading, _delta_pitch, _delta_range, _arc_height; 00798 osg::Vec3d _delta_focal_point; 00799 double _time_s_set_viewpoint; 00800 double _set_viewpoint_duration_s; 00801 double _set_viewpoint_accel; 00802 double _set_viewpoint_accel_2; 00803 00804 bool _after_first_frame; 00805 00806 osg::ref_ptr<Settings> _settings; 00807 00808 osgEarth::optional<Viewpoint> _homeViewpoint; 00809 double _homeViewpointDuration; 00810 00811 Action _last_action; 00812 // to support updating the camera after the update traversal (e.g., for tethering) 00813 osg::observer_ptr<osg::Camera> _viewCamera; 00814 00815 struct CameraPostUpdateCallback : public osg::NodeCallback { 00816 CameraPostUpdateCallback(EarthManipulator* m) : _m(m) { } 00817 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { _m->postUpdate(); traverse(node,nv); } 00818 EarthManipulator* _m; 00819 }; 00820 void postUpdate(); 00821 friend struct CameraUpdateCallback; 00822 00823 osg::observer_ptr<CameraPostUpdateCallback> _cameraUpdateCB; 00824 00825 void updateCamera( osg::Camera* eventCamera ); 00826 // Support snappy transition when the pointer leaves and 00827 // returns to earth during a drag 00828 osg::Vec3d _lastPointOnEarth; 00829 00830 }; 00831 00832 } } // namespace osgEarth::Util 00833 00834 #endif // OSGEARTHUTIL_EARTHMANIPULATOR