|
这个是从书中TrackballManipulator扩展的,setByMatrix很重要,用来直接设置漫游器的相机矩阵,这是原书代码中没有实现的,自己写了,发现有问题,m_vRotation的三个值好像不是对应于heading, pitch, roll的,有人解决过吗?或者有更好的实现方法?比如把m_vRotation这个旋转三角度直接用矩阵替换的?
// 直接设置相机观察矩阵 的逆矩阵
void osgGA::WalkTravelManipulator::setByMatrix(const osg::Matrix &matrix)
{
m_vPosition = matrix.getTrans();
osg:uat qut= matrix.getRotate();
double heading, pitch, roll;
QuatToHPR(qut,heading, pitch, roll);
/*osg::Matrixd mat;
mat=Matrixd::rotate( qut );
*/
//qut.normalize();
m_vRotation.x()=pitch;
m_vRotation.y()=roll;
m_vRotation.z()=heading;
}
//四元数转化为欧拉角
void osgGA::WalkTravelManipulator::QuatToHPR(const osg::Quat& q, double& heading, double& pitch, double& roll)
{
osg::Vec3d Y1 = q * osg::Vec3d(0.0,1.0,0.0);
// 方向向量垂直,属于gambal lock,约定此时roll=0.0
if(Y1.z()>0.9999)
{
heading = 2.0 * atan2(q.z(), q.w());
pitch = osg:I_2;
roll = 0.0;
return;
}
if(Y1.z()<-0.9999)
{
heading = 2.0 * atan2(q.z(), q.w());
pitch = -osg::PI_2;
roll = 0.0;
return;
}
heading = atan2(-Y1.x(),Y1.y()); // 和Y轴夹角,所以是atan2(-x,y)
pitch = asin(Y1.z());
osg::Vec3d X1 = q * osg::Vec3d(1.0,0.0,0.0);
osg::Vec3d X2 = osg::Vec3d(Y1.y(),-Y1.x(),0.0);
osg::Quat temp;
temp.makeRotate(X2,X1);
double sinhalfangle = sqrt( temp.x() * temp.x() + temp.y() * temp.y() + temp.z() * temp.z() );
roll = 2.0 * atan2( sinhalfangle, temp.w() );
}
|
|