用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字
云代码 - android代码库

3D图形编程 GLSurfaceView demo

2013-04-13 作者: 小蜜锋举报

[android]代码库

package com.bn.Sample11_1;

import static com.bn.Sample11_1.Sample11_1Activity.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.view.MotionEvent;

public class MySurfaceView extends GLSurfaceView {
	static final float UNIT_SIZE = 1f;
	static float direction = 0;// 视线方向
	static float cx = 0;// 摄像机x坐标
	static float cz = 15;// 摄像机z坐标
	static final float DEGREE_SPAN = (float) (3.0 / 180.0f * Math.PI);// 摄像机每次转动的角度
	// 线程循环的标志位
	boolean flag = true;
	float x;
	float y;
	float Offset = 15;
	SceneRenderer mRender;
	float preX;
	float preY;

	public MySurfaceView(Context context) {
		super(context);
		this.setEGLContextClientVersion(2); // 设置使用OPENGL ES2.0
		mRender = new SceneRenderer(); // 创建场景渲染器
		setRenderer(mRender); // 设置渲染器
		setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);// 设置渲染模式为主动渲染
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		x = event.getX();
		y = event.getY();
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			flag = true;
			new Thread() {
				@Override
				public void run() {
					while (flag) {
						if (x > 0 && x < WIDTH / 2 && y > 0 && y < HEIGHT / 2) {// 向前
							Offset = Offset - 0.5f;
						} else if (x > WIDTH / 2 && x < WIDTH && y > 0
								&& y < HEIGHT / 2) {// 向后
							Offset = Offset + 0.5f;
						} else if (x > 0 && x < WIDTH / 2 && y > HEIGHT / 2
								&& y < HEIGHT) {
							direction = direction + DEGREE_SPAN;
						} else if (x > WIDTH / 2 && x < WIDTH && y > HEIGHT / 2
								&& y < HEIGHT) {
							direction = direction - DEGREE_SPAN;
						}
						try {
							Thread.sleep(100);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}.start();
			break;
		case MotionEvent.ACTION_UP:
			flag = false;
			break;
		}
		// 设置新的观察目标点XZ坐标
		cx = (float) (Math.sin(direction) * Offset);// 观察目标点x坐标
		cz = (float) (Math.cos(direction) * Offset);// 观察目标点z坐标

		// 计算所有树的朝向
		mRender.tg.calculateBillboardDirection();

		// 给树按照离视点的距离排序
		Collections.sort(mRender.tg.alist);
		// 设置新的摄像机位置
		MatrixState.setCamera(cx, 0, cz, 0, 0, 0, 0, 1, 0);
		return true;
	}

	private class SceneRenderer implements GLSurfaceView.Renderer {
		TreeGroup tg;
		Desert desert;
		int treeId;
		int desertId;

		public void onDrawFrame(GL10 gl) {
			// 清除深度缓冲与颜色缓冲
			GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT
					| GLES20.GL_COLOR_BUFFER_BIT);

			MatrixState.pushMatrix();
			MatrixState.translate(0, -2, 0);
			desert.drawSelf(desertId);
			MatrixState.popMatrix();

			// 开启混合
			GLES20.glEnable(GLES20.GL_BLEND);
			// 设置混合因子
			GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA,
					GLES20.GL_ONE_MINUS_SRC_ALPHA);
			MatrixState.pushMatrix();
			MatrixState.translate(0, -2, 0);
			tg.drawSelf(treeId);
			MatrixState.popMatrix();
			// 关闭混合
			GLES20.glDisable(GLES20.GL_BLEND);
		}

		public void onSurfaceChanged(GL10 gl, int width, int height) {
			// 设置视窗大小及位置
			GLES20.glViewport(0, 0, width, height);
			// 计算GLSurfaceView的宽高比
			float ratio = (float) width / height;
			// 调用此方法计算产生透视投影矩阵
			MatrixState.setProjectFrustum(-ratio, ratio, -1, 1, 1, 100);
			// 调用此方法产生摄像机9参数位置矩阵
			MatrixState.setCamera(cx, 0, cz, 0, 0, 0, 0f, 1.0f, 0.0f);
		}

		public void onSurfaceCreated(GL10 gl, EGLConfig config) {
			// 设置屏幕背景色RGBA
			GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
			// 打开深度检测
			GLES20.glEnable(GLES20.GL_DEPTH_TEST);
			MatrixState.setInitStack();

			tg = new TreeGroup(MySurfaceView.this);
			// 初始化树顺序
			Collections.sort(mRender.tg.alist);
			desert = new Desert(MySurfaceView.this, new float[] { 0, 0, 0, 6,
					6, 6, 6, 6, 6, 0, 0, 0 }, 30, 20);
			// 初始化纹理
			treeId = initTexture(R.drawable.tree);
			desertId = initTexture(R.drawable.desert);
		}
	}

	// 生成纹理的id
	public int initTexture(int drawableId) {
		// 生成纹理ID
		int[] textures = new int[1];
		GLES20.glGenTextures(1, // 产生的纹理id的数量
				textures, // 纹理id的数组
				0 // 偏移量
		);
		int textureId = textures[0];
		GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
				GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
				GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
				GLES20.GL_REPEAT);
		GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
				GLES20.GL_REPEAT);

		// 通过输入流加载图片
		InputStream is = this.getResources().openRawResource(drawableId);
		Bitmap bitmapTmp;
		try {
			bitmapTmp = BitmapFactory.decodeStream(is);
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		// 实际加载纹理
		GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, // 纹理类型,在OpenGL
													// ES中必须为GL10.GL_TEXTURE_2D
				0, // 纹理的层次,0表示基本图像层,可以理解为直接贴图
				bitmapTmp, // 纹理图像
				0 // 纹理边框尺寸
		);
		bitmapTmp.recycle(); // 纹理加载成功后释放图片
		return textureId;
	}
}

[代码运行效果截图]


3D图形编程 GLSurfaceView  demo

[源代码打包下载]




网友评论    (发表评论)

共67 条评论 1/3页  1  2   3  >

发表评论:

评论须知:

  • 1、评论每次加2分,每天上限为30;
  • 2、请文明用语,共同创建干净的技术交流环境;
  • 3、若被发现提交非法信息,评论将会被删除,并且给予扣分处理,严重者给予封号处理;
  • 4、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。


扫码下载

加载中,请稍后...

输入口令后可复制整站源码

加载中,请稍后...