1. 程式人生 > >OSG學習 位置變換/旋轉 矩陣連乘

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();

效果: 在這裡插入圖片描述

	//繞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));

在這裡插入圖片描述

//移動連乘 
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)的位置,

在這裡插入圖片描述

計算方法: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;

結果: 在這裡插入圖片描述

//上述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的位置: 在這裡插入圖片描述``` 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);

結果同上