延伸閱讀:[ Android OpenGL ES 教學(三)] 轉換相關方法 發表在 http://cheng-min-i-taiwan.blogspot.com/2011/04/android-opengl-es_3388.html
參考文章:OpenGL ES Tutorial for Android – Part II – Building a polygon 發表在http://blog.jayway.com/2009/12/04/opengl-es-tutorial-for-android-%E2%80%93-part-ii-building-a-polygon/
在OpenGL中建立多邊形是利用點連接而成,如下圖(摘自參考文章)
上述的圖形可以轉換成點的陣列如下所示:
// 點的陣列
private float vertices[] = { -1.0f, 1.0f, 0.0f, // 0, 左上角
-1.0f, -1.0f, 0.0f, // 1, 左下角
1.0f, -1.0f, 0.0f, // 2, 右下角
1.0f, 1.0f, 0.0f, // 3, 右上角
}
接下來我們來實作看看, 其步驟如下:
1. 建立Square類別
2. 以下是Square.java程式列表(新增的程式用藍色字表示)
package nkut.cce.smartliving.opengl; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.nio.ShortBuffer; import javax.microedition.khronos.opengles.GL10; public class Square { // 點的陣列 private float vertices[] = { -1.0f, 1.0f, 0.0f, // 0, 左上角 -1.0f, -1.0f, 0.0f, // 1, 左下角 1.0f, -1.0f, 0.0f, // 2, 右下角 1.0f, 1.0f, 0.0f, // 3, 右上角 }; // 連接點的次序 private short[] indices = { 0, 1, 2, 0, 2, 3 }; // 點的緩衝區 private FloatBuffer vertexBuffer; // 索引值緩衝區 private ShortBuffer indexBuffer; public Square() { // 浮點數是4位元組因此需要把點陣列長度乘以4 ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); vertexBuffer = vbb.asFloatBuffer(); vertexBuffer.put(vertices); vertexBuffer.position(0); // 短整數是2位元組因此需要把點陣列長度乘以2 ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2); ibb.order(ByteOrder.nativeOrder()); indexBuffer = ibb.asShortBuffer(); indexBuffer.put(indices); indexBuffer.position(0); } /** * 畫圖函式 * * @param gl */ public void draw(GL10 gl) { // 逆時鐘 gl.glFrontFace(GL10.GL_CCW); // 啟動CULL_FACE gl.glEnable(GL10.GL_CULL_FACE); // 刪除多邀形的背景 gl.glCullFace(GL10.GL_BACK); // 啟動點的緩衝區 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // 指定位置和資料格式 gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); // 以三點劃出三角形 gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer); // 除能點的緩衝區 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // 除能CULL_FACE gl.glDisable(GL10.GL_CULL_FACE); } }
3. 以下是OpenGLRenderer.java程式列表(新增的程式用藍色字表示)
package nkut.cce.smartliving.opengl; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLSurfaceView.Renderer; import android.opengl.GLU; public class OpenGLRenderer implements Renderer { private Square square; public OpenGLRenderer() { // 初始化 square = new Square(); } @Override public void onDrawFrame(GL10 gl) { // TODO Auto-generated method stub // 清除螢幕和深度緩衝區 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 以單位矩陣取代目前的矩陣 gl.glLoadIdentity(); // Z軸轉置 4 單位 gl.glTranslatef(0, 0, -4); // 畫出方形 square.draw(gl); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // TODO Auto-generated method stub // 設定新視域視窗的大小 gl.glViewport(0, 0, width, height); // 選擇投射的陣列模式 gl.glMatrixMode(GL10.GL_PROJECTION); // 重設投射陣 gl.glLoadIdentity(); // 計算視窗的寬高比率 GLU.gluPerspective(gl, 45.0f, (float) width / (float) height, 0.1f, 100.0f); // 選擇MODELVIEW陣列 gl.glMatrixMode(GL10.GL_MODELVIEW); // 重設MODELVIEW陣列 gl.glLoadIdentity(); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // TODO Auto-generated method stub // 設定背景顏色為黑色, 格式是RGBA gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // 設定流暢的陰影模式 gl.glShadeModel(GL10.GL_SMOOTH); // 深度緩區的設定 gl.glClearDepthf(1.0f); // 啟動深度的測試 gl.glEnable(GL10.GL_DEPTH_TEST); // GL_LEQUAL深度函式測試 gl.glDepthFunc(GL10.GL_LEQUAL); // 設定很好的角度計算模式 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); } }
4. 執行結果
作者已經移除這則留言。
回覆刪除感謝您的提醒
刪除想請問一下,每個角的三個數字-1.0f, 1.0f, 0.0f,是不是分別是X Y Z啊!?
回覆刪除