Android上OpenGL開發一些經驗記錄(上)

來源:互聯網
上載者:User
Android沿用了J2ME的OPENGL ES API.

相比C版本的OpenGL,Opengl ES 沒有glu和glut庫,而且只能畫三角形(多邊形需要三角化)。

沒有直接的drawXXX 方法,只有通過 glVertiexPointer傳入頂點畫圖。

另外參數上,沒有指標和C風格的數組,Java需要用Buffer類來代替這個。

先看android的glVertexPointer :

GL10.glVertexPointer(int size, int type, int stride, Buffer pointer):

這個方法為 後面openGL繪圖準備頂點資料。 

size : 代表每個頂點包含幾個座標參數 ,如pointer的buffer中只含有 x,y座標, 則傳2, OpenGL會預設使用0作為z座標。如果包含 x,y,z 座標,則傳3。其他值在這裡都不適用。type : 是一個枚舉值,可以為 GL_FLOAT和 GL_FIXED,浮點數可對應java 的 float,要求pointer為 FloatBuffer.      GL_FIXED意為定點數,長度4位元組,高16位表示整數部分,低16位表示小數部分。傳入int值前需要先左移16位(即需擴大 0x10000倍)。要求pointer為IntBuffer.      stride :指每個元素之間,間隔多少個值。加入buffer中座標點數值間緊密相連,那麼stride就是0,如果點1,點2間還有不用到的值,則stride就是這種值的個數。pointer:這是最需要注意的一個參數,也是Java版OpenGL特有的。Buffer類型是一個基類,具體的類型是 FloatBuffer還是IntBuffer要根據前面type參數來決定。         Java中的 Buffer分兩種,一種direct,一種非direct.這裡只支援 DirectBuffer,也就是通過ByteBuffer.allocateDirect(int cap) 分配而來的buffer.         通過allocateDirect 得到的是一個 ByteBuffer,實際使用時,如果要作為FloatBuffer,可以通過 ByteBuffer.asFloatBuffer來得到,IntBuffer也同樣。         做到這些當然還不夠,ByteOrder也對這個參數有影響。當的ByteBuffer作為FloatBuffer,則float的4位元組預設是按照小端排列在directBuffer中,在         某些大端的裝置中這個buffer的格式就不正確,需要根據裝置設定ByteOrder.         所以以FloatBuffer為例,建立方法如下:         FloatBuffer buffer = ByteBuffer.allocateDirect(1024).order(ByteOrder.nativeOrder()).asFloatBuffer();         有了FloatBuffer,我們還需要將實際頂點座標傳入這個buffer。這隻需要調用 FloatBuffer.put(float)的方法即可。         注意放頂點座標是x,y...的格式,還是x,y,z...的格式要和前面第一個參數 size是2還是3統一。         所有的值放完以後,需要調用 buffer.rewind()或者 buffer.position(0),將buffer內遊標置回0,否則OpenGL會從最後一次put的下一個位置開始讀取。         關於三角化的演算法:Android的OpenGL API 畫多邊形目前只支援 triangle_fan,triangles, triangle_strip 三種。如果只有簡單無洞的凸多邊形,只需要將所有點當作triangle_fan的頂點就可以畫出。如果存在凹多邊形,就需要進行三角化(當然凸多邊形也可以三角化,保持邏輯上的統一)。有個最簡單的三角化演算法叫做 ear clipping三角化。幾何上非常容易理解:一個多邊形的一個頂點,和它相鄰兩個頂點可以組成一個三角形,如果這個三角形內部不存在這個多邊形的其他頂點,就可以把這個頂點和相鄰點組成的三角形當作一個ear.這個ear可以被切下來(沿兩個相鄰頂點切)。每切一次,得到一個三角形和一個少了一個頂點的多邊形,然後再對這個多邊形做同樣操作,直到剩下的這個多邊形也只剩下3個頂點。如此一來,這個多邊形被完全分解為3角形。要把把幾何上的操作變成代碼,只要解決這幾個問題:#如何判斷多邊形的一串頂點是逆時針還是順時針排列的?  - 從某個頂點指向它下一個頂點,可以得到一個向量,多邊形有幾條邊就得到幾個向量,如果所有相鄰兩個向量的叉積(前一個向量和後一個向量的叉積)之和大於0,則排列是逆時針的,反之是順時針的  (根據右手座標系判斷,一系列逆時針向量圍成的面積是指向z軸正向的),為0有兩種情況,這串點是直線,或者多邊形某兩條邊交叉,這種多變形不符合這個三角化演算法的條件。#根據頂點順逆情況,調整頂點排列,保證逆時針排序,則可以得到如下結論: - 如果相鄰兩個向量,前一個向量和後一個向量叉積,值為正,則兩個向量連接點這個頂點是凸點,值為負則為凹點。 - 如果有相鄰3個頂點 p1,p2,p3 組成三角形,有另外一個頂點 P,如何判斷P是否在三角形內? 分別做如下幾個叉積p2P X p1p2, p3P X p2p3 , p1P X p3p1 ,如果這3個叉積同為正或同為負,則這個頂點在三角形內部。 關於 glEnableClientState, glDisableClientState,glEnableClientState(int cap);cap : GL_COLOR_ARRAYGL_EDGE_FLAG_ARRAYGL_FOG_COORD_ARRAYGL_INDEX_ARRAYGL_NORMAL_ARRAYGL_SECONDARY_COLOR_ARRAYGL_TEXTURE_COORD_ARRAYGL_VERTEX_ARRAY是用來啟用或者關閉和這些數組功能。如同前面的glVertexPointer ,還有別的諸如 glColorPointer, glEdgeFlagPointer等等介面,glVertexPointer描述頂點位置,其他的描述頂點或者平面的屬性。這些數組預設都是disable狀態,如果用這兩個介面enable了某個數組,那麼當glDrawArrays 調用之前必須把相應的數組準備好。否則draw不能成功。所以如果不準備傳入某個數組,draw之前要先 disable這個數組(如果前面enable過)。反之如果要使用某個數組,也要事先enable。

 還有Java中缺少的API,比如沒有glPerspective的時候如何用glFrustm實現glPerspective,以及沒有gluLookAt的時候如何用modelView來得到同樣效果。將在之後文章裡面解說。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.