3D数学提炼总结-向量、矩阵几何意义

1 向量


1.1 点-向量-二者关系

:二维、三维空间一个点的坐标,描述位置。如a(ax, ay, az)

向量:二维、三维空间中向量描述原点到相对于某个点的位移移动,具有方向长度(大小)属性。描述位移。如a(ax, ay, az)

向量大小:|v| = √(a2+b2+c2+…+n2),表示向量的长度。

向量标准化vnorm = v/|v| , v不能为零向量,如下图,a(ax, ay)归一化运算:clip_image001[4]

1-1. 归一化(标准化)

关系:向量描述位移,包括相对位置。点描述位置。把向量比喻为一个箭头,头是点,尾是原点,整个向量就是点相对于原点的偏移。


1.2 零向量与负向量

零向量:[0,0,…,0],是一个没有位移、没有方向的向量。加性单位元。

负向量:任何向量都有负向量。-[x, y, z] = [-x, -y, -z]。加性逆元。几何解释:改变方向


1.3 向量的加法、减法运算

加法几何解释一:三角形法则

image_thumb15

1-2. 加法三角形法则

加法几何解释二:平行四边形法则

平移图1-1中绿色线至ab的交点(不再移动a),组成平行四边形,求半角向量,如下图:

image_thumb28

1-3. 平半角向量

减法几何解释:一个点到另一个点的向量。

减法:先把向量转为负向量再做加法。本职还是加法,继续使用三角形法则

image  image

1-4. 右图对左图减法的详细拆解


1.4 标量与向量乘法:

放大kk · a = k · (ax, ay, az) = (kax, kay, kaz

缩小kclip_image005[4] 

1.5 向量与向量乘法-点积

a·b = clip_image002[8]  ---满足交换律

点积结果返回标量值.

//unity vector3点积计算
public static float Dot(Vector3 lhs, Vector3 rhs)
{
    return (float) (
        (double) lhs.x * (double) rhs.x +
        (double) lhs.y * (double) rhs.y +
        (double) lhs.z * (double) rhs.z
    );
}

点积的几何解释一:角度

点积等于向量大小与向量的夹角:(同一平面)

a·b = |a| |b| cos θ

θ = arccos(a·b / (|a| b|) )

如果ab是单位向量,则分母为1,简化:

θ = arccos(a·b)

 image

1-5. a、b向量夹角

a·b > 0,θ∈[0°, 90°)

a·b = 0,θ = 90°

a·b > 0,θ∈(90°, 180°]

Unity实际应用方位判断

//判断a、b方位。求b在a的前后左右相对位置:
Transform a, b;
Vector3 diffVec  = a.position – b.position;
float front_back = Vector3.Dot(a.position.forward, diffVec);
float left_right = Vector3.Dot(a.position.right, diffVec);
if(front_back > 0) 前方
else 后方
if(left_right > 0) 右方
else 左方


点积的几何解释二:投影向量

image

1-6. 向量投影

V可以拆分:V是垂直向量,V||是投影向量

V = V + V||

如何求投影向量V||

用三角函数求V||的模:

image


带入计算求得向量V||

image 

最后也可方便求V

image

Unity的Vector3.Project分析:

public static Vector3 Project(Vector3 vector, Vector3 onNormal)
{
    //pow(onNormal, 2)
    float num1 = Vector3.Dot(onNormal, onNormal);
    if ((double) num1 < (double) Mathf.Epsilon)
        return Vector3.zero;
    float num2 = Vector3.Dot(vector, onNormal);
    return new Vector3(
        onNormal.x * num2 / num1,
        onNormal.y * num2 / num1,
        onNormal.z * num2 / num1
    );
}

实战如何用Vector3.Project算出V||

image

1-6. 事例

求投影向量和垂直向量,以及投影交点坐标:

    public Transform m_from_p;

    //一般为法线
    public Transform m_to_p;

    //相对于from_p和to_p而言
    public Transform m_origin_p;
    private Vector3  m_projects = Vector3.zero;

    void Update()
    {
        //warning: 要统一坐标空间
        //Vector3 toP_foDirect = m_to_p.InverseTransformDirection(m_from_p.position - m_origin_p.position);
        Vector3 toP_foDirect = m_from_p.position - m_origin_p.position;
        Vector3 toP_toDirect = m_to_p.position - m_origin_p.position;
        //求出投影向量 V_ii
        m_projects           = Vector3.Project(toP_foDirect, toP_toDirect);

        //from到原点连线
        Debug.DrawLine(m_origin_p.position, m_from_p.position, Color.blue);
        //绘制投影向量线
        Debug.DrawLine(m_origin_p.position, m_origin_p.position + m_projects, Color.black);

        //投影点坐标, 对project_P求模可以知道from_p到to_p所在轴的最短距离
        Vector3 project_P    = m_origin_p.position + m_projects;
        //float minDis       = project_P.magnitude;
        //垂直向量
        Vector3 V_T          = project_P - m_from_p.position;

        //绘制垂直向量线
        Debug.DrawLine(m_from_p.position, m_from_p.position + V_T.normalized * 100f, Color.green);
    }

果一个向量v在自身投影,就是v·v = vx2 + vy2 + vz2 = |v|2,继而可以求出v的模


1.6 向量与向量乘法-叉积

向量a与向量b的叉积结果向量nn垂直于向量ab组成的平面,可把其看作平面法线

image

1-7. 叉乘示意图

image

1-8. 叉积计算公式

几何解释一:平行四边形面积

几何解释二:顺时针和逆时针方向

a = (x1, y1, z1), b = (x2, y2, z2);

//a x b = (y1 * z2 - y2 * z1, z1 * x2 - x1 * z2, x1 * y2 - y1 * x2)
double ans = (y1 * z2 - y2 * z1)+(z1 * x2 - x1 * z2)+( x1 * y2 - y1 * x2)

if(ans>0)
    cout<<"逆时针"<<endl;
if(ans<0)
    cout<<"顺时针"<<endl;
if(ans==0)
    cout<<"共线"<<endl;

几何dot、cross:求点到点的角度

    // 通过 Dot、Cross 结合获取到 a 到 b, b 到 a 的不同夹角
    private void GetAngle(Vector3 a, Vector3 b)
    {
        /*ab叉积求得时针方向,点积求得*/

        Vector3 c = Vector3.Cross(a, b);
        float angle = Vector3.Angle(a, b);//只能返回[0°, 180°]

        // b 到 a 的夹角
        float sign = Mathf.Sign(Vector3.Dot(c.normalized, Vector3.Cross(a.normalized, b.normalized)));
        float signed_angle = angle * sign;

        Debug.Log("b -> a :" + signed_angle);

        // a 到 b 的夹角
        sign = Mathf.Sign(Vector3.Dot(c.normalized, Vector3.Cross(b.normalized, a.normalized)));
        signed_angle = angle * sign;

        Debug.Log("a -> b :" + signed_angle);
    }

shader中叉积计算写法

//shader中叉积计算写法
float crossProduct = a.yzx * b.zxy - a.zxy * b.yzx;


2 矩阵

行矩阵

M1m =clip_image010[4]


列矩阵

M1mT = Mm1clip_image011[4]


对角矩阵

也是方块矩阵,行与列相同

除了对角线以外的元素都为0,称为方块矩阵

clip_image012[4]


单位矩阵-一种特殊的对角矩阵

默认用 I 表示单位矩阵

对角线元素全为1,其余元素都为0

任何矩阵与单位矩阵相乘,结果任为其本身

clip_image013[4]


转置矩阵---转置运算

  • MijT = Mji
  • 矩阵的行变为列,列变为行
  • (A·B)T = BT·AT,具有反向串接各矩阵

 

逆矩阵

  • 必须为方阵才有逆矩阵行列相等(n=m)
  • M-1·M = I                      //必须满足
  • (M-1)-1 = M                 
  • I-1 = I                          //单位矩阵的逆矩阵=自身
  • (MT)-1 = (M-1)T             //转置矩阵的逆矩阵等于逆矩阵的转置
  • (A·B·C)-1 = C-1 ·B-1·A-1//反向串接各矩阵

Unity提供了相关的矩阵函数

 

正交矩阵

  • M·MT = MT·M = I
  • 任何正交矩阵行列式值:|A|= 1或 -1
  • https://gss0.bdstatic.com/-4o3dSag_xI4khGkpoWK1HF6hhy/baike/pic/item/0d338744ebf81a4c55f1e2e1da2a6059242da6d2.jpg

 

线性变换

缩放、旋转、平移

缩放:clip_image014[4]

只需要改变单位矩阵对角线元素值,(其中w分量为1===> 目标矩阵(行矩阵S(q)

 

旋转:clip_image015[4] clip_image016[4] clip_image017[4]


平移一:clip_image018[4] 


平移二:T(p) =clip_image019[4]


基础变换矩阵clip_image020[4] 

M3x3看作缩放旋转,t3x1看作平移,1w分量

将一个矩阵进行缩放、旋转、平移的复合变换先后顺序不一样,其结果也不一样。绝大多数情况下都是采用前述顺序。

 

矩阵的几何意义

为了进一步研究多元方程组,将多元方程组的系数组合在一个矩形数表,形成了矩阵。例如把三元方程组转化为三阶矩阵

clip_image021[4]

clip_image022[4]

例如,已知子坐标空间C3个坐标轴在父坐标空间P下的表示xc, yc, zc,以及其原点位置Oc。当给定一个子坐标空间中的一点Ac = (a,b,c),按照下面4个步骤求出Ac在父坐标空间下的位置。

1从坐标空间原点开始Oc

2x轴方向移动x个单位:Oc + axc

3y轴方向移动y个单位:Oc + axc + byc

4z轴方向移动z个单位:Oc + axc + byc + czc

Ap = Oc + axc +byc + czc


= (xoc, yoc ,zoc) + a(xxc, yxc, zxc) + b(xyc , yyc, zyc) + c(xzc, yzc, zzc)


= (xoc, yoc ,zoc) + clip_image024[4] clip_image026[6]


= (xoc, yoc ,zoc) + clip_image028[4] clip_image026[7]


= (xoc, yoc ,zoc,1) + clip_image030[6] clip_image032[10]


= clip_image034[4] clip_image030[7] clip_image032[11]  //笔误:O33应该=1


= clip_image036[4] clip_image032[12]


= clip_image038[6] clip_image032[13]


MA->p = clip_image038[7]


 

透视投影矩阵:

近裁剪面高度:clip_image040[4]

远裁剪面高度:clip_image042[4]

横纵比:摄像机的ViewPortRect中的WH属性决定着Game视图横纵比

clip_image044[4]


clip_image046[4]


clip_image048[4]


计算某一点是否在裁剪区域内,只需将该点与clip_image050[4],由观察空间变换到裁剪空间。


clip_image052[4]

=clip_image054[4]






注意此时的W分量,可能<0为负数。如果一个点在视锥体内,必须满足

clip_image056[6]

 

正交投影矩阵

 

近裁剪面高度:clip_image058[4]

远裁剪面高度:clip_image060[4]

横纵比:clip_image062[4]

clip_image064[4]


那么将顶点带入该矩阵相乘:


clip_image066[4]


=clip_image068[4]






判断条件如下

clip_image0567


法线变换

image

MA->B 顶点变换矩阵, N是法线,T是切线, G是法线变换矩阵

根据点积性质变换前垂直:(TA)T·NA = 0

变换后也应该垂直:(TA->B)T·NA->B = 0

切线公式:TB = (MA->B · TA)T

切线变换步骤:

TB · NB = (MA->B · TA)T ·(G · NA)

= (TA)T ·MA->BT·(G · NA)  = (TA)T · NA ·(MA->BT·G)

由于TAT·NA = 0

如果(MA->BT·G) = 0G = (MA->B-1)T

如果MA->B是正交矩阵,变换包含旋转和系数k统一缩放,MA->B的逆转置矩阵 = (MA->BT)-1 = (MA->B-1)T

如果MA->B是正交矩阵,变换包含旋转和系数k统一缩放,则(MA->B)-1=clip_image002[22], 简要推导如下

设MA->B = k·M(M为正交矩阵),

等式左边:(MA->B)-1=(K·M)-1 = 1/k · M-1

等式右边:1/K2 · (K·M)T = 1/k2 · k · MT = 1/K · M-1

如果MA->B是正交矩阵,变换包含旋转和系数k统一缩放,可得MA->B的逆转置矩阵  (MA->BT)-1 = clip_image002[24]

原文地址:https://www.cnblogs.com/baolong-chen/p/11639158.html