延伸閱讀:[ 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啊!?
回覆刪除