如何获取一个矩阵,其中我先进行平移操作,然后进行旋转操作,再进行第二次平移操作,最后再进行第二次旋转操作?

5

在一个Android应用中,我想要画一个跑步的腿。为了输出腿的上部分,我可以执行以下操作:

// legCX,legCY is the location on screen about which the leg rotates.
Matrix m = new Matrix();
m.postTranslate(-legCX,-legCY);
m.postRotate(legRot);
m.postTranslate(legCX,legCY);

我将矩阵设置到画布上并绘制了腿部。如何在膝盖以下绘制腿的第二部分?它以不同于上面的腿的速率旋转,并且具有随着上面的腿移动的中心点。我尝试了以下方法,但结果是围绕某个单一点旋转,该点不跟随上面的腿移动。
Matrix m = new Matrix();
m.postTranslate(-legCX,-legCY);
m.postRotate(legRot);
m.postTranslate(0,-legLength);
m.postRotate(footRot);
m.postTranslate(0,legLength);
m.postTranslate(legCX,legCY);

我怀疑需要在两个不同的矩阵对象中进行两次旋转,然后以某种方式将它们合并,但我无法确定如何做到这一点。
编辑: 这种矩阵被称为“变换矩阵”。组合多个操作称为变换的组合。然而,在这个主题的所有页面中,都没有提到如何进行一系列平移和旋转。
如果您可以使用矩阵绕一个点进行旋转,那么肯定可以通过多个矩阵操作来实现绕一个点旋转,然后绕另一个点进行额外的旋转。
我尝试查看关于骨骼动画的页面,但是我无法理解他们在说什么。

似乎你忘了撤销legRot操作。除了最内层的旋转外,其他所有操作都应该是完美平衡的。你可以通过在适当的位置添加相反的旋转,或者将前三个操作合并为一个矩阵,先应用该矩阵,然后再应用它的逆矩阵来实现这一点。如果这解决了你的问题,我会把这个评论改成一个答案。 - MvG
这个不起作用。我希望能找到一个关于如何做这个的教程,但要么不可能,要么我在搜索错误的东西。 - HappyEngineer
2个回答

6
如果我正确理解了您的问题,那么您是在处理相对旋转的情况。您可以尝试搜索双摆,如下图所示。

double pendulum

使用旋转矩阵可以找到围绕点 p0 旋转后点 p1 的新坐标,公式如下。

p2 围绕点 p1 旋转后的新坐标为:

最后,点 p2 围绕点 p0 旋转后的新坐标为:

矩阵乘法的顺序和角度的符号都很重要。

我在gamedev上找到了答案。我不确定那里得到的最终解决方案是否对应于您在此处执行的实际数学运算。它看起来并不像,但我不完全确定Matrix对象可能正在做什么。 - HappyEngineer

2
我很抱歉,这将是与语言无关的 - 我现在正在Android中做类似的事情,但我同时学习Android和矩阵数学!您似乎知道如何在Android中使用矩阵,因此我猜这不会成为问题。
所以 - 假设我们有两个网格(其中一个网格是可以独立于屏幕绘制的东西):UpperLeg和LowerLeg。
对于UpperLeg,您将拥有网格旋转的点(RotationPoint)(在现实世界中,我想这将是臀部),以及连接到其上的LowerLeg的点(AttachmentPoint)(在现实世界中,我想这将是膝盖)。
对于LowerLeg,您将拥有网格旋转的点(RotationPoint),(在现实世界中,我想这将是膝盖)。
UpperLeg.AttachmentPoint = LowerLeg.RotationPoint (这样您的腿就不会掉落)。
现在假设您有两个旋转量(对于UpperLeg和LowerLeg各一个):UpperLeg.Rotation和LowerLeg.Rotation。
(关于旋转 - 如果您没有听说过四元数,那么您应该看一下 - 令人惊奇的是,一位来自1846年的家伙提出了这些,它们基本上封装了旋转概念,可以转换为旋转矩阵,可以通过乘法组合(通过乘法)并且不会受到万向节锁的影响。)
首先,您需要将UpperLeg旋转:
将UpperLeg网格移动到UpperLeg.RotationPoint成为原点
旋转UpperLeg.Rotation
将UpperLeg网格移动到其在现实世界中所需的位置。我看到您正在做这个。
因此,对于LowerLeg,它将是:
  1. LowerLeg网格移动,使LowerLeg.RotationPoint成为原点。
  2. 旋转(UpperLeg.RotationLowerLeg.Rotation相结合)。
  3. LowerLeg网格移动相同的距离,即在步骤3中UpperLeg网格移动的距离。
  4. LowerLeg网格移动Vector,该Vector是从UpperLeg.RotationPointUpperLeg.AttachmentPoint的向量旋转UpperLeg.Rotation得到的。

以上步骤可以合并和优化。

本质上,我想说:
根据需要旋转LowerLeg,然后将其推到它需要去的地方——需要去的地方将由UpperLeg去的地方以及您到达LowerLeg附着到UpperLeg的位置的方式来确定。

这是我在这里的第一篇文章,如果我违反了任何基本规则,请告诉我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接