使用OpenGL开发Android应用详解系列三

注:近三篇转载中的视锥体部分结合着来看,再参照老罗的3d变换,基本可以初步理解和完成相关视锥体调整。

使用OpenGL开发Android应用详解系列三

【原创】转载请注明出处 我一家网 http://www.5yijia.com
前面两节主要介绍了一下OpenGL的基本概念,以及在Android开发中引入OpenGL时,Android项目的基本构成情况。这一节开始,我们通过具体的实例,来进行简单3D图形的描画。
注:代码基础还是采用上一节: 使用OpenGL开发Android应用详解系列二中使用的代码结构。

通过OpenGL来绘制简单立体图形

在进行绘制立体图形之前,我们先来了解一些相关术语,如果这些概念理解透彻的话,对Android中使用OpenGL开发很有帮助。

1. 相关术语理解
这里的术语包括: 坐标系,视锥体(frustum)和视窗(viewport)
(1)坐标系
为了制定三维空间内物体的位置,需要引入坐标系。下面是OpenGL的三维坐标系(注:和DirectX完全相反)

通过坐标系我们可以定义实际的物体,但是物体定义好了以后应该放在什么位置,接下来就是frustum来定义了.

2. 视锥体(frustum)

或者叫做视景,他主要用来定义物体可以表示的空间领域。

视锥体的视线方向是 -Z方向,也就是说,他是坐标轴中Z轴的反方向。请看下图:

通过从-Z方向作为视点来查看的话,视角(看的角度)与离得较近的切面,以及较远切面之间是成比例关系的.

(3)视窗(viewport)

上面图中那个蓝色的切面就是viewport,OpenGL中经常叫的视窗(viewport)。

2.OpenGL开发中使用视窗和视锥体

glViewport用来指定从标准设备的Window坐标的转换矩阵。矩阵变换主要指的是放大,缩小,旋转,截断,平行移动,线性变换的组合操作。

glViewport(GLint x,GLint y,GLsizei width,GLsizei height)为其函数原型。

参数说明:

x,y    以像素为单位,指定了视窗的左下角位置。

width,height   表示这个视窗矩形的宽度和高度,根据窗口的实时变化重绘窗口。

 

上面那个笑脸图像就是以左边图形的左下角的(x,y)坐标来投影右边图像的宽和高(width,height)。由于左边和右边的设备类别不同,导致投影后的图像变形了。为了防止变形,我们需要通过视锥体(frustum)的宽高比(aspect ratio),来让实际的设备保持和原有设备同样的比例。

在上面章节中讲过,设备大小或者纵横的方向改变时,会调用onSurfaceChanged方法,为了防止变形,我们可以通过下面的代码来控制.

@Override
	public void onSurfaceChanged(GL10 arg0, int width, int height) {
		arg0.glViewport(0, 0, width, height);

		arg0.glMatrixMode(GL10.GL_PROJECTION);
		arg0.glLoadIdentity();    
		GLU.gluPerspective(arg0, 45f,(float) width / height, 1f, 50f);
		// TODO Auto-generated method stub
	}

如果是直接绘制图形的话,opengl是没有空间的位置观念的,因为它根本不能分辨物体的前后关系。所以为了让OpenGL有前后位置的概念,我们需要使用深度缓冲区。

下面的代码设置Depth Test有效。

@Override
	public void onSurfaceCreated(GL10 arg0, EGLConfig config) {
		arg0.glEnable(GL10.GL_DEPTH_TEST);
		arg0.glDepthFunc(GL10.GL_LEQUAL);
		// TODO Auto-generated method stub
	}

3. 正方体的定义

接下来我们来定义一个正方体

package com.wuyijia.opengltest;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

public class MyOpenGLCube {

	//浮点缓冲区:批量get
	private final FloatBuffer mVertexBuffer;

	  /**
	   * 定义正方体坐标
	   */
	  public MyOpenGLCube(){

	    float vertices[] = {
	      //正方体前面
	      -0.5f, -0.5f, 0.5f,
	      0.5f, -0.5f, 0.5f,
	      -0.5f, 0.5f, 0.5f,
	      0.5f, 0.5f, 0.5f,

	      //正方体后面
	      -0.5f, -0.5f, -0.5f,
	      0.5f, -0.5f, -0.5f,
	      -0.5f, 0.5f, -0.5f,
	      0.5f, 0.5f, -0.5f,

	      //正方体左面
	      -0.5f, -0.5f, 0.5f,
	      -0.5f, -0.5f, -0.5f,
	      -0.5f, 0.5f, 0.5f,
	      -0.5f, 0.5f, -0.5f,

	      //正方体右面
	      0.5f, -0.5f, 0.5f,
	      0.5f, -0.5f, -0.5f,
	      0.5f, 0.5f, 0.5f,
	      0.5f, 0.5f, -0.5f,

	      //正方体上面
	      -0.5f, 0.5f, 0.5f,
	      0.5f, 0.5f, 0.5f,
	      -0.5f, 0.5f, -0.5f,
	      0.5f, 0.5f, -0.5f,

	      //正方体底面
	      -0.5f, -0.5f, 0.5f,
	      0.5f, -0.5f, 0.5f,
	      -0.5f, -0.5f, -0.5f,
	      0.5f, -0.5f, -0.5f
	    };

	    ByteBuffer vbb = 
	      ByteBuffer.allocateDirect(vertices.length * 4);
	    vbb.order(ByteOrder.nativeOrder());
	    mVertexBuffer = vbb.asFloatBuffer();
	    mVertexBuffer.put(vertices);
	    mVertexBuffer.position(0);

	  }

	  /**
	   * 绘制正方体
	   * @param gl
	   */
	  public void draw(GL10 gl){

	    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
	    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);

	    //正方体前面
	    gl.glNormal3f(0, 0, 1.0f);
	    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

	    //正方体后面
	    gl.glNormal3f(0, 0, -1.0f);
	    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4);

	    //正方体左面
	    gl.glNormal3f(-1.0f, 0, 0);
	    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4);

	    //正方体右面
	    gl.glNormal3f(1.0f, 0, 0);
	    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4);

	    //正方体上面
	    gl.glNormal3f(0, 1.0f, 0);
	    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4);

	    //正方体底面
	    gl.glNormal3f(0, -1.0f, 0);
	    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4);

	  }
}

上面的类定义了一个以屏幕中心为正方形原点,边长为1的正方体。

4. 渲染正方体
接下来我们在onDrawFrame函数中渲染刚才我们定义的正方体。

MyOpenGLCube myOpenGLCube = new MyOpenGLCube();
	@Override
	public void onDrawFrame(GL10 arg0) {
		arg0.glClear(GL10.GL_COLOR_BUFFER_BIT 
		        | GL10.GL_DEPTH_BUFFER_BIT);

		arg0.glMatrixMode(GL10.GL_MODELVIEW);
		arg0.glLoadIdentity();
		arg0.glTranslatef(0, 0, -3f);

		myOpenGLCube.draw(arg0);
		// TODO Auto-generated method stub
	}

OK,正方体渲染完成后,运行我们的应用,效果图如下:

我们发现运行的效果并不是立方体,而是一个正方形。原因是我们没有旋转立方体的缘故,所以看上去就像一个正方形。加上下面的代码再看一下效果。

@Override
	public void onDrawFrame(GL10 arg0) {
		arg0.glClear(GL10.GL_COLOR_BUFFER_BIT 
		        | GL10.GL_DEPTH_BUFFER_BIT);

		arg0.glMatrixMode(GL10.GL_MODELVIEW);
		arg0.glLoadIdentity();
		arg0.glTranslatef(0, 0, -3f);

		//旋转正方体
		arg0.glRotatef(30f, 0, 1, 0);

		myOpenGLCube.draw(arg0);
		// TODO Auto-generated method stub
	}

运行后效果如下:

终于看到立体效果了。


转自:http://www.5yijia.com/?p=95


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录: 结构如下,非常详细 第1章 android系统概述 1 1.1 基础知识 1 1.1.1 android开发系统的由来 1 1.1.2 移动电话系统开发模式 2 1.1.3 未来移动电话的功能及android的优势 4 1.2 android开发工作 6 1.2.1 android移植开发 6 1.2.2 android应用开发 8 1.2.3 android系统开发 9 1.3 android的sdk与源代码 10 1.3.1 基于sdk的android开发 10 1.3.2 基于源代码sdk android开发 11 第2章 android系统开发综述 13 2.1 android的系统架构 13 2.1.1 软件结构 13 2.1.2 android的工具 16 2.2 android源代码的开发环境 18 2.2.1 android源代码的获取和提交 18 2.2.2 android源代码结构 21 2.2.3 编译 24 .2.2.4 系统的运行 25 2.3 android sdk的开发环境 32 2.3.1 sdk的结构 32 2.3.2 windows环境sdk开发 33 2.3.3 linux环境sdk开发 42 第3章 android的linux内核与驱动程序 44 3.1 linux核心与驱动 44 3.2 android专用驱动 45 3.2.1 ashmem 45 3.2.2 binder 45 3.2.3 logger 46 3.3 android使用的设备驱动 46 3.3.1 framebuffer显示驱动 46 3.3.2 event输入设备驱动 48 3.3.3 v4l2摄像头——视频驱动 50 3.3.4 oss音频驱动 53 3.3.5 alsa音频驱动 54 3.3.6 mtd驱动 56 3.3.7 蓝牙驱动 57 3.3.8 wlan驱动 58 第4章 android的底层库和程序 60 4.1 底层库和程序的结构 60 4.1.1 本地实现的基本结构 60 4.1.2 增加本地程序和库的方法 61 4.2 标准c/c++库bionic 64 4.3 c语言工具库libcutils 65 4.4 init可执行程序 66 4.5 shell工具 72 4.6 c++工具库libutils 75 4.6.1 libutils的基本内容 75 4.6.2 binder 76 4.6.3 libutils中的其他内容 82 4.7 android的系统进程 85 4.7.1 servicemanager 85 4.7.2 zygote 87 第5章 android的java虚拟机和java环境 88 5.1 dalvik虚拟机和核心库 88 5.1.1 dex工具库和虚拟机的实现 89 5.1.2 核心库 90 5.1.3 nativehelper库 91 5.2 android的java程序环境 91 5.2.1 java类的层次结构 91 5.2.2 android java类的代码 92 5.2.3 android系统api 92 5.3 jni的使用 96 5.3.1 jni的架构和实现方式 97 5.3.2 jni的实现方式 97 5.3.3 在应用程序中使用jni 99 5.4 系统服务的java部分 101 5.4.1 binder 102 5.4.2 servicemanager 103 5.4.3 系统进程 103 第6章 android的gui系统 106 6.1 android gui系统综述 106 6.2 pixelflinger和libui库 108 6.2.1 pixelflinger 108 6.2.2 libui 108 6.2.3 输出/输入与硬件的接口 109 6.3 surface系统 113 6.3.1 surface系统本地接口 113 6.3.2 surfaceflinger本地代码 115 6.3.3 surface的java和jni代码 119 6.4 skia和2d图形系统 121 6.4.1 skia底层库 121 6.4.2 android图形系统的jni接口 124 6.4.3 android的图形包(graphics) 125 6.5 androidopengl系统与3d图形系统 125 6.5.1 opengl的本地代码 125 6.5.2 opengl的jni代码 130 6.5.3 opengl的java类 130 第7章 android的audio系统 132 7.1 audio系统综述 132 7.2 audio系统和上层接口 134 7.2.1 audio系统的各个层次 134 7.2.2 media库
本书共分两篇,第一篇介绍了Android 3D游戏开发的基础知识,主要对OpenGL ES的相关内容进行了介绍。   章 名主 要 内 容   第1章 英雄还看今朝—Android简介本章介绍了市场上主流的手机平台,同时也分析了未来手机平台的发展趋势及Android平台的前景   第2章 数风流人物—当前流行游戏类型简介本章以分类的方式简要地介绍了当前流行的游戏的玩法,游戏的视觉效果,游戏的设计及《仙剑》等著名游戏的历史   第3章 不积跬步,无以至千里—游戏开发基础知识本章初步介绍了游戏开发的基础知识   第4章 千里之行,始于足下—3D开发基础知识本章介绍了3D开发中的基础知识,包括OpenGL ES的介绍及OpenGL ES中绘制模型的原理,并通过点、线和角形的绘制介绍了OpenGL ES中模型的几种绘制方式。最后介绍了3D场景中常用的两种投影方式,并通过例子比较了这两种投影的区别   第5章 愿君多采撷,此物最相思—光照效果的开发本章介绍了光照的基础知识,包括环境光、散射光及镜面光   第6章 为伊消得人憔悴——纹理映射本章主要介绍了纹理的基础知识,以及纹理的不同拉伸方式和纹理过滤高级技术,从绘制角形开始到绘制地月系,可能会经历很长时间,但是这对以后的学习是有帮助的   第7章 海阔凭鱼跃,天高任鸟飞—3D基本形状的构建在本章中介绍了圆柱体、圆锥体、圆环、抛物面、双曲面和螺旋面在OpenGL ES中的渲染方法。这些基本形状在3D世界中应用广泛,在构造一些复杂物体时,经常会运用这些基本形状来进行拼装组合   第8章 执子之手,与子偕老—坐标变换本章介绍了坐标变换的应用。绘制3D场景的过程,主要是旋转和平移操作的组合,通过合理的堆栈操作,就比较容易绘制出所需的3D场景   第9章 孤帆远影碧空尽—摄像机与雾特效在本章中,首先对摄像机及其配置做了介绍。摄像机在3D编程中至关重要,没有正确的配置,摄像机可能不能获得想要的场景效果。然后对雾特效做了具体介绍,应用雾特效可以使场景更加逼真,并且可以减少场景渲染量来提高性能   第10章 假作真时真亦假—混合本章主要为读者介绍了混合,从混合的背景知识到如何配置源因子和目标因子。在介绍源因子和目标因子的时候,向读者介绍了一些预定义常量和一些常用的组合方式,以及如何启用混合   第11章 蓦然回首,那人却在灯火阑珊处—3D高级技术本章主要为读者介绍了3D的一部分高级技术。每一项技术通过讲解其原理和案例,使读者对3D高级技术有一定的了解   第12章 心有灵犀一点通—传感器在本章中,向读者介绍了Android中传感器的相关知识。包括传感器的种类、配置,并且着重介绍了姿态传感器的应用   第13章 千锤万凿出深山—游戏中的数学与物理在本章中对3D游戏中可能会用到的数学及物理知识进行了简单的介绍,这在3D游戏开发中是相当重要的。游戏中的核心算法,基本上都要用到数学和物理知识。一款游戏的性能很大程度上取决于游戏设计的算法   第14章 山舞银蛇,原驰蜡象—AI基本理念本章主要介绍了AI、AI引擎的基本组成与设计,以及游戏AI中图的搜索和模糊逻辑,其中游戏AI中图的搜索为本章的重点。在本章中详细介绍了5种算法的原理与实现   第15章 独上高楼,望尽天涯路—开发小秘籍本章介绍了地图设计器、多键技术、虚拟键盘、查找表技术、状态机、AABB边界框、穿透效应、拾取技术,以及天空盒和天空穹在OpenGL ES中的应用 第二篇以7个比较大的案例来说明Android平台下3D游戏的开发流程,通过这7个案例的讲解,读者对3D游戏的开发将会有更深层次的理解。   章 名主 要 内 容   第16章 体育类游戏——《疯狂投篮》本章介绍了Android 3D游戏《疯狂投篮》的开发。通过该案例向读者介绍了在Android平台下进行3D游戏开发的相关知识和基本流程,并对游戏开发中的编程技巧进行了介绍,并主要介绍了篮球与地面、墙面及篮框的碰撞检测及运动动画的实现方法   第17章 益智类游戏——《旋转积木》本章介绍了Android 3D游戏《旋转积木》的开发。主要介绍了积木旋转的不同状态的实现方法和地图设计器的应用   第18章 休闲类游戏——《摩天大楼》本章介绍了Android 3D游戏《摩天大楼》的开发。主要介绍了楼层与楼层之间的衔接与碰撞及掉落后翻转动画的实现   第19章 动作类游戏——《3D空战》本章介绍了Android 3D游戏《3D空战》的开发。主要介绍了飞机的构造方法和我方战机与敌方战机的操控及动画实现   第20章 桌面类游戏——《激情台球》本章介绍了Android 3D游戏《激情台球》的开发。主要介绍了台球与台球的碰撞检测实现、台球与球桌的碰撞检测实现和进球的判定实现   第21章 射击类游戏——《抢滩登陆》本章介绍了Android 3D游戏《抢滩登陆》的开发。主要运用了灰度图生成技术并且主要介绍了坦克运动的实现方法及炮弹碰撞检测的实现   第22章 竞技类游戏——《乡村飙车》本章介绍了Android 3D游戏《乡村飙车》的开发。主要介绍了运用分层绘制和拼接绘制的策略进行场景的优化绘制,并且对场景部件进行了分类控制   本书面向的读者   本书的内容详细,且几乎涵盖了Android 3D游戏开发所有相关的技术,并向读者介绍了真实项目的开发流程,主要面向以下读者。   Android的初学者   本书详细介绍了OpenGL ES的基础知识,并对Android 3D游戏程序的开发进行了介绍。作为一名Android的初学者,通过本书的学习可以快速全面地掌握Android 3D游戏开发的相关知识,稳健地步入Android 3D游戏开发人员的行列。   有一定Android基础且希望学习Android 3D游戏开发的读者   有一定Android基础的读者通过阅读本书的前半部分便可快速掌握OpenGL ES的基础知识,然后通过7个真实案例的学习迅速掌握Android平台下应用程序的开发。   在职的开发人员

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值