【我的安卓進階之旅】Opengl Es(3)繪製多邊形及圓形(附Github地址)

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

構建正方形和圓形

前面提到過,在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
    };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

圓形

圓形的構建,相對複雜一點,我們可以把圓形看成一個正多邊形,邊越多,圓越平滑。如下圖所示,分別爲正六邊形、正八邊形、正十六邊形和正一百邊形。
這裏寫圖片描述
以六邊形爲例,由012、023,034、045、056、061六個三角形,更多變形同樣如此。
我們觀察到如果邊數無限大,就會越接近圓形。在繪製過程中 我們取值N爲360。當然,如果N越大,圓形周邊的鋸齒就越不明顯。當我們把N取值爲4的時候,其實也能得到一個正方形

利用數學知識,即可得到,以多邊形中心建立直角座標系,得到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/180f))); 
        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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

圖形的繪製

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

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

爲:

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

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四個三角形
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

所以看到這裏,正方形又多了個構建方式:按照途中座標點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,稱之爲索引法,是根據索引序列,在頂點序列中找到對應的頂點,並根據繪製的方式,組成相應的圖元進行繪製。
頂點法擁有的繪製方式,索引法也都有。相對於頂點法在複雜圖形的繪製中無法避免大量頂點重複的情況,索引法可以相對頂點法減少很多重複頂點佔用的空間。

源碼

附上github下載地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章