使用鼠標自由旋轉三維圖形的算法和思路

轉自www.eternity3.com.cn

考慮鼠標移動在一個半球面而不是普通的平面,如圖所示。

鼠標移動時,不是簡單從屏幕上的A點移動到B點,而是在球O上沿着弧AB移動到了B點。
也就是說,向量OA沿着圓O旋轉到了向量OB。我們便可以將我們的圖形也按照同樣的方式進行旋轉。
因此我們需要知道的是旋轉的角度和旋轉的法向量。
步驟:
1.計算鼠標在半球面上的座標
我們可以通過鼠標在屏幕的平面座標計算鼠標在半球面上的座標
假設鼠標的屏幕座標爲(Xs, Ys),半球面座標爲(Xh, Yh, Zh)。顯然有
Xh = Xs
Yh = Ys
Zh^2 = r^2–Xh^2–Yh^2
其中r爲半球半徑,一般可以設置爲窗口高度的一半。
這樣便可以求出向量OA和向量OB的座標。

2.計算旋轉角度
有了向量OA和向量OB的座標,利用餘弦定理我們可以求得角AOB的大小,不過這個計算很複雜,開銷很大。
我們可以考慮用A到B的球面距離,即 弧AB的長度 / 圓O的周長 * 360度。
不過弧長也不是那麼好算,好在每次鼠標移動的間隔都不大,我們可以簡單的使用弦AB的距離來近似弧AB的長度。
因此我們的算法變得很簡單。
角AOB = 弦AB的長度 / 圓O的周長 * 360度
弦AB的長度可以用兩點間距離公式求得,即 d^2 = (Xa-Xb)^2+(Ya-Yb)^2+(Za-Zb)^2。

3.計算旋轉法向量
旋轉法向量n是垂直於向量OA和向量OB所決定的平面的,所以只需要求得向量OA與向量OB的外積(也就是叉乘),就可求得旋轉法向量n。
即 n = OA×OB。

4.OpenGL的矩陣乘法
有了旋轉角度和旋轉的法向量就可以使用glRotate函數來旋轉圖形了,不過這裏有一點需要注意的地方:
例如我們旋轉一個圖形:

程序代碼

glLoadIdentity();
glRotatef(theta, axis[0], axis[1], axis[2]);
drawCube();


在這裏的glRotate函數實際是產生了一個旋轉矩陣,並將其右乘到當前矩陣上,所以當前矩陣的變化爲:M = E·R。
如果我們繪製的圖形的某一點是P,那麼它在繪製時候,將被旋轉到點P’ = M·P = E·R·P。
當我們第二次旋轉的時候,glRotate函數又產生來一新的旋轉矩陣R’,它再次被右乘到當前矩陣上,所以當前矩陣的變化爲:M = E·R·R’。
那麼當我們再次繪製圖形時,P點將被旋轉到P’ = M·P = E·R·R’·P。
此時我們發現P點實際上是先按照第二次的旋轉矩陣旋轉,再按照第一次的旋轉,與我們想要的結果剛好相反。
因此我們需要將每一次的旋轉矩陣左乘到當前矩陣上,所以我們需要下面的步驟:

程序代碼

glLoadIdentity();
glRotatef(theta, axis[0], axis[1], axis[2]);
glMultMatrixf(lastMatrix);
glGetFloatv(GL_MODELVIEW_MATRIX, lastMatrix);


我們用lastMatrix保存當前矩陣,然後將其右乘到新的旋轉矩陣上,實際相當於將新的旋轉矩陣左乘到當前矩陣上,這樣做了之後才能實現我們想要的目的。

下面這個是編譯好的示例程序及源代碼:點擊下載

 
發佈了29 篇原創文章 · 獲贊 1 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章