[摘要]Android平臺是手機界的一股新生力量,它是完全免費并開源的,在Android上主要使用OpenGL ES來進行3D開發(fā)。因此,將探討在3D場景中如何實現(xiàn)對三維物體的觸摸控制,比如如何選中,移動,旋轉等,并給出一個比較高效的選中物體的算法和一個簡單實用的旋轉物體的算法,以及在此基礎上開發(fā)一個簡單的魔方游戲,游戲程序在:http://sites.google.com/site/quillchan/android。
[關鍵詞]AndroidOpenGL ES觸摸控制三維選中三維旋轉
中圖分類號:TP2文獻標識碼:A文章編號:1671-7597(2009)1210091-01
Android是Google開發(fā)的基于Linux平臺的開源手機操作系統(tǒng)。它包括操作系統(tǒng)、用戶界面和應用程序——移動電話工作所需的全部軟件,而且不存在任何以往阻礙移動產業(yè)創(chuàng)新的專有權障礙。
在Android上主要使用OpenGL ES來進行3D開發(fā)。OpenGL ES(OpenGL for Embedded Systems)是OpenGL三維圖形API的子集,針對手機、PDA和游戲主機等嵌入式設備而設計。Android 1.5中帶的是OpenGL ES 1.0版本,它是以OpenGL 1.3規(guī)范為基礎的。本文將對3D場景中物體的觸摸控制進行研究,并給出實現(xiàn)的算法。本文所做的論述都是基于Android 1.5,OpenGL ES 1.0。
一、如何選中三維物體
OpenGL ES并沒有像OpenGL一樣提供有選擇模式,因此需要自己去實現(xiàn)選中物體。
算法思路:作一條直線,該直線經過屏幕上的觸點并且與屏幕垂直;求出該直線在世界坐標系中的方程,然后再判斷該直線與三維物體是否有交點,如有交點,則選中該物體。
下面以立方體為例(不規(guī)則的三維物體都可以轉化為規(guī)則物體來操作),來說明一下算法的具體過程。設(x,y)為觸點的屏幕坐標,則得到視點坐標為(x,windowHeighty),記作(winX,winY)。分別給該點配上深度坐標,得到兩點A1(winX,winy,0),A2(winX,winy,1)。通過gluUnProject轉化到世界坐標,得到世界坐標系下一條直線的兩點:
GluUnProject(A1)-->S2(Sx2,Sy2,Sz2)
GluUnProject(A2)-->E2(Ex2,Ey2,Ez2)
現(xiàn)在問題就剩如何求直線與立方體的交點了。立方體一共有六個面,建立模型的時候頂點坐標都是已知的,因此可以得到立方體每個面的空間方程表示,再分別求出每個面與直線的交點。
1.設平面上3點為ptA,ptB,ptC;構造一個平面:
plane(ptA,ptB,ptC)。
2.再根據兩點構造一條直線:
line(S2,E2)。
3.求出交點:
crossPoint=cross(plane,line)。
4.再判斷該點是否在相交平面的正方形內(點到正方形兩對邊的距離之和如果大于邊長,則該點在正方形外部),如果是,說明選中了該物體。
5.為了提高效率,可以先判斷立方體都有哪些面朝向屏幕外側,然后再計算這些面與直線的交點就可以了。方法如下:由兩點S2,E2得到一個向量E2->S2(朝向屏幕外側),分別求該向量與立方體各個面的法線(方向朝外)的夾角,如果夾角小于90度,說明該面朝向屏幕外側,進而判斷直線與該面的交點是否落在這個面上。
先求平面朝外的法向量,設平面上的三點ptA,ptB,ptC(點的順序要按照右手法則):normal=(ptBptA)X(ptCptA)(X代表向量叉乘)。
再求E2->S2和法向量的夾角余弦值,如果余弦值大于零小于一,說明夾角小于90度,該面朝向屏幕外側。
二、如何旋轉三維物體
三維空間的旋轉有三個自由度,大家自然會想到使用三個對應于三條坐標軸的角度去記錄,即:
GlRotatef(ax,1,0,0)
GlRotatef(ay,0,1,0)
GlRotatef(az,0,0,1)
這就是我們通常所說的Euler Angle方法。但是這種方法存在一個萬向節(jié)死鎖的問題。
如何來避免萬向節(jié)死鎖呢?實際上數學上有種偏軸角(Axis Angle)的定義。先定出兩個旋轉向量,然后求出他們之間的最少旋轉角度,再繞這兩個向量的法線旋轉該角度即可。由于每次只繞一個固定的軸旋轉,因此并不會產生萬向節(jié)死鎖的問題。
這里我自己實現(xiàn)了一種類似于偏軸角的旋轉定義,但是比偏軸角的方法更符合用戶在屏幕上的旋轉操作。方法是通過將觸點映射到三維坐標上,對前后相鄰的兩個觸點(手指滑動形成)作一條直線,該條直線和垂直于屏幕的另一條直線形成一個平面,該平面的法線即是物體的旋轉軸,再通過觸點的位移得到合適的旋轉角度,把物體繞該法線旋轉即可。
記手指在屏幕上滑動形成的向量為V0;垂直于屏幕向外的向量為V1;則可得到旋轉軸:
axis=cross(V0,V1)
記手指在屏幕上滑動的距離為ds;通過設定屏幕大小和角度的比例因子TOUCH_SCALE_FACTOR,得旋轉角度:
angle=ds*TOUCH_SCALE_FACTOR
從而對物體進行旋轉glRotatef(angle,axis.x,axis.y,axis.z)。
三、結論
觸摸控制對于目前流行的3D游戲和3D桌面的開發(fā)都具有十分重要的意義,3D開發(fā)者們根據本文對觸摸控制所做的分析可以很好地理清思路,避開一些因為平臺不同碰到的瑣碎問題,節(jié)省開發(fā)時間。本文針對立方體這個特例在選中和旋轉物體的時候提供了高效的算法,也可以為別的規(guī)則的空間模型提供一個參考,具體的算法實現(xiàn)起來不同,思路大同小異。
參考文獻:
[1]Foley van Dam,Feiner,Hughes.Introduction to computer graphics [M].[s.1.]:Addison-Wesley Publishing.
[2]Dava Shreiner,OPENGL編程指南[M].北京:機械工業(yè)出版社,2008.
[3]Samual R.Buss,3D計算機圖形學(OPENGL版)[M].北京:清華大學出版社,2006.
作者簡介:
陳建偉,碩士,主要研究領域:手機嵌入式系統(tǒng),Android應用開發(fā)。