1.矩阵的基本概念
矩阵变换是osg中最常见的操作。在osg中,与矩阵有关的操作大都是由osg::Matrix类来完成的。其保存的是一个4*4的矩阵,共包含了16个浮点数,并提供了相应的运算操作。此外Matrix类不是由Referenced派生的,因此不能实现引用计数。
Matrix提供了与C++二维列数组相一致的接口,所以我们可以采用以下形式为矩阵元素赋值:
osg::Matrix m;
m(0,1)=0.f; //设置第二个元素(第0行第1列)
m(1,2)=0.f; //设置第七个元素(第1行第2列)
// 设置矩阵的所有16 个值:
m.set( 1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
10.f, 0.f, 0.f, 1.f ); // X 方向移动 10
其中单位矩阵可采用此方法定义:
osg::Matrix mt=osg::Matrix();
2.矩阵的平移旋转缩放操作
平移旋转缩放是osg矩阵操作中最常见的三个操作,而实现几何数据的变换需要通过osg::Transform节点类家族来实现的,其继承自Group类,它可以有多个子节点。但是Transform类是一个虚基类。用户应当使用osg::MatrixTransform或osg::PositionAttitudeTransform来替代它。它们提供了不同的变换接口,根据用户程序的需要,可以使用其中任意一个或者同时使用这两者。我们这里主要用的是osg::MatrixTransform,在其下通过setMatrix()函数设置矩阵,并将要变换的模型挂接到其下即可实现变换。
下面给出具体示例(在osg中,x轴方向平行屏幕向右,y轴方向垂直屏幕向里,z轴方向平行屏幕向上)。
平移:
osg::ref_ptr root=new osg::Group();
osg::ref_ptr osgcool=osgDB::readNodeFile("cow.osg");
osg::ref_ptr trans=new osg::MatrixTransform();
trans->setMatrix(osg::Matrix::translate(0,0,20));
trans->addChild(osgcool.get());
root->addChild(trans.get());
其中 trans->setMatrix(osg::Matrix::translate(0,0,20))就是用来平移物体的,在这表示向Z轴正方向平移也就是屏幕正上方平移20个单位。
缩放:
osg::ref_ptr root=new osg::Group();
osg::ref_ptr osgcool=osgDB::readNodeFile("cow.osg");
osg::ref_ptr trans=new osg::MatrixTransform();
trans->setMatrix(osg::Matrix::scale(0.5,0.5,0.5));
trans->addChild(osgcool.get());
root->addChild(trans.get());
osg::Matrix::scale(0.5,0.5,0.5)就是用来缩放物体的,在这也就是原来物体的一半大小。
旋转:
osg::ref_ptr root=newosg::Group();
osg::ref_ptrosgcool=osgDB::readNodeFile("cow.osg");
osg::ref_ptrtrans=new osg::MatrixTransform;
trans->setMatrix(osg::Matrix::rotate(osg::DegreesToRadians(90.0),0,1,0));
trans->addChild(osgcool.get());
root->addChild(trans.get());
osg::Matrix::rotate(osg::DegreesToRadians(90.0),0,1,0)该方法参数分别表示角度(角度转弧度),x,y,z表示旋转轴的方向向量。当角度为正值的时候,物体绕着x,y,z箭头指向向右旋转,否则物体绕着x,y,z箭头指向向左旋转。
3.矩阵的级联功能
Matrix 提供了完整的向量-矩阵乘法和矩阵级联的功能。要使 Vec3 变量 v 沿着新的原点矩阵 T,按照矩阵 R 执行旋转变换,只需要以下的代码:
osg::Matrix T;
T.makeTranslate(x,y,z);
osg::Matrix R;
R.makeRotate(angle,axis);
osg::Vec3 vPrime=v*R*T;
Matrix 采用了左乘(premultiplication)操作,这一点与 OpenGL 文档中所述的v' = TRv 正好相反。如果要对一个 Geode 使用上述变换,首先应该创建一个包含矩阵 T 的 MatrixTransform 节点,向其添加一个包含矩阵 R 的 MatrixTransform 子节点,然后再向这个旋转变换节点添加子节点 Geode 。
此外在一个MatrixTransform中对于平移T、旋转R、缩放S三种变换矩阵的组合,应该按如下顺序:M -> setMatrix( S * R * T )。按此顺序很重要的一个原因就是,旋转和缩放这样的变换一般是针对物体坐标系的原点进行的。缩放以原点为中心的对象与缩放已离开原点的对象所得到的结果不同。 同样,旋转以原点为中心的对象与旋转已离开原点的对象所得到的结果也不同。
4.几个重要函数
最后,列举矩阵中几个重要函数:
osg::Matrixd m;
osg::Matrixd inverse_m=osg::Matrixd::inverse(m);//求矩阵m的逆矩阵
osg::Vec3d v=m.getTrans(); //得到矩阵的平移量
osg::Quat quat_m=m.getRotate(); //得到旋转的四元数,也可以理解为将矩阵转换成四元数
/*
osg::Matrixd d;
d.setRotate(m_quat); //将四元数m_quat转化成矩阵d
osg::Vec3d rotateAix;
double angle;
m_quat.getRotate(angle,rotateAix); //得到旋转中心和旋转轴
*/
5.有关矩阵更多操作可以参看源码,其目录位于:OpenSceneGraph\src\osg中的以下cpp文件中