OpenGL 坐标系理解失误点矫正

925 阅读3分钟

在编写代码的时候有几个点理解不好:

问题一:

做矩阵操作时,发现平移的量,还有某些图形的尺寸基本都是个小数,这个小数指的是什么?

问题二:

cameraFrame.moveForward(10);是向哪个方向移动的?这个10指的是什么?

相信有些初学的朋友会发现同样的误区,这是由于坐标系知识点不够扎实导致。接下来我们来完善下这个知识点。


世界坐标系

首先需要明确下:

  1. OpenGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且始终不变
  2. 窗口范围按此单位恰好是(-1,-1)(1,1)
    即屏幕左下角(-1,-1),屏幕右上角(1,1)
    
  3. 世界坐标系是右手坐标系,具有以下特点
    a. 右边为+x方向
    b. 上边为+y方向
    c. 垂直屏幕向外为+z方向
    

问题一解析:

通过对窗口及世界坐标系展示,我们可以看出,一个屏幕如果我们平移或者设置图形尺寸大小比较大,就会超出屏幕展示


GLFrame使用forward

GLFrame默认构造函数会将物体初始化为:

  1. 位置在(0,0,0)
  2. 屏幕上方为+y方向
  3. forward(0,0,-1)
    朝向世界坐标系的-z(垂直于纸面向里)
    意思就是当向里跑的时候,就是向着垂直纸面向里的方向跑。
    
  4. 屏幕左方为+x方向

在相机坐标系【右手坐标系】:相机位于原点(0, 0, 0)

a. 竖直向上为`+y`
b. 相机正对方向为`+z`
c  根据右手法则可以判断`+x`在屏幕左方

以上为GLFrame的默认构造,该默认构造很适合相机,但是并不适合模型。 所以在设置模型时,我们有时会设置如下:

modelFrame.SetForwardVector(0, 0, 1);

问题二解析

如果cameraFram保持初始化构造,那么直接moveForward(10),就是想屏幕里即-z(世界坐标系)方向行走10个单位。

如果使用以下配置。

# 相当于将原来的正方向为-z,改为+z
cameraFrame.SetForwardVector(0, 0, 1);

那么调用moveForward(10);就是向着屏幕外方向走10个单位。

注意此时朝向为屏幕外,可能看不到我们在屏幕里面绘制的值,需要再旋转照相机180度的方向才可以看到。

由此,我们发现,对于相机来说,最好还是保持其原有方向:

向前就是向着屏幕里面,也就是世界坐标系的-z,同时也方便我们直观去观察。


发散回溯 —— OpenGL坐标系

看到上面分析让我产生一个纠结点,如果不同的坐标系(物体,世界,惯性,相机)还不一样,有的是左手系,有的是右手系,那不是坑死了。

最后翻阅资料了解到,原来一开始的疏忽导致后续一系列的理解误区。

知识点如下:

  • OpenGL坐标系(物体、世界、照相机,惯性)属于右手坐标系
  • 设备坐标系,属于左手坐标系

配图如下:

坐标系图例


发散延伸 —— 坐标系转换流程

绘制物体时的坐标系。程序刚初始化时,世界坐标系和当前绘图坐标系是重合的。 只有对当前绘图坐标系进行平移,伸缩,变换后,世界坐标系和当前绘图坐标系不再重合。

物体的顶点起始坐标是局部坐标,之后会转换为世界坐标、观察者坐标、裁剪坐标等。

转换流程参考下图:

坐标系转换流程


总结

坐标系知识如果大轮廓搞混乱,后续理解方向会出现很多误区。针对这次的使用,无非就是坐标系知识理解不够扎实,最后又回溯到最根本位置:OpenGL坐标系都是右手系。

参考:

OpenGL自定义相机与模型:GLFrame

OpenGL-坐标系