如何约束3D旋转(欧拉)

KTC*_*KTC 5 c++ 3d animation

约束3D旋转的正确/最佳方法是什么(使用欧拉角和/或四元数)?

我的做法似乎有些不对劲.我正在将旋转应用于骨架层次结构中的骨骼以进行动画,并且骨骼有时会明显地"跳"到错误的方向,并且各个Euler组件正在环绕其范围的另一端.

我使用欧拉角来表示当前方向,转换为四元数来进行旋转,并独立地夹住每个欧拉角轴.这是C++伪代码,基本上显示了我正在做的事情:

Euler min = ...;
Euler max = ...;

Quat rotation = ...;
Euler eCurrent = ...;

// do rotation
Quat qCurrent = eCurrent.toQuat();
qCurrent = qCurrent * rotation;
eCurrent = qCurrent.toEuler();

// constrain
for (unsigned int i = 0; i < 3; i++)
    eCurrent[i] = clamp(eCurrent[i], min[i], max[i]);
Run Code Online (Sandbox Code Playgroud)

小智 0

这里的问题是您应用的约束与应用的旋转无关。从概念的角度来看,这就是您想要实现的目标:

  • 假设骨头处于不受约束的状态。
  • 应用轮换
  • 骨骼是否超出限制?如果是,将其旋转到不再受约束的位置

限制欧拉旋转的代码是您将骨骼旋转回来的部分。但是,此代码忽略了原始骨骼旋转,因此您会看到奇怪的行为,例如您所看到的捕捉。

处理这个问题的一个简单方法是这样做:

  • 假设骨骼处于不受约束的状态
  • 应用轮换
  • 测试骨骼是否超出限制
  • 如果是,我们需要找到约束停止运动的位置。
    1. 将旋转减半,反向应用
    2. 骨骼是否超出限制?如果是,则转到 1
    3. 如果不是,则将旋转减半,然后向前旋转。转到2
  • 继续这样做,直到您的约束角度处于一定的公差范围内

现在这将起作用,但由于您的旋转四元数应用于所有角度,因此当这些约束中的任何一个为净值时,即使其他地方存在自由度,旋转也会停止。

相反,如果您彼此独立地应用旋转,那么您将能够可靠地使用夹紧或上述技术来遵守约束,并且还可以尽可能接近目标进行旋转。- -