2012-03-25 49 views
8

我在OpenGL上創建了一個非常簡單的項目,並且我被旋轉卡住了。我試圖在所有3個軸上單獨旋轉一個對象:X,Y和Z.由於圍繞一個軸旋轉後出現「萬向節鎖定」問題,我已經過了不眠之夜。然後我知道四元數會解決我的問題。我研究過四元數並實現了它,但是我還沒有能夠將旋轉轉換爲四元數。例如,如果我想圍繞Z軸旋轉90度,則只需創建四元數的{0,0,1}矢量,並使用此處的代碼圍繞該軸旋轉90度:如何從X Y Z旋轉中找到四元數的向量

http://iphonedevelopment.blogspot.com/2009/06/opengl-es-from-ground-up-part-7_04.html(最複雜的矩陣朝向底部)

對於一個矢量來說沒問題,但是,比如說,我首先要圍繞Z旋轉90度,然後圍繞X旋轉90度(就如一個例子)。我需要傳入什麼向量?我如何計算這個向量。我對矩陣和三角學不太瞭解(我知道基本知識和一般規則,但我只是不是專家),但我需要完成這些。有很多關於四元數的教程,但我似乎沒有理解(或者他們不回答我的問題)。我只需要學習構建圍繞多個軸組合的旋轉矢量。

更新:我發現這個漂亮的網頁約四元數,並決定實施他們這樣說:http://www.cprogramming.com/tutorial/3d/quaternions.html

這裏是我的四元數乘法代碼:

void cube::quatmul(float* q1, float* q2, float* resultRef){ 
float w = q1[0]*q2[0] - q1[1]*q2[1] - q1[2]*q2[2] - q1[3]*q2[3]; 
float x = q1[0]*q2[1] + q1[1]*q2[0] + q1[2]*q2[3] - q1[3]*q2[2]; 
float y = q1[0]*q2[2] - q1[1]*q2[3] + q1[2]*q2[0] + q1[3]*q2[1]; 
float z = q1[0]*q2[3] + q1[1]*q2[2] - q1[2]*q2[1] + q1[3]*q2[0]; 

resultRef[0] = w; 
resultRef[1] = x; 
resultRef[2] = y; 
resultRef[3] = z; 
} 

這裏是我的代碼將四元數應用於我的模型視圖矩陣(我有一個tmodelview變量,它是我的目標模型視圖矩陣):

void cube::applyquat(){ 
float& x = quaternion[1]; 
float& y = quaternion[2]; 
float& z = quaternion[3]; 
float& w = quaternion[0]; 
float magnitude = sqrtf(w * w + x * x + y * y + z * z); 
if(magnitude == 0){ 
    x = 1; 
    w = y = z = 0; 
}else 
if(magnitude != 1){ 
    x /= magnitude; 
    y /= magnitude; 
    z /= magnitude; 
    w /= magnitude; 
    } 

tmodelview[0] = 1 - (2 * y * y) - (2 * z * z); 
tmodelview[1] = 2 * x * y + 2 * w * z; 
tmodelview[2] = 2 * x * z - 2 * w * y; 
tmodelview[3] = 0; 

tmodelview[4] = 2 * x * y - 2 * w * z; 
tmodelview[5] = 1 - (2 * x * x) - (2 * z * z); 
tmodelview[6] = 2 * y * z - 2 * w * x; 
tmodelview[7] = 0; 

tmodelview[8] = 2 * x * z + 2 * w * y; 
tmodelview[9] = 2 * y * z + 2 * w * x; 
tmodelview[10] = 1 - (2 * x * x) - (2 * y * y); 
tmodelview[11] = 0; 

glMatrixMode(GL_MODELVIEW); 
glPushMatrix(); 
glLoadMatrixf(tmodelview); 
glMultMatrixf(modelview); 
glGetFloatv(GL_MODELVIEW_MATRIX, tmodelview); 
glPopMatrix(); 
} 

而且我對輪換代碼(我稱之爲外部),其中quaternion是立方體的一個類變量:

void cube::rotatex(int angle){ 
float quat[4]; 
float ang = angle * PI/180.0; 
quat[0] = cosf(ang/2); 
quat[1] = sinf(ang/2); 
quat[2] = 0; 
quat[3] = 0; 
quatmul(quat, quaternion, quaternion); 
applyquat(); 
} 

void cube::rotatey(int angle){ 
float quat[4]; 
float ang = angle * PI/180.0; 
quat[0] = cosf(ang/2); 
quat[1] = 0; 
quat[2] = sinf(ang/2); 
quat[3] = 0; 
quatmul(quat, quaternion, quaternion); 
applyquat(); 
} 

void cube::rotatez(int angle){ 
float quat[4]; 
float ang = angle * PI/180.0; 
quat[0] = cosf(ang/2); 
quat[1] = 0; 
quat[2] = 0; 
quat[3] = sinf(ang/2); 
quatmul(quat, quaternion, quaternion); 
applyquat(); 
} 

我打電話,說rotatex,10-11次,僅轉動1度,但我在10度到1度之後,立方體旋轉近90度,這是沒有意義的。此外,在調用不同軸的旋轉函數之後,My cube會發生扭曲,變得二維,並且不可逆地消失(模型視圖矩陣中的一列全部爲零),這顯然不應該在正確實現四元數時發生。

+0

你想獲得四元數的幫助嗎?或者想旋轉一個物體? – Beta 2012-03-25 20:52:46

+0

好吧,我已經走了四元數路徑並編寫代碼,所以如果你有一個涉及四元數的旋轉解決方案,它會很有幫助。我只需要實現的就是能夠在3D空間中旋轉3個自由度的物體 – 2012-03-25 20:54:38

+0

也許Jack Kuipers的書籍「Quaternions and Rotations Sequences」可能對您有所幫助。關於X-Y-Z旋轉(又名歐拉角)有很多說法。例如,你是圍繞舊的X軸還是新的軸旋轉(「附加」到你旋轉的物體上)? – ascobol 2012-03-25 21:20:25

回答

7

你正在接近這個錯誤的方式。如果X,Y和Z軸有三個歐拉角旋轉,將它們變成四元數,然後變成矩陣不會對您有所幫助。由於您想要的旋轉的表示,所以出現萬向節鎖。如果您將旋轉存儲爲X-Y-Z歐拉角,那麼您將得到Gimbal鎖。

您需要將您的想要的方位作爲四元數存儲以獲得優勢。也就是說,可以將當前的方向作爲一個四元數,然後問「我如何繞Z軸旋轉90度並將其用作我的新方向?」,但詢問「我的電流方向由這些XYZ歐拉角度定義,我如何將它轉換爲四元數?「。

對四元數相關部分的全面處理將會很漫長。 This site may help you out.值得注意的是,您鏈接的網站似乎確實在談論軸角旋轉,而不是四元數。

編輯:您發佈的代碼是正確的,只是爲tmodelview[6]tmodelview[9]跡象都錯了。

+0

謝謝。我知道我需要存儲我的方向(因此,四元數),並忘記那個角度。你的鏈接是相當有用的,但有一件事我仍然不明白,你正在談論的問題是:「我如何圍繞Z軸旋轉90度,並將其用作我的新方向?」 – 2012-03-25 21:54:49

+3

四元數乘法。如果你的四元數q指的是你當前的方位,而四元數r是圍繞Z軸旋轉90度,那麼四元數r * q就是你的新方向。一個確切的平行矩陣乘法,真的。 – 2012-03-25 21:57:08

+0

我會看看 – 2012-03-25 22:59:54

相關問題