1. 程式人生 > >Android OpenGL三——旋轉和觸控事件

Android OpenGL三——旋轉和觸控事件

OpenGL中新增Motion

在螢幕上繪製物件,是OpenGL比較基本的特性。如果你只想做這些,你完全可以使用包括Canvas和Drawable類的Android的圖形框架。

OpenGL ES為三維空間中的物件繪製,擴充套件了移動、變換等引人入勝的使用者體驗。

In this lesson, you take another step forward into using OpenGL ES by learning how to add motion to a shape with rotation

對圖形做旋轉操作

對繪製的物件做旋轉操作相當簡單。在你的渲染器中,另外建立一個關於旋轉的轉換矩陣,然後和你的投影和相機轉換檢視矩陣連結起來(有關投影和相機檢視,請檢視

上一篇文章)。

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);

    // 將旋轉矩陣和投影、相機檢視連結到一起
// 為了矩陣乘積的正確性,必須將*mMVPMatrix*放在首位 Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); // 繪製三角形 mTriangle.draw(scratch); }

添加了上述程式碼後,如果你的三角形還不能旋轉,請確認你是否添加了 GLSurfaceView.RENDERMODE_WHEN_DIRTY設定。

啟用連續繪製

如果你嚴格按照該系列部落格編寫程式碼,確保你已經註釋掉將渲染模式設定為只要當圖形改變時才繪製的程式碼,否則圖形的旋轉只用在requestRender()

才會生效。如下:

public MyGLSurfaceView(Context context) {
    ...
    // 只要當繪製資料發生變化時才繪製檢視
    //為了使三角形能夠自動旋轉,註釋掉這句
    //setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}

這個繪製模式的設定,如非必要,請儘量開啟。

響應觸控事件

想要讓你設計的OpenGL ES圖形和使用者做互動。只需要繼承GLSurfaceView的類重寫GLSurfaceViewonTouchEvent()方法,用於監聽觸控事件。

設定觸控監聽

private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
private float mPreviousX;
private float mPreviousY;

@Override
public boolean onTouchEvent(MotionEvent e) {
    // 觸控事件用各種輸入裝置傳遞,現在流行的觸控屏就是典型的觸控事件輸入裝置。

    float x = e.getX();
    float y = e.getY();

    switch (e.getAction()) {//監聽Move事件
        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;
}

再次提醒,如果發現無效的話,請檢查如下程式碼是否取消註釋。

public MyGLSurfaceView(Context context) {
    ...
    // 繪製資料發生變化時,才繪製檢視
    setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}

暴露旋轉角

上面的例項程式碼的正常執行,需要將旋轉角通過公共的方法在渲染器中暴露出來。因為,渲染器程式碼試執行在主執行緒以外的執行緒中的,所以,變數需要加上volatile申明。下面是例項程式碼:

public class MyGLRenderer implements GLSurfaceView.Renderer {
    ...

    public volatile float mAngle;

    public float getAngle() {
        return mAngle;
    }

    public void setAngle(float angle) {
        mAngle = angle;
    }
}

應用

為了使用通過觸控輸入的轉角,現將生成angle和mAngle的程式碼註釋掉,因為它們包含觸控生成角度的程式碼。

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, mAngle, 0, 0, -1.0f);

    // 將旋轉矩陣和投影、相機檢視連結到一起
    // 為了矩陣乘積的正確性,必須將*mMVPMatrix*放在首位
    Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);

    // Draw triangle
    mTriangle.draw(scratch);
}

效果圖

這裡寫圖片描述