您的位置:首页 > 移动开发 > Android开发

Android OpenGL例子学习

2016-12-08 17:29 357 查看
例子见附件.AndroidManifest.xml 
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="anson.code.openGLDemo1"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".OGDActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>

</manifest>
 OGDActivity.java 
package anson.code.openGLDemo1;

import android.app.Activity;
import android.os.Bundle;

public class OGDActivity extends Activity {
/** Called when the activity is first created. */
VortexView vortexView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
vortexView = new VortexView(this);
setContentView(vortexView);
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
vortexView.onPause();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
vortexView.onResume();
}

}
 VortexView.java 
package anson.code.openGLDemo1;

import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.view.MotionEvent;

public class VortexView extends GLSurfaceView {

private VortexRenderer renderer;
public VortexView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public VortexView(Context context) {
super(context);
// TODO Auto-generated constructor stub
renderer = new VortexRenderer();
setRenderer(renderer);
}
@Override
public boolean onTouchEvent(final MotionEvent event) {
// TODO Auto-generated method stub
queueEvent(new Runnable(){

@Override
public void run() {
// TODO Auto-generated method stub
renderer.setColor(event.getX()/getWidth(), event.getY() /getHeight(), 1.0f);
renderer.setAngle(event.getX()/10);
}

});

return super.onTouchEvent(event);
}

}
VortexRenderer.java
package anson.code.openGLDemo1;

/**
* 程序开始      :onSurfaceCreated  -->  onSurfaceChanged  --> onDrawFrame  --> onDrawFrame  --> onDrawFrame -->
* 程序后台唤醒:onSurfaceChanged  --> onDrawFrame  --> onSurfaceChanged   --> onDrawFrame  --> onDrawFrame -->
*
* 1) onDrawFrame() 方法会在每帧中被调用,用于描述一个时时绘制的场景,你还可以通过调用 glclear 方法去清空帧缓冲,接着通过其他OpenGl ES 调用去绘制目前的场景。
* 2) onSurfaceChanged() 方法在surface 大小尺寸改变的时候被调用,它主要设置你的openGL的观察点,你也可以在这里设置一个不会被移动到固定Camera
* 3) onSurfaceCreated() 方法被调用在开始渲染的时候,OpenGL ES 绘图上下文时都会被重建(当activity暂停和恢复的时候,绘图的上下文也随着丢失和重建.
*/

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView.Renderer;

publi
4000
c class VortexRenderer implements Renderer {
private float red = 0f;
private float green = 0f;
private float blue = 0f;

private ShortBuffer indexBuffer;
private FloatBuffer vertexBuffer;
private short[] indicesArray = {0, 1, 2};
private int numberOfVertices = 3;

private float angle;

private void initTriangle(){
/**
* allocate和allocateDirect方法都做了相同的工作,
* 不同的是allocateDirect方法 "直接"使用操作系统来分配Buffer.
* 因而它将提供更快的访问速度。不幸的是,并非所有的虚拟机都支持这种直接分配的方法.
* Sun推荐将以字节为单位的直接型缓冲区allocateDirect用于与大型文件相关并具有较长生命周期的缓冲区.
*/
ByteBuffer vbb = ByteBuffer.allocateDirect(numberOfVertices *3 *4);//36;

// ByteOrder nativeOrder() 返回当前硬件平台的字节序.
vbb.order(ByteOrder.nativeOrder());//返回ByteOrder的字节序, 并赋给ByteBuffer.

/** 为当前的ByteBuffer创建一个CharBuffer的视图。
* 在该视图buffer中的读写操作会按照ByteBuffer的字节序作用到ByteBuffer中的数据上
*/
vertexBuffer = vbb.asFloatBuffer();

ByteBuffer ibb = ByteBuffer.allocateDirect(numberOfVertices *2);
ibb.order(ByteOrder.nativeOrder());
indexBuffer = ibb.asShortBuffer();

/**
* coords分别定义了三个顶点的座,
* 对应为: X, Y, Z
* 这里需要注意的是:
* 相对于屏幕中, 原点既是在屏幕中的中点(取X/2, Y/2)
* 原点: 0, 0, 0
* 其中, Z轴需要以设置场景的深度为准.
* 各个座标取值[0, 1]的浮点值.
*/
float[] coords = {-0.5f, -0.5f, 0f,
0.5f, -0.5f, 0f,
0f, 0.5f, 0.1f};

vertexBuffer.put(coords);// 写入顶点座标到vertexBuffer, 以便下面显示场景.
indexBuffer.put(indicesArray);
vertexBuffer.position(0);//设置当前的读取起始位置.
indexBuffer.position(0);
}

public void setColor(float red, float green, float blue){
this.red = red;
this.green = green;
this.blue = blue;
}

public void setAngle(float an){
this.angle = an;
}

@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
/**
* RGB + A
* 绝大多数人都认为Alpha分量代表材料的透明度。这就是说,alpha值为0.0时所代表的材料是完全透明的。alpha值为1.0时所代表的材料则是完全不透明的。
* 红,绿,蓝和AFA值是在颜色缓冲区被清除之后使用的,并且缺省值全是0.即(0,0,0,0),其实就是设置颜色
*/
gl.glClearColor(red, green, blue, 0.0f);

gl.glClear(GL10.GL_COLOR_BUFFER_BIT);//表示把整个窗口清除为当前的清除颜色,glClear()的唯一参数表示需要被清除的缓冲区。

/**
* 定义旋转轴
* glRotatef(速度, X, Y, Z);
*/
gl.glRotatef(angle, 0f, 0f, 1f);
gl.glColor4f(0.5f, 0f, 0f, 0.5f);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, numberOfVertices, GL10.GL_UNSIGNED_SHORT, indexBuffer);
}

@Override
public void onSurfaceChanged(GL10 gl, int w, int h) {
// TODO Auto-generated method stub
gl.glViewport(0, 0, w, h);
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig cf) {
// TODO Auto-generated method stub
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
initTriangle();
}

} 
  添加画圆圈:  
package anson.code.openGLDemo1;import java.nio.FloatBuffer;import javax.microedition.khronos.egl.EGLConfig;import javax.microedition.khronos.opengles.GL10;import android.opengl.GLSurfaceView.Renderer;public class CRenderer implements Renderer {float rotateAngle;float rotateY;float r = 0.5f;//顶点数组,GL ES只能用这个办法画圆吗?private float[] vertices = new float[720];//度到弧度的转换public float DegToRad(float deg){//360 = 2PIfloat Pi = 3.14159265358979323846f;float Du = 360;float v = deg * (2*Pi) / Du;return v;}public void setAnX(float angle){rotateAngle -= angle;}public void setAnY(float ay){rotateY += ay;}public void onDrawFrame(GL10 gl) {// TODO Auto-generated method stub// 进入这个函数第一件要做的事就是清除屏幕和深度缓存gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);//画圆形drawCircle(gl);}public void drawCircle(GL10 gl){//重置投影矩阵gl.glLoadIdentity();// 移动操作,移入屏幕(Z轴)5个像素, x, y , zgl.glTranslatef(0.0f, 0.0f, -1.5f);//旋转, angle, x, y , zgl.glRotatef(rotateAngle, 1.0f, 0f, 0f);gl.glRotatef(rotateY, 0f, 1f, 0f);// 设置当前色为红色, R, G, B, Alphagl.glColor4f(1.0f, 0.1f, 0.1f, 1.0f);//设置圆形顶点数据,这个是在创建时生成FloatBuffer verBuffer = FloatBuffer.wrap(vertices);//设置顶点类型为浮点坐标(GL_FLOAT),不设置或者设置错误类型将导致图形不能显示或者显示错误gl.glVertexPointer(2, GL10.GL_FLOAT, 0, verBuffer);//打开顶点数组gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);//向OGL发送实际画图指令/*** GL_TRIANGLE_FAN* GL_LINES* GL_LINES_LOOP*/gl.glDrawArrays(GL10.GL_LINES, 0, 360);//关闭顶点数组功能gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);//画图结束gl.glFinish();//更改旋转角度//rotateAngle += 0.5;}public void onSurfaceChanged(GL10 gl, int width, int height) {// TODO Auto-generated method stubfloat ratio = (float) width / height;//设置OpenGL场景的大小gl.glViewport(0, 0, width, height);//设置投影矩阵,既告诉OPENGL 如何把三维矩阵换为二维显示到界面上.gl.glMatrixMode(GL10.GL_PROJECTION);//重置投影矩阵,初始化.gl.glLoadIdentity();// 设置视口的大小/*** glFrustumf(float left, float right, float bottom, float top, float zNear, float zFar)* 设置了显示视口的大小,也就是说,一个可视范围.* 把三维的东西用二维显示出来, 需要知道可以平面有多大 和 能看多近和多远.* 前面四个参数指定视口平面的大小, 后两个参数分别是可以看到的最近和最远.*///gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);gl.glFrustumf(-ratio, ratio, 1f, -1f, 1f, 25);// 选择模型观察矩阵gl.glMatrixMode(GL10.GL_MODELVIEW);// 重置模型观察矩阵gl.glLoadIdentity();}public void onSurfaceCreated(GL10 gl, EGLConfig config) {// TODO Auto-generated method stub// 启用阴影平滑/** glShadeModel函数用于控制opengl中绘制指定两点间其他点颜色的过渡模式。* 参数一般为GL_SMOOTH(默认),GL_FLAT。OpenGL默认是将制定的两点颜色进行插值,绘制之间的其他点。* 如果两点的颜色相同,使用两个参数效果相同。* 如果两点颜色不同,GL_SMOOTH会出现过渡效果,GL_FLAT 则只是以指定的某一点的单一色绘制其他所有点。*/gl.glShadeModel(GL10.GL_SMOOTH);// 黑色背景gl.glClearColor(0, 0, 0, 0);// 设置深度缓存gl.glClearDepthf(1.0f);// 启用深度测试/*** 在三维空间里一个物体A,在另一个物体B后面,为了不让档住的部分不显示,* 需要告诉OpenGL把被档住的部分隐藏, glEnable(GL10.GL_DEPTH_TEST)就是实现这个功能.*/gl.glEnable(GL10.GL_DEPTH_TEST);/***  所作深度测试的类型* 这里我们比较常用的深度测试函数有 GL_LESS 和 GL_LEQUAL* 两者的区别在于当深度相同时是显示新的象素 还是老的象素。*/gl.glDepthFunc(GL10.GL_LEQUAL);// 告诉系统对透视进行修正/*** 在OpenGL中,许多细节的实现算法有所不同。* 这样,可以调用函数glHint()对图像质量和绘制速度之间的权衡作一些控制,但并非所有的实现都采用它。* 其函数形式为:void glHint(GLenum target,GLenum hint);* 控制OpenGL行为的某些方面。* 参数target说明控制什么行为* 参数hint可以是:GL_FASTEST(即给出最有效的选择)、GL_NICEST(即给出最高质量的选择)、GL_DONT_CARE(即没有选择)。*/gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);//初始化圆形数据for (int i = 0; i < 720; i += 2) {// x valueif(i%4 ==0)vertices[i]   = (float) (Math.cos(DegToRad(i)) * r);// y valueif(i%4 ==0)vertices[i+1] = -(float) (Math.sin(DegToRad(i)) * r);}}}
  要使圆圈运动起来: 
package anson.code.openGLDemo1;import android.content.Context;import android.opengl.GLSurfaceView;import android.util.AttributeSet;import android.view.MotionEvent;public class CView extends GLSurfaceView {CRenderer renderer;float oX = 0f;float oY = 0f;public CView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stub}public CView(Context context) {super(context, null);// TODO Auto-generated constructor stubrenderer = new CRenderer();setRenderer(renderer);}@Overridepublic boolean onTouchEvent(MotionEvent event) {//android.util.Log.d("AnsonLog", "TouchEvent:::::::::");// TODO Auto-generated method stubswitch(event.getAction()){case MotionEvent.ACTION_DOWN:oX = event.getRawX();oY = event.getRawY();break;case MotionEvent.ACTION_MOVE:float cX = event.getRawX();float cY = event.getRawY();float disX = cX - oX;float disY = cY - oY;oX = cX;oY = cY;renderer.setAnX(disY/4f);renderer.setAnY(disX/4f);break;case MotionEvent.ACTION_UP:oX = 0f;oY = 0f;break;}return true;}}
   http://hi.baidu.com/fairzy/blog/item/959200fcd1b60dfbfc037f9b.html这里的几篇文件不错.  OpenGLDemo1.zip (53.8 KB)下载次数: 188
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: