0. 变换分类
两种变换:
一种是模型,另外一种是视图。
1. 变换矩阵
1.1 二维线性变化
- 缩放
x′y′\]=\[s00s\]\[xy\] \\begin{bmatrix} x'\\\\y' \\end{bmatrix}= \\begin{bmatrix} s \& 0\\\\0 \& s \\end{bmatrix} \\begin{bmatrix} x\\\\y \\end{bmatrix} \[x′y′\]=\[s00s\]\[xy
- 反转
x′y′\]=\[−1001\]\[xy\] \\begin{bmatrix} x'\\\\y' \\end{bmatrix}= \\begin{bmatrix} -1 \& 0\\\\0 \& 1 \\end{bmatrix} \\begin{bmatrix} x\\\\y \\end{bmatrix} \[x′y′\]=\[−1001\]\[xy
- 切变
x′y′\]=\[1a01\]\[xy\] \\begin{bmatrix} x'\\\\y' \\end{bmatrix}= \\begin{bmatrix} 1 \& a\\\\0 \& 1 \\end{bmatrix} \\begin{bmatrix} x\\\\y \\end{bmatrix} \[x′y′\]=\[10a1\]\[xy
- 旋转
x′y′\]=\[cosθ−sinθsinθcosθ\]\[xy\] \\begin{bmatrix} x'\\\\y' \\end{bmatrix}= \\begin{bmatrix} \\cos \\theta \& -\\sin \\theta\\\\ \\sin \\theta \& \\cos \\theta \\end{bmatrix} \\begin{bmatrix} x\\\\y \\end{bmatrix} \[x′y′\]=\[cosθsinθ−sinθcosθ\]\[xy
上面这些都可以统一表示成
x′y′\]=\[abcd\]\[xy\] \\begin{bmatrix} x'\\\\y' \\end{bmatrix}= \\begin{bmatrix} a \& b\\\\c \& d \\end{bmatrix} \\begin{bmatrix} x\\\\y \\end{bmatrix} \[x′y′\]=\[acbd\]\[xy
我们统称为线性变化
M=abcd M=\begin{bmatrix} a & b\\c & d \end{bmatrix} M=acbd
1.2 平移变化
但是我们发现,我们处理不了平移的这种情况
x′=x+txy′=y+ty x'=x+t_x\\ y'=y+t_y x′=x+txy′=y+ty
我们不想单独处理这种情况,我们想统一放在矩阵中来处理。
于是我们引入了一齐次坐标!
2. 齐次坐标
为了能表示平移,我们多增加了一个维度。
对于2D的点来说它的坐标表示变成了:(x,y,1)⊤(x,y,1)^{\top}(x,y,1)⊤
对于2D的点来说它的向量表示变成了:(x,y,0)⊤(x,y,0)^{\top}(x,y,0)⊤
于是我们可以用下面的方式来表示平移了:
x′y′w=10tx01ty001xyz=x+txy+ty1 \begin{bmatrix} x'\\y'\\w \end{bmatrix}= \begin{bmatrix} 1 & 0 & t_x\\ 0 & 1 & t_y\\ 0 & 0 & 1\\ \end{bmatrix} \begin{bmatrix} x\\y\\z \end{bmatrix}= \begin{bmatrix} x+t_x\\y+t_y\\1 \end{bmatrix} x′y′w = 100010txty1 xyz = x+txy+ty1
对于我们新增的w的理解
vector+vector=vectorpoint−point=vectorpoint+vector=pointpoint+point=point vector + vector = vector\\ point -point = vector\\ point+vector = point\\ point+point = point vector+vector=vectorpoint−point=vectorpoint+vector=pointpoint+point=point
对于ω≠1\omega \ne 1ω=1且不为0的情况
xyw=x/wy/w1 \begin{bmatrix} x\\y\\w \end{bmatrix}= \begin{bmatrix} x/w\\y/w\\1 \end{bmatrix} xyw = x/wy/w1
我们把上面的线性变化和平移变化合起来的变化称为仿射变换
x′y′\]=\[abcd\]\[xy\]+\[txty\] \\begin{bmatrix} x'\\\\y'\\\\ \\end{bmatrix}= \\begin{bmatrix} a \& b\\\\c \& d \\end{bmatrix} \\begin{bmatrix} x\\\\y \\end{bmatrix}+ \\begin{bmatrix} t_x\\\\t_y \\end{bmatrix} \[x′y′\]=\[acbd\]\[xy\]+\[txty
引入齐次坐标
x′y′1=abtxcdty001xy1 \begin{bmatrix} x'\\y'\\1 \end{bmatrix}= \begin{bmatrix} a & b & t_x\\c & d & t_y\\ 0 & 0 & 1 \end{bmatrix} \begin{bmatrix} x\\y\\1 \end{bmatrix} x′y′1 = ac0bd0txty1 xy1
3. 变换的组合
3.1 逆变换
跟矩阵的逆一样
B=SAS−1B=A B=SA\\ S^{-1}B=A B=SAS−1B=A
3.2 变换组合
变换的顺序很重要,因为矩阵乘法不可交换
而且我们的变换矩阵的乘是从右往左的。
但是矩阵的乘满足结合律
于是有
An(⋯A2(A1(X)))=(An⋯A2A1)X A_n(\cdots A_2(A_1(X))) = (A_n\cdots A_2A_1) X An(⋯A2(A1(X)))=(An⋯A2A1)X
我们可以预先计算出所有变换矩阵变成一个矩阵
举个例子,如何计算绕任意点旋转?
可以按下面的顺序去计算
- 我们把这个点移到原点
- 施加旋转操作
- 再把这个点移回去
矩阵的形式就像是T(c)R(α)T(−c)T(c)R(\alpha)T(-c)T(c)R(α)T(−c)
注意从右向左!
后面推广到三维的情况就不推了,比较类似。
4. pa0
其实就是个环境搭建
games101主页的给的硬盘打不开,不打了;看了评论区说搞个Eigen库就好了。
还想着用Eigen里的括号初始化,居然要3.4.版本后才支持,默认安装的是3.3.7。

于是把源码拉下来,编译一下
sh
cd eigen-3.4.0
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local
sudo make install
验证版本对没有
sh
pkg-config --modversion eigen3
对了,就可以做pa0的作业:
给定一个点 P=(2,1), 将该点绕原点先逆时针旋转45◦,再平移(1,2), 计算出
变换后点的坐标(要求用齐次坐标进行计算)。
这个其实就是代进旋转矩阵算一下的事,主要检验环境对不对。
cpp
std::cout << "This is my part" << std::endl;
Eigen::Vector3d point( 2, 1, 1);
double theta{M_PI / 4};
// Example of use Matrix3d
Eigen::Matrix3d rot {
{ cos(theta), -sin(theta), 1 },
{ sin(theta), cos(theta), 2},
{ 0, 0, 1}
};
Eigen::Vector3d np = rot * point;
std::cout << rot << std::endl;
std::cout << "I'm wondering getting a row space?" << std::endl;
std::cout << np << std::endl;
还听deepseek改了下cmake的文件
CMakeLists.txt
cmake_minimum_required (VERSION 2.8.11)
project (Transformation C CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
#include_directories(EIGEN3_INCLUDE_DIR)
add_executable (Transformation main.cpp)
find_package(Eigen3 3.4 REQUIRED)
target_link_libraries(Transformation Eigen3::Eigen)