openGL之圆环---openGL学习笔记(七)

时间:2022-09-10 17:14:41

画圆环的想法与画球体的想法大致相同,不同的是,圆环中间为空,而环体的直径又相同,所以通过设置两个半径,用两个半径和角度就可以确定每个点的x,y,z坐标。

首先,还是先把环体切成几个部分,每个部分打开之后都是一个矩形,把每个矩形都用画三角形带的方式绘制出来的话,那么圆环就可以实现。

接下来就是坐标的计算:

假定以圆环中心为坐标圆心,想要确定每个点的坐标,就需要设置两个半径,一个内圈半径r1,一个环体半径r2,再设置一个alpha角和alpha角的步长(alphaStep),用来取到环体上的每个圆,还要设置一个beta角和beta角的步长(betaStep),用来取到每一个圆上的点。

openGL之圆环---openGL学习笔记(七)

那么假定两点(x0,y0,z0)(x1,y1,z1),可以得出x0 = [(r1+r2)+r2 * cos(beta)] * cos(alpha),

y0 = [(r1+r2)+r2 * cos(beta)] * sin(alpha),z0 = -r2 * sin(beta).

而x1,y1,z1与x0,y0,z0不同的地方只有alpha的角度,给alpha加一个步长,就得到x1,y1,z1.

x1 = [(r1+r2)+r2 * cos(beta)] * cos(alpha+alphaStep),

y1 = [(r1+r2)+r2 * cos(beta)] * sin(alpha+alphaStep),

因为圆环环体的直径处处相等,所以圆环向Z轴负方向的延伸值不变。

所以,z1 = z0 = -r2 * sin(beta).

需要注意的是,z轴坐标需要取反,因为是向z轴负方向延伸。

取到了两点坐标之后,接下来就可以用两层循环取到圆环上的各个点。


for( int i = 0;i < count;i ++ ){
        alpha = i * alphaStep;
    for( int j = 0;j <= count0;j ++ ){
        beta = j * betaStep;
        x0 = (float) (Math.cos(alpha) * (Rring + Rinner + Rinner * Math.cos(beta)));
        y0 = (float) (Math.sin(alpha) * (Rring + Rinner + Rinner * Math.cos(beta)));
        z0 = (float) -(Rring * Math.sin(beta));

        x1 = (float) (Math.cos(alpha + alphaStep) * (Rring + Rinner + Rinner * Math.cos(beta)));
        y1 = (float) (Math.sin(alpha + alphaStep) * (Rring + Rinner + Rinner * Math.cos(beta)));
        z1 = (float) (-Rring * Math.sin(beta));
    }
取到了圆环上的各个点的坐标后,剩下的就简单了,设置清屏色,设置绘图颜色,然后指定模型视图矩阵,加载单位矩阵,放置眼球位置,设置旋转角度。最后再指定顶点指针,绘制三角形带。

运行效果图:(为观察方便起见,效果图还是以画线带的方式绘制)

openGL之圆环---openGL学习笔记(七)

附代码:

public class MyRingRenderer extends AbstractRenderer{
    @Override
    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, 0, 0, 5, 0, 0, 0, 0, 1, 0);//放置眼球位置
        gl.glRotatef(xRotate, 1, 0, 0);//x轴旋转角度
        gl.glRotatef(yRotate,0,1,0);//y轴旋转角度

        List<Float> coords = new ArrayList<Float>();
        float Rinner = 0.2f;//内圆半径
        float Rring = 0.3f;//环半径
        int count = 20;//循环次数
        float alpha = 0;//外圆角度
        float x0,x1,y0,y1,z0,z1;
        float alphaStep = (float) (2 * Math.PI / count);//alpha角的步长(外部圆环)
        float betaStep = (float) (2 * Math.PI / count);//beta角的步长(每个切片)
        float beta = 0;//切片循环角度
        int count0 = 20;//循环次数
        /***************************外层循环主要负责把圆环切成几个部分*******************************/
        for( int i = 0;i < count;i ++ ){
                alpha = i *alphaStep;
        /***************************内层循环主要负责把每个部分画出来*******************************/

            for( int j = 0;j <= count0;j ++ ){
                beta = j * betaStep;
                x0 = (float) (Math.cos(alpha) * (Rring + Rinner + Rinner * Math.cos(beta)));
                y0 = (float) (Math.sin(alpha) * (Rring + Rinner + Rinner * Math.cos(beta)));
                z0 = (float) -(Rring * Math.sin(beta));

                x1 = (float) (Math.cos(alpha + alphaStep) * (Rring + Rinner + Rinner * Math.cos(beta)));
                y1 = (float) (Math.sin(alpha + alphaStep) * (Rring + Rinner + Rinner * Math.cos(beta)));
                z1 = (float) (-Rring * Math.sin(beta));

                coords.add(x0);
                coords.add(y0);
                coords.add(z0);
                coords.add(x1);
                coords.add(y1);
                coords.add(z1);
            }

            gl.glVertexPointer(3,GL10.GL_FLOAT,0, BufferUtils.list2FloatBuffer(coords));//顶点指针
            gl.glDrawArrays(GL10.GL_LINE_STRIP,0,coords.size() / 3) ;//画线带

        }
    }
}