以下内容来自:
1、《OpenSceneGraph三维渲染引擎编程指南》肖鹏 刘更代 徐明亮 清华大学出版社
2、《OpenSceneGraph3.0三维视景仿真技术开发详解》国防工业出版社
3、自己的总结
产生目标场景视图的变换过程类似于用相机进行拍照,主要步骤为:
(1)把相机固定在三脚架上,让它对准场景(视图变换);
(1)对场景进行安排,使照片中各物体位于读者所希望的位置(模型变换);
(3)选择照相机镜头,并调整放大倍数(投影变换);
(4)确定最终照片的大小,如放大(视口变换)。
当完成上面步骤之后,就可以绘制场景了。视图可以简单理解为一个场景拍照。
视口(Viewport):将世界坐标系中的三维物体经过一系列几何变化(包括平移、选择和伸缩等),为了使显示的物体能以合适的位置、大小和方向显示出来,必须要通过投影,然后定义一个三维视景体,对物体进行裁剪,只使投影在视景体内的部分显示出来,然后在屏幕窗口内定义一个矩形,称为视口。视景体投影后的图形就在视口内显示,最后做一些适当变换,使图形在屏幕坐标系下显示。OSG包含SimpleViewer、Viewer、CompositeViewer三大视口类。
osg::Camera类继承自osg::Transform和osg::CullSetting类,用来管理OSG中的模型——视图矩阵。相机的管理主要是通过各种变换实现的。
1、视点变换:设置视点的方向和位置。默认情况下,视点定位为坐标原点,指向Y正方向。
//第1个参数是视点的位置
//第2个参数是参考点的位置,该点通常为场景中的中心轴上的点
//第3个参数是视点向上的方向向量
void setViewMatrixAsLookAt(const osg::Vec3d &eye, const osg::Vec3D ¢er, const osg::Vec3d &up)
void getViewMatrixAsLookAt(osg::Vec3d &eye, osg::Vec3d ¢er, osg::Vec3d &up, double lookDistance=1.0)
void getViewMatrixAsLookAt(osg::Vec3f &eye, osg::Vec3f ¢er, osg::Vec3f &up, float lookDistance=1.0)
2、模型变换:对模型的位置、大小和角度的变换。如位置变换节点(osg::PositionAttitudeTransform)和矩阵变换节点(osg::MatrixTransform)。
3、投影变换:经过上面的模型视景的转换后,场景中的物体放在了所希望的位置上,但由于显示器只能用二维图像显示三维物体,因此要靠投影来降低维数。事实上,投影变换的目的就是定义一个视景体,使视景体外多余的部分被裁减掉,最终进入图像的只是视景体内的有关部分。包括透视投影(Perspective Projection)和正视投影(Orthographic Projection)。
/*投影:透视投影(Perspective Projection)、正视投影(Orthographic Projection)*/
/*透视投影:透视视景体、对称透视视景体*/
/*透视视景体的函数*/
//设置/获取一个透视视图平截体的矩阵,并与当前矩阵相乘
//第1-4个参数分别是近裁减面的参数信息
//第5个参数表示视点距近裁减面的距离
//第6个参数表示视点距远裁剪面的距离
//zNear和zFar必须为正数
void setProjectionMatrixAsFrustum(double left, double right, double bottom, double top, double zNear, double zFar)
bool getProjectionMatrixAsFrustum(double &left, double &right, double &bottom, double &top, double &zNear, double &zFar)
/*对称透视视景体的函数*/
//使用对称透视视景体需要注意视野角度,如果调整不好会导致图形的变形,即宽屏变形问题
//设置/获取一个对称透视视图的平截头体的矩阵,并与当前矩阵相乘
//第1个参数表示yz平面视野角度
//第2个参数表示平截头的纵横比
//第3个参数表示视点距近裁减面的距离
//第4个参数表示视点距远裁剪面的距离
//必须为正数
void setProjectionMatrixAsPerspective(double fovy, double aspectRatio, double zNear, double zFar)
bool getProjectionMatrixAsPerspective(double &fovy, double &aspectRatio, double &zNear, double &zFar)
/*正射投影:正射投影、特殊正射投影*/
//使用正射投影矩阵把二维图形投影到二维屏时,需要指定zNear和zFar分别为-1.0和1.0,或者使用特殊正射投影矩阵达到渲染效果
/*正射投影的函数*/
//设置/获取一个平行正射投影矩阵,并与当前矩阵相乘
//第1-4个参数分别是近裁减面的参数信息
//第5个参数表示视点距近裁减面的距离
//第6个参数表示视点距远裁剪面的距离
//必须指定为正数且值不同
void setProjectionMatrixAsOrtho(double left, double right, double bottom, double top, double zNear, double zFar)
bool getProjectionMatrixAsOrtho(double &left, double &right, double &bottom, double &top, double &zNear, double &zFar)
/*特殊正射投影的函数*/
//设置/获取一个表示把二维投影坐标投影到屏幕上的矩阵,并与当前矩阵相乘
//第1-4个参数表示一个矩阵的信息
void setProjectionMatrixAsOrtho2D(double left, double right, double bottom, double top)
4、视口变换:将视景体内投影的物体显示在二维的视口平面上。即将经过几何变换、投影变换和裁剪变换后的物体显示于屏幕窗口内指定的区域内,这个区域通常为矩形,称为视口。
//设置/获取相机的视口
//第1-2个参数表示屏幕左下角的坐标
//第3个参数表示屏幕宽度
//第4个参数表示屏幕高度,在默认情况下,表示整个屏幕大小
void setViewport(osg::Viewport *viewport)
void setViewport(int x, int y, int width, int height)
const Viewport *getViewport() const
Viewport *getViewport()
5、裁剪变换:在OSG中,默认了6个裁剪平面以去除没有必要显示的物体。还可以定义其他裁剪平面来裁剪。定义裁剪平面的方法有很多,如osg::Scissor和osg::ClipPlane等。