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写入性能,分享了一则完整代码,具体介绍如下. 测试环境: ...
随机推荐
- 能在手机播放的Flash代码
有些使用Flash的广告图片变换代码在手机不支持,在网上搜到了一个解决的方法: Flash嵌入处: <iframe style="width:474px;height:276px; b ...
- UIBlurEffect实现模糊效果
//使用图片初始化背景 Pattern 图案,模式 self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageN ...
- Android基础总结(7)——异步消息处理
服务(Service)是Android中实现程序后台运行的解决方案,它非常适合用于去执行哪些不需要和用户交互而且还要长期运行的任务.服务的运行不依赖任何用户界面,即使当程序被切换到后台,或者用户打开了 ...
- ref传递
下面通过一个排序的小栗子来分析ref传递: static void Main(string[] args) { ,,,,}; int num; Console.WriteLine("请输入您 ...
- ASP.NET MVC 开源项目学习之ProDinner (一)
首先在github上面将ProDinner项目通过 Git Bash 克隆到本地,接下来我们开始分析这个项目吧~ 系统采用.Net 4.5, Asp.net Mvc 5,VS2012,Sql serv ...
- java基础回顾(四)——锁机制
关键字Synchronized 1.对于同步的方法或者代码块来说,必须获得对象锁才能够进入同步方法或者代码块进行操作: 2.如果采用method级别的同步,则对象锁即为method所在的实例对象,如果 ...
- windows live writer向cnblog发布文章设置(转)
Windows Live Writer是非常不错的一个日志发布工具,支持本地写文章,非常方便将word 中内容,包括图片进行处理,有点感觉相见恨晚. Live Writer最新版本下载地址是什么? h ...
- css3为图片添加鼠标移入放大效果
只需要为添加效果的图片定义一个伪类 img.zoom-img:hover { -webkit-transform: scale(1.15); -webkit-transition-timing-fun ...
- Android IOS WebRTC 音视频开发总结(二八)-- 多人视频方案介绍
很多人问视频会议,在线教学,主播怎么弄,所以整理下这方面的开源解决方案, 同时为了方便测试,在自己服务器上搭建了相应的服务端,文章来自博客园RTC.Blacker,转载请说明出处. 简单来说,WEBR ...
- MVC 项目 在前台使用DataTable
1:后台控制器代码 //CreateTestOutputDataHeader生成一个测试DataTable public ActionResult UseDataTable() { DataTable ...