Cocos 3D功能初探学习笔记---摄像机

发表于2015-09-12
评论0 4.3k浏览

随着手机硬件水平的提高,游戏行业竞争的激烈,玩家对于游戏画面的要求已经不再满足于2D画面;之前的3D游戏开发普遍采用unity3D引擎开发制作,从去年开始,cocos引擎逐步加入了3D功能的支持,熟悉cocos2D-X开发的小伙伴们可以更轻松的转换为3D开发程序员,关于cocos和unity的优劣,也是程序员们经常爱探讨的话题,笔者一直有这么一个观点,主流技术没有好坏之分,只有合适不合适,笔者总结了一下两者的优势和劣势,大家可以自行选择:

unity:优势:有充分的项目上的积累;完善的工具链;开发速度快,由于开发语言相对简单,学习速度也相对比较快

      劣势:不开源,不利于程序员深入学习openGL和底层代码,不利于基于引擎二次开发(由于积累较多,二次开发也许不那么必要)

cocos:优势:开源,利于学习和二次开发;api熟悉,有利于cocos2D-X程序员向3D程序

      劣势:需要时间积累;工具链,在3D中其实比2D更需要成熟的工具链

由于笔者学习3D其实抱着学习底层代码的目的,暂时没有实际开发的需要,所以选择同时学习,并更倾向于cocos的学习,由于零零散散的学习3D和openGL也有了一段时间,笔者对于3D游戏的学习有几点认识,尤其是对于2D工程师转向3D,需要学习如下内容:

1)3D思想,这是比较重要的,也是个人认为比较难的,包括对于摄像机光照等这些概念的理解等等,另外就是把自己的思维扩展到三维空间。

2)新api的学习,这点其实cocos2D-X程序员转到3D其实是比较方便的,总体的程序构建思想并没有变化

3)新语言,shader的学习在3D中比较重要;另外材质文件的制作也是一个新的内容的学习。

本系列教程将重点讲解cocos引擎的3D功能及3D思想,作为笔者学习cocos引擎3D功能的学习笔记,如果有错误欢迎指出,另外从cocos2D-X学习openGL系列将会继续更新,用于学习底层代码和openGL原理等等,之前由于项目上线比较紧张影响了更新速度,另外笔者9月份将重新回到学校读在职研究生,技术博客的更新可能也会受到影响,不过笔者还是会尽量保证这个系列文章的更新速度。

正文

本篇首先介绍摄像机,其实2D时cocos引擎就有摄像机这个概念,每个节点都拥有一个摄像机类,当时的摄像机类的使用实例就是实现节点对象的缩放旋转,因为节点本身就自带这些功能,所以摄像机使用的场合并不多,笔者只在有一次为了实现一个正面视角向前进效果的时候为了让场景有一个“假”3D的效果的时候使用了setEyeXYZ之类的接口,但在3D中,摄像机是个很重要的概念,因为如果直接在设备上显示标准几何模型的坐标,可能屏幕上什么都看不到,因为模型坐标的范围可能不与设备坐标范围相对应,显示器本身是个平面固定的二维矩形区域,显示一个三维模型需要做相应的投影和变化。

需要说明的是在cocos2D-X 2.0时代,摄像机类继承自,而现在摄像机类是Node节点类的子类,可以作为子节点加到任何一个节点上

openGL中支持两种类型的摄像机,分别是透视摄像机(有近大远小的透视效果)和正交摄像机(一般用于建筑设计图等等)。

                       

透视摄像机类似于我们日常用相机照相的效果,有一个视锥体的概念,它有两个平面,一个近平面一个远平面,这两个平面与视锥体的四个面相交,这六个面构成了一个平截椎体,在这个椎体范围内的物体会被绘制,如果某个图元落在组成的椎体的四个平面,那么它将不会被绘制,如果有一个物体穿过这里的某个平面,那么openGL将会对这个物体进行剪切(clip),会绘制这个物体和平面的交集,经过计算后会生成新的几何体。

创建一个透视摄像机需要调用如下函数

 Camera* cameraExample = Camera::createPerspective(30, (GLfloat)s.width/s.height, 10, 200);

第一个参数是透视相机的可视角度 (角度制,一般是在40-60度之间),它的大小决定了视角的横向宽度

第二个参数是相机的长宽比(通常会使用视窗的宽度除以视窗的高度),一般是屏幕的宽高比

第三个参数和第四个参数分别是视锥顶点到近截面和远截面的距离

创建好了之后,你还可以通过getNearPlane和getFarPlane获得视锥顶点到近截面和远截面的距离

和投影摄像机相比,正交摄像机就简单许多,它的主要作用是在投影之后依然保持物体的真实大小以及互相之间的角度。

                                                                    

创建一个正交摄像机需要调用如下函数

Camera* cameraExample = Camera::createOrthographic(100, 100, 10, 200);

第一个参数是x轴的正交投影的缩放因子(正交投影的宽度)。

第二个参数是沿y轴的正交投影的缩放因子(正交投影的高度)。

第三个参数和第四个参数分别是视锥顶点到近截面和远截面的距离。

创建完摄像机以后,就可以设置摄像机的位置了,代码如下

cameraExample->setPosition3D(Vec3(-100, 100, -50));

cameraExample->lookAt(Vec3(-100, 0, -50),Vec3(0,1,0));

首先是设置摄像机的位置,然后通过调用lookAt函数设置观察目标位置和摄像机向上位置,其中摄像机位置和观察目标位置两个点共同确定了观察方向向量,和这条线垂直的平面就确定了观察平面;摄像机向上方向一般被设置为y轴的方向,不传参数默认为Vec3::UNIT_Y(Y轴方向)

接下来就是设置摄像机标识:

cameraExample->setCameraFlag(CameraFlag::USER1);

这个标识用于指导定物体使用不同的摄像机进行观察,CameraFlag一共包含一个默认摄像机和八个用户定义摄像机,默认摄像机是由场景创建的,节点的默认摄像机标识和默认摄像机的标识相同,所以节点的默认摄像机即是场景自动创建的默认相机,节点将自身的标识和摄像机的标识做一个与操作,如果结果大于零,那么这个摄像机就负责显示这个节点;

默认摄像机用于绘制ui,它是最后被绘制的;一般来说需要一个另外的摄像机来绘制3d物体而不是默认摄像机,当深度测试未开启时,可以调整摄像机的绘制顺序;所有摄像机的绘制顺序都是先绘制2d物体和不透明3d物体,然后绘制透明3d物体。

通过调用setDepth可以设置摄像机的绘制顺序,越大的深度越绘制的靠上,所以默认摄像机默认是0,其他摄像机默认是1。

一个物体单位需要经过模型变换,视图变换和投影变换才能转换成opengl需要的信息,摄像机类可以通过调用一些函数分别获得这三个阶段的矩阵。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引