本篇文章介绍一个在游戏中的重要概念,在MVP矩阵中,视图矩阵和投影矩阵都和摄像机有关,说句白话,摄像机其实就是生成投影矩阵和视图矩阵的方式和原因,cocos2d-x中使用GamePlay3D类的Mat4类生成各种矩阵,一下就通过分析摄像机Camera类的代码来看这些矩阵是如何生成的。
首先来看正交矩阵的初始化代码:
bool Camera::initOrthographic(float zoomX,float zoomY,float nearPlane,float farPlane) { _zoom[0] = zoomX; _zoom[1] = zoomY; _nearPlane = nearPlane; _farPlane = farPlane; Mat4::createOrthographicOffCenter(0,_zoom[0],_zoom[1],_nearPlane,_farPlane,&_projection); _viewProjectionDirty = true; _frustumDirty = true; return true; }正交投影就是没有近大远小概念的投影,它的视锥体就是矩形,所以定义它的时候只要定义视口宽高和近平面以及远平面就可以了。调用Mat4的
createOrthographicOffCenter生成投影矩阵把它传给_projection。
bool Camera::initPerspective(float fieldOfView,float aspectRatio,float farPlane) { _fieldOfView = fieldOfView; _aspectRatio = aspectRatio; _nearPlane = nearPlane; _farPlane = farPlane; Mat4::createPerspective(_fieldOfView,_aspectRatio,&_projection); _viewProjectionDirty = true; _frustumDirty = true; return true; }而透视投影的初始化方式类似,参数分别为:视角角度,宽高比,近平面,远平面,最后函数会把投影矩阵传递给_projection。
定义一个摄像机,需要摄像机位置,观察方向,还有一个指向它右侧的向量,以及一个它上方的向量,这实际上是一个以摄像机位置为原点的坐标系,如图所示:
所以说在创建摄像机以后,就要定义它的位置和lookAt
_camera->setPosition3D(Vec3(0,130,130) + _sprite3D->getPosition3D()); _camera->lookAt(_sprite3D->getPosition3D());lookAt定义了观察目标位置和摄像机向上位置,如果不传参数第二个参数就默认为y轴方向
在lookAt中,我们定义了lookAt矩阵,也就是视图矩阵,至于视图矩阵的推导,可以参考这篇文章:http://www.cnblogs.com/mincomp/archive/2012/09/06/2672888.html,这里我们只需要知道这个结果就可以:
R为右向量,U为上向量,D为方向向量,它们的计算过程就在lookAt函数中:
//向上向量 Vec3 upv = up; upv.normalize(); //摄像机方向 Vec3 zaxis; Vec3::subtract(this->getPosition3D(),lookAtPos,&zaxis); zaxis.normalize(); //右轴 Vec3 xaxis; Vec3::cross(upv,zaxis,&xaxis); xaxis.normalize(); //上轴 Vec3 yaxis; Vec3::cross(zaxis,xaxis,&yaxis); yaxis.normalize(); //lookAt矩阵 Mat4 rotation; rotation.m[0] = xaxis.x; rotation.m[1] = xaxis.y; rotation.m[2] = xaxis.z; rotation.m[3] = 0; rotation.m[4] = yaxis.x; rotation.m[5] = yaxis.y; rotation.m[6] = yaxis.z; rotation.m[7] = 0; rotation.m[8] = zaxis.x; rotation.m[9] = zaxis.y; rotation.m[10] = zaxis.z; rotation.m[11] = 0;注意,这里的摄像机方向实际上是摄像机位置向量指向它看着的方向的相反方向,然后下面用向量的叉乘获得右轴和上轴,从而获得lookAt矩阵所需要的值,这些计算的原理可以参考:https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process
下一篇将介绍天空盒的原理
能力不足,水平有限,如有问题,欢迎指出。