Unity中用到的数学知识 整理 (为自己)

缓动数学知识

转自 http://easings.net/en

CSS

CSS properties transition and animation allow you to pick the easing function. Unfortunately, theydon’t support all easings and you must specify the desiredeasing function yourself (as a Bezier curve).

Selectan easing function to show its Bezier curve notation.

div {
  -webkit-transition: all 600ms easing’s Bezier curve;
  transition:         all 600ms easing’s Bezier curve; }

SCSS

Sass/SCSS candescribe animations too! Compass removes prefixes before the transition and animation properties,and the CompassCeaser plugin lets youpass the easing function by name (without specifying the exact Beziercurves).

div {
  @include transition(all 600ms ceaser($easing name)); }

JavaScript

jQuery with the jQueryEasing Plugin is theeasiest way to describe animation with easing. Pass the easing name (like easeInCirc) to the .animate() function as the third argument, or use itas the value of the easing option.

div.animate({ top: '-=100px' }, 600, 'easing name', function () { … })

unity 由两个向量求夹角

在Unity3D中,有时候我们需要计算二维向量的夹角。二维向量夹角一般在0~180度之前,可以直接调用Vector2.Angle(Vector2 from, Vector2 to)来计算。

但是在有些场景,我们需要-180~180度的夹角,此时可以用下面的脚本进行计算:

float VectorAngle(Vector2 from, Vector2 to)
    {
        float angle;
       
        Vector3 cross=Vector3.Cross(from, to);
        angle = Vector2.Angle(from, to);
        return cross.z > 0 ? -angle : angle;
    }

1.

1

2

3

float angle = Vector3.Angle (fromVector, toVector); //求出两向量之间的夹角 

Vector3 normal = Vector3.Cross (fromVector,toVector);//叉乘求出法线向量 

angle *= Mathf.Sign (Vector3.Dot(normal,upVector));  //求法线向量与物体上方向向量点乘,结果为1或-1,修正旋转方向 

2.

1

2

Vector3 velocity = Quaternion.Inverse (transform.rotation)*destinationVector; //对目标向量进行反向旋转,得到的新向量与z轴的夹角即为目标向量与当前物体方向的夹角         

float angle = Mathf.Atan2 (velocity.x,velocity.z) * Mathf.Rad2Deg; //返回tan值为x/z的角的弧度,再转化为度数。 

3.

数学法:已知a,b两个向量

cosθ=X;  (X=(a*b)/(|a|*|b|))

然后求θ=arccosX c#里是Mathf.Acos(X);

如下图

  Vector3 srcPos = new Vector3(0,0,0);
  Vector3 tarPos = new Vector3(0,0,-1);
  Vector3 srcRot = new Vector3(0,90,0);
  Quaternion srcQua = Quaternion.Euler(srcRot);
  Vector3 direction = tarPos - srcPos;
  Vector3 r = Quaternion.Inverse(srcQua) * direction;
  Debug.Log(r);
  float angle = Mathf.Atan2(r.x, r.z) * Mathf.Rad2Deg;
  Debug.Log(angle);


其中结果r为(1,0,0),angle为90 ;

关于Quaternion * Vector3
Quaternion * Vector3就是Vector3进行一次Quaternion 旋转。理论总是枯燥的,下面以实际项目代码为例,这是简化之后的部分项目代码:(c#)

[csharp] view plain copy
Vector3 directionVector = tarPosition - srcPosition;
Vector3 resultDirection = transform.rotation * directionVector;   

代码的目的就是计算出当前帧人物应该移动的方向。提一下这是一个FPS项目,即第一人称射击类,当玩家按住向右移动时,人物的旋转是不变的,只是移动

方向相对于玩家是向右,理解这一点很重要。

那么为什么movingDirection就是当前帧人物应该移动的方向呢?

我们不妨假设directionVector=(1,0,1);这就表示玩家想让人物向右移动的同时向前移动,且移动量相同。

至于具体的移动量没有意义,我们随便加一个系数就可以调节移动快慢。

关于Atan2
结果为正表示从 X 轴逆时针旋转的角度,结果为负表示从 X 轴顺时针旋转的角度。
ATAN2(a, b) 与 ATAN(a/b)稍有不同,ATAN2(a,b)的取值范围介于 -pi 到 pi 之间(不包括 -pi),
而ATAN(a/b)的取值范围介于-pi/2到pi/2之间(不包括±pi/2)。
若要用度表示反正切值,请将结果再乘以 180/3.14159。
另外要注意的是,函数atan2(y,x)中参数的顺序是倒置的,atan2(y,x)计算的值相当于点(x,y)的角度值。

  Vector3 srcPos = new Vector3(0,0,0);
  Vector3 tarPos = new Vector3(0,0,-1);
  Vector3 srcRot = new Vector3(0,90,0);
  Quaternion srcQua = Quaternion.Euler(srcRot);
  Vector3 direction = tarPos - srcPos;
  Vector3 r = Quaternion.Inverse(srcQua) * direction;
  Debug.Log(r);
  float angle = Mathf.Atan2(r.x, r.z) * Mathf.Rad2Deg;
  Debug.Log(angle);


其中结果r为(1,0,0),angle为90 ;

关于Quaternion * Vector3
Quaternion * Vector3就是Vector3进行一次Quaternion 旋转。理论总是枯燥的,下面以实际项目代码为例,这是简化之后的部分项目代码:(c#)

[csharp] view plain copy
Vector3 directionVector = tarPosition - srcPosition;
Vector3 resultDirection = transform.rotation * directionVector;   

代码的目的就是计算出当前帧人物应该移动的方向。提一下这是一个FPS项目,即第一人称射击类,当玩家按住向右移动时,人物的旋转是不变的,只是移动

方向相对于玩家是向右,理解这一点很重要。

那么为什么movingDirection就是当前帧人物应该移动的方向呢?

我们不妨假设directionVector=(1,0,1);这就表示玩家想让人物向右移动的同时向前移动,且移动量相同。

至于具体的移动量没有意义,我们随便加一个系数就可以调节移动快慢。

关于Atan2
结果为正表示从 X 轴逆时针旋转的角度,结果为负表示从 X 轴顺时针旋转的角度。
ATAN2(a, b) 与 ATAN(a/b)稍有不同,ATAN2(a,b)的取值范围介于 -pi 到 pi 之间(不包括 -pi),
而ATAN(a/b)的取值范围介于-pi/2到pi/2之间(不包括±pi/2)。
若要用度表示反正切值,请将结果再乘以 180/3.14159。
另外要注意的是,函数atan2(y,x)中参数的顺序是倒置

旋转矩阵(Rotation Matrix)的推导及其应用//

世界坐标中的一个点乘以一个四维矩阵,可以实现平移,旋转和缩放等等。

平移就是http://latex.codecogs.com/gif.latex?%5Bx%2Cy%2Cz%5D%27+%5Bdx%2Cdy%2Cdz%5D%27,旋转和缩放就是http://latex.codecogs.com/gif.latex?M%5Ctimes%20%5Bx%2Cy%2Cz%5D%27(M分别是对应的旋转缩放矩阵)

http://latex.codecogs.com/gif.latex?%5Bx%2Cy%2Cz%2C0%20%5C%20or%20%5C%201%5D中为0时,是向量,为1时,是坐标。

旋转:

缩放:

矩阵如何进行计算呢?之前的文章中有简介一种方法,把行旋转一下,然后与右侧对应相乘。在谷歌图片搜索旋转矩阵时,看到这张动图,觉得表述的很清晰了。

 

稍微复杂一点的是旋转,如果只是二维也很简单(因为很直观),但因为是三维的,有xyz三个轴,先推导二维的再延伸到三维。

YouTube上有很好的推导过程,视频链接地址(需穿.墙) https://www.youtube.com/watch?v=8XRvpDhTJpw

有点PXaYa),当坐标由 x –> y 旋转 θ 度后,求该点在新坐标轴的坐标是多少

所以对于二维旋转来讲,旋转矩阵就是

三维旋转,需要先搞清楚正、负方向(使用的是右手法则,在二维平面增加一维z,它的正方向朝向屏幕外)。

x轴进行旋转(在yz平面顺时针旋转)

y轴进行旋转(在zx平面顺时针旋转)

z轴进行旋转(在xy平面顺时针旋转)

图片来源Rotation Matrix -- from Wolfram MathWorld

参考:https://zh.wikipedia.org/wiki/旋转矩阵

了解这些有什么用处呢?之前有讲到渲染被分为三个阶段:应用 –> 几何 –> 栅格化,其中几何阶段做了大量的变换工作。

模型空间 –>( 模型矩阵) –> 世界空间 –> 视图矩阵 –> 观察空间(摄像机,右手坐标系,其余均采用左手) –> 投影矩阵 –> 裁剪空间 –> 屏幕空间,每一次变换都对应着相应的矩阵。

Unity中的 UNITY_MATRIX_MVP 矩阵表示的是从模型到裁剪坐标的矩阵变换,Model Matrix ● View Matrix ● Projection Matrix。在Unity2017中使用 UnityObjectToClipPos 进行了替换,MVP也即是 模型(M)、视图(V)、透视(P三个单词的首字母简写。

了解上面这些,才更容易理解Unity内置的变换矩阵

对照下面这张图,更容易理解一些。

https://img-blog.csdn.net/20130816091900765

VIEW MATRIX

下面是3类基本的2D图形变换。 

平移:

设某点向x方向移动 dx, y方向移动 dy ,[x,y]为变换前坐标, [X,Y]为变换后坐标。

 X = x+dx;  Y = y+dy;

以矩阵表示:

                                1    0    0

[X, Y, 1] = [x, y, 1][ 0    1    0  ] ; 

                               dx  dy   1

  1    0    0

  0    1    0   即平移变换矩阵。 

  dx  dy   1 

 旋转

 旋转相比平移稍稍复杂:

 设某点与原点连线和X轴夹角为b度,以原点为圆心,逆时针转过a  , 原点与该点连线长度为R, [x,y]为变换前坐标, [X,Y]为变换后坐标。

  x = Rcos(b) ; y = Rsin(b);

  X = Rcos(a+b) = Rcosacosb - Rsinasinb = xcosa - ysina; (合角公式)

  Y = Rsin(a+b) = Rsinacosb + Rcosasinb = xsina + ycosa ;

  用矩阵表示:

                                cosa   sina  0

 [X, Y, 1] = [x, y, 1][-sina  cosa  0  ] 

                                 0        0     1

  cosa   sina  0

 -sina  cosa  0  为旋转变换矩阵。

   0       0     1 

 缩放

 设某点坐标,在x轴方向扩大 sx倍,y轴方向扩大 sy倍,[x,y]为变换前坐标, [X,Y]为变换后坐标。

 X = sx*x; Y = sy*y;

则用矩阵表示:

                                sx    0    0

[X, Y, 1] = [x, y, 1][ 0    sy    0  ] ; 

                                0     0     1

 sx    0    0

 0    sy    0  即为缩放矩阵。 

 0     0     1

 2D基本的模型视图变换,就只有上面这3种,所有的复杂2D模型视图变换,都可以分解成上述3个。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值