c++ - 如何约束 3D 旋转 (Euler)

标签 c++ animation 3d

约束 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]);

最佳答案

欧拉角的一个问题是有多种方法可以表示相同的旋转,因此您可以轻松地创建一系列平滑的旋转,但表示该旋转的角度可能会跳来跳去。如果角度跳入和跳出约束范围,那么您将看到您所描述的效果。

假设只涉及 X 旋转,并且您已将 X 旋转限制在 0 到 180 度之间。还想象一下,将四元数转换为欧拉角的函数给出了 -180 到 180 度的角度。

然后你有这个旋转序列:

True rotation    After conversion    After constraint
179              179                 179
180              180                 180
181             -179                 0

你可以看到,即使旋转是平滑变化的,结果也会突然从一侧跳到另一侧,因为转换函数强制结果在一定范围内表示。

当您将四元数转换为欧拉角时,找到与先前结果最接近的角度。例如:

eCurrent = closestAngles(qCurrent.toEuler(),eCurrent);
eConstrained = clampAngles(eCurrent,min,max);

记住下一次的 eCurrent 值,并将 eConstrained 旋转应用于您的骨架。

关于c++ - 如何约束 3D 旋转 (Euler),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10662445/

相关文章:

c++ - 嵌套类中用户定义的转换运算符

使用函数指针调用成员函数的 C++ 语法

css - Sass 顺序动画

jquery - 反转(或切换)动画和淡入淡出

javascript - CSS 动画无法正常播放

java - 对三角形进行排序时快速排序太慢

C++ 程序在第一次尝试时给出垃圾,但如果它捕获异常并重试则给出正确的值

c++ - 类型转换返回类型

java - 如何在Java的Frame面板中显示、缩放3D立方体?

c++ - 为什么这个 XMVector3Transform 调用没有返回正确的结果?