2011-07-17 169 views
10

我正在編程Starcraft 2自定義地圖並在3D中獲得了一些帶有數學的proglems。目前我正在嘗試創建並旋轉圍繞任意軸的點,由x,y和z給出(xyz向量被歸一化)。圍繞任意軸的圓形旋轉

我一直在嘗試很多,並通過互聯網上的很多東西閱讀,但我不能得到它如何正確工作。我現在的腳本(你可能不知道的語言,但它沒有什麼特別的)是打破家居小時(不正常)的結果:

point CP; 
fixed AXY; 
point D; 
point DnoZ; 
point DXY_Z; 
fixed AZ; 
fixed LXY; 
missile[Missile].Angle = (missile[Missile].Angle + missile[Missile].Acceleration) % 360.0; 
missile[Missile].Acceleration += missile[Missile].AirResistance; 
if (missile[Missile].Parent > -1) { 
    D = missile[missile[Missile].Parent].Direction; 
    DnoZ = Point(PointGetX(D),0.0); 
    DXY_Z = Normalize(Point(SquareRoot(PointDot(DnoZ,DnoZ)),PointGetHeight(D))); 
    AZ = MaxF(ACos(PointGetX(DXY_Z)),ASin(PointGetY(DXY_Z)))+missile[Missile].Angle; 
    DnoZ = Normalize(DnoZ); 
    AXY = MaxF(ACos(PointGetX(DnoZ)),ASin(PointGetY(DnoZ))); 
    CP = Point(Cos(AXY+90),Sin(AXY+90)); 
    LXY = SquareRoot(PointDot(CP,CP)); 
    if (LXY > 0) { 
     CP = PointMult(CP,Cos(AZ)/LXY); 
     PointSetHeight(CP,Sin(AZ)); 
    } else { 
     CP = Point3(0.0,0.0,1.0); 
    } 
} else { 
    CP = Point(Cos(missile[Missile].Angle),Sin(missile[Missile].Angle)); 
} 
missile[Missile].Direction = Normalize(CP); 
missile[Missile].Position = PointAdd(missile[Missile].Position,PointMult(missile[Missile].Direction,missile[Missile].Distance)); 

我不能讓我的腦海裏圍繞着數學。如果你可以用簡單的術語來解釋這是最好的解決方案,那麼一段代碼就會很好(但不太有用,因爲我打算將來會做更多的3D工作)。

回答

18

http://en.wikipedia.org/wiki/Rotation_matrix。查看Rotation matrix from axis and angle部分。爲了您的方便,這裏是您需要的矩陣。它有點毛茸茸的。 theta爲角度,UX,UY和烏斯是x,y和z中的歸一化向量的分量

Here's the rotation matrix

如果不理解矩陣和向量,後背部和我會幫你。

+0

我發現矩陣也是,我的問題是我不明白如何使用它。我不明白的是如何創建我想要旋轉的點。謝謝你的幫助。 – Alexander

+0

經過深思熟慮之後,輪換不是問題,我想我理解輪換。我不能做的是找到一個垂直於我的軸的向量,至少沒有與軸一起旋轉的軸(軸每隔0.0625秒改變一次,我希望以一個恆定的距離圍繞它旋轉)。 – Alexander

+0

它現在可以工作,我使用一個UP矢量,我必須在每次旋轉時計算等。如果有需要時計算它的方法會更好。 – Alexander

9

做這樣的旋轉的一個有用的方法是用quaternions來做。在實踐中,我發現它們更容易使用,並且避免了Gimbal lock的額外獎勵。

Here是一個很好的步驟,解釋瞭如何以及爲什麼它們用於圍繞任意軸旋轉(這是對用戶問題的迴應)。這是一個更高的水平,對那些不熟悉這個想法的人來說會很有幫助,所以我建議從那裏開始。

更新,以避免鏈路腐蝕

從鏈接的網站上的文字:

當你毫無疑問已經得出結論,左右旋轉穿過原點和點(a,b,c)軸 三維中的單位球體是一個線性變換,因此可以用矩陣乘法表示,即 。我們將給出一個非常光滑的確定這個矩陣的方法,但是要理解該公式的緊湊性 ,以幾個備註開始將是明智的。

輪作在三維是相當特殊的線性變換 ,尤其是因爲它們保存 矢量的長度,並且還(當兩個矢量旋轉)的 矢量之間的角度。這種轉變稱爲「正交」,他們是通過正交矩陣代表 :

M M' = I 

,我們方便地表示轉置」。換句話說,正交矩陣的轉置是其逆。

考慮定義轉換所需的數據。 您已經給出旋轉軸的符號,ai + bj + ck, 方便地假定爲單位矢量。唯一的其他數據是 旋轉角度,由於缺乏更自然的特性,我將用r(用於旋轉?)表示 ,我們將假設以 弧度給出。

現在的旋轉實際上即使在正交變換 有點特別,而事實上他們也藉助他們的是 「取向保存」屬性稱爲特殊正交變換 (或矩陣)。比較它們與 也是長度和角度保持的反射,並且您會發現保留方向的幾何特徵(或者如果您喜歡,則使用「螺旋」)在矩陣的行列式中具有數值對應物。 旋轉的矩陣具有行列式1,而反射的矩陣具有 行列式-1。事實證明,兩次旋轉的產品(或組成)又是一次旋轉,這與產品的行列式是行列式的產物(或旋轉的情況下的1)相一致。

現在我們可以描述一步一步的方法,即可以按照 構建所需的矩陣(在我們快捷整個過程之前和 跳轉到Answer!)。首先考慮其中我們旋轉 單位矢量的工序:

u = ai + bj + ck 

,使得其與所述的「標準」的單位矢量的一個或許重合, K(該positve z軸)。現在我們知道如何圍繞z軸旋轉; 它做在x平時的2x2轉型的問題,Y 單獨座標:

 cos(r) sin(r) 0 
M = -sin(r) cos(r) 0 
     0  0  1 

最後,我們需要「撤銷」這是把ü初始旋轉到K, 這是很容易,因爲逆該轉換是由矩陣轉置表示的(我們 回憶)。換句話說,如果 矩陣R表示旋轉服用u到K,則R」取k到U, ,我們可以寫出轉換的這樣的組合物:

R' M R 

容易驗證,這矩陣乘以 倍ü時的產物,給出û回來:

R' M R u = R' M k = R' k = u 

因此這確實是關於用u限定的軸線旋轉。

該表達式的一個優點在於,它清楚地分離出M對角度r的依賴關係,Q與Q對Q軸和Q軸的依賴關係。但是,如果我們必須進行詳細的計算,我們顯然會有很多矩陣乘法。

所以,到快捷方式。事實證明,當所有塵埃落定時,旋轉之間的乘法運算與四元數乘法單元 同構。如果你以前沒有見過它們,四元數是一種複數的四維泛化。他們 「發明」威廉·漢密爾頓在1843年:

[哈密頓爵士] http://www-gap.dcs.st-and.ac.uk/~history/Mathematicians/Hamilton.html

和今天的3D圖形程序員都極大地在他的債務。

每個單位四元數q = q0 + q1*i + q2*j + q3*k然後定義一個旋轉矩陣:

 (q0² + q1² - q2² - q3²)  2(q1q2 - q0q3)   2(q1q3 + q0q2) 

Q =  2(q2q1 + q0q3)  (q0² - q1² + q2² - q3²)  2(q2q3 - q0q1) 

      2(q3q1 - q0q2)   2(q3q2 + q0q1)  (q0² - q1² - q2² + q3²) 

要驗證Q是正交矩陣,即。即Q Q' = I,意味着在 本質上,Q的行形成了一個正交基。因此,對於 例如,第一行應具有長度1:

(q0² + q1² - q2² - q3²)² + 4(q1q2 - q0q3)² + 4(q1q3 + q0q2)² 

    = (q0² + q1² - q2² - q3²)² + 4(q1q2)² + 4(q0q3)² + 4(q1q3)² + 4(q0q2)² 

    = (q0² + q1² + q2² + q3²)² 

    = 1 

和前兩行應具有點積爲零:

[ (q0² + q1² - q2² - q3²), 2(q1q2 - q0q3), 2(q1q3 + q0q2) ] 

    * [ 2(q2q1 + q0q3), (q0² - q1² + q2² - q3²), 2(q2q3 - q0q1) ] 

= 2(q0² + q1² - q2² - q3²)(q2q1 + q0q3) 

    + 2(q1q2 - q0q3)(q0² - q1² + q2² - q3²) 

    + 4(q1q3 + q0q2)(q2q3 - q0q1) 

= 4(q0²q1q2 + q1²q0q3 - q2²q0q3 - q3²q2q1) 

    + 4(q3²q1q2 - q1²q0q3 + q2²q0q3 - q0²q2q1) 

= 0 

它也可以在一般的顯示det(Q) = 1,和因此Q是 真的是輪換。

但圍繞什麼軸Q旋轉?以什麼角度?那麼, 給定角度r和單位矢量:

u = ai + bj + ck 

和以前一樣,對應的四元數是:

q = cos(r/2) + sin(r/2) * u 

    = cos(r/2) + sin(r/2) ai + sin(r/2) bj + sin(r/2) ck 

因此:

q0 = cos(r/2), q1 = sin(r/2) a, q2 = sin(r/2) b, q3 = sin(r/2) c, 

我們能夠獲得所期望的性質乘以Q「修正」u:

Q u = u 

我們做一個簡單的例子,而不是通過冗長的代數突破。

u = 0i + 0.6j + 0.8k是我們的單位矢量,r = pi是我們的旋轉角度。

然後四元數是:

q = cos(pi/2) + sin(pi/2) * u 

    = 0 + 0i + 0.6j + 0.8k 

和旋轉矩陣:

 -1  0  0 

Q =  0 -0.28 0.96 

     0 0.96 0.28 

在這種具體情況下,它是容易驗證QQ」 = I和DET(Q)= 1。

此外,我們計算的是:

Q u = [ 0, -0.28*0.6 + 0.96*0.8, 0.96*0.6 + 0.28*0.8 ]' 

    = [ 0, 0.6, 0.8 ]' 

    = u 

即。單位矢量u定義了旋轉軸,因爲它由Q「固定」。

最後,我們示出了轉動的角度是PI(或180 度)通過考慮■如何作用於單位矢量的方向上的正x軸,其垂直於U形 :

i + 0j + 0k, or as a vector, [ 1, 0, 0 ]' 

然後Q [ 1, 0, 0 ]' = [-1, 0, 0 ]'其是[1,0,0 ]」通過約ù角PI的旋轉。

至於由四元這種表示旋轉和 代表性的一些額外的方法(和他們是很好 什麼)的引用,在這裏看到的細節:

[代表3D旋轉] http://gandalf-library.sourceforge.net/tutorial/report/node125.html

內容 弧度和單位矢量u

鑑於角r = AI + BJ + CK或[A,b,C]」,定義:

q0 = cos(r/2), q1 = sin(r/2) a, q2 = sin(r/2) b, q3 = sin(r/2) c 

,並從這些數值構建旋轉矩陣:

 (q0² + q1² - q2² - q3²)  2(q1q2 - q0q3)   2(q1q3 + q0q2) 

Q =  2(q2q1 + q0q3)  (q0² - q1² + q2² - q3²)  2(q2q3 - q0q1) 

      2(q3q1 - q0q2)   2(q3q2 + q0q1)  (q0² - q1² - q2² + q3²) 

乘用Q則效果所需的旋轉,特別是:

Q u = u 
2

這裏是你可以用什麼來繞任何軸,可以是x,y或z。 RX,RY和RZ分別表示關於王牌X,Y,Z旋轉。

enter image description here

+4

該圖像來自[這裏](http://en.wikipedia.org/wiki/Rotation_matrix #Basic_rotations),對吧?你應該引用這個。 –

4

要執行3D旋轉,你只需要偏移旋轉到原點的點和圍繞每個軸順序地轉動,存儲用於與下一個旋轉操作使用的每個軸的旋轉之間的結果。該算法看起來像如下:

偏移量至原點。

Point of Rotation = (X1, Y1, Z1) 
Point Location = (X1+A, Y1+B, Z1+C) 

(Point Location - Point of Rotation) = (A, B, C). 

執行圍繞Z軸的旋轉。

A' = A*cos ZAngle - B*sin ZAngle 
    B' = A*sin ZAngle + B*cos ZAngle 
    C' = C. 

接下來,執行關於Y軸的旋轉。

C'' = C'*cos YAngle - A'*sin YAngle 
    A'' = C'*sin YAngle + A'*cos YAngle 
    B'' = B' 

現在執行上一次旋轉,關於X軸。

B''' = B''*cos XAngle - C''*sin XAngle 
    C''' = B''*sin XAngle + C''*cos XAngle 
    A''' = A'' 

最後,重新添加這些值旋轉的原點。

Rotated Point = (X1+A''', Y1+B''', Z1+C'''); 

我發現這個link是非常有幫助的。它定義瞭如何執行關於X,Y和Z軸的單獨旋轉。

在數學上,你可以定義一組操作,像這樣:

enter image description here

-2

Python實現,爲我工作。

cos180=-1 
sin180=0 

rotmatrix=np.zeros((3,3)) 
rotmatrix[0][0]=cos180 + rotaxis[0]**2 * (1-cos180) 
rotmatrix[0][1]=rotaxis[0]*rotaxis[1] * (1-cos180) - rotaxis[2] * sin180 
rotmatrix[0][2]=rotaxis[0]*rotaxis[2] * (1-cos180) + rotaxis[1] * sin180 

rotmatrix[1][0]=rotaxis[1]*rotaxis[0] * (1-cos180) + rotaxis[2] * sin180 
rotmatrix[1][1]=cos180 + rotaxis[1]**2 * (1-cos180) 
rotmatrix[1][2]=rotaxis[1]*rotaxis[2] * (1-cos180) - rotaxis[0] * sin180 

rotmatrix[2][0]=rotaxis[2]*rotaxis[0] * (1-cos180) - rotaxis[1] * sin180 
rotmatrix[2][1]=rotaxis[2]*rotaxis[1] * (1-cos180) + rotaxis[0] * sin180 
rotmatrix[2][2]=cos180 + rotaxis[2] ** 2 * (1-cos180)