OpenglES2.0 for Android:各種變換來一波

來源:互聯網
上載者:User

標籤:

OpenglES2.0 for Android:各種變換來一波監聽螢幕事件在進行各種變換之前,我們先來瞭解一下如何監聽螢幕的事件。我們下面的變換都需要用立方體來示範,所以我們繼續使用上一節的繪製立方體的內容首先建立一個項目 OpengESChange ,將上一節中關於繪製立方體的代碼複製過來 。在前面我們一直在使用android.opengl.GLSurfaceView在第一篇中我們已經知道了這個類的作用,為了監聽螢幕事件,我們建立一個類繼承自該類,重寫其onTouchEvent方法。此時該類 代碼如下 : (MySurfaceView.java  ):
package com.cumt.opengeschange;import com.cumt.render.MyRender;import android.content.Context;import android.opengl.GLSurfaceView;import android.view.MotionEvent;public class MySurfaceView extends GLSurfaceView {private MyRender myRender;public MySurfaceView(Context context) {super(context);// TODO Auto-generated constructor stubmyRender = new MyRender(context);this.setEGLContextClientVersion(2);this.setRenderer(myRender);// 設定渲染模式為主動渲染this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubreturn super.onTouchEvent(event);}}

在onTouchEvent方法中我們就可以檢測到各種事件了   我們也可以使用GLSurfaceView的setOnTouchListener來監聽視圖的觸控事件 ,代碼如下(MySurfaceView.java  ):
package com.cumt.opengeschange;import com.cumt.render.MyRender;import android.content.Context;import android.opengl.GLSurfaceView;import android.view.MotionEvent;import android.view.View;public class MySurfaceView extends GLSurfaceView {private MyRender myRender;public MySurfaceView(Context context) {super(context);// TODO Auto-generated constructor stubmyRender = new MyRender(context);this.setEGLContextClientVersion(2);this.setRenderer(myRender);// 設定渲染模式為主動渲染this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);this.setOnTouchListener(new OnTouchListener() {public boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubreturn false;}});}}


此時MainActivity也有稍微的改動 (MainActivity.java ):
package com.cumt.opengeschange;import android.app.Activity;import android.content.pm.ActivityInfo;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;public class MainActivity extends Activity {private MySurfaceView glSurfaceView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 設定為全屏requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);// 設定為橫屏模式setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);glSurfaceView = new MySurfaceView(this);setContentView(glSurfaceView);}@Overrideprotected void onPause() {// TODO Auto-generated method stubsuper.onPause();glSurfaceView.onPause();}@Overrideprotected void onResume() {// TODO Auto-generated method stubsuper.onResume();glSurfaceView.onResume();}}


此時我們的前期工作已經OK 了 

平移變換先來看下平移變換矩陣 :
矩陣中的三個參數分別表示沿X ,Y,Z軸方向的位移

平移矩陣M 乘 當前P點的向量,即可得到平移後的P ‘  點的向量 。
現在我們想要在原來繪製立方體的基礎上實現這樣的功能 :手指在螢幕上向左或向右移動時,我們的立方體向左或向右移動一段距離 。首先我們需要修改MatrixState中的代碼 ,建立一個平移變換矩陣 並初始化為單位矩陣,然後建立一個方法共外部調用以設定平移,最後修改我們原先的getFinalMatrix方法,在該方法中乘上該平移矩陣。過程如下代碼所示 (MatrixState.java ):

package com.cumt.utils;import android.opengl.Matrix;//儲存系統矩陣狀態的類public class MatrixState {private static float[] mProjMatrix = new float[16];// 4x4矩陣 儲存投影矩陣private static float[] mVMatrix = new float[16];// 攝像機位置朝向9參數矩陣/* * 第一步 :建立平移變換矩陣 */private static float[] mtMatrix = new float[16];// 平移變換矩陣/* * 第二步: 初始化為單位矩陣 */static{//初始化為單位矩陣Matrix.setIdentityM(mtMatrix, 0);}/* * 第三步 : 平移變換方法共外部使用 */public static void translate(float x,float y,float z)//設定沿xyz軸移動    {    Matrix.translateM(mtMatrix, 0, x, y, z);    }// 設定攝像機public static void setCamera(float cx, // 攝像機位置xfloat cy, // 攝像機位置yfloat cz, // 攝像機位置zfloat tx, // 攝像機目標點xfloat ty, // 攝像機目標點yfloat tz, // 攝像機目標點zfloat upx, // 攝像機UP向量X分量float upy, // 攝像機UP向量Y分量float upz // 攝像機UP向量Z分量) {Matrix.setLookAtM(mVMatrix, 0, cx, cy, cz, tx, ty, tz, upx, upy, upz);}// 設定透視投影參數public static void setProjectFrustum(float left, // near面的leftfloat right, // near面的rightfloat bottom, // near面的bottomfloat top, // near面的topfloat near, // near面距離float far // far面距離) {Matrix.frustumM(mProjMatrix, 0, left, right, bottom, top, near, far);}// 擷取具體物體的總變換矩陣static float[] mMVPMatrix = new float[16];public static float[] getFinalMatrix() {/* * 第四步  : 乘以平移變換矩陣 */Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mtMatrix, 0);Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);return mMVPMatrix;}}

這裡我們使用靜態程式碼片段初始化平移矩陣為單位矩陣,如果使用者沒有設定平移變換矩陣,也不會影響原圖形。
然後我們在MySurfaceView中監聽使用者的螢幕移動事件 ,代碼如下 (MySurfaceView.java):
package com.cumt.opengeschange;import com.cumt.render.MyRender;import com.cumt.utils.MatrixState;import android.content.Context;import android.opengl.GLSurfaceView;import android.view.MotionEvent;import android.view.View;public class MySurfaceView extends GLSurfaceView {private MyRender myRender;private float mPreviousX;//上次的觸控位置X座標public MySurfaceView(Context context) {super(context);// TODO Auto-generated constructor stubmyRender = new MyRender(context);this.setEGLContextClientVersion(2);this.setRenderer(myRender);// 設定渲染模式為主動渲染this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);this.setOnTouchListener(new OnTouchListener() {public boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubfloat x = event.getX();//當前的觸控位置X座標switch (event.getAction()) {case MotionEvent.ACTION_MOVE://檢測到移動事件時float dx = x - mPreviousX;if(dx > 0){MatrixState.translate(0.1f, 0, 0);}else{MatrixState.translate(-0.1f, 0, 0);}}mPreviousX=x;return true;}});}}

來看下運行效果 :

旋轉變換看下旋轉矩陣 :


表示將點 P 繞向量 U 旋轉 θ 度 。在OpenGL中我們使用void android.opengl.Matrix.rotateM(float[] m,int mOffset,float a,float x, float y, float z)方法來設定旋轉 ,第一個參數表示返回的旋轉矩陣,mOffset表示位移量,一般設定為0 ,a 表示角度 ,x y z表示旋轉軸對應向量的X,Y,Z分量
下面我們來實現這樣一個功能 : 每點擊螢幕一次,讓我們的立方體沿著其 Y 軸旋轉30度 
首先在我們原來的 MatrixState類中新增一個方法來設定旋轉 ,新增代碼如下 :
//旋轉變換public static void rotate(float angle, float x, float y, float z) {// 設定繞xyz軸移動Matrix.rotateM(mtMatrix, 0, angle, x, y, z);}

然後就在MySurfaceView類中設定監聽事件和旋轉 ,此時MySurfaceView.java代碼如下 :
package com.cumt.opengeschange;import com.cumt.render.MyRender;import com.cumt.utils.MatrixState;import android.content.Context;import android.opengl.GLSurfaceView;import android.view.MotionEvent;import android.view.View;public class MySurfaceView extends GLSurfaceView {private MyRender myRender;public MySurfaceView(Context context) {super(context);// TODO Auto-generated constructor stubmyRender = new MyRender(context);this.setEGLContextClientVersion(2);this.setRenderer(myRender);// 設定渲染模式為主動渲染this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);this.setOnTouchListener(new OnTouchListener() {public boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubswitch (event.getAction()) {case MotionEvent.ACTION_DOWN://檢測到點擊事件時MatrixState.rotate(30, 0, 1, 0);}return true;}});}}

我們運行看下效果:

縮放變換縮放矩陣 :

上面矩陣中三個參數分別表示縮放變換中的沿X,Y,Z軸方向的縮放率。
我們來實現下面的效果:點擊螢幕後進行一定比例的縮放操作 首先在MatrixState.java中加入如下代碼 :
//縮放變換public static void scale(float x,float y,float z)    {    Matrix.scaleM(mtMatrix,0, x, y, z);    }

然後就在MySurfaceView類中設定監聽事件和縮放 ,此時MySurfaceView.java代碼如下 :

package com.cumt.opengeschange;import com.cumt.render.MyRender;import com.cumt.utils.MatrixState;import android.content.Context;import android.opengl.GLSurfaceView;import android.view.MotionEvent;import android.view.View;public class MySurfaceView extends GLSurfaceView {private MyRender myRender;public MySurfaceView(Context context) {super(context);// TODO Auto-generated constructor stubmyRender = new MyRender(context);this.setEGLContextClientVersion(2);this.setRenderer(myRender);// 設定渲染模式為主動渲染this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);this.setOnTouchListener(new OnTouchListener() {public boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubswitch (event.getAction()) {case MotionEvent.ACTION_DOWN://檢測到點擊事件時MatrixState.scale(0.4f, 1.5f, 0.6f);//xyz三個方向按各自的縮放因子進行縮放}return true;}});}}


運行效果:


最後祝大家端午節快樂~~

OpenglES2.0 for Android:各種變換來一波

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.