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会旋转。
OpenGL完整实例的更多相关文章
- C# 调用第三方DLL完整实例
C# 调用第三方DLL完整实例 分类: C/C++ 以下代码为本人在实际项目中编写的调用第三方DLL接口程序的完整代码. public class ExecuteDLL : Form { ...//忽 ...
- (转)多个mapreduce工作相互依赖处理方法完整实例(JobControl)
多个mapreduce工作相互依赖处理方法完整实例(JobControl) 原文地址:http://mntms.iteye.com/blog/2096456?utm_source=tuicool&am ...
- 利用Div+CSS(嵌套+盒模型)布局页面完整实例流程
Div+CSS(嵌套+盒模型)布局页面完整实例流程: <!DOCTYPE html><html> <head> <meta charset="UT ...
- 微信小程序发送短信验证码完整实例
微信小程序注册完整实例,发送短信验证码,带60秒倒计时功能,无需服务器端.效果图: 代码: index.wxml <!--index.wxml--> <view class=&quo ...
- PHP实现视频文件上传完整实例
这篇文章主要介绍了PHP实现视频文件上传的技巧,包含了PHP配置信息的设计及大文件的处理,需要的朋友可以参考下 本文以一个完整实例的形式实现了视频文件上传的功能.虽然是比较基础的应用,仍有一定的 ...
- 超详细的php用户注册页面填写信息完整实例(附源码)
这篇文章主要介绍了一个超详细的php用户注册页面填写信息完整实例,内容包括邮箱自动匹配.密码强度验证以及防止表单重复等,小编特别喜欢这篇文章,推荐给大家. 注册页面是大多数网站必备的页面,所以很有必要 ...
- 前后端API交互数据加密——AES与RSA混合加密完整实例
前言 前段时间看到一篇文章讲如何保证API调用时数据的安全性(传送门:https://blog.csdn.net/ityouknow/article/details/80603617),文中讲到利用R ...
- Spring和ActiveMQ整合的完整实例
Spring和ActiveMQ整合的完整实例 前言 这篇博文,我们基于Spring+JMS+ActiveMQ+Tomcat,做一个Spring4.1.0和ActiveMQ5.11.1整合实例,实现了 ...
- python测试mysql写入性能完整实例
这篇文章主要介绍了python测试mysql写入性能完整实例,具有一定借鉴价值,需要的朋友可以参考下 本文主要研究的是python测试mysql写入性能,分享了一则完整代码,具体介绍如下. 测试环境: ...
随机推荐
- AS3深拷贝数据对象(2)深拷贝VO对象
Topic:对于用户自定义的VO对象进行深拷贝,一种VO对象的某属性可能是另一种VO对象的实例. 方法1:通过传说中的“AS3隐藏特性——ByteArray.writeObject和readObjec ...
- C#之泛型
泛型是C# 2.0版本才有的语言特性,是具有参数类型占位符的类.结构.接口和方法.这些占位符是类.结构.接口和方法所存储或使用的一个或多个占位符.简单来说,就是变量类型的参数化. 以下是详细demo: ...
- pycurl
http://www.cnblogs.com/lonelycatcher/archive/2012/02/09/2344005.html http://ju.outofmemory.cn/entry/ ...
- 【linux】 静态库编译
文件如下: root@ubuntu:/home/test# ll total drwxr-xr-x root root Sep : ./ drwxr-xr-x root root Sep : ../ ...
- 简短总结一下C#里跨线程更新UI
摘自: http://my.oschina.net/sdqxcxh/blog/53707 跨线程更新UI是写多线程程序尤其是通信类的程序经常遇到的问题,这里面主要的问题是冲突,比如数据线程想要更新UI ...
- iOS键盘类型
一.键盘风格 UIKit框架支持8种风格键盘. typedef enum { UIKeyboardTypeDefault, // 默认键盘:支持所有字符 UIKeyboa ...
- LTE参考资料
NETMANIAS TECHNICAL DOCUMENTS: http://www.netmanias.com/en/?m=board&id=techdocs
- CentOS学习笔记--MySQL安装
MySQL安装 Linux中使用最广泛的数据库就是MySQL,使用在线yum的方式安装的版本落后MySQL网站好几个小版本,本节亲自测试安装新版的MySQL. 测试机器环境: VMware Works ...
- POJ C程序设计进阶 编程题#2:字符串中次数第2多的字母
编程题#2:字符串中次数第2多的字母 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536k ...
- Pass Dynamic Value to a Grid Label
A grid label is the blue (normally) colored grid header that you see on PeopleSoft pages. The grid ...