0

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

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

现在我想进一步推动它。为了减少动画师的麻烦,我想删除额外的扭曲属性并在关节本身的所有三个欧拉旋转值之间进行插值以生成扭曲值。假设动画师直接在通道框中设置值或简单地相对旋转手腕,这些值很容易超过 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)?

4

2 回答 2

3

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

首先,矩阵的欧拉化会产生许多无法正确插值的有效解(如果您曾经在 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 上旋转的子级。切线框架矩阵中的欧拉数不会扭曲值 - 在这种情况下,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 数学运算即可计算出扭曲:例如,与肩部的 x 旋转相比,二头肌中的一根骨骼从肩部传播扭曲,它仅旋转 (-.5 * x) 之类的东西。您对存根骨骼而不是主线骨骼进行蒙皮,因此您会得到主骨骼的 YZ 旋转,但得到存根的调制 X 扭曲。

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

于 2013-08-25T22:48:42.470 回答
0

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

这在数学上很难定义

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

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

代替:

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

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

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

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

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

集群解决不了这个

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

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

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

于 2013-08-26T17:34:12.190 回答