OSG學習 位置變換/旋轉 矩陣連乘
阿新 • • 發佈:2018-12-17
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);
結果同上