OSG 绕坐标轴旋转正方向:
OSG学习 位置变换/旋转 矩阵连乘

旋转平移测试:

    osgViewer::Viewer viewer;
	osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");
	viewer.setCameraManipulator(new osgGA::OrbitManipulator);
	viewer.setUpViewOnSingleScreen(0);
	viewer.setUpViewInWindow(100, 100, 1024, 768);
	osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
	mt->addChild(node);
	//先向Z轴向上平移50,绕X轴正方向旋转90度,绕Z轴正方向旋转45度:
	mt->setMatrix(osg::Matrix::translate(0, 0, 50)* osg::Matrix::rotate(osg::PI_2, osg::X_AXIS)* osg::Matrix::rotate((osg::PI_2) / 2.0, osg::Z_AXIS));
	osg::ref_ptr<osg::Group> root = new osg::Group;
	root->addChild(node);
	root->addChild(mt);
	viewer.setSceneData(root);
	viewer.run();
	getchar();

效果:
OSG学习 位置变换/旋转 矩阵连乘

	//绕X轴正方向旋转90度,绕Z轴正方向旋转45度,最后向Z轴向上平移50,:
	mt->setMatrix( osg::Matrix::rotate(osg::PI_2, osg::X_AXIS)* osg::Matrix::rotate((osg::PI_2) / 2.0, osg::Z_AXIS)*osg::Matrix::translate(0, 0, 50));

OSG学习 位置变换/旋转 矩阵连乘

//移动连乘 
mt->setMatrix(osg::Matrix::translate(0, 0, 50)*osg::Matrix::translate(0, 0, -60)*osg::Matrix::translate(20, 0, 0));
//相当于 mt->setMatrix(osg::Matrix::translate(20, 0, -10));

矩阵连乘效果:从左至右依次变换
知道矩阵连乘就可以计算漫游器位置了:假设漫游器视点与Z轴(),Y轴夹角都是45度,距离目标中心点center(20,20,20*sqrt(2))距离为20那么就可以计算得到漫游器(eye)的位置,

OSG学习 位置变换/旋转 矩阵连乘

计算方法:center坐标加上延视角反方向长度为dis的向量对应坐标 即center坐标加上图中点p坐标
(注意旋转方向,确定旋转角度的正负号,图中与Y轴夹角是绕Z轴负方向旋转的,与Z轴夹角是绕X轴负方向旋转的)

float dis = 20;
float theta_z = -osg::PI_2 / 2;
float theta_y = -osg::PI_2 / 2;
osg::Vec3f center(20.0, 20.0, 20.0*sqrt(2));
osg::Vec3f eye = center + osg::Vec3f(0.,0.,0.)*osg::Matrix::translate(0., 0., -dis)*osg::Matrix::rotate(theta_z, osg::X_AXIS)* osg::Matrix::rotate(theta_y, osg::Z_AXIS);//center+p
std::cout << "vec x:" << vec.x() << " y:" << vec.y() << " z:" << vec.z() << std::endl;

结果:
OSG学习 位置变换/旋转 矩阵连乘

//上述center + p同于 
osg::Vec3f eye = osg::Vec3f(0.,0.,0.)*osg::Matrix::translate(0., 0., -dis)*osg::Matrix::rotate(theta_z, osg::X_AXIS)* osg::Matrix::rotate(theta_y, osg::Z_AXIS)*osg::Matrix::translate(center);
//相当于从点p沿视角方向移动center向量长度:从原点沿视角移动center向量长度位置为center,从p移动沿视角移动center向量长度位置为eye

//这种方式也是 osgGA::OrbitManipulator漫游器中计算相机当前位置的方法(源码位置osgGA OrbitManipulator.cpp)
/** Get the position of the manipulator as 4x4 matrix.*/
osg::Matrixd OrbitManipulator::getMatrix() const  //得到相机的位置变换矩阵
{//先平移至Z轴正上方dis处,后对其旋转,最后沿视角位移center长度
    return osg::Matrixd::translate( 0., 0., _distance ) * //与_center的距离 
           osg::Matrixd::rotate( _rotation ) *             //旋转
           osg::Matrixd::translate( _center );            //移动center长度
}

也可以用四元组来计算点p的坐标:osg::Quat*vec表示对向量vec按照Quat进行旋转:

//用四元数进行计算
osg::Vec3f eye = center + osg::Quat(theta_z, osg::X_AXIS, 0.0, osg::Y_AXIS, theta_y, osg::Z_AXIS)*osg::Vec3f(0., 0., -dis);

//在 osgGA::OrbitManipulator.cpp中使用四元数来计算eye的坐标
void OrbitManipulator::getTransformation( osg::Vec3d& eye, osg::Quat& rotation ) const
{
    eye = _center - _rotation * osg::Vec3d( 0., 0., -_distance );
    rotation = _rotation;
}

当然可以手动计算eye的位置:
OSG学习 位置变换/旋转 矩阵连乘```
float dis = 20;
float theta_1 = osg::PI_2 / 2;
float theta_2 = osg::PI_2 / 2;
osg::Vec3f center(20.0, 20.0, 20.0*sqrt(2));
float delt_z = dis * cosf(theta_1);
float len = dis * sinf(theta_1);
float delt_x = len * sinf(theta_2);
float delt_y = len * cosf(theta_2);
osg::Vec3f eye = center - osg::Vec3f(delt_x, delt_y, delt_z);

结果同上

相关文章: