Vertex (頂點)
頂點是3D建模時用到的最小構成元素,頂點定義為兩條或是多條邊交會的地方。在3D模型中一個頂點可以為多條邊,面或是多邊形所共享。一個頂點也可以代表一個點光源或是Camera的位置。下圖中標識為黃色的點為一個頂點(Vertex)。
在Android系統中可以使用一個浮點數數組來定義一個頂點,浮點數數組通常放在一個Buffer(java.nio)中來提高性能。
比如:下圖中定義了四個頂點和對應的Android 頂點定義:
上述的圖形可以轉換成點的陣列如下所示:
// 點的陣列
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, 右上角 }
其中 0.0f (沒有z軸)
為了提高性能,通常將這些數組存放到java.io 中定義的Buffer類中:
// 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);
有了頂點的定義,下面一步就是如何將它們傳給OpenGL ES庫,OpenGL ES提供一個成為”管道Pipeline”的機制,這個管道定義了一些“開關”來控制OpenGL ES支持的某些功能,缺省情況這些功能是關閉的,如果需要使用OpenGL ES的這些功能,需要明確告知OpenGL “管道”打開所需功能。因此對於我們的這個示例,需要告訴OpenGL庫打開Vertex buffer以便傳入頂點坐標Buffer。要注意的使用完某個功能之後,要關閉這個功能以免影響後續操作:
// Enabled the vertex buffer for writing and to be used during rendering.
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);// OpenGL docs.
// Specifies the location and data format of an array of vertex
// coordinates to use when rendering.
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); // OpenGL docs.
When you are done with the buffer don't forget to disable it.
// Disable the vertices buffer.
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);// OpenGL docs.
Edge(邊)邊定義為兩個頂點之間的線段。邊是面和多邊形的邊界線。在3D模型中,邊可以被相鄰的兩個面或是多邊形形共享。對一個邊做變換將影響邊相接的所有頂點,面或多邊形。在OpenGL中,通常無需直接來定義一個邊,而是通過頂點定義一個面,從而由面定義了其所對應的三條邊。可以通過修改邊的兩個頂點來更改一條邊,下圖黃色的線段代表一條邊:
Face (面)
在OpenGL ES中,面特指一個三角形,由三個頂點和三條邊構成,對一個面所做的變化影響到連接面的所有頂點和邊,面多邊形。下圖黃色區域代表一個面。
定義面的頂點的順序很重要在拼接曲面的時候,用來定義面的頂點的順序非常重要,因為頂點的順序定義了面的朝向(前向或是後向),為了獲取繪製的高性能,一般情況不會繪製面的前面和後面,只繪製面的“前面”。雖然“前面”“後面”的定義可以應人而易,但一般為所有的“前面”定義統一的頂點順序(順時針或是逆時針方向),故只能選一個,一律採取逆時針方向(CCW),指定法向量向外(弗萊明右手定則)。
下面代碼設置逆時針方法為面的“前面”:
gl.glFrontFace(GL10.GL_CCW);
打開 忽略“後面”設置:
gl.glEnable(GL10.GL_CULL_FACE);
明確指明“忽略“哪個面的代碼如下:
gl.glCullFace(GL10.GL_BACK);
Polygon (多邊形)
多邊形由多個面(三角形)拼接而成,在三維空間上,多邊形並一定表示這個Polygon在同一平面上。這裡我們使用缺省的逆時針方向代表面的“前面Front),下圖黃色區域為一個多邊形。
來看一個多邊形的示例在Android系統如何使用頂點和buffer 來定義,如下圖定義了一個正方形:逆時針方向(弗萊明右手)
private short[] indices = { 0, 1, 2, 0, 2, 3 };
To gain some performance we also put this ones in a byte buffer.
// short is 2 bytes, therefore we multiply the number if vertices with 2.
ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
ibb.order(ByteOrder.nativeOrder());
ShortBuffer indexBuffer = ibb.asShortBuffer();
indexBuffer.put(indices);
indexBuffer.position(0);
Render (渲染)我們已定義好了多邊形,下面就要了解如和使用OpenGL ES的API來繪製(渲染)這個多邊形了。 OpenGL ES提供了兩類方法來繪製一個空間幾何圖形:
* public abstract void glDrawArrays(int mode, int first, int count) 使用VetexBuffer 來繪製,頂點的順序由vertexBuffer中的順序指定。
* public abstract void glDrawElements(int mode, int count, int type, Buffer indices) ,可以重新定義頂點的順序,頂點的順序由indices Buffer 指定。
前面我們已定義裡頂點數組,因此我們將採用glDrawElements 來繪製多邊形。
同樣的頂點,可以定義的幾何圖形可以有所不同,比如三個頂點,可以代表三個獨立的點,也可以表示一個三角形,這就需要使用mode 來指明所需繪製的幾何圖形的基本類型。下列為幾個mode的類型:
GL_POINTS 繪製獨立的點。
GL_LINE_STRIP 繪製一系列線段。
GL_LINE_LOOP 類同上,但是首尾相連,構成一個封閉曲線。
GL_LINES 頂點兩兩連接,為多條線段構成
GL_TRIANGLES 每隔三個頂點構成一個三角形,為多個三角形組成。
GL_TRIANGLE_FAN 每相鄰三個頂點組成一個三角形,為一系列相接三角形構成。
GL_TRIANGLE_STRIP 每相鄰三個頂點組成一個三角形,為一系列相接三角形構成。
下列就是依照OpenGL ES 定義的繪出一個方形矩陣 Squire Class
OpenGLRenderer.java程式列表加入:
// 初始化
Square 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);
}
執行結果如下:
沒有留言:
張貼留言
請留言~一起討論吧~