OSG坐标问题

该博客探讨了OpenGL和OSG坐标系统的不同,指出OSG坐标系统是X向右,Y向内,Z向上的右手坐标系,与OpenGL相比存在90度旋转。文章通过代码示例解释了视点和旋转矩阵如何影响场景显示,并强调了摄像机坐标系在透视投影中的作用。作者强调理解摄像机坐标系的重要性,并澄清了混淆世界坐标系和观察矩阵的常见误解。
摘要由CSDN通过智能技术生成
v->push_back( osg::Vec3( -1.f, 0.f, -1.f ) );
v->push_back( osg::Vec3( 1.f, 0.f, -1.f ) );
v->push_back( osg::Vec3( 1.f, 0.f, 1.f ) );
v->push_back( osg::Vec3( -1.f, 0.f, 1.f ) );


这是一个快速入门上面第一个例子的部分代码,将其中的顶点坐标取值和OpenGL中的相应顶点取值比较可以猜测OSG的
坐标系统是X向右,Y向屏幕外,Z向上,也就是说OSG的坐标系统与OpenGL中的YZ互换了,不知道是不是这样的,我问一些网友说是这样的,但是我始终找不到官方的资料说这坐标问题,所以很疑惑。
今天看快速入门最后一章一个例子时又产生了疑惑,代码如下
 

osgViewer::Viewer viewer;
viewer.setSceneData( osgDB::readNodeFile( "cow.osg" ) );
viewer.getCamera()->setProjectionMatrixAsPerspective( 40., 1., 1., 100. );
// 创建矩阵,指定到视点的距离。
osg::Matrix trans;
trans.makeTranslate( 0., 0., -12. );
// 旋转一定角度(弧度值)。
double angle( 0. );
while (!viewer.done())
{
  // 创建旋转矩阵。
  osg::Matrix rot;
  rot.makeRotate( angle, osg::Vec3( 1., 0., 0. ) );
  angle += 0.01;
  // 设置视口矩阵(旋转矩阵和平移矩阵连乘)。
  viewer.getCamera()->setViewMatrix( rot * trans );
  // 绘制下一帧
  viewer.frame();
}


这里感到疑惑之一是trans.makeTranslate( 0., 0., -12. );
为什么这里改变Z的坐标,那么按照我上面的OSG坐标来说的话,这里是将相机向下移动了12个单位吧,为什么不是改变Y的坐标呢,难道视点不是指向Y的吗?
rot.makeRotate( angle, osg::Vec3( 1., 0., 0. ) );
这里也是,当我改为rot.makeRotate( angle, osg::Vec3( 0.,1., 0. ) );时牛不是沿Y旋转而是沿Z旋转
所以我现在得出的结论是写顶点坐标时,OSG的Y,Z坐标和OpenGL相反,而写矩阵时又和OpenGL一致,我想应该不至于这样吧,但是一直找不到相关的资料,希望高手解惑!!!

 

首先,OSG的坐标系是这样的:X向右,Y向屏幕里,Z向上,因此它符合右手坐标系;与OpenGL相比,它的坐标系相当于绕X轴正向逆时针旋转了90度。这一点在OSGQSG中有叙述,您可以再仔细找一下。

至于您遇到的困惑,我想主要是您混淆了三维世界和观察矩阵的概念~~如果您希望牛能够向下移动12个单位,同时绕X轴旋转的话,可以给它一个MatrixTransform的父节点,并且将变换矩阵传递给这个MatrixTransform节点。
但是在您的程序中,rot*trans的矩阵连乘操作是针对场景的主摄像机,即:
viewer.getCamera()->setViewMatrix( rot * trans );
那么也就是说,您修改的是摄像机的观察矩阵:即,在摄像机坐标系中,三维世界相对于摄像机的位置。
摄像机坐标系是由setProjectionMatrixAsPerspective决定的,也就是说,您的摄像机采用透视投影的方式,因此它面向XY平面,视野夹角40度,原点与世界原点暂时是重合的。(此时如果直接运行程序,可以看到一片黑,因为摄像机完全在牛模型的体内)
然后,三维世界沿着Z负方向移动了12个单元,此时您可以看见牛了。
之后,您选择沿X方向旋转三维世界(此处也就是旋转牛),由于摄像机面对着XY平面(Y向上),所以模型相当于横着滚动。此时请不要再用世界坐标系来理解您看到的景象了,因为有透视投影的关系,摄像机本身已经是面对XY平面的~~OSG的世界坐标系并没有发生任何变化

Y的方向是向里的,这一点您可以做实验来验证。三维仿真系统的坐标系和真实世界一样,都是右手坐标系。除此之外,请一定相信OSG和OpenGL的矩阵运算方法之间没有任何矛盾之处,这个坐标系的偏差也不会对场景的运算产生任何影响。因此请不要单纯地用Y/Z互换来解释您看到的现象,最起码来说,OSG和OpenGL的坐标系Y/Z轴是不能互换的,两者相差了90度!

这里关键的问题是setViewMatrix函数到底做了什么:它的作用并非是让摄像机运动!而是让整个三维世界·按照摄像机坐标系(而非绝对坐标系)·实现运动
那么,摄像机坐标系是由谁来定义的呢?显然它不应当与世界坐标系重合。我的理解是视点的变换改变了摄像机坐标系的旋转姿态,就如同自然世界中的我们不改动相机三脚架位置,而仅仅是调整相机使其对准某个方向一样。所谓的透视投影矩阵,其作用同样是调整视点,对于OSG来说,也就是改变摄像机坐标系的旋向。
透视投影矩阵和正交矩阵的有关定义请参阅OpenGL红宝书的相关解释,在第四版的86页可以找到下面的语句:
“可以通过旋转和平移来改变函数gluPerspective创建的视景体的朝向,如果不进行这些变换,视点将位于原点,视线指向Z轴负方向”。
这也就是我为什么说“摄像机坐标系是由setProjectionMatrixAsPerspective决定的,它面向XY平面”的原因。

如果您能够同意我对于摄像机坐标系的诠释。那么后面的问题就迎刃而解了,请参阅我第一次回帖中的解释。

 

不论是OPENGL还是OSG,都采用是右手系,

opengl坐标系,即z轴正向朝外;y轴正向朝上;x轴正向朝右.
osg坐标系,即z轴正向朝上;y轴正向朝前;x轴正向朝右.


可以这么来说,将opengl坐标系沿x轴沿前下方旋转90度,即osg的默认坐标系.


这跟Directx是不一样的,Directx采用左手坐标系,即z轴正向朝里;y轴正向朝上;x轴正向朝右.
在viewer.getCamera()->setProjectionMatrixAsPerspective( 40., 1., 1., 100. );之前,
osg::Vec3 vecEye, vecCenter, vecUp;
采用viewer.getCamera()->getViewMatrixAsLookAt(vecEye, vecCenter, vecUp);
可以看到:
vecEye = {0.0, 0.0, 0.0};
vecCenter = {0.0, 0.0, -1.0};
vecUp = { 0.0, 1.0, 0.0 };
由此可以看出在设置透视之前,镜头是对准XOY平面的

 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙行天下01

你的鼓励将是我的最大写作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值