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多态实战应用指南

《从基础到高阶详解Python多态实战应用指南》这篇文章主要从基础到高阶为大家详细介绍Python中多态的相关应用与技巧,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、多态的本质:python的“鸭子类型”哲学二、多态的三大实战场景场景1:数据处理管道——统一处理不同数据格式

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

MySQL数据类型与表操作全指南( 从基础到高级实践)

《MySQL数据类型与表操作全指南(从基础到高级实践)》本文详解MySQL数据类型分类(数值、日期/时间、字符串)及表操作(创建、修改、维护),涵盖优化技巧如数据类型选择、备份、分区,强调规范设计与... 目录mysql数据类型详解数值类型日期时间类型字符串类型表操作全解析创建表修改表结构添加列修改列删除列

深入理解go中interface机制

《深入理解go中interface机制》本文主要介绍了深入理解go中interface机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前言interface使用类型判断总结前言go的interface是一组method的集合,不

Python 函数详解:从基础语法到高级使用技巧

《Python函数详解:从基础语法到高级使用技巧》本文基于实例代码,全面讲解Python函数的定义、参数传递、变量作用域及类型标注等知识点,帮助初学者快速掌握函数的使用技巧,感兴趣的朋友跟随小编一起... 目录一、函数的基本概念与作用二、函数的定义与调用1. 无参函数2. 带参函数3. 带返回值的函数4.

深入解析Java NIO在高并发场景下的性能优化实践指南

《深入解析JavaNIO在高并发场景下的性能优化实践指南》随着互联网业务不断演进,对高并发、低延时网络服务的需求日益增长,本文将深入解析JavaNIO在高并发场景下的性能优化方法,希望对大家有所帮助... 目录简介一、技术背景与应用场景二、核心原理深入分析2.1 Selector多路复用2.2 Buffer

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

Java Spring的依赖注入理解及@Autowired用法示例详解

《JavaSpring的依赖注入理解及@Autowired用法示例详解》文章介绍了Spring依赖注入(DI)的概念、三种实现方式(构造器、Setter、字段注入),区分了@Autowired(注入... 目录一、什么是依赖注入(DI)?1. 定义2. 举个例子二、依赖注入的几种方式1. 构造器注入(Con

深入理解Go语言中二维切片的使用

《深入理解Go语言中二维切片的使用》本文深入讲解了Go语言中二维切片的概念与应用,用于表示矩阵、表格等二维数据结构,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录引言二维切片的基本概念定义创建二维切片二维切片的操作访问元素修改元素遍历二维切片二维切片的动态调整追加行动态