cocos2D-X源码分析之从cocos2D-X学习OpenGL(11)----摄像机
2016-06-11 11:30
951 查看
本篇文章介绍一个在游戏中的重要概念,在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 下一篇将介绍天空盒的原理
能力不足,水平有限,如有问题,欢迎指出。
首先来看正交矩阵的初始化代码:
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 下一篇将介绍天空盒的原理
能力不足,水平有限,如有问题,欢迎指出。
相关文章推荐
- cocos2dx之中文乱码问题
- cocos2dx之apk编译失败原因
- cocos2dx之加载瓦片地图tmx
- cocos2dx-2.2.1结合VS2010游戏开发入门(环境搭建)
- cocos2D-X源码分析之从cocos2D-X学习OpenGL(10)----MVP矩阵
- 新作品上线了啦,等你来玩!!!
- 使用tiled-0.16.1创建地图用于cocos2dx
- cocos2D-X源码分析之从cocos2D-X学习OpenGL(9)----变换和坐标系统
- cocos2dx android添加广点通广告平台的---插屏广告
- sublime中的cocos-js代码提示
- [Android开发]cocos2dx工程中接入支付宝sdk
- cocos2dx android SDK接入总结
- 【图片处理】cocos2dx png图片压缩处理
- quick-cocos2d-x 从2.2.5升级到3.3的体会,quickcocos2dx3.3
- Cocos2dx/NDK .a静态库的制作与使用
- cocos2D-X源码分析之从cocos2D-X学习OpenGL(8)----纹理
- cocos studio工程分析
- 毕设 cocos2d-x的总结
- 关于 网易 cocos2dx面试的几个问题
- cocos2dx切换到后台回来图片不显示问题