暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Android App开发超实用实例 | OpenGL在Android手机场景中绘制五角星

559

OpenGL(Open Graphics Library)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API),它由数百个不同的函数调用组成,用来呈现复杂的三维景象。下面这个实例演示了使用OpenGL在Android手机场景中绘制五角星。


01

实例功能


此实例主要通过使用GLSurfaceView控件加载自定义OpenGL渲染器Renderer,并在该Renderer中设置glDrawArrays()方法的参数值为GL10.GL_LINE_LOOP,实现在场景中绘制五角星。OpenGL(Open Graphics Library)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API),它由数百个不同的函数调用组成,用来呈现复杂的三维景象。

当该实例运行之后,单击“绘制五角星”按钮,在场景中绘制的五角星效果分别如图1(a)和图1(b)所示。在Android中,通常使用android.opengl.GLSurfaceView控件承载OpenGL的内容。


■ 图1


02

实现代码



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.bin.luo.mysample.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClickButton1"
            android:text="绘制五角星"
            android:textAllCaps="false"
            android:textSize="16dp" />

    </LinearLayout>
    <android.opengl.GLSurfaceView
        android:id="@+id/myGLSurfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>


03

代码说明


上面这段代码在MyCode\MySampleO61\app\src\main\res\layout\activity_main.xml文件中。在Android中,GLSurfaceView控件继承自SurfaceView,该控件实现了SurfaceHolder.Callback2接口,拥有SurfaceView的全部特性,也有View所有的功能和属性,特别是处理事件的功能,它主要是在SurfaceView的基础上加入了EGL的管理,并自带了一个GLThread绘制线程(EGLContext创建GL环境所在线程即为GLThread),绘制的工作直接通过OpenGL在绘制线程中进行,不会阻塞主线程,绘制的结果输出到SurfaceView所提供的Surface上,这使得GLSurfaceView也拥有了OpenGL ES所提供的图形处理功能,通过它定义的Render接口,使更改具体的Render的行为非常灵活,只需要将实现了渲染功能的Renderer的实现类设置给GLSurfaceView即可,如下面的代码所示: 

public class MainActivity extends Activity {
 MyRenderer myRenderer;
 GLSurfaceView myGLSurfaceView;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  myGLSurfaceView = (GLSurfaceView) findViewById(R.id.myGLSurfaceView);
  myRenderer = new MyRenderer();
  myGLSurfaceView.setRenderer(myRenderer);
 }
 public void onClickButton1(View v) {//响应单击按钮“绘制五角星”
  float[] myVerticesCoord = new float[]{
          0.5f, 0f, 0.0f,
          0.63f, 0.38f, 0.0f,
          1, 0.38f, 0.0f,
          0.69f, 0.59f, 0.0f,
          0.82f, 1f, 0.0f,
          0.5f, 0.75f, 0.0f,
          0.18f, 1f, 0.0f,
          0.31f, 0.59f, 0.0f,
          0, 0.38f, 0.0f,
          0.37f, 0.38f, 0.0f};
  myRenderer.resetVerticesCoord(myVerticesCoord);
 }
}


上面这段代码在MyCode\MySampleO61\app\src\main\java\com\bin\luo\mysample\ MainActivity.java文件中。在上面这段代码中,MyRenderer类即是一个自定义的OpenGL渲染器,所有的绘制工作均在此类中实现。MyRenderer类的主要代码如下:

public class MyRenderer implements GLSurfaceView.Renderer{
 float myVerticesCoord[]={};
 FloatBuffer myVerticesBuffer;
 public MyRenderer(){resetVerticesCoord(myVerticesCoord);}
 //重新设置顶点坐标,并初始化对应的缓冲区
 public void resetVerticesCoord(float[] verticesCoord){
  myVerticesCoord=verticesCoord;
  myVerticesBuffer=ByteBuffer.allocateDirect(myVerticesCoord.length*4)
          .order(ByteOrder.nativeOrder())
          .asFloatBuffer();
  myVerticesBuffer.put(myVerticesCoord);
  myVerticesBuffer.position(0);
 }
 @Override
 public void onSurfaceCreated(GL10 gl, EGLConfig config){}
 @Override
 public void onSurfaceChanged(GL10 gl, int width, int height){
  gl.glViewport(0,0,width,height);
  gl.glMatrixMode(GL10.GL_PROJECTION);
  gl.glLoadIdentity();
  GLU.gluPerspective(gl,45.0f,(float)width/(float)height,0.1f,100.0f);
  gl.glMatrixMode(GL10.GL_MODELVIEW);
 }
 @Override
 public void onDrawFrame(GL10 gl){
  //设置场景背景为白色
  gl.glClearColor(1.0f,1.0f,1.0f,1.0f);
  //清除颜色和深度缓存
  gl.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT);
  gl.glLoadIdentity();
  gl.glTranslatef(-0.5f,-0.5f,-2); //平移图形到指定位置
  gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
  gl.glVertexPointer(3,GL10.GL_FLOAT,0,myVerticesBuffer);
  gl.glLineWidth(8f); //设置线条宽度
  gl.glColor4f(1.0f,0.0f,0.0f,1.0f); //设置线条颜色
  //根据顶点坐标绘制封闭图形
  gl.glDrawArrays(GL10.GL_LINE_LOOP,0,myVerticesCoord.length/3);
 }
}


上面这段代码在MyCode\MySampleO61\app\src\main\java\com\bin\luo\mysample\ MyRenderer.java文件中。在这段代码中gl.glDrawArrays(GL10.GL_LINE_LOOP,0, myVerticesCoord.length/3)用于绘制封闭图形(五角星),glDrawArrays()方法的语法声明如下: 

void glDrawArrays(int mode,int first,int count)


其中,参数int mode 表示绘制模式,OpenGL 2.0及其后续版本提供以下参数值: GL_LINE_LOOP、GL_LINE_STRIP、GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN、GL_POINTS、GL_LINES;参数int first设置从数组缓存中的哪个位置开始绘制,一般为0;参数int count表示在数组中顶点的数量。

此实例的完整代码在MyCode\MySampleO61文件夹中。


04

补充说明


在测试代码时,必须保持网络畅通。


05

源代码下载

关注微信公众号,后台回复关键词 “Android App开发超实用代码136” 即可获得完整源代码。



06

参考书籍


扫码优惠购书


《Android App开发超实用代码集锦——jQuery Mobile+OpenCV+O》

ISBN:9787302589358

作者:罗帅、罗斌

定价:99元



问题描述+解决方案+真实源码+效果截图

介绍jQuery Mobile、OpenCV、OpenGL等在Android平台运行的应用

300个实例,提供完整源代码,边看边做边学



文章转载自清华计算机学堂,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论