我正在通过SLERP进行Quaternion混音,但我的实现做了一些非常错误的事情。您可以在此视频中看到它:video
以下是代码:
cosTheta = quatDot(a, b);
if (cosTheta > 0.9){
var quat = new Vec4(
a.x + (b.x - a.x)*t,
a.y + (b.y - a.y)*t,
a.z + (b.z - a.z)*t,
a.w + (b.w - a.w)*t
);
normalizeQuat(quat);
return quat;
}
cosTheta = Math.min(Math.max(cosTheta, -1), 1); //clamp
var theta = Math.acos(cosTheta) * t;
var v2 = quatMinus(b, quatExtend(a, cosTheta));
normalizeQuat(v2);
return quatSum(quatExtend(a, cosTheta), quatExtend(v2, Math.sin(theta)));
我有自己的帮助功能:
function quatDot(a,b){
return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
}
function quatMultiply(q,p){
return new Vec4(
q.w * p.x + q.x * p.w + q.y * p.z - q.z * p.y,
q.w * p.y + q.y * p.w + q.z * p.x - q.x * p.z,
q.w * p.z + q.z * p.w + q.x * p.y - q.y * p.x,
q.w * p.w - q.x * p.x - q.y * p.y - q.z * p.z);
}
function quatExtend(q, t){
return new Vec4(
q.x * t, q.y * t, q.z * t, q.w * t);
}
function quatMinus(q, p){
return new Vec4(
q.x - p.x,
q.y - p.y,
q.z - p.z,
q.w - p.w
);
}
function quatSum(q, p){
return new Vec4(
q.x + p.x,
q.y + p.y,
q.z + p.z,
q.w + p.w
);
}
我尝试过很多来自网站的实现,但总是有错误的移动。当我尝试简单的线性插值时,动画是平滑的,但奇怪的是加速。
答案 0 :(得分:0)
这是一个简单的错误:if cosTheta
< 0.9和t
= 0,然后theta
= 0,这意味着Math.sin(theta)
= 0,这意味着quatExtend(v2, Math.sin(theta))
是零四元数,你最终返回{{1} },这不是一个单位四元数。
我希望正确的实现能够将其中一个四元数的逆(或共轭)至少一次,并且永远不要调用normalizeQuat。但那只是直觉。为了超越直觉,尝试编写单元测试!
顺便说一下,如果我们正在进行代码审核,那么quatExtend(a, cosTheta)
不是cosTheta
的余弦会让人感到困惑。此外,theta
块闻起来像过早优化;你可以摆脱它。 :)