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

简介: 注:近三篇转载中的视锥体部分结合着来看,再参照老罗的3d变换,基本可以初步理解和完成相关视锥体调整。 使用OpenGL开发Android应用详解系列三 【原创】转载请注明出处 我一家网 http://www.5yijia.com 前面两节主要介绍了一下OpenGL的基本概念,以及在Android开发中引入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


目录
相关文章
|
15天前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
40 19
|
15天前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
41 14
|
15天前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
|
16天前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
16天前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
16天前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
24 0
|
7月前
|
XML 小程序 Java
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
138 0
|
缓存 C++
Opengl ES之FBO
Opengl ES连载系列
157 0
|
存储 编解码 算法
Opengl ES之LUT滤镜(上)
Opengl ES之连载系列
471 0
|
数据安全/隐私保护 开发者
OpenGL ES 多目标渲染(MRT)
Opengl ES连载系列
331 0
下一篇
DataWorks