【图形学】三维几何变换理论和实现

和二维几何变换一样,三维几何变换也要引入齐次坐标。点(x,y,z)的规范化齐次坐标为(x,y,z,1)。那么三维变换矩阵就是一个4*4的方阵。
T = ( a b c l d e f m g h i n p q r s ) T=\begin{pmatrix} a&b&c&l\\d&e&f&m\\g&h&i&n\\p&q&r&s \end{pmatrix} T= adgpbehqcfirlmns
这个矩阵可以分为如下4个子矩阵
T 0 = ( a b c d e f g h i ) T 1 = ( l m n ) T 2 = ( p q r ) T 3 = ( s ) T_0=\begin{pmatrix} a&b&c\\d&e&f\\g&h&i \end{pmatrix} T_1=\begin{pmatrix} l\\m\\n\end{pmatrix}T_2=\begin{pmatrix}p&q&r\end{pmatrix}T_3=\begin{pmatrix}s\end{pmatrix} T0= adgbehcfi T1= lmn T2=(pqr)T3=(s)
其中 T 0 T_0 T0进行比例、旋转、对称、错切变换 T 1 T_1 T1进行平移变换, T 2 T_2 T2进行投影变换, T 3 T_3 T3对物体进行整体的比例变换。

平移变换

{ x ′ = x + T x y ′ = y + T y z ′ = z + T z ( T x , T y , T z 是平移系数 ) \begin{cases} x^{\prime}=x+T_x\\ y^{\prime}=y+T_y\\ z^{\prime}=z+T_z \end{cases}(T_x,T_y,T_z是平移系数) x=x+Txy=y+Tyz=z+Tz(Tx,Ty,Tz是平移系数)
设三维平移变换矩阵为T
( x ′ y ′ z ′ 1 ) = ( x + T x y + T y z + T z 1 ) = T ( x y z 1 ) 得到 T = ( 1 0 0 T x 0 1 0 T y 0 0 0 T z 0 0 0 1 ) \begin{pmatrix} x^{\prime}\\y^{\prime}\\z^{\prime}\\1 \end{pmatrix}=\begin{pmatrix}x+T_x\\y+T_y\\z_+T_z\\1\end{pmatrix}=T\begin{pmatrix}x\\y\\z\\1\end{pmatrix}得到T=\begin{pmatrix}1&0&0&T_x\\0&1&0&T_y\\0&0&0&T_z\\0&0&0&1\end{pmatrix} xyz1 = x+Txy+Tyz+Tz1 =T xyz1 得到T= 100001000000TxTyTz1

比例变换

P ( x , y , z ) 相对于原点,沿 x 轴方向缩放 S x 倍,沿 Y 轴方向缩放 S y 倍 , 沿 z 轴方向缩放 S z 倍到点 P ′ ( x ′ , y ′ , z ′ ) P(x,y,z)相对于原点,沿x轴方向缩放S_x倍,沿Y轴方向缩放S_y倍,沿z轴方向缩放S_z倍到点P_{\prime}(x^{\prime},y^{\prime},z^{\prime}) P(x,y,z)相对于原点,沿x轴方向缩放Sx倍,沿Y轴方向缩放Sy,沿z轴方向缩放Sz倍到点P(x,y,z)
设三维变换矩阵为T
( x ′ y ′ z ′ 1 ) = ( x T x y T y z T z 1 ) = T ( x y z 1 ) 得到 T = ( T x 0 0 0 0 T y 0 0 0 0 T z 0 0 0 0 1 ) \begin{pmatrix} x^{\prime}\\y^{\prime}\\z^{\prime}\\1 \end{pmatrix}=\begin{pmatrix}xT_x\\yT_y\\zT_z\\1\end{pmatrix}=T\begin{pmatrix}x\\y\\z\\1\end{pmatrix}得到T=\begin{pmatrix}T_x&0&0&0\\0&T_y&0&0\\0&0&T_z&0\\0&0&0&1\end{pmatrix} xyz1 = xTxyTyzTz1 =T xyz1 得到T= Tx0000Ty0000Tz00001

更一般的情况, P 相对于点 ( p x , p y , p z ) 进行比例变换到 P ′ P相对于点(p_x,p_y,p_z)进行比例变换到P^{\prime} P相对于点(px,py,pz)进行比例变换到P。有 { x ′ = S x ( x − p x ) + p x y ′ = S y ( y − p y ) + p y z ′ = S z ( z − p z ) + p z \begin{cases} x^{\prime}=S_x(x-p_x)+p_x\\ y^{\prime}=S_y(y-p_y)+p_y\\ z^{\prime}=S_z(z-p_z)+p_z \end{cases} x=Sx(xpx)+pxy=Sy(ypy)+pyz=Sz(zpz)+pz
此时的三维变换矩阵T为 T = ( S x 0 0 p x ( 1 − S x ) 0 S y 0 p y ( 1 − S y ) 0 0 S z p z ( 1 − S z ) 0 0 0 1 ) \\T=\begin{pmatrix} S_x&0&0&p_x(1-S_x)\\ 0&S_y&0&p_y(1-S_y)\\ 0&0&S_z&p_z(1-S_z)\\ 0&0&0&1 \end{pmatrix} T= Sx0000Sy0000Sz0px(1Sx)py(1Sy)pz(1Sz)1

旋转变换

对点(x,y,z)相对于原点(0,0,0)进行旋转操作,采用右手坐标系,即大拇指指向旋转轴的正方向,四指的转向为转角的正方向。旋转我们可分为绕x轴、y轴、z轴旋转。假设绕x轴旋转角度为 α \alpha α,绕y轴旋转角度为 β \beta β,绕z轴旋转的角度为 γ \gamma γ。则相应的变换如下:

绕x轴旋转

{ x ′ = x y ′ = y cos ⁡ α − z sin ⁡ α z ′ = y sin ⁡ α + z cos ⁡ α 三维旋转矩阵 T = ( 1 0 0 0 0 cos ⁡ α − sin ⁡ α 0 0 sin ⁡ α cos ⁡ α 0 0 0 0 1 ) \begin{cases} x^{\prime}=x\\ y^{\prime}=y\cos\alpha-z\sin\alpha\\ z^{\prime}=y\sin\alpha+z\cos\alpha \end{cases}\\三维旋转矩阵T=\begin{pmatrix} 1&0&0&0\\ 0&\cos\alpha&-\sin\alpha&0\\ 0&\sin\alpha&\cos\alpha&0\\ 0&0&0&1 \end{pmatrix} x=xy=ycosαzsinαz=ysinα+zcosα三维旋转矩阵T= 10000cosαsinα00sinαcosα00001

绕Y轴旋转

{ x ′ = x cos ⁡ β + z sin ⁡ β y ′ = y z ′ = − x sin ⁡ β + z cos ⁡ β 三维旋转矩阵 T = ( cos ⁡ β 0 sin ⁡ β 0 0 1 0 0 − sin ⁡ β 0 cos ⁡ β 0 0 0 0 1 ) \begin{cases} x^{\prime}=x\cos\beta+z\sin\beta\\ y^{\prime}=y\\ z^{\prime}=-x\sin\beta+z\cos\beta \end{cases}\\三维旋转矩阵T=\begin{pmatrix} \cos\beta&0&\sin\beta&0\\ 0&1&0&0\\ -\sin\beta&0&\cos\beta&0\\ 0&0&0&1 \end{pmatrix} x=xcosβ+zsinβy=yz=xsinβ+zcosβ三维旋转矩阵T= cosβ0sinβ00100sinβ0cosβ00001

绕Z轴旋转

{ x ′ = x cos ⁡ γ − y sin ⁡ γ y ′ = y sin ⁡ γ + z cos ⁡ γ z ′ = z 三维旋转矩阵 T = ( cos ⁡ γ − sin ⁡ γ 0 0 sin ⁡ γ cos ⁡ γ 0 0 0 0 0 0 0 0 0 1 ) \begin{cases} x^{\prime}=x\cos\gamma-y\sin\gamma\\ y^{\prime}=y\sin\gamma+z\cos\gamma\\ z^{\prime}=z \end{cases}\\三维旋转矩阵T=\begin{pmatrix} \cos\gamma&-\sin\gamma&0&0\\ \sin\gamma&\cos\gamma&0&0\\ 0&0&0&0\\ 0&0&0&1 \end{pmatrix} x=xcosγysinγy=ysinγ+zcosγz=z三维旋转矩阵T= cosγsinγ00sinγcosγ0000000001

对称变换

  • 关于x轴对称
    三维变换矩阵T
    T = ( 1 0 0 0 0 − 1 0 0 0 0 − 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&0&0&0\\ 0&-1&0&0\\ 0&0&-1&0\\ 0&0&0&1 \end{pmatrix} T= 1000010000100001
  • 关于y轴对称,三维变换矩阵T
    T = ( − 1 0 0 0 0 1 0 0 0 0 − 1 0 0 0 0 1 ) T=\begin{pmatrix} -1&0&0&0\\ 0&1&0&0\\ 0&0&-1&0\\ 0&0&0&1 \end{pmatrix} T= 1000010000100001
  • 关于z轴对称,三维变换矩阵T
    T = ( − 1 0 0 0 0 − 1 0 0 0 0 1 0 0 0 0 1 ) T=\begin{pmatrix} -1&0&0&0\\ 0&-1&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{pmatrix} T= 1000010000100001
  • 关于xOy面对称
    三维变换矩阵T
    T = ( 1 0 0 0 0 1 0 0 0 0 − 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&0&0&0\\ 0&1&0&0\\ 0&0&-1&0\\ 0&0&0&1 \end{pmatrix} T= 1000010000100001
  • 关于yOz面对称
    三维变换矩阵T
    T = ( − 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 ) T=\begin{pmatrix} -1&0&0&0\\ 0&1&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{pmatrix} T= 1000010000100001
  • 关于zOx面对称
    三维变换矩阵T
    T = ( 1 0 0 0 0 − 1 0 0 0 0 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&0&0&0\\ 0&-1&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{pmatrix} T= 1000010000100001

错切变换

沿xy平面错切(z不变)
{ x ′ = x + λ x z y ′ = λ y z + y \begin{cases} x^{\prime}=x+\lambda _x z\\y^{\prime}=\lambda _yz+y \end{cases} {x=x+λxzy=λyz+y
三维变换矩阵T为 T = ( 1 0 λ x 0 0 1 λ y 0 0 0 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&0&\lambda _x&0\\ 0&1&\lambda _y&0\\ 0&0&1&0\\ 0&0&0&1 \end{pmatrix} T= 10000100λxλy100001
沿xz平面错切(y不变)
{ x ′ = x + λ x y z ′ = λ y y + z \begin{cases} x^{\prime}=x+\lambda _x y\\ z^{\prime}=\lambda _yy+z \end{cases} {x=x+λxyz=λyy+z
三维变换矩阵T为 T = ( 1 λ x 0 0 0 1 0 0 0 λ z 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&\lambda _x&0&0\\ 0&1&0&0\\ 0&\lambda _z&1&0\\ 0&0&0&1 \end{pmatrix} T= 1000λx1λz000100001
沿yz平面错切(x不变)
{ y ′ = y + λ x x z ′ = λ y x + z \begin{cases} y^{\prime}=y+\lambda _x x\\ z^{\prime}=\lambda _yx+z \end{cases} {y=y+λxxz=λyx+z
三维变换矩阵T为 T = ( 1 0 0 0 λ y 1 0 0 λ z 0 1 0 0 0 0 1 ) T=\begin{pmatrix} 1&0&0&0\\ \lambda _y&1&0&0\\ \lambda _z&0&1&0\\ 0&0&0&1 \end{pmatrix} T= 1λyλz0010000100001

代码实现

class CTransform3
{
public:
	CTransform3();
	virtual ~CTransform3();
	void Identity();//单位矩阵初始化
	void SetMatrix(CPoint3* P, int ptNumber);//三维顶点数组初始化
	void Translate(double tx, double ty, double tz);//平移变换
	void Scale(double sx, double sy, double sz);//比例变换
	void Scale(double sx, double sy, double sz, CPoint3 p);//相对于任意点的比例变换
	void RotateX(double alpha);//绕X轴旋转变换
	void RotateY(double beta);//绕Y轴旋转变换
	void RotateZ(double gamma);//绕Z轴旋转变换	
	void RotateX(double alpha, CPoint3 p);//相对于任意点的绕X轴旋转变换
	void RotateY(double beta, CPoint3 p);//相对于任意点的绕Y轴旋转变换
	void RotateZ(double gamma, CPoint3 p);//相对于任意点的绕Z轴旋转变换
	void ReflectX();//关于X轴反射变换
	void ReflectY();//关于Y轴反射变换
	void ReflectZ();//关于Z轴反射变换
	void ReflectXOY();//关于XOY面反射变换
	void ReflectYOZ();//关于YOZ面反射变换
	void ReflectZOX();//关于ZOX面反射变换
	void ShearXY(double a, double b);//沿XY平面错切变换
	void ShearYZ(double a, double b);//沿YZ平面错切变换
	void ShearXZ(double a, double b);//沿XZ平面错切变换
	void MultiplyMatrix();//矩阵相乘
private:
	double	m_matrix[4][4];//三维变换矩阵	
	CPoint3* m_p;//三维顶点数组名
	int	m_pNum;//三维顶点个数
};
#define PI 3.1415926//圆周率

CTransform3::CTransform3(void)
{

}

CTransform3::~CTransform3(void)
{

}

void CTransform3::Identity(void)//单位矩阵初始化
{
	m_matrix[0][0] = 1.0; m_matrix[0][1] = 0.0; m_matrix[0][2] = 0.0; m_matrix[0][3] = 0.0;
	m_matrix[1][0] = 0.0; m_matrix[1][1] = 1.0; m_matrix[1][2] = 0.0; m_matrix[1][3] = 0.0;
	m_matrix[2][0] = 0.0; m_matrix[2][1] = 0.0; m_matrix[2][2] = 1.0; m_matrix[2][3] = 0.0;
	m_matrix[3][0] = 0.0; m_matrix[3][1] = 0.0; m_matrix[3][2] = 0.0; m_matrix[3][3] = 1.0;
}

void CTransform3::SetMatrix(CPoint3* P, int ptNumber)//顶点数组初始化
{
	this->m_p = P;
	this->m_pNum = ptNumber;
}

void CTransform3::Translate(double tx, double ty, double tz)//平移变换
{
	Identity();
	m_matrix[0][3] = tx;
	m_matrix[1][3] = ty;
	m_matrix[2][3] = tz;
	MultiplyMatrix();
}

void CTransform3::Scale(double sx, double sy, double sz)//比例变换
{
	Identity();
	m_matrix[0][0] = sx;
	m_matrix[1][1] = sy;
	m_matrix[2][2] = sz;
	MultiplyMatrix();
}

void CTransform3::Scale(double sx, double sy, double sz, CPoint3 p)//相对于任意点的比例变换
{
	Translate(-p.m_x, -p.m_y, -p.m_z);
	Scale(sx, sy, sz);
	Translate(p.m_x, p.m_y, p.m_z);
}
void CTransform3::RotateX(double beta)//绕X轴旋转变换
{
	Identity();
	double rad = beta * PI / 180;
	m_matrix[1][1] = cos(rad); m_matrix[1][2] = -sin(rad);
	m_matrix[2][1] = sin(rad); m_matrix[2][2] = cos(rad);
	MultiplyMatrix();
}

void CTransform3::RotateY(double beta)//绕Y轴旋转变换
{
	Identity();
	double rad = beta * PI / 180;
	m_matrix[0][0] = cos(rad); m_matrix[0][2] = sin(rad);
	m_matrix[2][0] = -sin(rad); m_matrix[2][2] = cos(rad);
	MultiplyMatrix();
}

void CTransform3::RotateZ(double beta)//绕Z轴旋转变换
{
	Identity();
	double rad = beta * PI / 180;
	m_matrix[0][0] = cos(rad); m_matrix[0][1] = -sin(rad);
	m_matrix[1][0] = sin(rad); m_matrix[1][1] = cos(rad);
	MultiplyMatrix();
}

void CTransform3::RotateX(double beta, CPoint3 p)//相对于任意点的X轴旋转变换
{
	Translate(-p.m_x, -p.m_y, -p.m_z);
	RotateX(beta);
	Translate(p.m_x, p.m_y, p.m_z);
}

void CTransform3::RotateY(double beta, CPoint3 p)//相对于任意点的Y轴旋转变换
{
	Translate(-p.m_x, -p.m_y, -p.m_z);
	RotateY(beta);
	Translate(p.m_x, p.m_y, p.m_z);
}

void CTransform3::RotateZ(double beta, CPoint3 p)//相对于任意点的Z轴旋转变换
{
	Translate(-p.m_x, -p.m_y, -p.m_z);
	RotateZ(beta);
	Translate(p.m_x, p.m_y, p.m_z);
}

void CTransform3::ReflectX(void)//X轴反射变换
{
	Identity();
	m_matrix[1][1] = -1;
	m_matrix[2][2] = -1;
	MultiplyMatrix();
}

void CTransform3::ReflectY(void)//Y轴反射变换
{
	Identity();
	m_matrix[0][0] = -1;
	m_matrix[2][2] = -1;
	MultiplyMatrix();
}

void CTransform3::ReflectZ(void)//Z轴反射变换
{
	Identity();
	m_matrix[0][0] = -1;
	m_matrix[1][1] = -1;
	MultiplyMatrix();
}

void CTransform3::ReflectXOY(void)//XOY面反射变换
{
	Identity();
	m_matrix[2][2] = -1;
	MultiplyMatrix();
}

void CTransform3::ReflectYOZ(void)//YOZ面反射变换
{
	Identity();
	m_matrix[0][0] = -1;
	MultiplyMatrix();
}

void CTransform3::ReflectZOX(void)//XOZ面反射变换
{
	Identity();
	m_matrix[1][1] = -1;
	MultiplyMatrix();
}

void CTransform3::ShearXY(double a, double b)
{
	Identity();
	m_matrix[0][2] = a;
	m_matrix[0][2] = b;
	MultiplyMatrix();
}

void CTransform3::ShearYZ(double a, double b)
{
	Identity();
	m_matrix[0][1] = a;
	m_matrix[2][1] = b;
	MultiplyMatrix();
}

void CTransform3::ShearXZ(double a, double b)
{
	Identity();
	m_matrix[1][0] = a;
	m_matrix[2][0] = b;
	MultiplyMatrix();
}



void CTransform3::MultiplyMatrix(void)//矩阵相乘
{
	CPoint3* PTemp = new CPoint3[m_pNum];
	for (int i = 0; i < m_pNum; i++)
		PTemp[i] = m_p[i];
	for (int i = 0; i < m_pNum; i++)
	{
		m_p[i].m_x = m_matrix[0][0] * PTemp[i].m_x + m_matrix[0][1] * PTemp[i].m_y + m_matrix[0][2] * PTemp[i].m_z + m_matrix[0][3] * PTemp[i].m_w;
		m_p[i].m_y = m_matrix[1][0] * PTemp[i].m_x + m_matrix[1][1] * PTemp[i].m_y + m_matrix[1][2] * PTemp[i].m_z + m_matrix[1][3] * PTemp[i].m_w;
		m_p[i].m_z = m_matrix[2][0] * PTemp[i].m_x + m_matrix[2][1] * PTemp[i].m_y + m_matrix[2][2] * PTemp[i].m_z + m_matrix[2][3] * PTemp[i].m_w;
		m_p[i].m_w = m_matrix[3][0] * PTemp[i].m_x + m_matrix[3][1] * PTemp[i].m_y + m_matrix[3][2] * PTemp[i].m_z + m_matrix[3][3] * PTemp[i].m_w;
	}
	delete[]PTemp;
}
  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值