第二章 A 3D/Math Primer_left-handed and right-handed radar systems-程序员宅基地

技术标签: Rendering with DirectX && HLSL  

第二章 A 3D/Math Primer

本章介绍3D图形学的数学知识。借用一句Douglas Adams的名言,“别慌张”。我们会讲述vectors(向量),Matrix(矩阵),coordinate systems(坐标系统),transformations(变换),以及DirectXMath数学库。即使你已经很熟悉线性代数的知识,我也希望你能审核一下DirectX相关的内容。否则,做个深呼吸,坚持学习下去。


Vectors

你可能还记得高中物理课上学习的标量和向量的定义。标量是一个表示大小的量;向量是描述大小和方向的量。在3D图形学中Vectors有多种形式,可以表示速度,力量,方向或者简单的三维空间坐标点。
在几何数学中,可以把vector看作一个箭头;vector的长度即为大小,线段的指向即为vector的方向。在这种定义下,vector的尾部没有固定的位置。因此,判断两个vector相等只要比较他们的长度和方向是否都相等。但是,如果把vector的起点固定在坐标系统的原点,那么vector就可以表示成坐标系统中的一个点,该点指定了vector对应坐标轴的尺寸。在3D空间中,使用x,y,z坐标轴表示一个vector。比如点(2,5,8)表示一个距离原点对应于x轴偏移2个单位,y轴偏移5个单位,z轴偏移8个单位的vector。图2.1解释了2D中的情况。

图2.1 向量的表示。

Left-Handed and Right-Handed Coordinate Systems

图2.1显示了一个二维笛卡尔坐标系统(Cartesian coordinate system),x轴指向水平方向,y轴指向垂直方向,分别以向右和向上为正向。在三维空间中,z轴与x轴和y轴相互正交(垂直),根据左手或右手坐标系以指向屏幕里面或屏幕外面作为正向。在左手坐标系中,z轴朝向屏幕里面为正向,而在右手坐标系中朝向屏幕外面为正向。如何判断左右手坐标系有一个非常好的记忆方法,在你的眼前握住右手,保持拇指指向x轴的正向,食指指向y轴的正向,中指的指向即为z轴的正向也即朝向屏幕外面;左手刚好相反。图2.2描述了这两种坐标系。

图2.2 A mnemonic for 3D coordinate system hadedness。

Base Vector Operations

向量的加法和减法是两个向量各个部分都进行加减法,也就是两个向量中的各个元素对应的进行运算。例如,有两个向量a = (ax,ay,az)和b = (bx,by,bz),执行加法或减法产生向量c,依据表2.1执行这些操作。

表2.1 Basic Vector Operations

同理,乘法和除法是一个标量和一个向量的各个元素执行乘除法。下面是一个标量和向量相乘的例子:
4 * a = (4ax,4ay,4az)

Vector Length

vector的长度(或者大小)使用Pythagorean Theorem(勾股定理)进行计算。具体的使用以下公式(对于一个3维vector):

长度为1的vector称为unit vector(单位向量)。在只需要vector的方向而不用长度的情况下,unit vector是非常有用的。把一个vector的长度转变成1称为向量的标准化;标准化是通过把vector除以它的大小实现的。公式形式如下:


Dot Product(点积)

两个vectors的dot product是向量各个部分元素乘积的和。公式为:
a•b=(ax *bx)+(ay *by)+(az *bz)

这产生一个标量值,因些dot product也称为scalar product(或者inner product)。根据向量长度的定义,可以使用向量与其自身的点积的平方根来计算向量的长度。
在几何数学中,点积表示了两个向量之间的角度。公式为:
a • b = ||a||*||b|| * cos(θ)
θ即为向量a和b的夹角。如果向量a和b都已经标准化,点积可以简化为:
a • b = cos(θ)
根据这个公式,可以总结如下几点:
如果a • b  > 0,两个向量的夹角小于90度。
如果a • b  < 0,两个向量的夹角大于90度。
如果a • b  = 0,两个向量相互垂直。
在后面的章节中,你会发现点积在计算机图形学中有多种多样的应用。比如,在光照计算中可以用点积来计算照射表面和光源之间的角度。在第二部分,“Shader Authoring with HLSL”将会详细讲解。

Cross Product(叉积)

Cross Product是另一个非常有用的向量运算。两个向量的叉积得到一个与这两个向量都正交的第三个向量。叉积的公式为:
a × b = (ay * bz – az * by, az * bx – ax * bz, ax * by – ay * bx)
叉积可以用于计算一个triangle的法向量(也就是triangle的朝向)。

Matrix

一个m×n矩阵是一个m行,n列的二维数组。比如一个4×1矩阵,有4行1列,一个2×3矩阵有两行3列,如下所示:

在矩阵C中,指出了矩阵中每个元素对应的下标。只有一个单一的行或列的矩阵有时被称为行向量和列向量。具有相同行数和列数的矩阵称为方阵。在3D图形学中,4×4方阵应用最广泛。

Basic Matrix Operations

你可以使用矩阵执行一些基本的算术运算。在向量中,是对两个向量的逐个元素执行加减法。因些两个矩阵必要具有相同的行数和列数才可以做加减法。标量乘法同样是进行逐个元素运算,把标量与矩阵中的每个元素相乘。但是,矩阵的乘法却有点不一样。

Matrix Multiplication

对于矩阵乘法,一个具有n列的矩阵只能和一个具有n行的矩阵相乘。在所得到的矩阵中,每一个元素都是第一个矩阵的行与第二个矩阵对应的列进行dot product计算出来的。如下公式所示,如果把矩阵A的每一行作为行向量,矩阵B的每一列作为列向量,可以定义乘积矩阵元素为:

图2.3 illustrates this process。

图2.3 Matrix multiplication。

如下所示:

矩阵A是一个两行3列的矩阵,矩阵B一个3行两列的矩阵。矩阵B的行数与A的列数相同,因此可以进行矩阵乘法。相乘的结果一个2×3矩阵,计算如下:

需要注意的是矩阵乘法是不满足交换律(不能交换相乘,也无法得到相同的乘积)。事实,一般情况下定义矩阵乘法A * B,对于B * A的情况是没有定义的,比如一个3×3矩阵乘以一个2×3矩阵。

Transposition

矩阵的转置是通过把矩阵的元素依据主对角线反转得到的。对于一个方阵是很容易理解的,如下示例所述:

另外一种转置矩阵的方法是交换矩阵的行和列。这种很容易理解,特别是对于行向量和列向量,或者非方阵。例如:


Row-Major and Column-Major Order

处理矩阵时,必须考虑如何在计算机内存中存储矩阵。Direct3D以行优先的顺序存储矩阵,也就是说如果存储到一段连接内存中,是以一行一行的方式排列在内存中。这也是C语言中多维数组的存储格式。如下示例,是一个2×3矩阵以行优先顺序连接存储的形式:

相反,同样的矩阵以列优先顺序存储在内存中的形式为:
Column − Major: 1 4 2 5 3 6
把一个行优先矩阵转成一个列优先矩阵涉及矩阵的转置(反之亦然)。如何存储矩阵会带来性能上的影响,而且不同的存储方法依赖于特定的顺序。将在第4章,“Hello,Shaders!”再讨论。

The Identity Matrix

单位矩阵是一个特殊的方阵,除了主对角线元素都是1之外,其他的元素都为0。例如一个4×4的单个矩阵定义为:

相对矩阵乘法来说,单位矩阵就是数字1。换句话说,把一个矩阵与单位矩阵相乘结果该矩阵本身。

Transformations

前面已经讲过,vectors描述了3D空间中的方向和位置。比如,3D triangles中vertices的坐标位置就是用vectors存储的,两样法向量也是。但是在图形应用程序中vectors并不会一直保持不变。你的3D objects可能会在一个场景里移动,伸展,收缩,转动。专业的描述,位移称为translation(平移),伸展,收缩称为scaling(缩放),转动称为rotation(旋转)。这些操作统称为transformations(变换)。此外,想要把objects显示到屏幕上,需要经过多个参考坐标系的变换。矩阵将会用于把vectors的位置和方向从一个坐标系变换到另一个坐标系,同样用于translation,scaling和rotation。

Homogeneous Coordinates(齐次坐标)

在深入学习矩阵变换之前,需要特别注意的是我们将会使用齐次坐标。这种坐标系支持把translation,scaling,rotation操作合并到一个4×4矩阵。矩阵乘法满足结合律,因此可以把所有这些变换用一个4×4矩阵表示。在齐次坐标系中,每个坐标点有四个部分,分别为x,y,z,w。xyz坐标就是普通的3D坐标,坐标表示一个点的时候w为1,表示为方向的时候w为0。正如你所知道的,w = 0使得方向向量不能进行translation操作,这是非常有用的,因为单纯的方向向量在3D空间中是没有指明位置的。

Scaling

向量变换即执行向量-矩阵乘法,也就是一个矩阵乘以一个行向量或列向量。比如,3D缩放矩阵定义为:

主对角线上的数值表示对应于x,y,z轴的缩放因子。如果这些数据都相等,向量会等比例缩放。单位矩阵与此相似,相当于主对角线上数值都为1的缩放矩阵。
如下示例,使用一个非等比例的缩放矩阵变换一个点向量。点A的坐标为(-4,2,6,1)。其中第4列(w分量为1)是必须的,因为缩放矩阵有4列。

Translation

Translation主要是沿着x,y,z轴移动object。平移矩阵定义如下:

以下示例描述了,一个点向量沿着x轴正向平移10个单位,沿y轴正向平移5个单位,没z的负向平移6个单位。如果向量的w分量为0(此时表示一个方向向量),那么平移变换没有任何效果。

Rotation

Rotation更复杂一点,因为每个坐标轴都对应一个不同的旋转矩阵。

以下示例描述了,把点(1,0,0)绕z轴逆时针方向旋转90度(π/2弧度)。

Matrix Concatenation(矩阵串联)

可以把多种变换矩阵串连成单个变换矩阵,而不是单独应用每一种变换。比如,缩放,旋转,平移矩阵可以组合成:
W = S * R * T
通过把缩放,旋转,平移串连成一个矩阵可以只需一步完成点向量变换。但是串连的顺序非常重要。矩阵串连是从左到右进行相乘,而且是不可交换的。例如,要渲染地球环绕太阳运行,地球相对太阳平移,还要绕着太阳旋转,那么串连矩阵也要按这种顺序执行。然而,如果还要模拟地球自转,那么在执行“公转”变换前要先执行自转的旋转操作。在这种情景下,完整的矩阵串连会是这样:
W = Raxial * T * Rorbit
只要明确从左到右要执行变换的顺序,那么可以串连任意数量的单个变换。

Changing Coordinates Systems

变换矩阵除了用于scaling,translation,rotation外,还可以用于把一个向量从一个坐标系转移到另一个坐标系。

Object Space and World Space

通常可以使用Autodesk Maya或者3D Studio Max等建模软件创建3D模型。模型本身所处的坐标系称为object space(或model space)。你的场景里可能包含成百上千个独立的模型,但是这些模型很少会作为一个整体去创建。而是分别存储在一个单独的文件中,而且它们的vertices只与模型的原点有关,与别的3D模型都没有关联。为了使用这些模型进行交互,必须共用一个通用的坐标系,也就是必须处于同一个世界中。因此,必须把这些模型从object space变换到world space。

World transformation matrix(世界坐标变换矩阵)由scale,translation,和rotation三个矩阵串联而成。只需要把3D模型的每个vertex与world matrix相乘就可以得到模型所处的world space。

View Space

World space之后,object就变换到view space(或者camera space),这是一个相对于虚拟camera的坐标系。Camera的属性中定义了一个确定哪些object可见的空间体。这个空间体也被称为view frustum(视域体),如图2.4。View matrix用于把vectors从世界空间变换到视图空间,该矩阵由camera的位置(世界空间中),camera的朝向向量,以及一个表示朝向向上的向量组合计算得出的。在第三部分,“Rendering with DirectX”,将会讲角使用DirectX API创建view matrix。

图2.4 An illustration of the view frustum specified by the properties of a virtual camera.

Projection Space

Object space,world space和view space都是三维坐标系。但是,计算机屏幕却是二维的,projection matrix就是把3D几何图形投影到2D显示。在这个阶段,就可以描述深度的概念了,比如与屏幕越近的object比那些距屏幕较远的object看起来要大。这就是所谓的透视投影,与正交投影完全相反,正交投影的情况下所有object看起来与camera的距离都一样,不管实际的位置如何。
投影矩阵定义了视域体,并包含一个near plane(近裁剪面)和far plane(远裁剪面),一个垂直的视域,以及一个宽高比。在camera的和near plane之间的object是不可见的,超出far plane的object也不可见。就好比你的鼻子(near plane)和地平线(far plane)。视域定义了视域体的范围,宽高比即是显示器(或者窗口)的宽度除以高度。和view matrix一样,projection matrix也是调用DirectX API计算的。
World,view,projection space的变换都是在vertex shader阶段执行,但是需要你自己实现。可以单独使用每一种变换,也可以把这三个变换矩阵串联成一个world-view-projection矩阵,或者叫WVP。经过与投影矩阵相乘之后,所有的坐标都处于projection space(或者叫homogeneous clip space)中。
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/chenjinxian_3D/article/details/51771568

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签