目的是希望在漫游器做旋转操作时不按照场景中心,而是模型的中心来旋转。
我的做法是自定义了一个漫游器,继承自osgGA::TrackballManipulator,重写几个函数。
1.getInverseMatrix
父类默认的getInverseMatrix函数如下:
osg::Matrixd OrbitManipulator::getInverseMatrix() const
{
return osg::Matrixd::translate( -_center ) *
osg::Matrixd::rotate( _rotation.inverse() ) *
osg::Matrixd::translate( 0.0, 0.0, -_distance );
}
旋转相关的矩阵为_rotation,因此这个矩阵不能让它再改变了,可自定义成员函数作为旋转矩阵:
osg::Matrix m_rotationMat;
而这个旋转矩阵作用的中心应该是模型中心,可用getBound().center()来获取:
m_modelCenter = m_pSceneData->getBound().center();
修改后的getInverseMatrix函数:
osg::Matrixd MyCameraManipulator::getInverseMatrix() const
{
osg::Matrix m_viewMat = osg::Matrixd::translate(-_center) *
osg::Matrixd::rotate(_rotation.inverse()) *
osg::Matrixd::translate(0.0, 0.0, -_distance);
osg::Matrix invMat = osg::Matrixd::translate(-m_modelCenter) *
osg::Matrix::inverse(m_rotationMat) *
osg::Matrixd::translate(m_modelCenter) *
m_viewMat;
return invMat;
}
与getInverseMatrix同级的函数getMatrix似乎不对结果产生影响,不过还是可以简单修改一下:
osg::Matrixd MyCameraManipulator::getMatrix() const
{
return osg::Matrix::inverse(getInverseMatrix());
}
2.rotateTrackball
这个函数中在修改旋转矩阵,也就是将对_rotation的操作改作用到m_rotationMat:
void MyCameraManipulator::rotateTrackball(const float px0, const float py0, const float px1, const float py1, const float scale)
{
osg::Vec3d axis;
float angle;
trackball(axis, angle, px0 + (px1 - px0) * scale, py0 + (py1 - py0) * scale, px0, py0);
osg::Quat new_rotate;
new_rotate.makeRotate(angle, axis);
//_rotation = _rotation * new_rotate; //这句是父类本来的
m_rotationMat = m_rotationMat * osg::Matrix::rotate(new_rotate); //这句是修改的
}
以上应该可以做到旋转时以模型中心为旋转中心的效果了