GAMES101作業1


作業目標:

  • get_model_matrix(float rotation_angle):

逐個元素地構建模型變換矩陣並返回該矩陣。在此函數中,你只需要實現三維中繞 z 軸旋轉的變換矩陣,而不用處理平移與縮放

  • get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar):

使用給定的參數逐個元素地構建透視投影矩陣並返回該矩陣。

實現:

  • get_model_matrix(float rotation_angle)
    三維空間,繞Z軸旋轉,由一個角度,得到一個旋轉矩陣
Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
	float theta = (rotation_angle / 180.0) * MY_PI;//角度轉弧度
	Eigen::Matrix4f model = Eigen::Matrix4f::Identity();//新建一個4x4的矩陣

	model << std::cos(theta), -std::sin(theta), 0, 0,
		 std::sin(theta), std::cos(theta), 0, 0,
		 0, 0, 1.0, 0,
		 0, 0, 0, 1.0;
	//PS:繞X、Z軸旋轉的旋轉矩陣同理,繞Y軸的旋轉矩陣略有不同,sin和-sin的位置會互換
	
	return model;
}

  • get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)

攝像機上方是y正半軸,右邊是x正半軸、看向z負半軸

現在假設我們站在x正半軸 看向x負半軸

eye_fov:視角,攝像機最上方能看到的角度到最下方能看到的角度

aspect_ratio:矩形寬高比

zNear、zFar:近處面的z值,遠處面的z值,注意,朝向z負半軸,即兩者均為負值

目標得到投影矩陣,先將透視圖轉化為正交圖,然后再進行縮放,使得x、y、z三維方向的值的范圍均在[-1,1],最后將其平移到視口中心

視錐->立方體
透視圖->正交圖
image

根據zFar、zNear、eye_fov、aspect_ratio可以算出寬、高。
image

Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio, float zNear, float zFar)
{
	//Eigen::Matrix4f::Identity() 初始化為單位矩陣
	Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();

	//透視圖,近大遠小,是個視錐  此矩陣是一個公式
	Eigen::Matrix4f P2O = Eigen::Matrix4f::Identity();//將透視矩陣擠壓成正交矩陣
	P2O << zNear, 0, 0, 0,
		0, zNear, 0, 0,
		0, 0, zNear + zFar, - zFar* zNear,
		0, 0, 1.0, 0;

	float halfEyeAngelRadian = (eye_fov / 2.0 / 180.0) * MY_PI; //視角的一半
	float y_top = -zNear * std::tan(halfEyeAngelRadian);//y軸正方向值 = 顯示視口的一半高度 zNear是負值!
	float x_left = -y_top * aspect_ratio;//x軸負方向值 = 顯示視口的一半寬度
	float y_down = -y_top;
	float x_right = -x_left;

	//構造縮放矩陣,使視口大小等同窗口大小
	Eigen::Matrix4f scaleMat = Eigen::Matrix4f::Identity();
	scaleMat << 2 / (x_right - x_left), 0, 0, 0,			//將中心視為原點,則窗口的三維方向值域均為[-1,1] 
				0, 2 / (y_top - y_down), 0, 0,				//縮放的倍數為 期望值/當前值
				0, 0, 2 / (zNear - zFar), 0,				//所以縮放的倍數為 (1+1)/某一維度的當前值
				0, 0, 0, 1;

	//構造平移矩陣,將視口左下角移動到原點
	Eigen::Matrix4f translateMat = Eigen::Matrix4f::Identity();
	
	//左下角的點原本為 (x_left,y_down,zNear)
	//注意!此時已經經過了縮放,所以左下角的點的位置已經變化
	//左下角的點現在為 (-1,-1,zNear)
	//即其實可以不用管x和y軸,比較尺寸已經和窗口匹配了
	//但網上其他人卻還是右下方注釋的那樣寫的,左側+右側或者上側+下側,結果不都是0么?
	translateMat << 1, 0, 0, 0,					//-(x_left+x_right)/2
			0, 1, 0, 0,					//-(y_top+y_down)/2
			0, 0, 1, -(zNear+zFar)/2,
			0, 0, 0, 1;
	//注意!此處矩陣相乘,右結合率,必須先壓縮矩陣,再縮放,最后平移,順序一定不可以改!
	projection = translateMat * scaleMat * P2O;
	
	return projection;
}

運行結果:

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM