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会旋转。

时间: 2024-10-20 23:16:23

OpenGL完整实例的相关文章

[转]C语言构建动态数组完整实例

原文地址:http://www.jb51.net/article/52153.htm 本文以一个完整的实例代码简述了C语言构建动态数组的方法,供大家参考,完整实例如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <stdio.h> #include <malloc.h> int main(void) {     int len;     int * arr;     printf("请输入数组长度:&q

struts1.x完整实例

struts1.x完整实例 1.简介 struts是WEB程序MVC分层架构中的C,属于控制层,主要进行处理用户的请求,基于请求驱动.获取用户的请求地址并将表单中的数据封装到Form对象后交给Action进行处理.在Action中进行条用业务层处理具体的请求后将结果通过ActionMapping封装跳转地址返回给用户.struts是对servlet的再次封装,使得更加灵活高效.下面以一个登录的实例讲解struts的开发过程. 2.在新建的web工程中添加以下struts1.x  jar包 ant

spring mvc 和ajax异步交互完整实例(转自CSDN) 附下载地址

spring mvc 和ajax异步交互完整实例 spring MVC 异步交互demo: demo下载地址:http://download.csdn.net/download/quincylk/9521375 1.jsp页面: [java] view plain copy print? <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-

(转)多个mapreduce工作相互依赖处理方法完整实例(JobControl)

多个mapreduce工作相互依赖处理方法完整实例(JobControl) 原文地址:http://mntms.iteye.com/blog/2096456?utm_source=tuicool&utm_medium=referral 处理复杂的要求的时候,有时一个mapreduce程序时完成不了的,往往需要多个mapreduce程序,这个时候就要牵扯到各个任务之间的依赖关系,所谓依赖就是一个M/R Job 的处理结果是另外的M/R 的输入,以此类推,完成几个mapreduce程序,得到最后的结

Spring和ActiveMQ整合的完整实例

Spring和ActiveMQ整合的完整实例 前言 这篇博文,我们基于Spring+JMS+ActiveMQ+Tomcat,做一个Spring4.1.0和ActiveMQ5.11.1整合实例,实现了Point-To-Point的异步队列消息和PUB/SUB(发布/订阅)模型,简单实例,不包含任何业务. 环境准备 工具 JDK1.6或1.7 Spring4.1.0 ActiveMQ5.11.1 Tomcat7.x 目录结构 所需jar包 项目的配置 配置ConnectionFactory conn

PHP实现视频文件上传完整实例

PHP实现视频文件上传完整实例 转载 这篇文章主要介绍了PHP实现视频文件上传的技巧,包含了PHP配置信息的设计及大文件的处理,需要的朋友可以参考下 本文以一个完整实例的形式实现了视频文件上传的功能.虽然是比较基础的应用,仍有一定的参考价值.分享给大家供大家参考之用.具体方法如下: 首先,对PHP来说视频也属于文件,我们利用这个道理,可以通过与上传普通文件类似的方式实现上传PHP视频文件.不同的是视频文件一般较大,上传时间长,而php配置文件也对上传文件的大小有限制.如果需要更好地用PHP实现文

超详细的php用户注册页面填写信息完整实例(附源码)

这篇文章主要介绍了一个超详细的php用户注册页面填写信息完整实例,内容包括邮箱自动匹配.密码强度验证以及防止表单重复等,小编特别喜欢这篇文章,推荐给大家. 注册页面是大多数网站必备的页面,所以很有必要对自己的注册页面做些精心的设计.下面三张图,第一张是注册的展示页面,第二张思维导图就一个简单的逻辑,第三张是通过firebug查看调用的JS文件. 一.给每个输入框写下说明 在用户看到这个输入框的时候,就能非常清晰的明白这个输入框是做啥用的,最大限度的降低他们产生疑惑的可能性.我们需要假设用户毫不了

Struts2 + uploadify 多文件上传完整实例!

首先我这里使用的是  Jquery  Uploadify3.2的版本  导入相关的CSS  JS    <link rel="stylesheet" type="text/css" href="<%=basePath%>css/uploadify/uploadify.css"> <script src="<%=basePath%>js/jquery.min.js"></sc

java发送邮件完整实例

实例一 import java.util.Properties; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.int