文档章节

Cocos2dx-OpenGL ES2.0教程:你的第一个立方体(5)

乐逍遥jun
 乐逍遥jun
发布于 2016/02/22 21:38
字数 1255
阅读 23
收藏 0

上篇文章中,我们介绍了VBO索引的使用,使用VBO索引可以有效地减少顶点个数,优化内存,提高程序效率。

本教程将带领大家一起走进3D–绘制一个立方体。其实画立方体本质上和画三角形没什么区别,所有的模型最终都要转换为三角形。

同时,本文还会介绍如何通过修改MVP矩阵来让此立方体不停地旋转。另外,大家还可以动手去修改本教程的示例代码,借此我们可以更加深入地理解OpenGL的normalized device space。

准备立方体数据

在开始真正的绘制代码之前,我们先要准备好数据。首先,我们需要改进的是代表顶点属性的结构体:

1234
typedef struct {        float Position[3];        float Color[4];} Vertex;

这里,我们把Position从一个长度为2的数组变成了一个长度为3的数组,用于存储顶点的xyz的值。

接下来是顶点数据,因为一共有6个面。每个面由二个三角形组成,因此需要4个顶点,那么整个立方体就需要4*6=24个顶点。

123456789101112131415161718192021222324252627282930313233
Vertex data[] =   {       // Front       { {1, -1, 0}, {1, 0, 0, 1}},       { {1, 1, 0}, {0, 1, 0, 1}},       { {-1, 1, 0}, {0, 0, 1, 1}},       { {-1, -1, 0}, {0, 0, 0, 1}},       // Back       { {1, 1, -2}, {1, 0, 0, 1}},       { {-1, -1, -2}, {0, 1, 0, 1}},       { {1, -1, -2}, {0, 0, 1, 1}},       { {-1, 1, -2}, {0, 0, 0, 1}},       // Left       { {-1, -1, 0}, {1, 0, 0, 1}},       { {-1, 1, 0}, {0, 1, 0, 1}},       { {-1, 1, -2}, {0, 0, 1, 1}},       { {-1, -1, -2}, {0, 0, 0, 1}},       // Right       { {1, -1, -2}, {1, 0, 0, 1}},       { {1, 1, -2}, {0, 1, 0, 1}},       { {1, 1, 0}, {0, 0, 1, 1}},       { {1, -1, 0}, {0, 0, 0, 1}},       // Top       { {1, 1, 0}, {1, 0, 0, 1}},       { {1, 1, -2}, {0, 1, 0, 1}},       { {-1, 1, -2}, {0, 0, 1, 1}},       { {-1, 1, 0}, {0, 0, 0, 1}},       // Bottom       { {1, -1, -2}, {1, 0, 0, 1}},       { {1, -1, 0}, {0, 1, 0, 1}},       { {-1, -1, 0}, {0, 0, 1, 1}},       { {-1, -1, -2}, {0, 0, 0, 1}}   };

接下来,当然是最重要的VBO索引啦:

1234567891011121314151617181920
GLubyte indices[] = {       // Front       0, 1, 2,       2, 3, 0,       // Back       4, 5, 6,       4, 5, 7,       // Left       8, 9, 10,       10, 11, 8,       // Right       12, 13, 14,       14, 15, 12,       // Top       16, 17, 18,       18, 19, 16,       // Bottom       20, 21, 22,       22, 23, 20   };

最后,由于我们修改了顶点属性,所以我们要相应地修改vertex shader和glVertexAttribPointer的调用:

12345678910111213141516171819
glVertexAttribPointer(positionLocation,                          3,                          GL_FLOAT,                          GL_FALSE,                          sizeof(Vertex),                          (GLvoid*)offsetof(Vertex,Position));//下面是vertex shaderattribute vec3 a_position;  //注意之前我们使用的是vec2attribute vec4 a_color;varying vec4 v_fragmentColor;void main(){    gl_Position = CC_MVPMatrix * vec4(a_position.xyz,1);  //这里用swizzle的时候是xyz    v_fragmentColor = a_color;}

此时,编译运行,你会得到如下结果 :

cube01cube01

别诧异,这就是一个立方体,只不过现在它离我们的“眼睛”(Cemera)很近,所以我们只能看到一个面。接下来,让我们修改一个modelView矩阵,让它离我们的camera远一点。

让立方体动起来

我们有很多方法可以让立方体转起来。比如直接修改modelView矩阵,也可以使用modelView配合projection矩阵。

首先,是最简单的方法,我们把整个立方体数据先缩小一半,然后再往-z轴方向移动0.5个单位,最后让它围绕着x轴不停地旋转。

1234567891011
modelViewMatrix.scale(0.5);modelViewMatrix.translate(0.0,0, -0.5);static float rotation = 0;modelViewMatrix.rotate(Vec3(1,0,0),CC_DEGREES_TO_RADIANS(rotation));rotation++;if (rotation < 360) {    rotation = 0;}Director::getInstance()->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, modelViewMatrix);

注意,这里我们操纵顶点的取值范围只能是-1~+1,xyz每一个轴都是这样。超出这个区域(normalized device space)就会裁剪掉。但是我们实际操作一个物体的移动的时,肯定不可能局限于这么小的范围,我们可以通过modelView和projection矩阵来定义一个更好用的坐标系,然后基于这个坐标系去指定物体的坐标。
比如cocos2d-x里面,通过下列代码指定了自己的坐标系范围在(0~size.width)和(0~size.height)之间。

1234567891011121314
case Projection::_3D:{    float zeye = this->getZEye();    Mat4 matrixPerspective, matrixLookup;    loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);    // issue #1334    Mat4::createPerspective(60, (GLfloat)size.width/size.height, 10, zeye+size.height/2, &matrixPerspective);    multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, matrixPerspective);    Vec3 eye(size.width/2, size.height/2, zeye), center(size.width/2, size.height/2, 0.0f), up(0.0f, 1.0f, 0.0f);    Mat4::createLookAt(eye, center, up, &matrixLookup);    multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, matrixLookup);    loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);    break;}

这里面,我们可以直接拿来用,也可以自己再写一个。下面是我用的代码:

123456789101112131415
Mat4 projectionMatrix;Mat4::createPerspective(60, 480/320, 1.0, 42, &projectionMatrix);Director::getInstance()->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, projectionMatrix);Mat4 modelViewMatrix;Mat4::createLookAt(Vec3(0,0,1), Vec3(0,0,0), Vec3(0,1,0), &modelViewMatrix);modelViewMatrix.translate(0, 0, -5);static float rotation = 0;modelViewMatrix.rotate(Vec3(1,1,1),CC_DEGREES_TO_RADIANS(rotation));rotation++;if (rotation < 360) {    rotation = 0;}Director::getInstance()->multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, modelViewMatrix);

这里我让camera的位置位于(0,0,1),然后看着(0,0,0)点,并且头朝上(0,1,0)。大家可以尝试去修改createLookAt的参数,看看每一个参数具体是什么意思。这里有一个非常不错的程序介绍View Frustum的,强烈推荐!

最终效果:(如果你看不到,请升级你的浏览器!!!)

结语

附上本教程源码,从下篇文章开始,我们将介绍纹理映射。

推荐阅读

本文转载自:

乐逍遥jun
粉丝 6
博文 79
码字总数 39510
作品 0
东城
技术主管
私信 提问
零基础使用cocos2dx-lua和skynet全栈式开发网游三(客户端配置)

客户端配置 一、扯几个概念 问题:cocos2dx引擎到底如何运作的? 在解答这个问题前,需要了解几个概念。 1.颜色 在自然界中,存在一种场,叫电磁场。电荷粒子运动状态变化时,就会释放电磁波...

量子出击
2018/06/21
0
0
cocos2dx- call to OpenGL ES API with no current context(logged once per thread)

Android APP 在红米2(Android 5.1系统)上进行全屏应用切换的时候,会出现卡屏,不会闪退并且出现频繁.在红米note和moto x1(Android 4.4系统)中偶尔出现. 其他手机上暂时还未出现全屏切换...

GLancelot
2015/08/14
1K
3
Xcode6编译Cocos2d-x3.1.1 link错误

Xcode6编译Cocos2d-x3.1.1 link错误 原来苹果公司打算自己整一套OPenGL的东西,所有,有些东西需要根据IOS平台来加入它的东西。这个问题的解决方案如下: 在工程目录下cocos/platform/CCImag...

Nov_Eleven
2015/01/19
0
2
blender导出的骨骼动画加载在webgl后变形

@李勇2 你好,想跟你请教个问题: 我看到您写的《cocos2dx blender 骨骼动画实现》里面讲到了骨骼的变换和opengl中不同。我在做的时候,也发现代码加载动画和我在blender中设置的动画不同,但...

蚊子蚊子
2014/05/25
1K
1
Cocos2d-x上适合做工具的UI库:ImGui

  Cocos2d-x的控件类型仅限于基础的几种,如label、button、listview等,做游戏开发时基本够用了。但如果想用cocos2dx来做工具的话,那就有点困难了。   这里介绍一个适合做工具的UI库:...

hghhe
2018/09/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Bash 和 Python 编程语言优缺点分析

Bash 和 Python 是大多数自动化工程师最喜欢的编程语言。它们都各有优缺点,有时很难选择应该使用哪一个。所以,最诚实的答案是:这取决于任务、范围、背景和任务的复杂性。 让我们来比较一下...

xiangyunyan
23分钟前
3
0
Kubernetes从懵圈到熟练:读懂这一篇,集群节点不下线

排查完全陌生的问题,完全不熟悉的系统组件,是售后工程师的一大工作乐趣,当然也是挑战。今天借这篇文章,跟大家分析一例这样的问题。排查过程中,需要理解一些自己完全陌生的组件,比如sys...

阿里云云栖社区
28分钟前
7
0
解决exe4打包出现的问题

https://blog.csdn.net/gem_yaorao/article/details/48626155

南桥北木
45分钟前
1
0
SpringBoot高级篇JdbcTemplate之数据更新与删除

前面介绍了JdbcTemplate的插入数据和查询数据,占用CURD中的两项,本文则将主要介绍数据更新和删除。从基本使用上来看,姿势和前面的没啥两样 <!-- more --> I. 环境准备 环境依然借助前面一...

小灰灰Blog
今天
3
0
Filecoin 编译问题

https://github.com/filecoin-project/go-filecoin/issues/2503 Error go run ./build build command from root I've faced on this error Building go-filecoin...git log -n 1 --forma......

怎当她临去时秋波那一转
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部