簡體   English   中英

圍繞局部軸的OpenGL + SDL旋轉

[英]OpenGL + SDL rotation around local axis

我一直在研究半飛行模擬器。 我想要做的是使用俯仰滾動和偏航來旋轉物體。 我已經在網上看了很多,雖然他們解釋了問題所在但我不知道如何實現解決方案。 所以我舉例說:

glRotatef(yaw,0,1,0);
glRotatef(pitch,1,0,0);

偏航不能正常工作,音高可以正常工作。 從我一直在閱讀的內容看來,對象局部軸已經被改變,所以我需要找到對象的新局部軸並圍繞它旋轉。 所以我嘗試了類似的東西:

newpitch=pitch/57.29
VectorA(0,cos(newpitch)-sin(newpitch),sin(newpitch)+cos(newpitch));
glRotatef(yaw,vec.getXAxis(),vec.getYAxis(),vec.getZAxis());
glRotatef(pitch,1,0,0);

這似乎也行不通。

我也試過制作一般的旋轉矩陣並給它提供俯仰和偏航,但仍然存在同樣的問題。 我嘗試使用四元數,同樣的問題仍然存在!

這是我的四元數代碼:

void Quat::eulerToQuat(float roll,float pitch,float yaw){
    float radiansY = yaw/57.2;
    float radiansZ = roll/57.2;
    float radiansX = pitch/57.2;

    float sY = sinf(radiansY * 0.5);
    float cY = cosf(radiansY * 0.5);
    float sZ = sinf(radiansZ * 0.5);
    float cZ = cosf(radiansZ * 0.5);
    float sX = sinf(radiansX * 0.5);
    float cX = cosf(radiansX * 0.5);

    w = cY * cZ * cX - sY * sZ * sX;
    x = sY * sZ * cX + cY * cZ * sX;
    y = sY * cZ * cX + cY * sZ * sX;
    z = cY * sZ * cX - sY * cZ * sX;
}

然后我將其轉換為矩陣並使用glMultMatrix(matrix)和modelview矩陣,這也有同樣的問題。 所以我相信它不會是gimble lock =)。

所以在我的代碼中我做了:

float matrix[4][4];
Quat this;
this.eularToQuat(roll,pitch,yaw);
this.toMatrix(matrix);
glMultMatrix(matrix);

我覺得你指的是萬向節鎖嗎? 你是對的,每個旋轉都會修改后續局部旋轉的軸。 在你的情況下影響偏航,因為OpenGL矩陣堆棧的工作原理使你添加到它的每個東西在概念上發生在堆棧中已有的東西之前(即,它是以矩陣術語的后乘法)。

但是,即使正確實施,您的解決方案也無法解決問題。 您要做的是在局部坐標空間中獲取全局y軸,以便即使在圍繞全局z旋轉,移動局部軸之后也可以圍繞全局y旋轉。 但這只會給你帶來很多相同的問題,就好像你一直堅持使用全局軸並以其他順序應用旋轉一樣。 第二次旋轉現在將干擾第一次而不是反之。

另一種說服自己你正在做的事情是錯誤的方法是看看你有多少信息。 您試圖用兩個數字描述對象的方向。 兩個數字不足以描述任何旋轉,因此顯然有一些其他規則將兩個數字轉換為完整的方向。 無論您如何修改該規則,您最終都會限制您可以達到的方向。 但是有了飛機,你真的希望能夠達到任何方向,這是一個基本的矛盾。

之所以出現混亂,是因為,如果你有一個合適的存儲方向的方法,那么通過說“如果我通過繞局部y旋轉5,然后繞着局部z繞10來修改它是什么,那么向前推進就完全有效”。問題是試圖將所有這些轉換聚合成一對旋轉。 這是不可能的。

如果您已經普遍使用OpenGL,最簡單的解決方案往往是將方向存儲為完整的矩陣。 通過在該矩陣中出現它們時應用它們來累積俯仰和偏航旋轉。 您通過glMultMatrix將該矩陣傳遞給OpenGL來執行繪圖。

這不是一個最佳的解決方案,但速戰速決測試解決方案是使用glLoadMatrixglGet通過你的矩陣加載到,然后從圖形中從OpenGL的矩陣堆棧取回,分別應用轉換。 這不是堆棧的真正含義所以你可能會遇到一些性能問題,而且隨着時間的推移舍入錯誤會導致奇怪的行為,但是一旦你被這種方法說服,你就可以修復它們。 OpenGL手冊頁給出了所有變換矩陣的公式,你應該查找矩陣歸一化(你可能會使用正交矩陣,無論你是否意識到,這應該有助於谷歌)來處理累積舍入。

編輯:對於你在漫游時發布的代碼,四元數是表示方向的另一種有效方式,另一種可以安全地應用增量更新的方法。 它們也很緊湊,非常容易防止圓角誤差。 但是我認為你的問題可能是你沒有使用四元數作為方向的存儲,只是作為一個中間容器。 因此,將它們添加到鏈中並不能解決您的任何問題。

EDIT2:另外一個揮手的解釋,推動直接存儲俯仰和偏航的想法不夠好:想象一下,從飛行員的角度來看,你應用90度的偏航,然后是30度,然后偏航-90度。 然后你最終就像你應用了30度的卷一樣。 但是,如果你只是存儲音高和偏航,那么你就無法存儲音量。 此外,如果你只是將總的偏航和總音高相加,你最終會認為你應用了30度而不是滾動的音高。 因此,無論您使用俯仰和偏航的順序是什么,或者您使用全局軸還是局部軸,都會得到錯誤的結果。

你應該使用一個變換進行偏航,俯仰和滾動。 因為當你不這樣做時,你會把自己推向萬向節鎖 摘抄:

萬向節鎖定是三維空間中一個自由度的損失,當三個萬向節中的兩個的軸被驅動成平行配置時,“鎖定”系統在退化的二維空間中旋轉。

考慮這個Gimbal鎖定飛機的例子:

萬向節鎖定的飛機

當俯仰(綠色)和偏航(洋紅色)萬向節變得對齊時,滾動(藍色)和偏航的變化對飛機施加相同的旋轉

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM