前言
最近下定決心開始打好底子,走技美路線,於是找到了對岸很熱門的圖形學課程
去年有看幾集但不了了之,這次要努力堅持且每個作業都會寫一篇文章記錄
目標
• get_model_matrix(float rotation_angle): 逐一元素地建構模型變換矩
陣並傳回該矩陣。 在此函數中,你只需要實現三維中繞 z 軸旋轉的變換矩陣,
而不用處理平移與縮放。
• get_projection_matrix(float eye_fov, float aspect_ratio, float
zNear, float zFar): 使用給定的參數逐個元素地建立透視投影矩陣並返回
該矩陣。
• 加分題: 在 main.cpp 中建構一個函數,函數的作用是得到繞任意
過原點的軸的旋轉變換矩陣。
Eigen::Matrix4f get_rotation(Vector3f axis, float angle)
實作
1.旋轉矩陣Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
Eigen::Matrix4f model;
// TODO: Implement this function
// Create the model matrix for rotating the triangle around the Z axis.
// Then return it.
float sinValue = std::sin(rotation_angle * MY_PI / 180);
float cosValue = std::cos(rotation_angle * MY_PI / 180);
model << cosValue, -sinValue, 0.0, 0.0,
sinValue, cosValue, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0;
return model;
}
課堂上解釋過的旋轉矩陣,作業只有旋轉Z軸,太簡單了
要注意的是角度要換算成弧度
2.透視投影矩陣
Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,
float zNear, float zFar)
{
// Students will implement this function
Eigen::Matrix4f projection_pers2ortho = Eigen::Matrix4f::Identity();
// TODO: Implement this function
// Create the projection matrix for the given parameters.
// Then return it.
projection_pers2ortho << zNear, 0, 0, 0,
0, zNear, 0, 0,
0, 0, zNear + zFar, -zNear * zFar,
0, 0, 1, 0;
float height = tan(eye_fov / 2 * MY_PI / 180) * -zNear * 2;
float width = height * aspect_ratio;
float depth = std::abs(zNear - zFar);
Eigen::Matrix4f projection_ortho;
projection_ortho << 2 / width, 0, 0, -width / 2,
0, 2 / height, 0, -height / 2,
0, 0, 2 / depth, -depth / 2,
0, 0, 0, 1;
return projection_ortho * projection_pers2ortho;
}
根據課程內容,透視投影矩陣是將透視投影的視錐體變換為長方體
透視投影矩陣
再對變換過的座標乘上正視投影矩陣就完成了
要注意的是上面算出的height要乘上近平面的距離(zNear)而不是遠平面的距離(zFar)。
還有zNear要是負的,因為在這邊相機是往-Z方向看,zNear和zFar都是負數,若沒有加負號則height會是負數,會造成矩陣將scale乘上負數,導致成像是上下顛倒的
最後編譯執行可以得到一個三角形,並且按A或D可以旋轉三角形
3.加分題
這題滿難的,翻了上課影片老師只有稍微帶過一個可以繞任意軸旋轉的公式 - 羅德里格旋轉公式(rodrigues rotation formula)
看了真的很懵啊...尤其我數學又不好,雖然但是,我還是耐著性子查了一下推導方法
很多推導都是30分鐘以上的長片,又更加勸退我,不然就是一堆代數的文字講解
好在有一部影片先用簡單的畫圖方式讓人理解,我才徹底明白
其實就是假設旋轉軸為Y軸,再用叉積、點積等方式取得Z軸及X軸,在Z軸及X軸上做2D旋轉,最後把這些向量加起來而已。也許哪天有空的時候做個3D視覺化推導
了解原理後,再將公式寫成程式碼,就能讓三角形繞特定軸旋轉了!
Eigen::Matrix4f get_rotation(Vector3f axis, float angle)
{
axis = axis.normalized();
Eigen::Matrix4f model = Eigen::Matrix4f::Identity();
Eigen::Matrix3f temp = Eigen::Matrix3f::Identity();
float ag = angle / 180 * MY_PI;
Eigen::Matrix3f tr;
Eigen::Matrix3f crossM;
crossM << 0, -axis[2], axis[1],
axis[2], 0, -axis[0],
-axis[1], axis[0], 0;
tr = cos(ag) * temp + (1 - cos(ag)) * axis * axis.transpose() + crossM * sin(ag);
model << tr(0, 0), tr(0, 1), tr(0, 2), 0,
tr(1, 0), tr(1, 1), tr(1, 2), 0,
tr(2, 0), tr(2, 1), tr(2, 2), 0,
0, 0, 0, 1;
return model;
}