【问题标题】:How do I get a matrix where I translate then rotate then translate then rotate a second time?如何获得一个矩阵,我先平移然后旋转,然后平移然后再旋转第二次?
【发布时间】:2013-02-26 06:13:14
【问题描述】:

在一个 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);

我怀疑可能有必要在两个不同的 Matrix 对象中进行两次旋转,然后以某种方式将它们组合起来,但我不知道该怎么做。

编辑: 这种类型的矩阵似乎被称为“变换矩阵”。组合多个操作称为转换的组合。但是,关于这个主题的页面都没有提到如何进行一系列的平移和旋转。

当然,如果您可以使用矩阵围绕一个点进行旋转,那么必须可以以某种方式执行多个矩阵运算以允许围绕一个点进行旋转,然后围绕另一个点进行额外的旋转。

我曾尝试查看有关骨骼动画的页面,但我无法理解他们在谈论什么。

【问题讨论】:

  • 您似乎忘记撤消 legRot。除了最里面的旋转,所有其他操作都应该完美平衡。您可以通过在适当的位置添加反向旋转来实现这一点,或者将前三个操作组合到一个矩阵中,然后先应用该矩阵,然后应用它的逆矩阵。如果这解决了你的问题,我会把这个评论变成答案。
  • 这不起作用。我希望我能找到一个关于如何做到这一点的教程,但要么不可能,要么我正在寻找错误的东西。

标签: android math matrix


【解决方案1】:

如果我正确理解你的问题,你有一个相对旋转的情况。您可以尝试搜索双摆,见图。

使用旋转矩阵可以找到点p1 围绕点p0 旋转的新坐标,如下所示

p2绕点p1旋转的新坐标为

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

矩阵乘法的顺序和角度的符号一样重要。

【讨论】:

  • 我在gamedev上找到了答案。我不确定我得到的最终解决方案是否与您在这里所做的实际数学相符。它看起来不像,但我不完全确定 Matrix 对象可能在做什么。 gamedev.stackexchange.com/questions/50171/…
【解决方案2】:

恐怕这将与语言无关 - 我实际上正在 Android 中做类似的事情,但我同时在学习 android 和矩阵数学!你似乎知道如何在 Android 中使用矩阵,所以我猜这不会有问题。

所以 - 假设我们有两个网格(其中一个网格是您可以在屏幕上独立绘制的东西):UpperLegLowerLeg

  • 对于UpperLeg,您将获得网格旋转的点 (RotationPoint)(在现实世界中,我猜这将是臀部)并且您将获得@987654325 的点@ 附加到它(AttachmentPoint)(在现实世界中我猜这将是膝盖)。
  • 对于LowerLeg,您将获得网格旋转的点 (RotationPoint)(在现实世界中,我猜这将是膝盖)。

UpperLeg.AttachmentPoint = LowerLeg.RotationPoint(这样你的腿就不会掉下来)。

现在假设您有两种旋转量(一种用于UpperLeg,一种用于LowerLeg):UpperLeg.RotationLowerLeg.Rotation

(一个关于旋转的主题 - 如果你还没有听说过 四元数,你应该看看 - 让我惊讶的是 1846 年的某个人想出了这些 - 它们基本上封装了旋转的概念,可以变成旋转矩阵,可以组合(通过乘法)并且不受万向节锁定的影响。

首先你将UpperLeg旋转:

  1. 移动UpperLeg 网格,使UpperLeg.RotationPoint 成为原点
  2. 旋转UpperLeg.Rotation
  3. 移动UpperLeg 网格,使其位于现实世界中需要的位置。 我看到你正在这样做。

所以对于LowerLeg,它会是:

  1. 移动LowerLeg 网格,使LowerLeg.RotationPoint 成为原点
  2. 按(UpperLeg.Rotation 结合LowerLeg.Rotation)轮换
  3. LowerLeg 网格移动的量与在步骤 3 中移动UpperLeg 网格的量相同
  4. LowerLeg 网格移动到由UpperLeg.Rotation 旋转的向量(从UpperLeg.RotationPointUpperLeg.AttachmentPoint 的向量)。

以上步骤可以组合优化。

基本上我是说:
旋转LowerLeg,因为它需要旋转,然后将它推到需要去的地方——它需要去的地方将取决于UpperLeg去的地方,以及你如何到达LowerLeg连接到UpperLeg的地方.

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

【讨论】:

    猜你喜欢
    • 2013-09-27
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 1970-01-01
    相关资源
    最近更新 更多