一 前言
1.概述
主要概述了點乘,叉乘的實用例子,沒有講述什么原理性的,偏向應用層。點乘叉乘數學原理性的東西比較“難記”,網上很多。實用舉例,網上算是比較少吧。故,來總結一番。
2.可以解決的問題
I.如何計算角度
II.如何判斷前后
III.如何判斷逆時針還是順時針。
IV.如何判斷其他物體在目標物體左右。
V.如何計算平行四邊形面積
二 理論知識
1.點乘性質
a · b = |a|*|b| cosθ
a ·b = b·a
結果是float類型
2.叉乘性質
aXb = c,c⊥a,c⊥b。
|aXb| = |a| |b| sinθ,
a X b = -b X a
叉乘的結果還是向量,且其模就是那兩個向量為邊的平行四邊形面積
3.性質總結
根據點乘,叉乘的公式得知,用到cos函數和sin函數,所以理解cos函數和sin函數很重要。
復習一下,我推薦使用根據函數圖像理解。
點乘,cos函數
叉乘,sin函數
三.分析&理解
當然,這邊計算角度,直接可以用Vector.Angle(p1,p2) 就可以解決,但是返回角度范圍為(0,180)。
我們根據上述點乘叉乘,可以得出,點乘,叉乘都可以算出角度。
1.點乘 計算角度
首先我們根據公式 a · b = |a|*|b| cosθ,θ∈(0,180)
I.在知道a,b均為單位向量的情況,則 cosθ = Mathf.Dot(a,b)這里的θ角度跟Vector.Angle的返回的結果是一致的(0,180),則cosθ最終返回的也只是 (-1,1)之間.
II.繼續得出 θ =arcCos(Mathf.Dot(a,b)) ---------注意這個θ是弧度值,弧度制就類似π/2, 90度。
III.我們的目的是得出角度,則 angle = θ * Mathf.Rad2Deg ----------注意:Mathf.Rad2Deg即為 180/π,與之相乘則弧度轉角度; 注意區分Mathf.Deg2Rad 為π/180,角度轉弧度,Deg即Degree,角度的意思。
float cosAngle = Vector3.Dot(p1.normalized, p2.normalized); float angleDot = Mathf.Acos(cosAngle)*Mathf.Rad2Deg; float angleVector = Vector3.Angle(p1, p2); Debug.Log("angleDot:" + angleDot); Debug.Log("angleVector:" + angleVector);
由上述對比,完全與Vector.Angle一致,結果都是0,180范圍。
2.點乘計算背向還是面向
根據上述1中結果,可以使用其判斷是面向還是背向,點乘結果>0, θ∈0,,90)則面向;
點乘結果<0,θ∈90,180,則背向。
3.叉乘計算角度
我們根據公式 |aXb| = |a|*|b|*sin<θ>
I.當然,我們只需要計算角度,還是需要轉為單位向量計算最為方便,得出|aXb| = sin<θ>
II.則得出,θ = ARCSin(|aXb|), (Mathf.Magnitude,這是求向量長度)
III.因為上述得出的是弧度制,依然 則 angle = Mathf.arcSin(|aXb|) *Mathf.Rad2Deg
Vector3 corssResult = Vector3.Cross(p1.normalized, p2.normalized); float angleCross = Mathf.Asin(Vector3.Magnitude(corssResult)) * Mathf.Rad2Deg; Debug.Log("angleCross:" + angleCross); Debug.Log("angleVector:" + angleVector);
由上述對比得出angleCross 范圍在(0,90),即兩個向量間的延伸交叉最小的夾角,這個真的有點出乎意料,需要自己注意一下。
這個應用啥吶,應用“兩個向量不考慮方向的情況之間誰更緊密”吧。
4.如何判斷逆時針還是順時針
(因為根據1 點乘中得出的角度,范圍都只是0,180,並還不能清楚知道兩個向量的具體方位,所以還缺個順時針還是逆時針。)
我們可以根據叉乘的性質 a X b = - b X a ,可以根據叉乘的正負值,來判斷a,b的相對位置,即b是出於a的順時針還是逆時針。
這里需要注意“叉乘的正負值”:注意順時針,逆時針的概念,是在2d空間中判斷,所以需要指定兩個維度,一般在x,y屏幕上,則判斷z軸上的正負,即為“叉乘的正負值”。
Vector3 resultCross = Vector3.Cross(p1, p2); //在指定x,y平面則判斷z軸正負,為正,則p2在p1順時針,為負,則p2在p1逆時針。 Debug.Log("p1:"+p1+" p2:"+p2 +"resultCross.z:" + resultCross.z);
5.如何判斷物體在左邊還是右邊
其實判斷在左邊還是在右邊,理論與4相似,只是需要稍微加工一下。假設p1為目標點,p2判斷是在p1的左邊還是右邊。
見圖:
//因為我們是在xy平面上,所以判斷z軸 var crossResult = Vector3.Cross(Vector3.up,p2-p1).z; //Vector3.Cross(trans1.up, trans2.position - trans1.position).z; //transform的寫法 Debug.Log("crossResult:" + crossResult);
crossResult 為正則在其左邊,為負則在其右邊。也4中順時針,逆時針一個道理,只不過對比的是物體的正前方的向量。
注意如果為0,則是物體正前方,或者正后方;判斷正后方還是正前方參考2中用法。
6.如何計算出兩向量組成的平行四邊形面積
根據平行四邊形公式 S=a*h,h為高,a為底。
a = |p1|
又因為h = |p2|*sinθ,則 a* h = |p1|*|p2|*sinθ
即 |p1Xp2| = S
float s = Vector3.Magnitude(resultCross);
7.光照強度應用
通過對任意平面的任意兩個向量進行插乘,得到該平面的法向量。然后通過光照向量和法向量進行點乘,計算出光照強度。
光照強度:光向量與平面越垂直就所受光照強度越大,即法向量與光照向量重合。反之如果光照向量與平面平行,則該面所有那個光的強度越弱。
(注意叉乘計算出的法向量方向根據右手定則)
四 總結
上述基本涵蓋了游戲中的點乘叉乘的所有用法,都是自己敲一遍論證后的結果,當然,還需要你自己敲一遍,如有講述錯誤,歡迎指正。
哎,這是2018年唯一一篇比較原創花心思的博客,不能這樣啦,博客要堅持寫,代碼要親自敲啊。