zoukankan      html  css  js  c++  java
  • OpenGL学习(5)——变换

    学习三种变换:Scaling, Rotation和Translation。

    上学期修了Kobbelt教授(男神!)的图形学基础课,这部分内容已经接触过。
    添加GLM库,直接给出齐次坐标系下的变换矩阵和相应的代码表示:

    Scaling

    (M=egin{bmatrix} a&0&0&0\ 0&b&0&0\ 0&0&c&0\ 0&0&0&1\ end{bmatrix})

    glm::mat4 m = glm::scale(glm::mat4(1.0f), glm::vec3(a, b, c));
    

    Rotation

    绕x轴,( heta)表示旋转角度:
    (M=egin{bmatrix} 1&0&0&0\ 0&cos heta&-sin heta&0\ 0&sin heta&cos heta&0\ 0&0&0&1\ end{bmatrix})

    glm::mat4 m = glm::rotate(glm::mat4(1.0f), glm::radians(theta), glm::vec3(1.0f, 0.0f, 0.0f));
    

    绕y轴:
    (M=egin{bmatrix} cos heta&0&sin heta&0\ 0&1&0&0\ -sin heta&0&cos heta&0\ 0&0&0&1\ end{bmatrix})

    glm::mat4 m = glm::rotate(glm::mat4(1.0f), glm::radians(theta), glm::vec3(0.0f, 1.0f, 0.0f));
    

    绕z轴:
    (M=egin{bmatrix} cos heta&-sin heta&0&0\ sin heta&cos heta&0&0\ 0&0&1&0\ 0&0&0&1\ end{bmatrix})

    glm::mat4 m = glm::rotate(glm::mat4(1.0f), glm::radians(theta), glm::vec3(0.0f, 0.0f, 1.0f));
    

    绕任意轴(x, y, z),(x, y, z)为单位向量:
    (M=egin{bmatrix} cos heta+x^2(1-cos heta)&xy(1-cos heta)-zcos heta&xz(1-cos heta)+ycos heta&0\ yx(1-cos heta)+zcos heta&cos heta+y^2(1-cos heta)&yz(1-cos heta)-xcos heta&0\ zx(1-cos heta)-ycos heta&zy(1-cos heta)+xcos heta&cos heta+z^2(1-cos heta)&0\ 0&0&0&1\ end{bmatrix})

    glm::mat4 m = glm::rotate(glm::mat4(1.0f), glm::radians(theta), glm::vec3(x, y, z));
    

    Translation

    (M=egin{bmatrix} 1&0&0&t_x\ 0&1&0&t_y\ 0&0&1&t_z\ 0&0&0&1\ end{bmatrix})

    glm::mat4 m = glm::translate(glm::mat4(1.0f), glm::vec3(tx, ty, tz));
    

    在glm中,矩阵以column-major的顺序储存,即原变换矩阵的转置。以上述Translation代码为例,变换矩阵m的各元素索引为:

    m[0][0] == 1.0f, m[0][1] == 0.0f, m[0][2] == 0.0f, m[0][3] == 0.0f
    m[1][0] == 0.0f, m[1][1] == 1.0f, m[1][2] == 0.0f, m[1][3] == 0.0f
    m[2][0] == 0.0f, m[2][1] == 0.0f, m[2][2] == 1.0f, m[2][3] == 0.0f
    m[3][0] == tx, m[3][1] == ty, m[3][2] == tz, m[3][3] == 1.0f
    

    练习

    1.Using the last transformation on the container, try switching the order around by first rotating and then translating. See what happens and try to reason why this happens.
    先Rotation,再Translation
    新建transform.cpp和transform.h,并添加到工程中。定义一个transform函数返回变换矩阵:
    transform.h

    #ifndef TRANSFORM_H
    #define TRANSFORM_H
    
    #include <glm/glm/glm.hpp>
    #include <glm/glm/gtc/matrix_transform.hpp>
    #include <glm/glm/gtc/type_ptr.hpp>
    #include <GLFW/glfw3.h>
    #include <iostream>
    
    glm::mat4 transform();
    
    #endif // TRANSFORM_H
    

    transform.cpp

    #include "transform.h"
    
    glm::mat4 transform()
    {
        glm::mat4 transMatrix = glm::mat4(1.0f);
        transMatrix = glm::translate(transMatrix, glm::vec3(0.5f, -0.5f, 0.0f));
        transMatrix = glm::rotate(transMatrix, glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f));
        return transMatrix;
    }
    

    修改Vertex Shader,定义uniform将变换矩阵传递到Shader中,对顶点坐标进行位置变换:

    #version 330 core
    layout (location = 0) in vec3 Pos;
    layout (location = 1) in vec3 Col;
    layout (location = 2) in vec2 Tex;
    out vec4 Color;
    out vec2 texCoord;
    uniform mat4 transform;
    
    void main()
    {
        gl_Position = transform * vec4(Pos, 1.0f);
        Color = vec4(Col, 1.0f);
        texCoord = Tex;
    }
    

    在渲染循环中添加一行代码,调用glUniformMatrix4fv函数更新uniform的值,即transform函数的返回值。glUniformMatrix4fv函数的第二和第三个参数分别表示矩阵的数量以及是否对矩阵转置:

    glUniformMatrix4fv(glGetUniformLocation(ourShader.ID, "transform"), 1, GL_FALSE, glm::value_ptr(transform()));
    


    先Translation,再Rotation
    只需要修改transform.cpp:

    #include "transform.h"
    
    glm::mat4 transform()
    {
        glm::mat4 transMatrix = glm::mat4(1.0f);
        transMatrix = glm::rotate(transMatrix, glm::radians(45.0f), glm::vec3(0.0f, 0.0f, 1.0f));
        transMatrix = glm::translate(transMatrix, glm::vec3(0.5f, -0.5f, 0.0f));
        return transMatrix;
    }
    


    2.Try drawing a second container with another call to glDrawElements but place it at a different position using transformations only. Make sure this second container is placed at the top-left of the window and instead of rotating, scale it over time.
    在transform.cpp中定义transform2函数:

    glm::mat4 transform2()
    {
        float timeValue = glfwGetTime();
        float scaleValue = sin(timeValue)/2.0f+0.5f;
        glm::mat4 transMatrix = glm::mat4(1.0f);
        transMatrix = glm::translate(transMatrix, glm::vec3(-0.5f, 0.5f, 0.0f));
        transMatrix = glm::scale(transMatrix, glm::vec3(scaleValue, scaleValue, 0.0f));
        return transMatrix;
    }
    
  • 相关阅读:
    【转】聚集索引和非聚集索引的区别
    【转】【Android游戏开发十三】(保存游戏数据 [下文])详解SQLite存储方式,并把SQLite的数据库文件存储在SD卡中!!!
    【转】数据库范式(1NF 2NF 3NF BCNF)详解一
    【转】数据库 无损连接分解
    如何防止被路由器限速如何更改电脑网卡的MAC地址
    BZOJ 1497 最大权闭合图
    POJ 1966 无向图点联通度 最小割
    POJ 1815 最小割
    POJ 2987 最大权闭合图
    POJ 2391 floyd+二分+最大流
  • 原文地址:https://www.cnblogs.com/yiqian/p/10915348.html
Copyright © 2011-2022 走看看