OpenGL ES2.0入门之Android篇(二)——添加动作及触摸事件

来源:互联网 发布:淘宝设置发货地址 编辑:程序博客网 时间:2024/06/08 02:54

上篇文章中介绍了如何使用OpenGL ES2.0绘制三角形,本章将在上篇的基础上进行讲解,另附链接 OpenGL ES2.0入门之Android篇(一)——绘制三角形)

定义投影和相机视图

  • 在OpenGL ES环境中,投影和相机视图让绘制对象以更接近于人们肉眼所看到的实物对象的样子显示
  • 投影: 前文讲过,Android和OpenGL ES的坐标系不一样,如果没有投影的话,绘制的图像将会被拉伸变形,并且旋转屏幕图像显示的比例也不一样
  • 相机视图: 这种变换是基于一个虚拟相机的位置来调整绘制对象的坐标
  • 如果只定义了投影,通常会导致什么也看不到,所以需要结合相机视图才能看到屏幕上的绘图

1. 在GLSurfaceView.Renderer类中定义一个投影

// mMVPMatrix是"Model View Projection Matrix"的缩写private final float[] mMVPMatrix = new float[16];private final float[] mProjectionMatrix = new float[16];//定义投影矩阵变量private final float[] mViewMatrix = new float[16];//定义相机视图矩阵变量@Overridepublic void onSurfaceChanged(GL10 unused, int width, int height) {    GLES20.glViewport(0, 0, width, height);    float ratio = (float) width / height;//GLSurfaceView的宽高比    // 根据六个面定义投影矩阵  frustumM(float[] m, int offset, float left, float right, float bottom, float top, float near, float far)    Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);}

投影矩阵在onDrawFrame()方法中使用

Matrix.frustumM请参考Matrix源码

2. 在onDrawFrame()方法中定义相机视图

@Overridepublic void onDrawFrame(GL10 unused) {    ...    // 设置相机的位置(视图矩阵)    Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);    // 将mProjectionMatrix和mViewMatrix矩阵相乘并赋给mMVPMatrix    Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);    // 绘制形状    mTriangle.draw(mMVPMatrix);}

3. 修改三角形类中的draw()方法

一、修改vertexShaderCode为

public class Triangle {private final String vertexShaderCode =    "uniform mat4 uMVPMatrix;" +    "attribute vec4 vPosition;" +    "void main() {" +    "  gl_Position = uMVPMatrix * vPosition;" +    "}";private int mMVPMatrixHandle;...

}

    public void draw(float[] mvpMatrix) { // 传递计算出的变换矩阵    ...    // 获得形状的变换矩阵的handle    mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");    // 把变换矩阵传给着色器    GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);    // 绘制三角形    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);    // 禁用指向三角形的顶点数组    GLES20.glDisableVertexAttribArray(mPositionHandle);}

此时运行应用程序,它能够按照正确的比例绘制图形,下一步就是添加动作

4. 旋转图形

在MyGlRenderer中添加旋转矩阵代码

private float[] mRotationMatrix = new float[16];public void onDrawFrame(GL10 gl) {    float[] scratch = new float[16];    ...    // 创建旋转矩阵    long time = SystemClock.uptimeMillis() % 4000L;    float angle = 0.090f * ((int) time);    Matrix.setRotateM(mRotationMatrix, 0, angle, 0, 0, -1.0f);    // 将旋转矩阵合并到投影和相机视图变换矩阵中    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);    // 绘制三角形    mTriangle.draw(scratch);}

启用持续渲染

public MyGLSurfaceView(Context context) {...// 将下面的代码注释掉//setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

}

此时运行应用程序,可以观察到图形会一直旋转,下面将展示如何监听用户的触摸事件,让用户旋转一个OpenGL ES对象

5. 在MyGLSurfaceView中设置触摸监听器

1.覆写onTouchEvent()方法

private final float TOUCH_SCALE_FACTOR = 180.0f / 320;private float mPreviousX;private float mPreviousY;@Overridepublic boolean onTouchEvent(MotionEvent e) {    // 这是Android中的基础知识,这里就不讲解了    float x = e.getX();    float y = e.getY();    switch (e.getAction()) {        case MotionEvent.ACTION_MOVE:            float dx = x - mPreviousX;            float dy = y - mPreviousY;            // 反向旋转至中线以上            if (y > getHeight() / 2) {              dx = dx * -1 ;            }            // 反向旋转至中线左面            if (x < getWidth() / 2) {              dy = dy * -1 ;            }            mRenderer.setAngle(                    mRenderer.getAngle() +                    ((dx + dy) * TOUCH_SCALE_FACTOR));            requestRender();//请求渲染    }    mPreviousX = x;    mPreviousY = y;    return true;}

2.将setRenderMode的注释去掉

public MyGLSurfaceView(Context context) {    ...    // 只有在绘制数据改变时才绘制view    setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);}

3.在MyGlRenderer中将旋转角度暴露出去

public class MyGLRenderer implements GLSurfaceView.Renderer {    ...    public volatile float mAngle;    public float getAngle() {        return mAngle;    }    public void setAngle(float angle) {        mAngle = angle;    }}

4.在onDrawFrame()方法中调用旋转角度

public void onDrawFrame(GL10 gl) {    ...    float[] scratch = new float[16];    // 注释掉生成旋转角度的代码    // long time = SystemClock.uptimeMillis() % 4000L;    // float angle = 0.090f * ((int) time);    // 添加mAngle    Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);    // 合并旋转矩阵到投影和相机视图矩阵    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);    // 绘制三角形    mTriangle.draw(scratch);}

此时运行程序,在屏幕上划动旋转三角形,显示如下图所示:

示例源码:点击下载源码

1 0