OpenGL学习(5)——变换

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

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

Scaling

\(M=\begin{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轴,\(\theta\)表示旋转角度:
\(M=\begin{bmatrix} 1&0&0&0\\ 0&\cos\theta&-\sin\theta&0\\ 0&\sin\theta&\cos\theta&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=\begin{bmatrix} \cos\theta&0&\sin\theta&0\\ 0&1&0&0\\ -\sin\theta&0&\cos\theta&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=\begin{bmatrix} \cos\theta&-\sin\theta&0&0\\ \sin\theta&\cos\theta&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=\begin{bmatrix} \cos\theta+x^2(1-\cos\theta)&xy(1-\cos\theta)-z\cos\theta&xz(1-\cos\theta)+y\cos\theta&0\\ yx(1-\cos\theta)+z\cos\theta&\cos\theta+y^2(1-\cos\theta)&yz(1-\cos\theta)-x\cos\theta&0\\ zx(1-\cos\theta)-y\cos\theta&zy(1-\cos\theta)+x\cos\theta&\cos\theta+z^2(1-\cos\theta)&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=\begin{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;
}
posted @ 2019-05-24 03:22  一只名为狗的猫  阅读(365)  评论(0编辑  收藏  举报