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

先画一个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. 解决在 MVC  局部视图中加载 ueditor 编辑器时, 编辑器加载不出的 bug

    在 MVC 局部视图中,有时我们需要 加载 ueditor 编辑器,或进行局部刷新, 但是在加载局部视图后,ueditor 编辑器加载不出,这是由于 ueditor 使用的缓存,只要清空缓存,重新实例 ...

  2. 学习练习 java 输入输出流练习2

     编写IoDemo.java的Java应用程序,程序完成的功能是:首先读取text.txt文件内容,再通过键盘输入文件的名称为iodemo.txt,把text.txt的内容存入iodemo.txt p ...

  3. 学习练习 java 二分查找法

    package com.hanqi; import java.util.*; public class Test5 { public static void main(String[] args) { ...

  4. TCP/IP详解学习笔记(6)-- IP选路

    1.概述      路由算法是用于获取路由表中的路由项目.它是路由选择协议的核心. 2.路由算法的分类      从路由算法能否随网络的通信量或拓扑自适应的进行调整变化来分,可以分为两类. 静态路由选 ...

  5. 查询数据库后台Block 的Sql存储过程

    查询数据库后台Block 的Sql存储过程 SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER OFF GO /*记录SQL Server的阻塞情况 wang 200 ...

  6. Android IOS WebRTC 音视频开发总结(五十)-- 技术服务如何定价?

    这篇文章最早是杜老师写的,看完感触很深,加上之前跟咨询公司的朋友也讨论过这方面的问题,所以结合自己的经验,做了些删改(得到了杜老师的授权). 先通过下面几个简单的问题来了解技术服务: 问题1:技术服务 ...

  7. JSON-JQuery常用技巧

    1:Jquery对象选择查找 var group = $(".classeslist li"); class 为 classeslist 内部 的所有 li 元素对象 遍历: fo ...

  8. Android数据库(sqlite)加密方案

    最近因为一些项目的安全性需要将数据库加密,一开始想到的就是先将数据库通过AES加密,然后运行时再解密,另一种是将数据库里的内容加密. 很快这两种方案都是不理想的,第一种加密方式形同虚设,第二种,如果加 ...

  9. crontab的使用说明

    网上瞎转载的,仅供参考 名称 : crontab 使用权限 : 所有使用者 使用方式 : crontab file [-u user]-用指定的文件替代目前的crontab. crontab-[-u ...

  10. CentOS 7服务

    重启防火墙service firewalld start/restart/stop 使用systemctl来启动/停止/重启服务要启动一个服务,你需要使用如下命令:# systemctl start ...