Added rescale of quaternion in Matrix::set(Quat), a copy operation in osg::Quat and

extra tracking options in NodeTrackerManipulator.
This commit is contained in:
Robert Osfield
2004-08-31 09:20:31 +00:00
parent 15def16d43
commit 08017daf37
4 changed files with 79 additions and 10 deletions

View File

@@ -84,6 +84,8 @@ class SG_EXPORT Quat
makeRotate(angle1,axis1,angle2,axis2,angle3,axis3);
}
inline Quat& operator = (const Quat& v) { _v[0]=v._v[0]; _v[1]=v._v[1]; _v[2]=v._v[2]; _v[3]=v._v[3]; return *this; }
inline bool operator == (const Quat& v) const { return _v[0]==v._v[0] && _v[1]==v._v[1] && _v[2]==v._v[2] && _v[3]==v._v[3]; }
inline bool operator != (const Quat& v) const { return _v[0]!=v._v[0] || _v[1]!=v._v[1] || _v[2]!=v._v[2] || _v[3]!=v._v[3]; }

View File

@@ -35,6 +35,8 @@ class OSGGA_EXPORT NodeTrackerManipulator : public MatrixManipulator
enum TrackerMode
{
NODE_CENTER,
NODE_CENTER_AND_AZMIM_ROTATION,
NODE_CENTER_AND_AZMIM_ELEVATION_ROTATION,
NODE_CENTER_AND_ROTATION,
};

View File

@@ -62,8 +62,16 @@ void Matrix_implementation::set( value_type a00, value_type a01, value_type a02,
#define QZ q._v[2]
#define QW q._v[3]
void Matrix_implementation::set(const Quat& q)
void Matrix_implementation::set(const Quat& q_in)
{
Quat q(q_in);
double length2 = q.length2();
if (length2!=1.0)
{
// normalize quat if required.
q /= sqrt(length2);
}
// Source: Gamasutra, Rotating Objects Using Quaternions
//
//http://www.gamasutra.com/features/programming/19980703/quaternions_01.htm

View File

@@ -31,6 +31,9 @@ public:
NodeTrackerManipulator::NodeTrackerManipulator()
{
_trackerMode = NODE_CENTER_AND_ROTATION;
_trackerMode = NODE_CENTER_AND_AZMIM_ROTATION;
_trackerMode = NODE_CENTER_AND_AZMIM_ELEVATION_ROTATION;
_rotationMode = ELEVATION_AZIM;
_distance = 1.0;
@@ -361,7 +364,67 @@ void NodeTrackerManipulator::computeNodeCenterAndRotation(osg::Vec3d& nodeCenter
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);
/*
Euler Code not in correct coordinate frame, just an experiment here.
// Assuming the angles are in radians.
double heading, attitude, bank = 0;
if (localToWorld(0,1) > 0.998)
{ // singularity at north pole
heading = atan2(localToWorld(2,0),localToWorld(2,2));
attitude = osg::PI_2;
bank = 0;
}
else if (localToWorld(0,1) < -0.998)
{ // singularity at south pole
heading = atan2(localToWorld(2,0),localToWorld(2,2));
attitude = -osg::PI_2;
bank = 0;
}
else
{
heading = atan2(-localToWorld(0,2),localToWorld(0,0));
bank = atan2(-localToWorld(2,1),localToWorld(1,1));
attitude = asin(localToWorld(0,1));
}
osg::notify(osg::NOTICE)<<"heading = "<<heading<<" attitude="<<attitude<<" bank="<<bank<<std::endl;
*/
switch(_trackerMode)
{
case(NODE_CENTER_AND_AZMIM_ROTATION):
{
double azim = atan2(-localToWorld(0,1),localToWorld(0,0));
nodeRotation.makeRotate(-azim,0.0,0.0,1.0);
break;
}
case(NODE_CENTER_AND_AZMIM_ELEVATION_ROTATION):
{
double azim = atan2(-localToWorld(0,1),localToWorld(0,0));
double elevation = acos(localToWorld(2,2));
osg::Quat azimRotation;
osg::Quat elevationRotation;
azimRotation.makeRotate(-azim,0.0,0.0,1.0);
elevationRotation.makeRotate(-elevation,0.0,1.0,0.0);
nodeRotation = elevationRotation*azimRotation;
osg::notify(osg::NOTICE)<<"azimRotation = "<<azim<<std::endl;
osg::notify(osg::NOTICE)<<"elevationRotation = "<<elevation<<std::endl;
break;
}
case(NODE_CENTER_AND_ROTATION):
{
localToWorld.get(nodeRotation);
break;
}
case(NODE_CENTER):
default:
{
nodeRotation = osg::Quat();
break;
}
}
}
@@ -370,10 +433,7 @@ osg::Matrixd NodeTrackerManipulator::getMatrix() const
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);
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
@@ -381,10 +441,7 @@ osg::Matrixd NodeTrackerManipulator::getInverseMatrix() const
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);
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)