尝试课本实例使用OpenGL完成绘制旋转球体

课本实例效果

自用

窗口初始设置

窗口的一些初始设置

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    // 设置背景色:白色
    gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    // 关闭抗抖动
    gl.glDisable(GL10.GL_DITHER);  //可提高性能
    // 启动阴影平滑
    gl.glShadeModel(GL10.GL_SMOOTH);
    // 复位深度缓存
    gl.glClearDepthf(1f);
    // 所做深度测试的类型
    gl.glDepthFunc(GL10.GL_LEQUAL);
    // 启动深度测试
    gl.glEnable(GL10.GL_DEPTH_TEST);
    // 对透视进行修正
    gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
    //计算球面顶点坐标
    makeSphereVertices();

}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
    // 设置输出屏幕大小
    gl.glViewport(0, 0, width, height);
    // 设置投影矩阵
    gl.glMatrixMode(GL10.GL_PROJECTION);
    // 重置投影矩阵
    gl.glLoadIdentity();
    // 设置视口大小
    GLU.gluPerspective(gl, 50, (float) width / (float) height, 0.1f, 100.0f);
    // 设置透视图视口大小
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    //计算透视窗的宽度、高度比
    float ratio = (float) width / height;
    // 重置投影矩阵
    gl.glLoadIdentity();
}

绘制球体准备

绘制准备的代码
画笔颜色设置gl.glColor4f
球体旋转gl.glRotatef(rotate, 0f, 0.2f, 0f);

@Override
public void onDrawFrame(GL10 gl) {
    //清除屏幕缓存和深度缓存
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    gl.glLoadIdentity();
    // 设置画笔颜色
    gl.glColor4f(1.0f, 0.0f, 1.0f, 0.0f);
    // 设置镜头的方位
    GLU.gluLookAt(gl, 10.0f, 8.0f, 6.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
    gl.glRotatef(rotate, 0f, 0.2f, 0f);
    //画图
    draw(gl);
    rotate+=1;
}

球体的坐标

private void makeSphereVertices() {
    float altitude;//纬度
    float altitudeDelta;//下一层纬度
    float azimuth;//经度
    float ex;//点坐标x
    float ey;//点坐标y
    float ez;//点坐标z
    //将纬度等分成divide份,这样就能计算出每一等份的纬度值
    for(int i = 0; i <= divide; i++) {
        //获取当前等份的纬度值
        altitude = (float) (Math.PI/2.0 - i * (Math.PI) / divide);
        //获取下一等份的纬度值
        altitudeDelta = (float) (Math.PI/2.0 - (i + 1) * (Math.PI) / divide);
        //当前纬度和下一纬度的点坐标
        float[] vertices = new float[divide*6+6];

        //将经度等分成divide份,这样就能得到当前纬度值和下一纬度值的每一份经度值
        for(int j = 0; j <= divide; j++) {
            //计算经度值
            azimuth = (float)(j * (Math.PI*2) / divide);
            ex = (float) (Math.cos(altitude) * Math.cos(azimuth));
            ey = (float)  Math.sin(altitude);
            ez = (float) -(Math.cos(altitude) * Math.sin(azimuth));
            //此经度值下的当前纬度的点坐标
            vertices[6*j] = radius * ex;
            vertices[6*j+1] = radius * ey;
            vertices[6*j+2] = radius * ez;
            ex = (float) (Math.cos(altitudeDelta) * Math.cos(azimuth));
            ey = (float) Math.sin(altitudeDelta);
            ez = (float) -(Math.cos(altitudeDelta) * Math.sin(azimuth));
            //此经度值下的下一纬度的点坐标
            vertices[6*j+3] = radius * ex;
            vertices[6*j+4] = radius * ey;
            vertices[6*j+5] = radius * ez;
        }
        //将点坐标转换成FloatBuffer类型添加到点坐标集合ArrayList<FloatBuffer>里
        mVertices.add(makeFloatBufferFromArray(vertices));
    }
}

绘制球体

private void draw(GL10 gl) {
    //打开顶点开关
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    //每次声明两条临近的纬度线的点坐标并绘制出来
    for(int i = 0;i <= divide ; i++){
        //将顶点坐标传给 OpenGL 管道
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertices.get(i));
        //用画线的方式将点连接并画出来
        gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, divide*2+2);
    }
    //关闭顶点开关
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}

#工具代码

private FloatBuffer makeFloatBufferFromArray(float[] array) {
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(array.length * Float.SIZE);
    byteBuffer.order(ByteOrder.nativeOrder());
    FloatBuffer floatBuffer = byteBuffer.asFloatBuffer();
    floatBuffer.put(array);
    floatBuffer.position(0);
    return floatBuffer;
}

MainActivity函数设置

在MainActivity中加入如下代码

// 创建一个GLSurfaceView,用于显示OpenGL绘制的图形
GLSurfaceView glView = new GLSurfaceView(this);
// 创建GLSurfaceView的内容绘制器
MyRenderer myRender = new MyRenderer();
NewRenderer newRenderer = new NewRenderer();
// 为GLSurfaceView设置绘制器
glView.setRenderer(newRenderer);
setContentView(glView);

实现效果

自用

参考

《疯狂Android讲义(第四版)》——李刚
Android OpenGL绘制球体-雪穗_

作者:李沅缘
原文地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值