OpenGL ES总结(二)OpenGL坐标变换之平移及旋转

世界坐标系:

  • 在OpenGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的。你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。长度单位这样来定:窗口范围按此单位恰好是(-1,-1)到(1,1),即屏幕左下角坐标为(-1,-1),右上角坐标为(1,1)。

    openGL使用右手坐标

    从左到右,x递增

    从下到上,y递增

    从远到近,z递增

当前绘图坐标系:

  • 是绘制物体时的坐标系。程序刚初始化时,世界坐标系和当前绘图坐标系是重合的。当用glTranslatef(),glScalef(), glRotatef()等对当前绘图坐标系进行平移、伸缩、旋转变换之后,世界坐标系和当前绘图坐标系不再重合。注意,这里的平移旋转是将当前绘图坐标系看做一个整体在世界坐标系中进行旋转平移。然后,改变以后,再用glVertex3f()等绘图函数绘图时,都是在当前绘图坐标系进行绘图,所有的函数参数也都是相对当前绘图坐标系来讲的。

其中四种坐标经常要在程序中用到:世界坐标,物体坐标,设备坐标和眼坐标。

  • 1、世界坐标是OpenGL中用来描述场景的坐标,Z+轴垂直屏幕向外,X+从左到右,Y+轴从下到上,是右手笛卡尔坐标系统。我们用这个坐标系来描述物体及光源的位置。

    将物体放到场景中也就是将物体平移到特定位置、旋转一定角度,这些操作就是坐标变换。OpenGL中提供了glTranslate*/glRotate*/glScale*三条坐标变换命令,利用OpenGL的矩阵运算命令,则可以实现任意复杂的坐标变换。

    • OpenGL中有一个坐标变换矩阵栈(ModelView),栈顶就是当前坐标变换矩阵,进入OpenGL管道的每个坐标(齐次坐标)都会先乘上这个矩阵,结果才是对应点在场景中的世界坐标。OpenGL中的坐标变换都是通过矩阵运算完成的,与图形学课本的描述完全一致。要注意的是变换中的矩阵乘法是左乘,而矩阵乘法与算术乘法不同,不符合交换律(万一不明白去看矩阵代数书好了)。
    • glTranslate*(x,y,z):平移,参数为各轴向的移动量。
    • glRotate(d,x,y,z):旋转,第一个参数为转动的度数,后三个参数表明是否绕该轴旋转。通常x,y,z中只有一个为1,其余为0,用连续几条旋转命令完成复杂旋转。由于矩阵运算的左乘特点,旋转命令的顺序与旋转动作的顺序正好相反。
  • 2、物体坐标是以物体某一点为原点而建立的“世界坐标”,该坐标系仅对该物体适用,用来简化对物体各部分坐标的描述。物体放到场景中时,各部分经历的坐标变换相同,相对位置不变,所以可视为一个整体,与人类的思维习惯一致。
  • 3、眼坐标是以视点为原点,以视线的方向为Z+轴正方向的坐标系中的方向。OpenGL管道会将世界坐标先变换到眼坐标,然后进行裁剪,只有在视线范围(视见体)之内的场景才会进入下一阶段的计算。同样的,有投影变换矩阵栈(Projection),栈顶矩阵就是当前投影变换矩阵,负责将场景各坐标变换到眼坐标,由所得到的结果是裁剪后的场景部分,称为裁剪坐标。前面提到过的视见体设定其实就是在建立该矩阵。
  • 4、设备坐标:OpenGL 的重要功能之一就是将三维的世界坐标经过变换、投影等计算,最终算出它在显示设备上对应的位置,这个位置就称为设备坐标。在屏幕、打印机等设备上的坐标是二维坐标。值得一提的是,OpenGL可以只使用设备的一部分进行绘制,这个部分称为视区或视口(viewport)。投影得到的是视区内的坐标(投影坐标),从投影坐标到设备坐标的计算过程就是设备变换了。

    对应代码:

package com.example.hejunlin.openglcoordinate;

import android.opengl.GLSurfaceView;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    private GLSurfaceView mSurfaceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mSurfaceView = new GLSurfaceView(this);
        mSurfaceView.setRenderer(new MyGLRenderer());
        setContentView(mSurfaceView);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mSurfaceView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mSurfaceView.onPause();
    }
}

Renderer

package com.example.hejunlin.openglcoordinate;

import android.opengl.GLES31;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.Matrix;
import android.util.Log;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * Created by hejunlin on 2017/3/13.
 */

public class MyGLRenderer implements GLSurfaceView.Renderer {

    private Coordinate coordinate;
    private float mAngle = 45;

    public MyGLRenderer() {
        coordinate = new Coordinate();
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glClearColor(255.0f, 255.0f, 255.0f, 1.0f);
        gl.glClearDepthf(1.0f);
        gl.glEnable(GL10.GL_DEPTH_TEST);
        gl.glDepthFunc(GL10.GL_LEQUAL);
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
        gl.glShadeModel(GL10.GL_SMOOTH);
        gl.glDisable(GL10.GL_DITHER);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {

        if (height == 0) {
            height = 1;
        }
        float aspect = (float) width / height;

        gl.glViewport(0, 0, width, height);

        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
        GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.0f);

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();

    }

    @Override
    public void onDrawFrame(GL10 gl) {
        Log.d("AAA" , ">> onDrawFrame mAngle " + mAngle);
        // 画背景颜色
        GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT | GLES31.GL_DEPTH_BUFFER_BIT);

        gl.glLoadIdentity();
        gl.glTranslatef(0.0f, 0.3f, -2.0f);
        mAngle ++;
//        gl.glRotatef(mAngle,1.0f,1.0f,1.0f);

        coordinate.draw(gl);

    }

}

Coordinate

package com.example.hejunlin.openglcoordinate;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

/**
 * Created by hejunlin on 2017/3/13.
 */

public class Coordinate {
    private FloatBuffer vertexsBuffer;
    private FloatBuffer colorsBuffer;

    private ByteBuffer indicesBuffer;

    private float vertexs[] = {
            0.0f, 0.0f, 0.0f,
            1.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 0.0f,
            0.0f, 0.0f, 1.0f
    };

    private float colors[] = {
            1.0f, 0.0f, 0.0f, 1.0f,
            1.0f, 0.0f, 0.0f, 1.0f,
            0.0f, 1.0f, 0.0f, 1.0f,
            0.0f, 1.0f, 0.0f, 1.0f,
            0.0f, 0.0f, 1.0f, 1.0f,
            0.0f, 0.0f, 1.0f, 1.0f
    };

    private byte indices[] = {0, 1, 2};

    public Coordinate() {

        ByteBuffer vbb = ByteBuffer.allocateDirect(vertexs.length * 4);
        vbb.order(ByteOrder.nativeOrder());
        vertexsBuffer = vbb.asFloatBuffer();
        vertexsBuffer.put(vertexs);
        vertexsBuffer.position(0);

        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
        cbb.order(ByteOrder.nativeOrder());
        colorsBuffer = cbb.asFloatBuffer();
        colorsBuffer.put(colors);
        colorsBuffer.position(0);

    }

    public void draw(GL10 gl) {

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexsBuffer);
        gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorsBuffer);
        gl.glLineWidth(9);
        gl.glDrawArrays(GL10.GL_LINES, 0, vertexs.length / 3);

        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

    }
}

通过变换 gl.glTranslatef(0.0f, 0.3f, -2.0f)中,前两个参数,来看下变换后效果。

下图坐标:(0.0f, 0.0f, -2.0f)

先换x,变成(0.3f, 0.0f, -2.0f),对应图如下:

换x,变成(-0.3f, 0.0f, -2.0f),对应图如下:

换y,变成(0.0f, 0.3f, -2.0f),对应图如下:

换y,变成(0.0f, -0.3f, -2.0f),对应图如下:

void glTranslatef(GLdouble x,

         GLdouble y,

         GLdouble z);

参数说明:

x,y,z:分别指定沿x,y,z轴方向的平移分量。

重点就是沿着x,y,z轴移动。

注意在glTranslatef(x, y, z)中,当您移动的时候,您并不是相对屏幕中心移动,而是相对与当前所在的屏幕位置。

其作用就是将你绘点坐标的原点在当前原点的基础上平移一个(x,y,z)向量。

关于 OpenGL坐标系之间的转换,可参考

http://blog.csdn.net/sac761/article/details/52179585

时间: 2024-10-14 12:33:01

OpenGL ES总结(二)OpenGL坐标变换之平移及旋转的相关文章

Assignment 4 OpenGL中正十二面体追踪球实现(平移、旋转、多面体线框体切换)

一.使用平台    windows  8.1     visual  studio  2012    二.使用方法     鼠标左键控制旋转,鼠标右键控制平移,点击鼠标中键出现菜单可选多面体 或线框体绘制.     键盘↑↓←→控制平移,F1 和 F2 键分别为多面体和线框体绘制的切换.  三.实现简述     主函数  在 main 函数中与这次实验相关的主要有以下几个函数:  glutReshapeFunc(myReshape);  //窗口改变时重新设

Android OpenGL ES 应用(二) 纹理

上一篇讲了基础入门 OpenGL (一) ,这一次主要学习OpenGL 纹理基本学习总结 要是做复杂的OpenGL应用程序,一定会用到纹理技术.纹理说白了就是把图片或者视频图像绘制到OpenGL空间中. 因此纹理也有坐标系,称ST坐标,或者UV 上面是纹理坐标空间,但没有固定的方向 下面演示加载一张image作为纹理贴图. public class TextureUtils { public static int createTexture(InputStream ins) { int[] te

OpenGL ES教程系列(经典合集)

为了搞透播放器的开发,花了些时间收集这些资料,虽然我已经搞定opengles渲染视频的内容,但是想玩玩opengles,往深里玩,图像处理这块是个好的方向,所以opengles是值得好好学的. OpenGL ES教程原创系列 2011-12-18[iTyran原创]iPhone中OpenGL ES显示3DS MAX模型之二:lib3ds加载模型 2011-12-17[iTyran原创]GLKit 矩阵变换:自转公转 2011-12-02[iTyran原创]Xcode创建的默认iOS OpenGL

OpenGL ES 简单教程

什么是OpenGL ES? OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库. 为桌面版本号OpenGL 的一个子集. OpenGL ES 定义了一个在移动平台上可以支持OpenGL最基本功能的精简标准.以适应如手机.PDA或其他消费者移动终端的显示系统. Khronos Group 定义和管理了OpenGL ES标准. OpenGL 与 OpenGL ES的关系OpenGL ES 是基于桌面版本号OpenGL 的

3D OpenGL ES

什么是OpenGL ES? OpenGL ES (为OpenGL for Embedded System的缩写) 为适用于嵌入式系统的一个免费二维和三维图形库. 为桌面版本OpenGL 的一个子集. OpenGL ES管道(Pipeline) OpenGL ES 1.x 的工序是固定的,称为Fix-Function Pipeline,可以想象一个带有很多控制开关的机器,尽管加工的工序是固定的,但是可以通过打开或关闭开关来设置参数或者打开关闭某些功能.OpenGL ES 2.0 允许提供编程来控制

Android OpenGL ES 开发教程 从入门到精通

From:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五

[转]Android OpenGL ES 开发教程 从入门到精通

本文转自:http://blog.csdn.net/mapdigit/article/details/7526556 Android OpenGL ES 简明开发教程 Android OpenGL ES 简明开发教程一:概述 Android OpenGL ES 简明开发教程二:构造OpenGL ES View Android OpenGL ES 简明开发教程三:3D绘图基本概念 Android OpenGL ES 简明开发教程四:3D 坐标变换 Android OpenGL ES 简明开发教程五

OpenGL ES总结(一)OpenGL 初识

转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/61615215 OpenGL是在图形图像中,非常优秀的渲染库,文中Demo下载地址:https://github.com/hejunlin2013/OpenGL31,看下今天的Agenda: OpenGL是什么? OpenGL主要功能是什么? OpenGL ES是什么? Android中如何描述OpenGL ES版本 映射坐标绘制对

(转)Android OpenGL ES(一)

转:http://wiki.jikexueyuan.com/project/opengl-es-guide/pipeline.html OpenGL ES 主要用来开发 3D 图形应用的.OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机.PDA 和游戏主机等嵌入式设备而设计. 什么是 OpenGL ES? OpenGL ES (为 OpenGL for Embedded System 的缩写) 为适用于嵌入式系统