3D Game Programming withDX11 学习笔记 数学知识总结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3D Game Programming withDX11 学习笔记 数学知识总结相关的知识,希望对你有一定的参考价值。
在图形学中,数学是不可或缺的一部分,所以本书最开始的部分就是数学知识的复习。在图形学中,最常用的是矢量和矩阵,所以我根据前面三个章节的数学知识,总结一下数学知识。
一、矢量
数学中的矢量,拥有方向和长度。其实矢量和点在坐标系中的表示完全一致(笛卡尔坐标系为准),区分矢量和点的关键,我觉得就是做平移。点是不能用平移操作来保证一致的,比如点A(1,2,3)经过平移矢量(1,2,3)后就是B(2,4,6),此时就是一个新的点。但是矢量经过相同平移操作后,还是矢量(1,2,3),这是因为矢量表示的是 vector head相对于 vector tail的偏移,平移操作并不会改变这种偏移。
在矢量中一个关键就是坐标系,数学中的坐标系主要分为左手坐标系和右手坐标系。我时不时会弄混左手和右手坐标系,后来做了一个快捷的记忆:我的头是y方向,右手伸出来是x方向,那么如果z方向向前是正方向,那我就处于左手坐标系; 如果我的z方向向后是正方向,那我就处于右手坐标系。所以看起来我的脸决定了我的坐标系:)
矢量的数学操作主要是:加、减、乘三种操作,如果算上求模(求长度),那就是四种操作。A=(xa,ya,za), B=(xb,yb,zb)
加:A + B = (xa+xb, ya+yb, za+zb)
减:A - B = (xa-xb, ya-yb, za-zb)
乘:A *B = xaxb+yayb+zazb
模:||A||2= xa2 + ya2+za2
细心的会发现矢量乘的结果变成了一个数,确实,最终的结果就是一个数,其本质就是一种映射或者投影,表示的是A矢量在B矢量方向上的投影长度,矢量的乘可以用公式表示为:
A *B = ||A|| *||B|| * sinθ,其中θ为两个矢量的夹角(由于不熟悉博客的数学公式添加,只有先这写着了,后面熟练了再修改吧)
矢量中最常见的操作就是归一化,比如有一个矢量的序列{V0,v1,V2...},如何将这些矢量归一化为互相垂直的单位矢量?
这儿引入投影的一个表示:projn(V)= v . n/||n||, 表示的是v在n的单位矢量上的投影,那么对于矢量序列,我们可以这样进行正交归一化:
1)v0, v1,v2.......
2) w0 = v0;
3) w1 = v1 - projw0(v1)
4) w2 = v2 - projw0(v2) - projw1(v2)
........
根据上面的规律,可以得到正交化的规律:将当前矢量(第一个除外)去除在前面所有矢量上的分量(投影),得到的就是与前面各个适量正交的矢量。
最后我们将正交化的矢量进行归一化操作,即可得到一组正交归一化矢量序列。
矢量的最后一个知识点是:矢量的叉积,与矢量点积得到一个投影的结果值不同,矢量的叉积得到的是一个矢量,基本公式为:
AXB = (yazb -zayb, zaxb - xazb, xayb - yaxb),
单看公式看不出规律,不过可以这样理解:xyz, yzx, zxy,分别去掉x, y , z,最后的结果就是三个分量的第一项,然后交换得到三个分量需要减去的第二项
矢量的叉积的实际意义,就是求得一个和A/B两个矢量都垂直的矢量,这在图形学中,可以用来求解游戏对象的一些常用矢量, 比如上(up)/下(down)/左(left)/右(right)/前(forward)/后(back)这些矢量都是互相垂直的,可以利用矢量的叉积得到。注意在笛卡尔坐标系中,矢量的叉积都是左手定律决定方向的,所以AXB和BXA是刚好方向相反的两个等长矢量。
二、矩阵
在图形学中,我们会绘制各种各样的游戏实例,这些实例都是用基本的点(verts)和相关的贴图(textures)、材质(material)等共同设置渲染状态的。对于基本的顶点,常常需要做的一个基本操作就是变换:平移、旋转、缩放等。这些变换操作对应的就是矩阵的变换。
矩阵的定义就不再多说,就是一个nxm的同类元素的集合,通常这个元素就是数字(也可以为其他,这儿不再扩展)。
矩阵最基本的操作可以分为: 矩阵的乘, 矩阵的转置, 矩阵的行列式, 矩阵的逆
矩阵的乘积: C = AB ≠BA
C矩阵中的每个元素是Cij是A矩阵的i行和B矩阵j列的对应点积的结果,基于此可以得到A矩阵的列数和B矩阵的行数是相等的(不然怎么做点积....)
矩阵的转置AT,就是将矩阵的行和列对换,说的简单点就是一列一列的变,新的每列是以前矩阵的每行竖着排列(感觉就是重新排队)
矩阵的行列式,是一个比较重要的点,Aij作为行列式的代指,就是去除A矩阵的i行和j列后得到的行列式计算结果,整体的公式为:
detA = ∑j=1n A1j(-1)i+jdetA1j
可以看出矩阵的行列式计算就是一个递归的计算过程,一般在图形学中的计算不会超过4x4的维度,所以可以用笔算的方式来计算这些矩阵的行列式:)
基于行列式,可以得到一个新的矩阵: 邻接矩阵A*,基于基本的矩阵A可以得到一个新的矩阵CA,其中的元素Cij = (-1)i+jdetAij,则可以定义邻接矩阵为:
A* = CAT 基于邻接矩阵,我们可以得到矩阵A的逆矩阵A-1 :A-1 = A*/detA
三、变换矩阵
基于矩阵的定义,我们可以将图形学中的一些常见的变换转化为对应的变换矩阵,这样在对点或者矢量进行变换的时候,其对应的数学操作就是一个变换矩阵的操作。基本的变换矩阵可以分为:缩放矩阵, 平移矩阵,旋转矩阵。
对于变换矩阵对矢量的作用,可以这样理解:u =(x,y,z) = xi + yj + zk, 那么一个变换操作可以表示为τ(u) = τ(xi + yj + zk) = xτ(i) + yτ(j) + zτ(k) = [x y z] [τ(i) τ(j) τ(k)]T = uA
所以说的直白点,就是用矩阵A来表示一种变换操作。那么具体如何表示呢?可以分拆为基本矩阵,然后进行合并即可。
1、缩放矩阵S
拆开用行向量表示为S(i) = (sx .1, sy.0, sz.0), S(j) = (sx .0, sy.1, sz.0),S(k) = (sx .0, sy.0, sz.1)
则缩放矩阵可以表示为S = [si , sj, sk]T, si = (sx,0,0), sj = (0,sy,0), sk = (0,0,sz)
2、旋转矩阵R
其实旋转矩阵是三个矩阵中相对比较难的矩阵,这儿给出一个旋转公式:
Rn(V) = projn(v) + Rn(V⊥)
= (n v) n + cosθ V⊥ + sinθ (n x v)
= cosθ V + (1 - cosθ)(n v)n + sinθ(n x v)
具体的常用的三个旋转矩阵可以列出来:
3、平移矩阵T
平移矩阵比较简单,就不做推算,直接给出结果即可:
综合三种基本矩阵,我们可以进行组合得到一个较为复杂的变换矩阵。不过在图形学的计算中,对于三种矩阵的排序有一定的讲究,一般先用缩放矩阵S对当前的变换对象进行缩放,然后用旋转矩阵R进行旋转操作,最后用平移矩阵T进行平移操作,所以可以归并为SRT矩阵。
总结:经过基本的矢量,矩阵和变换的数学知识总结后,接下来就要进入正式的图形学知识了,我会在后面持续更新~
以上是关于3D Game Programming withDX11 学习笔记 数学知识总结的主要内容,如果未能解决你的问题,请参考以下文章
图形学数学基础书籍3D Math Primer for Graphics and Game Development,Mathematics for 3D Game Programming and Co
图形学数学基础书籍3D Math Primer for Graphics and Game Development,Mathematics for 3D Game Programming and Co
图形学数学基础书籍3D Math Primer for Graphics and Game Development,Mathematics for 3D Game Programming and Co
Dynamic programming-polygon game
解题报告——Block Game(思维题)(Benelux Algorithm Programming Contest 2016 Preliminary)(计蒜客)
AtCoder AISing Programming Contest 2019 Task D. Nearest Card Game