Jayway Team Blog:OpenGL ES Tutorial for Android –Part II– Building a polygon
3D Graphics using OpenGL ES (Including Nehe's Port)Example 2
來完成建立多邊形這個教學!
在開始建立程式前,先補充說明在建立3D模型時,需要用到的一些子元素
(頂點、邊、表面和多邊形),他們都能獨立的分別被實做出來。
- 頂點(Vertex)
頂點是構成3D模型的最小建物,他是由兩個或兩個以上的邊交界而成的點。一個頂點可以在所有相關聯的邊、面和多邊形中共用。頂點也可以是照相機或光源位置的表示。在Android中,我們浮點數陣列來定義它,同時我們將它放在byte buffer中以獲取較佳的效能。
private float vertices[] = {
-1.0f, 1.0f, 0.0f, // 0, Top Left
-1.0f, -1.0f, 0.0f, // 1, Bottom Left
1.0f, -1.0f, 0.0f, // 2, Bottom Right
1.0f, 1.0f, 0.0f, // 3, Top Right
};
// a float is 4 bytes, therefore we multiply the number if vertices with 4.
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
FloatBuffer vertexBuffer = vbb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
要注意的一個浮點數是4個位元組,將它和頂點數相乘,才可以正確的配置buffer大小。- 邊(Edge)
邊是在兩個頂點之間的線段。它們是表面和多邊形的邊緣線。在3D模型中,便可以在 兩個鄰近表面或多邊形之間共用。轉換一條邊,影響所有相連接的頂點,面和多邊形 。在OpenGL ES中,我們不能定義邊,你只能通過給定的頂點定義面,這將至少構建三條邊。如果你想要修改一條邊,你應該改變產生這條邊的兩個頂點。
- 面(face)
面是一個三角形,面就是這三個頂點和三個邊所圍成的表面,變換一個面影響所有關聯 的頂點,邊和多邊形。對於這些元素的介紹先到這裡,Jayway還有一些細部的介紹,都還蠻有價值的,但我相信大家沒看到code就很難過,我們就先來畫畫三角形吧!
Triangle.java
Triangle.java
com.hanshuo.opengl.tutorial; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; /* * A triangle with 3 vertices. */ public class Triangle { private FloatBuffer vertexBuffer; // 頂點陣列的緩衝 private ByteBuffer indexBuffer; // 索引緩衝 private float[] vertices = { // 三角形的頂點們 0.0f, 1.0f, 0.0f, // 0. 頂 -1.0f, -1.0f, 0.0f, // 1. 左下 1.0f, -1.0f, 0.0f // 2. 右下 }; private byte[] indices = { 0, 1, 2 }; // 連結這些點的順序 // 建構子 – 建立資料陣列的緩衝 public Triangle() { // 建立頂點陣列緩衝. 頂點是浮點數要乘4個byte. ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); // 使用原生順序 vertexBuffer = vbb.asFloatBuffer(); // 轉換位元組緩衝為浮點數 vertexBuffer.put(vertices); // 將資料複製到緩衝 vertexBuffer.position(0); // 倒轉歸零 //建立頂點索引陣列緩衝 indexBuffer = ByteBuffer.allocateDirect(indices.length); indexBuffer.put(indices); indexBuffer.position(0); } // 渲染這個圖形 public void draw(GL10 gl) { // Enable vertex-array and define the buffers gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); // int size, int type, int stride, Buffer pointer // size: 頂點的座標數 (只有2,3,4). // type: 頂點座標的資料型態, GL_BYTE, GL_SHORT, GL_FIXED, or GL_FLOAT // stride: 連續頂點可以有幾個byte的offset. 0是緊密的包裝? // 透過index-array繪製元素 gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer); // int mode, int count, int type, Buffer indices) // mode: GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, or GL_TRIANGLES // count: 有幾個元素將要被渲染 // type:頂點的資料型態 (must be GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT). // indices:index array的指標 gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); } }
TutorialPartI.java (藍色是新的程式碼)
package com.hanshuo.opengl.tutorial; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.GLU; import android.opengl.GLSurfaceView.Renderer; public class OpenGLRenderer implements Renderer { Triangle triangle; public OpenGLRenderer() { // Set up the data-array buffers for these shapes (多了這裡)
triangle = new Triangle();
//
(多了這裡)} public void onSurfaceCreated(GL10 gl, EGLConfig config) { // 將背景設成紅色 (rgba). gl.glClearColor(1.0f, 0.0f, 0.0f, 0.0f); // 允許陰影平滑, 預設也可以,不是必須的 gl.glShadeModel(GL10.GL_SMOOTH); // 深度緩衝設置 gl.glClearDepthf(1.0f); // 允許深度測試 gl.glEnable(GL10.GL_DEPTH_TEST); // 深度檢測類型 gl.glDepthFunc(GL10.GL_LEQUAL); // 精細度設置 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); } public void onDrawFrame(GL10 gl) { // 清除螢幕和深度緩衝 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
// Reset model-view matrix
(多了這裡)
gl.glTranslatef(-1.5f, 0.0f, -6.0f);
// Translate left and into the screen
(多了這裡)
triangle.draw(gl);
// Draw triangle
(多了這裡)}
執行結果:
沒有留言:
張貼留言