From Jan Peciva, additional comments, and standarisation of throw and handling of mouse wheel.

This commit is contained in:
Robert Osfield 2010-06-14 15:20:47 +00:00
parent 7f7cc83f3f
commit da60a3c615
9 changed files with 207 additions and 59 deletions

View File

@ -35,7 +35,34 @@
namespace osg {
/** Encapsulates OpenGL blend/transparency state. */
/** Encapsulates OpenGL blend/transparency state.
*
* Blending combines incoming fragment with a fragment
* already present in the target buffer.
*
* OpenGL 1.1 supports following source and destination blending factors:
* GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
* GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA,
* GL_ZERO, GL_ONE.
*
* Moreover, there are three source-only blending factors:
* GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA_SATURATE
* and two destination-only blending factors:
* GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR.
* OpenGL 1.4 allowed to use these five blending factors
* as both - source and destination blending factors.
*
* Following four source and destination blending factors
* were added by Imaging subset of OpenGL 1.2
* and made mandatory by OpenGL 1.4:
* GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR,
* GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA
*
* OpenGL 1.4 further provides glBlendFuncSeparate
* (promoted from GL_EXT_blend_func_separate).
* It makes possible to set blending functions for RGB and Alpha separately.
* Before, it was possible to set just one blending function for RGBA.
*/
class OSG_EXPORT BlendFunc : public StateAttribute
{
public :

View File

@ -188,6 +188,7 @@ class Vec3d
/** Normalize the vector so that it has length unity.
* Returns the previous length of the vector.
* If the vector is zero length, it is left unchanged and zero is returned.
*/
inline value_type normalize()
{

View File

@ -50,6 +50,11 @@ class OSGGA_EXPORT OrbitManipulator : public StandardManipulator
virtual void getTransformation( osg::Vec3d& eye, osg::Quat& rotation ) const;
virtual void getTransformation( osg::Vec3d& center, osg::Vec3d& eye, osg::Vec3d& up ) const;
void setHeading( double azimuth );
double getHeading() const;
void setElevation( double elevation );
double getElevation() const;
virtual void setCenter( const osg::Vec3d& center );
const osg::Vec3d& getCenter() const;
virtual void setRotation( const osg::Quat& rotation );

View File

@ -39,7 +39,7 @@ class OSGGA_EXPORT StandardManipulator : public CameraManipulator
UPDATE_MODEL_SIZE = 0x01,
COMPUTE_HOME_USING_BBOX = 0x02,
PROCESS_MOUSE_WHEEL = 0x04,
SET_CENTER_ON_WHEEL_UP = 0x08,
SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT = 0x08,
DEFAULT_SETTINGS = UPDATE_MODEL_SIZE | COMPUTE_HOME_USING_BBOX | PROCESS_MOUSE_WHEEL
};
@ -62,6 +62,8 @@ class OSGGA_EXPORT StandardManipulator : public CameraManipulator
virtual void setVerticalAxisFixed( bool value );
inline bool getVerticalAxisFixed() const;
inline bool getAllowThrow() const;
virtual void setAllowThrow( bool allowThrow );
virtual void setAnimationTime( const double t );
double getAnimationTime() const;
@ -113,6 +115,7 @@ class OSGGA_EXPORT StandardManipulator : public CameraManipulator
// mouse state
bool _thrown;
bool _allowThrow;
float _mouseCenterX, _mouseCenterY;
// internal event stack comprising last two mouse events.
@ -181,6 +184,12 @@ inline bool StandardManipulator::getVerticalAxisFixed() const
return _verticalAxisFixed;
}
/// Returns true if the camera can be thrown, false otherwise. It defaults to true.
inline bool StandardManipulator::getAllowThrow() const
{
return _allowThrow;
}
}

View File

@ -37,7 +37,7 @@ FirstPersonManipulator::FirstPersonManipulator( int flags )
setAcceleration( 0.25, true );
setMaxVelocity( 0.25, true );
setWheelMovement( 0.05, true );
if( _flags & SET_CENTER_ON_WHEEL_UP )
if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT )
setAnimationTime( 0.2 );
}
@ -233,50 +233,62 @@ void FirstPersonManipulator::init( const GUIEventAdapter& ea, GUIActionAdapter&
// doc in parent
bool FirstPersonManipulator::handleMouseWheel( const GUIEventAdapter& ea, GUIActionAdapter& us )
{
switch( ea.getScrollingMotion() ) {
osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion();
// mouse scroll up event
case GUIEventAdapter::SCROLL_UP: {
// handle centering
if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT )
{
if( _flags & SET_CENTER_ON_WHEEL_UP ) {
if( sm == GUIEventAdapter::SCROLL_DOWN && _wheelMovement > 0. ||
sm == GUIEventAdapter::SCROLL_UP && _wheelMovement < 0. )
{
// stop thrown animation
_thrown = false;
if( getAnimationTime() <= 0. )
// center by mouse intersection (no animation)
setCenterByMousePointerIntersection( ea, us );
// center by mouse intersection (no animation)
setCenterByMousePointerIntersection( ea, us );
else {
// start new animation only if there is no animation in progress
if( !isAnimating() )
startAnimationByMousePointerIntersection( ea, us );
// start new animation only if there is no animation in progress
if( !isAnimating() )
startAnimationByMousePointerIntersection( ea, us );
}
}
}
}
// move forward
moveForward( isAnimating() ? dynamic_cast< FirstPersonAnimationData* >( _animationData.get() )->_targetRot : _rotation,
_wheelMovement * (getRelativeFlag( _wheelMovementFlagIndex ) ? _modelSize : 1. ));
us.requestRedraw();
us.requestContinuousUpdate( isAnimating() || _thrown );
return true;
}
switch( sm ) {
// mouse scroll down event
case GUIEventAdapter::SCROLL_DOWN:
moveForward( -_wheelMovement * (getRelativeFlag( _wheelMovementFlagIndex ) ? _modelSize : 1. ));
_thrown = false;
us.requestRedraw();
us.requestContinuousUpdate( isAnimating() || _thrown );
return true;
// mouse scroll up event
case GUIEventAdapter::SCROLL_UP:
{
// move forward
moveForward( isAnimating() ? dynamic_cast< FirstPersonAnimationData* >( _animationData.get() )->_targetRot : _rotation,
-_wheelMovement * (getRelativeFlag( _wheelMovementFlagIndex ) ? _modelSize : 1. ));
us.requestRedraw();
us.requestContinuousUpdate( isAnimating() || _thrown );
return true;
}
// unhandled mouse scrolling motion
default:
return false;
}
// mouse scroll down event
case GUIEventAdapter::SCROLL_DOWN:
{
// move backward
moveForward( _wheelMovement * (getRelativeFlag( _wheelMovementFlagIndex ) ? _modelSize : 1. ));
_thrown = false;
us.requestRedraw();
us.requestContinuousUpdate( isAnimating() || _thrown );
return true;
}
// unhandled mouse scrolling motion
default:
return false;
}
}

View File

@ -114,6 +114,7 @@ bool FlightManipulator::handleKeyDown( const GUIEventAdapter& ea, GUIActionAdapt
}
/// General flight-style event handler
bool FlightManipulator::flightHandleEvent( const GUIEventAdapter& ea, GUIActionAdapter& us )
{
addMouseEvent( ea );

View File

@ -36,7 +36,7 @@ OrbitManipulator::OrbitManipulator( int flags )
{
setMinimumDistance( 0.05, true );
setWheelZoomFactor( 0.1 );
if( _flags & SET_CENTER_ON_WHEEL_UP )
if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT )
setAnimationTime( 0.2 );
}
@ -148,34 +148,108 @@ void OrbitManipulator::getTransformation( osg::Vec3d& center, osg::Vec3d& eye, o
}
/** Sets the transformation by heading. Heading is given as an angle in radians giving a azimuth in xy plane.
Its meaning is similar to longitude used in cartography and navigation.
Positive number is going to the east direction.*/
void OrbitManipulator::setHeading( double azimuth )
{
CoordinateFrame coordinateFrame = getCoordinateFrame( _center );
Vec3d localUp = getUpVector( coordinateFrame );
Vec3d localRight = getSideVector( coordinateFrame );
Vec3d dir = Quat( getElevation(), localRight ) * Quat( azimuth, localUp ) * Vec3d( 0., -_distance, 0. );
setTransformation( _center, _center + dir, localUp );
}
/// Returns the heading in radians. \sa setHeading
double OrbitManipulator::getHeading() const
{
CoordinateFrame coordinateFrame = getCoordinateFrame( _center );
Vec3d localFront = getFrontVector( coordinateFrame );
Vec3d localRight = getSideVector( coordinateFrame );
Vec3d center, eye, tmp;
getTransformation( center, eye, tmp );
Plane frontPlane( localFront, center );
double frontDist = frontPlane.distance( eye );
Plane rightPlane( localRight, center );
double rightDist = rightPlane.distance( eye );
return atan2( rightDist, -frontDist );
}
/** Sets the transformation by elevation. Elevation is given as an angle in radians from xy plane.
Its meaning is similar to latitude used in cartography and navigation.
Positive number is going to the north direction, negative to the south.*/
void OrbitManipulator::setElevation( double elevation )
{
CoordinateFrame coordinateFrame = getCoordinateFrame( _center );
Vec3d localUp = getUpVector( coordinateFrame );
Vec3d localRight = getSideVector( coordinateFrame );
Vec3d dir = Quat( -elevation, localRight ) * Quat( getHeading(), localUp ) * Vec3d( 0., -_distance, 0. );
setTransformation( _center, _center + dir, localUp );
}
/// Returns the elevation in radians. \sa setElevation
double OrbitManipulator::getElevation() const
{
CoordinateFrame coordinateFrame = getCoordinateFrame( _center );
Vec3d localUp = getUpVector( coordinateFrame );
localUp.normalize();
Vec3d center, eye, tmp;
getTransformation( center, eye, tmp );
Plane plane( localUp, center );
double dist = plane.distance( eye );
return asin( -dist / (eye-center).length() );
}
// doc in parent
bool OrbitManipulator::handleMouseWheel( const GUIEventAdapter& ea, GUIActionAdapter& us )
{
switch( ea.getScrollingMotion() )
osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion();
// handle centering
if( _flags & SET_CENTER_ON_WHEEL_FORWARD_MOVEMENT )
{
if( sm == GUIEventAdapter::SCROLL_DOWN && _wheelZoomFactor > 0. ||
sm == GUIEventAdapter::SCROLL_UP && _wheelZoomFactor < 0. )
{
if( getAnimationTime() <= 0. )
{
// center by mouse intersection (no animation)
setCenterByMousePointerIntersection( ea, us );
}
else
{
// start new animation only if there is no animation in progress
if( !isAnimating() )
startAnimationByMousePointerIntersection( ea, us );
}
}
}
switch( sm )
{
// mouse scroll up event
case GUIEventAdapter::SCROLL_UP:
{
if( _flags & SET_CENTER_ON_WHEEL_UP )
{
if( getAnimationTime() <= 0. )
{
// center by mouse intersection (no animation)
setCenterByMousePointerIntersection( ea, us );
}
else
{
// start new animation only if there is no animation in progress
if( !isAnimating() )
startAnimationByMousePointerIntersection( ea, us );
}
}
// perform zoom
zoomModel( -_wheelZoomFactor, true );
zoomModel( _wheelZoomFactor, true );
us.requestRedraw();
us.requestContinuousUpdate( isAnimating() || _thrown );
return true;
@ -183,10 +257,13 @@ bool OrbitManipulator::handleMouseWheel( const GUIEventAdapter& ea, GUIActionAda
// mouse scroll down event
case GUIEventAdapter::SCROLL_DOWN:
zoomModel( _wheelZoomFactor, true );
{
// perform zoom
zoomModel( -_wheelZoomFactor, true );
us.requestRedraw();
us.requestContinuousUpdate( false );
return true;
}
// unhandled mouse scrolling motion
default:
@ -530,7 +607,8 @@ void OrbitManipulator::setTrackballSize( const double& size )
/** Set the mouse wheel zoom factor.
The amount of camera movement on each mouse wheel event
is computed as the current distance to the center multiplied by this factor.
For example, value of 0.1 will short distance to center by 10% on each wheel up event.*/
For example, value of 0.1 will short distance to center by 10% on each wheel up event.
Use negative value for reverse mouse wheel direction.*/
void OrbitManipulator::setWheelZoomFactor( double wheelZoomFactor )
{
_wheelZoomFactor = wheelZoomFactor;

View File

@ -25,16 +25,16 @@ using namespace osgUtil;
/** \fn void StandardManipulator::setTransformation( const osg::Vec3d& eye, const osg::Quat& rotation );
/** \fn void StandardManipulator::setTransformation( const osg::Vec3d& eye, const osg::Quat& rotation )
Sets manipulator by eye position and eye orientation.*/
/** \fn void StandardManipulator::setTransformation( const osg::Vec3d& center, const osg::Vec3d& eye, const osg::Vec3d& up );
/** \fn void StandardManipulator::setTransformation( const osg::Vec3d& center, const osg::Vec3d& eye, const osg::Vec3d& up )
Sets manipulator by focal center, eye position, and up vector.*/
/** \fn void StandardManipulator::getTransformation( osg::Vec3d& eye, osg::Quat& rotation );
/** \fn void StandardManipulator::getTransformation( osg::Vec3d& eye, osg::Quat& rotation )
Gets manipulator's eye position and eye orientation.*/
/** \fn void StandardManipulator::getTransformation( osg::Vec3d& center, osg::Vec3d& eye, osg::Vec3d& up );
/** \fn void StandardManipulator::getTransformation( osg::Vec3d& center, osg::Vec3d& eye, osg::Vec3d& up )
Gets manipulator's focal center, eye position, and up vector.*/
@ -51,6 +51,7 @@ int StandardManipulator::allocateRelativeFlag()
StandardManipulator::StandardManipulator( int flags )
: inherited(),
_thrown( false ),
_allowThrow( true ),
_mouseCenterX(0.0f), _mouseCenterY(0.0f),
_delta_frame_time(0.01), _last_frame_time(0.0),
_modelSize( 0. ),
@ -65,6 +66,7 @@ StandardManipulator::StandardManipulator( int flags )
StandardManipulator::StandardManipulator( const StandardManipulator& uim, const CopyOp& copyOp )
: inherited( uim, copyOp ),
_thrown( uim._thrown ),
_allowThrow( uim._allowThrow ),
_mouseCenterX(0.0f), _mouseCenterY(0.0f),
_ga_t1( dynamic_cast< GUIEventAdapter* >( copyOp( uim._ga_t1.get() ) ) ),
_ga_t0( dynamic_cast< GUIEventAdapter* >( copyOp( uim._ga_t0.get() ) ) ),
@ -364,7 +366,7 @@ bool StandardManipulator::handleMouseRelease( const GUIEventAdapter& ea, GUIActi
if( isMouseMoving() )
{
if( performMovement() )
if( performMovement() && _allowThrow )
{
us.requestRedraw();
us.requestContinuousUpdate( true );
@ -583,6 +585,15 @@ bool StandardManipulator::isMouseMoving() const
}
/** Set the 'allow throw' flag. If it is set to true (default), releasing the mouse button
while moving the mouse results in a throw. If manipulator was thrown, it continues spinning
although no mouse button is down at the moment.*/
void StandardManipulator::setAllowThrow( bool allowThrow )
{
_allowThrow = allowThrow;
}
/** Returns the scale that should be applied on animation of "thrown" manipulator state
to avoid its dependency on varying frame rate.

View File

@ -35,12 +35,16 @@ TerrainManipulator::TerrainManipulator( const TerrainManipulator& tm, const Copy
}
/** Sets the manipulator rotation mode. RotationMode is now deprecated by
osgGA::StandardManipulator::setVerticalAxisFixed() functionality,
that is used across StandardManipulator derived classes.*/
void TerrainManipulator::setRotationMode( TerrainManipulator::RotationMode mode )
{
setVerticalAxisFixed( mode == ELEVATION_AZIM );
}
/** Returns the manipulator rotation mode.*/
TerrainManipulator::RotationMode TerrainManipulator::getRotationMode() const
{
return getVerticalAxisFixed() ? ELEVATION_AZIM : ELEVATION_AZIM_ROLL;