zoukankan      html  css  js  c++  java
  • 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会旋转。

  • 相关阅读:
    Map集合
    Collections 工具类
    LinkedList 集合
    List集合
    Iterator迭代器
    Collection集合
    时间日期类
    一看就懂!速写docker 容器数据库备份脚本
    Nginx 配置之HTTPS和WSS那些你不知道的事!
    https 证书认证/颁发/秒级认证无烦恼
  • 原文地址:https://www.cnblogs.com/hongguang-kim/p/5648002.html
Copyright © 2011-2022 走看看