你应该如何进行矩阵变换?
How should you do matrix transformations?
我们正在渲染一个带火焰的等距网格,其中每个图块都是一个组件,但我们在 Transform2D 的源代码中找到了这条评论
The returned matrix must not be modified by the user.
/// 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);
}
广告中的角色正对着网格站着。但是一旦我们通过改变它的位置将演员移动到第 2 列第 3 行,矩阵似乎为演员重置了。
在火焰引擎中修改矩阵变换的惯用方法是什么?似乎在某些情况下矩阵只是重置。我认为发生这种情况是因为它只是在您进行旋转、位置或缩放等变换时重新计算矩阵。
我们正在使用 flutter web 构建它,我们还注意到有时当 alt tab 时矩阵会被重置。
您是正确的,Transform2D
不允许这些类型的“顶部附加变换”——主要是因为变换矩阵在任何底层 属性 发生变化时都会重新计算。但是,您可以创建派生的 class,覆盖 transformMatrix
getter,以便应用其他转换。
我不确定在 Flame 中实现等距游戏的最佳方法是什么,但您可以尝试以下方法:
[World]
+--[Ground]
| +--[Tile]s
|
+--[Overground]
+--[Character]
+--[Enemy]s
+--[Structure]s
+--...
在这里,Ground
将是一个在渲染其 children Tile
之前应用等距投影的组件(这只是常规的 PositionComponents)。因此,无需乘以变换矩阵:您只是应用了一个额外的 canvas 变换。
Overground
组件有点棘手。它有很多children,每个都是一个规则的PositionComponent
,在世界坐标中给出了(x, y)
的位置。 Overground
的工作是将等距投影应用于该位置,将其转换为屏幕坐标,然后在渲染每个组件之前相应地平移 canvas。此外,Overground
需要根据他们与相机的距离不断 re-sort children。
我们正在渲染一个带火焰的等距网格,其中每个图块都是一个组件,但我们在 Transform2D 的源代码中找到了这条评论
The returned matrix must not be modified by the user.
/// 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);
}
广告中的角色正对着网格站着。但是一旦我们通过改变它的位置将演员移动到第 2 列第 3 行,矩阵似乎为演员重置了。
在火焰引擎中修改矩阵变换的惯用方法是什么?似乎在某些情况下矩阵只是重置。我认为发生这种情况是因为它只是在您进行旋转、位置或缩放等变换时重新计算矩阵。
我们正在使用 flutter web 构建它,我们还注意到有时当 alt tab 时矩阵会被重置。
您是正确的,Transform2D
不允许这些类型的“顶部附加变换”——主要是因为变换矩阵在任何底层 属性 发生变化时都会重新计算。但是,您可以创建派生的 class,覆盖 transformMatrix
getter,以便应用其他转换。
我不确定在 Flame 中实现等距游戏的最佳方法是什么,但您可以尝试以下方法:
[World]
+--[Ground]
| +--[Tile]s
|
+--[Overground]
+--[Character]
+--[Enemy]s
+--[Structure]s
+--...
在这里,Ground
将是一个在渲染其 children Tile
之前应用等距投影的组件(这只是常规的 PositionComponents)。因此,无需乘以变换矩阵:您只是应用了一个额外的 canvas 变换。
Overground
组件有点棘手。它有很多children,每个都是一个规则的PositionComponent
,在世界坐标中给出了(x, y)
的位置。 Overground
的工作是将等距投影应用于该位置,将其转换为屏幕坐标,然后在渲染每个组件之前相应地平移 canvas。此外,Overground
需要根据他们与相机的距离不断 re-sort children。