gpt4 book ai didi

c++ - glm::mix 返回无效的四元数

转载 作者:行者123 更新时间:2023-11-30 04:26:29 24 4
gpt4 key购买 nike

我正在尝试在我的游戏引擎中实现骨骼动画,但我遇到了插值问题。

每一帧,我想在帧之间进行插值,因此我有类似于这样的代码:

// This is the soon-to-be-interpolated joint
Joint &finalJoint = finalSkeleton.joints[i];

// These are our existing joints
const Joint &joint0 = skeleton0.joints[i];
const Joint &joint1 = skeleton1.joints[i];

// Interpolate
finalJoint.position = glm::lerp(joint0.position, joint1.position, interpolate);
finalJoint.orientation = glm::mix(joint0.orientation, joint1.orientation, interpolate);

最后一行是问题所在。 finalJoint 的方向有时会是 (-1.#IND, -1.#IND, -1.#IND, -1.#IND)

这些是一些示例值及其结果(请注意,interpolation 在所有三种情况下都是 0.4):

  • joint0.orientation = (0.707107, 0.000242, 0.707107, 0.0)
    joint1.orientation = (0.707107, 0.000242, 0.707107, 0.0)
    finalJoint = (-1.#IND, -1.#IND, -1.#IND, -1.#IND) (不正确)

    <
  • joint0.orientation = (-0.451596, -0.61858, -0.262811, -0.586814)
    joint1.orientation = (-0.451596, -0.61858, -0.262811, -0.586814)
    finalJoint = (-0.451596, -0.61858, -0.262811, -0.586814) (正确)

  • joint0.orientation = (0.449636, 0.6195, 0.26294, 0.58729)
    joint1.orientation = (0.449636, 0.6195, 0.26294, 0.58729)
    finalJoint = (-1.#IND, -1.#IND, -1.#IND, -1.#IND) (不正确)

    <

(是的,我知道它是在相同值之间进行插值。)

我还没有完全理解四元数是如何工作的,但这对我来说似乎很奇怪。

最佳答案

如果您查看 typical Slerp equation ,您会看到它在分数的分母中有一个 Sin(Ω),其中 Ω 是两个四元数之间的角度:即 Ω = acos(dot_product(q1,q1 )); 现在,Sin(0)==0; 当你除以零时,就会出现问题。正如维基百科文章中提到的,这是一个可移除的不连续性,但这需要一些额外的检查。

我只是把代码拉下来看看。这是它的总和:

T angle = acos(dot(x, y));
return (glm::sin((T(1)-a)*angle)*x+glm::sin(a*angle)*y)/glm::sin(angle);

没有特殊检查。当角度接近零时,这很容易出现数值问题。对于某些插值,它也可能绕着旋转球体走很长的路。还有两个其他版本的 glm:::mix 被注释掉,可以更好地处理这些问题。看起来当前版本及其伴随的问题是 committed to the repository 2011 年 5 月。

如果角度小于某个阈值,我建议恢复到使用线性插值的版本。只需注释掉当前的并取消注释旧的即可。

关于c++ - glm::mix 返回无效的四元数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11571966/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com