虽然用于在 3D 方向之间进行插值的流行 slerp
公式非常酷且有用,但我突然想到这是一个线性动画。
不太复杂的动画,例如 float 之间的简单补间,可以轻松更改为二次缓入和缓出,但 slerp
公式并不那么简单(其发明者 Shoemake 甚至没有在他最初发现后公布该公式的推导)。
所以我正在使用这个:
template <typename T>
inline QuaternionT<T> QuaternionT<T>::Slerp(T t, const QuaternionT<T>& v1) const
{
const T epsilon = 0.0005f;
T dot = Dot(v1);
if (dot > 1 - epsilon) {
QuaternionT<T> result = v1 + (*this - v1).Scaled(t);
result.Normalize();
return result;
}
if (dot < 0)
dot = 0;
if (dot > 1)
dot = 1;
T theta0 = std::acos(dot);
T theta = theta0 * t;
QuaternionT<T> v2 = (v1 - Scaled(dot));
v2.Normalize();
QuaternionT<T> q = Scaled(std::cos(theta)) + v2.Scaled(std::sin(theta));
q.Normalize();
return q;
}
有谁知道如何根据t
(即经过/持续时间)进行缓动插值?
最佳答案
控制 lerping 的“轻松程度”的是 t
的变化率,而不是 lerping 本身。我假设 T
是一个标量(如 float/double)。
AFAICT,您正在尝试获得缓入效果,但路径本身是起始四元数和结束四元数之间的“直线”旋转。因此,只要t
从0到1变化,您所要做的就是改变t的变化率以获得“缓动插值”。
我通常使用 3*t^2-2*t^3
公式来缓入/缓出。我会留下Wikipedia link在这里,以防万一。
(我觉得我在这里遗漏了一些东西。如果这回答了您的问题,请告诉我)。
关于math - 带四元数的非线性 slerp 动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16205821/