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

原文链接:https://wuwang.blog.csdn.net/article/details/52818488

上篇博客中我们已经使用到了相机和投影,利用变换矩阵,绘制出了等腰直角三角形。在本篇博客中,我们绘制正方形和圆形同样少不了变换矩阵。

构建正方形和圆形
前面提到过,在OpenGLES的世界里面是没有正方形和圆形的,只有点、线、三角形。三角形就是OpenGLES提供的最复杂的图元单位。所以我们要绘制填充的正方形和圆形就需要利用三角形来实现。

正方形
正方形的构建比较简单,可以用两个三角形组成。当然,你也可以用很多很多三角形去合成一个正方形,只要你乐意。如下图所示,我们可以按照123组成的三角形和134组成的三角形,两个拼合成一个正方形。 
Android OpenGLES2.0(四)——正方形和圆形 
可以设置正方形的坐标数组为:

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
    };


圆形
圆形的构建,相对复杂一点,我们可以把圆形看成一个正多边形,边越多,圆越平滑。如下图所示,分别为正六边形、正八边形、正十六边形和正一百边形。 
Android OpenGLES2.0(四)——正方形和圆形 
以六边形为例,由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/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;
}


图形的绘制
得到了坐标数组,剩下的工作就和三角形的绘制基本相同了。唯一不同的地方,是需要修改:

 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的绘制方式。 
最后绘制结果如下: 
Android OpenGLES2.0(四)——正方形和圆形  

绘制小结
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,称之为索引法,是根据索引序列,在顶点序列中找到对应的顶点,并根据绘制的方式,组成相应的图元进行绘制。 
顶点法拥有的绘制方式,索引法也都有。相对于顶点法在复杂图形的绘制中无法避免大量顶点重复的情况,索引法可以相对顶点法减少很多重复顶点占用的空间。
 

上一篇:119. Pascal‘s Triangle II(Leetcode每日一题-2021.02.12)


下一篇:【BZOJ2395】[Balkan 2011] Timeismoney(最小乘积生成树)