1

我试图通过使用轨迹(曲线)而不是关键帧来优化我的骨骼动画系统。每条曲线都处理一个特定的组件,然后(现在)我线性插值这些值。适合我的骨骼位置,但是我很难摆脱四元数分量插值的“锯齿状”......

基本上,每个骨骼四元数的每个分量(XY 和 Z)都有 1 条曲线,我使用以下代码独立插入 XY 和 Z 曲线:

// Simple lerp... (f is always a value between 0.0f and 1.0f)
return ( curve->data_array[ currentframe ].value * ( 1.0f - f ) ) +
       ( curve->data_array[ nextframe ].value * f );

当我对四元数 XYZ 进行插值时,我使用以下代码在对其进行归一化之前重建四元数的 W 分量,并在绘制之前将其影响到我的骨骼:

Quaternion QuaternionW( const Quaternion q )
{
    Quaternion t = { q.x, q.y, q.z };

    float l = 1.0f - ( q.x * q.x ) - ( q.y * q.y ) - ( q.z * q.z );

    t.w = ( l < 0.0f ) ? 0.0f : -sqrtf( l );

    return t;
}

绘图看起来很好,只是骨头有时会变得很生涩,是不是因为浮点精度?还是重新计算 W 分量?或者我绝对没有办法以这种方式线性插值四元数的每个分量?

ps:附带说明一下,如果我将上面的代码替换为以下代码,则在我的曲线插值函数中:

return curve->data_array[ currentframe ].value;

相反或线性插值,一切都很好......所以数据显然是正确的......我很困惑......

[ 编辑 ]

经过更多研究,我发现问题来自帧数据......我得到了以下内容:

帧 0:quat.x = 0.950497

帧 1:quat.x = -0.952190

帧 2:quat.x = 0.953192

这就是导致反转和锯齿状的原因......我试图检测这种情况并反转数据的符号,但它仍然不能完全解决问题,因为某些帧现在看起来很奇怪(在绘图时视觉上)。

任何想法如何正确修复曲线?

4

2 回答 2

2

你的数据可能没有错。方向的四元数表示具有 2 倍冗余的有趣特性。如果你否定一个四元数的所有四个元素,你就会留下相同的方向。如果您将四元数视为轴/角度表示,则很容易看出这一点:围绕轴a旋转Θ与围绕轴-a旋转相同。

那么你应该怎么呢?如前所述,slerp是正确的做法。四元数方向存在于单位超球面上。如果在球体上的点之间进行线性插值,则会离开球体。但是,如果这些点彼此靠近,则通常没什么大不了的(尽管之后您仍应重新归一化)。你绝对需要确保你做的是在插值之前检查你的两个四元数的内积:例如

k=q0[0]*q1[0] + q0[1]*q1[1] + q0[2]*q1[2] + q0[3]*q1[3];

如果k<0,则否定其中一个四元数:for (ii=0;ii<4;++ii) q1[ii]=-q1[ii]; 这可确保您不会尝试在圆周围进行很长的插值。然而,这确实意味着您必须将四元数视为一个整体,而不是部分。完全丢弃一个组件尤其成问题,因为您需要它的符号来防止四元数模棱两可。

于 2012-11-20T17:38:11.393 回答
0

幼稚的考虑

线性插值适用于加法运算的事物,即每次执行相应操作时都会将某些事物添加到其他事物中。然而,Queternions 是乘法的:你将它们相乘以链接它们。

出于这个原因,我最初建议计算以下内容:

pow(secondQuaternion, f)*pow(firstQuaternion, 1. - f)

维基百科有一关于四元数的计算能力等。正如您在下面的评论指出这不起作用,以上仅供参考。

适当的插值

自从写这篇文章以来,我阅读了更多关于 slerp (球面线性插值)的内容,并发现维基百科有一个关于四元数 slerp 的部分。您上面的评论表明您已经熟悉该术语。这个公式比我上面写的要复杂一些,但由于它使用权力的方式,它仍然相当相关。我想你最好通过调整或移植该公式的可用实现来做到最好。例如,此页面带有一些代码。

修复数据

至于你更新的问题

任何想法如何正确修复曲线?

在维护正确数据的同时修复错误需要了解确实发生了哪些类型的错误。因此,如果可能的话,我会首先尝试找到该错误的根源。如果可以修复它以生成正确的数据,那么很好。如果没有,它仍然应该让您更好地了解预期的内容和时间。

于 2012-11-15T18:26:35.700 回答