DYT/Tool/OpenSceneGraph-3.6.5/include/osgEarth/EarthManipulator

1038 lines
42 KiB
Plaintext
Raw Permalink Normal View History

2024-12-24 23:49:36 +00:00
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#pragma once
#include <osgEarth/Common>
#include <osgEarth/Common>
#include <osgEarth/Viewpoint>
#include <osgEarth/GeoData>
#include <osgEarth/Revisioning>
#include <osgEarth/Terrain>
#include <osgEarth/MapNode>
#include <osg/Timer>
#include <osg/ArgumentParser>
#include <osgGA/CameraManipulator>
#include <map>
#include <list>
#include <utility>
namespace osgEarth { namespace Util
{
/**
* A programmable manipulator suitable for use with geospatial terrains.
*
* You can use the "Settings" class to define custom input device bindings
* and navigation parameters. Create one or more of these and call
* applySettings() to "program" the manipulator at runtime.
*/
class OSGEARTH_EXPORT EarthManipulator : public osgGA::CameraManipulator
{
public:
/** Bindable manipulator actions. */
enum ActionType {
ACTION_NULL,
ACTION_HOME,
ACTION_GOTO,
ACTION_PAN,
ACTION_PAN_LEFT,
ACTION_PAN_RIGHT,
ACTION_PAN_UP,
ACTION_PAN_DOWN,
ACTION_ROTATE,
ACTION_ROTATE_LEFT,
ACTION_ROTATE_RIGHT,
ACTION_ROTATE_UP,
ACTION_ROTATE_DOWN,
ACTION_ZOOM,
ACTION_ZOOM_IN,
ACTION_ZOOM_OUT,
ACTION_EARTH_DRAG
};
/** Vector of action types */
typedef std::vector<ActionType> ActionTypeVector;
/** Bindable event types. */
enum EventType {
EVENT_MOUSE_DOUBLE_CLICK = osgGA::GUIEventAdapter::DOUBLECLICK,
EVENT_MOUSE_DRAG = osgGA::GUIEventAdapter::DRAG,
EVENT_KEY_DOWN = osgGA::GUIEventAdapter::KEYDOWN,
EVENT_SCROLL = osgGA::GUIEventAdapter::SCROLL,
EVENT_MOUSE_CLICK = osgGA::GUIEventAdapter::USER << 1,
EVENT_MULTI_DRAG = osgGA::GUIEventAdapter::USER << 2, // drag with 2 fingers
EVENT_MULTI_PINCH = osgGA::GUIEventAdapter::USER << 3, // pinch with 2 fingers
EVENT_MULTI_TWIST = osgGA::GUIEventAdapter::USER << 4, // drag 2 fingers in different directions
EVENT_TOUCH_DRAG = osgGA::GUIEventAdapter::USER << 5 // drag 1 finger or pen with touch-screen
};
/** Bindable mouse buttons. */
enum MouseEvent {
MOUSE_LEFT_BUTTON = osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON,
MOUSE_MIDDLE_BUTTON = osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON,
MOUSE_RIGHT_BUTTON = osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON
};
/** Action options. Certain options are only meaningful to certain Actions.
See the bind* documentation for information. */
enum ActionOptionType {
OPTION_SCALE_X, // Sensitivity multiplier for horizontal input movements
OPTION_SCALE_Y, // Sensitivity multiplier for vertical input movements
OPTION_CONTINUOUS, // Whether to act as long as the button or key is depressed
OPTION_SINGLE_AXIS, // If true, only operate on one axis at a time (the one with the larger value)
OPTION_GOTO_RANGE_FACTOR, // for ACTION_GOTO, multiply the Range by this factor (to zoom in/out)
OPTION_DURATION // Time it takes to complete the action (in seconds)
};
/** Tethering options **/
enum TetherMode
{
TETHER_CENTER, // The camera will follow the center of the node.
TETHER_CENTER_AND_ROTATION, // The camera will follow the node and all rotations made by the node
TETHER_CENTER_AND_HEADING // The camera will follow the node and only follow heading rotation
};
/** Camera projection matrix type **/
enum CameraProjection
{
PROJ_PERSPECTIVE,
PROJ_ORTHOGRAPHIC
};
struct OSGEARTH_EXPORT ActionOption {
ActionOption() { }
ActionOption( int option, bool value ) : _option(option), _bool_value(value) { }
ActionOption( int option, int value ) : _option(option), _int_value(value) { }
ActionOption( int option, double value ) : _option(option), _dbl_value(value) { }
int option() const { return _option; }
bool boolValue() const { return _bool_value; }
int intValue() const { return _int_value; }
double doubleValue() const { return _dbl_value; }
private:
int _option;
union {
bool _bool_value;
int _int_value;
double _dbl_value;
};
};
struct OSGEARTH_EXPORT ActionOptions : public std::vector<ActionOption> {
void add( int option, bool value ) { push_back( ActionOption(option,value) ); }
void add( int option, int value ) { push_back( ActionOption(option,value) ); }
void add( int option, double value) { push_back( ActionOption(option,value) ); }
};
protected:
struct InputSpec
{
InputSpec( int event_type, int input_mask, int modkey_mask )
: _event_type(event_type), _input_mask(input_mask), _modkey_mask( modkey_mask ) { }
InputSpec( const InputSpec& rhs )
: _event_type(rhs._event_type), _input_mask(rhs._input_mask), _modkey_mask(rhs._modkey_mask) { }
bool operator == ( const InputSpec& rhs ) const {
return _event_type == rhs._event_type &&
_input_mask == rhs._input_mask &&
((_modkey_mask|osgGA::GUIEventAdapter::MODKEY_NUM_LOCK) == (rhs._modkey_mask|osgGA::GUIEventAdapter::MODKEY_NUM_LOCK));
}
inline bool operator < (const InputSpec& rhs) const {
if ( _event_type < rhs._event_type) return true;
else if ( _event_type > rhs._event_type ) return false;
else if ( _input_mask < rhs._input_mask ) return true;
else if ( _input_mask > rhs._input_mask ) return false;
else return ( _modkey_mask < rhs._modkey_mask );
}
int _event_type;
int _input_mask;
int _modkey_mask;
};
typedef std::list<InputSpec> InputSpecs;
enum Direction {
DIR_NA,
DIR_LEFT,
DIR_RIGHT,
DIR_UP,
DIR_DOWN
};
struct Action
{
Action( ActionType type =ACTION_NULL );
Action( ActionType type, const ActionOptions& options );
Action( const Action& rhs );
ActionType _type;
Direction _dir;
ActionOptions _options;
bool getBoolOption( int option, bool defaultValue ) const;
int getIntOption( int option, int defaultValue ) const;
double getDoubleOption( int option, double defaultValue ) const;
private:
void init();
};
void dumpActionInfo( const Action& action, osg::NotifySeverity level ) const;
static Action NullAction;
public:
class OSGEARTH_EXPORT Settings : public osg::Referenced, public Revisioned
{
public:
// construct with default settings
Settings();
// copy ctor
Settings( const Settings& rhs );
/** dtor */
virtual ~Settings() { }
// look for settings in an AP
void apply(osg::ArgumentParser& args);
/**
* Assigns behavior to the action of dragging the mouse while depressing one or
* more mouse buttons and modifier keys.
*
* @param action
* The EarthManipulator::ActionType value to which to bind this mouse
* input specification.
*
* @param button_mask
* Mask of osgGA::GUIEventAdapter::MouseButtonMask values
*
* @param modkey_mask (default = 0L)
* A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key
* combination to associate with the action.
*
* @param options
* Action options. Valid options are:
* OPTION_CONTINUOUS, OPTION_SCALE_X, OPTION_SCALE_Y
*/
void bindMouse(
ActionType action, int button_mask,
int modkey_mask = 0L,
const ActionOptions& options =ActionOptions() );
/**
* Assigns a bevahior to the action of clicking one or more mouse buttons.
*
* @param action
* The EarthManipulator::ActionType value to which to bind this mouse click
* input specification.
*
* @param button_mask
* Mask of osgGA::GUIEventAdapter::MouseButtonMask values
*
* @param modkey_mask (default = 0L)
* A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key
* combination to associate with the action.
*
* @param options
* Action options. Valid options are:
* OPTION_GOTO_RANGE_FACTOR, OPTION_DURATION
*/
void bindMouseClick(
ActionType action, int button_mask,
int modkey_mask =0L,
const ActionOptions& options =ActionOptions() );
/**
* Assigns a bevahior to the action of double-clicking one or more mouse buttons.
*
* @param action
* The EarthManipulator::ActionType value to which to bind this double-click
* input specification.
*
* @param button_mask
* Mask of osgGA::GUIEventAdapter::MouseButtonMask values
*
* @param modkey_mask (default = 0L)
* A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key
* combination to associate with the action.
*
* @param options
* Action options. Valid options are:
* OPTION_GOTO_RANGE_FACTOR, OPTION_DURATION
*/
void bindMouseDoubleClick(
ActionType action, int button_mask,
int modkey_mask =0L,
const ActionOptions& options =ActionOptions() );
/**
* Assigns a bevahior to the action of depressing a key.
*
* @param action
* The EarthManipulator::ActionType value to which to bind this key
* input specification.
*
* @param key
* A osgGA::GUIEventAdapter::KeySymbol value
*
* @param modkey_mask (default = 0L)
* A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key
* combination to associate with the action.
*
* @param options
* Action options. Valid options are:
* OPTION_CONTINUOUS
*/
void bindKey(
ActionType action, int key,
int modkey_mask =0L,
const ActionOptions& options =ActionOptions() );
/**
* Assigns a bevahior to operation of the mouse's scroll wheel.
*
* @param action
* The EarthManipulator::ActionType value to which to bind this scroll
* input specification.
*
* @param scrolling_motion
* A osgGA::GUIEventAdapter::ScrollingMotion value
*
* @param modkey_mask (default = 0L)
* A mask of osgGA::GUIEventAdapter::ModKeyMask values defining a modifier key
* combination to associate with the action.
*
* @param options
* Action options. Valid options are:
* OPTION_SCALE_Y, OPTION_DURATION
*/
void bindScroll(
ActionType action, int scrolling_motion,
int modkey_mask =0L,
const ActionOptions& options =ActionOptions() );
void bindPinch(
ActionType action, const ActionOptions& =ActionOptions() );
void bindTwist(
ActionType action, const ActionOptions& =ActionOptions() );
void bindMultiDrag(
ActionType action, const ActionOptions& =ActionOptions() );
void bindTouchDrag(
ActionType action, const ActionOptions& =ActionOptions() );
/**
* Sets an overall mouse sensitivity factor.
*
* @param value
* A scale factor to apply to mouse readings.
* 1.0 = default; < 1.0 = less sensitive; > 1.0 = more sensitive.
*/
void setMouseSensitivity( double value ) { _mouse_sens = value; }
double getMouseSensitivity() const { return _mouse_sens; }
double& mouseSensitivity() { return _mouse_sens; }
/**
* Sets an overall touch sensitivity factor.
*
* @param value
* A scale factor to apply to mouse readings.
* 0.005 = default; < 0.005 = less sensitive; > 0.005 = more sensitive.
*/
void setTouchSensitivity( double value ) { _touch_sens = value; }
double getTouchSensitivity() const { return _touch_sens; }
double& touchSensitivity() { return _touch_sens; }
/**
* Sets the keyboard action sensitivity factor. This applies to navigation actions
* that are bound to keyboard events. For example, you may bind the LEFT arrow to
* the ACTION_PAN_LEFT action; this factor adjusts how much panning will occur during
* each frame that the key is depressed.
*
* @param value
* A scale factor to apply to keyboard-controller navigation.
* 1.0 = default; < 1.0 = less sensitive; > 1.0 = more sensitive.
*/
void setKeyboardSensitivity( double value ) { _keyboard_sens = value; }
double getKeyboardSensitivity() const { return _keyboard_sens; }
double& keyboardSensitivity() { return _keyboard_sens; }
/**
* Sets the scroll-wheel sensitivity factor. This applies to navigation actions
* that are bound to scrolling events. For example, you may bind the scroll wheel to
* the ACTION_ZOOM_IN action; this factor adjusts how much zooming will occur each time
* you click the scroll wheel.
*
* @param value
* A scale factor to apply to scroll-wheel-controlled navigation.
* 1.0 = default; < 1.0 = less sensitive; > 1.0 = more sensitive.
*/
void setScrollSensitivity( double value ) { _scroll_sens = value; }
double getScrollSensitivity() const { return _scroll_sens; }
double& scrollSensitivity() { return _scroll_sens; }
/**
* When set to true, prevents simultaneous control of pitch and azimuth.
*
* Usually you can alter pitch and azimuth at the same time. When this flag
* is set, you can only control one at a time - if you start slewing the azimuth of the camera,
* the pitch stays locked until you stop moving and then start slewing the pitch.
*
* Default = false.
*/
void setSingleAxisRotation( bool value ) { _single_axis_rotation = value; }
bool getSingleAxisRotation() const { return _single_axis_rotation; }
bool& singleAxisRotation() { return _single_axis_rotation; }
/**
* Sets whether to lock in a camera heading when performing panning operations (i.e.,
* changing the focal point).
*/
void setLockAzimuthWhilePanning( bool value ) { _lock_azim_while_panning = value; }
bool getLockAzimuthWhilePanning() const { return _lock_azim_while_panning; }
bool& lockAzimuthWhilePanning() { return _lock_azim_while_panning; }
/**
* Sets the minimum and maximum allowable local camera pitch, in degrees.
*
* By "local" we mean relative to the tangent plane passing through the focal point on
* the surface of the terrain.
*
* Defaults are: Min = -90, Max = -10.
*/
void setMinMaxPitch( double min_pitch, double max_pitch );
/** Gets the minimum allowable local pitch, in degrees. */
double getMinPitch() const { return _min_pitch; }
/** Gets the maximum allowable local pitch, in degrees. */
double getMaxPitch() const { return _max_pitch; }
/** Gets the max x offset in world coordinates */
double getMaxXOffset() const { return _max_x_offset; }
/** Gets the max y offset in world coordinates */
double getMaxYOffset() const { return _max_y_offset; }
/** Gets the minimum distance from the focal point in world coordinates */
double getMinDistance() const {return _min_distance; }
/** Gets the maximum distance from the focal point in world coordinates */
double getMaxDistance() const {return _max_distance; }
/** Sets the min and max distance from the focal point in world coordinates */
void setMinMaxDistance( double min_distance, double max_distance);
/**
* Sets the maximum allowable offsets for the x and y camera offsets in world coordinates
*/
void setMaxOffset(double max_x_offset, double max_y_offset);
/** Mode used for tethering to a node. */
void setTetherMode( TetherMode value ) { _tether_mode = value; }
TetherMode getTetherMode() const { return _tether_mode; }
TetherMode& tetherMode() { return _tether_mode; }
/** Access to the list of Actions that will automatically break a tether */
ActionTypeVector& getBreakTetherActions() { return _breakTetherActions; }
const ActionTypeVector& getBreakTetherActions() const { return _breakTetherActions; }
/** Whether a setViewpoint transition whould "arc" */
void setArcViewpointTransitions( bool value );
bool getArcViewpointTransitions() const { return _arc_viewpoints; }
/** Activates auto-duration for transitioned viewpoints. */
void setAutoViewpointDurationEnabled( bool value );
bool getAutoViewpointDurationEnabled() const { return _auto_vp_duration; }
void setAutoViewpointDurationLimits( double minSeconds, double maxSeconds );
void getAutoViewpointDurationLimits( double& out_minSeconds, double& out_maxSeconds ) const {
out_minSeconds = _min_vp_duration_s;
out_maxSeconds = _max_vp_duration_s;
}
/** Whether to automatically adjust an orthographic camera so that it "tracks" the last known FOV and Aspect Ratio. */
bool getOrthoTracksPerspective() const { return _orthoTracksPerspective; }
void setOrthoTracksPerspective(bool value) { _orthoTracksPerspective = value; }
bool& orthoTracksPerspective() { return _orthoTracksPerspective; }
/** Whether or not to keep the camera from going through the terrain surface */
bool getTerrainAvoidanceEnabled() const { return _terrainAvoidanceEnabled; }
void setTerrainAvoidanceEnabled( bool value ) { _terrainAvoidanceEnabled = value; }
bool& terrainAvoidanceEnabled() { return _terrainAvoidanceEnabled; }
/** Minimum range for terrain avoidance checks in world coordinates */
double getTerrainAvoidanceMinimumDistance() const {return _terrainAvoidanceMinDistance; }
void setTerrainAvoidanceMinimumDistance(double minDistance) { _terrainAvoidanceMinDistance = minDistance; }
double& terrainAvoidanceMinimumDistance() { return _terrainAvoidanceMinDistance; }
void setThrowingEnabled(bool throwingEnabled) { _throwingEnabled = throwingEnabled; }
bool getThrowingEnabled () const { return _throwingEnabled; }
bool& throwingEnabled() { return _throwingEnabled; }
void setThrowDecayRate(double throwDecayRate) { _throwDecayRate = osg::clampBetween(throwDecayRate, 0.0, 1.0); }
double getThrowDecayRate () const { return _throwDecayRate; }
double& throwDecayRate() { return _throwDecayRate; }
void setZoomToMouse(bool value) { _zoomToMouse = value; }
bool getZoomToMouse() const { return _zoomToMouse; }
bool& zoomToMouse() { return _zoomToMouse; }
private:
friend class EarthManipulator;
typedef std::pair<InputSpec,Action> ActionBinding;
typedef std::map<InputSpec,Action> ActionBindings;
// Gets the action bound to the provided input specification, or NullAction if there is
// to matching binding.
const Action& getAction( int event_type, int input_mask, int modkey_mask ) const;
void expandSpec( const InputSpec& input, InputSpecs& output ) const;
void bind( const InputSpec& spec, const Action& action );
private:
ActionBindings _bindings;
bool _single_axis_rotation;
bool _lock_azim_while_panning;
double _mouse_sens;
double _keyboard_sens;
double _scroll_sens;
double _touch_sens;
double _min_pitch;
double _max_pitch;
double _max_x_offset;
double _max_y_offset;
double _min_distance;
double _max_distance;
TetherMode _tether_mode;
ActionTypeVector _breakTetherActions;
bool _arc_viewpoints;
bool _auto_vp_duration;
double _min_vp_duration_s, _max_vp_duration_s;
bool _orthoTracksPerspective;
bool _terrainAvoidanceEnabled;
double _terrainAvoidanceMinDistance;
bool _throwingEnabled;
double _throwDecayRate;
bool _zoomToMouse;
};
public:
EarthManipulator();
EarthManipulator(osg::ArgumentParser& args);
EarthManipulator(const EarthManipulator& rhs);
/**
* Applies a new settings object to the manipulator, which takes effect immediately.
*/
void applySettings( Settings* settings );
/**
* Gets a handle on the current manipulator settings object.
*/
Settings* getSettings() const;
/**
* Gets the current camera position.
*/
Viewpoint getViewpoint() const;
/**
* Sets the camera position, optionally moving it there over time.
*/
virtual void setViewpoint( const Viewpoint& vp, double duration_s =0.0 );
/**
* Cancels a call to setViewpoint that resulted in an ongoing transition OR
* attachment to a node.
*/
void clearViewpoint();
/**
* Sets the viewpoint to activate when performing the ACTION_HOME action.
*/
void setHomeViewpoint( const Viewpoint& vp, double duration_s = 0.0 );
/**
* Whether the manipulator is performing a viewpoint transition.
*/
bool isSettingViewpoint() const;
/**
* Whether the view is tethered to a node.
*/
bool isTethering() const;
/**
* Sets a callback to be invoked upon a tether or tether break
*/
class TetherCallback : public osg::Referenced
{
public:
virtual void operator()(osg::Node* tetherNode) { }
protected:
virtual ~TetherCallback() { }
};
void setTetherCallback(TetherCallback* cb) { _tetherCallback = cb; }
TetherCallback* getTetherCallback() { return _tetherCallback.get(); }
/**
* Post-camera-update callback; use to access the camera position after
* the call to updateCamera (for frame synchronization)
*/
class UpdateCameraCallback : public osg::Referenced
{
public:
virtual void onUpdateCamera(const osg::Camera*) { }
protected:
virtual ~UpdateCameraCallback() { }
};
void setUpdateCameraCallback(UpdateCameraCallback* cb) { _updateCameraCallback = cb; }
UpdateCameraCallback* getUpdateCameraCallback() { return _updateCameraCallback.get(); }
/**
* Move the focal point of the camera using deltas (normalized screen coords).
*/
virtual void pan( double dx, double dy );
/**
* Rotate the camera (dx = azimuth, dy = pitch) using deltas (radians).
*/
virtual void rotate( double dx, double dy );
/**
* Zoom the camera using deltas (dy only)
*/
virtual void zoom( double dx, double dy, osg::View* view );
/**
* Drag the earth using deltas
*/
virtual void drag( double dx, double dy, osg::View* view);
/**
* Converts screen coordinates (relative to the view's viewpoint) to world
* coordinates. Note, this method will use the mask set by setTraversalMask().
*
* @param x, y
* Viewport coordinates
* @param view
* View for which to calculate world coordinates
* @param out_coords
* Output world coordinates (only valid if the method returns true)
*/
bool screenToWorld(float x, float y, osg::View* view, osg::Vec3d& out_coords ) const;
/**
* Gets the distance from the focal point in world coordiantes
*/
double getDistance() const { return _distance; }
/**
* Sets the distance from the focal point in world coordinates.
*
* The incoming distance value will be clamped within the valid range specified by the settings.
*/
void setDistance( double distance);
/**
* Gets the rotation of the manipulator. Note: This rotation is in addition to the rotation needed to center the view on the focal point.
*/
const osg::Quat& getRotation() { return _rotation; }
/**
* Sets the rotation of the manipulator. Note: This rotation is in addition to the rotation needed to center the view on the focal point.
*/
void setRotation( const osg::Quat& rotation) { _rotation = rotation; }
/**
* Gets the traversal node mask used to find root MapNode and CoordinateSystemNodes. Default is 0x1.
*/
osg::Node::NodeMask getFindNodeTraversalMask( ) { return _findNodeTraversalMask; }
/**
* Sets the traversal node mask used to find root MapNode and CoordinateSystemNode. Default is 0x1.
* Use this method if you change MapNode or CoordinateSystemNode mask and want manipulator to work with them correctly.
*/
void setFindNodeTraversalMask( const osg::Node::NodeMask & nodeMask ) { _findNodeTraversalMask = nodeMask; }
/**
* Expressly set the initial vertical FOV.
* If the manipulator detects that the camera has switched from persective
* to orthographic projection, it will use the last know VFOV of the perspective
* projection to match the zoom level in orthographic mode. However, if you start
* in orthographic mode, it doesn't have this information; you can provide it
* with this method.
*/
void setInitialVFOV(double vfov);
/**
* The last detected VFOV of a perspective camera (or the initial FOV if started in ortho)
*/
double getLastKnownVFOV() const { return _lastKnownVFOV; }
/**
* Assigns a NodeVisitor to use when OSG calls updateCamera() at the end of
* the update traversal. This is useful if you have a Transform subclass that
* overrides Transform::computeLocalToWorldMatrix and needs access to a
* NodeVisitor.
*/
void setUpdateCameraNodeVisitor(osg::NodeVisitor* nv);
public: // osgGA::CameraManipulator
virtual const char* className() const { return "EarthManipulator"; }
/** set the position of the matrix manipulator using a 4x4 Matrix.*/
virtual void setByMatrix(const osg::Matrixd& matrix);
/** set the position of the matrix manipulator using a 4x4 Matrix.*/
virtual void setByInverseMatrix(const osg::Matrixd& matrix) { setByMatrix(osg::Matrixd::inverse(matrix)); }
/** get the position of the manipulator as 4x4 Matrix.*/
virtual osg::Matrixd getMatrix() const;
/** get the position of the manipulator as a inverse matrix of the manipulator, typically used as a model view matrix.*/
virtual osg::Matrixd getInverseMatrix() const;
/** update the camera with the current values from this manipulator. Overloaded to support tethering, this method is
called by Viewer or ComppositeViewer at the end of the update traversal. */
virtual void updateCamera(osg::Camera& camera);
// Gets the stereo convergance mode.
virtual osgUtil::SceneView::FusionDistanceMode getFusionDistanceMode() const { return osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE; }
// Gets the stereo convergance distance.
virtual float getFusionDistanceValue() const { return _distance; }
// Attach a node to the manipulator.
virtual void setNode(osg::Node*);
// Gets the node to which this manipulator is attached.
virtual osg::Node* getNode();
// Move the camera to the default position.
virtual void home(double /*unused*/);
virtual void home(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
// Start/restart the manipulator.
virtual void init(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
// handle events, return true if handled, false otherwise.
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);
// Get the keyboard and mouse usage of this manipulator.
virtual void getUsage(osg::ApplicationUsage& usage) const;
virtual void computeHomePosition(const osg::Camera *camera = NULL, bool useBoundingBox = false);
// react to a tile-added event from the Terrain
virtual void handleTileUpdate(const TileKey& key, osg::Node* tile, TerrainCallbackContext& context);
// returns the absolute Euler angles composited from the composite rotation matrix.
void getCompositeEulerAngles( double* out_azim, double* out_pitch =0L ) const;
protected:
virtual ~EarthManipulator();
bool intersect(const osg::Vec3d& start, const osg::Vec3d& end, osg::Vec3d& intersection, osg::Vec3d& normal) const;
bool intersectLookVector(osg::Vec3d& eye, osg::Vec3d& out_target, osg::Vec3d& up) const;
// resets the mouse event stack and pushes the provided event.
void resetMouse( osgGA::GUIActionAdapter& aa, bool flushEventStack=true);
// Reset the internal event stack.
void flushMouseEventStack();
// Add the current mouse osgGA::GUIEvent to internal stack.
void addMouseEvent(const osgGA::GUIEventAdapter& ea);
// sets the camera position by doing a "look at" calculation, converting the center
// point into a look vector and intersecting the terrain.
void setByLookAt(const osg::Vec3d& eye, const osg::Vec3d& center, const osg::Vec3d& up);
// sets the camera position by doing a "look at" calculation, but takes the target point
// "as-is" and does not try to find an intersection.
void setByLookAtRaw(const osg::Vec3d& eye, const osg::Vec3d& target, const osg::Vec3d& up);
// checks to see whether the mouse is "moving".
bool isMouseMoving();
// This sets the camera's roll based on your location on the globe.
void recalculateRoll();
// Gets the matrix without a pre-MapNode transform (i.e., map world space)
osg::Matrixd getWorldMatrix() const;
// Gets the inverse matrix without a pre-MapNode transform (i.e., map world space)
osg::Matrixd getWorldInverseMatrix() const;
protected:
enum TaskType
{
TASK_NONE,
TASK_PAN,
TASK_ROTATE,
TASK_ZOOM
};
struct Task : public osg::Referenced
{
Task() : _type(TASK_NONE) { }
void set( TaskType type, double dx, double dy, double duration, double now ) {
_type = type; _dx = dx; _dy = dy; _duration_s = duration; _time_last_service = now;
}
TaskType _type;
double _dx, _dy;
double _duration_s;
double _time_last_service;
};
// "ticks" the resident Task, which allows for multi-frame animation of navigation
// movements.
bool serviceTask(osg::View*);
// returns the Euler Angles baked into _rotation, the local frame's rotation quaternion.
void getEulerAngles(const osg::Quat& quat, double* azim, double* pitch) const;
// Makes a quaternion from an azimuth and pitch.
osg::Quat getQuaternion(double azim, double pitch) const;
/**
* Fire a ray from the current eyepoint along the current look vector,
* intersect the terrain at the closest point, and reset the matrix parameters
* based on that point.
*/
bool recalculateCenterFromLookVector();
void recalculateCenter(const osg::CoordinateFrame& frame);
osg::Matrixd getRotation(const osg::Vec3d& center) const;
osg::Quat computeCenterRotation(const osg::Vec3d& center) const;
void updateTether(double t);
void updateSetViewpoint();
bool isMouseClick( const osgGA::GUIEventAdapter* mouse_up_event ) const;
void applyOptionsToDeltas( const Action& action, double& dx, double& dy );
void configureDefaultSettings();
void reinitialize();
bool established();
// sets the new center (focal) point and recalculates it's L2W matrix.
void setCenter( const osg::Vec3d& center );
// creates a "local-to-world" transform relative to the input point.
bool createLocalCoordFrame( const osg::Vec3d& worldPos, osg::CoordinateFrame& out_frame ) const;
// returns an ActionType that would be initiated by the OSG UI event
ActionType getActionTypeForEvent( const osgGA::GUIEventAdapter& ea ) const;
public:
void recalculateCenter() { recalculateCenter(_centerLocalToWorld); }
const GeoPoint& centerMap() const { return _centerMap; }
protected:
typedef osgGA::GUIEventAdapter::TouchData::TouchPoint TouchPoint;
typedef std::vector<TouchPoint> MultiTouchPoint; // one per ID (finger/touchpoint)
typedef std::deque<MultiTouchPoint> MultiTouchPointQueue;
MultiTouchPointQueue _touchPointQueue;
struct TouchEvent {
TouchEvent() : _mbmask(0) { }
EventType _eventType;
unsigned _mbmask;
float _dx, _dy;
};
typedef std::vector<TouchEvent> TouchEvents;
void addTouchEvents( const osgGA::GUIEventAdapter& ea );
bool parseTouchEvents( TouchEvents& ev );
// Applies an action using the raw input parameters.
bool handleAction( const Action& action, double dx, double dy, double duration );
virtual bool handleMouseAction( const Action& action, osg::View* view );
virtual bool handleMouseClickAction( const Action& action );
virtual bool handleKeyboardAction( const Action& action, double duration_s = DBL_MAX );
virtual bool handleScrollAction( const Action& action, double duration_s = DBL_MAX );
virtual bool handlePointAction( const Action& type, float mx, float my, osg::View* view );
virtual void handleContinuousAction( const Action& action, osg::View* view );
virtual void handleMovementAction( const ActionType& type, double dx, double dy, osg::View* view );
protected:
// makeshift "stack" of the last 2 incoming events.
osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t1;
osg::ref_ptr<const osgGA::GUIEventAdapter> _ga_t0;
osg::ref_ptr<const osgGA::GUIEventAdapter> _mouse_down_event;
bool _pushed;
osg::observer_ptr<osg::Node> _node;
osg::observer_ptr<MapNode> _mapNode;
osg::ref_ptr<const osgEarth::SpatialReference> _srs;
double _time_s_now;
bool _thrown;
double _throw_dx;
double _throw_dy;
double _dx;
double _dy;
// The world coordinate of the Viewpoint focal point.
osg::Vec3d _center;
GeoPoint _centerMap;
double _centerHeight;
// local2world matrix for the center point.
osg::CoordinateFrame _centerLocalToWorld;
// Rotation offset to _rotation when tethering.
osg::Quat _tetherRotation;
// The initial offset applied to the tether rotation when orientation-tethering begins.
// This is usually just the inverse of the first-calculated _tetherRotation.
optional<osg::Quat> _tetherRotationOffset;
// The rotation (heading and pitch) of the camera in the
// earth-local frame defined by _centerRotation.
osg::Quat _rotation;
// The rotation that makes the camera look down on the focal
// point on the earth. This is equivalent to a rotation by
// latitude, longitude.
osg::Quat _centerRotation;
// distance from camera to center of rotation.
double _distance;
// XYZ offsets of the focal point in the local tangent plane coordinate system
// of the focal point.
osg::Vec3d _posOffset;
// XY offsets (left/right, down/up) of the focal point in the plane normal to
// the view heading.
osg::Vec2d _viewOffset;
osg::Vec3d _previousUp;
osg::ref_ptr<Task> _task;
osg::Timer_t _time_last_frame;
bool _continuous;
double _continuous_dx;
double _continuous_dy;
double _last_continuous_action_time;
double _single_axis_x;
double _single_axis_y;
// the "pending" viewpoint is only used to enable setting the
// viewpoint before the frame loop starts
optional<Viewpoint> _pendingViewpoint;
Duration _pendingViewpointDuration;
optional<Viewpoint> _setVP0; // Starting viewpoint
optional<Viewpoint> _setVP1; // Final viewpoint
optional<Duration> _setVPStartTime; // Time of call to setViewpoint
Duration _setVPDuration; // Transition time for setViewpoint
double _setVPAccel, _setVPAccel2; // Acceleration factors for setViewpoint
double _setVPArcHeight; // Altitude arcing height for setViewpoint
osg::Quat _tetherRotationVP0; // saves _tetherRotation at the start of a transition
osg::Quat _tetherRotationVP1; // target _tetherRotation if not tethered
TetherMode _lastTetherMode;
osg::Matrix _mapNodeFrame, _mapNodeFrameInverse;
// returns "t", the parametric coefficient of a timed transition. 1=finished.
double setViewpointFrame(double time_s);
void setLookAt(const osg::Vec3d& center, double azim, double pitch, double range, const osg::Vec3d& posoffset);
void resetLookAt();
void collapseTetherRotationIntoRotation();
unsigned _frameCount;
osg::ref_ptr<Settings> _settings;
osgEarth::optional<Viewpoint> _homeViewpoint;
double _homeViewpointDuration;
Action _last_action;
EventType _last_event;
double _time_s_last_event;
double _lastKnownVFOV;
/** updates a camera to switch between prospective and ortho. */
void updateProjection( osg::Camera* eventCamera );
// Support snappy transition when the pointer leaves and
// returns to earth during a drag
osg::Vec3d _lastPointOnEarth;
osg::ref_ptr< TerrainCallback > _terrainCallback;
// Traversal mask used in established and dtor methods to find MapNode and CoordinateSystemNode
osg::Node::NodeMask _findNodeTraversalMask;
osg::ref_ptr<TetherCallback> _tetherCallback;
osg::ref_ptr<UpdateCameraCallback> _updateCameraCallback;
bool _userWillCallUpdateCamera;
osg::observer_ptr<osg::NodeVisitor> _updateCameraNodeVisitor;
void collisionDetect();
void ctor_init();
};
} }