520 likes | 727 Views
第七章 多媒体开发. 本章主要内容. 多媒体开发. 多媒体即 Multimedia ,含义: 在计算机系统中组合两种或两种以上媒体的一种人机交互式的信息交流 方式。 本章介绍 如何在 Android 上应用多媒体,达到让应用程序美观、易用并且具有吸引力的效果。. 多媒体开发. 音频. 原生 Android 系统所支持解码即播放的音频格有: AAC , AMR , WAV , MP3 , WMA , OGG , MIDI 及 FLAC ( 3.1+ )等等 ; 支持编码的音频格式有: AAC , AMR 。
E N D
多媒体开发 多媒体即Multimedia,含义:在计算机系统中组合两种或两种以上媒体的一种人机交互式的信息交流方式。 本章介绍如何在Android上应用多媒体,达到让应用程序美观、易用并且具有吸引力的效果。
多媒体开发 音频 原生Android系统所支持解码即播放的音频格有:AAC,AMR,WAV,MP3,WMA,OGG,MIDI及FLAC(3.1+)等等;支持编码的音频格式有:AAC,AMR。 而对于Android模拟器来说,暂时只支持解码OGG,WAV和MP3三种格式。
多媒体开发 播放音频 借助于Android提供的MediaPlayer类可以快速的完成播放一段音频的代码实现。 创建MediaPlayer对象的方式有两种,一是使用静态方法MediaPlayer.create创建,通过参数使播放器与资源相关联起来,再使用start()方法开始播放指定的音频文件,代码如下: MediaPlayermediaPlayer = MediaPlayer.create(this, R.raw.tmp); mediaPlayer.start();
多媒体开发 播放音频 二是使用构造方法MediaPlayer()创建一个播放器对象,然后使用播放器的setDataSource()方法将音频资源相关联。 代码如下: MediaPlayermp = newMediaPlayer(); mp.setDataSource(PATH_TO_FILE); mp.prepare(); mp.start();
多媒体开发 录制音频 录制音频资源最方便的方式是使用MediaRecorder类,通过设置录制音频来源(通常是设备默认的麦克风)就能方便的录制语音,具体包括如下一些步骤: new一个android.media.MediaRecorder实例; 使用MediaRecorder.setAudioSource()方法来设置音频资源;这将会很可能使用到MediaRecorder.AudioSource.MIC; 使用MediaRecorder.setOutputFormat()方法设置输出文件格式; 用MediaRecorder.setAudioEncoder()方法来设置音频编码; 使用setOutputFile()方法设置输出的音频文件; 最后,使用prepare()和start()方法开始录制音频,通过stop()和release()方法完成一段音频的录制。
多媒体开发 录制音频——代码示例 /* 实例化MediaRecorder对象 */ recorder = newMediaRecorder(); /* 设置麦克风 */ recorder.setAudioSource(MediaRecorder.AudioSource.MIC); /* 设置输出文件的格式 */ recorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT); /* 设置音频文件的编码 */ recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); /* 设置输出文件的路径 */ recorder.setOutputFile(mRecAudioFile.getAbsolutePath()); /* 准备 */ recorder.prepare(); /* 开始 */ recorder.start(); /* 停止录音 */ recorder.stop(); /* 释放MediaRecorder */ recorder.release();
多媒体开发 注意 录制音频 由于录制音频需要使用麦克风,因此需要在AndroidManifest.xml文件中声明使用麦克风的权限: <uses-permissionandroid:name="android.permission.RECORD_AUDIO"></uses-permission>
多媒体开发 视频 Android原生系统所支持解码的视频编码格式有:H.263(后缀.3gp和.mp4)、H.264 AVC(3.0+版本,后缀.3gp和.mp4等等)、MPEG-4 SP(后缀.3gp)和VP8(2.3.3+版本,后缀.webm),其中H.263和H.264是Android支持的编码格式。 与音频的使用方式的不同点是音频本身并不会表现为用户界面,而视频则需要成为用户界面的一部分,视频播放只要使用VideoView类就可以实现,而视频录制也是借助于MediaRecorder类。
多媒体开发 播放视频 使用VideoView播放视屏的代码如下: Context context = getApplicationContext(); VideoViewmVideoView = newVideoView(context); mVideoView = (VideoView) findViewById(R.id.surface_view); mVideoView.setVideoURI(Uri.parse(path)); MediaController mc = newMediaController(this); mc.setAnchorView(mVideoView); mVideoView.setMediaController(mc); mVideoView.requestFocus(); mVideoView.start();
多媒体开发 录制视频——Preview类 Preview类主要就是实现了SurfaceHolder.Callback接口的三个回调方法,并且加入了用于监听开始录制和停止录制的按键事件方法,以及用于控制视频开始录制和停止录制的方法。下面是Preview类的一些变量和构造函数。 publicclass Preview extendsSurfaceViewimplementsSurfaceHolder.Callback{ privateSurfaceHolderholder = null; privatestaticbooleanisRecording = false; /* 录制的视频文件名及存放路径 */ private File mRecVideoFile; private File mRecVideoPath; /* MediaRecorder对象 */ privateMediaRecordermMediaRecorder; /* 录制视频文件名的前缀 */ private String strTempFile = "A_VideoRecordTest_"; public Preview(Context context) { super(context); holder = this.getHolder();//获取SurfaceHolder对象 holder.addCallback(this);//添加回调接口 holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//缓冲类型 holder.setFixedSize(400, 300);//设置视图大小 } ……
多媒体开发 录制视频——Preview类 surfaceCreated()方法,初始化视频预览界面。 publicvoidsurfaceCreated(SurfaceHolder holder) { if(mMediaRecorder==null){ mRecVideoFile = new File("/mnt/sdcard/VideoRecordTempFile.3gp"); mMediaRecorder = newMediaRecorder(); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); mMediaRecorder.setOutputFile(mRecVideoFile.getAbsolutePath()); mMediaRecorder.setPreviewDisplay(holder.getSurface()); try { mMediaRecorder.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
多媒体开发 录制视频——Preview类 onKeyDown()方法,处理键被按下的事件。 publicbooleanonKeyDown(intkeyCode, KeyEvent event) { switch(keyCode){ caseKeyEvent.KEYCODE_DPAD_CENTER:{ //方向导航键中键 if(mMediaRecorder !=null){ if(isRecording){ finishRecordVideo(); isRecording = false; } else{ startRecordVideo(); isRecording = true; } } break; } caseKeyEvent.KEYCODE_BACK:{ System.exit(0); } } returnsuper.onKeyDown(keyCode, event); }
多媒体开发 录制视频——Preview类 startRecordVideo()方法,开始录制视频(保存视频文件)。 publicvoidstartRecordVideo(){ try{ /* 创建视频文件 */ mRecVideoFile = File.createTempFile(strTempFile, ".3gp", mRecVideoPath); /* 设置输出文件的路径 */ mMediaRecorder.setOutputFile(mRecVideoFile.getAbsolutePath()); mMediaRecorder.setPreviewDisplay(holder.getSurface()); /* 准备 */ mMediaRecorder.prepare(); /* 开始 */ mMediaRecorder.start(); }catch (IOException e){ e.printStackTrace(); } } 实现了Preview之后,在主Activity中使用setContentView()方法将视图设置为Preview即可。
使用Path类绘制2D图形 Android提供了Path类用于绘制2D图形。 Path类简单来说就是封装了一系列由线段(方形、多边形等)、2次曲线(圆、椭圆等)和3次曲线复合而成的几何轨迹集合的类,借助于Canvas的drawPath(path, paint)方法可以将这些轨迹集合绘制出来,这里面另外一个paint参数则是用于设置画笔风格。
使用Path类绘制2D图形 Path类基本方法 Path提供了很多绘制基本图形的方法,例如: • addArc():用于绘制一段圆弧; • addCircle():用于绘制圆形; • addOval():用于绘制椭圆; • addPath():用于绘制一组轨迹; • addRect():用于绘制矩形; • addRoundRect():用于绘制圆角矩形; 可以使用这些提供好的方法为基础通过组合绘制出各种图形。另外Path还提供了一些直接操作元线段的方法,例如moveTo()、lineTo()等方法。
使用Path类绘制2D图形 Path绘制2D图形示例 初始界面 画出直线和圆 通过点击画曲线
使用Path类绘制2D图形 Path绘制2D图形代码示例 PathView的代码如下: publicclassPathViewextends View { private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //抗锯齿 private Path mPath;//声明Path类对象 privatebooleanmCurDown;//指示屏幕是否被按下(点击) privateintmCurX;//被点击点的坐标 privateintmCurY; privatefinalRectmRect = newRect();//该矩形用于控制局部更新区域 publicPathView(Context context, AttributeSetattrs) { super(context, attrs); setFocusable(true); //设置视图可获得焦点 setFocusableInTouchMode(true);//设置视图可获取触摸事件 mPaint.setStyle(Paint.Style.STROKE);//绘制成线 mPaint.setStrokeWidth(3);//设置绘制线宽 mPath = new Path();//创建Path实例 }
使用Path类绘制2D图形 Path绘制2D图形代码示例 drawLine(),用于绘制直线的方法。 publicvoiddrawLine(){//向Path中添加一条线段供绘制 mPath.moveTo(20, 20); mPath.lineTo(120, 1200); invalidate();//立即更新视图 } drawCircle(),用于绘制圆圈的方法。 publicvoiddrawCircle(){//向Path中添加一个圆形供绘制 mPath.addCircle(180, 180, 45, Path.Direction.CCW); invalidate(); }
使用Path类绘制2D图形 Path绘制2D图形代码示例 showPath(),显示绘制的图形。 privatevoidshowPath(Canvas canvas, int x, int y, Path.FillTypeft, Paint paint) { canvas.translate(x, y); canvas.clipRect(0, 0, 280, 300);//可以绘制图形的区域 canvas.drawColor(Color.WHITE);//为该区域着色 mPath.setFillType(ft);//设置fill方式 canvas.drawPath(mPath, paint);//绘制Path } onDraw(),用于更新显示。 protectedvoidonDraw(Canvas canvas) { Paint paint = mPaint; canvas.drawColor(0xFFCCCCCC);//为Canvas着色 canvas.translate(20, 20);//Canvas向左下方向偏移(20,20) paint.setAntiAlias(true);//抗锯齿 paint.setColor(Color.BLACK);//设置画笔颜色 paint.setPathEffect(null);//不采用特效 showPath(canvas, 0, 0, Path.FillType.WINDING, paint }
使用Path类绘制2D图形 Path绘制2D图形代码示例 onTouchEvent(),处理触摸事件;drawPoint(),画点。 publicbooleanonTouchEvent(MotionEvent event) { int action = event.getAction(); mCurDown = action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE; int N = event.getHistorySize(); for (int i=0; i<N; i++) { drawPoint(event.getHistoricalX(i), event.getHistoricalY(i)); } drawPoint(event.getX(), event.getY());//添加当前被触摸的点 returntrue; } privatevoiddrawPoint(float x, float y) { mCurX = (int)x - 20; mCurY = (int)y - 20; if (mCurDown) {//添加当前被触摸点并刷新视图显示 mPath.addCircle(mCurX, mCurY, 1, Path.Direction.CCW); mRect.set((int)x-3, (int)y-3, (int)x+3, (int)y+3); invalidate(mRect); //只更新矩形区域 } }
界面实现的注意事项 使用Path类绘制2D图形 Path绘制2D图形 由于该示例中还需要在Activity中添加一些其他的UI控件,所以需要在布局文件中将PathView作为一个控件元素使用,使之成为界面组成的一部分。 <FrameLayoutandroid:layout_width="fill_parent" android:layout_height="wrap_content“ android:layout_weight="1"> <com.android.example.pathdraw.PathView android:id="@+id/pathdrawview" android:layout_width="fill_parent" android:layout_height="fill_parent"/> </FrameLayout>
使用OpenGL ES绘制3D图形 OpenGL 简介 Logo • OpenGL(Open Graphics Library) • OpenGL是一个图形编程接口规范标准,用于生成二维、三维图像。特点: • 跨编程语言 • 跨平台 • OpenGL由近三百五十个不同的函数调用组成,用来从简单的图元绘制复杂的三维景象,它的主要用途在于: • CAD • 虚拟现实 • 科学可视化程序 • 游戏程序设计
使用OpenGL ES绘制3D图形 OpenGL 发展历程 • OpenGL进化自SGI的早期3D接口IRIS GL。 • 1992年7月 发布了 OpenGL 1.0 版本,并与微软共同推出 Windows NT 版本的 OpenGL 。 • 1995年 OpenGL 1.1 版本面市,加入了新功能,并引入了纹理特性等等。 • 2003年的7月28日,SGI和ARB公布了OpenGL 1.5。OpenGL 1.5的新功能包括:顶点Buffer Object、Shadow功能、隐蔽查询、非乘方纹理等。
使用OpenGL ES绘制3D图形 OpenGL 发展历程 • 2004年8月,OpenGL2.0版本由3Dlabs发布。opengl2.0支持OpenGL Shading Language、新的shader扩展特性以及其他多项增强特性。 • 2008年Khronos工作组推出OpenGL 3,增加了新版本的shader语言, OpenGL着色语言GLSL1.30,可以充分发挥当前可编程图形硬件的潜能。 • 2009年3月公布了升级版新规范OpenGL 3.1, OpenGL着色语言“GLSL”从1.30版升级到了1.40版,通过改进程序增强了对最新可编程图形硬件的访问,还有更高效的顶点处理、扩展的纹理功能、更弹性的缓冲管理等等。
使用OpenGL ES绘制3D图形 OpenGL 发展历程 • 2009年8月Khronos小组发布了OpenGL 3.2。OpenGL3.2版本提升了性能表现、改进了视觉质量、提高了几何图形处理速度,而且使Direct3D程序更容易移植为OpenGL。 • 2010年3月10日, OpenGL同时推出了3.3和4.0版本,同年7月26日又发布了4.1版本,OpenGL4.1提高视觉密集型应用OpenCL™的互操作性,并继续加速计算剖面为核心的支持和兼容性,到目前(2011/6/11)OpenGL4.1仍是最新版本。
使用OpenGL ES绘制3D图形 OpenGL ES 简介 • OpenGL ES (OpenGL for Embedded Systems) • 它是OpenGL用于嵌入式系统的API库 • 是 OpenGL三维图形API的子集 • 针对手机、PDA和游戏主机等嵌入式设备而设计 • OpenGL ES 与OpenGL的联系 • OpenGL ES 是从 OpenGL 裁剪定制而来的 • 去除了复杂图元等许多非绝对必要的特性 • OpenGL ES 1.0 以 OpenGL 1.3 规范为基础 • OpenGL ES 1.1 以 OpenGL 1.5 规范为基础 • OpenGL ES 2.0 则是参照 OpenGL 2.0 规范定义 Logo
使用OpenGL ES绘制3D图形 Android OpenGL ES 简介 Android系统通过OpenGL ES API来提供对高性能3D图形的支持。 • Android 3D 图形系统分为两部分: • Java 框架 • 本地代码 • 本地代码主要实现的 OpenGL 接口的库,在 Java框架层,javax.microedition.khronos.opengles是 java 标准的 OpenGL 包,android.opengl包提供了 OpenGL 系统和 Android GUI 系统之间的联系。
使用OpenGL ES绘制3D图形 Android OpenGL ES 支持列表 • GL • GL 10 • GL 10 EXT • GL 11 • GL 11 EXT • GL 11 ExtensionPack
使用OpenGL ES绘制3D图形 Android OpenGL ES 开发入门 Android OpenGL API——android.opengl 接口:
使用OpenGL ES绘制3D图形 Android OpenGL ES 开发入门 android.opengl概览 类:
使用OpenGL ES绘制3D图形 Android OpenGL ES 开发入门 android.opengl概览 类(续):
使用OpenGL ES绘制3D图形 Android OpenGL入门——GLSurfaceView 要在Android设备上显示opengl图像,首先需要在布局中加入一个用于显示opengl图形的视图(View)。 类似于其他的一些View例如,GridView、ListView、MapView等等,Android提供了GLSurfaceView用于显示opengl图像。 我们可以通过继承GLSurfaceView来实现自己的用于opengl的View,当然,最简单的用法是直接使用它。用法如下,在对应Activity的onCreate()方法中加入: GLSurfaceView view = newGLSurfaceView(this); view.setRenderer(newOpenGLRenderer()); setContentView(view);
使用OpenGL ES绘制3D图形 Android OpenGL入门——GLSurfaceView 一个简单的Renderer——矩形 GLSurfaceView Renderer的绘制结果
使用OpenGL ES绘制3D图形 Android OpenGL入门——Renderer GLSurfaceView view = newGLSurfaceView(this); view.setRenderer(newOpenGLRenderer()); setContentView(view); GLSurfaceView只是在布局中加入了一块View用于绘制图形,而Renderer类就是用于绘制具体的图形了,如上段代码的第二句就是给GLSurfaceView设置了一个用于绘图的Renderer。 GLSurfaceView.Renderer是Android提供的一个接口,所有用于绘制图像的Renderer类都必须实现这个接口。
使用OpenGL ES绘制3D图形 Android OpenGL入门——Renderer 实现Renderer接口需要实现如下三个方法: publicvoidonSurfaceCreated(GL10 gl, EGLConfigconfig) 该函数在视图需要创建的时候调用。一些用于初始化的绘制代码通常放在这里。 publicvoidonDrawFrame(GL10 gl) 该函数内是实现具体绘制业务的代码。 publicvoidonSurfaceChanged(GL10 gl, int width, int height) 该函数在屏幕尺寸发生变化时调用,用于适应屏幕的调整。
使用OpenGL ES绘制3D图形 一个简单的Renderer——矩形 • 要实现前面所示的白色矩形,我们通过实现Renderer接口来实现这个特定的Renderer——OpenGLRenderer • 为了让结构变得清晰,首先把矩形的具体实现放在一个单独的类中,命名为——Square,这个类主要包括: • 构造方法 • 提供一个特定矩形的数值信息(如定点,边,面,颜色等) • 实现一个方法draw(GL10 gl)供OpenGLRenderer调用
使用OpenGL ES绘制3D图形 一个简单的Renderer——矩形 如图所示,一个简单的矩形包括了四个顶点(v0, v1, v2, v3),通过一个数组来记录: privatefloatvertices[] = { -1.0f, 1.0f, 0.0f, // v0 -1.0f, -1.0f, 0.0f, // v1 1.0f, -1.0f, 0.0f, // v2 1.0f, 1.0f, 0.0f, // v3 }; 注:三维坐标,z轴全为0
使用OpenGL ES绘制3D图形 一个简单的Renderer——矩形 将顶点组合成面 如图所示,OpenGL默认的是逆时针的连接顶点来形成一个面,为此建立一个顶点序列数组: privateshort[] indices = { 0, 1, 2, 0, 2, 3 };
使用OpenGL ES绘制3D图形 一个简单的Renderer——矩形 Square构造方法——public Square() 主要用途——为自身对象分配足够的缓存空间 • publicSquare() { • // 顶点为浮点型,占用4个字节,所以乘以4 • ByteBuffervbb = ByteBuffer.allocateDirect(vertices.length * 4); • vbb.order(ByteOrder.nativeOrder()); • vertexBuffer = vbb.asFloatBuffer(); • vertexBuffer.put(vertices); • vertexBuffer.position(0); • // 序列用短整型保存,短整型占用2个字节,所以乘以2 • ByteBufferibb = ByteBuffer.allocateDirect(indices.length * 2); • ibb.order(ByteOrder.nativeOrder()); • indexBuffer = ibb.asShortBuffer(); • indexBuffer.put(indices); • indexBuffer.position(0); • }
使用OpenGL ES绘制3D图形 一个简单的Renderer——矩形 Square的draw(GL10 gl)方法——绘制矩形 publicvoiddraw(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); // 逆时针方向. gl.glEnable(GL10.GL_CULL_FACE); // 使能面淘汰机制. gl.glCullFace(GL10.GL_BACK); // 定制面淘汰机制 // 使能顶点缓存 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // 指定顶点缓存的位置以及顶点坐标数据的类型 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); // 指定序列缓存的位置以及序列数据的类型 gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer); // 清除顶点缓存 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // 停止面淘汰机制 gl.glDisable(GL10.GL_CULL_FACE); }
使用OpenGL ES绘制3D图形 一个简单的Renderer——矩形 • 完成了Square类,就可以在OpenGLRenderer中使用它了 • OpenGLRenderer主要包括如下一些方法: • 构造方法 • 三个实现Renderer接口的方法 本例中,构造方法很简单,如下: publicOpenGLRenderer() { // 初始化待绘制的矩形对象. square = new Square(); }
使用OpenGL ES绘制3D图形 一个简单的Renderer——矩形 OpenGLRenderer. onSurfaceCreated(GL10 gl, EGLConfigconfig): publicvoidonSurfaceCreated(GL10 gl, EGLConfigconfig) { // 设置背景颜色为黑色 gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 使能平滑阴影效果. gl.glShadeModel(GL10.GL_SMOOTH); // 设置深度缓存. gl.glClearDepthf(1.0f); // 使能深度测试. gl.glEnable(GL10.GL_DEPTH_TEST); // 设置深度测试的方式. gl.glDepthFunc(GL10.GL_LEQUAL); // 设置成最好的显示效果. gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); }
使用OpenGL ES绘制3D图形 一个简单的Renderer——矩形 OpenGLRenderer. onDrawFrame(GL10 gl) : publicvoidonDrawFrame(GL10 gl) { // 清屏并且清除深度缓存. gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 重新载入绘图矩阵 gl.glLoadIdentity(); // 使用向量(0,0,-5)平移图像,使绘制结果便于观察 gl.glTranslatef(0, 0, - 5); // 绘制矩形. square.draw(gl); } OpenGLRenderer. onSurfaceChanged(GL10 gl, int width, int height):
使用OpenGL ES绘制3D图形 一个简单的Renderer——矩形 OpenGLRenderer实现后,只需要在主Activity里面使用: GLSurfaceView view = newGLSurfaceView(this); view.setRenderer(newOpenGLRenderer()); setContentView(view); 将GLSurfaceView的Renderer设置为OpenGLRenderer即可实现Square的绘制了。
使用OpenGL ES绘制3D图形 延伸——对矩形进行平移、旋转和缩放 在OpenGL中要实现动态的图形效果,通常需要对图形模型进行平移,旋转和缩放等操作。这三个操作涉及如下三个方法: • glTranslatef(float x, float y, float z)——以向量(x,y,z)平移 • glRotatef(float angle, float x, float y, float z)——围绕向量(x,y,z)逆时针方向旋转angle度 • glScalef(float x, float y, float z)——分别将图形在对应坐标维度缩放x,y,z倍 这些方法主要用在Renderer的onDrawFrame()中,在每帧进行绘制时做对应的变换调整,达到动态的效果。
使用OpenGL ES绘制3D图形 延伸——对矩形进行平移、旋转和缩放 例如,在onDrawFrame()添加如下语句,可以实现矩形循环缩放的效果,截图见下页(move为整形全局变量,flag为全局布尔变量): if(flag) { move--; } if(!flag) { move++; } gl.glScalef(0.01f * move, 0.01f * move, 0.01f * move); if(move == 0){ flag = false; } if(move == 100) { flag = true; }
使用OpenGL ES绘制3D图形 Android OpenGL示例——TestOpenGL_ES
使用OpenGL ES绘制3D图形 附——Android OpenGL 3D实例代码 可触摸旋转控制的3D立方体(项目名称TestOpenGL_ES II) 注:TestOpenGL_ESI是不可旋转的版本