OpenGL中的坐标系

来源:互联网 发布:js input text 只读 编辑:程序博客网 时间:2024/06/06 01:20

视图模型变换过程就是一个将顶点坐标从世界坐标系变换到视觉坐标系的过程。这里很重要的是对两个坐标系的认识。

世界坐标系,也称为全局坐标系它是一个右手坐标系,可以认为该坐标系是固定不变的,在初始态下,其x轴为沿屏幕水平向右,y轴为沿屏幕垂直向上,z轴则为垂直屏幕面向外指向用户,当然,如果在程序中对视点进行了转换,就不能再认为是这样的了。

视觉坐标系,也称为局部坐标系它是一个左手坐标系,该坐标系是可以活动的。在初始态下,其原点及x,y轴分别与世界坐标系的原点及x,y轴重合,而z轴则正好相反,即为垂直屏幕面向内。


--------------------------------------------------------------------------------

OPENGL坐标系可分为:世界坐标系和当前绘图坐标系。用过ANSYS的应该很清楚,呵呵。

世界坐标系以屏幕中心为原点(0, 0, 0)。你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。长度单位这样来定:窗口范围按此单位恰好是(-1,-1)到(1,1)。

当前绘图坐标系是绘制物体时的坐标系,就是模型坐标系。程序刚初始化时,世界坐标系和当前绘图坐标系是重合的。当用glTranslatef(),glScalef(), glRotatef()对当前绘图坐标系进行平移、伸缩、旋转变换之后, 世界坐标系和当前绘图坐标系不再重合。改变以后,再用glVertex3f()等绘图函数绘图时,都是在当前绘图坐标系进行绘图,所有的函数参数也都是相 对当前绘图坐标系来讲的。

世界坐标是OpenGL中用来描述场景的坐标,Z+轴垂直屏幕向外,X+从左到右,Y+轴从下到上,是右手笛卡尔坐标系统。我们用这个坐标系来描述物体及光源的位置。

将物体放到场景中也就是将物体平移到特定位置、旋转一定角度,这些操作就是坐标变换。OpenGL中提供了glTranslate*/glRotate*/glScale*三条坐标变换命令,利用OpenGL的矩阵运算命令,则可以实现任意复杂的坐标变换。

非常重要:OpenGL 中有一个坐标变换矩阵栈(ModelView),栈顶就是当前坐标变换矩阵,进入OpenGL管道的每个坐标(齐次坐标)都会先乘上这个矩阵,结果才是对应点在场景中的世界坐标。OpenGL中的坐标变换都是通过矩阵运算完成的,与图形学课本的描述完全一致。要注意的是变换中的矩阵乘法是左乘,而矩阵乘法与算术乘法不同,不符合交换律(万一不明白去看矩阵代数书好了)。

glTranslate*(x,y,z):平移,参数为各轴向的移动量。
glRotate(d,x,y,z):旋转,第一个参数为转动的度数,后三个参数表明是否绕该轴旋转。通常x,y,z中只有一个为1,其余为0,用连续几条旋转命令完成复杂旋转。由于矩阵运算的左乘特点,旋转命令的顺序与旋转动作的顺序正好相反。

考察下面利用三个变换绘制顶点的代码:

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glMultMatrixf(N); /* apply transformation N */

glMultMatrixf(M); /* apply transformationM */

glMultMatrixf(L); /* apply transformation L */

glBegin(GL_POINTS);

glVertex3f(v); /* draw transformed vertexv */

glEnd();

    在这个过程中,GL_MODELVIEW状态相继引入了I(单位阵)、NML矩阵。变换后的顶点为NMLv。因此,顶点的变换为N(M(Lv)),即是先作变换L,然后是变换M最后才是N。这里,顶点v的实际变换顺序正好与指定的顺序相反。

  • 视图变换

    视图变换改变视点的位置和方向,也就是改变视觉坐标系。在世界坐标系中,视点和物体的位置是一个相对的关系,对物体作一些平移、旋转变换,必定可以通过对视点作相应的平移、旋转变换来达到相同的视觉效果。完成视图变换可以有以下几种方法:

    (1).

利用一个或几个造型变换命令(即glTranslate*()glRotate*())。由于这些命令也是在GL_MODELVIEW状态下执行的,所以较难和那些造型变换命令区分开来,移动视点的变换和移动物体的变换很容易混淆。为了便于建立清晰的物体和场景模型,可以认为只有其中一个变换在起作用,比如认为只有模型变换的话,那么glTranslate*()glRotate*()将统一被视为对物体的变换。

(2).利用实用库函数gluLookAt()设置视觉坐标系。在实际的编程应用中,用户在完成场景的建模后,往往需要选择一个合适的视角或者不停地变换视角,以对场景作观察。实用库函数gluLookAt()就提供了这样的一个功能。

void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,

      GLdouble centerx,GLdouble centery,GLdouble centerz,

      GLdouble upx,GLdouble upy,GLdouble upz);

该函数定义一个视图矩阵,并与当前矩阵相乘。

eyex, eyey,eyez

指定视点的位置

centerx,centery,centerz

指定参考点的位置

upx,upy,upz

指定视点向上的方向

(3).创建封装旋转和平移命令的实用函数。有些应用需要用简便方法指定视图变换的定制函数。例如,在飞机飞行中指定滚动、俯仰和航向旋转角,或对环绕对象运动的照相机指定一种利用极坐标的变换。

物体坐标是以物体某一点为原点而建立的“世界坐标”,该坐标系仅对该物体适用,用来简化对物体各部分坐标的描述。物体放到场景中时,各部分经历的坐标变换相同,相对位置不变,所以可视为一个整体,与人类的思维习惯一致。

眼坐标是以视点为原点,以视线的方向为Z+轴正方向的坐标系中的方向。OpenGL管道会将世界坐标先变换到眼坐标,然后进行裁剪,只有在视线范围(视见体)之内的场景才会进入下一阶段的计算。

同样的,有投影变换矩阵栈(Projection),栈顶矩阵就是当前投影变换矩阵,负责将场景各坐标变换到眼坐标,由所得到的结果是裁剪后的场景部分,称为裁剪坐标。前面提到过的视见体设定其实就是在建立该矩阵。

设备坐标:OpenGL 的重要功能之一就是将三维的世界坐标经过变换、投影等计算,最终算出它在显示设备上对应的位置,这个位置就称为设备坐标。在屏幕、打印机等设备上的坐标是二维坐标。值得一提的是,OpenGL可以只使用设备的一部分进行绘制,这个部分称为视区或视口(viewport)。投影得到的是视区内的坐标(投影坐标),从投影坐标到设备坐标的计算过程就是设备变换了。

矩阵栈切换:glMatrixMode(GL_MODELVIEWING或GL_PROJECTION);本命令执行后参数所指矩阵栈就成为当前矩阵栈,以后的矩阵栈操纵命令将作用于它。

矩阵栈操纵命令:
glPushMatrix(); 当前矩阵入栈,这时矩阵栈将栈顶值压入栈。
glPopMatrix(); 栈顶出栈,通常与上一条命令配合使用。
glLoadIdentity(); 将栈顶设为不变矩阵(就是对角线全为1其它为0的那个)。
glMultMatrix(M);将栈顶T设为M·T。

------------------------------------------------------------------

从三维物体到二维图象,就如同用相机拍照一样,通常都要经历以下几个步骤:

  1、将相机置于三角架上,让它对准三维景物,它相当于OpenGL中调整视点的位置,即视点变换(Viewing Transformation)。

  2、将三维物体放在场景中的适当位置,它相当于OpenGL中的模型变换(Modeling Transformation),即对模型进行旋转、平移和缩放。

  3、选择相机镜头并调焦,使三维物体投影在二维胶片上,它相当于OpenGL中把三维模型投影到二维屏幕上的过程,即OpenGL的投影变换(Projection Transformation),OpenGL中投影的方法有两种,即正射投影和透视投影。为了使显示的物体能以合适的位置、大小和方向显示出来,必须要通过投影。有时为了突出图形的一部分,只把图形的某一部分显示出来,这时可以定义一个三维视景体(Viewing Volume)。正射投影时一般是一个长方体的视景体,透视投影时一般是一个棱台似的视景体。只有视景体内的物体能被投影在显示平面上,其他部分则不能。

  4、冲洗底片,决定二维相片的大小,它相当与OpenGL中的视口变换(Viewport Transformation)(在屏幕窗口内可以定义一个矩形,称为视口(Viewport),视景体投影后的图形就在视口内显示)规定屏幕上显示场景的范围和尺寸。

  通过上面的几个步骤,一个三维空间里的物体就可以用相应的二维平面物体表示了