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 ...
随机推荐
- react-router v4 实现路由拦截的一种思路(待验证)
出处:https://segmentfault.com/q/1010000010905474
- redux 知识点
redux原理:store中维护了一个state,我们dispatch一个action,接下来reducer根据这个action更新state. react-redux提供两个关键模块:Provide ...
- centos7编译安装php7.2
去官网下载php7.2安装包,选择一个结点下载:http://php.net/downloads.php 下载:wget -ivh http://cn.php.net/distributions/ph ...
- Abp问题解决集合1
ABP学习经验 1. 视图中(控制器中直接使用仓储)会遇到使用实体外键,出现数据库连接关闭的错误 初学者经常会犯这样一个错误,没错说的就是我自己,这个问题折腾了我很长世间.还是没有细看文档,对ab ...
- 《Windows核心编程》第3章——深入理解handle
本文借助windbg来理解程序中的函数如何使用handle对句柄表进行查询的.所以先要开启Win7下Windbg的内和调试功能. 解决win7下内核调试的问题 win7下debug默认无法进行内核调试 ...
- Kafka Stream
Kafka Stream是Apache Kafka从0.10版本引入的一个新Feature(当前:1.0.0-rc0,参见:https://github.com/apache/kafka/releas ...
- Block Design 小技巧之添加RTL代码到block_design
Block Design 小技巧之添加RTL代码到block_design 1.首先得打开Block Design,右击RTL文件,才会出现Add module to Block Design选项. ...
- python slave status 2
#!/usr/bin/env python import MySQLdbimport contextlib @contextlib.contextmanagerdef mysql(Host,Port, ...
- 数据仓库专题19-数据建模语言Information Engineering - IE模型(转载)
Information Engineering采用Crow's Foot表示法(也有叫做James Martin表示法的),中文翻译中对使用了Crow's Foot表示法的模型也有笼统的称做鸭掌模型的 ...
- Selenium2+python自动化43-判断title(title_is)
From: https://www.cnblogs.com/yoyoketang/p/6539117.html 前言 获取页面title的方法可以直接用driver.title获取到,然后也可以把获取 ...