OpenGL -- 飘动的旗帜 (java)

转载 2012年03月28日 14:11:09

原创内容,转载请注明EOE论坛。       声明:因为本人的学习都是居于杨丰盛老师的《Android应用开发揭秘》一书,因此,本内容教程代码和大部分的内容都来自公布在网络上的杨老师的代码。C/C++部分可以看NeHe的OpenGL教程:http://yarin.blog.51cto.com/1130898/380974

 

 效果图片

 

1 . 局部顶点:我们将这张图片由X、Y轴平均分割成44份,也就是有45个分割点,这些构成小方格的点就是局部顶点了。

     2.  局部纹理:因为顶点是局部的,也就是说,要对局部顶点构成的每一个小方格进行纹理(贴图)。纹理的单位也整数“1”,所以,每个小方格就表示纹理的1/44部分了。

     3. 三角函数:因为三角函数“正弦”或者“余弦”在坐标轴上是波动的,那么我们将图片平躺在以X、Y轴的平面上,Z轴作为表示“正弦”或者“余弦”的波动轴。那么就会有我们看到的波动的效果了。
上主要代码:

 

  1. package com.geolo.android;  
  2. /* 
  3.  * 代码大部分注释源于杨丰盛的《Android应用开发揭秘》 
  4.  * */  
  5. import java.nio.FloatBuffer;  
  6. import java.nio.IntBuffer;  
  7. import javax.microedition.khronos.egl.EGLConfig;  
  8. import javax.microedition.khronos.opengles.GL10;  
  9. import android.content.Context;  
  10. import android.graphics.Bitmap;  
  11. import android.graphics.BitmapFactory;  
  12. import android.opengl.GLSurfaceView.Renderer;  
  13. import android.opengl.GLU;  
  14. import android.opengl.GLUtils;  
  15. public class MyRenderer implements Renderer {  
  16.   
  17.         private float vertex[][][]=new float[45][45][3];//局部顶点数组(45,45,3)          
  18.         private float hold;// 局部顶点数据的临时变量  
  19.         private float angleX,angleY = 0;  
  20.         public float getAngleY() {  
  21.                 return angleY;  
  22.         }  
  23.         public void setAngleY(float angleY) {  
  24.                 this.angleY = angleY;  
  25.         }  
  26.         private Bitmap mBitmap = null;  
  27.         private int textrueId = 0;  
  28.         private FloatBuffer texCoord = FloatBuffer.allocate(8);  
  29.         private FloatBuffer points = FloatBuffer.allocate(12);  
  30.         int wiggle_count = 0;// 指定旗形波浪的运动速度  
  31.         public MyRenderer(Context context){//构造函数,用来初始化纹理用的图片  
  32.                 mBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.img);  
  33.         }  
  34.         @Override  
  35.         public void onSurfaceCreated(GL10 gl, EGLConfig config) {  
  36.                 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);//告诉系统需要对透视进行修正  
  37.                 gl.glClearColor(0, 0, 0, 1);//设置清理屏幕的颜色  
  38.                 gl.glEnable(GL10.GL_DEPTH_TEST);//启用深度缓存  
  39.                 gl.glClearDepthf(10.0f);//设置深度测试  
  40.                 gl.glDepthFunc(GL10.GL_LEQUAL);//深度测试的类型(小于或者等于时我们都渲染)  
  41.                 setupTexture(gl);//加载纹理  
  42.                 initData();//初始化局部顶点的数据  
  43.         }  
  44.         @Override  
  45.         public void onSurfaceChanged(GL10 gl, int width, int height) {  
  46.                 float radio = (float)width/height;  
  47.                 gl.glViewport(0, 0, width, height);//设置视口(OpenGL场景的大小)  
  48.                 gl.glMatrixMode(GL10.GL_PROJECTION);//设置投影矩阵为透视投影  
  49.                 gl.glLoadIdentity();//重置投影矩阵(置为单位矩阵)  
  50.                 gl.glFrustumf(-radio, radio, -1, 1, 1, 30);//创建一个透视投影矩阵(设置视口大小)  
  51.         }  
  52.         @Override  
  53.         public void onDrawFrame(GL10 gl) {  
  54.                 // 首先清理屏幕  
  55.                 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);  
  56.                 // 设置模型视图矩阵  
  57.                 gl.glMatrixMode(GL10.GL_MODELVIEW);  
  58.                 //重置矩阵  
  59.                 gl.glLoadIdentity();  
  60.                 // 视点变换  
  61.                 GLU.gluLookAt(gl, 0, 0, 3, 0, 0, 0, 0, 1, 0);  
  62.                 //绘制旗帜  
  63.                 drawFlag(gl);  
  64.         }  
  65.         /**装载纹理*/  
  66.         private void setupTexture(GL10 gl){  
  67.                 gl.glEnable(GL10.GL_TEXTURE_2D);// 开启2D纹理贴图  
  68.                 IntBuffer intBuffer = IntBuffer.allocate(1);//创建一个int[]单位的缓冲区,用来存储该纹理的名称ID  
  69.                 gl.glGenTextures(1, intBuffer);//创建纹理,并将纹理ID值写入缓冲区。--不知道我的理解对不对。。。。  
  70.                 textrueId = intBuffer.get();//保存ID名称  
  71.                 //根据纹理ID绑定纹理  
  72.                 gl.glBindTexture(GL10.GL_TEXTURE_2D, textrueId);  
  73.                 // 生成纹理或者说载入纹理  
  74.                 GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, mBitmap, 0);  
  75.                 // 配置图像也可以说是设置滤波  
  76.                 gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_NEAREST);  
  77.                 gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);          
  78.                 //因为已经载入了纹理,因此,Bitmap可以被清除。  
  79.                 mBitmap.recycle();  
  80.                 mBitmap = null;  
  81.         }  
  82.         /**初始化顶点数据*/  
  83.         private void initData(){  
  84.                 // 沿X平面循环  
  85.                 for(int x=0; x<45; x++){  
  86.                         // 沿Y平面循环  
  87.                         for(int y=0; y<45; y++){  
  88.                                 // 向表面添加波浪效果  
  89.                                 vertex[x][y][0]=((float)x/5.0f)-4.5f;//x  
  90.                                 vertex[x][y][1]=(((float)y/5.0f)-4.5f); //y  
  91.                                 vertex[x][y][2]=(float)(Math.sin(((((float)x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));//z  
  92.                         }  
  93.                 }  
  94.         }  
  95.         private void drawFlag(GL10 gl){  
  96.                 int x, y;// 循环变量                          
  97.                 float float_x, float_y, float_xb, float_yb;        //用来将旗形的波浪分割成很小的四边形  
  98.                 gl.glTranslatef(0.0f,0.0f,-12.0f);//平移操作                                  
  99.                 // 旋转操作  
  100.                 gl.glRotatef(angleX,1.0f,0.0f,0.0f);                                  
  101.                 gl.glRotatef(angleY,0.0f,1.0f,0.0f);                                                          
  102.                 // 允许设置顶点数组和纹理坐标数组  
  103.                 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);  
  104.                 gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  
  105.                 // 设置顶点数组、纹理坐标数组  
  106.                 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, points);  
  107.                 gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoord);  
  108.                 gl.glBindTexture(GL10.GL_TEXTURE_2D, textrueId);//绑定纹理                  
  109.                 for (x = 0; x < 44; x++){  
  110.                         for (y = 0; y < 44; y++){  
  111.                                 float_x = (float) (x) / 44.0f; // 生成X浮点值  
  112.                                 float_y = (float) (y) / 44.0f; // 生成Y浮点值  
  113.                                 float_xb = (float) (x + 1) / 44.0f; // X浮点值+0.0227f  
  114.                                 float_yb = (float) (y + 1) / 44.0f; // Y浮点值+0.0227f  
  115.                                 // 保存纹理坐标数组  
  116.                                 texCoord.clear();  
  117.                                 texCoord.put(float_x);  
  118.                                 texCoord.put(float_y);  
  119.                                 texCoord.put(float_x);  
  120.                                 texCoord.put(float_yb);  
  121.                                 texCoord.put(float_xb);  
  122.                                 texCoord.put(float_yb);  
  123.                                 texCoord.put(float_xb);  
  124.                                 texCoord.put(float_y);  
  125.                                 // 保存顶点数组  
  126.                                 points.clear();  
  127.                                 points.put(vertex[x][y][0]);  
  128.                                 points.put(vertex[x][y][1]);  
  129.                                 points.put(vertex[x][y][2]);  
  130.                                 points.put(vertex[x][y + 1][0]);  
  131.                                 points.put(vertex[x][y + 1][1]);  
  132.                                 points.put(vertex[x][y + 1][2]);  
  133.                                 points.put(vertex[x + 1][y + 1][0]);  
  134.                                 points.put(vertex[x + 1][y + 1][1]);  
  135.                                 points.put(vertex[x + 1][y + 1][2]);  
  136.                                 points.put(vertex[x + 1][y][0]);  
  137.                                 points.put(vertex[x + 1][y][1]);  
  138.                                 points.put(vertex[x + 1][y][2]);  
  139.                                 // 绘制  
  140.                                 gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);  
  141.                         }  
  142.                 }  
  143.                 // 禁止设置顶点数组、纹理坐标数组  
  144.                 gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);  
  145.                 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);  
  146.   
  147.                 // 用来降低波浪速度(每隔2帧一次)  
  148.                 if( wiggle_count == 2 ){  
  149.                         // 沿Y平面循环  
  150.                         for( y = 0; y < 45; y++ ){  
  151.                                 // 存储当前左侧波浪值  
  152.                                 hold=vertex[0][y][2];  
  153.                                 // 沿X平面循环  
  154.                                 for( x = 0; x < 44; x++){  
  155.                                         // 当前波浪值等于其右侧的波浪值  
  156.                                         vertex[x][y][2] = vertex[x+1][y][2];  
  157.                                 }  
  158.                                 // 刚才的值成为最左侧的波浪值  
  159.                                 vertex[44][y][2]=hold;                          
  160.                         }  
  161.                         // 计数器清零  
  162.                         wiggle_count = 0;          
  163.                 }  
  164.                 wiggle_count++;          
  165.         }  
  166.         public float getAngleX() {  
  167.                 return angleX;  
  168.         }  
  169.         public void setAngleX(float angleX) {  
  170.                 this.angleX = angleX;  
  171.         }  
  172. }  
 

 

   -->  分析下代码的主要部分:

 

  1. for(int x=0; x<45; x++){  
  2.   for(int y=0; y<45; y++) {  
  3.    // 向表面添加波浪效果  
  4.    points[x][y][0]=float((x/5.0f)-4.5f);  
  5.    points[x][y][1]=float((y/5.0f)-4.5f);  
  6.    points[x][y][2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f));  
  7.   }  
  8.  }  
 

 

    上面的两个循环初始化网格上的点。使用整数循环可以消除由于浮点运算取整造成的脉冲锯齿的出现。我们将x和y变量都除以5,再减去4.5。这样使得我们的波浪可以“居中”(译者:这样计算所得结果将落在区间[-4.5,4.5]之间)。(NeHe文章翻译)
       点[x][y][2]最后的值就是一个sine函数计算的结果。Sin()函数需要一个弧度参变量。将float_x乘以40.0f,得到角度值。然后除以360.0f再乘以PI,乘以2,就转换为弧度了。(NeHe文章翻译)    

 

  1. for( y = 0; y < 45; y++ ){  
  2.                                 // 存储当前左侧波浪值  
  3.                                 hold=vertex[0][y][2];  
  4.                                 // 沿X平面循环  
  5.                                 for( x = 0; x < 44; x++){  
  6.                                         // 当前波浪值等于其右侧的波浪值  
  7.                                         vertex[x][y][2] = vertex[x+1][y][2];  
  8.                                 }  
  9.                                 // 刚才的值成为最左侧的波浪值  
  10.                                 vertex[44][y][2]=hold;                          
  11.                         }  
 

 

  我们每次要将当前的小方格的局部坐标保存起来,在下一次将该坐标传递给下一个小方格---物理学上,粒子波动的效果。比如跳绳。
     如果疑问,我会在补充内容。

 

 

效果图:

 

源代码:::http://www.eoeandroid.com/thread-66326-1-1.html

相关文章推荐

OpenGL -- 飘动的旗帜 (java)

原创内容,转载请注明EOE论坛。       声明:因为本人的学习都是居于杨丰盛老师的《Android应用开发揭秘》一书,因此,本内容教程代码和大部分的内容都来自公布在网络上的杨老师的代码。C/C++...
  • GEOLO
  • GEOLO
  • 2011年03月27日 18:48
  • 3247

NeHe OpenGL第十一课:飘动的旗帜

yarin原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://yarin.blog.51cto.com/1130898/380349N...
  • GEOLO
  • GEOLO
  • 2011年07月14日 16:09
  • 948

OpenGL学习三十九:飘动的旗帜

(此节内容对应NEHE教程第11课)   目前为止我们做的例子都是平面的,这个例子是带有波动效果的, 2维图形包括X,Y两个坐标系。因此看到的是平面的。 3维图形由X,Y,Z三个坐标系构成,当...

Android实现飘动的旗帜效果实例

做一个飘动的旗帜效果,思路大概为:将旗形的波浪分割成很小的四边形,然后多少时间进行刷新,Z方向上运用sin函数改变,看起来有飘动的感觉 实例代码如下: 1、准备图片资源 : initBit...

Unity ShaderLab: 2D/3D Wave Flag Shader(飘动旗帜)的实现

个人实现的第一个在实际项目中使用的shader。 2D Wave Flag Shader 效果图: Shader "Custom/WaveFlag2D" {Properties { _Col...

Nehe第11课飘动的旗帜

  • 2012年03月26日 20:15
  • 2.56MB
  • 下载

OpenGL-11飘扬的旗帜

  • 2015年07月16日 10:28
  • 539KB
  • 下载

android opengl es 飘动的flag

越来越感到知识相关性的重要性,光会一点编程,是远远不够的。数学,物理,和计算机是不可分割兄弟。 (1)Activity类 package sim.feel; import android.app...

OpenGL飘动的钟表

  • 2013年01月22日 18:47
  • 315KB
  • 下载

opengl绘制飘动的国旗效果源码

  • 2017年09月06日 16:51
  • 1000KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OpenGL -- 飘动的旗帜 (java)
举报原因:
原因补充:

(最多只允许输入30个字)