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]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM