GAMES101 Assignment1 (对应Lecture3-4)

课程作业框架来自GAMES

基础部分:

目标要求:需要完成一个旋转矩阵和一个透视投影矩阵,根据给定的三维坐标在屏幕上绘制相应的三角形。

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* 绕Z轴旋转矩阵
* return model
* parameters:
* rotation_angle:旋转角度
**/
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();

// TODO: Implement this function
// Create the model matrix for rotating the triangle around the Z axis.
// Then return it.
// 框架提供的转为弧度制函数
float angle = radian(rotation_angle);
float cos_angle = cos(angle);
float sin_angle = sin(angle);

// 旋转矩阵
Eigen::Matrix4f rotation_matrix;
rotation_matrix<<cos_angle,-sin_angle,0,0,sin_angle,cos_angle,0,0,0,0,1,0,0,0,0,1;
model = rotation_matrix * model;

return model;
}


/* 透视投影矩阵
* return Eigen::Matrix4f projection
* parameters
* eye_fov: 垂直可视度
* aspect_ratio: width/height
* zNear>0, zFar>0
**/
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
float zNear, float zFar)
{
// Students will implement this function
// 默认单位矩阵
Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();

// TODO: Implement this function
// Create the projection matrix for the given parameters.
// Then return it.

float half_height = tan(eye_fov/2*MY_PI/180)*zNear;
float half_width = aspect_ratio*half_height;
// 透视范围顶部
float t = half_height;
// 透视范围右侧
float r = half_width;
// 透视范围底部
float b = -half_height;
// 透视范围左侧
float l = -half_width;
// 近端, 因为是z轴负方向
float n = -zNear;
// 远端
float f = -zFar;

// 变换透视投影的方式是将透视投影转变成正交投影
Eigen::Matrix4f S,T,M;

// 缩放成canonical
S<<
2/(r-l),0,0,0,
0,2/(t-b),0,0,
0,0,2/(n-f),0,
0,0,0,1;

// 正交投影的平移矩阵,平移到原点
T<<
1,0,0,-(l+r)/2,
0,1,0,-(b+t)/2,
0,0,1,-(n+f)/2,
0,0,0,1;

// 透视投影转正交投影
M<<
zNear,0,0,0,
0,zNear,0,0,
0,0,zNear+zFar,-zFar*zNear,
0,0,1,0;

projection = S * T * M * projection;
return projection;
}

提高部分:

目标要求:在main.cpp实现一个函数完成绕任意过原点轴的旋转变换矩阵

绕任意轴旋转函数(罗德里格斯公式)

绕n轴旋转α角度

R(n,α) = cos(α) * I + (1 - cos(α)) * n * n_transpose + sin(α) * N;其中I为单位矩阵,N为n的反对称阵

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* 
*绕axis轴旋转rotation_angle
**/
Eigen::Matrix4f get_rotation(Vector3f axis, float rotation_angle){
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
float angle = radian(rotation_angle);

Eigen::Matrix3f I = Eigen::Matrix3f::Identity();
// n的反对称阵
Eigen::Matrix3f N;
N<<
0, -axis.z(), axis.y(),
axis.z(), 0, -axis.x(),
-axis.y(), axis.x(), 0;

// 罗德里格斯
Eigen::Matrix3f rotation_matrix = cos(angle) * I + (1-cos(angle)) * axis * axis.transpose() + sin(angle) * N;

// 将3*3变成4*4
model.block<3, 3>(0,0) = rotation_matrix;

return model.
}

在这里main.cpp的main函数中两个位置的set_model切换为使用get_rotation函数,并自己设定axis