Android基于OpenGL在GLSurfaceView上绘制三角形及使用投影和相机视图方法示例
作者:pku_android 发布时间:2023-06-08 03:59:42
本文实例讲述了Android基于OpenGL在GLSurfaceView上绘制三角形及使用投影和相机视图方法。分享给大家供大家参考,具体如下:
定义三角形
OpenGL 允许我们使用三维坐标来定义物体。在绘制三角形前,我们需要定义它各个点的坐标。我们一般使用数组来存储各个顶点的坐标。
OpenGL ES 默认 [0,0,0] (X,Y,Z) 在GLSurfaceView的中心,[1,1,0]在右上角,[-1,-1,0]在左下角。
绘制三角形
在绘制三角形之前,我们必须告诉OpenGL我们正在使用顶点数组。然后我们才使用绘制函数画出三角形。
实验步骤:
1. 添加新的类Triangle
代码如下:
public class Triangle {
public Triangle()
{
float triangleCoords[] = {
// X, Y, Z 这是一个等边三角形
-0.5f, -0.25f, 0,
0.5f, -0.25f, 0,
0.0f, 0.559016994f, 0
};
// 初始化三角形的顶点缓存
ByteBuffer vbb = ByteBuffer.allocateDirect(
// (# of coordinate values * 4 bytes per float)
triangleCoords.length * 4);
vbb.order(ByteOrder.nativeOrder());// 使用设备硬件本身的字节序
triangleVB = vbb.asFloatBuffer(); // 从ByteBuffer中创建一个浮点缓存
triangleVB.put(triangleCoords); // 向浮点缓存中添加顶点坐标
triangleVB.position(0); // 使缓存读第一个坐标
}
public void draw(GL10 gl)
{
gl.glColor4f(0.63671875f, 0.76953125f, 0.22265625f, 0.0f); //设置当前颜色
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleVB);//设置顶点
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);//绘制三角形
}
private FloatBuffer triangleVB;
}
2. 在myGLRenderer类中添加成员privateTriangle mTriangle并在构造函数中初始化。
代码如下:
public myGLRenderer()
{
mTriangle = new Triangle();
}
3. 在myGLRenderer类的onSurfaceCreated()函数最后添加glEnableClientState()方法来启用顶点数组。
代码如下:
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
}
4. 在myGLRenderer类的onDrawFrame()函数最后添加三角形绘制方法。
代码如下:
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
mTriangle.draw(gl);
}
这样,我们便完成了一个平面三角形的绘制。但我们发现这个三角形并不像我们定义的那样是一个等边三角形,这是由于OpenGL总假设我们的屏幕是一个正方形,这样在绘制的时候最终图形会随着屏幕长宽比例的不同而被拉伸。为了得到正确的显示,我们需要将图形投影到正确的位置。这一功能我们在下一节进行实现。
Android设备屏幕通常不是正方形的,而OpenGL总是默认地将正方形坐标系投影到这一设备上,这就导致图形无法按真实比例显示。要解决这一问题,我们可以使用OpenGL 的投影模式和相机视图将图形的坐标进行转换以适应不同的设备显示。
实验步骤:
1. 修改myGLRenderer类的onSurfaceCreated()函数来启用GL10.GL_PROJECTION模式,计算屏幕的长宽比并使用这一比例来转换物体的坐标。
代码如下:
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION); // 设置当前矩阵为投影矩阵
gl.glLoadIdentity(); // 重置矩阵为初始值
gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); // 根据长宽比设置投影矩阵
}
2. 修改myGLRenderer的onDrawFrame()方法,启用MODELVIEW模式,并使用GLU.gluLookAt()来设置视点。
代码如下:
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 设置当前矩阵为模型视图模式
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity(); // reset the matrix to its default state
// 设置视点
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
mTriangle.draw(gl);
}
这样,我们绘制的图形比例就总是正确的,不再受设备的影响而被拉伸变形了。
希望本文所述对大家Android程序设计有所帮助。


猜你喜欢
- 死锁在多线程的情况下,会出现数据不同步情况, 而为了避免这种情况,之前也说了:界区实现方法有两种,一种是用synchronized,一种是用
- 提到输入参数的基本验证(非空、长度、大小、格式…),在以前我们还是通过手写代码,各种if、else、StringUtils.isEmpty、
- 本文实例为大家分享了Android九宫格图片展示的具体代码,供大家参考,具体内容如下XML布局主页面main布局<com.handma
- 一、修改版本和指定生成APK文件名【可选】将项目切换到Project视图,打开app目录下的build.gradle文件1.1 修定软件版本
- 目录 任务和线程的区别: 一、认识Task和Task的基本使用1、认识Task2、创建Task 二、Task的
- MyBatis * 介绍MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是 * 功能。那么 * 拦截MyBatis
- SpringBoot配置文件优先级前面SpringBoot基础有提到,关于SpringBoot配置文件可以是properties或者是yam
- 依赖如下:<dependency> <groupId>org.springframework.boot&
- 前言这周接到一个需求,需要在应用从后台切换到前台时,展示我们的广告。展示页面其实可以复用以前的开屏广告页,唯一的问题就是如何监听应用从后台切
- 解析和遍历一个HTML文档如何解析一个HTML文档:String html = "<html><head>
- 1.获取String osName =System.getProperties().getProperty(&quo
- Thread类相对于线程池中的线程,使用者有更多的控制权。该类允许创建前台线程,设置线程优先级等。Thread类的构造函数重载为接受Thre
- JSON.toJSONString()空字段不忽略修改使用JSON.toJSONString(object)方法,返回的json中,默认会将
- 目录实现效果实现方式实现步骤Blend绘制Path绘制Path绘制直线绘制曲线改变曲线形状移除Path上的线段移除Path上的点Path添加
- public List<string> GetXYFromPic(String jpgPath) {
- 核心思想:“分”与“合”。主体流程先将一个序列分成很多个不能再分割的子序列,将各个子序列分别排序后再将子序列合并。其实就是重复两个步骤:【1
- Hibernate是一个彻底的ORM(Object Relational Mapping,对象关系映射)开源框架。我们先看一下官方文档所给出
- 这篇文章主要来讲讲c#中的泛型,因为泛型在c#中有很重要的位置,对于写出高可读性,高性能的代码有着关键的作用。一、什么是泛型?泛型是 2.0
- java web 实现分页功能,分享给大家,具体如下:使用框架:ssm数据库:oracle话说 oracle 的分页查询比 mysql 复杂
- mybatis-plus想要修改某字段为null问题场景使用mybatis + mybatisPlus进行修改某字段,想要将其设为null,