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

齐次坐标系

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

引入齐次坐标 ( x , y , z , w ) T (x,y,z,w)^T (x,y,z,w)T w = 1 w=1 w=1表示空间的点, w = 0 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} Offset=100001000010TxTyTz1
T x \bf{T_x} Tx T y \bf{T_y} Ty T z \bf{T_z} Tz分别表示沿着 x x x y y y z z z轴的平移距离。根据矩阵的运算法则,如果是点的坐标,那么 w = 1 w=1 w=1正好线性累加上位移;如果是向量, w = 0 w=0 w=0会抵消位移的效果。

x 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} RotationX=10000cosθsinθ00sinθcosθ00001
这是右手系的变换矩阵, θ \theta θ是从 x x x轴负向看向正向顺时针的旋转角度。

y 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} RotationY=cosθ0sinθ00100sinθ0cosθ00001
这是右手系的变换矩阵, θ \theta θ是从 y y y轴负向看向正向顺时针的旋转角度。

z 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} RotationY=cosθsinθ00sinθcosθ0000000001
这是右手系的变换矩阵, θ \theta θ是从 z z z轴负向看向正向顺时针的旋转角度。

绕任意轴的旋转矩阵:
假设一个轴的向量 R = ( R x , R y , R z ) \bf{R}=(\bf{R_x}, \bf{R_y},R_z) R=(Rx,Ry,Rz),现在绕这个轴进行旋转,那么变换矩阵应该是:
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} RotationY=cosθ+Rx2(1cosθ)RyRx(1cosθ+Rzsinθ)RzRx(1cosθRzsinθ)0RxRy(1cosθRzsinθ)cosθ+Ry2(1cosθ)RzRy(1cosθ+Rxsinθ)0RxRz(1cosθ+Rysinθ)RyRz(1cosθRxsinθ)cosθ+Rz2(1cosθ)00011

一般的建模方法

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

建模时,应该以物体为参考中心,选定一个物体的局部坐标中心 l o c a l C e n t e r \bf{localCenter} 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 worldPos=OffsetRotationlocalPos

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

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值