Android OpenGL教程-第二课【转】
第二课 你的第一个多边形:
在第一个教程的基础上,我们添加了一个三角形和一个四边形。也许你认为这很简单,但你已经迈出了一大步,要知道任何在OpenGL中绘制的模型都会被分解为这两种简单的图形。
读完了这一课,你会学到如何在空间放置模型,并且会知道深度缓存的概念。
其他类不变,只更改OpenGLRenderer类。
首先,我们画一个三角形,主要是在OnDrawFrame里面画,使用的函数是
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);
或者
gl.glDrawElements(GL10.GL_TRIANGLES, 3, GL10.GL_FLOAT, mIndexBuffer);
我们先使用drawArray,drawElement里面要多用一个indexBuffer。
第一步,定义个array
private float[] mTriangleArray = {
0f, 1f, 0f, // 是上顶点
-1f, -1f, 0f, // 左下顶点
1f, -1f, 0f // 右下顶点
};
这里实际上是定义了三角形的三个顶点,三个数分别是x,y,z的坐标,和数学里直角坐标系相同
0f, 1f, 0f 是上顶点
-1f, -1f, 0f 是左下顶点
1f, -1f, 0f 是右下顶点

定义个FloatBuffer,这是android画三角形必须的结构
private FloatBuffer mTriangleBuffer;
来一个函数转换array到Buffer
我们直接上一个工具类
BufferUtil类:
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer; public class BufferUtil {
public static FloatBuffer mBuffer; public static FloatBuffer floatToBuffer(float[] a) {
// 先初始化buffer,数组的长度*4,因为一个float占4个字节
ByteBuffer mbb = ByteBuffer.allocateDirect(a.length * 4);
// 数组排序用nativeOrder
mbb.order(ByteOrder.nativeOrder());
mBuffer = mbb.asFloatBuffer();
mBuffer.put(a);
mBuffer.position(0);
return mBuffer;
}
}
注意:这里有个排序的问题,是使用大端(BIG_ENDIAN)还是用小端(LITTLE_ENDIAN),在android里面,opengl画图must use native order direct buffer,否则报错为ERROR/AndroidRuntime(6897): java.lang.IllegalArgumentException: Must use a native order direct Buffer这个错误在android1.6以上会出现,在1.5上不会出现。
这里我们直接使用allocateDirect和nativeOrder,就能满足android的要求
第二步:
在SurfaceCreate里面构建这个Buffer
mTriangleBuffer = BufferUtil.floatToBuffer(mTriangleArray);
第三步:
在OndrawFrame里面画三角形
// 利用数组模型来画模型,要加此句(原文中没有)
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // 三角形的颜色为红色,透明度为不透明
gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // 设置顶点,第一个参数是坐标的维数,这里是3维,第二个参数,表示buffer里面放的是float,第三个参数是0,
// 是因为我们的坐标在数组中是紧凑的排列的,没有使用offset,最后的参数放的是存放顶点坐标的buffer
gl.glVertexPointer(, GL10.GL_FLOAT, , mTriangleBuffer); // 画数组,第一个参数表示画三角形,第二个参数是first,第三个参数是count,表示在buffer里面的坐标的开始和个数
gl.glDrawArrays(GL10.GL_TRIANGLES, , );
运行,会看到一个大三角形

下面,我们来变换坐标轴,画个小三角形,原理就是把坐标轴向远拉,意思就是让镜头向后拉,这样三角形就小了。
第一步:
在onSurfaceChanged(原文是OnSurfaceCreate,有错误)里面加入下面几行代码
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
这几行为透视图设置屏幕。意味着越远的东西看起来越小。这么做创建了一个现实外观的场景。此处透视按照基于窗口宽度和高度的45度视角来计算。0.1f,100.0f是我们在场景中所能绘制深度的起点和终点。
gl.glMatrixMode(GL10.GL_PROJECTION);指明接下来的两行代码将影响projection matrix(投影矩阵)。投影矩阵负责为我们的场景增加透视。
glLoadIdentity()近似于重置。它将所选的矩阵状态恢复成其原始状态。调用 glLoadIdentity()之后我们为场景设置透视图。
glMatrixMode(GL_MODELVIEW)指明任何新的变换将会影响 modelview matrix(模型观察矩阵)。模型观察矩阵中存放了我们的物体讯息。最后我们重置模型观察矩阵。如果您还不能理解这些术语的含义,请别着急。在以后的教程里,我会向大家解释。只要知道如果您想获得一个精彩的透视场景的话,必须这么做。
第二步:
在OndrawFrame里面增加代码如下:
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重置当前的模型观察矩阵。
gl.glLoadIdentity();
// 沿着X轴左移1.5个单位,Y轴不动(0.0f),最后移入屏幕6.0f个单位
gl.glTranslatef(-1.5f, 0.0f, -6.0f);
当您调用glLoadIdentity()之后,您实际上将当前点移到了屏幕中心,X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。中心左面的坐标值是负值,右面是正值。移向屏幕顶端是正值,移向屏幕底端是负值。移入屏幕深处是负值,移出屏幕则是正值。
glTranslatef(x, y, z)沿着 X, Y 和 Z 轴移动。根据前面的次序,下面的代码沿着X轴左移1.5个单位,Y轴不动(0.0f),最后移入屏幕6.0f个单位。注意在glTranslatef(x, y, z)中当您移动的时候,您并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置。
这时候就能画出个小三角形了。

下面,我们来画一个四边形
四边形的顶点数组为:
// 四边形的顶点数组
private float[] mQuadsArray = {
1f, 1f, 0f, // 右上
-1f, 1f, 0f, // 左上
-1f, -1f, 0f, // 左下
1f, -1f, 0f // 右下
}; // 从这里可以看出,我们按照逆时针的方向画图
private FloatBuffer mQuadsBuffer;
在OnDrawFrame里面添加代码
gl.glLoadIdentity();
// 坐标向右移1.5个单位
gl.glTranslatef(1.5f, 0.0f, -6.0f);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mQuadsBuffer);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4); // 画四边形
在onSurfaceCreated里面添加代码
mQuadsBuffer = BufferUtil.floatToBuffer(mQuadsArray);
第一个参数是绘图模式,而且你现在看到两种可能的OpenGL绘图方式。 我想花时间来讨论现在不同的绘图模式。
它们是:
GL_POINTS
GL_LINES
GL_LINE_LOOP
GL_LINE_STRIP
GL_TRIANGLES
GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN
我们还没有讨论点或线,所以我只介绍最后的三个 。在我开始之前,我要提醒你,顶点数组可能包含不止一个三角形,以便当您只看到一个物体顶点数组,你要知道,不仅限于这一点。
GL_TRIANGLES - 这个参数意味着OpenGL使用三个顶点来组成图形。所以,在开始的三个顶点,将用顶点1,顶点2,顶点3来组成一个三角形。完成后,在用下一组的三个顶点来组成三角形,直到数组结束。
GL_TRIANGLE_STRIP - OpenGL的使用将最开始的两个顶点出发,然后遍历每个顶点,这些顶点将使用前2个顶点一起组成一个三角形。所以第三个点与第一个,第二个生成一个三角形。第四个点将于第二个,第三个生成三角形。
也就是说,0,1,2这三个点组成一个三角形,1,2,3这三个点也组成一个三角形。
GL_TRIANGLE_FAN - 在跳过开始的2个顶点,然后遍历每个顶点,让OpenGL将这些顶点于它们前一个,以及数组的第一个顶点一起组成一个三角形。 第3个点将与 第二个点(前一个)和第一个点(第一个).生成一个三角形。
也就是说,同样是0,1,2,3这4个顶点。
在STRIP状态下是,0,1,2;1,2,3这2个三角形。
在FAN状态下是,0,1,2;0,2,3这2个三角形。
这次我们将使用 GL_TRIANGLE_FAN ,我们将在显示区域获得一个矩形。

(注:本教程转自其他网页,并加以修改,查看原网页请点击这里)
Android OpenGL教程-第二课【转】的更多相关文章
- Android OpenGL教程-第一课【转】
第一课 快速的开始一个Android OpenGL项目 首先,读懂我们的教程,需要有android的初步基础,我们这里只是通过android提供的SDK,来进行OpenGL的学习,所以你必须先学习如何 ...
- NeHe OpenGL教程 第二课:多边形
前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢 ...
- NeHe OpenGL教程 第二十九课:Blt函数
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十八课:贝塞尔曲面
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十七课:影子
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十六课:反射
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十五课:变形
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十四课:扩展
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十三课:球面映射
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
随机推荐
- 《html5 从入门到精通》读书笔记(二)
接着上面继续记录笔记,这次要记的知识点比较多...记录下我认为比较重要的东西. 一.表单属性 1.autocomplete属性 该属性规定form或input域应该拥有自动完成功能. <form ...
- [C#]合并单元格(行、列)
详细链接:https://shop499704308.taobao.com/?spm=a1z38n.10677092.card.11.594c1debsAGeak説明:控件ID指的是页面上面的Grid ...
- 【Selenium专题】 FAQ_对象识别_Compound class names are not supported
测试代码 public void login(){ WebDriver driver = new ChromeDriver(); driver.get("http://IP:Port/cli ...
- python 小点
python中列表不能除以列表,列表不能除以整数.浮点数. numpy数组可以实现数组除以整数.
- CentOS 图形界面的关闭与开启
初衷 • 本地开多个虚拟机搞集群测试,为了节省资源,关掉图形界面更好点 CentOS 设置方法 • 编辑配置文件:vim /etc/inittab • 把默认值::initdefault:,改为::i ...
- 大数据list去重
MaxList模块主要是对Java集合大数据去重的相关介绍. 背景: 最近在项目中遇到了List集合中的数据要去重,大概一个2500万的数据,开始存储在List中,需要跟一个2万的List去去重. 直 ...
- SQLServer XML
OPENXML 参见:OPENXML (SQL Server) | Microsoft Docs SQL For XML 参见:FOR XML (SQL Server) | Microsoft Doc ...
- JavaScript中setInterval的用法总结
setInterval动作的作用是在播放动画的时,每隔一定时间就调用函数,方法或对象.可以使用本动作更新来自数据库的变量或更新时间显示. setInterval动作的语法格式如下:setInterva ...
- 斐讯K2P配置文件破解笔记
手上有一个斐讯K2P路由器,刷机前我想把原机带的固件备份出来.搜到恩山A大开启telnet.固件备份的教程,里面提到了配置文件破解的方法,心血来潮试了一下,发现算出的密码不能解密,一直报"b ...
- Beautiful Soup解析网页
使用前步骤: 1.Beautiful Soup目前已经被移植到bs4,所以导入Beautiful Soup时先安装bs4库. 2.安装lxml库:如果不使用此库,就会使用Python默认的解析器,而l ...