四元数的插值方法

四元数常见的插值方法有线性插值(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)=(1t)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)=(1t)q0+tq1(1t)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((1t)θ)q0+sin(θ)sin(tθ)q1θ=acos(q0q1)
编程时需要注意的问题:
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

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值