如何约束 3D 旋转(欧拉)
How to constrain 3D rotations (Euler)
约束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]);
欧拉角的一个问题是有多种方法可以表示相同的旋转,因此您可以轻松创建平滑的旋转序列,但表示该旋转的角度可能会跳来跳去。 如果角度跳入和跳出约束范围,那么您会看到您所描述的效果。
假设只涉及 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 旋转应用于骨架。
这里的问题是您应用的约束与要应用的旋转无关。从概念的角度来看,这就是您要实现的目标:
- 假设骨骼处于不受约束的状态。
- 应用旋转
- 骨骼是否超出限制?如果是,请将其旋转到不再受约束的位置
夹紧欧拉旋转的代码是将骨骼向后旋转的部分。但是,此代码忽略了原始骨骼旋转,因此您将看到奇怪的行为,例如您看到的捕捉。
解决此问题的一种简单方法是执行此操作:
- 假设骨骼处于不受约束的状态
- 应用旋转
- 测试骨骼是否超出约束
- 如果是,我们需要找到约束停止移动的位置。
- 旋转减半,反向应用
- 骨骼是否超出限制?如果是,请转到 1
- 如果没有,请将旋转减半,向前应用。转到 2
- 继续这样做,直到你在约束角度的一定范围内
现在这将起作用,但是由于您的旋转四分之一值应用于所有角度,因此当这些约束中的任何一个是净约束时,旋转将停止,即使其他地方有自由。
相反,如果您彼此独立地应用旋转,那么您将能够可靠地使用您的夹紧或上述技术来遵守约束,并尽可能靠近您的目标旋转。 - -
- 使用 C++在 OpenGL 中移动自动旋转的 3D 多边形
- 如何使用偏航、俯仰和滚动旋转 3D 矢量?
- 3D透视图投影,带有摄像头旋转
- 从特征::等距3d提取旋转时出错
- VTK:旋转3D模型并捕获其深度图
- 给定的3D旋转矩阵和3D方向矢量发现角差
- 在3D中合并旋转
- Android OpenCV - 每次旋转是否有可能捕捉到不同的3D对象点击?
- 特征:将矩阵3d旋转转换为四元数
- 围绕另一个 3D 点旋转一个 3D 点
- 在3D中旋转针孔相机
- 如何在 3D 场景中旋转单个对象
- 使用 DirectX11 进行相机 3D 旋转
- 如何约束 3D 旋转(欧拉)
- 如何使用glm旋转3D相机
- 如何在3D中围绕相同的枢轴/点旋转多个对象
- 无法在WebGL中创建沿轴旋转的3D Koch
- Turbo c++ 3D旋转问题
- OpenGL中的3D旋转
- 特征:围绕轴 W 执行 3D 旋转并锚定在点 P 处