约束3D旋转的正确/最佳方法是什么(使用欧拉角和/或四元数)?
我的做法似乎有些不对劲。我正在将旋转应用于动画骨架层次结构中的骨骼,并且骨骼有时会明显“跳”到错误的方向,并且各个欧拉组件会绕到它们范围的另一端。
我使用欧拉角来表示当前方向,转换为四元数以进行旋转,并且独立地夹住每个欧拉角轴。这是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]);
答案 0 :(得分:0)
这里的问题是您应用的约束与应用的旋转无关。从概念的角度来看,这是你想要实现的目标:
夹住Euler旋转的代码是将骨骼旋转回来的部分。但是,此代码忽略原始骨骼旋转,因此您将看到奇怪的行为,例如您看到的捕捉。
使用它的一个简单方法是改为:
现在这将起作用,但是因为你的旋转四分之一被应用于所有角度,当这些约束中的任何一个是净时,旋转将停止,即使在某些其他地方存在自由。
如果您相互独立地应用旋转,那么您将能够可靠地使用您的夹具或上述技术来遵守约束,并且尽可能地旋转到您的目标。 - -
答案 1 :(得分:0)
欧拉角的一个问题是有多种方法来表示相同的旋转,因此您可以轻松创建一系列平滑的旋转,但表示旋转的角度可能会跳转。如果角度跳入和跳出约束范围,那么你将看到像你所描述的效果。
想象一下,只涉及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旋转应用于骨架。