osgEarth 2.1.1

/home/cube/sources/osgearth/src/osgEarthUtil/EarthManipulator

Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines