zoukankan      html  css  js  c++  java
  • opengl 教程(6) 平移变换

    原帖地址:http://ogldev.atspace.co.uk/www/tutorial06/tutorial06.html

         在这篇教程中,我们开始对三维物体进行位置变化操作,比如平移、旋转、缩放等等。物体位置变化的操作通常都是通过矩阵来实现的,每种变化用一个矩阵表示,如果一个物体进行多种位置操作,可以把它们对应的矩阵乘起来,最后再乘以顶点的坐标,这样就可以得到物体位置变化后的顶点坐标位置。

          首先我们看下平移操作,平移表示沿着一个任意长度和方向的向量,把物体从一个位置移动到另一个位置。比如我现在要把下图中左边的三角形移动到右边去。

          第一种方法就是提供一个偏移向量,在下图中偏移向量就是(1,1),把该向量作为一个uniform变量传输到shader中去,在每个顶点shader操作中,把该向量增加到顶点的位置上。

          第二种方法是用一个矩阵表示偏移,然后把该矩阵作为uniform变量,传输到shader中去,然后用该矩阵乘以顶点坐标得到偏移后的顶点坐标。

         下面我们看下如何得到这个平移矩阵?如下图,什么样的矩阵乘以顶点(0,0),得到顶点(1,1),首先2维矩阵是不能做到这点的,同样的你也不能通过三维矩阵从顶点(0,0,0)得到(1,1,1)。

          通常情况下,给定矩阵M,一个顶点P(x,y,z),以及向量V(v1,v2,v3),则有M * P=P1(x + v1, y + v2, z + v3),这意味着矩阵M把顶点P,平移到位置P1,从P1的结果可以看出,它的每个分量是P的每个分量和V的相对应的分量乘积的和

    translation

         对于3维向量来说,最终的矩阵M如下图左边矩阵,而三维向量(x,y,z)也扩展成了四维向量(x,y,z,1),此时 M*P=P1得以实现。四维向量的第四维称作w,这种坐标也就齐次坐标,通常对点来说w=1,对向量来说w=0,所以点可以平移,但向量不行。

    equation3

    下面简单看下程序的代码:

    struct Matrix4f {
    float m[4][4];
    };

    我们在math_3d.h中增加一个4x4的矩阵结构,用来定义物体坐标变化矩阵。

    GLuint gWorldLocation;

          我们用这个OpenGL句柄访问shader中的世界变化矩阵uniform变量,之所以叫世界变化矩阵,是因为我们的平移操作时在世界坐标系中进行的。

    Matrix4f World;
    World.m[0][0] = 1.0f; World.m[0][1] = 0.0f; World.m[0][2] = 0.0f; World.m[0][3] = sinf(Scale);
    World.m[1][0] = 0.0f; World.m[1][1] = 1.0f; World.m[1][2] = 0.0f; World.m[1][3] = 0.0f;
    World.m[2][0] = 0.0f; World.m[2][1] = 0.0f; World.m[2][2] = 1.0f; World.m[2][3] = 0.0f;
    World.m[3][0] = 0.0f; World.m[3][1] = 0.0f; World.m[3][2] = 0.0f; World.m[3][3] = 1.0f;

          在渲染函数中,我们定义了世界矩阵,并设置v2和 v3 为0,这样物体在Y轴和z轴坐标不变,设置v1为sinf函数的结果,它的值在[-1,1]之间变化,则物体的x坐标在[-1,1]之间不断变化。

    glUniformMatrix4fv(gWorldLocation, 1, GL_TRUE, &World.m[0][0]);

          这是给第二个uniform变量赋值,它是一个4x4的矩阵。第一个参数是shader uniform变量的位置索引,第二个参数是要更新的矩阵的数量,我们只有一个矩阵,所以其值是1,通过这个参数,我们可以同时给多个矩阵赋值。第三个参数指定矩阵是行主序还是列主序,行主序意思是矩阵在数组中是按一行一行存储的,列主序则表示矩阵在数组中是一列一列存储的,c++默认是行主序的,例如下面的二维数组:

    int a[2][3];
    a[0][0] = 1;
    a[0][1] = 2;
    a[0][2] = 3;
    a[1][0] = 4;
    a[1][1] = 5;
    a[1][2] = 6;

    它表示下面的矩阵:
    1 2 3
    4 5 6
    在内存中的存储方式是:1 2 3 4 5 6

          glUniformMatrix4fv()的第三个参数是 GL_TRUE ,因为我们使用行主序。也可以使用列主序,这时表示的是转置的矩阵。第四个参数矩阵在内存中的起始地址。

    下面是shader中的代码:

    uniform mat4 gWorld;

    它表示一个4x4的矩阵,在shader中mat2,mat3也可以使用。

    gl_Position = gWorld * vec4(Position, 1.0);

    三角形顶点的位置属性是三维向量,但我们在shader中使用四维的齐次坐标,所以我们会扩展位置向量,并设置w=1.0。

    程序执行后,每帧都会传入一个平移世界矩阵,我们用它改变顶点的位置,使得物体x坐标在[-1,1]之间移动。

    程序运行后,界面如下,一个三角形在x方向不断的移来移去:

    imageimage

  • 相关阅读:
    项目
    Cache Code
    是什么限制了我们面向对象
    程序设计语言本质
    不要迷失在技术的海洋中
    程序是给自己看的还是给别人看的
    程序员的春天
    新手如何学习一门新的语言
    无废话C#设计模式之二十:Mediator
    (原创)代码分析-DataGrid实现增删(带提示)改和分页
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/2743136.html
Copyright © 2011-2022 走看看