Made improvements to the handling of small rotations in Quat and

TerrainManipulator
This commit is contained in:
Robert Osfield 2004-05-20 23:25:26 +00:00
parent 48d148601b
commit ab2b817e61
3 changed files with 37 additions and 11 deletions

View File

@ -132,6 +132,7 @@ class OSGGA_EXPORT TerrainManipulator : public MatrixManipulator
osg::Vec3d _center;
osg::Quat _rotation;
float _distance;
osg::Vec3d _previousUp;
};

View File

@ -14,6 +14,7 @@
#include <osg/Quat>
#include <osg/Matrixf>
#include <osg/Matrixd>
#include <osg/Notify>
#include <math.h>
@ -103,7 +104,7 @@ void Quat::makeRotate( const Vec3f& from, const Vec3f& to )
// are co-incident or opposite in direction.
void Quat::makeRotate( const Vec3d& from, const Vec3d& to )
{
const value_type epsilon = 0.00001;
const value_type epsilon = 0.0000001;
value_type length1 = from.length();
value_type length2 = to.length();
@ -113,10 +114,12 @@ void Quat::makeRotate( const Vec3d& from, const Vec3d& to )
if ( fabs(cosangle - 1) < epsilon )
{
osg::notify(osg::INFO)<<"*** Quat::makeRotate(from,to) with near co-linear vectors, epsilon= "<<fabs(cosangle-1)<<std::endl;
// cosangle is close to 1, so the vectors are close to being coincident
// Need to generate an angle of zero with any vector we like
// We'll choose (1,0,0)
makeRotate( 0.0, 1.0, 0.0, 0.0 );
makeRotate( 0.0, 0.0, 0.0, 1.0 );
}
else
if ( fabs(cosangle + 1.0) < epsilon )

View File

@ -280,6 +280,8 @@ void TerrainManipulator::setByMatrix(const osg::Matrixd& matrix)
}
}
CoordinateFrame coordinateFrame = getCoordinateFrame(_center);
_previousUp = getUpVector(coordinateFrame);
clampOrientation();
}
@ -340,6 +342,9 @@ void TerrainManipulator::computePosition(const osg::Vec3d& eye,const osg::Vec3d&
rotation_matrix.get(_rotation);
_rotation = _rotation.inverse();
CoordinateFrame coordinateFrame = getCoordinateFrame(_center);
_previousUp = getUpVector(coordinateFrame);
clampOrientation();
}
@ -391,6 +396,7 @@ bool TerrainManipulator::calcMovement()
CoordinateFrame coordinateFrame = getCoordinateFrame(_center);
osg::Vec3d localUp = getUpVector(coordinateFrame);
//osg::Vec3d localUp = _previousUp;
osg::Vec3d forwardVector = localUp^sideVector;
@ -406,6 +412,7 @@ bool TerrainManipulator::calcMovement()
rotate_azim.makeRotate(-dx,localUp);
_rotation = _rotation * rotate_elevation * rotate_azim;
}
return true;
@ -427,8 +434,9 @@ bool TerrainManipulator::calcMovement()
osg::Vec3d sideVector = getSideVector(rotation_matrix);
osg::Vec3d upVector = getFrontVector(rotation_matrix);
CoordinateFrame coordinateFrame = getCoordinateFrame(_center);
osg::Vec3d localUp = getUpVector(coordinateFrame);
// CoordinateFrame coordinateFrame = getCoordinateFrame(_center);
// osg::Vec3d localUp = getUpVector(coordinateFrame);
osg::Vec3d localUp = _previousUp;
osg::Vec3d forwardVector =localUp^sideVector;
sideVector = forwardVector^localUp;
@ -443,13 +451,13 @@ bool TerrainManipulator::calcMovement()
// need to recompute the itersection point along the look vector.
// now reorientate the coordinate frame to the frame coords.
coordinateFrame = getCoordinateFrame(_center);
CoordinateFrame coordinateFrame = getCoordinateFrame(_center);
// need to reintersect with the terrain
osgUtil::IntersectVisitor iv;
double distance = _node->getBound().radius();
osg::Vec3d start_segment = osg::Vec3d(_center[0],_center[1],_center[2]) + getUpVector(coordinateFrame) * distance;
osg::Vec3d start_segment = _center + getUpVector(coordinateFrame) * distance;
osg::Vec3d end_segment = start_segment - getUpVector(coordinateFrame) * (2.0f*distance);
osg::notify(INFO)<<"start="<<start_segment<<"\tend="<<end_segment<<"\tupVector="<<getUpVector(coordinateFrame)<<std::endl;
@ -483,13 +491,23 @@ bool TerrainManipulator::calcMovement()
coordinateFrame = getCoordinateFrame(_center);
osg::Vec3d new_localUp = getUpVector(coordinateFrame);
osg::Quat pan_rotation;
pan_rotation.makeRotate(localUp,new_localUp);
_rotation = _rotation * pan_rotation;
osg::notify(osg::NOTICE)<<"Rotating from "<<localUp<<" to "<<new_localUp<<" angle = "<<acos(localUp*new_localUp/(localUp.length()*new_localUp.length()))<<std::endl;
//clampOrientation();
if (!pan_rotation.zeroRotation())
{
_rotation = _rotation * pan_rotation;
_previousUp = new_localUp;
//osg::notify(osg::NOTICE)<<"Rotating from "<<localUp<<" to "<<new_localUp<<" angle = "<<acos(localUp*new_localUp/(localUp.length()*new_localUp.length()))<<std::endl;
//clampOrientation();
}
else
{
osg::notify(osg::NOTICE)<<"New up orientation nearly inline - no need to rotate"<<std::endl;
}
return true;
}
@ -526,6 +544,7 @@ void TerrainManipulator::clampOrientation()
CoordinateFrame coordinateFrame = getCoordinateFrame(_center);
osg::Vec3d localUp = getUpVector(coordinateFrame);
//osg::Vec3d localUp = _previousUp;
osg::Vec3d sideVector = lookVector ^ localUp;
@ -544,7 +563,10 @@ void TerrainManipulator::clampOrientation()
osg::Quat rotate_roll;
rotate_roll.makeRotate(upVector,newUpVector);
_rotation = _rotation * rotate_roll;
if (!rotate_roll.zeroRotation())
{
_rotation = _rotation * rotate_roll;
}
}
}