1038 lines
42 KiB
Plaintext
1038 lines
42 KiB
Plaintext
|
/* -*-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();
|
||
|
};
|
||
|
|
||
|
} }
|