使用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


目录
相关文章
|
4天前
|
存储 Android开发
如何查看Flutter应用在Android设备上已被撤销的权限?
如何查看Flutter应用在Android设备上已被撤销的权限?
116 64
|
1月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
305 76
|
2月前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
86 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
2月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
229 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
2月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
76 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
3月前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
191 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
2月前
|
安全 Android开发 iOS开发
escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
escrcpy 是一款基于 Scrcpy 的开源项目,使用 Electron 构建,提供图形化界面来显示和控制 Android 设备。它支持 USB 和 Wi-Fi 连接,帧率可达 30-120fps,延迟低至 35-70ms,启动迅速且画质清晰。escrcpy 拥有丰富的功能,包括自动化任务、多设备管理、反向网络共享、批量操作等,无需注册账号或广告干扰。适用于游戏直播、办公协作和教育演示等多种场景,是一款轻量级、高性能的 Android 控制工具。
140 1
|
11月前
|
XML 小程序 Java
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
206 0
|
数据安全/隐私保护 开发者
OpenGL ES 多目标渲染(MRT)
Opengl ES连载系列
420 0
|
缓存 C++
Opengl ES之FBO
Opengl ES连载系列
235 0

热门文章

最新文章

下一篇
oss创建bucket