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

2023-10-31

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

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

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

准备立方体数据

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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索引啦:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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的调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    glVertexAttribPointer(positionLocation,
                          3,
                          GL_FLOAT,
                          GL_FALSE,
                          sizeof(Vertex),
                          (GLvoid*)offsetof(Vertex,Position));

//下面是vertex shader

attribute vec3 a_position;  //注意之前我们使用的是vec2
attribute 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轴不停地旋转。

1
2
3
4
5
6
7
8
9
10
11
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)之间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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的,强烈推荐!

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

width="800" height="400" src="http://zilongshanren.com/webgl/ex05.html" style="margin: 0px; padding: 0px; border-style: none; border-width: initial; outline: 0px; font-family: 'open sans', 'Helvetica Neue', 'Microsoft Yahei', Helvetica, Arial, sans-serif; font-size: 14px; vertical-align: baseline; color: rgb(86, 90, 95); line-height: 22.4px;">

结语

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

推荐阅读

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐

  • matlab 代码转 Python

    可以使用 MATLAB 工具箱 MATLAB 集成工具 将 MATLAB 代码转换为 Python 代码 这个工具箱可以自动将大部分 MATLAB 代码转换为类似的 Python 代码 并且可以自动处理一些类型和语法上的差异 在 MATLA
  • nrf52832通过i2c官方库nrf_drv_twi读取tmp117温度

    twi调试过程如下 1 代码实现 分别实现对nrf drv twi init nrf drv twi rx nrf drv twi tx相关官方库的调用 2 修改工程配置文件sdk config h 增加TWI的相关配置 参考 nRF5 S
  • WSL2安装google chrome浏览器

    一 环境 Windows 11 Ubuntu 22 04 二 安装google chrome步骤 官方文档 1 创建文件夹 mkdir chrome 2 进入目录 cd chrome 3 下载chrome压缩包 sudo wget http
  • 计量经济学及Stata应用 5.12 多元回归的Stata实例

    1 多元回归 regress y x1 x2 x3 reg y x1 x2 x3 2 解释定义 1 右上角 Number of obs 样本容量N F n N F统计量 自由度为k 约束条件 m N K 检验整个方程的联合显著性 Prob
  • C++的new和delete

    一 new和delete 1 在C 中堆内存的分配和释放是通过new和delete 来操作的 他们和C语言的malloc和free有什么区别呢 new的底层也是通过malloc来开辟内存的 new比malloc 多一项功能 就是开辟完内存
  • 数据结构:KMP算法

    给定一个字符串 S 以及一个模式串 P 所有字符串中只包含大小写英文字母以及阿拉伯数字 模式串 P 在字符串 S 中多次作为子串出现 求出模式串 P 在字符串 S 中所有出现的位置的起始下标 KMP算法 数组下标从1开始 额外next数组
  • Java常用代码汇总

    1 字符串有整型的相互转换 String a String valueOf 2 integer to numeric string int i Integer parseInt a numeric string to an int 2 向文
  • 编程题 排序子序列(java实现)

    点进来你就是我的人了博主主页 戳一戳 欢迎大佬指点 欢迎志同道合的朋友一起加油喔 链接 排序子序列 牛牛定义排序子序列为一个数组中一段连续的子序列 并且这段子序列是非递增或者非递减排序的 牛牛有一个长度为n的整数数组A 他现在有一个任务是把
  • 云计算免费视频教程:Bashshell脚本编程详解

    云计算免费视频教程 Bashshell脚本编程详解 Shell本身是一个用C语言编写的程序 它是用户使用Unix Linux的桥梁 用户的大部分工作都是通过Shell完成的 Shell既是一种命令语言 也是一种程序设计语言 作为命令语言 它
  • 使用全局配置处理字段名和属性名不一致的情况

    使用全局配置处理字段名和属性名不一致的情况 若字段名和实体类中的属性名不一致 但是字段名符合数据库的规则 使用 实体类中的属性名符合Java的规则 使用驼峰 此时可通过以下三种方式处理字段名和实体类中的属性的映射关系 a gt 可以通过为字
  • outlook邮箱邮件大小限制_Office Outlook 2010、2013附件大小超过了允许的范围限制三种解决方法图解 – 爱分享...

    在outlook2010 2013中添加附件超过20M 就会提示 附件大小超出了允许的范围 outlook2007的附件默认大小是150M 而outlook2010 2013的是20M 有种说法是10M 也许是版本问题 未验证 也许微软出于
  • 如何下载安装VSCode(2023年9月13日更新)

    与VSCode同步更新 如果喜欢 访问原文章链接 https blog csdn net qq 39124701 article details 129400983 给原帖点赞 收藏 支持原作者 1 示例链接 可直接下载 https vsc
  • STM32外部中断

    STM32外部中断 STM32有19个外部中断 线0 15对应外部IO口的输入中断 线16连接PVD输出 线17连接RTC闹钟事件 线18连接USB唤醒事件 GPIO与中断线的映射关系 GPIOx 0映射到EXTI0 GPIOx 1映射到E
  • 使用Python和OpenCV进行拍摄截图

    使用Python和OpenCV进行拍摄截图 1 效果图 2 原理 3 源码 参考 这篇博客将介绍如何使用OpenCV Python和PyAutoGui库拍摄截图 使用pyautogui 可以轻松地将屏幕截图直接捕捉到磁盘或内存 并且转换为O
  • 基于Transformers的自然语言处理入门【八】-Transformers解决序列标注任务

    基于Transformers的自然语言处理入门 八 Transformers解决序列标注任务 1 序列标注概念 2 常见的token级别分类任务 3 预处理数据 4 微调预训练模型 1 序列标注概念 序列标注 通常也可以看作是token级别
  • maven多model打包,launch4j打exe包,inno setup打安装包

    背景 最近公司要做java的本地化服务 需要在用户的终端部署安装java的服务 目前设计的进行http服务 从而提高云服务的容错性 性能 顺便进行有其他window的模块的连接 因为不是所有的本地业务模块都会打入本地服务 根据不同的需求 选
  • 思科c系列服务器cimc密码,UCS C系列服务器故障排除提示.PDF

    UCS C系列服务器故障排除提示 PDF UCS C系列服务器故障排除提示 目录 简介 先决条件 要求 使用的组件 网络图 规则 背景信息 C系列故障排除提示 获取对TAC的Showtech支持 显示系统事件日志事件 显示传感器读 显示CI
  • Laravel框架开发实践

    Laravel是一款优秀的PHP框架 它的流行不仅仅是因为它的优秀特性 而且它开创了一种全新的编程思路 帮助开发者更加高效地完成Web应用的开发 在学习Laravel开发过程中 我深刻体会到了Laravel框架的简洁 高效和灵活 下面是我的
  • 拉结尔6月21日服务器维护,拉结尔6月23日停服维护公告

    拉结尔手游将在6月23日进行短暂的维护更新哦 不清楚具体更新内容究竟是什么的小伙伴们 接下来就让我们一起来看一下吧 拉结尔6月23日停服维护公告 尊敬的探索者 拉结尔 于6月19日更新了全新周年庆版本 针对近日部分探索者反馈的关于新版本的问
  • Cocos2dx-OpenGL ES2.0教程:你的第一个立方体(5)

    在上篇文章中 我们介绍了VBO索引的使用 使用VBO索引可以有效地减少顶点个数 优化内存 提高程序效率 本教程将带领大家一起走进3D 绘制一个立方体 其实画立方体本质上和画三角形没什么区别 所有的模型最终都要转换为三角形 同时 本文还会介绍