计算机图形学-----齐次坐标、空间变换矩阵和通用的建模方法

版权声明:所有的博客都是个人笔记,交流可以留言或者加QQ:2630492017 https://blog.csdn.net/qq_35976351/article/details/84871397

齐次坐标系

齐次坐标系是为了区分空间点和向量的。三维空间中, ( x , y , z ) (x,y,z) 可以表示一个点 p p 的位置,但是也可以表示一个向量 v \bf{v} 。对于点的移动是有实际意义的,但是移动向量没有任何意义!点和向量在三维空间中的真正区别在于是否支持移动。

引入齐次坐标 ( x , y , z , w ) T (x,y,z,w)^T w = 1 w=1 表示空间的点, w = 0 w=0 表示空间的向量。这样是为了后期矩阵变换的时候,统一运算规则,不用单独区分点或者向量。

空间变换矩阵

一般来说,在图形学中,使用矩阵的方式进行变换,可以把多个连续的操作压缩到一个中,减少计算量;同时利用矩阵的优化算法,可以提高计算效率。

位移矩阵
O f f s e t = [ 1 0 0 T x 0 1 0 T y 0 0 1 T z 0 0 0 1 ] \bf{Offset}= \begin{bmatrix} 1 & 0 & 0 & \bf{T_x} \\ 0 & 1 & 0 & \bf{T_y}\\ 0 & 0 & 1 & \bf{T_z} \\ 0 & 0 & 0 & 1 \end{bmatrix}
T x \bf{T_x} T y \bf{T_y} T z \bf{T_z} 分别表示沿着 x x y y z z 轴的平移距离。根据矩阵的运算法则,如果是点的坐标,那么 w = 1 w=1 正好线性累加上位移;如果是向量, w = 0 w=0 会抵消位移的效果。

x x 轴的旋转矩阵
R o t a t i o n X = [ 1 0 0 0 0 cos θ sin θ 0 0 sin θ cos θ 0 0 0 0 1 ] \bf{RotationX}= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos{\theta} & -\sin{\theta} & 0\\ 0 & \sin{\theta} & \cos{\theta} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
这是右手系的变换矩阵, θ \theta 是从 x x 轴负向看向正向顺时针的旋转角度。

y y 轴的旋转矩阵
R o t a t i o n Y = [ cos θ 0 sin θ 0 0 1 0 0 sin θ 0 cos θ 0 0 0 0 1 ] \bf{RotationY}= \begin{bmatrix} \cos{\theta} & 0 & \sin{\theta} & 0 \\ 0 & 1 & 0 & 0\\ -\sin{\theta} & 0 & \cos{\theta} & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
这是右手系的变换矩阵, θ \theta 是从 y y 轴负向看向正向顺时针的旋转角度。

z z 轴的旋转矩阵
R o t a t i o n Y = [ cos θ sin θ 0 0 sin θ cos θ 0 0 0 0 0 0 0 0 0 1 ] \bf{RotationY}= \begin{bmatrix} \cos{\theta} & -\sin{\theta} & 0 & 0 \\ \sin{\theta} & \cos{\theta} & 0 & 0 \\ 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
这是右手系的变换矩阵, θ \theta 是从 z z 轴负向看向正向顺时针的旋转角度。

绕任意轴的旋转矩阵:
假设一个轴的向量 R = ( R x , R y , R z ) \bf{R}=(\bf{R_x}, \bf{R_y},R_z) ,现在绕这个轴进行旋转,那么变换矩阵应该是:
R o t a t i o n Y = [ cos θ + R x 2 ( 1 cos θ ) R x R y ( 1 cos θ R z sin θ ) R x R z ( 1 cos θ + R y sin θ ) 0 R y R x ( 1 cos θ + R z sin θ ) cos θ + R y 2 ( 1 cos θ ) R y R z ( 1 cos θ R x sin θ ) 0 R z R x ( 1 cos θ R z sin θ ) R z R y ( 1 cos θ + R x sin θ ) cos θ + R z 2 ( 1 cos θ ) 1 0 0 0 1 ] \bf{RotationY}= \begin{bmatrix} \cos{\theta}+R_{x}^2(1-\cos{\theta}) & R_xR_y(1-\cos{\theta}-R_z\sin{\theta}) & R_xR_z(1-\cos{\theta}+R_y\sin{\theta}) & 0 \\ R_yR_x(1-\cos{\theta}+R_z\sin{\theta}) & \cos{\theta}+R_{y}^2(1-\cos{\theta}) & R_yR_z(1-\cos{\theta}-R_x\sin{\theta}) & 0 \\ R_zR_x(1-\cos{\theta}-R_z\sin{\theta}) & R_zR_y(1-\cos{\theta}+R_x\sin{\theta}) & \cos{\theta}+R_{z}^2(1-\cos{\theta}) & 1 \\ 0 & 0 & 0 & 1 \end{bmatrix}

一般的建模方法

矩阵乘法是不可逆的,因此不能直接随便交换变换的顺序。先旋转再平移和先平移再旋转的效果是不同的;同样的,绕不同的轴旋转的次序不同,得到的结果可能也是不同的。一般来说,应该先执行局部的旋转,再执行局部坐标系的平移。

建模时,应该以物体为参考中心,选定一个物体的局部坐标中心 l o c a l C e n t e r \bf{localCenter} ,使用齐次坐标系表示,然后再给出物体各个定点在局部坐标系中的位置,局部坐标累计上局部旋转在累计上局部中心的坐标,即可生成全局的坐标。

注意,一定是先进行局部坐标系的旋转,再执行平移;否则结果错误。还有,这里使用的列向量的机制,矩阵乘法是从右向左结合的,那么变换矩阵是:
w o r l d P o s = O f f s e t R o t a t i o n l o c a l P o s \bf{worldPos}=\bf{Offset}*Rotation*localPos

Github示例代码,纯C++实现的渲染管线:
https://github.com/StudentErick/PipeLine

猜你喜欢

转载自blog.csdn.net/qq_35976351/article/details/84871397