四元数分量插值

时间:2012-11-15 08:49:28

标签: math quaternions

我试图通过使用轨道(曲线)而不是关键帧来优化我的骨架动画系统。然后每条曲线处理一个特定的组件(现在)我对这些值进行线性插值。对我的骨骼位置工作正常,但我很难摆脱四元数组件插值的“jagyness”...

基本上每个骨骼四元数的每个分量(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

Frame1中: quat.x = -0.952190

式2: quat.x = 0.953192

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

如何正确修复曲线?

2 个答案:

答案 0 :(得分: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];这样可以确保您不会尝试在圆周内插入很长的路径。但这确实意味着您必须将四元数作为一个整体处理,而不是部分处理。完全丢弃一个组件特别成问题,因为你需要它的符号来保持四元数不模糊。

答案 1 :(得分:0)

天真的考虑因素

线性插值适用于操作性较强的事物,即每次执行相应操作时都会向其他事物添加内容。然而,Queternions是乘法的:你将它们相乘以链接它们。

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

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

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

正确插值

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

修复数据

关于您更新的问题

  

如何正确修复曲线?

在保持正确数据的同时修复错误需要了解发生了哪些类型的错误。因此,我首先尝试找到该错误的来源,如果可能的话。如果可以修复以生成正确的数据,那么很好。如果没有,它仍然可以让你更好地了解期望什么,什么时候。