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

相关文章

Java利用Spire.Doc for Java实现在模板的基础上创建Word文档

《Java利用Spire.DocforJava实现在模板的基础上创建Word文档》在日常开发中,我们经常需要根据特定数据动态生成Word文档,本文将深入探讨如何利用强大的Java库Spire.Do... 目录1. Spire.Doc for Java 库介绍与安装特点与优势Maven 依赖配置2. 通过替换

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

2025最新版Android Studio安装及组件配置教程(SDK、JDK、Gradle)

《2025最新版AndroidStudio安装及组件配置教程(SDK、JDK、Gradle)》:本文主要介绍2025最新版AndroidStudio安装及组件配置(SDK、JDK、Gradle... 目录原生 android 简介Android Studio必备组件一、Android Studio安装二、A

JavaScript装饰器从基础到实战教程

《JavaScript装饰器从基础到实战教程》装饰器是js中一种声明式语法特性,用于在不修改原始代码的情况下,动态扩展类、方法、属性或参数的行为,本文将从基础概念入手,逐步讲解装饰器的类型、用法、进阶... 目录一、装饰器基础概念1.1 什么是装饰器?1.2 装饰器的语法1.3 装饰器的执行时机二、装饰器的

Java JAR 启动内存参数配置指南(从基础设置到性能优化)

《JavaJAR启动内存参数配置指南(从基础设置到性能优化)》在启动Java可执行JAR文件时,合理配置JVM内存参数是保障应用稳定性和性能的关键,本文将系统讲解如何通过命令行参数、环境变量等方式... 目录一、核心内存参数详解1.1 堆内存配置1.2 元空间配置(MetASPace)1.3 线程栈配置1.

Java领域模型示例详解

《Java领域模型示例详解》本文介绍了Java领域模型(POJO/Entity/VO/DTO/BO)的定义、用途和区别,强调了它们在不同场景下的角色和使用场景,文章还通过一个流程示例展示了各模型如何协... 目录Java领域模型(POJO / Entity / VO/ DTO / BO)一、为什么需要领域模

GO语言zap日志库理解和使用方法示例

《GO语言zap日志库理解和使用方法示例》Zap是一个高性能、结构化日志库,专为Go语言设计,它由Uber开源,并且在Go社区中非常受欢迎,:本文主要介绍GO语言zap日志库理解和使用方法的相关资... 目录1. zap日志库介绍2.安装zap库3.配置日志记录器3.1 Logger3.2 Sugared

深入理解Redis线程模型的原理及使用

《深入理解Redis线程模型的原理及使用》Redis的线程模型整体还是多线程的,只是后台执行指令的核心线程是单线程的,整个线程模型可以理解为还是以单线程为主,基于这种单线程为主的线程模型,不同客户端的... 目录1 Redis是单线程www.chinasem.cn还是多线程2 Redis如何保证指令原子性2.

深入理解MySQL流模式

《深入理解MySQL流模式》MySQL的Binlog流模式是一种实时读取二进制日志的技术,允许下游系统几乎无延迟地获取数据库变更事件,适用于需要极低延迟复制的场景,感兴趣的可以了解一下... 目录核心概念一句话总结1. 背景知识:什么是 Binlog?2. 传统方式 vs. 流模式传统文件方式 (非流式)流

深入理解Go之==的使用

《深入理解Go之==的使用》本文主要介绍了深入理解Go之==的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录概述类型基本类型复合类型引用类型接口类型使用type定义的类型不可比较性谈谈map总结概述相信==判等操作,大