本篇文章介紹一個在遊戲中的重要概念,在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], 0, _zoom[1], _nearPlane, _farPlane, &_projection);
_viewProjectionDirty = true;
_frustumDirty = true;
return true;
}
正交投影就是沒有近大遠小概念的投影,它的視錐體就是矩形,所以定義它的時候只要定義視口寬高和近平面以及遠平面就可以了。調用Mat4的createOrthographicOffCenter生成投影矩陣把它傳給_projection。
bool Camera::initPerspective(float fieldOfView, float aspectRatio, float nearPlane, float farPlane)
{
_fieldOfView = fieldOfView;
_aspectRatio = aspectRatio;
_nearPlane = nearPlane;
_farPlane = farPlane;
Mat4::createPerspective(_fieldOfView, _aspectRatio, _nearPlane, _farPlane, &_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下一篇將介紹天空盒的原理
能力不足,水平有限,如有問題,歡迎指出。