1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 安卓学习笔记37:利用OpenGL ES绘制平面图形

安卓学习笔记37:利用OpenGL ES绘制平面图形

时间:2024-02-03 10:55:39

相关推荐

安卓学习笔记37:利用OpenGL ES绘制平面图形

文章目录

零、学习目标一、OpenGL概述二、了解三维直角坐标系三、案例演示 - 绘制三角形(一)运行效果(二)实现步骤1、创建安卓应用【DrawTriangle】2、建模:创建三角形类 - Triangle3、渲染:创建三角形表面视图 - TriangleSurfaceView4、展示:主界面类 - MainActivity5、运行程序,查看效果(三)小结1、建模2、渲染3、展示(四)课堂练习:绘制嵌套三角形四、案例演示 - 采用拼合法绘制正方形(一)运行效果(二)实现步骤1、创建安装应用【DrawSquareBySyntheticMethod】2、创建正方形模型类 - Square3、创建正方形表面视图类 - SquareSurfaceView4、主界面类MainActivity展示正方形5、启动应用,查看效果6、让正方形动起来(三) 课堂练习:让全部正方形旋转起来五、案例演示 - 采用顶点法绘制正方形(一)运行效果(二)实现步骤1、创建安卓应用【DrawSquareByVertexMethod】2、建模:创建正方形类 - Square(1)采用FAN模式(2)采用STRIP模式3、渲染:创建正方形表面视图 - SquareSurfaceView4、展示:主界面类 - MainActivity5、启动应用,查看效果(三)课堂作业 - 采用顶点法绘制变色旋转正方形六、案例演示 - 采用索引法绘制正方形(一)运行效果(二)实现步骤1、创建安卓应用【DrawSquareByIndexMethod】2、建模:正方形类 - Square3、渲染:正方形表面视图 - SquareSurfaceView4、展示:主界面类 - MainActivity5、启动应用,查看效果(三)课堂练习:采用索引法绘制嵌套实心六边形七、案例演示 - 采用索引法绘制空心正方形(一)运行效果(二)实现步骤1、创建安卓应用【DrawHollowedSquare】2、建模:正方形类 - Square3、渲染:正方形表面视图 - SquareSurfaceView4、展示:主界面类 - MainActivity5、启动应用,查看效果(三)课堂练习:采用索引法绘制嵌套空心六边形

零、学习目标

会利用OpenGL ES绘制三角形会利用OpenGL ES绘制正方形会利用OpenGL ES绘制六边形

一、OpenGL概述

OpenGL™ 是行业领域中最为广泛接纳的 2D/3D 图形 API,其自诞生至今已催生了各种计算机平台及设备上的数千优秀应用程序。OpenGL™ 是独立于视窗操作系统或其它操作系统的,亦是网络透明的。在包含CAD、内容创作、能源、娱乐、游戏开发、制造业、制药业及虚拟现实等行业领域中,OpenGL™ 帮助程序员实现在 PC、工作站、超级计算机等硬件设备上的高性能、极具冲击力的高视觉表现力图形处理软件的开发 。

OpenGL的前身是SGI公司为其图形工作站开发的IRIS GL。IRIS GL是一个工业标准的3D图形软件接口,功能虽然强大但是移植性不好,于是SGI公司便在IRIS GL的基础上开发了OpenGL。OpenGL的英文全称是“Open Graphics Library”,顾名思义,OpenGL便是“开放的图形程序接口”。虽然DirectX在家用市场全面领先,但在专业高端绘图领域,OpenGL是不能被取代的主角。

OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广。

OpenGL 规范被广泛用于 PC 和移动设备。在SIGGRAPH 大会上,OpenGL 背后公益性组织科纳斯组织(Khronos Group)公布了新版本:

面对移动领域的 OpenGL ES 版本更新到 3.0面对桌面领域的 OpenGL 版本更新到 4.3可运用在增强现实领域的图形接口 OpenVL

三者中,OpenGL ES 3.0 成为主角,因为它是 Android、iOS 等主流移动平台上的图形接口标准。

二、了解三维直角坐标系

三维空间上点的位置由三个坐标值确定:P(x, y, z)——横坐标、纵坐标、竖坐标三维直角坐标系有三个坐标面:xoy坐标面、yoz坐标面、zox坐标面,三个坐标面把空间划分为八个部分,称为八卦限。(23=82^3 = 823=8)

三、案例演示 - 绘制三角形

(一)运行效果

(二)实现步骤

1、创建安卓应用【DrawTriangle】

2、建模:创建三角形类 - Triangle

在当前状态下绘制三角形,主要是设置并保存三角形的顶点坐标值声明变量

注意:ΔP1P2P3\Delta P_1P_2P_3ΔP1​P2​P3​在xoyxoyxoy平面。构造方法:将三角形整型坐标值放到整型缓冲区对象里

在自绘方法里绘制三角形

查看三角形类完整源代码

package net.hw.draw_triangle;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.IntBuffer;import javax.microedition.khronos.opengles.GL10;/*** 功能:三角形类* 作者:华卫* 日期:12月30日*/public class Triangle {private int one = 0x10000; // 定义单位长度(OpenGL ES只使用int类型值高16位作为坐标值)private IntBuffer triangleBuffer; // 三角形整型缓冲区对象(用于存放三角形顶点坐标值)private int[] triangleVertices = new int[] {0, one, 0,// 第一个顶点-one, -one, 0, // 第二个顶点one, -one, 0 // 第三个顶点}; // 三角形定点数组/*** 构造方法:将三角形整型坐标值放到整型缓冲区对象里*/public Triangle() {// 创建字节数组,分配内存空间,因为Java中int是4个字节,所以要乘以4ByteBuffer byteBuffer = ByteBuffer.allocateDirect(triangleVertices.length * 4);// 按本地字节顺序来使用字节数据byteBuffer.order(ByteOrder.nativeOrder());// 将字节缓冲区转换成整型缓冲区triangleBuffer = byteBuffer.asIntBuffer();// 将三角形顶点坐标数据存放到整型缓冲区triangleBuffer.put(triangleVertices);// 整型缓冲区对象的内部指针定位到第一个字节triangleBuffer.position(0);}/*** 自绘方法** @param gl*/public void drawSelf(GL10 gl) {// 将三角形顶点坐标数据通过整型缓冲区加载到内存gl.glVertexPointer(3, // 参数1:指定每个顶点对应的坐标个数,只能是2、3、4GL10.GL_FIXED, // 参数2:指定每个顶点坐标的数据类型,可以取GL_BYTE, GL_SHORT, GL_FIXED, GL_FLOAT0, // 参数3:指定连续顶点间的字节排列方式,0表明采用紧凑方式triangleBuffer // 参数4:指定数组中第一个顶点的首地址,默认值为0);// 绘制三角形gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, // 参数1:模式0, // 参数2:起点3 // 参数3:顶点数);}}

3、渲染:创建三角形表面视图 - TriangleSurfaceView

在onDrawFrame方法里,对模型进行平移和旋转等操作实现渲染器接口 - Renderer

声明变量

编写表面创建回调方法

编写表面变化回调方法

说明:调用glLoadIdentity()之后,实际上将当前点移到了屏幕中心,X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。中心左面的坐标值是负值,右面是正值。移向屏幕顶端是正值,移向屏幕底端是负值。移入屏幕深处是负值,移出屏幕则是正值。编写绘制帧回调方法

查看三角形表面视图完整源代码

package net.hw.draw_triangle;import android.opengl.GLSurfaceView;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;/*** 功能:三角形表面视图* 作者:华卫* 日期:12月30日*/public class TriangleSurfaceView implements GLSurfaceView.Renderer {private Triangle triangle; // 声明三角形变量/*** 表面创建回调方法** @param gl* @param config*/@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// 实例化三角形对象triangle = new Triangle();}/*** 表面变化回调方法** @param gl* @param width* @param height*/@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// 计算视口宽高比float ratio = (float) width / height;// 设置视口大小(整个手机屏幕)gl.glViewport(0, 0, width, height);// 设置当前矩阵模式为投影矩阵gl.glMatrixMode(GL10.GL_PROJECTION);// 将当前点移到屏幕中心gl.glLoadIdentity();// 设置透视投影的刻度范围gl.glFrustumf(-ratio * 2, ratio * 2, -2, 2, 1, 10);// 设置当前矩阵模式为模型视图矩阵gl.glMatrixMode(GL10.GL_MODELVIEW);}/*** 绘制帧回调方法** @param gl*/@Overridepublic void onDrawFrame(GL10 gl) {// 清除屏幕,否则上次绘制的图形不会自动消失gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// 允许使用顶点绘制图形gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// 将当前点移到屏幕中心gl.glLoadIdentity();// 沿x轴正向移动一个单位,沿z轴负向移动两个单位gl.glTranslatef(1.0f, 0.0f, -2.0f);// 画笔设置为红色gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);// 绘制第一个三角形triangle.drawSelf(gl);// 将当前点移到屏幕中心gl.glLoadIdentity();// 沿x轴正向移动一个单位,沿y轴负向移动两个单位,沿z轴负向移动两个单位gl.glTranslatef(1.0f, -2.0f, -2.0f);// 绕z轴旋转180度gl.glRotatef(180, 0.0f, 0.0f, 1.0f);// 画笔设置为绿色gl.glColor4f(0.0f, 1.0f, 0.0f, 1.0f);// 绘制第二个三角形triangle.drawSelf(gl);// 将当前点移到屏幕中心gl.glLoadIdentity();// 沿x轴负向移动三个单位,沿y轴正向移动两个单位,沿z轴负向移动五个单位gl.glTranslatef(-3.0f, 2.0f, -5.0f);// 画笔设置为黄色gl.glColor4f(1.0f, 1.0f, 0.0f, 1.0f);// 绘制第三个三角形triangle.drawSelf(gl);// 将当前点移到屏幕中心gl.glLoadIdentity();// 沿x轴负向移动三个单位,沿y轴正向移动三个单位,沿z轴负向移动五个单位gl.glTranslatef(-3.0f, 4.0f, -5.0f);// 绕z轴旋转180度gl.glRotatef(180, 0.0f, 0.0f, 1.0f);// 画笔设置为紫色gl.glColor4f(1.0f, 0.0f, 1.0f, 1.0f);// 绘制第四个三角形triangle.drawSelf(gl);// 禁止使用顶点绘制图形gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);}}

4、展示:主界面类 - MainActivity

5、运行程序,查看效果

(三)小结

1、建模

创建三角形类Triangle构造方法:存放三角形顶点坐标值到整型缓冲区对象里自绘方法:加载顶点坐标数据到内存;绘制三角形

2、渲染

创建三角形表面视图TriangleSurfaceView实现Renderer接口(渲染器接口:GLSurfaceView的子接口)改写三个方法:onSurfaceCreated、onSurfaceChanged、onDrawFrame设置视口大小、设置透视投影的可视范围、设置矩阵模式、设置颜色、平移旋转变换、调用三角形自绘方法手机三维坐标系:x轴——水平向右为正向;y轴——竖直向上为正向;z轴——垂直向外为正向平移方法glTranslatef(x, y, z):第一个参数管左右移动,第二个参数管上下移动,第三个参数管远近

3、展示

实例化表面视图设置表面视图的渲染器将表面视图设置为用户界面

(四)课堂练习:绘制嵌套三角形

利用OpenGL ES绘制嵌套三角形。大小是通过透视原理来实现的,在z轴方向距离观者越远越小。

四、案例演示 - 采用拼合法绘制正方形

(一)运行效果

所有正方形静止不动

中央正方形饶z轴逆时针旋转

中央正方形绕z轴逆时针旋转,外围正方形绕z轴顺时针旋转

中央正方形绕y轴逆时针旋转,外围正方形绕z轴顺时针旋转

(二)实现步骤

1、创建安装应用【DrawSquareBySyntheticMethod】

2、创建正方形模型类 - Square

package net.hw.draw_square_synthetic;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.IntBuffer;import javax.microedition.khronos.opengles.GL10;/*** 功能:正方形类* 作者:华卫* 日期:12月30日*/public class Square {/*** 定义单位长度*/private int one = 0x10000;/*** 字节缓冲区*/private ByteBuffer byteBuffer;/*** 三角形整型缓冲区*/private IntBuffer triangleBuffer;/*** 三角形顶点坐标数组*/private int[] triangleVertices = new int[]{0, one, 0, // 上顶点坐标-one, 0, 0, // 左顶点坐标one, 0, 0 // 右顶点坐标};/*** 构造方法:把三角形顶点坐标值保存到整型缓冲区对象里*/public Square(){// 分配内存空间byteBuffer = ByteBuffer.allocateDirect(triangleVertices.length * 4);// 设置字节数据的使用顺序byteBuffer.order(ByteOrder.nativeOrder());// 把字节缓冲区转换成整型缓冲区triangleBuffer = byteBuffer.asIntBuffer();// 把三角形顶点坐标存入整型缓冲区triangleBuffer.put(triangleVertices);// 将整型缓冲区内部指针移到第一个数据(否则指针指向最后一个数据的下一个位置)triangleBuffer.position(0);}/*** 自绘方法:采用拼合法来绘制正方形* @param gl*/public void drawSelf(GL10 gl){// 将三角形顶点坐标加载到内存gl.glVertexPointer(3, GL10.GL_FIXED, 0, triangleBuffer);// 绘制上三角形gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);// 绕x轴旋转180度gl.glRotatef(180, 1.0f, 0.0f, 0.0f);// 绘制下三角形gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);}}

3、创建正方形表面视图类 - SquareSurfaceView

package net.hw.draw_square_synthetic;import android.opengl.GLSurfaceView;import javax.microedition.khronos.opengles.GL10;/*** 功能:正方形表面视图类* 作者:华卫* 日期:12月31日*/public class SquareSurfaceView implements GLSurfaceView.Renderer {private Square square; // 声明正方形变量/*** 表面创建回调方法*/@Overridepublic void onSurfaceCreated(GL10 gl, javax.microedition.khronos.egl.EGLConfig config) {// 实例化正方形square = new Square();}/*** 表面变化回调方法*/@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// 保存手机屏幕宽高比float ratio = (float) width / height;// 设置视口大小,整个手机屏幕gl.glViewport(0, 0, width, height);// 设置矩阵模式为投影模式gl.glMatrixMode(GL10.GL_PROJECTION);// 加载单位矩阵,将当前点移到屏幕中心gl.glLoadIdentity();// 设置透视投影的可视范围gl.glFrustumf(-2 * ratio, 2 * ratio, -2, 2, 1, 10);// 设置矩阵模式为模型视图模式gl.glMatrixMode(gl.GL_MODELVIEW);}/*** 绘制帧回调方法*/@Overridepublic void onDrawFrame(GL10 gl) {// 清除屏幕gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// 启用顶点绘制方法gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// 任务1、在屏幕正中央绘制红色正方形gl.glLoadIdentity(); // 加载单位矩阵gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // 红色gl.glTranslatef(0.0f, 0.0f, -2.0f); // 往屏幕内平移两个单位gl.glRotatef(90, 0.0f, 0.0f, 1.0f);square.drawSelf(gl); // 调用正方形自绘方法// 任务2、在中心正方形左上角绘制一个黄色小正方形gl.glLoadIdentity(); // 加载单位矩阵gl.glColor4f(1.0f, 1.0f, 0.0f, 1.0f); // 黄色gl.glTranslatef(-3.0f, 3.0f, -4.0f); // 平移gl.glRotatef(45, 0.0f, 0.0f, 1.0f); // 绕z轴旋转45度square.drawSelf(gl); // 调用正方形自绘方法// 任务3、在中心正方形正上方绘制一个绿色小正方形gl.glLoadIdentity(); // 加载单位矩阵gl.glColor4f(0.0f, 1.0f, 0.0f, 1.0f); // 绿色gl.glTranslatef(0.0f, 3.0f, -4.0f); // 平移gl.glRotatef(45, 0.0f, 0.0f, 1.0f); // 绕z轴旋转45度square.drawSelf(gl); // 调用正方形自绘方法// 任务4、在中心正方形右上角绘制一个小正方形gl.glLoadIdentity(); // 加载单位矩阵gl.glColor4f(0.0f, 1.0f, 1.0f, 1.0f); // 设置颜色gl.glTranslatef(3.0f, 3.0f, -4.0f); // 平移gl.glRotatef(45, 0.0f, 0.0f, 1.0f); // 绕z轴旋转45度square.drawSelf(gl); // 调用正方形自绘方法// 任务5、在中心正方形左边绘制一个小正方形gl.glLoadIdentity(); // 加载单位矩阵gl.glColor4f(0.0f, 0.4f, 0.5f, 1.0f);// 设置颜色gl.glTranslatef(-3.0f, 0.0f, -4.0f); // 平移gl.glRotatef(45, 0.0f, 0.0f, 1.0f); // 绕z轴旋转45度square.drawSelf(gl); // 调用正方形自绘方法// 任务6、在中心正方形左下角绘制一个小正方形gl.glLoadIdentity(); // 加载单位矩阵gl.glColor4f(1.0f, 0.4f, 0.5f, 1.0f);// 设置颜色gl.glTranslatef(-3.0f, -3.0f, -4.0f); // 平移gl.glRotatef(45, 0.0f, 0.0f, 1.0f); // 绕z轴旋转45度square.drawSelf(gl); // 调用正方形自绘方法// 任务7、在中心正方形正下方绘制一个小正方形gl.glLoadIdentity(); // 加载单位矩阵gl.glColor4f(0.7f, 1.0f, 0.5f, 1.0f);// 设置颜色gl.glTranslatef(0.0f, -3.0f, -4.0f); // 平移gl.glRotatef(45, 0.0f, 0.0f, 1.0f); // 绕z轴旋转45度square.drawSelf(gl); // 调用正方形自绘方法// 任务8、在中心正方形右下角绘制一个小正方形gl.glLoadIdentity(); // 加载单位矩阵gl.glColor4f(0.7f, 1.0f, 1.0f, 1.0f);// 设置颜色gl.glTranslatef(3.0f, -3.0f, -4.0f); // 平移gl.glRotatef(45, 0.0f, 0.0f, 1.0f); // 绕z轴旋转45度square.drawSelf(gl); // 调用正方形自绘方法// 任务9、在中心正方形右下角绘制一个小正方形gl.glLoadIdentity(); // 加载单位矩阵gl.glColor4f(0.2f, 1.0f, 0.8f, 1.0f);// 设置颜色gl.glTranslatef(3.0f, 0.0f, -4.0f); // 平移gl.glRotatef(45, 0.0f, 0.0f, 1.0f); // 绕z轴旋转45度square.drawSelf(gl); // 调用正方形自绘方法// 禁用顶点绘制方法gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);} }

4、主界面类MainActivity展示正方形

package net.hw.draw_square_synthetic;import android.opengl.GLSurfaceView;import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {/*** 声明图形库表面视图*/private GLSurfaceView mGlSurfaceView;/*** 声明正方形表面视图(渲染器)*/private SquareSurfaceView mSquareSurfaceView;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 实例化图形库表面视图mGlSurfaceView = new GLSurfaceView(this);// 实例化正方形表面视图(渲染器)mSquareSurfaceView = new SquareSurfaceView();// 给图形库表面视图设置渲染器mGlSurfaceView.setRenderer(mSquareSurfaceView);// 将图形库表面视图设置为用户界面setContentView(mGlSurfaceView);}}

5、启动应用,查看效果

6、让正方形动起来

回顾一下在自定义视图里如何实现动画的?要利用Thread和Handler来处理。现在的自定义视图继承了SurfaceView,里面隐含了线程,通过回调方法onDrawFrame体现出来。声明起始时间

保存起始时间

计算流逝的时间

让中央红色正方形每0.1秒钟逆时针绕z轴旋转5度

启动应用,查看效果

(三) 课堂练习:让全部正方形旋转起来

让中心正方形每0.1秒钟逆时针旋转5度,周围的九个小正方形每0.1秒钟顺时针旋转5度。提示:大家可以尝试绕不同的坐标轴旋转,仔细观看动画效果。

中央正方形绕y轴逆时针旋转,外围正方形绕z轴顺时针旋转

五、案例演示 - 采用顶点法绘制正方形

上一个案例,我们采用三角形拼合法来绘制正方形,建模时保存的是三角形顶点坐标,通过拼合而绘制正方形,而渲染与展示都跟绘制三角形没有什么区别。

怎么实现动画?直接在自定义视图 (GLSurfaceView)里就可以实现动画,不需要在主窗口里利用Thread和Handler来实现,操作起来更加方便简捷。

(一)运行效果

(二)实现步骤

1、创建安卓应用【DrawSquareByVertexMethod】

2、建模:创建正方形类 - Square

(1)采用FAN模式

△P1P2P3△P_1P_2P_3△P1​P2​P3​(右上三角形)+ △P1P3P4△P_1P_3P_4△P1​P3​P4​(左下三角形)

(2)采用STRIP模式

△P1P2P3△P_1P_2P_3△P1​P2​P3​(左上三角形)+ △P2P3P4△P_2P_3P_4△P2​P3​P4​(右下三角形)

package net.hw.draw_square_vertex;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.opengles.GL10;/*** 功能:采用顶点法创建正方形模型* 有两种模式:FAN模式与STRIP模式* 作者:华卫* 日期:12月31日*/public class Square {private FloatBuffer squareBuffer; // 声明浮点型缓冲区变量private ByteBuffer byteBuffer; // 声明字节型缓冲区变量private float[] squareVertices = new float[] {-1.5f, 1.5f, 0.0f, // 左上角顶点坐标(P1)1.5f, 1.5f, 0.0f, // 右上角顶点坐标(P2)1.5f, -1.5f, 0.0f, // 右下角顶点坐标(P3)-1.5f, -1.5f, 0.0f, // 左下角顶点坐标(P4)}; // 正方形顶点坐标数组/*** 构造方法:将正方形顶点坐标存放到浮点型缓冲区对象里*/public Square() {// 为字节缓冲区对象分配内存空间byteBuffer = ByteBuffer.allocateDirect(squareVertices.length * 4);// 按本地字节顺序使用字节数据byteBuffer.order(ByteOrder.nativeOrder());// 把字节缓冲区对象转换成浮点型缓冲区对象squareBuffer = byteBuffer.asFloatBuffer();// 将正方形顶点坐标存放到浮点型缓冲区对象里squareBuffer.put(squareVertices);// 设置浮点型缓冲区内部指针指向第一个字节squareBuffer.position(0);}/*** 自绘方法*/public void drawSelf(GL10 gl) {// 将正方形顶点坐标值加载到内存gl.glVertexPointer(3, GL10.GL_FLOAT, 0, squareBuffer);// 按照FAN模式来绘制正方形gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);}}

3、渲染:创建正方形表面视图 - SquareSurfaceView

package net.hw.draw_square_vertex;import android.opengl.GLSurfaceView;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;/*** 功能:正方形表面视图* 作者:华卫* 日期:12月31日*/public class SquareSurfaceView implements GLSurfaceView.Renderer {private Square square; // 声明正方形变量@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// 实例化正方形square = new Square();}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// 计算屏幕宽高比float ratio = (float) width / height;// 设置视口大小,整个手机屏幕gl.glViewport(0, 0, width, height);// 设置矩阵模式为投影模式gl.glMatrixMode(GL10.GL_PROJECTION);// 加载单位矩阵,将当前点移到屏幕中心gl.glLoadIdentity();// 设置透视投影的刻度范围gl.glFrustumf(-2 * ratio, 2 * ratio, -2, 2, 1, 10);// 设置矩阵模式为模型视图模式gl.glMatrixMode(GL10.GL_MODELVIEW);}@Overridepublic void onDrawFrame(GL10 gl) {// 清除手机屏幕gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// 采用顶点方式来绘制图形gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);gl.glLoadIdentity(); // 加载单位矩阵,将当前点移到屏幕中心gl.glTranslatef(0.0f, 0.0f, -2.0f); // 往屏幕内平移两个单位gl.glColor4f(1.0f, 1.0f, 0.0f, 1.0f); // 设置为黄色square.drawSelf(gl); // 绘制正方形gl.glLoadIdentity(); // 加载单位矩阵,将当前点移到屏幕中心gl.glTranslatef(0.0f, 0.0f, -2.8f); // 往屏幕内平移2.8个单位gl.glRotatef(45, 0.0f, 0.0f, 1.0f); // 绕z轴旋转45度gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // 设置为红色square.drawSelf(gl); // 绘制正方形// 禁用顶点方式来绘制图形gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);}}

4、展示:主界面类 - MainActivity

package net.hw.draw_square_vertex;import android.opengl.GLSurfaceView;import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {private GLSurfaceView mGlSurfaceView; // 声明图形库表面视图private SquareSurfaceView mSquareSurfaceView; // 声明正方形表面视图(渲染器)@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 实例化图形库表面视图mGlSurfaceView = new GLSurfaceView(this);// 实例化正方形表面视图(渲染器)mSquareSurfaceView = new SquareSurfaceView();// 给图形库表面视图设置渲染器mGlSurfaceView.setRenderer(mSquareSurfaceView);// 将图形库表面视图设置为用户界面setContentView(mGlSurfaceView);}}

5、启动应用,查看效果

(三)课堂作业 - 采用顶点法绘制变色旋转正方形

六、案例演示 - 采用索引法绘制正方形

我们已学习了采用拼合法与顶点法绘制正方形。不同方法仅仅在建模上不同,而渲染与展示都是相同的。采用索引法可以规定顶点顺序,操作起来更加灵活。

(一)运行效果

(二)实现步骤

1、创建安卓应用【DrawSquareByIndexMethod】

2、建模:正方形类 - Square

package net.hw.draw_sqaure_index;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.opengles.GL10;/*** 功能:采用索引法创建正方形模型* 作者:华卫* 日期:12月31日*/public class Square {/*** 声明浮点型缓冲区变量*/private FloatBuffer squareBuffer;/*** 声明字节型缓冲区变量*/private ByteBuffer byteBuffer;/*** 声明索引字节型缓冲区*/private ByteBuffer indexBuffer;/*** 正方形顶点坐标数组*/private float[] rectangleVertices = new float[] {-1.5f, 1.5f, 0.0f, // 左上角顶点坐标(P1--0)1.5f, 1.5f, 0.0f, // 右上角顶点坐标(P2--1)1.5f, -1.5f, 0.0f, // 右下角顶点坐标(P3--2)-1.5f, -1.5f, 0.0f, // 左下角顶点坐标(P4--3)};/*** 定义顶点顺序的索引数组(跟FAN模式与STRIP模式都可以不同)*/private byte[] indices = new byte[]{0, 1, 3, // 左上三角形的三个顶点顺序(△P1P2P4)1, 2, 3 // 右下三角形的三个顶点顺序(△P2P3P4)};/*** 构造方法:将正方形顶点坐标存放到浮点型缓冲区对象里*/public Square() {// 为字节缓冲区对象分配内存空间byteBuffer = ByteBuffer.allocateDirect(rectangleVertices.length * 4);// 按本地字节顺序使用字节数据byteBuffer.order(ByteOrder.nativeOrder());// 把字节缓冲区对象转换成浮点型缓冲区对象squareBuffer = byteBuffer.asFloatBuffer();// 将正方形顶点坐标存放到浮点型缓冲区对象里squareBuffer.put(rectangleVertices);// 设置浮点型缓冲区内部指针指向第一个数据squareBuffer.position(0);// 分配内存空间indexBuffer = ByteBuffer.allocateDirect(indices.length);// 将索引数组存放到字节型缓冲区对象里indexBuffer.put(indices);// 设置字节型缓冲区内部指针指向第一个数据indexBuffer.position(0);}/*** 自绘方法*/public void drawSelf(GL10 gl) {// 将正方形顶点坐标值加载到内存gl.glVertexPointer(3, GL10.GL_FLOAT, 0, squareBuffer);// 按索引顺序绘制两个三角形,合成一个正方形gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_BYTE, indexBuffer);}}

3、渲染:正方形表面视图 - SquareSurfaceView

package net.hw.draw_sqaure_index;import android.opengl.GLSurfaceView;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;/*** 功能:创建正方形表面视图,渲染正方形* 作者:华卫* 日期:12月31日*/public class SquareSurfaceView implements GLSurfaceView.Renderer {/*** 声明正方形变量*/private Square square;@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {// 实例化正方形square = new Square();}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {// 计算屏幕宽高比float ratio = (float) width / height;// 设置视口大小,整个手机屏幕gl.glViewport(0, 0, width, height);// 设置矩阵模式为投影模式gl.glMatrixMode(GL10.GL_PROJECTION);// 加载单位矩阵,将当前点移到屏幕中心gl.glLoadIdentity();// 设置透视投影的刻度范围gl.glFrustumf(-2 * ratio, 2 * ratio, -2, 2, 1, 10);// 设置矩阵模式为模型视图模式gl.glMatrixMode(GL10.GL_MODELVIEW);}@Overridepublic void onDrawFrame(GL10 gl) {// 清除手机屏幕gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);// 采用顶点方式来绘制图形gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// 加载单位矩阵,将当前点移到屏幕中心gl.glLoadIdentity();// 往屏幕内平移两个单位gl.glTranslatef(0.0f, 0.0f, -2.0f);// 画笔设置为黄色gl.glColor4f(1.0f, 1.0f, 0.0f, 1.0f);// 绘制正方形square.drawSelf(gl);// 禁用顶点方式来绘制图形gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);}}

4、展示:主界面类 - MainActivity

package net.hw.draw_sqaure_index;import android.opengl.GLSurfaceView;import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {/*** 声明图形库表面视图*/private GLSurfaceView mGlSurfaceView;/*** 声明正方形表面视图(渲染器)*/private SquareSurfaceView mSquareSurfaceView;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 实例化图形库表面视图mGlSurfaceView = new GLSurfaceView(this);// 实例化正方形表面视图(渲染器)mSquareSurfaceView = new SquareSurfaceView();// 给图形库表面视图设置渲染器mGlSurfaceView.setRenderer(mSquareSurfaceView);// 将图形库表面视图设置为用户界面setContentView(mGlSurfaceView);}}

5、启动应用,查看效果

(三)课堂练习:采用索引法绘制嵌套实心六边形

七、案例演示 - 采用索引法绘制空心正方形

我们已经学会用三种方法来绘制正方形:拼合法、顶点法(FAN模式与STRIP模式)、索引法,其中索引法最灵活。但是前几个案例我们绘制的都是实心正方形,下面我们来学习如何绘制空心正方形。

(一)运行效果

(二)实现步骤

1、创建安卓应用【DrawHollowedSquare】

2、建模:正方形类 - Square

第一条边:P1P2(0,1)P_1P_2(0, 1)P1​P2​(0,1)第二条边:P2P3(1,2)P_2P_3(1, 2)P2​P3​(1,2)第三条边:P3P4(2,3)P_3P_4(2, 3)P3​P4​(2,3)第四条边:P4P1(3,0)P_4P_1(3, 0)P4​P1​(3,0)

package net.hw.draw_hollowed_square;import java.nio.ByteBuffer;import java.nio.ByteOrder;import java.nio.FloatBuffer;import javax.microedition.khronos.opengles.GL10;/*** 功能:采用索引法绘制空心正方形* 作者:华卫* 日期:12月31日*/public class Square {private FloatBuffer squareBuffer; // 声明浮点型缓冲区变量private ByteBuffer byteBuffer; // 声明字节型缓冲区变量private ByteBuffer indexBuffer; // 声明字节型缓冲区// 定义正方形四个顶点的坐标private float[] squareVertices = new float[] {-1.5f, 1.5f, 0.0f, // 左上角顶点坐标(P1--0)1.5f, 1.5f, 0.0f, // 右上角顶点坐标(P2--1)1.5f, -1.5f, 0.0f, // 右下角顶点坐标(P3--2)-1.5f, -1.5f, 0.0f, // 左下角顶点坐标(P4--3)};// 定义正方形四条边的顶点顺序private byte[] indices = new byte[] {0, 1, // 第一条边P1P2的顶点顺序1, 2, // 第二条边P2P3的顶点顺序2, 3, // 第三条边P3P4的顶点顺序3, 0, // 第四条边P4P1的顶点顺序};/*** 构造方法:将正方形顶点坐标存放到浮点型缓冲区对象里*/public Square() {// 分配内存空间byteBuffer = ByteBuffer.allocateDirect(squareVertices.length * 4);// 按本地字节顺序来使用字节数据byteBuffer.order(ByteOrder.nativeOrder());// 将字节型缓冲区转换成浮点型缓冲区squareBuffer = byteBuffer.asFloatBuffer();// 将正方形顶点坐标数据放入浮点型缓冲区squareBuffer.put(squareVertices);// 设置浮点型缓冲区内部指针指向第一个数据squareBuffer.position(0);// 将顶点顺序存入字节缓冲区// 分配内存空间indexBuffer = ByteBuffer.allocateDirect(indices.length);// 将顶点索引数组存入字节型缓冲区indexBuffer.put(indices);// 设置字节缓冲区内部指针指向第一个数据indexBuffer.position(0);}/*** 自绘方法** @param gl*/public void drawSelf(GL10 gl) {// 将正方形顶点坐标数据加载到内存gl.glVertexPointer(3, GL10.GL_FLOAT, 0, squareBuffer);// 按索引顺序绘制空心正方形gl.glDrawElements(GL10.GL_LINES, 8, GL10.GL_UNSIGNED_BYTE, indexBuffer);}}

3、渲染:正方形表面视图 - SquareSurfaceView

package net.hw.draw_hollowed_square;import android.opengl.GLSurfaceView;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;/*** 功能:创建正方形表面视图,渲染正方形* 作者:华卫* 日期:12月31日*/public class SquareSurfaceView implements GLSurfaceView.Renderer {private Square square; // 声明正方形变量@Overridepublic void onSurfaceCreated(GL10 gl, EGLConfig config) {square = new Square(); // 实例化正方形}@Overridepublic void onSurfaceChanged(GL10 gl, int width, int height) {float ratio = (float) width / height; // 计算屏幕宽高比gl.glViewport(0, 0, width, height); // 设置视口大小,整个手机屏幕gl.glMatrixMode(GL10.GL_PROJECTION); // 设置矩阵模式为投影模式gl.glLoadIdentity(); // 设置当前矩阵为单位矩阵gl.glFrustumf(-2 * ratio, 2 * ratio, -2, 2, 1, 10); // 设置透视投影的刻度范围gl.glMatrixMode(GL10.GL_MODELVIEW); // 设置矩阵模式为模型视图模式}@Overridepublic void onDrawFrame(GL10 gl) {gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 清除手机屏幕gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // 采用顶点方式来绘制图形gl.glLoadIdentity(); // 将当前矩阵设置为单位矩阵gl.glTranslatef(0.0f, 0.0f, -2.0f); // 往屏幕内平移2个单位gl.glColor4f(1.0f, 1.0f, 0.0f, 1.0f); // 设置为黄色square.drawSelf(gl); // 绘制正方形gl.glLoadIdentity(); // 将当前矩阵设置为单位矩阵gl.glTranslatef(0.0f, 0.0f, -2.85f); // 往屏幕内平移2.85个单位gl.glRotatef(45, 0.0f, 0.0f, 1.0f); // 绕z轴旋转45度gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // 设置为红色square.drawSelf(gl); // 绘制正方形gl.glLoadIdentity(); // 将当前矩阵设置为单位矩阵gl.glTranslatef(0.0f, 0.0f, -4.0f); // 往屏幕内平移4个单位gl.glColor4f(0.0f, 1.0f, 0.0f, 1.0f); // 设置为绿色square.drawSelf(gl); // 绘制正方形gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // 禁用顶点方式来绘制图形}}

4、展示:主界面类 - MainActivity

package net.hw.draw_hollowed_square;import android.opengl.GLSurfaceView;import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;public class MainActivity extends AppCompatActivity {private GLSurfaceView mGlSurfaceView; // 图形库表面视图private SquareSurfaceView mSquareSurfaceView; // 正方形表面视图(渲染器)@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mGlSurfaceView = new GLSurfaceView(this); // 实例化图形库表面视图mSquareSurfaceView = new SquareSurfaceView(); // 实例化正方形表面视图(渲染器)mGlSurfaceView.setRenderer(mSquareSurfaceView); // 给图形库表面视图设置渲染器setContentView(mGlSurfaceView); // 将图形库表面视图设置为用户界面}}

5、启动应用,查看效果

(三)课堂练习:采用索引法绘制嵌套空心六边形

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。