首页 > 代码库 > 剑英陪你玩转图形学 (三)归去来

剑英陪你玩转图形学 (三)归去来

今天的主题是数学,尤其是要把向量说一说

开篇废话

王全安又进去了,最近不太好引用岛国文化来开篇,来点民族的。

恰逢中秋,让我想起了一首脍炙人口的水调歌头。

 

明月几时有,把酒问群友。
不知这次版本,今晚能出否。
我欲推倒重构,又恐项目经理,深夜对我吼。
增删改代码,好像没保存…..

深呼吸,看屏幕,泪在流。
不应有恨,谁没忘记存代码?
人有悲欢离合,码有丢失冲突,此事古难全。
但愿人长久,leader别发现。

 

小伙伴们中秋都是怎么过的?有没有项目经理深吼你呢?

欢迎来德云社听相声,哦不,来听李总讲故事,好像也不对,我们是一个玩代码系列,图形学方向。

 

图形学是个综合学科,他的很大一部分都是3D数学。

图形学用的3D数学,客户端逻辑用的3D数学,有什么不一样的?

我不知道分界线在哪里,我只知道做游戏客户端,3D数学无处不在。

既然躲不开,就让我们来好好享受一番吧。

快速提高班

现在,教大家一些快速提高自己业务(zhuangbi)水平的方法。

今天讲提高业务水平的最后一个要诀,悟。

悟是你一定要钻研出一些你自己的观点。百度搜不到的东西。

这样和别人交流业务的时候,可以极大的提高别人对你的印象。

忍、持、悟。这次已经把全套秘籍都教给你了,让我们来回顾一下。

忍:不要主动去教别人,别人有疑惑会找你,主动去教容易招致反感。

持:要有选择的回答,拿不准的东西不要乱答,提升准确性。

悟:要有自己的观点。

学会这一套,业务(zhuangbi)水平就会一发不可收拾。

 

现在给大家简单的介绍一下Unity3D的数学库,对提升业务水平有帮助哦。

基本数学工具:

UnityEngine.Mathf

集中了float型数值计算的相关数学函数的静态类型,比如cos sin sqlr

相对System.Math 更加实用,因为我们最长使用的数据类型是float,Mathf会更方便。

UnityEngine.Random

随机数产生器,和System.Random 使用方法不同,原理一样,只是静态化了,可以少写两行。

特定的数学工具:

特定的数学工具对应的数学函数就在这个类型内

Vector2 Vector3 Vector4

表示向量或者顶点,他们的相关计算函数都在Vector2 Vector3 Vector4内。

比如Vector3.Cross 叉积 Vector3.Dot 点积

Rect

表示一个2D矩形区域

Bounds

表示一个3D的方块区域

Matrix4X4

表示矩阵,矩阵用土的掉渣的方式表示一个空间变换,旋转跳跃我眯着眼。

Quaternion

表示四元数,四元数用土的掉渣的方式表示一个旋转,这个我们文后会介绍。

常用的数学工具就这些,当然还有float,这个我们最最常用的数学工具。

理解计算的意义

说到数学,对很多人来说是帮助睡眠小助手。

睡前两行数学书,包你一夜好睡眠。

确实对着那些名词,是会让人混混欲睡的。

现在开始上图片。

上错图了,不好意思

阿基米德说:给我一个支点,我就能撬动地球

卡马克说:给我一个像素,我就能弄一个3D引擎

李总说:……….

伟人们告诉我们,要学真东西就得从零单排。

我准备了一组例子

下文所提的例子可以在线使用
http://lightszero.github.io/basemath/outweb.html
例子代码可以从如下GITHUB地址取得
https://github.com/lightszero/BlockFun/tree/master/unity/basemath

随机数有什么用

随机对应固定,产生更多自然的变化。但是随机数也是受控的,这是概率论方面的问题了,

我们准备了两个例子,一个是用随机数来求圆周率


可以用随机数来求圆周率

随机在贴图上画点,把圆内和圆外的分别统计出来,可知圆的面积是0.5*0.5*PI,正方形的面积是1*1.

则PI = 圆的面积/方的面积*4.

画的总点数可以认为是方的面积

落在圆内的点数可以认为是圆的面积

另一个是用随机数来分布角色


图中一屏幕的苍老师,是用随机数来分布的,你每次打开都会不一样。

向量

向量是本篇的重点

Vector3是一个数据结构,既可以表示标量点,也可以表示一个向量。

你希望他是什么他就是什么,这也是很多小伙伴困惑的地方。

这其实是我们在编程中只关心数值所产生的一个普遍问题。

想想float,单位和功能并不在其中。

表达缩放,float可以,表达速度,float 可以,表达长度,float可以,表达时间,float可以。

赋予数据结构何等意义,是人类该考虑的问题。

 

对于坐标的加减法,这些自不必提,我们来厘清一下点积和叉积这两个非常重要的运算。

 

向量点积的意义:

还记得盟军敢死队把敌军的视野标识出来诞生的玩法么?判断我们的猪脚是否暴露在敌人的圆锥形视野中,就要依靠点积。

点积的意义主要在于求出两个向量的夹角,试想一下,夹角和视野的关系。

在shader的光照模型中,用三角面的法线和光线方向确定光强,用向量求夹角,这就是点积的意义。

关于点积我们准备了一个例子

一屏幕的苍老师,鼠标的位置表示红音老师的目光方向。
红音老师的目光范围是左右30度。
红音老师目光所及的位置苍老师是白色的,看不到的位置苍老师是红色的。

 

向量叉积的意义:

如果你有一队飞机,在飞行过程中想让他们保持队形,向量叉积的计算就刚好可以满足你,叉积求出和两个向量垂直的向量。

利用这个特性可以随时计算出队长的前后左右上下正方向,当然也可以按别的什么东西对齐。

在直接绘图相关的计算中,叉积的一大应用是自动计算法线。与一个三角面的任意两边垂直的向量一定与这个三角面垂直,就是这个三角面的法线。

关于叉积我们也准备了一个例子

无论红音老师看向哪个方向,红音军团总会保持阵型屹立在红音老师的周围

 

插插插

插值,可以说是客户端开发中最主要的思想。

是动画的基础思想,对Vector3来说,插值有着两种截然不同的意义。

因为Vector3同时表达两种意义,作为标量他表示3D空间中的一点。

对点和点的坐标插值,就是两点间的一条直线。

延既定路线运动,基本都是对点的插值而来

 

作为向量Vector3表达一个方向,对方向和方向插值,就是一个旋转扇面。

比如经典的小蛤蟆,他的脸是你指哪里就转向哪里

但是作为向量时直接使用Vector3插值,会得到奇异的结果。

如图,从方向A插值到方向B,直接用Vector插值,会导致中间值的长度改变,在AB180度时,再想想这个奇异的结果。

对向量的插值,就要依靠四元数这个工具了,后文我们会顺便提一下。

向量的插值和顶点的插值,在直接绘图的计算中,有一个很典型的场合,骨骼动画。

 

我们也准备了一个插值的例子
在上面的基础上改为红音老师鼠标点击后才转向。
会通过插值逐渐转向
但是红音军团为了快速完成保卫任务,采用直线移动,最后会保持阵型不变。
红音军团通过坐标插值移动。

本篇讲到这里就结束了,再会。后面捎带介绍一下其他的数学工具。

向量弄清楚了,都不是问题。

矩阵

记得么,我们曾介绍过,矩阵是一个土的掉渣的数学工具

矩阵的意义是一个空间变换:旋转、跳跃、我眯着眼。

矩阵可以描述任何一种空间变换。大约有旋转、平移、缩放这些信息。

虽然矩阵,也可以描述出梯形变换和平行四边形推倒的效果,并不常用。

一个3*4矩阵内部保存了旋转、平移、缩放的参数。

可以保存一个矩阵,描述一个物体在另一个空间中的位置。

插插插

遗憾的是,矩阵并不适合于插值。

仅有平移可以直接插值。

矩阵和Vector一样,对于旋转直接数学插值会产生奇异结果。

对于缩放,矩阵也会产生一个不明显的错误。

如果模型进行xy轴不均匀的缩放,那么同一个矩阵并不适合这个模型的法线,会导致法线和表面不再垂直。

这也是为什么光照模型中要使用逆转置矩阵的原因。

四元数

四元数也是一个土的掉渣的描述工具,他描述的信息叫做轴角对。

轴角对,就是一个旋转轴,加一个旋转角度。

设轴向量为n,旋转角度为t
四元数的值为:
x = n.x * sin(t / 2)  
y = n.y * sin(t / 2)  
z = n.z * sin(t / 2)  
w = cos(t / 2)

至于超复数那套解释,知道一下用于提升业务(zhuangbi)水平就行了。

其实四元数这么存,只是为了四元数乘法直接得到两个旋转连接后得到的新的轴角对。

四元数这样保存,可以让四元数乘法直接变成旋转连接工具。

红色的q1表示一个旋转,绿色的q2表示一个旋转,他们的乘法结果就是蓝色的q3。

四元数表达的信息是一个旋转变换,可以直接存一个四元数作为物体的旋转量。

 

另外插入一点个人的意见,也许满是无知与偏见,听一下就行了:

四元数发明于1843年,图形学诞生于1963年,可是1985年四元数才被用于表达旋转并逐渐推广。

用于图形学中的四元数,最重要的价值就是轴角对的一种计算工具。

我对超复数、非零四元数乘法环共轭作用实现转动那套并不信服,就像是马后炮一样。

如早认识到非零四元数乘法环共轭作用实现转动,又怎么会花了二十几年才找到一个表达旋转的适合方法。

插插插

四元数对于旋转的描述就是旋转轴+角度,没有比他更适更针对旋转插值的了。

骨骼动画中对于骨骼旋转的插值计算,都是使用四元数插值的。

区域

区域就是包围盒

有两种常用的形式

Axis Aligned Bounding Box

oriented bounding box

AABB 轴对齐包围盒。

OBB 定向包围盒。

是为了简化碰撞和包围测试的一种方法。将一堆东西包在一个盒子里

我找到一张图,说明的很形象,把小人包起来,判断小人在不在一个区域,判断他的盒子就快的多。

OBB是小人在自己空间中的盒子,他不随小人的旋转跳跃而变化。

AABB是小人在世界空间中的盒子,小人旋转就要重新生成。

除了碰撞盒,还有其他常用的包围形式

2D的Rect

3D的OBB AABB 还有碰撞球,胶囊体等等。

 

全文完。顺便爆照

a

剑英陪你玩转图形学 (三)归去来