1. 程式人生 > >Android OpenGLES2.0(四)——正方形和圓形

Android OpenGLES2.0(四)——正方形和圓形

上篇部落格中我們已經使用到了相機和投影,利用變換矩陣,繪製出了等腰直角三角形。在本篇部落格中,我們繪製正方形和圓形同樣少不了變換矩陣。

構建正方形和圓形

前面提到過,在OpenGLES的世界裡面是沒有正方形和圓形的,只有點、線、三角形。三角形就是OpenGLES提供的最複雜的圖元單位。所以我們要繪製填充的正方形和圓形就需要利用三角形來實現。

正方形

正方形的構建比較簡單,可以用兩個三角形組成。當然,你也可以用很多很多三角形去合成一個正方形,只要你樂意。如下圖所示,我們可以按照123組成的三角形和134組成的三角形,兩個拼合成一個正方形。
這裡寫圖片描述
可以設定正方形的座標陣列為:

static
float triangleCoords[] = { -0.5f, 0.5f, 0.0f, // top left -0.5f, -0.5f, 0.0f, // bottom left 0.5f, -0.5f, 0.0f, // bottom right 0.5f, 0.5f, 0.0f // top right };

圓形

圓形的構建,相對複雜一點,我們可以把圓形看成一個正多邊形,邊越多,圓越平滑。如下圖所示,分別為正六邊形、正八邊形、正十六邊形和正一百邊形。
這裡寫圖片描述
以六邊形為例,由012、023,034、045、056、061六個三角形,更多變形同樣如此。
利用簡單的數學知識,即可得到,以多邊形中心建立直角座標系,得到n變形的頂點座標為:

private float[]  createPositions(){
    ArrayList<Float> data=new ArrayList<>();
    data.add(0.0f);             //設定圓心座標
    data.add(0.0f);             
    data.add(0.0f);
    float angDegSpan=360f/n;
    for(float i=0;i<360+angDegSpan;i+=angDegSpan){
        data.add((float) (radius*Math.sin(i*Math.PI/180
f))); data.add((float)(radius*Math.cos(i*Math.PI/180f))); data.add(0.0f); } float[] f=new float[data.size()]; for (int i=0;i<f.length;i++){ f[i]=data.get(i); } return f; }

圖形的繪製

得到了座標陣列,剩下的工作就和三角形的繪製基本相同了。唯一不同的地方,是需要修改:

 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 1);

為:

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, shapePos.length/3);

GLES20.glDrawArrays的第一個引數表示繪製方式,第二個引數表示偏移量,第三個引數表示頂點個數。
繪製方式有:

int GL_POINTS       //將傳入的頂點座標作為單獨的點繪製
int GL_LINES        //將傳入的座標作為單獨線條繪製,ABCDEFG六個頂點,繪製AB、CD、EF三條線
int GL_LINE_STRIP   //將傳入的頂點作為折線繪製,ABCD四個頂點,繪製AB、BC、CD三條線
int GL_LINE_LOOP    //將傳入的頂點作為閉合折線繪製,ABCD四個頂點,繪製AB、BC、CD、DA四條線。
int GL_TRIANGLES    //將傳入的頂點作為單獨的三角形繪製,ABCDEF繪製ABC,DEF兩個三角形
int GL_TRIANGLE_FAN    //將傳入的頂點作為扇面繪製,ABCDEF繪製ABC、ACD、ADE、AEF四個三角形
int GL_TRIANGLE_STRIP   //將傳入的頂點作為三角條帶繪製,ABCDEF繪製ABC,BCD,CDE,DEF四個三角形

所以看到這裡,正方形又多了個構建方式:按照途中座標點1243的順序傳入,然後繪製時選擇GL_TRIANGLE_STRIP的繪製方式。
最後繪製結果如下:
正方形 圓形

繪製小結

GL_TRIANGLE_STRIP

由上面的註釋,我們可以知道,GL_TRIANGLE_STRIP的方式繪製連續的三角形,比直接用GL_TRIANGLES的方式繪製三角形少好多個頂點,效率會高很多。另外,GL_TRIANGLE_STRIP並不是只能繪製連續的三角形構成的物體,我們只需要將不需要重複繪製的點重複兩次即可。比如,傳入ABCDEEFFGH座標,就會得到ABC、BCD、CDE以及FGH四個三角形

GL_TRIANGLE_FAN

扇面繪製是以第一個為零點進行繪製,通常我們繪製圓形,圓錐的錐面都會使用到,值得注意的是,最後一個點的左邊應當與第二個點重合,在計算的時候,起點角度為0度,終點角度應包含360度。

頂點法和索引法

上述提到的繪製,使用的都是GLES20.glDrawArrays,也就是頂點法,是根據傳入的定點順序進行繪製的。還有一個方法進行繪製GLES20.glDrawElements,稱之為索引法,是根據索引序列,在頂點序列中找到對應的頂點,並根據繪製的方式,組成相應的圖元進行繪製。
頂點法擁有的繪製方式,索引法也都有。相對於頂點法在複雜圖形的繪製中無法避免大量頂點重複的情況,索引法可以相對頂點法減少很多重複頂點佔用的空間。

原始碼