openGL画三角形---openGL学习笔记(四)

来源:互联网 发布:淘宝美工一组图多少钱 编辑:程序博客网 时间:2024/05/17 05:05

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

然后再次指定顶点指针,最后调用画三角形扇面方法即可。

最终效果图:


0 0