我正在開發在XNA三維spaceshooter作爲學校項目(基本上在小行星帶3D功率UPS),並已着手實施滾動,俯仰和偏航相對於船的局部軸。 (我要強調的是:旋轉方面不絕對/世界X,Y和Z軸)。可悲的是,我一直在努力與這個在過去的幾個星期。谷歌和我的新石器時代的猴子大腦讓我失望了;也許你們可以幫忙!XNA - 3D關於局部(改變)船軸的旋轉 - 我錯過了什麼?
這裏是我的設置:
通過鍵盤輸入,我有以下變量蓄勢待發:
- yawRadians,從船的初始 位置
- pitchRadians存儲目標偏航而去,其存儲所希望的間距從 船舶的初始位置遠離
- rollRadians,其從船的存儲所需的輥 遠s的初始位置
該船還保持着自己的前,後,右,左,上和下單位矢量,這些矢量用於旋轉和推進。 (不同的鍵將推動船舶向前,後方等。這部分工作很好。)
最終,我生成旋轉矩陣mShipRotation,表示船舶的所有旋轉,它被傳遞給船的繪製方法。
我的問題是與旋轉自己。我試過的不同解決方案有不同的結果。以下是我已經走了這麼遠:
方法1 - 相對於絕對/世界X偏航,俯仰和滾轉,Y和Z軸
起初,我天真地使用嘗試按照我的船的更新方法:
qYawPitchRoll = Quaternion.CreateFromYawPitchRoll(yawRadians, pitchRadians, rollRadians);
vFront = Vector3.Transform(vOriginalFront, qYawPitchRoll);
vBack = -1 * vFront;
vRight = Vector3.Transform(vOriginalRight, qYawPitchRoll);
vLeft = -1 * vRight;
vTop = Vector3.Transform(vOriginalTop, qYawPitchRoll);
vBottom = -1 * vTop;
mShipRotation = Matrix.CreateFromQuaternion(qYawPitchRoll);
(vOriginalFront,vOriginalRight和vOriginalTop只儲存船的初始方向)
以上實際工作沒有任何錯誤,除了旋轉總是相對於在x,y和z軸,而不是相對於船的前/後/左/右/上/下的載體。這導致該船並不總是像預期的那樣偏航和俯仰。 (具體來說,如果你已經向上傾斜,那麼偏航就會退化爲滾動,這樣就可以理解,因爲這個解決方案中的偏航只是圍繞着世界軸線旋轉。)
我聽說Quarternion。 CreateFromAxisAngle方法,聽起來很完美。我可以將三個四元數旋轉組合在一起,一個圍繞船的每個局部軸。有什麼可能出錯?
方法二 - 四元數。CreateFromAxisAngle
下面是我在船上的更新方法所使用的第二代碼片段:
qPitch = Quaternion.CreateFromAxisAngle(vRight, pitchRadians);
qYaw = Quaternion.CreateFromAxisAngle(vTop, yawRadians);
qRoll = Quaternion.CreateFromAxisAngle(vFront, rollRadians);
qPitchYawAndRoll = Quaternion.Concatenate(Quaternion.Concatenate(qPitch, qYaw), qRoll);
vFront = Vector3.Normalize(Vector3.Transform(vOriginalFront, qPitchYawAndRoll));
vBack = -1 * vFront;
vRight = Vector3.Normalize(Vector3.Transform(vOriginalRight, qPitchYawAndRoll));
vLeft = -1 * vRight;
vTop = Vector3.Normalize(Vector3.Transform(vOriginalTop, qPitchYawAndRoll));
vBottom = -1 * vTop;
mShipRotation = Matrix.CreateFromQuaternion(qPitchYawAndRoll);
上述作品完美,如果我只能做一個旋轉在一個時間(偏航,俯仰或滾動),但如果我同時結合了多個旋轉,船開始瘋狂地旋轉並指向許多不同的方向,變得越來越彎曲,直到它完全消失。
我已經嘗試過上述的變體,我首先將音高應用於所有矢量,然後是偏航,然後是滾動,但沒有運氣。
我也試了一下直接使用矩陣,儘管萬向節鎖定的擔憂:
方法3:矩陣
mShipRotation = Matrix.Identity;
mShipRotation *= Matrix.CreateFromAxisAngle(vRight, pitchRadians);
mShipRotation *= Matrix.CreateFromAxisAngle(vFront, rollRadians);
mShipRotation *= Matrix.CreateFromAxisAngle(vTop, yawRadians);
vFront = Vector3.Normalize(Vector3.Transform(vOriginalFront, mShipRotation));
vBack = -1 * vFront;
vRight = Vector3.Normalize(Vector3.Transform(vOriginalRight, mShipRotation));
vLeft = -1 * vRight;
vTop = Vector3.Normalize(Vector3.Transform(vOriginalTop, mShipRotation));
vBottom = -1 * vTop;
沒有運氣;我得到了同樣的行爲。一次旋轉一圈即可,但繞多個軸旋轉會導致相同的離心旋轉行爲。經過一些精彩的調試(讀作:將變量盲目地輸出到控制檯)之後,我注意到Front/Right/Top矢量隨着時間的推移慢慢變得不那麼正交。我基本上在每一步中都添加了標準化,並嘗試計算基於叉積的新矢量,以確保它們始終保持垂直於彼此,但即使如此,它們也不是完全正交的。我猜這是由於浮點數學不是非常精確。
請注意,我每次更新方法都會重新生成mShipRotation矩陣,因此它不能直接累積漂移或不準確性。我認爲應用多個Quarternion旋轉可能會累積錯誤(因爲我可以做一次旋轉就好),但我嘗試修復它並沒有奏效。
簡而言之:
- 我可以俯仰/翻滾/偏航相對於世界軸x,y和z只是 細。這不僅僅是球員預期會發生的事情,因爲 滾動/俯仰/偏航與船舶無關,而是與 世界相關。
- 我可以在船的局部座標軸(前/後/上/下/左/右)上滾動,俯仰或偏航,但一次只能有一個。他們的任何組合將導致船舶螺旋和迅速變形。
我試過四元數和矩陣。我已經嘗試過在各種論壇中找到的建議,但最終還是沒有找到可行的解決方案。通常人們推薦使用Quaternion.CreateFromYawPitchRoll,並沒有真正意識到其意圖是讓一艘船圍繞自己的(不斷變化的)軸旋轉,而不是(固定的)世界軸。
任何想法?考慮到您對船舶的前部,右側和頂部矢量進行滾動,俯仰和偏航的情況,您將如何着手創建旋轉矩陣?
一位智者曾經說過,一張圖片講千言萬語 – annonymously