Games101作业1:旋转矩阵及投影变换

Assignment1

前置知识

旋转矩阵(二维)

( c o s α − s i n α s i n α c o s α ) \begin{pmatrix} cos\alpha&-sin\alpha \\ sin\alpha&cos\alpha \end{pmatrix} (cosαsinαsinαcosα)
三维的旋转矩阵,保持这四个系数的值和相对位置不变,绕哪个轴转,就将对应列设成1,四个系数补到对应位置上。唯一例外是绕y轴旋转,右上角的符号要移到左下角(相对其他两矩阵转置),因为绕y转时叉积方向和另外两条轴相反(右手拇指向着旋转轴的方向,绕x转是y到z,绕z转是x到y;绕y转若想得到x到z需要拇指背对y轴方向)

View/Transformation

如何定义一个camera 位置、Up方向、Look-at方向

camera坐标系 原点、Y轴(Up)、Z轴(-Look-at)

变换矩阵(从World Space到View Space)
M v i e w = R v i e w T v i e w M_{view}=R_{view}T_{view} Mview=RviewTview
涉及坐标系变换,先将原点从World Space的原点移到Camera的位置(-X,-Y,-Z);再旋转(用World Space中的Camera三条轴位置所得矩阵的逆矩阵),由于是纯旋转(正交)矩阵,逆矩阵等于转置矩阵

Perspective Projection

任务 现实中视锥体近平面n比远平面f要小(近大远小),然而我们要将视锥体投影到齐次坐标系中,所以需要将f映射成与n一样的大小并保持对应关系不变(将远平面f挤成近平面n一样大小),再对得到的立方体用正交变换

推导

x轴和y轴不涉及复杂变换,因此用简单投影公式即可(如Ynew = Yold*(Zn/Z) z为视锥体里面的点 n为近平面:将视锥体内挤成和n一样大小)

由此得到变换后结果(同时乘了z,此时z仍未知),由该结果可倒推出部分M
∵ M P 2 O ( x y z 1 ) = ( n x n y u n k n o w n z ) ∴ M P 2 O = ( n 0 0 0 0 n 0 0 ? ? ? ? 0 0 1 0 ) \because M_{P2O} \begin{pmatrix} x \\ y \\ z \\ 1\end{pmatrix} = \begin{pmatrix} nx \\ ny \\ unknown \\ z\end{pmatrix} \therefore M_{P2O} = \begin{pmatrix} n&0&0&0 \\ 0&n&0&0 \\ ?&?&?&? \\ 0&0&1&0\end{pmatrix} MP2Oxyz1=nxnyunknownzMP2O=n0?00n?000?100?0
接下来从近平面n和远平面分别得到两条性质(相当于代入特殊值n和f解方程)

近平面n上的点全部不变 远平面f上的点Z坐标全部不变

首先运用第一条性质,将n代入Z:
∵ M P 2 O ( x y n 1 ) = ( n x n y n 2 n ) ∴ ( 0 0 A B ) ( x y n 1 ) = n 2 \because M_{P2O}\begin{pmatrix} x \\ y \\ n \\ 1\end{pmatrix} = \begin{pmatrix} nx \\ ny \\ n^{2} \\ n\end{pmatrix} \therefore \begin{pmatrix} 0&0&A&B \end{pmatrix} \begin{pmatrix} x \\ y \\ n \\ 1\end{pmatrix} = n^2 MP2Oxyn1=nxnyn2n(00AB)xyn1=n2
进一步推导除第三行的形式(最终结果n平方和xy都无关,因此前两项为0)

同理运用第二条性质,将f代入Z(形式完全一致)

联立两条方程,得出完整的投影矩阵:
{ A n + B = n 2 A f + B = f 2 → { A = n + f B = − n f → M P 2 O = ( n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ) \begin{cases} An+B=n^2 \\Af+B=f^2 \end{cases} \rightarrow \begin{cases} A = n+f \\B=-nf \end{cases} \rightarrow M_{P2O} = \begin{pmatrix} n&0&0&0 \\ 0&n&0&0 \\ 0&0&n+f&-nf \\ 0&0&1&0\end{pmatrix} {An+B=n2Af+B=f2{A=n+fB=nfMP2O=n0000n0000n+f100nf0
再乘上正交矩阵,得到完整投影矩阵:

正交矩阵的任务是先将视线立方体移到(View Space)的原点,再缩放到标准大小[-1,1];在右手坐标系中,近平面n的Z坐标比远平面f要大,因此是n-f
M 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 1 − ( n + f ) / 2 0 0 0 1 ) M_{O} = \begin{pmatrix} 2/(r-l)&0&0&0 \\ 0&2/(t-b)&0&0 \\ 0&0&2/(n-f)&0 \\ 0&0&0&1\end{pmatrix} \begin{pmatrix} 1&0&0&-(r+l)/2 \\ 0&1&0&-(t+b)/2 \\ 0&0&1&-(n+f)/2 \\ 0&0&0&1\end{pmatrix} MO=2/(rl)00002/(tb)00002/(nf)00001100001000010(r+l)/2(t+b)/2(n+f)/21
在视锥体内部的点经过变换后的z值比原来小:变换矩阵与(x,y,z,1)相乘后z的值等于(-nf)*z^(-1)+(n+f),是个反比例函数,这个图像恒过(n,n)与(f,f),在n与f之间,是下凹的,所以变小了

code

Eigen::Matrix4f get_model_matrix(float rotation_angle)
{
    //  将角度转换为弧度
    float radian = (rotation_angle * MY_PI)/ 180.0 ;
    Eigen::Matrix4f translate;
    translate <<
        cos(radian), -sin(radian), 0, 0,
        sin(radian), cos(radian), 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1;
    model = translate * model;
    return model;
}

Eigen::Matrix4f get_projection_matrix(float eye_fov, float aspect_ratio,float zNear, float zFar)
{
    Eigen::Matrix4f projection = Eigen::Matrix4f::Identity();

    //  用参数构造正交矩阵
	Eigen::Matrix4f OrthographicRS = Eigen::Matrix4f::Identity();
    Eigen::Matrix4f OrthographicT = Eigen::Matrix4f::Identity();
    float top = zNear * tan((eye_fov / 2.0) * MY_PI / 180.0);   //  注意用的是zNear(最终大小以n平面为准)
    float right = top * aspect_ratio;                       //  乘屏幕比得x坐标

    OrthographicRS <<
        1 / right, 0, 0, 0,
        0, 1 / top, 0, 0,
        0, 0,1 / (zNear - zFar), 0,
        0, 0, 0, 1;

    OrthographicT <<
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 1, -(zNear + zFar) / 2,
        0, 0, 0, 1;

    projection = OrthographicRS * OrthographicT;

	//  投影矩阵
	Eigen::Matrix4f P2O = Eigen::Matrix4f::Identity();
	P2O <<
		zNear, 0, 0, 0,
		0, zNear, 0, 0,
		0, 0, zNear + zFar, -zNear * zFar,
		0, 0, 1, 0;

    projection *= P2O;

    return projection;
}

注意事项

角度值转弧度制

angle = rad * PI / 180

bug:看不见三角形,且按a或d几下之后提示溢出

矩阵左乘和右乘的问题:写投影矩阵时,将P2O放在正交矩阵的坐标,实际上应该放到右边(变换矩阵应该放在右边

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值