简述
和其他三维引擎一样,模型的矩阵操作是比不可少的。 osg中有一个专门的类来处理。即osg::MatrixTransform类。同样osg::MatrixTransform这个类的祖宗类也是osg::Group, 继承类osg::Group所有的特性。所以它可以当一个子节点加入到根节点Root中。也可以当父亲节点添加很多子节点,这样当对它进行移动等矩阵变换时,它所有的子节点都会相应变换。
这里还涉及到另外一个类osg::Matrixd,这个类是一个矩阵类,被当成参数传入osg::MatrixTransform,以实现模型的矩阵变换。
其中osg::Matrixd实现了一些静态函数可以直接调用
移动
static Matrixd | translate (const Vec3f &dv) |
staticMatrixd | translate (const Vec3d &dv) |
staticMatrixd |
translate (value_type x, value_type y, value_type z)
|
缩放
static Matrixd | scale (const Vec3f &sv) |
staticMatrixd | scale (const Vec3d &sv) |
staticMatrixd |
scale (value_type sx, value_type sy, value_type sz)
|
旋转
static Matrixd | rotate (const Vec3f &from, const Vec3f &to) |
staticMatrixd | rotate (const Vec3d &from, const Vec3d &to) |
staticMatrixd | rotate (value_type angle, value_type x, value_type y, value_type z) |
staticMatrixd | rotate (value_type angle, constVec3f &axis) |
staticMatrixd |
rotate (value_type angle, const Vec3d &axis)
|
矩阵操作的简单流程
(1) 实例化一个MatrixTransform对象
osg::ref_ptr
(2)添加一个子节点
osg::ref_ptr
mt->addChild(cow);
(3)设置矩阵,先向x轴移动30, 绕x轴旋转90度, 再缩放到原来的0.2倍
mt->setMatrix(osg::Matrix::translate(osg::Vec3(30, 0, 0)) *
osg::Matrix::rotate(90, osg::Vec3d(1, 0, 0)) *
osg::Matrix::scale(osg::Vec3(0.2, 0.2, 0.2)) );
注:--如果 移动和缩放效果要累加,矩阵相乘即可。不能多次调用setMatrix函数,后面的会覆盖掉前面的
下面的是错误做法,只会缩放到原来的0.2倍
mt->setMatrix(osg::Matrix::translate(osg::Vec3(30, 0, 0)));
mt->setMatrix(osg::Matrix::rotate(90, osg::Vec3d(1, 0, 0)));
mt->setMatrix(osg::Matrix::scale(osg::Vec3(0.2, 0.2, 0.2)));
--矩阵相乘一般不满足交换律,所有前后顺序不能任意变动,否则会出现不同的效果
这样设置和上面的效果是不同的
mt->setMatrix(osg::Matrix::scale(osg::Vec3(0.2, 0.2, 0.2)) *
osg::Matrix::translate(osg::Vec3(30, 0, 0)) *
osg::Matrix::rotate(90, osg::Vec3d(1, 0, 0)));
实现
int main()
{
osg::ref_ptr viewer = new osgViewer::Viewer;
osg::ref_ptr root = new osg::Group;
osg::ref_ptr glider = osgDB::readNodeFile("glider.osg");
osg::ref_ptr mt = new osg::MatrixTransform;
osg::ref_ptr cow= osgDB::readNodeFile("cow.osg");
mt->addChild(cow);
mt->setMatrix( osg::Matrix::translate(osg::Vec3(30, 0, 0)) * osg::Matrix::rotate(90, osg::Vec3d(1, 0, 0)) * osg::Matrix::scale(osg::Vec3(0.2, 0.2, 0.2)));
root->addChild(glider);
root->addChild(mt);
viewer->setSceneData(root);
viewer->addEventHandler(new osgViewer::WindowSizeHandler);
return viewer->run();
return 0;
}