Added UFO manipulator
This commit is contained in:
parent
537fa6c604
commit
a7ac8f5992
165
include/osgGA/UFOManipulator
Normal file
165
include/osgGA/UFOManipulator
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef OSGGA_UFO_MANIPULATOR_DEF
|
||||||
|
#define OSGGA_UFO_MANIPULATOR_DEF 1
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <Producer/Keyboard>
|
||||||
|
|
||||||
|
#include <osgGA/MatrixManipulator>
|
||||||
|
#include <osg/Node>
|
||||||
|
#include <osg/Matrix>
|
||||||
|
|
||||||
|
/**
|
||||||
|
\class UFOManipulator
|
||||||
|
\brief A UFO manipulator driven with keybindings.
|
||||||
|
|
||||||
|
The UFOManipulator is better suited for applications that employ
|
||||||
|
architectural walk-throughs, or situations where the eyepoint motion
|
||||||
|
model must move slowly, deliberately and well controlled.
|
||||||
|
|
||||||
|
The UFO Manipulator allows the following movements with the listed
|
||||||
|
Key combinations:
|
||||||
|
\param UpArrow Acceleration forward.
|
||||||
|
\param DownArrow Acceleration backward (or deceleration forward).
|
||||||
|
\param LeftArrow Rotate view and direction of travel to the left.
|
||||||
|
\param RightArrow Rotate view and direction of travel to the right.
|
||||||
|
\param SpaceBar Brake. Gradually decelerates linear and rotational movement.
|
||||||
|
\param Shift/UpArrow Accelerate up.
|
||||||
|
\param Shift/DownArrow Accelerate down.
|
||||||
|
\param Shift/LeftArrow Accelerate (linearly) left.
|
||||||
|
\param Shift/RightArrow Accelerate (linearly) right.
|
||||||
|
\param Shift/SpaceBar Instant brake. Immediately stop all linear and rotational movement.
|
||||||
|
|
||||||
|
When the Shift key is released, up, down, linear left and/or linear right movement is decelerated.
|
||||||
|
|
||||||
|
\param Ctrl/UpArrow Rotate view (but not direction of travel) up.
|
||||||
|
\param Ctrl/DownArrow Rotate view (but not direction of travel) down.
|
||||||
|
\param Ctrl/LeftArrow Rotate view (but not direction of travel) left.
|
||||||
|
\param Ctrl/RightArrow Rotate view (but not direction of travel) right.
|
||||||
|
\param Ctrl/Return Straightens out the view offset.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace osgGA {
|
||||||
|
|
||||||
|
class OSGGA_EXPORT UFOManipulator : public osgGA::MatrixManipulator
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Default constructor */
|
||||||
|
UFOManipulator();
|
||||||
|
|
||||||
|
/** return className
|
||||||
|
\return returns constant "UFOManipulator"
|
||||||
|
*/
|
||||||
|
virtual const char* className() const;
|
||||||
|
|
||||||
|
/** Set the current position with a matrix
|
||||||
|
\param matrix A viewpoint matrix.
|
||||||
|
*/
|
||||||
|
virtual void setByMatrix( const osg::Matrix &matrix ) ;
|
||||||
|
|
||||||
|
/** Set the current position with the invers matrix
|
||||||
|
\param invmatrix The inverse of a viewpoint matrix
|
||||||
|
*/
|
||||||
|
virtual void setByInverseMatrix( const osg::Matrix &invmat);
|
||||||
|
|
||||||
|
/** Get the current viewmatrix */
|
||||||
|
virtual osg::Matrix getMatrix() const;
|
||||||
|
|
||||||
|
/** Get the current inverse view matrix */
|
||||||
|
virtual osg::Matrix getInverseMatrix() const ;
|
||||||
|
|
||||||
|
/** Set the subgraph this manipulator is driving the eye through.
|
||||||
|
\param node root of subgraph
|
||||||
|
*/
|
||||||
|
virtual void setNode(osg::Node*);
|
||||||
|
|
||||||
|
/** Get the root node of the subgraph this manipulator is driving the eye through (const)*/
|
||||||
|
virtual const osg::Node* getNode() const;
|
||||||
|
|
||||||
|
/** Get the root node of the subgraph this manipulator is driving the eye through */
|
||||||
|
virtual osg::Node* getNode();
|
||||||
|
|
||||||
|
/** Computes the home position based on the extents and scale of the
|
||||||
|
scene graph rooted at node */
|
||||||
|
virtual void computeHomePosition();
|
||||||
|
|
||||||
|
/** Sets the viewpoint matrix to the home position */
|
||||||
|
virtual void home(const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&) ;
|
||||||
|
|
||||||
|
/** Handles incoming osgGA events */
|
||||||
|
bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter &aa);
|
||||||
|
|
||||||
|
/** Reports Usage parameters to the application */
|
||||||
|
void getUsage(osg::ApplicationUsage& usage) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
private:
|
||||||
|
osg::ref_ptr<osg::Node> _node;
|
||||||
|
float _viewAngle;
|
||||||
|
osg::Matrix _matrix;
|
||||||
|
osg::Matrix _inverseMatrix;
|
||||||
|
osg::Matrix _offset;
|
||||||
|
|
||||||
|
double _minHeightAboveGround;
|
||||||
|
double _minDistanceInFront;
|
||||||
|
|
||||||
|
double _speedEpsilon;
|
||||||
|
double _forwardSpeed;
|
||||||
|
double _sideSpeed;
|
||||||
|
double _upSpeed;
|
||||||
|
double _speedAccelerationFactor;
|
||||||
|
double _speedDecelerationFactor;
|
||||||
|
|
||||||
|
bool _decelerateUpSideRate;
|
||||||
|
|
||||||
|
double _directionRotationEpsilon;
|
||||||
|
double _directionRotationRate;
|
||||||
|
double _directionRotationAcceleration;
|
||||||
|
double _directionRotationDeceleration;
|
||||||
|
|
||||||
|
double _viewOffsetDelta;
|
||||||
|
double _pitchOffsetRate;
|
||||||
|
double _pitchOffset;
|
||||||
|
double _yawOffsetRate;
|
||||||
|
double _yawOffset;
|
||||||
|
|
||||||
|
double _t0;
|
||||||
|
double _dt;
|
||||||
|
osg::Vec3 _direction;
|
||||||
|
osg::Vec3 _position;
|
||||||
|
|
||||||
|
|
||||||
|
bool _shift;
|
||||||
|
bool _ctrl;
|
||||||
|
bool _decelerateOffsetRate;
|
||||||
|
|
||||||
|
bool _straightenOffset;
|
||||||
|
|
||||||
|
void _home();
|
||||||
|
void _stop();
|
||||||
|
void _keyDown( const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &);
|
||||||
|
void _keyUp( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter &);
|
||||||
|
void _frame(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter &);
|
||||||
|
|
||||||
|
void _adjustPosition();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -8,6 +8,7 @@ CXXFILES = \
|
|||||||
DriveManipulator.cpp\
|
DriveManipulator.cpp\
|
||||||
EventVisitor.cpp\
|
EventVisitor.cpp\
|
||||||
FlightManipulator.cpp\
|
FlightManipulator.cpp\
|
||||||
|
UFOManipulator.cpp\
|
||||||
GUIEventAdapter.cpp\
|
GUIEventAdapter.cpp\
|
||||||
GUIEventHandler.cpp\
|
GUIEventHandler.cpp\
|
||||||
GUIEventHandlerVisitor.cpp\
|
GUIEventHandlerVisitor.cpp\
|
||||||
|
511
src/osgGA/UFOManipulator.cpp
Normal file
511
src/osgGA/UFOManipulator.cpp
Normal file
@ -0,0 +1,511 @@
|
|||||||
|
#include <osgGA/UFOManipulator>
|
||||||
|
#include <osgUtil/IntersectVisitor>
|
||||||
|
|
||||||
|
using namespace osgGA;
|
||||||
|
|
||||||
|
UFOManipulator::UFOManipulator():
|
||||||
|
_t0(0.0),
|
||||||
|
_shift(false),
|
||||||
|
_ctrl(false)
|
||||||
|
{
|
||||||
|
_minHeightAboveGround = 2.0;
|
||||||
|
_minDistanceInFront = 5.0;
|
||||||
|
|
||||||
|
_speedAccelerationFactor = 0.4;
|
||||||
|
_speedDecelerationFactor = 0.90;
|
||||||
|
|
||||||
|
_directionRotationRate = 0.0;
|
||||||
|
_directionRotationAcceleration = M_PI*0.00005;
|
||||||
|
_directionRotationDeceleration = 0.90;
|
||||||
|
|
||||||
|
_speedEpsilon = 0.02;
|
||||||
|
_directionRotationEpsilon = 0.0001;
|
||||||
|
|
||||||
|
_viewOffsetDelta = M_PI * 0.0025;
|
||||||
|
_pitchOffsetRate = 0.0;
|
||||||
|
_pitchOffset = 0.0;
|
||||||
|
|
||||||
|
_yawOffsetRate = 0.0;
|
||||||
|
_yawOffset = 0.0;
|
||||||
|
_offset.makeIdentity();
|
||||||
|
|
||||||
|
_decelerateOffsetRate = true;
|
||||||
|
_straightenOffset = false;
|
||||||
|
|
||||||
|
_direction.set( 0,1,0);
|
||||||
|
_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFOManipulator::setNode( osg::Node *node )
|
||||||
|
{
|
||||||
|
_node = node;
|
||||||
|
|
||||||
|
if (getAutoComputeHomePosition())
|
||||||
|
computeHomePosition();
|
||||||
|
|
||||||
|
_home();
|
||||||
|
}
|
||||||
|
|
||||||
|
const osg::Node* UFOManipulator::getNode() const
|
||||||
|
{
|
||||||
|
return _node.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Node* UFOManipulator::getNode()
|
||||||
|
{
|
||||||
|
return _node.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* UFOManipulator::className() const
|
||||||
|
{
|
||||||
|
return "UFOManipulator";
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFOManipulator::setByMatrix( const osg::Matrix &mat )
|
||||||
|
{
|
||||||
|
_inverseMatrix = mat;
|
||||||
|
_matrix.invert( _inverseMatrix );
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFOManipulator::setByInverseMatrix( const osg::Matrix &invmat)
|
||||||
|
{
|
||||||
|
_matrix = invmat;
|
||||||
|
_inverseMatrix.invert( _matrix );
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Matrix UFOManipulator::getMatrix() const
|
||||||
|
{
|
||||||
|
return (_offset * _matrix);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Matrix UFOManipulator::getInverseMatrix() const
|
||||||
|
{
|
||||||
|
return (_inverseMatrix * _offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFOManipulator::computeHomePosition()
|
||||||
|
{
|
||||||
|
if( !_node.valid() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
osg::BoundingSphere bs = _node->getBound();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find the ground - Assumption: The ground is the hit of an intersection
|
||||||
|
* from a line segment extending from above to below the database at its
|
||||||
|
* horizontal center, that intersects the database closest to zero. */
|
||||||
|
osgUtil::IntersectVisitor iv;
|
||||||
|
osg::ref_ptr<osg::LineSegment> seg = new osg::LineSegment;
|
||||||
|
osg::Vec3 A = bs.center() + (osg::Vec3(0,0,1)*(bs.radius()*2));
|
||||||
|
osg::Vec3 B = bs.center() + (osg::Vec3(0,0,-1)*(bs.radius()*2));
|
||||||
|
|
||||||
|
if( (B-A).length() == 0.0)
|
||||||
|
{
|
||||||
|
puts( "DOH" ); fflush(stdout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
seg->set( bs.center() + (osg::Vec3(0,0,1)*(bs.radius()*2)),
|
||||||
|
bs.center() + (osg::Vec3(0,0,-1)*(bs.radius()*2)) );
|
||||||
|
*/
|
||||||
|
seg->set( A, B );
|
||||||
|
|
||||||
|
iv.addLineSegment( seg.get() );
|
||||||
|
_node->accept(iv);
|
||||||
|
|
||||||
|
// start with it high
|
||||||
|
double ground = bs.radius() * 3;
|
||||||
|
|
||||||
|
if (iv.hits())
|
||||||
|
{
|
||||||
|
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(seg.get());
|
||||||
|
for(osgUtil::IntersectVisitor::HitList::iterator hitr=hitList.begin();
|
||||||
|
hitr!=hitList.end(); ++hitr)
|
||||||
|
{
|
||||||
|
osg::Vec3d ip = hitList.front().getWorldIntersectPoint();
|
||||||
|
if( fabs(ip[3]) < ground )
|
||||||
|
ground = ip[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
osg::notify(osg::WARN)<<"UFOManipulator : I can't find the ground!"<<std::endl;
|
||||||
|
ground = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
osg::Vec3 p(bs.center()[0], bs.center()[1], ground + (_minHeightAboveGround*1.25) );
|
||||||
|
setHomePosition( p, p + osg::Vec3(0,1,0), osg::Vec3(0,0,1) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFOManipulator::home(const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&)
|
||||||
|
{
|
||||||
|
_home();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFOManipulator::_home()
|
||||||
|
{
|
||||||
|
if (getAutoComputeHomePosition())
|
||||||
|
computeHomePosition();
|
||||||
|
|
||||||
|
_position = _homeEye;
|
||||||
|
_direction = _homeCenter - _homeEye;
|
||||||
|
_direction.normalize();
|
||||||
|
_directionRotationRate = 0.0;
|
||||||
|
|
||||||
|
_inverseMatrix.makeLookAt( _homeEye, _homeCenter, _homeUp );
|
||||||
|
_matrix.invert( _matrix );
|
||||||
|
|
||||||
|
_offset.makeIdentity();
|
||||||
|
|
||||||
|
_forwardSpeed = 0.0;
|
||||||
|
_sideSpeed = 0.0;
|
||||||
|
_upSpeed = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UFOManipulator::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter &aa)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch(ea.getEventType())
|
||||||
|
{
|
||||||
|
case(osgGA::GUIEventAdapter::KEYUP):
|
||||||
|
_keyUp( ea, aa );
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case(osgGA::GUIEventAdapter::KEYDOWN):
|
||||||
|
_keyDown(ea, aa);
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case(osgGA::GUIEventAdapter::FRAME):
|
||||||
|
_frame(ea,aa);
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFOManipulator::getUsage(osg::ApplicationUsage& usage) const
|
||||||
|
{
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <SpaceBar>", "Reset the viewing angle to 0.0");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <UpArrow>", "Acceleration forward.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <DownArrow>", "Acceleration backward (or deceleration forward");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <LeftArrow>", "Rotate view and direction of travel to the left.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <RightArrow>", "Rotate view and direction of travel to the right.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <SpaceBar>", "Brake. Gradually decelerates linear and rotational movement.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <Shift/UpArrow>", "Accelerate up.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <Shift/DownArrow>", "Accelerate down.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <Shift/LeftArrow>", "Accelerate (linearly) left.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <Shift/RightArrow>","Accelerate (linearly) right.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <Shift/SpaceBar>", "Instant brake. Immediately stop all linear and rotational movement.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <Ctrl/UpArrow>", "Rotate view (but not direction of travel) up.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <Ctrl/DownArrow>", "Rotate view (but not direction of travel) down.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <Ctrl/LeftArrow>", "Rotate view (but not direction of travel) left.");
|
||||||
|
usage.addKeyboardMouseBinding("UFO Manipulator: <Ctrl/RightArrow>", "Rotate view (but not direction of travel) right.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void UFOManipulator::_keyUp( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter & )
|
||||||
|
{
|
||||||
|
switch( ea.getKey() )
|
||||||
|
{
|
||||||
|
case Producer::KeyChar_Control_L:
|
||||||
|
case Producer::KeyChar_Control_R:
|
||||||
|
_ctrl = false;
|
||||||
|
_decelerateOffsetRate = true;
|
||||||
|
_straightenOffset = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Producer::KeyChar_Shift_L:
|
||||||
|
case Producer::KeyChar_Shift_R:
|
||||||
|
_shift = false;
|
||||||
|
_decelerateUpSideRate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFOManipulator::_keyDown( const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter & )
|
||||||
|
{
|
||||||
|
switch( ea.getKey() )
|
||||||
|
{
|
||||||
|
case Producer::KeyChar_Control_L:
|
||||||
|
case Producer::KeyChar_Control_R:
|
||||||
|
_ctrl = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Producer::KeyChar_Shift_L :
|
||||||
|
case Producer::KeyChar_Shift_R :
|
||||||
|
_shift = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Producer::KeyChar_Up:
|
||||||
|
if( _ctrl )
|
||||||
|
{
|
||||||
|
_pitchOffsetRate -= _viewOffsetDelta;
|
||||||
|
_decelerateOffsetRate = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( _shift )
|
||||||
|
{
|
||||||
|
_upSpeed += _speedAccelerationFactor;
|
||||||
|
_decelerateUpSideRate = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_forwardSpeed += _speedAccelerationFactor;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Producer::KeyChar_Down:
|
||||||
|
if( _ctrl )
|
||||||
|
{
|
||||||
|
_pitchOffsetRate += _viewOffsetDelta;
|
||||||
|
_decelerateOffsetRate = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( _shift )
|
||||||
|
{
|
||||||
|
_upSpeed -= _speedAccelerationFactor;
|
||||||
|
_decelerateUpSideRate = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_forwardSpeed -= _speedAccelerationFactor;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Producer::KeyChar_Right:
|
||||||
|
if( _ctrl )
|
||||||
|
{
|
||||||
|
_yawOffsetRate += _viewOffsetDelta;
|
||||||
|
_decelerateOffsetRate = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(_shift)
|
||||||
|
{
|
||||||
|
_sideSpeed += _speedAccelerationFactor;
|
||||||
|
_decelerateUpSideRate = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_directionRotationRate -= _directionRotationAcceleration;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Producer::KeyChar_Left:
|
||||||
|
if( _ctrl )
|
||||||
|
{
|
||||||
|
_yawOffsetRate -= _viewOffsetDelta;
|
||||||
|
_decelerateOffsetRate = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(_shift)
|
||||||
|
{
|
||||||
|
_sideSpeed -= _speedAccelerationFactor;
|
||||||
|
_decelerateUpSideRate = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_directionRotationRate += _directionRotationAcceleration;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Producer::KeyChar_Return:
|
||||||
|
if( _ctrl )
|
||||||
|
{
|
||||||
|
_straightenOffset = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ' ':
|
||||||
|
if( _shift )
|
||||||
|
{
|
||||||
|
_stop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( fabs(_forwardSpeed) > 0.0 )
|
||||||
|
{
|
||||||
|
_forwardSpeed *= _speedDecelerationFactor;
|
||||||
|
|
||||||
|
if( fabs(_forwardSpeed ) < _speedEpsilon )
|
||||||
|
_forwardSpeed = 0.0;
|
||||||
|
}
|
||||||
|
if( fabs(_sideSpeed) > 0.0 )
|
||||||
|
{
|
||||||
|
_sideSpeed *= _speedDecelerationFactor;
|
||||||
|
|
||||||
|
if( fabs( _sideSpeed ) < _speedEpsilon )
|
||||||
|
_sideSpeed = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fabs(_upSpeed) > 0.0 )
|
||||||
|
{
|
||||||
|
_upSpeed *= _speedDecelerationFactor;
|
||||||
|
|
||||||
|
if( fabs( _upSpeed ) < _speedEpsilon )
|
||||||
|
_sideSpeed = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( fabs(_directionRotationRate ) > 0.0 )
|
||||||
|
{
|
||||||
|
_directionRotationRate *= _directionRotationDeceleration;
|
||||||
|
if( fabs( _directionRotationRate ) < _directionRotationEpsilon )
|
||||||
|
_directionRotationRate = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'H':
|
||||||
|
_home();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFOManipulator::_frame( const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter & )
|
||||||
|
{
|
||||||
|
double t1 = ea.time();
|
||||||
|
if( _t0 == 0.0 )
|
||||||
|
{
|
||||||
|
_t0 = ea.time();
|
||||||
|
_dt = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_dt = t1 - _t0;
|
||||||
|
_t0 = t1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fabs( _directionRotationRate ) > _directionRotationEpsilon )
|
||||||
|
{
|
||||||
|
_direction = _direction * osg::Matrix::rotate( _directionRotationRate, osg::Vec3(0,0,1));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
osg::Vec3 _sideVec = _direction * osg::Matrix::rotate( -M_PI*0.5, osg::Vec3(0,0,1));
|
||||||
|
|
||||||
|
_position += ((_direction * _forwardSpeed) +
|
||||||
|
(_sideVec * _sideSpeed) +
|
||||||
|
(osg::Vec3(0,0,1) * _upSpeed))
|
||||||
|
* _dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
_pitchOffset += _pitchOffsetRate * _dt;
|
||||||
|
if( _pitchOffset >= M_PI || _pitchOffset < -M_PI )
|
||||||
|
_pitchOffset *= -1;
|
||||||
|
|
||||||
|
_yawOffset += _yawOffsetRate * _dt;
|
||||||
|
if( _yawOffset >= M_PI || _yawOffset < -M_PI )
|
||||||
|
_yawOffset *= -1;
|
||||||
|
|
||||||
|
_offset = osg::Matrix::rotate( _yawOffset, osg::Vec3(0,1,0),
|
||||||
|
_pitchOffset, osg::Vec3(1,0,0),
|
||||||
|
0.0, osg::Vec3(0,0,1));
|
||||||
|
|
||||||
|
_adjustPosition();
|
||||||
|
|
||||||
|
_inverseMatrix.makeLookAt( _position, _position + _direction, osg::Vec3(0,0,1));
|
||||||
|
_matrix.invert(_inverseMatrix);
|
||||||
|
|
||||||
|
if( _decelerateUpSideRate )
|
||||||
|
{
|
||||||
|
_upSpeed *= 0.98;
|
||||||
|
_sideSpeed *= 0.98;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _decelerateOffsetRate )
|
||||||
|
{
|
||||||
|
_yawOffsetRate *= 0.98;
|
||||||
|
_pitchOffsetRate *= 0.98;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _straightenOffset )
|
||||||
|
{
|
||||||
|
_pitchOffsetRate = 0.0;
|
||||||
|
_yawOffsetRate = 0.0;
|
||||||
|
_pitchOffset *= 0.99;
|
||||||
|
_yawOffset *= 0.99;
|
||||||
|
|
||||||
|
if( fabs(_pitchOffset ) < 0.01 )
|
||||||
|
_pitchOffset = 0.0;
|
||||||
|
if( fabs(_yawOffset ) < 0.01 )
|
||||||
|
_pitchOffset = 0.0;
|
||||||
|
|
||||||
|
if( _pitchOffset == 0.0 && _yawOffset == 0.0 )
|
||||||
|
_straightenOffset = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UFOManipulator::_adjustPosition()
|
||||||
|
{
|
||||||
|
if( !_node.valid() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
osgUtil::IntersectVisitor iv;
|
||||||
|
|
||||||
|
// Forward line segment at 3 times our intersect distance
|
||||||
|
osg::ref_ptr<osg::LineSegment> segForward = new osg::LineSegment;
|
||||||
|
segForward->set(_position, _position + (_direction * (_minDistanceInFront * 3.0)) );
|
||||||
|
iv.addLineSegment( segForward.get() );
|
||||||
|
|
||||||
|
|
||||||
|
// Down line segment at 3 times our intersect distance
|
||||||
|
osg::ref_ptr<osg::LineSegment> segDown = new osg::LineSegment;
|
||||||
|
segDown->set( _position,
|
||||||
|
_position - (osg::Vec3(0,0, _minHeightAboveGround*3)));
|
||||||
|
iv.addLineSegment( segDown.get() );
|
||||||
|
|
||||||
|
_node->accept(iv);
|
||||||
|
|
||||||
|
if (iv.hits())
|
||||||
|
{
|
||||||
|
// Check intersects infront.
|
||||||
|
{
|
||||||
|
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segForward.get());
|
||||||
|
if (!hitList.empty())
|
||||||
|
{
|
||||||
|
osg::Vec3d ip = hitList.front().getWorldIntersectPoint();
|
||||||
|
|
||||||
|
double d = (ip - _position).length();
|
||||||
|
|
||||||
|
if( d < _minDistanceInFront )
|
||||||
|
{
|
||||||
|
osg::Vec3 op = _position;
|
||||||
|
_position = ip + (_direction * -_minDistanceInFront);
|
||||||
|
_stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check intersects below.
|
||||||
|
{
|
||||||
|
osgUtil::IntersectVisitor::HitList& hitList = iv.getHitList(segDown.get());
|
||||||
|
if (!hitList.empty())
|
||||||
|
{
|
||||||
|
osg::Vec3d ip = hitList.front().getWorldIntersectPoint();
|
||||||
|
if( _position[2] - ip[2] < _minHeightAboveGround )
|
||||||
|
_position[2] = ip[2] + _minHeightAboveGround;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void UFOManipulator::_stop()
|
||||||
|
{
|
||||||
|
_forwardSpeed = 0.0;
|
||||||
|
_sideSpeed = 0.0;
|
||||||
|
_upSpeed = 0.0;
|
||||||
|
_directionRotationRate = 0.0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user