Android OpenGL ES 绘图 -- 缩放、平移、旋转

OpenGL的缩放、平移、旋转

注: 参考:http://wiki.jikexueyuan.com/project/opengl-es-basics/coordinate-transformation.html

Coordinate System坐标系

OpenGL 使用了右手坐标系统,右手坐标系判断方法:在空间直角坐标系中,让右手拇指指向x轴的正方向,食指指向y轴的正方向,如果中指能指向z轴的正方向,则称这个坐标系为右手直角坐标系。

Translate 平移变换

方法 public abstract void glTranslatef (float x, float y, float z) 用于坐标平移变换。

Rotate 旋转

方法public abstract void glRotatef(float angle, float x, float y, float z) 用来实现选择坐标变换,单位为角度。
比如你选择一个骰子,首先按下列顺序选择3次:

gl.glRotatef(90f, 1.0f, 0.0f, 0.0f);
gl.glRotatef(90f, 0.0f, 1.0f, 0.0f);
gl.glRotatef(90f, 0.0f, 0.0f, 1.0f);  


然后打算逆向旋转回原先的初始状态,需要有如下旋转:

gl.glRotatef(90f, -1.0f, 0.0f, 0.0f);
gl.glRotatef(90f, 0.0f, -1.0f, 0.0f);
gl.glRotatef(90f, 0.0f, 0.0f, -1.0f);  


或者如下旋转:

gl.glRotatef(90f, 0.0f, 0.0f, -1.0f);
gl.glRotatef(90f, 0.0f, -1.0f, 0.0f);
gl.glRotatef(90f, -1.0f, 0.0f, 0.0f);  

旋转变换 glRotatef(angle, -x, -y, -z) 和 glRotatef(-angle, x, y, z) 是等价的,但选择变换的顺序直接影响最终坐标变换的结果。 角度为正时表示逆时针方向。

Translate & Rotate (平移和旋转组合变换)

在对 Mesh(网格,构成三维形体的基本单位)同时进行平移和选择变换时,坐标变换的顺序也直接影响最终的结果。
比如:先平移后旋转,旋转的中心为平移后的坐标。

先选择后平移: 平移在则相对于旋转后的坐标系:

Scale(缩放)

方法public abstract void glScalef (float x, float y, float z)用于缩放变换。
比如使用 gl.glScalef(2f, 2f, 2f) 变换后的基本,相当于把每个坐标刻度值都乘以2.

Translate & Scale(平移和缩放组合变换)

同样当需要平移和缩放时,变换的顺序也会影响最终结果。
比如先平移后缩放:

gl.glTranslatef(2, 0, 0);
gl.glScalef(0.5f, 0.5f, 0.5f);  


如果调换一下顺序:

gl.glScalef(0.5f, 0.5f, 0.5f);
gl.glTranslatef(2, 0, 0);  

结果就有所不同:

注:以上所有操作都是针对矩阵,对于已经绘制的图形无影响

矩阵操作,单位矩阵

在进行平移,旋转,缩放变换时,所有的变换都是针对当前的矩阵(与当前矩阵相乘),如果需要将当前矩阵回复最初的无变换的矩阵,可以使用单位矩阵(无平移,缩放,旋转

public abstract void glLoadIdentity()。

在栈中保存当前矩阵和从栈中恢复所存矩阵,可以使用

public abstract void glPushMatrix()

public abstract void glPopMatrix()。

在进行坐标变换的一个好习惯是在变换前使用 glPushMatrix 保存当前矩阵,完成坐标变换操作后,再调用 glPopMatrix 恢复原先的矩阵设置。

Demo

利用上面介绍的坐标变换知识,来绘制 3 个正方形 A,B,C。进行缩放变换,使的 B 比 A 小 50%,C 比 B 小 50%。 然后以屏幕中心逆时针旋转 A,B 以 A 为中心顺时针旋转,C 以 B 为中心顺时针旋转同时以自己中心高速逆时针旋转。

本次示例使用透视投影
在onSurfaceChanged中设置

        // Sets the current view port to the new size.
        gl.glViewport(0, 0, width, height);
        // Select the projection matrix
        gl.glMatrixMode(GL10.GL_PROJECTION);
        // Reset the projection matrix
        gl.glLoadIdentity();// OpenGL docs.
        //设置透视投影,参数作用请看之前的文章
        GLU.gluPerspective(gl,45.f,(float) width/height,10f,100f);
        // Select the modelview matrix
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        // Reset the modelview matrix
        gl.glLoadIdentity();

所画图形为之前的矩形(因设置透视投影,各轴刻度值相等,所画矩形为正方形),封装成drawREC绘制方法

 private void drawREC(GL10 gl) {

        float vertices[] = {
                -0.5f,  0.5f, 0.0f,  // 0, Top Left
                -0.5f, -0.5f, 0.0f,  // 1, Bottom Left
                0.5f, -0.5f, 0.0f,  // 2, Bottom Right
                0.5f,  0.5f, 0.0f,  // 3, Top Right
        };
        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
        vbb.order(ByteOrder.nativeOrder());
        FloatBuffer vertexBuffer = vbb.asFloatBuffer();
        vertexBuffer.put(vertices);
        vertexBuffer.position(0);

        short[] indices = { 0, 1,
                            2, 0,
                            2, 3 };
        ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length * 2);
        ibb.order(ByteOrder.nativeOrder());
        ShortBuffer indexBuffer = ibb.asShortBuffer();
        indexBuffer.put(indices);
        indexBuffer.position(0);
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glDrawElements(GL10.GL_TRIANGLES, indices.length,
                GL10.GL_UNSIGNED_SHORT, indexBuffer);
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }

在onDrawFrame开始绘制

    float angle =0f;
    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glFrontFace(GL10.GL_CCW);
        gl.glEnable(GL10.GL_CULL_FACE);
        //重置视角矩阵
        gl.glLoadIdentity();
        gl.glTranslatef(0,0,-10f);
        // 清除屏幕和深度缓存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT |
                GL10.GL_DEPTH_BUFFER_BIT);
        //REC A
        // Save the current matrix.
        gl.glPushMatrix();
        // Rotate square A counter-clockwise.
        gl.glRotatef(angle, 0, 0, 1);
        // Draw REC A.
        drawREC(gl);
        // Restore the last matrix.
        gl.glPopMatrix();
        // SQUARE B
        //making it rotate around A.
        gl.glRotatef(-angle, 0, 0, 1);
        // Move square B.
        gl.glTranslatef(2, 0, 0);
        // Scale it to 50% of REC A
        gl.glScalef(0.5f, 0.5f, 0.5f);
        // Draw REC B.
        drawREC(gl);
        // REC C
        // Make the rotation around B
        gl.glRotatef(-angle, 0, 0, 1);
        gl.glTranslatef(2, 0, 0);
        // Scale it to 50% of REC B
        gl.glScalef(0.5f, .5f, 0.5f);
        // Rotate around it's own center.
        gl.glRotatef(angle*10, 0, 0, 1);
        // Draw REC C.
        drawREC(gl);
        // Increse the angle.
        angle++;
    }
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
OpenGL是一种开放源代码的图形库,用于开发二维和三维图形应用程序。其支持光照、平移旋转缩放等功能。 光照是在OpenGL中实现逼真和真实感的一个重要方面。通过对物体表面的光照进行计算和模拟,可以模拟出光线在真实世界中的表现。OpenGL提供了多种光照模型和光源类型,如平行光照、点光源和聚光灯等。通过设置光源的属性,如位置、颜色和强度,可以控制光照的效果。同时,还可以设置材质的属性,如漫反射、镜面反射和环境光反射等,以使物体表面具有不同的反射特性。 平移旋转缩放是控制物体在OpenGL中位置、方向和大小的重要操作。通过平移(Translation),可以改变物体的位置。通过旋转(Rotation),可以改变物体的方向。通过缩放(Scaling),可以改变物体的大小。这些操作可以通过设置模型视图矩阵来实现,将物体的顶点坐标进行相应的变换。平移旋转缩放都可以相对于世界坐标系进行,也可以相对于物体自身坐标系进行。 在OpenGL中,可以通过矩阵操作来实现平移旋转缩放平移可以通过将物体的位置矩阵与一个平移矩阵相乘来实现。旋转可以通过将物体的方向矩阵与一个旋转矩阵相乘来实现。缩放可以通过将物体的大小矩阵与一个缩放矩阵相乘来实现。通过改变这些矩阵的数值,可以控制物体在空间中的位置、方向和大小。 总结来说,OpenGL提供了一系列的函数和接口,可以实现光照、平移旋转缩放等操作,使得开发者可以自由控制物体的表现和行为。这些功能在图形应用程序中非常重要,可以帮助开发者创建出逼真和动态的图形效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值