OpenGL完整實例


結合上一節的內容,分享完整代碼。

先畫一個cube,然后通過OnGestureListener去觸發onFling使它旋轉起來。

OnGestureListener相關的方法我已經都加了注釋,可以參考注釋去了解有關的方法是干什么的。

旋轉相關隨便復制了一個,主要說明OnGestureListener。

簡單的觸摸操作會用一些OnTouchListener復雜的還是需要用到OnGestureListener。

Acivity & Render:

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGLConfig;
import android.app.Activity;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.Window;

public class OpenGL extends Activity implements OnGestureListener {
    // 定義旋轉角度
    private float anglex = 0f;
    private float angley = 0f;
    static final float ROTATE_FACTOR = 180f;
    // 定義手勢檢測器實例
    GestureDetector detector;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 去標題欄
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        // 創建一個GLSurfaceView,用於顯示OpenGL繪制的圖形
        GLSurfaceView glView = new GLSurfaceView(this);
        // 創建GLSurfaceView的內容繪制器
        GLRenderer myRender = new GLRenderer(this);
        // 為GLSurfaceView設置繪制器
        glView.setRenderer(myRender);
        setContentView(glView);
        // 創建手勢檢測器
        detector = new GestureDetector(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 將該Activity上的觸碰事件交給GestureDetector處理
        return detector.onTouchEvent(event);
    }

    // 用戶輕觸觸摸屏,由1個MotionEvent ACTION_DOWN觸發
    public boolean onDown(MotionEvent e) {
        // TODO Auto-generated method stub
        System.out.println("onDown");
        return false;
    }

    /*
     * 用戶按下觸摸屏、快速移動后松開,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE,
     * 1個ACTION_UP觸發(non-Javadoc)
     * Fling事件的處理代碼:除了第一個觸發Fling的ACTION_DOWN和最后一個ACTION_MOVE中包含的坐標等信息外
     * ,我們還可以根據用戶在X軸或者Y軸上的移動速度作為條件
     * 比如下面的代碼中我們就在用戶移動超過100個像素,且X軸上每秒的移動速度大於200像素時才進行處理。
     * 
     * @see android.view.GestureDetector.OnGestureListener#onFling(android.view.
     * MotionEvent, android.view.MotionEvent, float, float)
     * 這個例子中,tv.setLongClickable( true )是必須的,因為
     * 只有這樣,view才能夠處理不同於Tap(輕觸)的hold(即ACTION_MOVE,或者多個ACTION_DOWN)
     * ,我們同樣可以通過layout定義中的android:longClickable來做到這一點
     */
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        System.out.println("onFling");
        // 參數解釋:
        // e1:第1個ACTION_DOWN MotionEvent
        // e2:最后一個ACTION_MOVE MotionEvent
        // velocityX:X軸上的移動速度,像素/秒
        // velocityY:Y軸上的移動速度,像素/秒
        velocityX = e1.getX() - e2.getX();
        velocityY = e1.getY() - e2.getY();
        velocityX = velocityX > 4000 ? 4000 : velocityX;
        velocityX = velocityX < -4000 ? -4000 : velocityX;
        velocityY = velocityY > 4000 ? 4000 : velocityY;
        velocityY = velocityY < -4000 ? -4000 : velocityY;
        // 根據橫向上的速度計算沿Y軸旋轉的角度
        angley += -velocityX * ROTATE_FACTOR / 4000;
        // 根據縱向上的速度計算沿X軸旋轉的角度
        anglex += -velocityY * ROTATE_FACTOR / 4000;
        return true;
    }

    // Touch了不移動一直Touch down時觸發
    public void onLongPress(MotionEvent arg0) {
        // TODO Auto-generated method stub
        System.out.println("onLongPress");
    }

    // 用戶按下觸摸屏,並拖動,由1個MotionEvent ACTION_DOWN, 多個ACTION_MOVE觸發
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        // TODO Auto-generated method stub
        System.out.println("onScroll");
        return false;
    }

    /*
     * Touch了還沒有滑動時觸發 (1)onDown只要Touch Down一定立刻觸發 (2)Touch
     * Down后過一會沒有滑動先觸發onShowPress再觸發onLongPress So: Touch Down后一直不滑動,onDown ->
     * onShowPress -> onLongPress這個順序觸發。
     */
    public void onShowPress(MotionEvent arg0) {
        // TODO Auto-generated method stub
        System.out.println("onShowPress");
    }

    /*
     * 兩個函數都是在Touch Down后又沒有滑動(onScroll),又沒有長按(onLongPress),然后Touch Up時觸發
     * 點擊一下非常快的(不滑動)Touch Up: onDown->onSingleTapUp->onSingleTapConfirmed
     * 點擊一下稍微慢點的(不滑動)Touch Up://確認是單擊事件觸發
     * onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed
     */
    public boolean onSingleTapUp(MotionEvent arg0) {
        // TODO Auto-generated method stub
        System.out.println("onSingleTopUp");
        return false;
    }

    class GLRenderer implements GLSurfaceView.Renderer {
        private final Context context;
        private final GLCube cube = new GLCube();

        GLRenderer(Context context) {
            this.context = context;
        }

        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
            // Define the lighting
            float lightAmbient[] = new float[] { 0.2f, 0.2f, 0.2f, 1 };
            float lightDiffuse[] = new float[] { 1, 1, 1, 1 };
            float[] lightPos = new float[] { 1, 1, 1, 1 };
            gl.glEnable(GL10.GL_LIGHTING);
            gl.glEnable(GL10.GL_LIGHT0);
            gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0);
            gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0);
            gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPos, 0);

            // What is the cube made of?
            float matAmbient[] = new float[] { 1, 1, 1, 1 };
            float matDiffuse[] = new float[] { 1, 1, 1, 1 };
            gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT,
                    matAmbient, 0);
            gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE,
                    matDiffuse, 0);

            // Set up any OpenGL options we need
            gl.glEnable(GL10.GL_DEPTH_TEST);
            gl.glDepthFunc(GL10.GL_LEQUAL);
            gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

            gl.glDisable(GL10.GL_DEPTH_TEST);
            gl.glEnable(GL10.GL_BLEND);
            gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE);

            // Enable textures
            gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
            gl.glEnable(GL10.GL_TEXTURE_2D);

            // Load the cube's texture from a bitmap
            GLCube.loadTexture(gl, context, R.drawable.android);

        }

        public void onSurfaceChanged(GL10 gl, int width, int height) {
            // Define the view frustum
            gl.glViewport(0, 0, width, height);
            gl.glMatrixMode(GL10.GL_PROJECTION);
            gl.glLoadIdentity();
            float ratio = (float) width / height;
            GLU.gluPerspective(gl, 45.0f, ratio, 1, 100f);

        }

        public void onDrawFrame(GL10 gl) {
            // Clear the screen to black
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

            // Position model so we can see it
            gl.glMatrixMode(GL10.GL_MODELVIEW);
            gl.glLoadIdentity();
            gl.glTranslatef(0, 0, -3.0f);

            gl.glRotatef(angley, 0, 1, 0);
            gl.glRotatef(anglex, 1, 0, 0);

            // Draw the model
            cube.draw(gl);
        }
    }
}

然后是一個Cube:

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;

class GLCube {
   private final IntBuffer mVertexBuffer;
   
   
   private final IntBuffer mTextureBuffer;

   
   public GLCube() {
      
      int one = 65536;
      int half = one / 2;
      int vertices[] = { 
            // FRONT
            -half, -half, half, half, -half, half,
            -half, half, half, half, half, half,
            // BACK
            -half, -half, -half, -half, half, -half,
            half, -half, -half, half, half, -half,
            // LEFT
            -half, -half, half, -half, half, half,
            -half, -half, -half, -half, half, -half,
            // RIGHT
            half, -half, -half, half, half, -half,
            half, -half, half, half, half, half,
            // TOP
            -half, half, half, half, half, half,
            -half, half, -half, half, half, -half,
            // BOTTOM
            -half, -half, half, -half, -half, -half,
            half, -half, half, half, -half, -half, };

      int texCoords[] = {
            // FRONT
            0, one, one, one, 0, 0, one, 0,
            // BACK
            one, one, one, 0, 0, one, 0, 0,
            // LEFT
            one, one, one, 0, 0, one, 0, 0,
            // RIGHT
            one, one, one, 0, 0, one, 0, 0,
            // TOP
            one, 0, 0, 0, one, one, 0, one,
            // BOTTOM
            0, 0, 0, one, one, 0, one, one, };
      
      ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
      vbb.order(ByteOrder.nativeOrder());
      mVertexBuffer = vbb.asIntBuffer();
      mVertexBuffer.put(vertices);
      mVertexBuffer.position(0);

      ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4);
      tbb.order(ByteOrder.nativeOrder());
      mTextureBuffer = tbb.asIntBuffer();
      mTextureBuffer.put(texCoords);
      mTextureBuffer.position(0);
      
   }
   

   public void draw(GL10 gl) { 
      gl.glVertexPointer(3, GL10.GL_FIXED, 0, mVertexBuffer);
      
      gl.glTexCoordPointer(2, GL10.GL_FIXED, 0, mTextureBuffer);
      
      gl.glColor4f(1, 1, 1, 1);
      gl.glNormal3f(0, 0, 1);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
      gl.glNormal3f(0, 0, -1);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);

      gl.glColor4f(1, 1, 1, 1);
      gl.glNormal3f(-1, 0, 0);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);
      gl.glNormal3f(1, 0, 0);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);

      gl.glColor4f(1, 1, 1, 1);
      gl.glNormal3f(0, 1, 0);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);
      gl.glNormal3f(0, -1, 0);
      gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);
   }
   
   
   static void loadTexture(GL10 gl, Context context, int resource) {
      Bitmap bmp = BitmapFactory.decodeResource(
            context.getResources(), resource);
      GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);
      gl.glTexParameterx(GL10.GL_TEXTURE_2D,
            GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
      gl.glTexParameterx(GL10.GL_TEXTURE_2D,
            GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
      bmp.recycle();
   }
   
}

運行:鼠標滑動屏幕,cube會旋轉。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM