1. 程式人生 > >openGL畫三角形---openGL學習筆記(四)

openGL畫三角形---openGL學習筆記(四)

在openGL中,所有面狀圖形的繪製都是使用畫三角形方法,而針對不同需求,openGL給出三種不同的畫三角形方法:

①traingles:畫三角形集


②traingle_strip:畫三角形帶


③traingle_fan:畫三角形扇面


畫三角形集在筆記(一)中已經實現過,現在我們用三角形帶渲染一個正方形,效果圖如下。

onSurfaceCreated()和onSurfaceChanged()兩個方法與之前一模一樣,現在只看onDrawFrame()方法:

首先畫三角形帶的原理是,依次後推一位,比如:按逆時針順序給定四個點,A、B、C、D,呼叫畫三角形帶方法後,openGL的繪製順序是,ABCA(第一個三角形)--->BCDB(第二個三角形)以此類推,這樣明顯不是一個正方形。

所以,我們要用畫三角形帶的方式渲染一個正方形,那麼點的順序就是逆時針方向A-->B-->D-->C.

知道了點的順序後就可以寫onDrawFrame()方法了,同樣的,還是先清除顏色緩衝區,設定繪圖顏色,設定矩陣模式,載入單位矩陣,放置眼球位置,設定旋轉角度(如需要)。

做好了這些工作之後,就要設定頂點座標了,為方便起見,我們在Z=0的平面上繪製正方形,並且正方形與Y軸左右對稱,那麼四個點的Z軸座標就都是0,設定XY軸座標之前,我們先定義一個半徑r=0.5f,那麼A點座標就為-r,r,0,相應的B點座標為-r,-r,0,C點座標為r,r,0,D點座標為r,-r,0。

然後設定頂點指標,最後畫矩陣的型別為GL10.GL_TRIANGLE_STRIP.

這樣就用畫三角形帶的方法渲染出了一個正方形,附程式碼:

/**
 * 用三角形帶渲染出正方形
*/
public class MyTriangleRenderer extends AbstractRenderer{

    public void onDrawFrame(GL10 gl) {

        //清除顏色緩衝區
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
//設定繪圖顏色
gl.glColor4f(1f, 1f, 1f, 1f);
//設定模型檢視矩陣
gl.glMatrixMode(GL10.GL_MODELVIEW);
//載入單位矩陣
gl.glLoadIdentity();
//放置眼球位置 GLU.gluLookAt(gl, 0f, 0f, 5f, 0f, 0f, 0f, 0f, 1f, 0f); //旋轉角度,以便更直觀檢視 gl.glRotatef(xRotate, 1, 0, 0);// x軸旋轉 (openGL規定,順時針旋轉為負值) gl.glRotatef(yRotate,1,0,0);// y軸旋轉 /** * 計算點的座標 * @param r 半徑 * @param coordsList 座標集合 * @param x,y,z 每個點的座標 * @param alpha 角度 * */ float r = 0.5f;//半徑 float [] coords = { -r,r,0, -r,-r,0, r,r,0, r,-r,0, }; gl.glVertexPointer(3,GL10.GL_FLOAT,0, BufferUtils.array2ByteBuffer(coords));//指定頂點指標 gl.glDrawArrays( GL10.GL_TRIANGLE_STRIP,0,4 ); } }
接下來我們用畫三角形扇面的方法繪製一個稜錐:

效果圖如下

方便起見,我們設定平截頭體的中心為座標的原點,假定平截頭體前後的距離0.5f,那麼稜錐的頂點座標為(0,0,0.5f),稜錐底面圓上的座標為(x,y,-0.5f),而xy依舊用迴圈取到:

for( float alpha = 0f; alpha < Math.PI * 6;alpha = (float) (alpha+Math.PI / 8 )){
    x = (float) (Math.cos(alpha) * r);
y = (float) (Math.sin(alpha) * r);
}

這樣稜錐頂點和稜錐底面圓上的兩點,就可以用畫三角形扇面的方法繪製,而多個這樣的扇面組合起來就是我們需要的稜錐。

這樣繪製完之後我們發現,稜錐是單一顏色的,那麼如何做到讓稜錐出現交叉色呢?這就需要用到另一個緩衝區資料---顏色緩衝區。

我們可以設定一個布林型變數flag,通過flag的值來新增顏色資料到顏色集合,然後將這個Float集合轉換成位元組緩衝區,最後設定頂點顏色指標。

boolean flag = false;
List<Float> colorList = new ArrayList<Float>();
if( flag = !flag ){
    //黃色
colorList.add(1f);
colorList.add(1f);
colorList.add(0f);
colorList.add(1f);
}else {
    //紅色
colorList.add(1f);
colorList.add(0f);
colorList.add(0f);
colorList.add(1f);
}
ByteBuffer colorBuffer = BufferUtils.list2ByteBuffer(colorList);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer );//頂點顏色指標
這樣繪製完成之後,發現稜錐沒有底面,那麼同樣,我們也可以通過畫三角形扇面的方法也可以畫一個稜錐的底面:

首先我們知道錐底的中心點座標為(0,0,-0.5f),而底面圓上的座標和上面畫扇面所用到的迴圈一模一樣,所以乾脆直接新增進底面座標的list:

/******************** 錐底 **********************/
float r = 0.5f;//半徑
float x = 0f,y = 0f,z = -0.5f;//底面圓心點的座標
List<Float> coordsConeBottomList = new ArrayList<Float>();coordsConeBottomList.add(0f);coordsConeBottomList.add(0f);coordsConeBottomList.add(-0.5f);
for( float alpha = 0f; alpha < Math.PI * 6;alpha = (float) (alpha+Math.PI / 8 )){
    x = (float) (Math.cos(alpha) * r);
y = (float) (Math.sin(alpha) * r);
//錐面座標
coordsList.add(x);
coordsList.add(y);
coordsList.add(z);
//錐底座標
coordsConeBottomList.add(x);
coordsConeBottomList.add(y);
coordsConeBottomList.add(z);
}

然後再次指定頂點指標,最後呼叫畫三角形扇面方法即可。

最終效果圖: