【问题标题】:How should you do matrix transformations?你应该如何进行矩阵变换?
【发布时间】:2022-01-12 12:01:29
【问题描述】:

我们正在渲染一个带有火焰的等距网格,其中每个图块都是一个组件,但我们在 Transform2D 的源代码中找到了这条注释

用户不得修改返回的矩阵。

  /// The total transformation matrix for the component. This matrix combines
  /// translation, rotation, reflection and scale transforms into a single
  /// entity. The matrix is cached and gets recalculated only as necessary.
  ///
  /// The returned matrix must not be modified by the user.
  Matrix4 get transformMatrix {
    if (_recalculate) {
      // The transforms below are equivalent to:
      //   _transformMatrix = Matrix4.identity()
      //       .. translate(_position.x, _position.y)
      //       .. rotateZ(_angle)
      //       .. scale(_scale.x, _scale.y, 1)
      //       .. translate(_offset.x, _offset.y);
      final m = _transformMatrix.storage;
      final cosA = math.cos(_angle);
      final sinA = math.sin(_angle);
      m[0] = cosA * _scale.x;
      m[1] = sinA * _scale.x;
      m[4] = -sinA * _scale.y;
      m[5] = cosA * _scale.y;
      m[12] = _position.x + m[0] * _offset.x + m[4] * _offset.y;
      m[13] = _position.y + m[1] * _offset.x + m[5] * _offset.y;
      _recalculate = false;
    }
    return _transformMatrix;
  }

它似乎确实有效,所有图块都是它自己的组件,每个组件只呈现一个彩色矩形。 (Matrix4.isometric() 是我们的扩展)。

IsometricGrid 扩展了 PositionComponent

IsometricGrid({
    this.tiles = const [],
    this.rows = 1,
    this.columns = 1,
    this.tileWidth = 1,
    this.tileHeight = 1,
  }) : super() {
    final isometricMatrix = Matrix4.isometric();
    transformMatrix.multiply(isometricMatrix);
    projectionMatrix = isometricMatrix;
    inverseProjectionMatrix = Matrix4.inverted(projectionMatrix);
  }

我们得到

但我们后来想用 IsometricGrid.addActor 向网格中添加一个演员

  addActor(PositionComponent actor) {
    actor.transform.transformMatrix.multiply(inverseProjectionMatrix);
    add(actor);
  }

哪个广告角色直立在网格上。但是一旦我们通过改变它的位置将actor移动到第2列第3行,矩阵似乎为actor重置了。

在火焰引擎中修改矩阵的惯用方法是什么?似乎在某些情况下矩阵只是重置。我认为这是因为它只是在您进行旋转、位置或缩放等转换时重新计算矩阵。

我们正在使用 Flutter web 构建它,我们还注意到有时当使用 alt 选项卡时,矩阵会重置。

【问题讨论】:

    标签: flutter dart matrix flame


    【解决方案1】:

    Transform2D 不允许这种“顶部的附加变换”是正确的——主要是因为每当任何底层属性发生变化时,变换矩阵都会重新计算。但是,您可以创建一个派生类,覆盖 transformMatrix getter,以便它应用额外的转换。

    我不确定在 Flame 中实现等距游戏的最佳方式是什么,但您可以尝试以下方法:

    [World]
     +--[Ground]
     |   +--[Tile]s
     |
     +--[Overground]
         +--[Character]
         +--[Enemy]s
         +--[Structure]s
         +--...
    

    这里,Ground 将是一个在渲染其子级Tiles(只是常规的 PositionComponents)之前应用等距投影的组件。因此,无需乘以变换矩阵:您只是应用了一个额外的画布变换。

    Overground 组件有点棘手。它有很多孩子,每个孩子都是一个普通的PositionComponent(x, y) 的位置在世界坐标中。然后Overground 的工作是将等距投影应用到该位置,将其转​​换为屏幕坐标,然后在渲染每个组件之前相应地平移画布。此外,Overground 需要根据孩子与相机的距离不断地重新排序。

    【讨论】:

    • 嗨,很好的答案。我们确实想到了这样的解决方案,因为这似乎是我们将尝试的唯一选择。我们希望转换将允许在未来的更新中进行此类转换。
    • 但是你能解释一下你的意思是什么“地面将是一个在渲染其子瓷砖之前应用等距投影的组件(它们只是常规的位置组件)。因此,不需要乘以变换矩阵” ?没有矩阵?您能否详细说明如何在没有矩阵的情况下进行此投影?
    猜你喜欢
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 2015-10-22
    • 1970-01-01
    • 2020-08-11
    • 2013-03-16
    相关资源
    最近更新 更多