在世界坐标系中一个目标的变换有很多种,基础的变换有三种:平移旋转和缩放。这三种变换顺序不一样,结果不一样。一般的顺序为:平移T,渲染R,缩放S.
M
=
T
∗
R
∗
S
M = T*R*S
M=T∗R∗S 如果一个顶点的局部坐标为
v
(
x
,
y
,
z
,
1
)
v(x,y,z,1)
v(x,y,z,1),乘以M就变为世界坐标。这些知识点都较为简单,下面要说的是鼠标拖动一个目标移动时,我们如何对目标进行旋转平移和缩放。
假设 鼠标在窗口中移动前后的坐标为
p
1
(
x
,
y
)
p
2
(
x
,
y
)
p_1(x,y) p_2(x,y)
p1(x,y)p2(x,y),目标的长宽分别为
w
,
h
w,h
w,h。目标在世界坐标系中的位置为
c
(
x
,
y
,
z
)
c(x,y,z)
c(x,y,z)
平移
第一步 将窗口坐标转为视口坐标(窗口视口大小相同时)
p
v
(
x
,
y
)
=
(
x
,
h
−
y
)
p_v(x,y) = (x,h-y)
pv(x,y)=(x,h−y)
其中h为视口的高度,xy为窗口坐标。
第二步 将视口坐标转为世界坐标
p
w
(
x
,
y
,
z
)
=
F
−
1
∗
V
−
1
∗
P
−
1
∗
p
v
p_w(x,y,z) = F^{-1}*V^{-1}*P^{-1}*p_v
pw(x,y,z)=F−1∗V−1∗P−1∗pv
第三步 计算在世界坐标系中鼠标移动的偏移量
o
f
f
s
e
t
w
=
p
w
2
−
p
w
1
offset_w = p_{w2}-p_{w1}
offsetw=pw2−pw1
第四步 平移
c
n
e
w
=
c
+
o
f
f
s
e
t
w
c_{new} = c + offset_w
cnew=c+offsetw
最后平移一般情况下根据平移量更新平移矩阵,
T
−
>
T
n
e
w
T->T_{new}
T−>Tnew
c
n
e
w
=
T
n
e
w
∗
R
∗
S
c_{new} = T_{new} * R * S
cnew=Tnew∗R∗S
缩放
缩放比较麻烦,首先计算缩放比例,然后还需区分,绕顶点缩放还是绕中心点缩放。
第一步计算缩放比
直接指定,简单不赘述。这里主要描述下鼠标拖动某个锚点进行缩放。
做法如下:
比如拖动锚点
A
A
A,此时需要找到他对面的点
A
′
A^{'}
A′,左下角的对面的点就是右上角,左边中间的点就是右边中间的点。
假设
A
A
A移动后的坐标为
p
a
p_{a}
pa,
A
′
A^{'}
A′移动后的坐标为
p
a
′
p_{a^{'}}
pa′
重点来了,将他们转为局部坐标系,转为局部坐标系不是简单的乘以世界变换矩阵的逆,而是要去除缩放矩阵。
p
a
L
=
R
−
1
∗
T
−
1
∗
p
a
p
a
′
L
=
R
−
1
∗
T
−
1
∗
p
a
′
p_{a}^{L} = R^{-1} * T^{-1} * p_{a}\\p_{a^{'}}^{L} = R^{-1} * T^{-1} * p_{a^{'}}
paL=R−1∗T−1∗papa′L=R−1∗T−1∗pa′
此时计算缩放比
s
c
a
l
e
x
=
a
b
s
(
p
a
L
.
x
−
p
a
′
L
.
x
)
/
w
s
c
a
l
e
y
=
a
b
s
(
p
a
L
.
y
−
p
a
′
L
.
y
)
/
h
scale_x = abs(p_{a}^{L}.x - p_{a^{'}}^{L}.x)/w\\scale_y = abs(p_{a}^{L}.y - p_{a^{'}}^{L}.y)/h
scalex=abs(paL.x−pa′L.x)/wscaley=abs(paL.y−pa′L.y)/h
第二步 如果是指定点,还需要进行平移缩放平移的操作。
如果指定点是
t
a
c
k
w
(
x
,
y
,
z
)
tack_w(x,y,z)
tackw(x,y,z) 此时需要将他转为局部坐标。
t
a
c
k
l
(
x
,
y
,
z
)
=
S
−
1
∗
R
−
1
∗
T
−
1
∗
t
a
c
k
w
(
x
,
y
,
z
)
tack_l(x,y,z) = S^{-1} * R^{-1} * T^{-1} * tack_w(x,y,z)
tackl(x,y,z)=S−1∗R−1∗T−1∗tackw(x,y,z)
注意:此时计算局部坐标时,计算了缩放矩阵的逆。
缩放矩阵计算如下:
S
=
T
1
∗
S
n
∗
T
2
S = T_1*S_n*T_2
S=T1∗Sn∗T2
其中
T
1
为
−
t
a
c
k
l
(
x
,
y
,
z
)
平移矩阵,
T
2
为
t
a
c
k
l
(
x
,
y
,
z
)
平移矩阵
S
n
为单位矩阵进行了
(
s
c
a
l
e
x
,
s
c
a
l
e
y
,
1.0
)
的缩放
T_1为-tack_l(x,y,z)平移矩阵,T_2为tack_l(x,y,z)平移矩阵S_n为单位矩阵进行了(scale_x,scale_y,1.0)的缩放
T1为−tackl(x,y,z)平移矩阵,T2为tackl(x,y,z)平移矩阵Sn为单位矩阵进行了(scalex,scaley,1.0)的缩放
如果在子空间中进行变换,平移时还需要考虑除以父空间的缩放比。
旋转
旋转相对简单,一般目标的旋转都绕中心点旋转,如果绕固定点旋转,和缩放一样,先平移,再旋转,后平移