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


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

    开篇废话

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

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

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

    深呼吸,看屏幕,泪在流。
    不应有恨,谁没忘记存代码?
    人有悲欢离合,码有丢失冲突,此事古难全。
    但愿人长久,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

  • 相关阅读:
    java实现算年龄
    java实现手机尾号评分
    java实现手机尾号评分
    java实现手机尾号评分
    java实现手机尾号评分
    java实现手机尾号评分
    java实现三角螺旋阵
    Delphi ActiveForm发布全攻略
    序列化FastReport,重要提示少走弯路 good
    深入探索ScrollWindow
  • 原文地址:https://www.cnblogs.com/crazylights/p/3977348.html
Copyright © 2020-2023  润新知