本节书摘来自异步社区《Android 应用案例开发大全(第二版)》一书中的第2章,第2.5节辅助绘制类,作者 吴亚峰 , 于复兴 , 杜化美,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.5 辅助绘制类
Android 应用案例开发大全(第二版)
上一节介绍了壁纸实现的开发,本节将开始对辅助绘制类的开发进行详细介绍。在绘制3D水族馆动态壁纸中的各个物体之前,必须要做好准备工作,而这些准备工作就包括辅助绘制类的开发。辅助绘制类包括背景图辅助绘制类BackGround,气泡辅助绘制类Bubble和模型辅助绘制类LoadedObjectVertexNormalTexture,下面就对这些类的开发进行详细介绍。
2.5.1 背景图辅助绘制类——BackGround
本小节将对本案例的背景图辅助绘制类进行详细介绍,这个类的作用是绘制水族馆的馆体,所有的鱼、水草和石头都包含在水族馆的馆体内。具体代码如下所示。
1 package com.bn.ld.draw;
2 ……//此处省略部分类和包的引入代码,读者可自行查阅光盘中的源代码
3 public class BackGround {
4 private FloatBuffer mVertexBuffer; // 顶点坐标数据缓冲
5 private FloatBuffer mTextureBuffer; // 顶点纹理数据缓冲
6 int vCount;
7 public BackGround() {
8 vCount=12; // 顶点的数量
9 float vertices[]=new float[] { // 顶点坐标数据数组
10 -23*Constant.SCREEN_SCALEX,20*Constant.SCREEN_SCALEY,-30*Constant.SCREEN_SCALEZ,
11 -23*Constant.SCREEN_SCALEX,-10*Constant.SCREEN_SCALEY,-30*Constant.SCREEN_SCALEZ,
12 23*Constant.SCREEN_SCALEX,20*Constant.SCREEN_SCALEY,-30*Constant.SCREEN_SCALEZ,
13 -23*Constant.SCREEN_SCALEX,-10*Constant.SCREEN_SCALEY,-30*Constant.SCREEN_SCALEZ,
14 23*Constant.SCREEN_SCALEX,-10*Constant.SCREEN_SCALEY,-30*Constant.SCREEN_SCALEZ,
15 23*Constant.SCREEN_SCALEX,20*Constant.SCREEN_SCALEY,-30*Constant.SCREEN_SCALEZ,
16 -23*Constant.SCREEN_SCALEX,-10*Constant.SCREEN_SCALEY,-30*Constant.SCREEN_SCALEZ,
17 -23*Constant.SCREEN_SCALEX,-10*Constant.SCREEN_SCALEY,30*Constant.SCREEN_SCALEZ,
18 23*Constant.SCREEN_SCALEX,-10*Constant.SCREEN_SCALEY,-30*Constant.SCREEN_SCALEZ,
19 -23*Constant.SCREEN_SCALEX,-10*Constant.SCREEN_SCALEY,30*Constant.SCREEN_SCALEZ,
20 23*Constant.SCREEN_SCALEX,-10*Constant.SCREEN_SCALEY,30*Constant.SCREEN_SCALEZ,
21 23*Constant.SCREEN_SCALEX,-10*Constant.SCREEN_SCALEY,-30*Constant.SCREEN_SCALEZ,
22 };
23 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); // 创建顶点坐标数据缓冲
24 vbb.order(ByteOrder.nativeOrder()); // 设置字节顺序
25 mVertexBuffer = vbb.asFloatBuffer(); // 转换为int型缓冲
26 mVertexBuffer.put(vertices); // 向缓冲区中放入顶点坐标数据
27 mVertexBuffer.position(0); // 设置缓冲区起始位置
28 float textureCoors[]=new float[]{ // 顶点纹理S、T坐标值数组
29 0,0,0,0.85f,1,0,
30 0,0.85f,1,0.85f,1,0,
31 0,0.9f,0,1,1,0.9f,
32 0,1,1,1,1,0.9f
33 };
34 ByteBuffer cbb = ByteBuffer.allocateDirect(textureCoors.length*4); // 创建顶点纹理数据缓冲
35 cbb.order(ByteOrder.nativeOrder()); // 设置字节顺序
36 mTextureBuffer = cbb.asFloatBuffer(); // 转换为int型缓冲
37 mTextureBuffer.put(textureCoors); // 向缓冲区中放入顶点纹理数据
38 mTextureBuffer.position(0); // 设置缓冲区起始位置
39 }
40 public void drawSelf(GL10 gl,int texld){
41 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// 允许使用顶点数组
42 gl.glVertexPointer( // 为画笔指定顶点坐标数据
43 3, // 每个顶点的坐标数量为3
44 GL10.GL_FLOAT, // 顶点坐标的类型GL_FIXED
45 0, // 连续顶点坐标数据之间的间隔
46 mVertexBuffer ); // 顶点坐标数据
47 gl.glEnable(GL10.GL_TEXTURE_2D); // 开启纹理
48 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);// 允许使用纹理数组
49 gl.glTexCoordPointer( // 为画笔指定纹理u、v坐标数据
50 2, // 每个顶点两个纹理坐标数据 S、T
51 GL10.GL_FLOAT, // 数据类型
52 0, // 连续纹理坐标数据之间的间隔
53 mTextureBuffer ); // 纹理坐标数据
54 gl.glBindTexture(GL10.GL_TEXTURE_2D, texld); // 为画笔绑定指定名称ID纹理
55 gl.glDrawArrays( // 绘制图形
56 GL10.GL_TRIANGLES, // 以三角形的方式绘制
57 0, // 开始点编号
58 vCount // 顶点坐标的个数
59 );}}
第4~22行为创建顶点坐标缓冲和顶点纹理坐标缓冲,设置背景图片的顶点坐标。
第23~39行为初始化顶点坐标缓冲和顶点纹理数据缓冲并且设置了字节顺序,同时将数据放入了缓冲区,设置缓冲区的起始位置。
第40~59行为设置允许使用顶点数组,为画笔指定顶点坐标数据,开启纹理,允许使用纹理数组,为画笔绑定纹理,并且以三角形的方式绘制图形。
2.5.2 气泡辅助绘制类——Bubble
本小节将对案例中的气泡辅助绘制类进行详细介绍,在本案例的运行界面中,屏幕前面不断从下方冒出透明的气泡,这些气泡有大有小而且位置各不相同,上升的最大高度也不同,要绘制出这些气泡,就必须对气泡辅助绘制类进行很好地设计,具体代码如下所示。
1 package com.bn.ld.draw;
2 ……//此处省略部分类和包的引入代码,读者可自行查阅光盘中的源代码
3 public class Bubble {
4 private FloatBuffer mVertexBuffer; // 顶点坐标数据缓冲
5 private FloatBuffer mTextureBuffer; // 顶点纹理数据缓
6 int vCount=0; // 顶点数量
7 public Bubble() {
8 float UNIT_SIZE=1.0f;
9 vCount=6; // 顶点的数量
10 float vertices[]=new float[]{ //顶点坐标数据数组
11 -0.15f*UNIT_SIZE,0.15f*UNIT_SIZE,0,
12 -0.15f*UNIT_SIZE,-0.15f*UNIT_SIZE,0,
13 0.15f*UNIT_SIZE,0.15f*UNIT_SIZE,0,
14 -0.15f*UNIT_SIZE,-0.15f*UNIT_SIZE,0,
15 0.15f*UNIT_SIZE,-0.15f*UNIT_SIZE,0,
16 0.15f*UNIT_SIZE,0.15f*UNIT_SIZE,0,
17 };
18 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); // 创建顶点坐标数据缓冲
19 vbb.order(ByteOrder.nativeOrder()); // 设置字节顺序
20 mVertexBuffer = vbb.asFloatBuffer(); // 转换为int型缓冲
21 mVertexBuffer.put(vertices); // 向缓冲区中放入顶点坐标数据
22 mVertexBuffer.position(0); // 设置缓冲区起始位置
23 float textureCoors[]=new float[]{ // 顶点纹理S、T坐标值数组
24 0,0,0,1,1,0,
25 0,1,1,1,1,0
26 };
27 ByteBuffer cbb = ByteBuffer.allocateDirect(textureCoors.length*4); // 创建顶点纹理数据缓冲
28 cbb.order(ByteOrder.nativeOrder()); // 设置字节顺序
29 mTextureBuffer = cbb.asFloatBuffer(); // 转换为int型缓冲
30 mTextureBuffer.put(textureCoors); // 向缓冲区中放入顶点着色数据
31 mTextureBuffer.position(0); // 设置缓冲区起始位置
32 }
33 public void drawSelf(GL10 gl,int texld){
34 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // 允许使用顶点数组
35 gl.glVertexPointer ( // 为画笔指定顶点坐标数据
36 3, // 每个顶点的坐标数量为3
37 GL10.GL_FLOAT, // 顶点坐标值的类型为GL_FIXED
38 0, // 连续顶点坐标数据之间的间隔
39 mVertexBuffer // 顶点坐标数据
40 );
41 gl.glEnable(GL10.GL_TEXTURE_2D); // 开启纹理
42 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);// 允许使用纹理数组
43 gl.glTexCoordPointer ( // 为画笔指定纹理u、v坐标数据
44 2, // 每个顶点两个纹理坐标数据 S、T
45 GL10.GL_FLOAT, // 数据类型
46 0, // 连续纹理坐标数据之间的间隔
47 mTextureBuffer ); // 纹理坐标数据
48 gl.glBindTexture(GL10.GL_TEXTURE_2D, texld); // 为画笔绑定指定名称ID纹理
49 gl.glDrawArrays ( // 绘制图形
50 GL10.GL_TRIANGLES, // 三角形方式填充
51 0, // 开始点编号
52 vCount // 顶点坐标的个数
53 ); }}
第4~17行定义了顶点坐标缓冲和顶点纹理坐标缓冲,设置气泡的顶点坐标。
第18~32行为初始化顶点坐标缓冲和顶点纹理数据缓冲并且设置了字节顺序,同时将数据放入缓冲区,设置缓冲区的起始位置为0。
第33~53行为设置允许使用顶点数组,为画笔指定顶点坐标数据、开启纹理、允许使用纹理数组、为画笔绑定纹理,并且以三角形的方式进行绘制。
2.5.3 3D模型辅助绘制类——LoadedObjectVertexNormalTexture
因为水族馆中必不可少的是鱼,所以要向壁纸中加入鱼元素。本案例中的鱼为3D模型,下面就对加载3D模型并进行3D模型相关处理的辅助绘制类进行详细介绍,具体代码如下所示。
1 package com.bn.ld.draw;
2 ……//此处省略部分类和包的引入代码,读者可自行查阅光盘中的源代码
3 public class LoadedObjectVertexNormalTexture{
4 private FloatBuffer mVertexBuffer; // 顶点坐标数据缓冲
5 private FloatBuffer mTexBuffer; // 顶点纹理数据缓冲
6 int vCount=0; // 顶点数量
7 public LoadedObjectVertexNormalTexture(float[] vertices,float[] normals,float
texCoors[]) {
8 vCount=vertices.length/3; // 计算顶点个数
9 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4); // 创建顶点坐标数据缓冲
10 vbb.order(ByteOrder.nativeOrder()); // 设置字节顺序
11 mVertexBuffer = vbb.asFloatBuffer(); // 转换为float型缓冲
12 mVertexBuffer.put(vertices); // 向缓冲区中放入顶点坐标数据
13 mVertexBuffer.position(0); // 设置缓冲区起始位置
14 ByteBuffer vbt = ByteBuffer.allocateDirect(texCoors.length*4); // 创建纹理坐标数据缓冲
15 vbt.order(ByteOrder.nativeOrder()); // 设置字节顺序
16 mTexBuffer = vbt.asFloatBuffer(); // 转换为float型缓冲
17 mTexBuffer.put(texCoors); // 向缓冲区中放入顶点坐标数据
18 mTexBuffer.position(0); // 设置缓冲区起始位置
19 }
20 public void drawSelf(GL10 gl,int texId) {
21 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // 启用顶点坐标数组
22 gl.glEnable(GL10.GL_TEXTURE_2D); // 开启纹理
23 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);// 允许使用纹理S、T坐标缓冲
24 gl.glVertexPointer( // 为画笔指定顶点坐标数据
25 3, // 每个顶点的坐标数量为3
26 GL10.GL_FLOAT, // 顶点坐标值的类型为 GL_FIXED
27 0, // 连续顶点坐标数据之间的间隔
28 mVertexBuffer); // 顶点坐标数据
29 gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexBuffer); // 为画笔指定纹理S、T坐标缓冲
30 gl.glBindTexture(GL10.GL_TEXTURE_2D, texId); // 绑定当前纹理
31 gl.glDrawArrays ( // 绘制图形
32 GL10.GL_TRIANGLES, // 以三角形方式填充
33 0, // 开始点编号
34 vCount ); // 顶点的数量
35 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // 禁用顶点坐标数组
36 gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);// 禁用纹理S、T坐标缓冲
37 gl.glDisable(GL10.GL_TEXTURE_2D); // 禁用纹理
38 }}
第4~19行创建了顶点坐标缓冲和顶点纹理坐标缓冲,并且初始化顶点坐标缓冲和顶点纹理数据缓冲、设置了字节顺序、将数据放入了缓冲区,设置缓冲区起始位置为0。
第20~38行允许使用顶点数组、为画笔指定顶点坐标数据、开启纹理、允许使用纹理数组、为画笔绑定纹理,并以三角形的方式填充。