[转载]GLKit 矩阵变换:自转公转
版权声明:iTyran原创作品,谢绝转载!否则将追究法律责任。
在上一篇文章[iTyran原创]Xcode创建的默认iOSOpenGL ES 2.0 project代码分析中,
我跳过了- (void)update函数里面的矩阵变换分析,在这里我们来研究下这里干了些什么事情。
1.预备知识。
OpenGL ES 中有两套矩阵,都是4×4的GLfloat矩阵。一个叫modelview matrix ,你大部分时间都会与之打交道。它是你用来对虚拟世界进行变换的矩阵。要对虚拟世界中的物体进行旋转,转移或尺寸变化,你都需要对此矩阵进行修改。
另一个矩阵用来创建根据设定的视口(参考从零开始学习OpenGLES之三 – 透视)对世界坐标进行描述的二维表示。此矩阵称为 projection matrix 。在绝大部分时间内,你都不需要接触该矩阵。
一个3×3的矩阵可以描述绕任意轴旋转任何角度的情况。然而,为表示可能遇到的任何变换,我们仍然需要第四行/列。第四列用来保存变换信息,第四行用来表示透视变换。
至于第四行/列如何在矩阵变换中起到神奇的作用,那些令人你头痛的问题数学家门帮我们解决了。我们理解如何使用就好。
2.创建 projectionMatrix
视口矩阵使用GLKit是很简单的事情。
float aspect = fabsf(self.view.bounds.size.width /self.view.bounds.size.height); GLKMatrix4 projectionMatrix =GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f),
aspect, 0.1f,100.0f);
首先是计算屏幕的宽高比aspect。我们的OpenGL ES程序是全屏的,所以这里直接使用self.view.bounds.size里面的值就能表示屏幕宽高。
GLKMatrix4MakePerspective有4个参数。
参数1:视角,要求输入幅度,GLKMathDegreesToRadians帮助我们把角度值转换为幅度。
参数2:算屏幕的宽高比,如果不正确设置,可能显示不出画面。
参数3:near,
参数4:far
near和far共同决定了可视深度,都必须为正值,near一般设为一个比较小的数,far必须大于near。
我们做个测试,把far值改为4,你会看到如下的效果。
你会发现正方体不能显示完全,有一部分看不到了。
3.baseModelViewMatrix公转
还记得笛卡尔坐标系吧,回顾下这里:http://ityran.com/article-3-1.html
GLKMatrix4 baseModelViewMatrix =GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f);
观察gCubeVertexData数据,正方体是围绕原点展开的。这里把物体往-z方向移动4个单位。
baseModelViewMatrix =GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f);
GLKMatrix4Rotate做矩阵旋转
它有5个参数:
参数1:传入矩阵,被变化的矩阵
参数2:旋转的角度。正值逆时针旋转。
参数3~5:共同组成一个向量,围绕这个向量做旋转。
这里我们还是做一个测试,把向量参数变成1.0f, 0.0f, 0.0f
这时候正方体将围绕x轴旋转。如下图:
4.modelViewMatrix 自转 + 公转
// -1.5f和shader2的1.5f间隔开一个距离
modelViewMatrix = GLKMatrix4MakeTranslation(0.0f,0.0f, -1.5f);
//自转
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix,_rotation, 1.0f, 1.0f, 1.0f);
//公转自转作用在一起。
modelViewMatrix =GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
SHADER_1通过下面的方式设置projectionMatrix和modelviewMatrix。
self.effect.transform.projectionMatrix =projectionMatrix; self.effect.transform.modelviewMatrix = modelViewMatrix;
modelViewMatrix最终会和gCubeVertexData里面的每个点的position信息相乘,得出一个新的正方体坐标。
SHADER_2稍有不同,可编程着色器自己实现光线代码的计算,又多了些矩阵变换。
//GLKMatrix4GetMatrix3 upper-left 3x3 section of a4x4,左上角 _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix),NULL); _modelViewProjectionMatrix =GLKMatrix4Multiply(projectionMatrix, modelViewMatrix);
具体这段代码如何结合Shader.vsh里面的代码实现的变化有待进一步研究。
由于OpenGL ES 2.0 对GLKit 的引入,使得矩阵变换更加简单。而Xcode创建的默认iOS OpenGL ES 2.0 project很好的展示了这些用法,是很值得学习的。