2012-12-19 71 views
4

我一直在尋找在Stack Overflow中OpenGL ES中2D選擇的介紹。我主要看到有關3D的問題。Android OpenGL ES:你如何選擇2D對象?

我正在使用OpenGL ES在Android 4.0.3上設計基於2D圖層的關卡編輯器。在關卡編輯器中,屏幕中央有一個2D,黃色,正方形的物體。我想要的只是檢測用戶是否觸摸了該物體。

enter image description here

在關卡編輯器,沒有任何重疊的瓷磚。相反,它們並排放置,就像MS Paint中位圖圖像中的兩個附近像素一樣。我的目的是在關卡編輯器中爲每個方形對象單獨檢測觸摸事件。

使用簡單的頂點數組創建對象,並使用GL_TRIANGLES繪製2個平直的直角三角形。沒有操作,也沒有從文件或任何東西加載。我唯一知道的是,如果用戶觸摸任何一個黃色三角形,那麼這兩個黃色三角形都將被選中。

任何人都可以提供一個提示,我需要如何做到這一點?提前致謝。

編輯:

這是draw()功能:

public void draw(GL10 gl) { 
    gl.glPushMatrix(); 
    gl.glTranslatef(-(deltaX - translateX), (deltaY - translateY), 1f); 
    gl.glColor4f(1f, 1f, 0f, 1f); 
    //TODO: Move ClientState and MatrixStack outside of draw(). 
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); 
    gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertices); 
    gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 6); 
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); 
    gl.glPopMatrix(); 
} 

編輯2:

我仍然缺少一些信息。你在用相機嗎?或在模型渲染之前推動其他 矩陣?例如,如果您使用的是 正交相機,你可以很容易地unproject你的屏幕座標 [x_screen,y_screen]像這樣(y是類似):

我不使用相機,但我可能使用正交投影。再次,我不知道,因爲我只是使用一個常見的OpenGL函數。我推擠和彈出矩陣,因爲我計劃將許多平鋪(正方形2D對象)與不同的平移矩陣集成在一起。沒有兩個瓷磚會具有相同的平移矩陣M.

2D投影是否與正射投影相同?我沒有看到兩者之間的任何區別。

下面是當表面創建(一類擴展GLSurfaceView,貫徹GLSurfaceView.Renderer)初始設置:

public void onSurfaceChanged(GL10 gl, int width, int height) { 
    gl.glViewport(0, 0, width, height); 
} 

public void onSurfaceCreated(GL10 gl, EGLConfig arg1) { 
    reset(); 
} 
public void onDrawFrame(GL10 gl) { 
    clearScreen(gl); 
    gl.glMatrixMode(GL10.GL_PROJECTION); 
    gl.glLoadIdentity(); 
    gl.glOrthof(0f, super.getWidth(), 0f, super.getHeight(), 1, -1); 
    gl.glMatrixMode(GL10.GL_MODELVIEW); 
    gl.glLoadIdentity(); 
    canvas.draw(gl); 
} 

private void clearScreen(GL10 gl) { 
    gl.glClearColor(0.5f, 1f, 1f, 1f); 
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT); 
} 

回答

2

一個基本的方法是下列:

  1. 定義邊界框對每個「可觸摸」對象。這可能是 只是一個矩形(x,y,寬度,高度)。
  2. 當你在世界上更新一個瓷磚時,你更新了它的邊界框(完全在世界座標中) 。
  3. 當用戶觸摸屏幕時,您必須取消投影屏幕 座標到世界座標
  4. 檢查未投影點是否與任何邊界框重疊。

關於prev項目的一些提示。 [編輯]

  • 1和2。你應該有跟蹤你在哪裏呈現 您的瓷磚。存儲他們的位置和大小。一個矩形是一個方便結構的 。在你的例子中,它可以像這樣計算,如 。模型更改時必須重新計算它。讓我們把它稱爲矩形R:

    r.x = yourTile.position.x -(deltaX - translateX) 
    r.y = yourTile.position.y -(deltaY - translateY) 
    r.width= yourTile.width //as there is no model scaling 
    r.height = yourTile.height// 
    
  • 3 - 如果你正在使用 正視相機,你可以很容易地unproject屏幕 座標[x_screen,y_screen]像這樣(y是類似):

    x_model = ((x_screen/GL_viewport_width) -0.5)*camera.WIDTH + Camera.position.x 
    
  • 4 - 對於每一個矩形的檢查[x_model; y_model]在裏面。

[第二編輯]通過要更新矩陣的方式,你可以考慮使用的是相機postition surfaceView.width()/ 2,surfaceView.height()/ 2。你在屏幕上匹配1個像素到世界上的1個單位,所以你不需要任何東西。你可以在我的公式中替換這些值,並得到x_screen = x_model - (你需要翻轉觸摸事件的Y部分,因爲Y在Java中向下增長,GL向上)。

最後的話。如果用戶觸摸point [x,y],檢查[x,screenHeight-y] *是否碰到了一些矩形並完成了。 做一些調試,記錄觸摸點,看看它們是否如預期的那樣。生成矩形並查看它們是否與屏幕上顯示的內容相匹配,然後檢查點是否在矩形內。

我必須告訴你,你不應該把相機設置爲屏幕尺寸,因爲你的應用在不同的設備上看起來會有很大的不同。這本身就是一個話題,所以我不會再深究,但是考慮根據世界單位來定義你的模型 - 獨立於屏幕尺寸。這是越來越脫離主題,但我希望你已經看到了你需要知道的東西!

*翻轉我告訴過你。 PS:堅持正投影(使用透視會更復雜)。

+0

對於#2,我沒有說它們是靜態的,但是你暗示着我寫它的方式,它會使對象成爲「靜態」。我該怎麼辦? 對於#3,我增加了一些代碼給你看。 –

+0

我已添加一些更多信息。請檢查。 –

+0

您現在應該可以檢測到一個選擇,但我建議你對相機的研究,並從視圖中分離模型/網格。這肯定會改善你的代碼,當然!想象一下,你做了一些翻譯,縮放,您將看到的內容的用戶,放大/縮小,而且還有檢測的選擇,並且可以碰撞,使他們不重疊......只有瓷磚,它應該是幾乎微不足道的,如果你有一個組織良好的代碼! –

0

您檢查了LibGDX

使用OpenGL ES使生活變得如此簡單。

+0

這不是我要找的解決方案。請重新閱讀這個問題。謝謝。 –

1

請允許我發表第二個回答你的問題。這是完全更高層次/哲學的。可能是一個愚蠢的,無用的答案,但是,我希望它能幫助新來計算機圖形學的人將它的思想改變爲「圖形模式」。

你不能真的在屏幕上選擇一個三角形。那個廣場不是2個三角形。那個正方形只是一堆黃色像素。OpenGL需要一些頂點,連接它們,處理它們併爲屏幕上的一些像素着色。在圖形管道的一個階段,甚至幾何信息都會丟失,而且只有孤立的像素。這與紙上打印機打印的信件類似。你通常不處理來自紙(好吧,也許條形碼閱讀器的功能:d)信息

如果您需要進一步處理您的圖紙,你必須對他們進行建模,並用自己的輔助數據結構對其進行處理。這就是爲什麼我建議你創建一個矩形來模擬你的瓷磚。你創建你想象中的對象的「世界」,然後渲染它們到屏幕上。用戶觸摸事件不屬於同一個世界,因此您必須將屏幕座標「翻譯」爲您的世界座標。然後你改變你的世界中的某些東西(可能是用戶拖動她的手指,並且你必須移動一個對象),然後再返回告訴OpenGL來渲染你的世界。

你應該在你的模式,而不是視圖操作。網格更像是一個視圖,所以你不應該將它們與模型信息混合在一起,這是分離兩個事物的好實踐。 (請專家指正,我很圖形愛好者)