和二维几何变换一样,三维几何变换也要引入齐次坐标。点(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=
?adgp?behq?cfir?lmns?
?
这个矩阵可以分为如下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?=
?adg?beh?cfi?
?T1?=
?lmn?
?T2?=(p?q?r?)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+Tx?y′=y+Ty?z′=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}
?x′y′z′1?
?=
?x+Tx?y+Ty?z+?Tz?1?
?=T
?xyz1?
?得到T=
?1000?0100?0000?Tx?Ty?Tz?1?
?
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}
?x′y′z′1?
?=
?xTx?yTy?zTz?1?
?=T
?xyz1?
?得到T=
?Tx?000?0Ty?00?00Tz?0?0001?
?
更一般的情况,
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?(x?px?)+px?y′=Sy?(y?py?)+py?z′=Sz?(z?pz?)+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=
?Sx?000?0Sy?00?00Sz?0?px?(1?Sx?)py?(1?Sy?)pz?(1?Sz?)1?
?
对点(x,y,z)相对于原点(0,0,0)进行旋转操作,采用右手坐标系,即大拇指指向旋转轴的正方向,四指的转向为转角的正方向。旋转我们可分为绕x轴、y轴、z轴旋转。假设绕x轴旋转角度为 α \alpha α,绕y轴旋转角度为 β \beta β,绕z轴旋转的角度为 γ \gamma γ。则相应的变换如下:
{ 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= ?1000?0cosαsinα0?0?sinαcosα0?0001? ?
{ 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β0?sinβ0?0100?sinβ0cosβ0?0001? ?
{ 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γ00??sinγcosγ00?0000?0001? ?
沿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+λx?zy′=λy?z+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=
?1000?0100?λx?λy?10?0001?
?
沿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+λx?yz′=λy?y+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?λx?1λz?0?0010?0001?
?
沿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+λx?xz′=λy?x+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?λz?0?0100?0010?0001?
?
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;
}