【问题标题】:How To Find The "Twist" Angle From Euler Angles如何从欧拉角中找到“扭曲”角
【发布时间】:2013-08-28 05:39:23
【问题描述】:

编辑:我认为需要进一步澄清我正在尝试做的事情:

我在 Maya 中有一个前臂装备设置,使用线变形器来控制扭曲。线变形器位于 skinCluster 的顶部。腕关节有一个额外的角度属性,称为“扭曲”,它链接到与腕关节位于同一位置但保持肘关节方向的父关节。 twist 属性也连接到导线的 dropoffLocatorTwist[1] 属性。下降到 100 度时,金属丝将前臂扭曲到无穷大,关节仍然代表手腕和手的“姿势”。为了补偿 skinCluster 的过度旋转,我添加了一个重复的手腕层次结构并将扭曲连接到它的旋转 x。将复制层次结构的 worldInverseMatrix 连接到 skinClusters 的 bindPreMatrix 属性可以有效地否定腕/手关节围绕肘骨轴的任何旋转。

现在我想进一步推动它。为了减少动画师的麻烦,我想删除额外的扭曲属性,并在关节本身的所有三个欧拉旋转值之间进行插值以生成扭曲值。假设动画师直接在通道框中设置值或简单地相对旋转手腕,这些值很容易超过 1000pi(以度为单位)。如果多边形网格足够密集,线变形器可以轻松地沿曲线执行扭曲到该量级,而不会产生任何伪影。问题是如何对欧拉旋转进行插值以获得准确表示姿势和扭曲的单个角度值。我已经尝试通过将每个欧拉值乘以矩阵中伴随行向量的欧拉旋转的切线的点积来用曲线切线和腕矩阵进行插值,但这并不完全有效:

twist=rx*(矩阵第1行切点)+ry*(矩阵第2行切点)+rz*(矩阵第3行切点)

特别是,它不喜欢绕 Y 轴旋转。谁能告诉我为什么会这样以及如何正确地将欧拉旋转分解为扭曲角而不将扭曲限制为 -pi pi?

以前问过:

我正在使用 Maya 线(曲线)变形器,并希望根据关节的欧拉旋转找到沿线切线的扭曲值。 Maya 中的关节实际上是变换矩阵,但其组合方式是用户可以输入可能的最大浮点值作为任何欧拉旋转分量的度数。我想取那些欧拉值(xyz),并以这样的方式组合它们,结果是轴角旋转,其中轴是父矩阵的第一行(或线的切线),角度是围绕该轴的未绑定扭曲值,允许对网格进行无限制的无翻转扭曲。问题是我找不到插值 x、y 和 z 值的方法,因此得到的角度仅代表扭曲而没有别的。更简单地说,我想找到欧拉旋转的“x”旋转值,其中 x 轴已旋转,因此现在由“y”、“z”或所有三个组件之间的某个值表示.有什么方法可以做到这一点,而不会将 x 的值丢失到一个较小但等效的值(例如 270 == 90,但我们想要 270)?

【问题讨论】:

  • 问题不是关节引起的,而是集群引起的。簇只是在矢量移动时变换点。旋转 360 度后的向量是相同的。如果您之间有足够的关节,它看起来仍然正确。但是如果你想每个关节旋转超过 180 度,那么集群就无法处理这个问题。这可以用其他方法解决

标签: rotation axis maya euler-angles twist


【解决方案1】:

这是一个重要的问题,原因有几个。

首先,矩阵的欧拉化会产生许多无法正确插值的有效解(如果您曾经在 Maya 图形编辑器中使用过空白欧拉过滤器,您就会明白我的意思)。有许多欧拉组合会产生给定的四元数或旋转矩阵。这意味着很难创建一个涵盖所有可能性的确定性解决方案。

其次,样条曲线的切线是一个向量,但如果没有至少一个其他向量来为解决方案增添趣味,就无法将向量转换为矩阵。如果您熟悉 maya 的样条线 IK 以及为扭曲控制找到合适的参考框架的复杂性,您会在这里看到相同的问题。

第三,也是最重要的目的:twist 不能表示为 3d 空间中的旋转 - 它是原始曲线的非欧几里得空间中的相对旋转对应一个一致的世界空间矩阵。

如果您想处理扭曲,您需要为要采样的曲线上的任何点构建一个参考框架变换,并且您需要为其提供一些额外的信息来开始它。由于扭曲是相对的,因此您需要提供一个起点来测量扭曲。您会注意到所有用于沿曲线(运动路径、样条线 IK)工作的原生 Maya 工具都执行此操作。

创建矩阵非常简单。获得曲线切线的归一化向量,以及“向上向量”的另一个。向上向量是您必须按照惯例定义的东西 - 这就是为什么所有使用曲线几何切线的 Maya 工具都需要您选择或提供一个。如果您的曲线或多或少位于 XZ 平面上,则可以使用世界上矢量。如果它或多或少是垂直的,您可以使用 X 或 Z。无论如何,您需要标准化的向上向量。您的“边”向量,即最终矩阵的局部 z 轴,是切线向量和边向量的叉积。现在将原始向上向量替换为切线和侧向量的交叉向量(否则您的矩阵将被剪切)。最后,您需要获得切线的曲线上点的世界空间位置。

现在像这样组装你的矩阵:

tangent.x  tangent.y  tangent.z  0
up.x       up.y       up.z       0
side.x     side.y     side.z     0 
pos.x      pos.y      pos.z      1

这会在采样点创建一个矩阵,局部 x 指向曲线切线,局部 y 或多或少指向原始向上向量。在该矩阵的上下文中,扭曲轴是局部 X 旋转。通过创建两个变换更容易控制扭曲:一个使用此矩阵提供参考框架的父级和一个锁定在 Y 和 Z 上且仅在 X 上旋转的子级。切线框架矩阵中的欧拉数将 not 是一个扭曲值 - 在这种情况下,twiat 是一个完全相对的概念,不能在单个矩阵中表达!

老实说,对于这种事情,使用内置工具可能更容易解决。我会尝试使用运动路径将参考变换(关节或定位器)约束到曲线:Animation>Motion Paths>Attach to Motion Path。默认情况下,这将满足您的要求,您的 X 轴将是曲线的切线,而 Y 将是世界上的。您可以将第二个关节作为第一个关节的父节点(局部归零),它的局部 X 将是扭曲轴,您可以锁定其他两个轴并使用该值。

根据曲线的形状,您可能会遇到两组不同的问题。如果您的向上向量太接近曲线的方向,则解是不稳定的。您可以通过选择不同的“向上”向量来解决这个问题 - 对于垂直方向的曲线,您可以使用世界 Z 而不是世界 Y。但是,如果曲线在所有 3 维中循环,则没有数学上完整的解决方案。

第二种策略是使用拉伸几何体来提供“向上”向量。如果您沿着原始曲线拉伸一条线段,形成一条带,原始曲线作为 V=0 等参线,然后在曲线上的任何点,您都可以使用 U 等参线作为向上向量。这样您就可以看到并在必要时纠正沿曲线的扭曲以避免翻转和摆动——否则在这种情况下这将是很常见的。您可以使用 pointOnSurface 命令从曲面上抓取矢量。只要您的拉伸历史记录处于启用状态,您就可以编辑原始曲线或为其设置动画,并且此解决方案仍然有效。

更新

响应 OP 的进一步信息:

1) 我不会太担心非常大的旋转。正如 jooja 指出的那样,这在您需要建模的现实世界中没有确切的含义——实际上,只有非常特殊的角色才会需要它。手腕扭转旋转的生物学极限小于 +/- 90,而在肩部则更小。卡通人物可能会超越这一点 - 但可能只是在诸如扭曲橡皮筋特效之类的背景下,而不是通用装备。

2) 欧拉扭曲相对温和,即使对于 3 轴关节,只要它是第一个欧拉项(即,XYZ 旋转中的 X)。如果您的手臂没有沿第一轴任何额外的关节方向布置,您可以通过跟踪第一个欧拉旋转来测量累积的扭曲(即,对于 XYZ 骨骼,链是沿局部 X 布置的零旋转关节的直线长度)。在该配置中,很容易添加存根骨骼以使用简单的表达式或基于节点的数学来抵消扭曲旋转。您可以将扭曲旋转分布在多个骨骼上以保持平滑(尽管使用现代双四元数蒙皮这不是问题,肩部和手腕周围的两三个骨骼可能就足够了)。由于骨骼是短截线,因此它们无需进行复杂的 3D 数学运算即可计算出扭曲:例如,二头肌中的骨骼从肩部传播扭曲,仅旋转 (-.5 * x) 与肩部的 x 旋转。您对存根骨骼而不是主线骨骼进行蒙皮,因此您会得到主骨骼的 YZ 旋转,但得到存根的调制 X 扭曲。

这种安排的主要缺点是您的绑定姿势不能也是您的归零姿势:您需要沿链的局部轴在“未扭曲”状态下是连续的 - 这意味着您的 0,0,0肩部是与世界 X 对齐的刚性 T 姿势,而不是大多数模型所获得的更放松的姿势。动画师往往不喜欢那种零姿势(当然,如果你要匹配现有的模型,你别无选择)。但是,您可以使用 dagPose 提供替代的零姿势,这些姿势实际上是归零的,但确实将角色放回中性姿势。

【讨论】:

  • 另外让我添加一个旋转之外的旋转实际上并不存在。它们的存在只是因为一些外部观察者正在计数。如果我把一个篮球留在院子里,然后投三分球,那么在没有人观察的情况下,我无法知道它绕着自己旋转了多少次。唯一可以观察到的是一个 0-360 切片内的角度变化。本质上,扭曲是试图在空间上强加一种抽象的属性概念,而空间本身并不具有这种属性。使用模拟很容易做到这一点,但制作动画却很痛苦。曲线不知道任何无法解决的参考。
  • 我想要完成的工作似乎有些混乱,所以我更新了我的问题。请检查我的修改。
  • 您正在使用钢丝变形器来抵消因手腕扭曲而产生的风车?这是一个相当传统的人形角色,还是更奇特的角色?
  • 而且……你只关心手腕的扭转?
  • 现在,它只是一个手臂模型,所以是的。我正在使用线变形器而不是皮肤簇来处理扭曲(以完全绕过糖果包装/翻转伪影),并使用单独的层次结构来抵消风车。我希望这也可以应用于其他区域,例如肩膀或整个躯干,但我还没有尝试过。
【解决方案2】:

3D 图形不是现实。在数学建模方面,现实真的很糟糕。在这种特殊情况下,所做的简化是 Maya 和几乎所有 3D 应用程序使用的表面模型实际上最终不会旋转任何东西。看到表面要么完全离散化(多边形、体素),要么将连续表面简化为一堆离散控制点(样条线)。这样做的好处是它易于操作,因为一切都只是矢量移动,甚至是旋转。没错,整个过程中确实没有旋转,而一些节点知道旋转最终结果,毕竟节点和它发送到渲染器不知道节点做了什么。

这在数学上很难定义

所以你要问的是什么是这样的:

“相对于一个轴投影的旋转总和是多少?”

代替:

“如何正确地将欧拉旋转分解为扭曲角而不将扭曲限制为 -pi pi?”

后者在数学上更难理解且定义不明确。后一个问题的基本答案是你不能。前一种形式定义得更好,但仍然像问我今天走了多远,知道我从床上开始,一天在床上结束。原因是你不知道我是如何在两者之间移动的。所以真正的答案实际上是时间积分,这取决于之前的所有帧,换句话说,你需要一个模拟来解决这个问题。您需要做出一些假设和角落约束来帮助您解决问题。

最简单的方法是强制一个轴始终指向您的扭曲方向。然后使该轴成为最后评估的欧拉(实际上 Maya 不使用欧拉角,它使用 Tait-Bryan 角)现在可以简单地假设扭曲是这些单个通道的总和。为此,您的旋转顺序需要与您的方向相匹配,因此如果它沿着 x,则旋转顺序需要以字母 x 开头,例如 xyz。

上面的操作是在假设其他角度实际上没有旋转很多圈的情况下进行的。当然,对于动画师来说,它是否完全正确并不重要,只要它成功了。即使您不计算扭曲,真正任意旋转其他轴也会导致奇怪的插值问题。

如果这还不够,那么它会变得有点乏味,因为我需要画图。基本上问题是欧拉角或泰特-布赖恩角不是一个很好的插值模型,只是指向方向。插值如此直接地摆动是一个非常奇怪的混乱。其中一些具有非常不直观的极端情况。

集群无法解决这个问题

因此每个点不能超过360度才能返回原点。由于这些点是连接的,它似乎又回到了起点。确实,使用的矩阵计算最终具有类似的限制,但是如果您查看单个点,点移动是限制因素并不重要。现在,如果您有一个点链,使得没有一个点“旋转”不超过 45 度(越少越好,越多点越平滑),那么您就没有问题。但是还是不行。为什么?

骨骼移动点的位置,加权矢量移动称为集群,因为移动每个单独的点需要大量工作。最终效果是每个关节跨度只能旋转大约 双四元数插值的东西可以用来代替普通的集群。它实际上存储了 2 个深蹲并在它们之间进行插值。这可以通过一些噱头解决整个 360 度切片。距离无限扭曲还很远(假设有足够的扭曲点数),肯定会更好。

双quat插值可以做到这一点,所以也许你应该改用双quat蒙皮。

【讨论】:

  • 我现在提供了一些数学示例。
  • @user2715943 它远没有那么简单。事实上,聘请一名数学家非常困难。
  • 我正在使用双 quat 蒙皮,但对于沿 x 轴定向的关节,我想否定所有 rotateX 影响并用线扭曲替换它们。我不能简单地锁定通道——尤其是手腕,因为我肯定会抱怨动画师,这仍然会留下 y 或 z 轴何时变为 x 的问题,因此应该会影响线扭曲属性。跨度>
  • @user2715943 是的,但从数学上讲这并不容易,因为奇怪的事情会发生,其他通道可能会在一半时间反向旋转你的扭曲并沿着另一半旋转。这就是为什么你看不到这样的钻机。欧拉从未声称他的方法会代表任何有用的东西,只是你可以用这个方案完美地定位事物。不插入任何东西。但是你不能把轴相加,它不完美吗?动画师会用肉眼衡量你的装备。无论如何,创意崩溃论坛可能是讨论这个问题的更好地方,因为它没有答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
  • 2012-06-21
  • 2014-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多