2013-10-28 92 views
0

[C++] {的DirectX 9}轉換一個局部旋轉到一個全球性(矩陣)

TL; DR:如何轉換表示在X軸局部旋轉到全球偏航浮法/音調/使用矩陣滾動?

因此,我寫了一個小遊戲,其中玩家被表示爲斧頭網格。鼠標移動時,播放器的視圖會水平旋轉(圍繞Y軸)。 [Here]是一個截圖,以獲得更好的想法。

所以我試圖讓按住鼠標來回擺動的斧子動畫。目前,我將播放器類中播放器的全局位置和旋轉值存儲爲變量(m_x,m_y,m_z,m_rotationX,m_rotationY,m_rotationZ)。

當我繪製對象時,我將所有這些座標轉換爲全局空間來創建一個世界矩陣。所以是的,這些都是全球座標。 m_rotationY根據鼠標移動而變化。

這是什麼意思是,如果我增加m_rotationX(即通過某個動畫增量的正弦值),該對象將被GLOBALLY旋轉,這意味着如果我向左或向右看,斧頭在屏幕上擺動而不是離開從中。

我的問題:我需要做什麼樣的矩陣變換才能將某個「局部」x旋轉值轉換爲「全局」x,y和z旋轉值。

if(m_attacking) 
{ 
    m_attackAnimation += 0.1f; 
    float rotationAmount = sin(m_attackAnimation) * 0.1; 

    // How do I figure out m_rotationX, m_rotationY and m_rotationZ 
    // from rotationAmount here? :c 
} 

我的想法至今都被創建一個X旋轉矩陣,然後變換某種使用矢量的,但我所有的實驗與一直相當成功。

感謝您的時間:d

編輯:

更多圖!

這是當我做m_rotationX = rotationAmount;

http://imgur.com/a/yZqzx

EDIT 2會發生什麼:

因此,基於費德里科的回答,我有以下代碼設置:

// Get the local "right" vector 
D3DXVECTOR3 right(1, 0, 0); 
D3DXMATRIX rotationY; 
D3DXMatrixRotationY(&rotationY, m_rotationY); 
D3DXVec3TransformCoord(&right, &right, &rotationY); 

// Calculate the theta value we want to rotate by 
m_attackAnimation += 0.1f; 
float rotationAmount = sin(m_attackAnimation) * 0.1; 

//Cross product 
D3DXVECTOR3 axis; 
D3DXVECTOR3 up(0, 1, 0); 
D3DXVec3Cross(&axis, &right, &up); 

//Rotation matrix 
D3DXMATRIX matrix; 
D3DXMatrixRotationAxis(&matrix, &axis, rotationAmount); 

這應該給我是表示X軸局部旋轉的旋轉矩陣。不過,我可能完全錯了。

無論如何,我怎麼把它恢復到全球的rotationX,的rotationY,和漂浮的rotationZ

* 編輯3:*

這是我從矩陣中提取旋轉角度的嘗試。不幸的是,結果是完全關閉的。斧頭從視線中消失,角色隨機移動。

float rotY = acosf(matrix._11); 
float rotX = asinf(matrix._13/sin(rotY)); 
float rotZ = acosf(matrix._21/sin(rotX)); 

m_rotationX += rotX; 
m_rotationY += rotY; 
m_rotationZ += rotZ; 

在數學上,這聽起來對我來說很合理。不知道該從哪裏出發。

猜測我只是試圖用Frederico建議的矩陣來實現它。

+0

是的,它似乎是正確的,目的是讓世界轉動值回你應該做的從矩陣值反sin和cos,看看我的維基百科帖子,但你不應該這樣做,如果你總是使用d3dx矩陣和載體 –

+0

嗯,看着維基百科鏈接,似乎我只能得到yRotation值。座標矩陣[0] [0]只是cos(yRotation),所以我可以很容易地得到它。所有其他人都從其他多個角度複合。是的,我最終需要這樣做。目前歐拉鎖並不是問題,因爲我只是沿着Y軸旋轉相機。 – MachineMalfunction

+0

沒關係,想通了: Y = invCos(matrix [0] [0]); X = invSin(矩陣[0] [2]/sin(Y)); Z = invCos(矩陣[1] [0]/sin(X)); 現在來執行它。 – MachineMalfunction

回答

0

如果我明白你想要做什麼,這將創建一個矩陣,它將圍繞一個任意的軸旋轉,在你的情況下,軸是方向和向上向量之間的叉積,它是指向你的軸向右(或向左,取決於座標系和產品訂單)。 Cross產品總是返回一個垂直於另外兩個的向量。

//Cross product 
D3DXVECTOR3 axis; 
D3DXVec3Cross(&axis, &direction, &up); 

//Rotation matrix 
D3DXMATRIX matrix; 
D3DXMatrixRotationAxis(&matrix, &axis, rotationAmount); 

生成的矩陣應該是你的旋轉矩陣。

如果要獲取旋轉角度,請在「旋轉矩陣XYZ」部分查看http://en.wikipedia.org/wiki/Euler_angles,但我建議您使用由directx給出的內置矩陣和向量操作來存儲您的位置和旋轉。

它將允許您輕鬆地旋轉,翻譯和縮放位置和方向使用矩陣,而不需要在每個操作下處理數學,並且不會導致gimabl鎖定(http://en.wikipedia.org/wiki/Gimbal_lock)。查看http://msdn.microsoft.com/en-us/library/windows/desktop/bb205164(v=vs.85).aspx的directx數學運算或搜索其他教程,學習如何處理它們非常簡單。

如果你想在特定的數學或其他遊戲相關主題的一些相關信息,我建議你由Jason格雷戈裏閱讀「遊戲引擎架構」

+0

嗯,我明白你的意思,但我無法弄清楚如何將這個旋轉矩陣轉換回兩個或三個值代表rotationX,rotationY和rotationZ – MachineMalfunction

+0

進一步谷歌搜索後,我可以看到,從偏航,Pitch和Roll旋轉矩陣是一項艱鉅任務的地獄。儘管如此,這是一個好的開始。謝謝! – MachineMalfunction

+0

關於第二個想法,您的公式正在爲RotationAmount返回一個矩陣旋轉,所以像Delta一樣?如果是這樣,有沒有辦法用全旋轉矩陣修改單個軸?另外,把這個評論部分變成一個炸彈區。對不起 – MachineMalfunction