Camera定义

游戏中,Camera用来向用户展示场景,Camera就像一个摄像机,摄像机里面的景象就是Camera的展示范围,如下图所示:

在3D空间中Camera被定义为一个位置,有一个单位“方向”向量和一个“向上”的单位向量组成,方向和向上向量告诉OpenGL 当前Camera如何定向。

视景体

Camera的另一个重要特性是视觉平截体(View Frustrum),在上面的图片中可以看到一个被砍去顶尖的角锥体,这就是一个视觉平截体,所以视觉平截体内部的东西都可以在屏幕上看到,视觉平截体被六个剖面确定,near、far、left、right、top、bottom。near剖面还有一个特殊的性质:你可以认为它是相机照出的照片中的平面。这个由3D转换为2D的过程,称为投影,通常有两种投影:orthographic projection(正交投影) 和 perspective projection(透视投影、中心投影),正交投影在2D的图形中经常使用,无论物体离camera远近,物体在屏幕上的大小始终一样。透视投影是现实世界中的成像原理:物体离眼睛越远,物体的就越小。不同的投射类型就是改变视景体的形状,透视投影的视觉平截体形状就是上图的角锥体形状,正交投影的视觉平截体是一个长方体,投影的过程简单来说:对于物体上的每一个点,计算这个点到camera之间的连线是否与near剖面相交。下图是正交投影与透视投影的图片示例:


 由此可以看出为什么在透视投影下,屏幕上越远的物体会越小,而正交投影下,物体保持大小不变。OpenGL一般使用3D空间展示,无论你是绘图还是输出字符串,当你使用正交投影时,可以假设z轴不存在,下图就是一个2D精灵在3D空间中的样子:

因此,在这里可以忽略2D和3D的不同之处,下图是一个在未设置任何矩阵(matrix)下使用SpriteBatch绘图的正交视景体


我们所做的就是让我们的精灵在x/y平面上移动,忽略z轴,保持我们一直工作在2D空间的假象

透视投影使用两个属性来定义它的投影规则:广角和纵横比(长宽比),广角是一个角度值,用来定义视场有多大”开口“,如下图

纵横比是视口的宽度和高度比。视口是一个长方形,即camera用来进行渲染图像的地方,一个480*320像素的窗口,它的纵横比是480/320。

Camera相关类

Camera:基础类

OrthographicCamera:正交Camera 继承自Camera

PerspectiveCamera:投影Camera继承在Camera

首先看Camera类

  1. public abstract class Camera {
  2. public final Vector3 position = new Vector3();
  3. public final Vector3 direction = new Vector3(0, 0, -1);
  4. public final Vector3 up = new Vector3(0, 1, 0);

三个公共成员分别是Camera的位置、方向、up向量 ,采用的是默认属性,因此camera默认位于原点,z轴默认朝上。

  1. public final Matrix4 projection = new Matrix4();
  2. public final Matrix4 view = new Matrix4();
  3. public final Matrix4 combined = new Matrix4();
  4. public final Matrix4 invProjectionView = new Matrix4();

这是一系列的在OpenGL ES 2.0中用到的矩阵,前两个是投影和模型视图矩阵,第三个是前两个的结合,第四个是第三个的翻转,经常用来做提取登时,这些都不会经常使用到

  1. public float near = 1;
  2. public float far = 100;
  3. public float viewportWidth = 0;
  4. public float viewportHeight = 0;

这是near和far剖面距离camera的距离,以及视口的宽度和高度,near和far必须遵循0<=near<far的公式。默认情况情况下near剖面距离camera是1个单位,对于正交投影,near经常设置为0,width和height用来计算透视投影的纵横比或者正交投影的视景体长方体

  1. public final Frustum frustum = new Frustum();

最后的成员是Frustum,有6个平面组成,Frustum可以用来进行裁剪:检测一个物体是否在Frustum内,如果不在则不绘制它。Frustum有一些的方法用来检测一个 盒子、球体或者一个点是否在Frustum中。

  1. public abstract void update();
  2. public void apply(GL10 gl);

这是两个常用方法,update方法用来重新计算camera的举证,当camera的属性发生改变时进行调用。apply方法用来设置camera的GL_PROJECTION或者GL_MODELVIEW矩阵,不过这个方法在OpenGL ES 2.0上不可用。

  1. public void unproject(Vector3 vec);
  2. public void project(Vector3 vec);
  3. public Ray getPickRay(float x, float y);

最后是几个你可能用到额高级方法。unproject方法用来从屏幕坐标中取得一个点,并产生这个点的三位坐标。与原有类的OrthographicCamera.screenToWorld()左右相同,也等同于gluUnproject方法。x、y坐标是可触坐标,参数中的z坐标是个0和1之间的值,0表示点位于near平面,1表示点位于far平面;

project方法正好相反,从3D世界中取得一个点,并转换成屏幕上的2d点;

getPickRay方法会返回一个直线,可以想象成3D世界中,从camera位置到x、y的一条直线,用来检测这个直线是否与其他图形或者物体接触到。

  1. public class OrthographicCamera extends Camera {
  2. public float zoom = 1;
  3. public OrthographicCamera(float viewportWidth, float viewportHeight);

OrthographicCamera有一个额外成员zoom用来定义缩放因子。构造参数定义了camera的视口width和高度,如果想要最佳的利用机器像素,只需要在这里定义GRaphics.getWidth()/getHeight(),也可以使用不同的单位,比如厘米。

  1. public class PerspectiveCamera extends Camera {
  2. public float fieldOfView = 67;
  3. public PerspectiveCamera(float fieldOfView, float viewportWidth, float viewportHeight);

PerspectiveCamera 也有一个额外的成员,广角。

文章翻译完,对Camera的理解又进了一层。

转一篇讲camera的 mb好多年不搞3d 都忘光了的更多相关文章

  1. 在知乎上看到 Web Socket这篇文章讲得确实挺好,从头看到尾都非常形象生动,一口气看完,没有半点模糊,非常不错

    在知乎上看到这篇文章讲得确实挺好,从头看到尾都非常形象生动,一口气看完,没有半点模糊,非常不错,所以推荐给大家,非常值得一读. 作者:Ovear链接:https://www.zhihu.com/que ...

  2. 对于DQN的三大改进 - 这篇讲的好些

    可以看这篇文章: https://blog.csdn.net/u013236946/article/details/73161586 这篇也讲的不错: https://www.cnblogs.com/ ...

  3. 推荐一篇讲arm架构gcc内联汇编的文章

    这是来自ethernut网站的一篇文章,原文链接: http://www.ethernut.de/en/documents/arm-inline-asm.html 另外,据说nut/os是个不错的开源 ...

  4. 觉得一篇讲SPFA还不错的文章

    我觉得他整理的有一些乱,我都改成插入代码了,看的顺眼一些 转载自http://blog.csdn.net/juststeps/article/details/8772755 下面的都是原文: 最短路径 ...

  5. 复盘一篇讲sklearn库学习文章(上)

    认识 sklearn 官网地址: https://scikit-learn.gor/stable/ 从2007年发布以来, scikit-learn已成为重要的Python机器学习库, 简称sklea ...

  6. 一篇讲Java指令重排和内存可见性的好文

    在这里: http://tech.meituan.com/java-memory-reordering.html 指令重排和内存可见性(缓存不一致)是两个不同的问题. volatile关键字太强,即阻 ...

  7. 很好的一篇讲LTP在编解码中的作用的文章

    原文链接 LONG-TERM PREDICTION by: Adit Aviv       Kfir Grichman introduction: The speech signal has been ...

  8. Android扩展 - 拍照篇(Camera)

    1.调用系统摄像头 1.声明常量和变量 2.按钮点击事件,打开系统摄像头 3.重写onActivityResult事件接收拍照返回 4.生成文件名返回路径 5.保存图片 private static  ...

  9. linux动态链接库---一篇讲尽

    一般我们在Linux下执行某些外部程序的时候可能会提示找不到共享库的错误, 比如: tmux: error while loading shared libraries: libevent-1.4.s ...

随机推荐

  1. FormData对象

    FF4中增加了一个很有意思的对象,FormData.通常我们提交(使用submit button)时,会把form中的所有表格元素的name与value组成一个queryString,提交到后台.这用 ...

  2. Linux系统调用--mmap/munmap函数详解【转】

    转自:http://www.cnblogs.com/leaven/archive/2011/01/14/1935199.html http://linux.chinaunix.net/techdoc/ ...

  3. Android使用Application总结

    对于application的使用,一般是 在Android源码中对他的描述是; * Base class for those who need to maintain global applicati ...

  4. SQL Server系统表sysobjects介绍与使用

    关于SQL Server数据库的一切信息都保存在它的系统表格里.我怀疑你是否花过比较多的时间来检查系统表格,因为你总是忙于用户表格.但是,你可能需要偶尔做一点不同寻常的事,例如数据库所有的触发器.你可 ...

  5. IOS 音频开发文件大小计算

    音频基础知识 音频文件计算大小 音频转码 标签(空格分隔): 调查 IOS音频 https://developer.apple.com/library/ios/documentation/MusicA ...

  6. Mysql数据库知识-Mysql索引总结 mysql mysql数据库 mysql函数

    mysql数据库知识-Mysql索引总结: 索引(Index)是帮助MySQL高效获取数据的数据结构. 下边是自己整理的资料与自己的学习总结,,做一个汇总. 一.真的有必要使用索引吗? 不是每一个性能 ...

  7. 如何查看Python的内置函数

    经常调用的时候不知道python当前版本的内置函数是哪些,可以用下面的指令查看: C:\Users\Administrator>python Python 2.7.11 (v2.7.11:6d1 ...

  8. tar 报错gzip: stdin: not in gzip format

    今天在linux下 用tar -zxvf xxx.tar.bz2 然后就报这个错. gzip: stdin: not in gzip formattar: Child returned status ...

  9. Basic 分类: POJ 2015-08-03 15:49 3人阅读 评论(0) 收藏

    Basic Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 905 Accepted: 228 Description The p ...

  10. 提高 Linux 上 socket 性能

      http://www.cnblogs.com/luxf/archive/2010/06/13/1757662.html 基于Linux的Socket网络编程的性能优化   1 引言    随着In ...