在使用cocos3d的四元素旋转过程中,节点会莫名其妙的变形,使用下面代码代替原来的lerp就能解决
function Quat_lerp(a: Quat, b: Quat, t: number, out: Quat = a) {
Quat.lerp(out, a, b, clamp01(t));
Quat.normalize(out, out);
return out;
}
下面解释原因:
cocos3d处于性能的考虑,使用了模型矩阵乘以反向旋转矩阵的方式得到模型比例,而旋转矩阵是基于四元素的逆计算得到的,而对于四元素逆的计算,cocos为了性能直接使用了四元素的共轭,共轭和逆相等的前提是四元素是标准化的,问题就出在四元素线行插值过程中,四元素可能是非标准化的,但这里cocos没有做,cocos没做的原因也很简单,因为他数学部分直接拿了gl-matrix的,gl-matrix没做处理,所以cocos也没做处理。
所以上面这段函数我对插值结果做了标准化处理之后,变形问题就消失了,并且对t做了[0,1]范围的限制。另外值得一提的是四元素使用slerp即球面插值也能解决这问题,因为它计算得到的就是标准化的四元素。
补充
之前解决了cocos旋转会影响缩放的问题,但是四元素简单的线行插值还会有另外一个问题,就是反向旋转,本来我只需旋转30度,插值结果却是旋转了360-30=330度。下面是解决方案
let q_1 = new Quat();
function Quat_lerp(a: Quat, b: Quat, t: number, out: Quat = a) {
if (Quat.dot(a, b) < 0.0) {
q_1.set(-b.x, -b.y, -b.z, -b.w);
}
else {
q_1.set(b);
}
Quat.lerp(out, a, q_1, clamp01(t));
Quat.normalize(out, out);
return out;
}
我建了一个3D交流群475557897,专门来解决cocos的这些奇葩问题,欢迎志同道合的小伙伴加入