在進入豐富多彩3D世界中需要定以『視錐體』和『精靈頂點』.3D空間中頂點需有xyz座標.並且使用『透視投影』.距離相機越遠,物體越小.離相機較近對象覆蓋較進隊象.3D頂點包含『位置(xyz)』『顏色(rgba)』『法線(x,y,z)』並且完成3D頂點『模型』渲染
public class VERTICES3D {
擁有頂點顏色
boolean hasColor = false;
擁有紋理坐標
boolean hasTexCoord =false;
擁有法線
boolean hasNormal = false;
每個頂點所占空間
int vertex_size = 0;
最大頂點量
int vertex_max = 0;
最大索引量
int index_max = 0;
頂點數組
IntBuffer vertex_array = null;
索引數組
ShortBuffer index_array = null;
頂點緩存
int[] vertex_Buffer;
構造函式分配頂點記憶體,vertex_max為最大頂點量,index_max為最大索引量
VERTICES3D(int vertex_max,int index_max,boolean hasColor,boolean hasTexCoord,boolean hasNormal){
ByteBuffer buffer = null;
this.vertex_max = vertex_max;
this.index_max = index_max;
this.hasColor = hasColor;// 是否擁有頂點顏色
this.hasTexCoord = hasTexCoord;// 是否擁有紋理坐標
this.hasNormal = hasNormal;// 是否擁有法線
計算每頂點所占大小.顏色(rgbs)占4單元.紋理座標(uv)占2單元.3D座標(xyz)占3單元.每個整數占4字節
this.vertex_size = (3 + (hasColor ? 4 : 0) + (hasTexCoord ? 2 : 0) + (hasNormal ? 3: 0)) * 4;
vertex_Buffer = new int[vertex_max * vertex_size / 4];
因為OpenGL ES是以C API結口提供.無法直接使用JAVA數組.因此你需要C數組系統堆棧記憶體.而非JAVA虛擬機記憶體.需要 FloatBuffer分配頂點記憶體.vertex_max為最大頂點量.
buffer = ByteBuffer.allocateDirect(vertex_size * vertex_max);
將『網絡字節』改為『主機字節』或稱為『CPU字節』
buffer.order(ByteOrder.nativeOrder());
獲取頂點整數數組
vertex_array = buffer.asIntBuffer();
每索引占兩BYTE.即OpenGL ES每次最多渲染65536個頂點.
if(index_max > 0){
每個短整形占兩個字節.index_max為最大索引量
buffer = ByteBuffer.allocateDirect(index_max * Short.SIZE/8);
將『網絡字節』改為『主機字節』
buffer.order(ByteOrder.nativeOrder());
獲取頂點短整數數組
index_array = buffer.asShortBuffer();
}
}
將頂點提交給OpenGL數組並觸發
public void setVertices(float[] vertices,int offset,int count){
清空緩存.設定當前位置
vertex_array.clear();
int len = offset + count;
for(int i=offset, j=0; i < len; i++, j++)
vertex_Buffer[j] = Float.floatToRawIntBits(vertices[i]);
寫入數據.移動當前位置
vertex_array.put(vertex_Buffer, 0, count);
觸發
vertex_array.flip();
}
將頂點索引提交給OpenGL數組
public void setIndices(short[] indices,int offset,int count) {
清空緩存.設定當前位置
index_array.clear();
寫入數據.移動當前位置
index_array.put(indices, offset, count);
觸發
index_array.flip();
}
獲取索引量
public int getNumIndices(){
return index_array.limit();
}
獲取頂點量
public int getNumVertices(){
return vertex_array.limit() / (vertex_size/4);
}
綁定頂點數據
public void Bind(){
GL10 gl = GRAPHICS.gl;
啟用頂點數組
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
設置當前寫入位置0
vertex_array.position(0);
設置頂點指針,每個頂點包含xyz分量
gl.glVertexPointer(3, GL10.GL_FLOAT, vertex_size, vertex_array);
擁有頂點顏色
if(hasColor == true) {
啟用頂點顏色數組
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
設置當前寫入位置3
vertex_array.position(3);
設置顏色指針,RGBA四分量
gl.glColorPointer(4, GL10.GL_FLOAT, vertex_size, vertex_array);
}
擁有紋理坐標
if(hasTexCoord == true){
啟用紋理坐標
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
設置當前寫入位置
vertex_array.position(hasColor?7:3);
設置紋理坐標指針UV分量
gl.glTexCoordPointer(2, GL10.GL_FLOAT, vertex_size, vertex_array);
}
擁有法線
if (hasNormal = true) {
啟用法線
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
int offset = 3;
if (hasColor)
offset += 4;
if (hasTexCoord)
offset += 2;
設置當前寫入位置
vertex_array.position(offset);
設置法線指針,xyz分量
gl.glNormalPointer(GL10.GL_FLOAT, vertex_size, vertex_array);
}
}
取消綁定數據
public void Unbind(){
GL10 gl = GRAPHICS.gl;
關閉頂點紋理數組
if(hasColor)
gl.glDisableClientState(GL10.GL_COLOR_ARRAY );
關閉頂點顏色數組
if(hasTexCoord)
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
關閉法線數組
if (hasNormal)
gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
}
繪畫3D模型.需要先綁3D頂點
public void Draw(int mode,int offset,int count){
GL10 gl = GRAPHICS.gl;
繪畫頂點
if(index_array != null) {// 繪畫
index_array.position(offset);
gl.glDrawElements(mode, count, GL10.GL_UNSIGNED_SHORT, index_array);
}
else {
gl.glDrawArrays(mode, offset, count);
}
}
}
你必須登入才能發表留言。