OpenGLES Android篇零基础系列(二):OpenGL各坐标系及模型矩阵(ModelViewMatrix),投影矩阵(ProjectionMatrix)等的深入理解

本文主要是介绍OpenGLES Android篇零基础系列(二):OpenGL各坐标系及模型矩阵(ModelViewMatrix),投影矩阵(ProjectionMatrix)等的深入理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一篇我们粗略的介绍了下GLES20 中 GLSurfaceView以及Render接口的使用。
对于三角形顶点坐标的定义并没有做出注释,其实在官方的ApiDemo中,它也是赤裸裸的,一个注释都没有,且代码写得一点都不敢恭维,不知道那位同行现在是不是还在google里面。下面贴出一小段官方的ApiDemo中的代码,一起鉴赏鉴赏:

 private static final int FLOAT_SIZE_BYTES = 4;private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;private final float[] mTriangleVerticesData = {// X, Y, Z, U, V-1.0f, -0.5f, 0, 0.0f, 0.5f,1.0f, -0.5f, 0, 1.0f, 0.5f,0.0f,  1.0f, 0, 0.0f,  1.0f };

如上,你们能看懂吗?在定义三角形顶点坐标数据时,仅仅只是简单粗暴的注释X,Y,Z,U,V,其中X,Y,Z好理解,可这U,V又是什么呢?X,Y,Z,U,V它们之间又有什么联系呢?

如果仅仅只是想从ApiDemo里面去研究,去搞懂它们是什么,怎么用,那估计不是一天两天的事,还得从浩瀚的网络中去查找。

正文:坐标系

OpenGL有6种坐标系,分别如下:

  • 1,物体或模型坐标系(Object or model coordinates);
  • 2,世界坐标系(World coordinates)
  • 3,眼坐标或相机坐标(Eye (or Camera) coordinates)
  • 4,裁剪坐标系(Clip coordinates)
  • 5,标准设备坐标系(Normalized device coordinates)
  • 6,屏幕坐标系(Window (or screen) coordinates)
    除了上面6种外,OpenGL还存在一种假想坐标系纹理坐标系,这个坐标系是不存在的,它其实是一系列变换矩阵的结果,比如它能使顶点从物体或模型坐标系变换到世界坐标系

从object coordainates到world coordinates再到camera coordinate的变换,在OpenGL中统一称为model-view转换,初始化的时候,object coordinates和world coordinates还有camera coordinates坐标重合在原点,变换矩阵都为Identity,所以在OpenGL中用glLoadIdentity()初始化变换矩阵栈。model-view matix转换points,vectorsd到camera坐标系。

OpenGL 的重要功能之一就是将三维的世界坐标经过变换、投影等计算,最终算出它在显示设备上对应的位置,这个位置就称为设备坐标。在屏幕、打印机等设备上的坐标是二维坐标。值得一提的是,OpenGL可以只使用设备的一部分进行绘制,这个部分称为视区或视口(viewport)。投影得到的是视区内的坐标(投影坐标),从投影坐标到设备坐标的计算过程就是设备变换了。

我们在OpenGL ES中常用到的几种坐标系:世界坐标系、物体坐标系、设备坐标系、眼坐标系当然还有假想的纹理坐标系

一、屏幕坐标系

对于移动设备来说,我们都知道,左上角为坐标原点,向右为X轴,向下为Y轴。如下图(图画的丑了点,先忍忍啊^_^):
这里写图片描述

二、世界坐标系

这个世界坐标系是针对OpenGL来说明的。即三维坐标系X,Y,Z.
它有一个漂亮的学名:右手笛卡尔坐标系统,这个坐标系常用来描述物体及光源的位置。
在移动设备中,屏幕中心为坐标三点,水平向右为X轴,在原点垂直X轴向上为Y轴,在原点垂直X,Y轴指向屏幕外为Z轴(正面对手机屏幕,直戳你眼睛的就是Z轴),同样如下图:
这里写图片描述

将物体放到场景中也就是将物体平移到特定位置、旋转一定角度,这些操作就是坐标变换。OpenGL中提供了glTranslate*/glRotate*/glScale*三条坐标变换命令,利用OpenGL的矩阵运算命令,则可以实现任意复杂的坐标变换。
在这里还要提一个重要的概念:坐标变换矩阵栈(ModelView)

坐标变换矩阵栈

用来存储一系列的变换矩阵,栈顶就是当前坐标的变换矩阵,进入OpenGL管道的每个坐标(齐次坐标)都会先乘上这个矩阵,结果才是对应点在场景中的世界坐标。OpenGL中的坐标变换都是通过矩阵运算完成的。
如图:
这里写图片描述
ModelViewMatrix:模型矩阵
ProjectionMatrix:投影矩阵

三、纹理坐标系

通过上一节,我们知道,纹理是图片,视频等的一种渲染方式,图片只有通过纹理才能加载到GLES中。
因此纹理坐标系是指图片,视频等在手机屏幕上的坐标系,即U,V也有叫ST。该坐标系是一种假想坐标系,并不真正存在的,只是变换矩阵的结果。下面就统一叫UV坐标系。
当应用初始化时,UV坐标系与三维坐标系(世界坐标系)重合。
我们要注意的是,在OpenGL绘制过程中,它是可以选择绘制模式的,比如:点,线,面,且都是坐标集合里面进行顺序绘制的。i.e.:

private final float[] mTriangleVerticesData = {// X, Y, Z,-1.0f, -0.5f, 0, //11.0f, -0.5f, 0, //20.0f,  1.0f, 0, //3};

当我们以纹理的形式加载一个图片到OpenGL中时,如何让它显示在世界坐标系中呢?这时就用到了纹理贴图的方式(即根据在世界坐标系中绘制顶点的先后顺序,把UV坐标系中的坐标与其一一对应),画图更加直接(从网上copy的图,在此感谢):

倒立的图片

四、物体坐标系

物体坐标系是以物体的某一个点为原点来建立的三维坐标系(世界坐标系)。仅针对该物体。物体放到场景中时,各部分经历的坐标变换矩阵相同,相对位置不变,所以可视为一个整体

五、眼坐标系或相机坐标系

以视点为原点,以视线的方向为Z+轴正方向的坐标系中的方向。OpenGL管道会将世界坐标先变换到眼坐标,然后进行裁剪,只有在视线范围(视见体)之内的场景才会进入下一阶段的计算。

六、裁剪坐标系

由眼坐标可知,OpenGL管道首先会将目标从世界坐标变换到眼坐标,然后对视线范围外的部分进行裁剪。
裁剪过程中用到投影变换矩阵栈(ProjectionMatrix),栈顶矩阵就是当前投影变换矩阵,负责将场景各坐标变换到眼坐标,由所得到的结果是裁剪后的场景部分,称为裁剪坐标

我们上面说到了ModelViewMatrix 与ProjectionMatrix两个矩阵栈,那矩阵栈是怎么切换的呢?
用函数:glMatrixMode(GL_MODELVIEWING或GL_PROJECTION);本命令执行后参数所指矩阵栈就成为当前矩阵栈,以后的矩阵栈操纵命令将作用于它。
紧接着glMatrixMode()就是初始化矩阵,我们在上面也讲到,所有矩阵都为Identity,所以用方法glLoadIdentity()初始化矩阵。

上一节

参考资料

OpenGL坐标系介绍
OpenGL中各种坐标系的理解
Android OpenGL20 世界坐标系,屏幕坐标系,纹理坐标系
Android OpenGL 坐标系
详解OpenGL的坐标系、投影和几何变换-矩阵压栈思想/矩阵列式存储
OpenGL 矩阵变换(讲的太好了~!)

这篇关于OpenGLES Android篇零基础系列(二):OpenGL各坐标系及模型矩阵(ModelViewMatrix),投影矩阵(ProjectionMatrix)等的深入理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1018165

相关文章

Python基础语法中defaultdict的使用小结

《Python基础语法中defaultdict的使用小结》Python的defaultdict是collections模块中提供的一种特殊的字典类型,它与普通的字典(dict)有着相似的功能,本文主要... 目录示例1示例2python的defaultdict是collections模块中提供的一种特殊的字

在Android平台上实现消息推送功能

《在Android平台上实现消息推送功能》随着移动互联网应用的飞速发展,消息推送已成为移动应用中不可或缺的功能,在Android平台上,实现消息推送涉及到服务端的消息发送、客户端的消息接收、通知渠道(... 目录一、项目概述二、相关知识介绍2.1 消息推送的基本原理2.2 Firebase Cloud Me

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

Android中Dialog的使用详解

《Android中Dialog的使用详解》Dialog(对话框)是Android中常用的UI组件,用于临时显示重要信息或获取用户输入,本文给大家介绍Android中Dialog的使用,感兴趣的朋友一起... 目录android中Dialog的使用详解1. 基本Dialog类型1.1 AlertDialog(

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

C#基础之委托详解(Delegate)

《C#基础之委托详解(Delegate)》:本文主要介绍C#基础之委托(Delegate),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 委托定义2. 委托实例化3. 多播委托(Multicast Delegates)4. 委托的用途事件处理回调函数LINQ

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda