用户注册



邮箱:

密码:

用户登录


邮箱:

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

发表随想


还能输入: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、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。


扫码下载

加载中,请稍后...

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

加载中,请稍后...