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);
}
然後再次指定頂點指標,最後呼叫畫三角形扇面方法即可。
最終效果圖: