查看: 4657|回复: 7

OSG坐标问题

[复制链接]

该用户从未签到

发表于 2008-5-9 15:37:21 | 显示全部楼层 |阅读模式
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中的Y,Z互换了,不知道是不是这样的,我问一些网友说是这样的,但是我始终找不到官方的资料说这坐标问题,所以很疑惑。
今天看快速入门最后一章一个例子时又产生了疑惑,代码如下
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一致,我想应该不至于这样吧,但是一直找不到相关的资料,希望高手解惑!!!

该用户从未签到

 楼主| 发表于 2008-5-9 15:48:36 | 显示全部楼层
希望能给我们这些新手详细的讲解一下坐标的问题。

该用户从未签到

发表于 2008-5-9 17:10:25 | 显示全部楼层
首先,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的世界坐标系并没有发生任何变化

该用户从未签到

 楼主| 发表于 2008-5-9 18:32:52 | 显示全部楼层
谢谢你的讲解!!
首先我在OSGQSG中真的没有看到这些叙述,我前些时问一个网友他是说Y向屏幕外,也就是说Z和Y换了下,相对于OpenGL而言。所以一直觉得很困惑。
其次,我的意图不是要牛向下移动12个单位,而是我认为摄像机的指向是沿Y的负方向(因为我看OpenGL指南上面说的是默认的摄像机指向Z轴负方向)如果按照Z和Y就是互换下,那么这里就是说应该是Y坐标值为-12,另外OpenGL指南上面说的摄像机坐标应该就是视点坐标,而setProjectionMatrixAsPerspective应该是指定的投影矩阵吧,投影矩阵应该不会和视点有关系吧,为什么说摄像机采用透视投影的方式,因此它面向XY平面,这个点也很疑惑,难道OSG和OpenGL的那些矩阵不是对应的吗?书上说的是模型视图矩阵就是移动物体和相机的,而投影矩阵是定义视景体的,就相当于个焦距吧,视口变换是定义屏幕窗口大小的,这些在OSG中都是怎么定义的呢?由于是三维已经OpenGL的初学者所以对这些东西都不是很清楚,希望能耐心讲解。

该用户从未签到

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

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

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

该用户从未签到

 楼主| 发表于 2008-5-10 23:55:43 | 显示全部楼层
谢谢了,我自己再琢磨下

该用户从未签到

发表于 2008-5-11 00:07:24 | 显示全部楼层
不论是OPENGL还是OSG,都采用是右手系,

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



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


这跟Directx是不一样的,Directx采用左手坐标系,即z轴正向朝里;y轴正向朝上;x轴正向朝右.




该用户从未签到

发表于 2010-8-10 15:59:55 | 显示全部楼层
在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平面的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表