【问题标题】:Combine matrix transformations组合矩阵变换
【发布时间】:2021-06-24 10:04:45
【问题描述】:

我想将两个矩阵的转换合并为一个。我有一个包含不同形状的场景 - 矩形,圆形,......它有自己的矩阵,其中包含所有转换:旋转,缩放,平移。当我对场景应用变换时,场景内的所有元素都将获得该变换。使用此存储库中的 code 可以很好地工作,该存储库用于使用手指手势应用转换。这些图像和形状是使用 OpenGL GLES2 使用 library 生成的。我没有提供完整的源代码,因为问题来自矩阵的顺序,如下所述。

但我希望某些形状具有带有变换的单独矩阵,即形状从其特定矩阵以及场景变换中获取变换。这意味着我需要结合这两个矩阵的转换并将其用于该形状。

假设场景具有矩阵m1,而图像(​​狮子图像)具有矩阵m2,那么我需要结合这两个矩阵的转换。我曾尝试使用 preConcat,并首先应用场景中的变换,然后将其应用到形状。

var m = Matrix()
m.preConcat(m1)
m.preConcat(m2)

然后将矩阵 m 的变换应用到形状,这样它就会接收来自两个矩阵的组合变换。当场景的变换发生变化时,这很有效。因此,当我缩放、旋转、平移整个场景时,所有形状都会成功地接收到来自两个矩阵的转换。

改变整个场景的变换,应用于所有形状 (工作!)


但是当我尝试使用相同的代码仅更改该特定形状的转换时,问题就出现了。当我尝试转换时遇到问题时,旋转和缩放的枢轴点更改为屏幕的中心,而不是它的假设方式,并且枢轴应该与两个手指之间的中心匹配。三角形内的圆圈与屏幕的中间相匹配,因此一旦图像的中心与屏幕的中心相匹配,它就会在该点上旋转。重要的是要说图像的开头被认为是该图像的中心,而不是图像的左上角。

仅更改图像的转换 (不工作!)




切换顺序

我已经尝试切换连接矩阵的顺序,换句话说,我首先应用形状矩阵 m2 的变换,然后是来自矩阵的变换整个场景m1

var m = Matrix()
m.preConcat(m2)
m.preConcat(m1)

但是现在发生了相反的情况,它在更改形状的变换时开始正常工作,但在更改整个场景的变换时却不起作用。

更改整个场景的变换,应用于所有形状 (不工作!)

仅更改图像的转换 (正在工作!)




根据我们要更改的矩阵变换使用不同的顺序

我尝试在连接矩阵时使用不同的顺序。场景的顺序是 m1 -> m2m2 -> m1 用于图像。

// use when transforming the scene
var m = Matrix()
m.preConcat(m1)
m.preConcat(m2)

// used when transforming the image
var m = Matrix()
m.preConcat(m2)
m.preConcat(m1)

现在它有点工作了,唯一的问题是当我切换矩阵的顺序时,我得到了一个令人讨厌的翻译,因为它可以在 6-7 秒处看到。但除此之外它还有效!

所以有几个问题:

  1. 在更改矩阵 m1m2 的顺序时,是什么导致了这种转换?
  2. 有没有办法解决翻译问题?
  3. 为什么需要更改矩阵的顺序?

【问题讨论】:

    标签: android matrix transformation


    【解决方案1】:

    我想出了一个绝妙的解决方案,而不是使用 m1 作为将用于所有形状的场景的矩阵并使用 m2 作为矩阵图像(狮子图像),然后结合这两个矩阵的变换。

    我所做的是为每一层使用单独的矩阵,所以现在 m1 成为(三角形、线、圆)的矩阵,而 m2 被保留用于图像。


    现在,当我想一次只转换一层时,当调用 onTouch() 方法时,我们会为该特定矩阵应用转换。因此,如果我只想将变换应用到图像层,我只通过 OpenGLMatrixGestureDetector 将它们应用到 m2 矩阵,如果我只想将它们应用到形状(三角形、线条、圆形),然后我只将转换设置为 m1 矩阵。


    所以最好的部分是当我想将变换应用于两个图层(形状和图像)时该怎么做。那么当调用 onTouch() 事件时,我将转换应用于两个矩阵,就好像我们一次选择一个层一样,然后应用转换,然后选择下一层并应用相同的转换。 这样我们通过 OpenGLMatrixGestureDetector 对每个矩阵应用相同的变换,这样我们就可以更新两个矩阵。

    很酷的是,我们可以使用撤消/重做逻辑,通过在每个转换会话之后从矩阵值中收集转换。当我们需要恢复它们时,只需设置之前存储的矩阵值。

    结论: 为每一层使用单独的矩阵(OpenGLMatrixGestureDetector)。要一次将转换应用于一个层,在 onTouch() 中使用与我们要转换的特定层对应的手势检测器。要将转换应用于多个层,请使用具有相同 onTouch() 事件的所有手势检测器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多