四元数常见的插值方法有线性插值(Lerp)和球面线性插值(Slerp)
首先,线性插值方法:
q
t
=
L
e
r
p
(
q
0
,
q
1
,
t
)
=
(
1
−
t
)
q
0
+
t
q
1
q_t = Lerp(q_0,q_1,t) = (1-t)q_0+tq_1
qt=Lerp(q0,q1,t)=(1−t)q0+tq1
由于这样算出的
q
t
q_t
qt并不是单位四元数,所以需要对其进行归一化处理,也就是使用了归一化线性插值(Nlerp)方法:
q
t
=
N
l
e
r
p
(
q
0
,
q
1
,
t
)
=
(
1
−
t
)
q
0
+
t
q
1
∣
∣
(
1
−
t
)
q
0
+
t
q
1
∣
∣
q_t = Nlerp(q_0,q_1,t) = \frac{(1-t)q_0+tq_1}{||(1-t)q_0+tq_1||}
qt=Nlerp(q0,q1,t)=∣∣(1−t)q0+tq1∣∣(1−t)q0+tq1
这样虽然能保证是单位四元数了,但是有个问题就是这样计算并不能保证均匀的角速度,于是就有了球面线性插值(Spherical Linear Interpolation)方法,
简称Slerp。能够保证每个四元数之间的角速度是固定的。这种方法不对四元数q直接插值,而是对角度
q
1
q_1
q1和
q
2
q_2
q2之间的夹角
θ
\theta
θ插值,这从原理上保证了插值的效果。
计算公式:
q
t
=
S
l
e
r
p
(
q
0
,
q
1
,
t
)
=
s
i
n
(
(
1
−
t
)
θ
)
s
i
n
(
θ
)
q
0
+
s
i
n
(
t
θ
)
s
i
n
(
θ
)
q
1
θ
=
a
c
o
s
(
q
0
⋅
q
1
)
q_t = Slerp(q_0,q_1,t) = \frac{sin((1-t)\theta)}{sin(\theta)}q_0 +\frac{sin(t\theta)}{sin(\theta)}q_1 \\ \theta = acos(q_0 \cdot q_1)
qt=Slerp(q0,q1,t)=sin(θ)sin((1−t)θ)q0+sin(θ)sin(tθ)q1θ=acos(q0⋅q1)
编程时需要注意的问题:
1.若θ非常小,那么sin(θ)可能会由于浮点数的误差被近似为0.0,从而导致除以0的错误.所以,我们在实施 Slerp
之前,需要检查两个四元数的夹角是否过小(或者完全相同)。一旦发现这种问题,我们就必须改用 Nlerp 对两个四元数进行插值,这时候 Nlerp 的误差非常小,所以基本不会与真正的 Slerp 有什么区别。
2.在对两个单位四元数进行插值之前,我们需要先检测q0与q1之间是否是钝角,即检测它们点积的结果q0⋅q1 是否为负数。如果 q0⋅q1<0,那么我们就反转其中的一个四元数,比如说将q1改为−q1 ,并使用q0与−q1之间新的夹角来进行插值,这样才能保证插值的路径是最短的.
本文参考:https://zhuanlan.zhihu.com/p/47396001
四元数的插值方法
最新推荐文章于 2023-03-22 14:20:20 发布