Added trackmode support for handling rotation of tracked node

This commit is contained in:
Robert Osfield 2004-08-30 18:53:44 +00:00
parent 2733324701
commit 6578655ff3
2 changed files with 74 additions and 18 deletions

View File

@ -32,6 +32,16 @@ class OSGGA_EXPORT NodeTrackerManipulator : public MatrixManipulator
const osg::Node* getTrackNode() const { return _trackNode.get(); }
enum TrackerMode
{
NODE_CENTER,
NODE_CENTER_AND_ROTATION,
};
void setTrackerMode(TrackerMode mode);
TrackerMode getTrackerNode() const { return _trackerMode; }
enum RotationMode
{
ELEVATION_AZIM_ROLL,
@ -94,7 +104,10 @@ class OSGGA_EXPORT NodeTrackerManipulator : public MatrixManipulator
/** Add the current mouse GUIEvent to internal stack.*/
void addMouseEvent(const GUIEventAdapter& ea);
osg::Vec3d computeCenter() const;
void computeNodeWorldToLocal(osg::Matrixd& worldToLocal) const;
void computeNodeLocalToWorld(osg::Matrixd& localToWorld) const;
void computeNodeCenterAndRotation(osg::Vec3d& center, osg::Quat& rotation) const;
void computePosition(const osg::Vec3d& eye,const osg::Vec3d& lv,const osg::Vec3d& up);
@ -121,11 +134,13 @@ class OSGGA_EXPORT NodeTrackerManipulator : public MatrixManipulator
osg::ref_ptr<osg::Node> _node;
osg::ref_ptr<osg::Node> _trackNode;
TrackerMode _trackerMode;
RotationMode _rotationMode;
bool _thrown;
osg::Vec3d _center;
osg::Quat _nodeRotation;
osg::Quat _rotation;
float _distance;
osg::Vec3d _previousUp;

View File

@ -30,7 +30,8 @@ public:
NodeTrackerManipulator::NodeTrackerManipulator()
{
_rotationMode =ELEVATION_AZIM;
_trackerMode = NODE_CENTER_AND_ROTATION;
_rotationMode = ELEVATION_AZIM;
_distance = 1.0;
_thrown = false;
@ -97,9 +98,9 @@ void NodeTrackerManipulator::init(const GUIEventAdapter& ,GUIActionAdapter& )
void NodeTrackerManipulator::getUsage(osg::ApplicationUsage& usage) const
{
usage.addKeyboardMouseBinding("Trackball: Space","Reset the viewing position to home");
usage.addKeyboardMouseBinding("Trackball: +","When in stereo, increase the fusion distance");
usage.addKeyboardMouseBinding("Trackball: -","When in stereo, reduse the fusion distance");
usage.addKeyboardMouseBinding("NodeTracker: Space","Reset the viewing position to home");
usage.addKeyboardMouseBinding("NodeTracker: +","When in stereo, increase the fusion distance");
usage.addKeyboardMouseBinding("NodeTracker: -","When in stereo, reduse the fusion distance");
}
bool NodeTrackerManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& us)
@ -314,36 +315,76 @@ void NodeTrackerManipulator::setByMatrix(const osg::Matrixd& matrix)
clampOrientation();
}
osg::Vec3d NodeTrackerManipulator::computeCenter() const
void NodeTrackerManipulator::computeNodeWorldToLocal(osg::Matrixd& worldToLocal) const
{
if (_trackNode.valid())
{
CollectParentPaths cpp;
NodeTrackerManipulator* non_const_this = const_cast<NodeTrackerManipulator*>(this);
non_const_this->_trackNode->accept(cpp);
if (!cpp._nodePaths.empty())
{
osg::Matrix localToWorld;
localToWorld = osg::computeLocalToWorld(cpp._nodePaths[0]);
return _trackNode->getBound().center() * localToWorld;
worldToLocal = osg::computeWorldToLocal(cpp._nodePaths[0]);
}
}
return osg::Vec3d(0.0,0.0,0.0);
}
void NodeTrackerManipulator::computeNodeLocalToWorld(osg::Matrixd& localToWorld) const
{
if (_trackNode.valid())
{
CollectParentPaths cpp;
NodeTrackerManipulator* non_const_this = const_cast<NodeTrackerManipulator*>(this);
non_const_this->_trackNode->accept(cpp);
if (!cpp._nodePaths.empty())
{
localToWorld = osg::computeLocalToWorld(cpp._nodePaths[0]);
}
}
}
void NodeTrackerManipulator::computeNodeCenterAndRotation(osg::Vec3d& nodeCenter, osg::Quat& nodeRotation) const
{
osg::Matrixd localToWorld;
computeNodeLocalToWorld(localToWorld);
if (_trackNode.valid())
nodeCenter = _trackNode->getBound().center()*localToWorld;
else
nodeCenter = osg::Vec3d(0.0f,0.0f,0.0f)*localToWorld;
// scale the matrix to get rid of any scales before we extract the rotation.
double sx = 1.0/sqrt(localToWorld(0,0)*localToWorld(0,0) + localToWorld(1,0)*localToWorld(1,0) + localToWorld(2,0)*localToWorld(2,0));
double sy = 1.0/sqrt(localToWorld(0,1)*localToWorld(0,1) + localToWorld(1,1)*localToWorld(1,1) + localToWorld(2,1)*localToWorld(2,1));
double sz = 1.0/sqrt(localToWorld(0,2)*localToWorld(0,2) + localToWorld(1,2)*localToWorld(1,2) + localToWorld(2,2)*localToWorld(2,2));
localToWorld = localToWorld*osg::Matrixd::scale(sx,sy,sz);
localToWorld.get(nodeRotation);
}
osg::Matrixd NodeTrackerManipulator::getMatrix() const
{
return osg::Matrixd::translate(0.0,0.0,_distance)*osg::Matrixd::rotate(_rotation)*osg::Matrix::translate(computeCenter());
osg::Vec3d nodeCenter;
osg::Quat nodeRotation;
computeNodeCenterAndRotation(nodeCenter,nodeRotation);
if (_trackerMode==NODE_CENTER)
return osg::Matrixd::translate(0.0,0.0,_distance)*osg::Matrixd::rotate(_rotation)*osg::Matrix::translate(nodeCenter);
else
return osg::Matrixd::translate(0.0,0.0,_distance)*osg::Matrixd::rotate(_rotation)*osg::Matrixd::rotate(nodeRotation)*osg::Matrix::translate(nodeCenter);
}
osg::Matrixd NodeTrackerManipulator::getInverseMatrix() const
{
return osg::Matrix::translate(-computeCenter())*osg::Matrixd::rotate(_rotation.inverse())*osg::Matrixd::translate(0.0,0.0,-_distance);
osg::Vec3d nodeCenter;
osg::Quat nodeRotation;
computeNodeCenterAndRotation(nodeCenter,nodeRotation);
if (_trackerMode==NODE_CENTER)
return osg::Matrixd::translate(-nodeCenter)*osg::Matrixd::rotate(_rotation.inverse())*osg::Matrixd::translate(0.0,0.0,-_distance);
else
return osg::Matrixd::translate(-nodeCenter)*osg::Matrixd::rotate(nodeRotation.inverse())*osg::Matrixd::rotate(_rotation.inverse())*osg::Matrixd::translate(0.0,0.0,-_distance);
}
void NodeTrackerManipulator::computePosition(const osg::Vec3d& eye,const osg::Vec3d& center,const osg::Vec3d& up)
@ -424,12 +465,12 @@ bool NodeTrackerManipulator::calcMovement()
if (_trackNode.valid())
{
osg::notify(osg::NOTICE)<<"_trackNode="<<_trackNode->getName()<<std::endl;
// osg::notify(osg::NOTICE)<<"_trackNode="<<_trackNode->getName()<<std::endl;
CollectParentPaths cpp;
_trackNode->accept(cpp);
osg::notify(osg::NOTICE)<<"number of nodepaths = "<<cpp._nodePaths.size()<<std::endl;
// osg::notify(osg::NOTICE)<<"number of nodepaths = "<<cpp._nodePaths.size()<<std::endl;
if (!cpp._nodePaths.empty())
{