2012-11-07 121 views
0

我在我的程序中有一個函數,該函數用一個角度w_nx & w_ny圍繞另一個點(x_m,y_m,z_m)旋轉一個點(x_p,y_p,z_p)。新座標存儲在全局變量x_n,y_n和z_n中。圍繞y軸旋轉(如此改變w_nx的值 - 以便y值不會受到傷害)正常工作,但只要我圍繞x軸或z軸旋轉(改變w_ny的值)座標不再準確。我評論了我認爲是我的錯誤的那一行,但我無法弄清楚那段代碼有什麼問題。圍繞另一個點旋轉一個3D點

任何人都可以幫助我嗎?

void rotate(float x_m, float y_m, float z_m, float x_p, float y_p, float z_p, float w_nx ,float w_ny) 
    { 
     float z_b = z_p - z_m; 
     float x_b = x_p - x_m; 
     float y_b = y_p - y_m; 
     float length_ = sqrt((z_b*z_b)+(x_b*x_b)+(y_b*y_b)); 
     float w_bx = asin(z_b/sqrt((x_b*x_b)+(z_b*z_b))) + w_nx; 
     float w_by = asin(x_b/sqrt((x_b*x_b)+(y_b*y_b))) + w_ny; //<- there must be that fault 
     x_n = cos(w_bx)*sin(w_by)*length_+x_m; 
     z_n = sin(w_bx)*sin(w_by)*length_+z_m; 
     y_n = cos(w_by)*length_+y_m; 
    } 
+1

如果你使用[tag:opengl]我確定一個圖形庫將有一個矩陣和載體植入,你可以使用。通過矩陣旋轉點將簡化您的算法。 – andre

+2

@ahenderson你的意思是「執行」? ;) – leemes

+0

如果你還不熟悉這個術語,你應該閱讀「Gimbal Lock」。我不能立即告訴你的代碼是否會受到它的影響,但當你使用「歐拉角」進行這種旋轉時,這是一個常見的缺陷。 – Rook

回答

2

嘗試使用向量數學。決定你旋轉的順序,首先沿着x軸,然後沿着y軸旋轉。

如果沿z的旋轉,[Z '= Z]

x' = x*cos a - y*sin a; 
y' = x*sin a + y*cos a; 

同樣重複y軸:[Y'= Y']

x'' = x'*cos b - z' * sin b; 
z'' = x'*sin b + z' * cos b; 

沿X再次旋轉軸:[X ''」 = X '']

y''' = y'' * cos c - z'' * sin c 
z''' = y'' * sin c + z'' * cos c 

和周圍一些特定 「點」 旋轉最後一個問題:

首先從座標中減去點,然後應用旋轉並最終將點加回結果。

就我所知,這個問題與「萬向節鎖」有很大關係。角度w_ny不能相對於固定的xyz座標系測量,而是應用角度w_nx旋轉的座標系。

正如kakTuZ觀察到的,您的代碼將點轉換爲球座標。沒有什麼內在的錯誤 - 經緯度可以達到地球上的所有地方。如果一個人不關心如何將地球赤道面相對於太陽周圍的軌跡傾斜,那我可以。

沿着第一個w_ny不旋轉下一個參考軸的結果是,兩個點在赤道彼此相距1 km,在極點和90度的緯度上彼此靠近。儘管明顯的目的是讓它們在旋轉的地方保持相距1公里。

+1

你爲什麼要用3個角度? 2足夠了,我從哪裏得到'''? –

+1

@AndiFaust有'z'= z','y''= y'','x'''= x'''丟失。這三個計算是與「旋轉矩陣」的矩陣乘法。 – leemes

+0

如果你沿Y軸旋轉,Y不會改變等 –

0

如果你想變換座標系統而不是隻有你需要3個角度的點。但你是對的 - 對於轉換點2個角度就足夠了。詳情請詢問Wikipedia ...

但是,當你使用opengl你真的應該使用opengl函數,如glRotatef。這些函數將在GPU上進行計算 - 而不是CPU上的函數。該文檔是here

+0

我試圖使用'glrotatef',但它只是轉動繪圖,而不是座標,我需要旋轉座標以檢查碰撞 –

+0

哦,你想要做手動合謀檢查......我已經當我學習時實施了一個,這是一個痛苦和緩慢。也許你應該考慮使用[物理引擎](http://en.wikipedia.org/wiki/Physics_engine) – Andreas

4

什麼代碼幾乎確實:

  • 計算差矢量
  • 轉換載體導入spherical coordinates
  • 附加w_nx和wn_y到的傾斜和方位角(參見鏈接術語)
  • 轉換改性球座標返回到笛卡爾座標

有兩個p roblems:

  • 轉換是不正確的,你做的計算是兩個傾角矢量(一個沿x軸,其他沿y軸)
  • 即便計算是正確的,在球面座標變換是不一樣的使用矩陣和矢量數學將有助於在此情況下圍繞兩個軸旋轉

因此:

b = p - m 
b = RotationMatrixAroundX(wn_x) * b 
b = RotationMatrixAroundY(wn_y) * b 
n = m + b 

basic rotation matrices

0

像許多人所說的,你應該使用glRotatef來旋轉它進行渲染。對於碰撞處理,您可以通過在其渲染點上將其位置向量乘上堆棧頂部的OpenGL ModelView矩陣來獲取其世界空間位置。用glGetFloatv獲得該矩陣,然後將它乘以自己的矢量矩陣乘法函數,或者使用可以在線輕鬆獲得的許多矩陣之一。

但是,這將是一個痛苦!相反,請使用GL反饋緩衝區。這個緩衝區將簡單地存儲原始圖將被繪製的點,而不是實際繪製原始圖,然後你可以從那裏訪問它們。
This是一個很好的起點。