cocos设置 相机矩阵和投影矩阵 源码浅析
在cocos中,最后设置视口大小,相机矩阵,裁剪矩阵是在setProjection方法中,源码如下:
void Director::setProjection(Projection projection)
{
//屏幕的可绘制区域,设计分辨率,fix模式下不和设计分辨率一样,其余和设计分辨率相等 Size size = _winSizeInPoints;
//设置适口,吧自己调整后的设计分辨率,换算成屏幕分辨率,设置绘制区域
setViewport(); switch (projection)
{
case Projection::_2D:
{
//单位化裁剪矩阵
loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); #if CC_TARGET_PLATFORM == CC_PLATFORM_WP8
if(getOpenGLView() != nullptr)
{
multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, getOpenGLView()->getOrientationMatrix());
}
#endif Mat4 orthoMatrix;
/*创建自定义投影矩阵*/
/*
left 视图体的最小 X 值。
right 视图体的最大 X 值。
bottom 视图体的最小 Y 值。
top 视图体的最大 Y 值。
zNearPlane 视图体的最小 Z 值。
zFarPlane 视图体的最大 Z 值。
返回值 正交投影矩阵。
*/
Mat4::createOrthographicOffCenter(, size.width, , size.height, -, , &orthoMatrix); multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix); loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
break;
} case Projection::_3D:
{
//得到观察者的Z,以设计分辨率为单位
/*
(_winSizeInPoints.height / 1.1566f);,为什么是1.1566,
根据相似三角形,通过这个值,得到的裁剪面正好就是 z为0的裁剪面,也就是2d中我们设置精灵的地方
原理可参考 http://blog.sina.com.cn/s/blog_6084f5880102v26q.html
*/
float zeye = this->getZEye();
//投影矩阵和View矩阵
Mat4 matrixPerspective, matrixLookup; //初始化一个单位矩阵,初始化投影矩阵为单位矩阵
loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); #if CC_TARGET_PLATFORM == CC_PLATFORM_WP8
//if needed, we need to add a rotation for Landscape orientations on Windows Phone 8 since it is always in Portrait Mode
GLView* view = getOpenGLView();
if(getOpenGLView() != nullptr)
{
multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, getOpenGLView()->getOrientationMatrix());
}
#endif
// issue #1334
//创建裁剪矩阵
/*
cocos直接使用设计分辨率winSizeInPoints来设置投影矩阵和观察点,并没有将其缩放到屏幕的实际分辨率,而只有视口设置为实际分辨率。
透视矩阵定义的视锥体的长宽比和视口的长宽比是相等的,这样才会保证不会变形
视口的大小为 设计分辨率*scale(scalex和scaley大部分情形一样),所以他们的比是一样的 我的理解:设计分辨率下的坐标相当于 世界坐标,然后乘以相机矩阵,得到相机下的坐标,然后乘以裁剪矩阵,得到裁剪后的规范化坐标,基本没用到实际分辨率 */
//参数一:垂直张角 参数二 宽高比,参数三:近端距离。距离eyez,也就是眼睛z坐标的距离 参数四:远端距离 参数五:生成的裁剪矩阵
/*
[x,y,z,1] 乘以 这个矩阵之后,变为[x'z,y'z,zz',wz],w=1,然后新的除以z,就是透视除法,把x',y',z' 变为(0,1)范围 // 经过投影变换后,物体坐标变换到了裁剪坐标系,经过OpenGL自动执行的透视除法后,变换到规范化设备坐标系中。透视除法就是将裁剪坐标系中坐标都除以齐次坐标的过程。
做过实验:把距离摄像机的近端距离由10变为100,发现 最后的图像没有变大,原因:
经过投影之后,x'=x/(z*aspect*tan(fov/2))这是投影之后的x坐标,范围为(-1,1),可以看到大小只受
aspect 和fov的影响,aspect不变,fov也不变,所以图像大小不变,受影响的只是z‘,不过投影到2d图像上,
这个用不到
*/
Mat4::createPerspective(, (GLfloat)size.width/size.height, , zeye+size.height/, &matrixPerspective);
//Mat4::createPerspective(60, (GLfloat)size.width/size.height, 100, zeye+size.height/2, &matrixPerspective); //单位矩阵先乘以投银矩阵,得到投影矩阵
multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, matrixPerspective); Vec3 eye(size.width/, size.height/, zeye), center(size.width/, size.height/, 0.0f), up(0.0f, 1.0f, 0.0f); //生成相机坐标矩阵
/*
参数一:眼睛的位置,正中间 参数二:眼睛看向哪里,看向视口中点 参数三 头顶朝向,一班都是010
*/
Mat4::createLookAt(eye, center, up, &matrixLookup);
//通过测试得知 cameraPos.z=projectPos.w ,w就是z
Vec4 cameraPos=matrixLookup *Vec4(,,,);
Vec4 projectPos= matrixPerspective *cameraPos; //loopup矩阵右乘裁剪矩阵 也就是p*V
multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, matrixLookup); //初始化模型视口矩阵??
loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
break;
} case Projection::CUSTOM:
// Projection Delegate is no longer needed
// since the event "PROJECTION CHANGED" is emitted
break; default:
CCLOG("cocos2d: Director: unrecognized projection");
break;
} _projection = projection;
//
GL::setProjectionMatrixDirty(); _eventDispatcher->dispatchEvent(_eventProjectionChanged);
}
下面再看看生成投影矩阵的代码:
void Mat4::createPerspective(float fieldOfView, float aspectRatio,
float zNearPlane, float zFarPlane, Mat4* dst)
{
GP_ASSERT(dst);
GP_ASSERT(zFarPlane != zNearPlane); float f_n = 1.0f / (zFarPlane - zNearPlane);
float theta = MATH_DEG_TO_RAD(fieldOfView) * 0.5f;
if (fabs(fmod(theta, MATH_PIOVER2)) < MATH_EPSILON)
{
CCLOGERROR("Invalid field of view value (%f) causes attempted calculation tan(%f), which is undefined.", fieldOfView, theta);
return;
}
float divisor = tan(theta);
GP_ASSERT(divisor);
float factor = 1.0f / divisor; memset(dst, , MATRIX_SIZE); GP_ASSERT(aspectRatio);
dst->m[] = (1.0f / aspectRatio) * factor;
dst->m[] = factor;
dst->m[] = (-(zFarPlane + zNearPlane)) * f_n;
//测试的值m[11]控制着裁剪矩阵(x'z,x'y,z'z,z)的z,左手坐标系m[11]为1,右手坐标系m[11]为-1,控制着
//最后x,y,z 的正负,不管是左手坐标系还是右手坐标系,得出的裁剪矩阵x',y',z'的坐标应该是一样的
//而在世界坐标转换为 相机坐标的时候,z坐标正好相反,所以通过m[11]使2者的裁剪坐标一致
dst->m[] = -1.0f;
dst->m[] = -2.0f * zFarPlane * zNearPlane * f_n;
}
cocos设置 相机矩阵和投影矩阵 源码浅析的更多相关文章
- 【深入浅出jQuery】源码浅析--整体架构
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- 【深入浅出jQuery】源码浅析2--奇技淫巧
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- Struts2源码浅析-ConfigurationProvider
ConfigurationProvider接口 主要完成struts配置文件 加载 注册过程 ConfigurationProvider接口定义 public interface Configurat ...
- Android 手势识别类 ( 三 ) GestureDetector 源码浅析
前言:上 篇介绍了提供手势绘制的视图平台GestureOverlayView,但是在视图平台上绘制出的手势,是需要存储以及在必要的利用时加载取出手势.所 以,用户绘制出的一个完整的手势是需要一定的代码 ...
- Android开发之Theme、Style探索及源码浅析
1 背景 前段时间群里有伙伴问到了关于Android开发中Theme与Style的问题,当然,这类东西在网上随便一搜一大把模板,所以关于怎么用的问题我想这里也就不做太多的说明了,我们这里把重点放在理解 ...
- 【深入浅出jQuery】源码浅析2--使用技巧
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
- spring源码浅析——IOC
=========================================== 原文链接: spring源码浅析--IOC 转载请注明出处! ======================= ...
- Android源码浅析(六)——SecureCRT远程连接Linux,配置端点和字节码
Android源码浅析(六)--SecureCRT远程连接Linux,配置端点和字节码 需要编译源码的同学,一般都是win+虚拟机吧,但是再虚拟机里体验并不是很好,所有市面上有很多的软件能够做到在wi ...
- Android源码浅析(五)——关于定制系统,如何给你的Android应用系统签名
Android源码浅析(五)--关于定制系统,如何给你的Android应用系统签名 今天来点简单的我相信很多定制系统的同学都会有一些特定功能的需求,比如 修改系统时间 静默安装 执行某shell命令 ...
- Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令
Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...
随机推荐
- count(*) 和 count(1)和count(列名)区别
执行效果上: count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL count(1)包括了所有列,用1代表代码行,在统计结果的时候,不会忽略列值为NULL cou ...
- axios 的使用方法
axios是一个基于promise的HTTP库, 可以再浏览器和node.js中使用 浏览器的兼容 安装 使用npm安装 npm install axios --save 使用bower安装 bowe ...
- 关于meshgrid和numpy.c_以及numpy.r_
meshgrid的目的是生成两套行列数一致的矩阵,其中一个是行重复,一个是列复制:可以这么来理解,通过ravel()将矩阵数据拉平之后,就可以将这两套矩阵累加在一起,形成一个两行数据,要达到这个效果是 ...
- Block Design 小技巧之添加RTL代码到block_design
Block Design 小技巧之添加RTL代码到block_design 1.首先得打开Block Design,右击RTL文件,才会出现Add module to Block Design选项. ...
- WCF 基础连接已经关闭: 服务器关闭了本应保持活动状态的连接。
详细错误信息: System.ServiceModel.CommunicationException: 接收对 http://localhost:48655/XXXXXX.svc 的 HTTP 响应时 ...
- 黄聪:PHP JSON_ENCODE 不转义中文汉字的方法
ios程序中不识别读取到的JSON数据中 \u开头的数据. PHP 生成JSON的时候,必须将汉字不转义为 \u开头的UNICODE数据. 网上很多,但是其实都是错误的,正确的方法是在json_enc ...
- SpringBoot使用redis缓存List
一.概述 最近在做性能优化,之前有一个业务是这样实现的: 1.温度报警后第三方通讯管理机直接把报警信息保存到数据库: 2.我们在数据库中添加触发器,(BEFORE INSERT)根据这条报警信息处理业 ...
- centos7系列-给普通用户sudo权限
对于linux用户来讲,普通用户的权限是有一定限制的,所以在有些操作的时候,是需要sudo权限的,那么如何在linux下赋予普通用户sudo权限呢?此处将讲解一下方法. 在login我们的系统后,如果 ...
- vue中mounted中无法获取到dom元素
一.解决方案: 加上异步setTimeout,延迟获取dom的代码的执行 mounted() { // debugger this.$nextTick(()=> { setTimeout(()= ...
- PAT 乙级 1083 是否存在相等的差(20 分)
1083 是否存在相等的差(20 分) 给定 N 张卡片,正面分别写上 1.2.…….N,然后全部翻面,洗牌,在背面分别写上 1.2.…….N.将每张牌的正反两面数字相减(大减小),得到 N 个非负差 ...