1 向量
1.1 點-向量-二者關系
點:二維、三維空間一個點的坐標,描述位置。如a(ax, ay, az)
向量:二維、三維空間中向量描述原點到相對於某個點的位移移動,具有方向和長度(大小)屬性。描述位移。如a(ax, ay, az)
向量大小:|v| = √(a2+b2+c2+…+n2),表示向量的長度。
向量標准化:vnorm = v/|v| , v不能為零向量,如下圖,對a(ax, ay)歸一化運算:
1-1. 歸一化(標准化)
關系:向量描述位移,包括相對位置。點描述位置。把向量比喻為一個箭頭,頭是點,尾是原點,整個向量就是點相對於原點的偏移。
1.2 零向量與負向量
零向量:[0,0,…,0],是一個沒有位移、沒有方向的向量。加性單位元。
負向量:任何向量都有負向量。-[x, y, z] = [-x, -y, -z]。加性逆元。幾何解釋:改變方向
1.3 向量的加法、減法運算
加法幾何解釋一:三角形法則
1-2. 加法三角形法則
加法幾何解釋二:平行四邊形法則
平移圖1-1中綠色線至a與b的交點(不再移動a),組成平行四邊形,求半角向量,如下圖:
1-3. 平半角向量
減法幾何解釋:一個點到另一個點的向量。
減法:先把向量轉為負向量再做加法。本職還是加法,繼續使用三角形法則
1-4. 右圖對左圖減法的詳細拆解
1.4 標量與向量乘法:
放大k倍:k · a = k · (ax, ay, az) = (kax, kay, kaz)
1.5 向量與向量乘法-點積
點積結果返回標量值.
//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|) )
如果a、b是單位向量,則分母為1,簡化:
θ = arccos(a·b)
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 左方
點積的幾何解釋二:投影向量
1-6. 向量投影
V可以拆分:V⊥是垂直向量,V||是投影向量
V = V⊥ + V||
如何求投影向量V||?
用三角函數求V||的模:
帶入計算求得向量V||
最后也可方便求V⊥
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||
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的叉積結果向量n,n垂直於向量a與b組成的平面,可把其看作平面法線。
1-7. 叉乘示意圖
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 矩陣
行矩陣
列矩陣
對角矩陣
也是方塊矩陣,行與列相同
除了對角線以外的元素都為0,稱為方塊矩陣
單位矩陣-一種特殊的對角矩陣
默認用 I 表示單位矩陣
對角線元素全為1,其余元素都為0
任何矩陣與單位矩陣相乘,結果任為其本身
轉置矩陣---轉置運算
-
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//反向串接各矩陣
正交矩陣
-
M ·MT = MT·M = I
-
任何正交矩陣行列式值:|A|= 1或 -1
-
線性變換
縮放、旋轉、平移
只需要改變單位矩陣對角線元素值,(其中w分量為1)===> 目標矩陣(行矩陣)·S(q)
把M3x3看作縮放旋轉,t3x1看作平移,1為w分量
將一個矩陣進行縮放、旋轉、平移的復合變換先后順序不一樣,其結果也不一樣。絕大多數情況下都是采用前述順序。
矩陣的幾何意義
為了進一步研究多元方程組,將多元方程組的系數組合在一個矩形數表,形成了矩陣。例如把三元方程組轉化為三階矩陣
例如,已知子坐標空間C的3個坐標軸在父坐標空間P下的表示xc, yc, zc,以及其原點位置Oc。當給定一個子坐標空間中的一點Ac = (a,b,c),按照下面4個步驟求出Ac在父坐標空間下的位置。
1從坐標空間原點開始Oc
2向x軸方向移動x個單位:Oc + axc
3向y軸方向移動y個單位:Oc + axc + byc
4向z軸方向移動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)
透視投影矩陣:
橫縱比:攝像機的ViewPortRect中的W和H屬性決定着Game視圖橫縱比
計算某一點是否在裁剪區域內,只需將該點與,由觀察空間變換到裁剪空間。
注意此時的W分量,可能<0為負數。如果一個點在視錐體內,必須滿足
正交投影矩陣
那么將頂點帶入該矩陣相乘:
判斷條件如下
法線變換
有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) = 0,G = (MA->B-1)T
如果MA->B是正交矩陣,變換包含旋轉和系數k統一縮放,MA->B的逆轉置矩陣 = (MA->BT)-1 = (MA->B-1)T
如果MA->B是正交矩陣,變換包含旋轉和系數k統一縮放,則(MA->B)-1=, 簡要推導如下
設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