This series of blogs is to record the problems and thoughts that the author encountered while studying the GAMES101 course.
- GAMES101: Course official website
- GAMES101: B station video
- GAMES101: Related file download (Baidu SkyDrive)
1. Basic questions
From Assignment1.pdf, you can know that the task of the basic question is to fill in the two functions
get_model_matrix()
get_projection_matrix()
The other module function frameworks have already been given. You only need to carefully read the content in Assignment1.pdf and read the source code to try to understand. Affect the final job result.
Next, explain the functions that need to be filled in this question in the order of MVP.
-
get_model_matrix() :
Since the title requires rotation around the z-axis , the rotation matrix can be known from homework 0:
first understand the meaning of the formal parameters passed in to the function, and by observingmian()
the function, we can know thatrotation_angle
the rotation angle is passed in: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 Radian_angle = rotation_angle / 180 * MY_PI; //Radian Eigen::Matrix4f Rz; Rz << cos(Radian_angle), -sin(Radian_angle), 0, 0, sin(Radian_angle), cos(Radian_angle), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1; model = Rz * model; return model; }
The
float Radian_angle = rotation_angle / 180 * MY_PI;
statement is because the trigonometric functions such as sin and cos in the math library use the radian system, but the inputrotation_angle
is the angle system, and the angle needs to be converted to radians first. -
get_view_matrix() :
The working framework of this function has been given. By observingmian()
the function, we can know thateye_pos
the angle of view position is passed in, that is, the position of the camera. Next, briefly analyze the function of the function:Eigen::Matrix4f get_view_matrix(Eigen::Vector3f eye_pos) { Eigen::Matrix4f view = Eigen::Matrix4f::Identity(); Eigen::Matrix4f translate; translate << 1, 0, 0, -eye_pos[0], 0, 1, 0, -eye_pos[1], 0, 0, 1, -eye_pos[2], 0, 0, 0, 1; view = translate * view; return view; }
The function of the view matrix is actually the process of moving the camera to the standard source point. From this analysis, we can know that the
translate
matrix in the above code actually does such a thing, because we can know from the lecture that the translation operation is actually at the end of the fourth-order matrix One column represents the translation distance.
Sinceeye_pos
the current position of the camera is stored in , but to translate to the source point, a parameter with a negative value must be translated, such as (1, 0, 0), if you want to translate to the source point, you must translate -1 distance on the x-axis, so by This makes it easy to understandtranslate
the camera translation operation done by the matrix. -
get_projection_matrix() :
The last is the projection matrix. Through the analysis of Professor Yan, we can know that the projection matrix first needs to compress the image, that is, squeeze a high-resolution image into an image that can be put into the camera, and then proceed Orthogonal projection can obtain the image of distant objects projected to the camera.The corresponding is actually M persp → ortho M_{persp\rightarrow ortho}Mpersp→orthomatrix for image compression and M ortho M_{ortho}MorthoThe matrix is orthographically projected. Through the analysis of Professor Yan, we can know that the two matrices are:
M persp → ortho = ( n 0 0 0 0 n 0 0 0 0 n + f − nf 0 0 1 0 ) M_{persp\rightarrow ortho}=\left( \begin{matrix} n& 0& 0& 0\\ 0& n& 0& 0\\ 0& 0& n+f& -nf\\ 0& 0& 1& 0\\ \end{matrix} \right)Mpersp→ortho= n0000n0000n+f100−nf0
M o r t h o = ( 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f 0 0 0 0 1 ) ( 1 0 0 − r + l 2 0 1 0 − t + b 2 0 0 0 − n + f 2 0 0 0 1 ) M_{ortho}=\left( \begin{matrix} \frac{2}{r-l}& 0& 0& 0\\ 0& \frac{2}{t-b}& 0& 0\\ 0& 0& \frac{2}{n-f}& 0\\ 0& 0& 0& 1\\ \end{matrix} \right) \left( \begin{matrix} 1& 0& 0& -\frac{r+l}{2}\\ 0& 1& 0& -\frac{t+b}{2}\\ 0& 0& 0& -\frac{n+f}{2}\\ 0& 0& 0& 1\\ \end{matrix} \right) Mortho= r−l20000t−b20000n−f200001 100001000000−2r+l−2t+b−2n+f1
First analyze the meaning of the formal parameters of the projection matrixeye_fov
: is the viewing angle, which is the opening angle shown on page 30 of GAMES101_Lecture_04.pdfaspect_ratio
: is the aspect ratio, this title is 1, that is, the camera is squarezNear
andzFar
: are the distance from the eye to the camera and the distance from the eye to the view, corresponding to nn shown on page 30 of GAMES101_Lecture_04.pdfn andfff
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar) { zNear = -zNear; zFar = -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. Eigen::Matrix4f Mpersp_to_ortho; Mpersp_to_ortho << zNear, 0, 0, 0, 0, zNear, 0, 0, 0, 0, zNear+zFar, -zNear*zFar, 0, 0, 1, 0; float eye_fov_havle = eye_fov / 2 / 180 * MY_PI; float top = tan(eye_fov_havle) * -zNear; //because zNear is a nagetive number, but top is positive number float bottle = -top; float right = top * aspect_ratio; float left = -right; Eigen::Matrix4f Mortho, translation, canonical; translation << 1, 0, 0, -(right+left)/2, 0, 1, 0, -(top+bottle)/2, 0, 0, 1, -(zNear+zFar)/2, 0, 0, 0, 1; canonical << 2/(right-left), 0, 0, 0, 0, 2/(top-bottle), 0, 0, 0, 0, 2/(zNear-zFar), 0, 0, 0, 0, 1; Mortho = canonical * translation; projection = Mortho * Mpersp_to_ortho; return projection; }
The first is the sum of the first two sentences
zNear = -zNear;
,zFar = -zFar;
because the formula derived by Professor Yan in class is based on the fact that we are in the positive direction of the z-axis and look towards the negative direction, so the nn in the formulan andfff is a negative number, but observingmain()
the function shows that when the function is called, a positive number is passed in, that is, the meaning of these two formal parameters is the distance, so we need to manually adjust it to a negative value.The following code is very simple, and you should be able to understand it after listening carefully in class. It corresponds to the conversion process on pages 23 and 24 of GAMES101_Lecture_04.pdf .
Then according to the same steps of job 0, first create a new build folder in the corresponding code framework , then copy run0.sh to the build folder, and change the name to run1.sh , and follow the steps in Assignment1.pdf , Change the content of it to
#/bin/bash cmake .. make -j4 ./Rasterizer
Execute after the modification is completed
./run1.sh
, and the following results show that the operation is correct:
Press the A and D keys to rotate the triangle around the z-axis , because we are looking in the negative direction of the z-axis , so press the A key to increase the angle and the triangle should rotate counterclockwise That's right.
Two, improve the question
According to Assignment1.pdf , it can be seen that the improvement question needs to construct get_rotation()
a function to realize the rotation around any axis. The Rodrigues' Rotation Formula
mentioned by Professor Yan in the class can realize this function, which is located on page 10 of the courseware GAMES101_Lecture_04.pdf , but to be honest, I did not understand the principle of this formula, but realized the function according to the gourd painting, and did not To know whether the answer is correct, dig a hole first, and fill it in later when you have time [doge.jpg].get_rotation()
Here I recommend 剑 来!
a blog . Chapter 2.2 is about the formula for rotating around any axis in three dimensions. It is easy to understand, but it is inconsistent with the Rodrigue rotation formula taught by Professor Yan. It can be used as a supplement Materials to read.
Eigen::Matrix4f get_rotation(Vector3f axis, float 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 Radian_angle = rotation_angle / 180 * MY_PI; //Radian
Eigen::Matrix4f I, N, Rod;
Eigen::Vector4f n(axis.x(), axis.y(), axis.z(), 0);
Eigen::RowVector4f nT(axis.x(), axis.y(), axis.z(), 0);
I <<
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1;
N <<
0, -axis.z(), axis.y(), 0,
axis.z(), 0, -axis.x(), 0,
-axis.y(), axis.x(), 0, 0,
0, 0, 0, 1;
Rod = cos(Radian_angle) * I + (1 - cos(Radian_angle)) * n * nT + sin(Radian_angle) * N;
Rod(3, 3) = 1; //Ensure correct proportion
return Rod;
}