结合上一节的内容,分享完整代码。

先画一个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会旋转。

OpenGL完整实例的更多相关文章

  1. C# 调用第三方DLL完整实例

    C# 调用第三方DLL完整实例 分类: C/C++ 以下代码为本人在实际项目中编写的调用第三方DLL接口程序的完整代码. public class ExecuteDLL : Form { ...//忽 ...

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

    多个mapreduce工作相互依赖处理方法完整实例(JobControl) 原文地址:http://mntms.iteye.com/blog/2096456?utm_source=tuicool&am ...

  3. 利用Div+CSS(嵌套+盒模型)布局页面完整实例流程

    Div+CSS(嵌套+盒模型)布局页面完整实例流程: <!DOCTYPE html><html> <head>  <meta charset="UT ...

  4. 微信小程序发送短信验证码完整实例

    微信小程序注册完整实例,发送短信验证码,带60秒倒计时功能,无需服务器端.效果图: 代码: index.wxml <!--index.wxml--> <view class=&quo ...

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

    这篇文章主要介绍了PHP实现视频文件上传的技巧,包含了PHP配置信息的设计及大文件的处理,需要的朋友可以参考下    本文以一个完整实例的形式实现了视频文件上传的功能.虽然是比较基础的应用,仍有一定的 ...

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

    这篇文章主要介绍了一个超详细的php用户注册页面填写信息完整实例,内容包括邮箱自动匹配.密码强度验证以及防止表单重复等,小编特别喜欢这篇文章,推荐给大家. 注册页面是大多数网站必备的页面,所以很有必要 ...

  7. 前后端API交互数据加密——AES与RSA混合加密完整实例

    前言 前段时间看到一篇文章讲如何保证API调用时数据的安全性(传送门:https://blog.csdn.net/ityouknow/article/details/80603617),文中讲到利用R ...

  8. Spring和ActiveMQ整合的完整实例

     Spring和ActiveMQ整合的完整实例 前言 这篇博文,我们基于Spring+JMS+ActiveMQ+Tomcat,做一个Spring4.1.0和ActiveMQ5.11.1整合实例,实现了 ...

  9. python测试mysql写入性能完整实例

    这篇文章主要介绍了python测试mysql写入性能完整实例,具有一定借鉴价值,需要的朋友可以参考下 本文主要研究的是python测试mysql写入性能,分享了一则完整代码,具体介绍如下. 测试环境: ...

随机推荐

  1. Android开发-API指南-<permission-group>

    <permission-group> 英文原文:http://developer.android.com/guide/topics/manifest/permission-group-el ...

  2. Wordpress SEO对策(译)

    原文link http://netaone.com/wp/wordpress-seo-plugin/ 统一管理SEO对策的设定能够统一管理SEO相关设定的插件:All in One SEO Pack. ...

  3. 【练习】增加日志组数至4组,且每组日志成员大小为50M,每组2个成员。

    1.查看日志组成员路径及日志组大小.状态 SQL> select group#,member from v$logfile; GROUP# MEMBER ---------- --------- ...

  4. Eclipse SVN冲突解决

    基本原则是:每次提交前需要先和线上的对比,先把冲突解决掉,然后把线上的更新到本地,最后把本地的提交上去. 右键项目 -> Team -> 与资源库同步 在同步视图中选择Conflicts ...

  5. 如何用手机维护Mysql数据库

    如何用手机维护网站数据库 身边很多人都在拿ipad或iphone来玩儿游戏或听歌,大多数人认为它们就是个娱乐设备,在我看来它们同样可以帮助我们更加快捷的工作,我用手机遥控单反.用手机控制PPT的播放. ...

  6. hql语句关联查询(select new )

    在  new bean()中,对象里要有其构造方法,查询参数必须是构造方法中的参数,get set也要同步 类似于 String hql= "select  new A(a.id, a.na ...

  7. docker学习(一)

    atomic使用有点费劲,我改为centos7来做为学习环境. 1 安装 epel源就自带,目前版本是1.10.3 yum -y install docker docker version Clien ...

  8. angular service讲解

    controller是相对独立的,也就是说,两个controller之间,内存是不共享的,这个controller是无法访问其他其他controller的属性或者方法的; 以前,我都是通过localS ...

  9. JS 中 this 关键字详解

    本文主要解释在JS里面this关键字的指向问题(在浏览器环境下). 首先,必须搞清楚在JS里面,函数的几种调用方式: 普通函数调用 作为方法来调用 作为构造函数来调用 使用apply/call方法来调 ...

  10. ios中,长按Webview中的图片

    我们所要解决的问题如题目所示:ios中,长按Webview中的图片,将图片保存到本地相册. 解决方案:对load的html网页,执行js注入,通过在webview中执行js代码,来响应点击事件,通过j ...