具有最短路径的四元数 slerp 不起作用
Quaternion slerp with shortest path not working
我的 slerp 例程如下。从我读过的内容来看,针对 > 0 的检查应该处理它,所以它总是采用最短路径。但它从来没有。在我穿过 "pole" 的情况下,四元数翻转并生成具有 NAN 值的角度。
quat quat::slerp(quat dest, float t)
{
const quat &from = *this;
static const double epsilon = 0.0001;
double theta, cosTheta, sinTheta;
double p, q;
cosTheta = from.x*dest.x + from.y*dest.y + from.z*dest.z + from.w*dest.w;
if(cosTheta < 0.0)
{
dest = { -from.x, -from.y, -from.z, -from.w };
cosTheta = -cosTheta;
}
if((1.0-fabs(cosTheta)) > epsilon)
{
theta = acos(cosTheta);
sinTheta = sin(theta);
q = sin((1-t) * theta) / sinTheta;
p = sin(t*theta) / sinTheta;
}
else
{
q = 1-t;
p = t;
}
quat qo;
qo.w = (float)((q * from.w) + (p * dest.w));
qo.x = (float)((q * from.x) + (p * dest.x));
qo.y = (float)((q * from.y) + (p * dest.y));
qo.z = (float)((q * from.z) + (p * dest.z));
return qo;
}
也许还有其他错误,但这行肯定有一个:
dest = { -from.x, -from.y, -from.z, -from.w };
它用 -from
覆盖了 dest
,这是不正确的。应该是:
dest = { -dest.x, -dest.y, -dest.z, -dest.w };
我的 slerp 例程如下。从我读过的内容来看,针对 > 0 的检查应该处理它,所以它总是采用最短路径。但它从来没有。在我穿过 "pole" 的情况下,四元数翻转并生成具有 NAN 值的角度。
quat quat::slerp(quat dest, float t)
{
const quat &from = *this;
static const double epsilon = 0.0001;
double theta, cosTheta, sinTheta;
double p, q;
cosTheta = from.x*dest.x + from.y*dest.y + from.z*dest.z + from.w*dest.w;
if(cosTheta < 0.0)
{
dest = { -from.x, -from.y, -from.z, -from.w };
cosTheta = -cosTheta;
}
if((1.0-fabs(cosTheta)) > epsilon)
{
theta = acos(cosTheta);
sinTheta = sin(theta);
q = sin((1-t) * theta) / sinTheta;
p = sin(t*theta) / sinTheta;
}
else
{
q = 1-t;
p = t;
}
quat qo;
qo.w = (float)((q * from.w) + (p * dest.w));
qo.x = (float)((q * from.x) + (p * dest.x));
qo.y = (float)((q * from.y) + (p * dest.y));
qo.z = (float)((q * from.z) + (p * dest.z));
return qo;
}
也许还有其他错误,但这行肯定有一个:
dest = { -from.x, -from.y, -from.z, -from.w };
它用 -from
覆盖了 dest
,这是不正确的。应该是:
dest = { -dest.x, -dest.y, -dest.z, -dest.w };