http://www.cocoachina.com/ios/20141107/10155.html
先科普一下投影矩阵(Projection Matrix)这个概念。
投影矩阵(Projection Matrix)
所谓投影变换,就是将你的视觉坐标系转换到标准坐标系,使用不同的投影变换,所得出的效果也不尽相同。
我们要介绍的是两种投影变换:正交法(Orthographic)和透视法(Perspective)。
下边的示意图中,左边的是透视法,右边是正交法,观察点位于坐标系远点。
理解透视法比较容易,因为透视就是我们平时眼睛看到事物的基本方式。正交法虽然会难一点,但是不用担心,因为你刚刚做完的“正方体”其实就是正交投影的观察结果。
想象一下你站在铁轨上,沿着铁轨看过去,你所看到的景象就是透视,如下:
而如果是在正交视角下看的话,上面这张图会变得畸形而且铁路的两侧永远都是平行的。
在下面的这张图里面,你会看到另一种投影透视法,它是一个被削尖的金字塔形,金字塔中的是你视觉感受到的实物场景,这一场景会投影到金字塔的横截面上,而这个横截面其实就是你的设备屏幕。
好了,现在我们知道Metal对所有的物体都采用了正交投影法,所以我们要做的就是将其转换为透视投影,同样的,这种转换我们也需要使用到矩阵。
为了简化整个将你的正方体放进金字塔模型中的过程。我们需要创建一个投影矩阵来描述上面说的金字塔模型,并且将其绘制到你统一的代码框架中。
iOS中已经提供了创建透视投影矩阵的方法,所以我们只需尽情使用就好了。
iOS中创建正交投影的函数
//创建透视投影矩阵--这样就能创建一个正交投影了!
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(75.0), aspect, 0.1f, 100.0f);
OPENGL坐标系可分为:世界坐标系和当前绘图坐标系。
世界坐标系:在OpenGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的。你面对
屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。长度单位这样来定:
窗口范围按此单位恰好是(-1,-1)到(1,1),即屏幕左下角坐标为(-1,-1),右上角
坐标为(1,1)。
当前绘图坐标系:是绘制物体时的坐标系。程序刚初始化时,世界坐标系和当前绘图坐标系是重合
的。当用glTranslatef(),glScalef(), glRotatef()等对当前绘图坐标系进行平移、
注意,这里的平移旋
将当前绘图坐标系看做一个整体在世界坐标系中进行旋转平移。然后,改变以
后,再用glVertex3f()等绘图函数绘图时,都是在当前绘图坐标系进行绘图,所有的
函数参数也都是相对当前绘图坐标系来讲的。
OPENGL坐标变换很有特点,为了简单描述先定义2个坐标系:
(1)世界坐标系:
无论如何变换,世界坐标系都不动,以屏幕中心为原点(0, 0, 0),你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。
(2)当前绘图坐标系(即局部坐标系):
当前绘图坐标系是绘制物体时的坐标系。程序刚初始化时,世界坐标系和当前绘图坐标系是重合的,当用glTranslatef()等变换函数做移动和旋转时,都是改变的当前绘图坐标系,改变的位置都是当前绘图坐标系相对自己的x,y,z轴所做的改变,改变以后,再绘图时,都是在当前绘图坐标系进行绘图,所有的函数参数也都是相对当前绘图坐标系来讲的。
glLoadIdentity():另当前绘图坐标系从新回到世界坐标系的位置,另他们重合。
glTranslatef(x,y,z):使整个绘图坐标系相对世界坐标系沿x,y,z轴移动x,y,z个单位,注意:这里是让整个绘图坐标系进行移动 这一点要明白!!!
如下:
//先将整个绘图坐标系旋转 然后再将整个绘图坐标系 按照绘图坐标系的方向进行 移动
//由于每次绘图时顶点坐标并没有变化 所以再次绘图时相当于重新开始绘图
//方法一:
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, 0.2, 0.0f, 0.0f, 1.0f);
// modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 1.0f, 1.0f, -1.0f);
modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 0.0f, 1.0f, 0.0f);
//先将整个绘图坐标系按照绘图坐标系的方向进行移动 然后再将整个绘图坐标系 按照绘图坐标系的方向进行 旋转
//由于每次绘图时顶点坐标并没有变化 所以再次绘图时相当于重新开始绘图
//方法二:
// modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, 0.2, 0.0f, 0.0f, 1.0f);
// modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 1.0f, 1.0f, -1.0f);
modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 0.0f, 1.0f, 0.0f);
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 0.0f, 0.0f, 1.0f);
上面不同方法的结果: