Skip to content

Commit

Permalink
Added Matrix4 extension (flame-engine#838)
Browse files Browse the repository at this point in the history
* Added Matrix4 extension

* Added unit tests for Matrix4 extension class

* Update doc/util.md

Co-authored-by: Lukas Klingsbo <[email protected]>

* Renamed transformVector2 to transform2
  • Loading branch information
wolfenrain authored Jun 9, 2021
1 parent 39b6ade commit 50ca95a
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 0 deletions.
33 changes: 33 additions & 0 deletions doc/util.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ Methods:

Methods:
- `toRect`: Converts this math `Rectangle` into an ui `Rect`.

### Size

Methods:
Expand Down Expand Up @@ -241,3 +242,35 @@ Operators:
- `&`: Combines two `Vector2`s to form a Rect, the origin should be on the left and the size on the
right.
- `%`: Modulo/Remainder of x and y separately of two `Vector2`s.

### Matrix4

This class comes from the `vector_math` package. We have created a few extension methods on top
of what is already offered by `vector_math`.

Methods:
- `translate2`: Translate the `Matrix4` by the given `Vector2`.
- `transform2`: Create a new `Vector2` by transforming the given `Vector2` using the `Matrix4`.
- `transformed2`: Transform the input `Vector2` into the output `Vector2`.

Getters:
- `m11`: The first row and first column.
- `m12`: The first row and second column.
- `m13`: The first row and third column.
- `m14`: The first row and fourth column.
- `m21`: The second row and first column.
- `m22`: The second row and second column.
- `m23`: The second row and third column.
- `m24`: The second row and fourth column.
- `m31`: The third row and first column.
- `m32`: The third row and second column.
- `m33`: The third row and third column.
- `m34`: The third row and fourth column.
- `m41`: The fourth row and first column.
- `m42`: The fourth row and second column.
- `m43`: The fourth row and third column.
- `m44`: The fourth row and fourth column.

Factories:
- `scale`: Create a scaled `Matrix4`. Either by passing a `Vector4` or `Vector2` as it's first
argument, or by passing x y z doubles.
1 change: 1 addition & 0 deletions packages/flame/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
- Add `SpriteAnimation` support to parallax
- Fix `Parallax` alignment for images with different width and height
- Fix `ImageComposition` image bounds validation
- Add `Matrix4` extensions

## [1.0.0-releasecandidate.11]
- Replace deprecated analysis option lines-of-executable-code with source-lines-of-code
Expand Down
1 change: 1 addition & 0 deletions packages/flame/lib/extensions.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export 'src/extensions/canvas.dart';
export 'src/extensions/color.dart';
export 'src/extensions/image.dart';
export 'src/extensions/matrix4.dart';
export 'src/extensions/offset.dart';
export 'src/extensions/rect.dart';
export 'src/extensions/rectangle.dart';
Expand Down
87 changes: 87 additions & 0 deletions packages/flame/lib/src/extensions/matrix4.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import 'package:vector_math/vector_math_64.dart';

export 'package:vector_math/vector_math_64.dart' hide Colors;

extension Matrix4Extension on Matrix4 {
/// A first row and first column value.
double get m11 => storage[0];

/// A first row and second column value.
double get m12 => storage[1];

/// A first row and third column value.
double get m13 => storage[2];

/// A first row and fourth column value.
double get m14 => storage[3];

/// A second row and first column value.
double get m21 => storage[4];

/// A second row and second column value.
double get m22 => storage[5];

/// A second row and third column value.
double get m23 => storage[6];

/// A second row and fourth column value.
double get m24 => storage[7];

/// A third row and first column value.
double get m31 => storage[8];

/// A third row and second column value.
double get m32 => storage[9];

/// A third row and third column value.
double get m33 => storage[10];

/// A third row and fourth column value.
double get m34 => storage[11];

/// A fourth row and first column value.
double get m41 => storage[12];

/// A fourth row and second column value.
double get m42 => storage[13];

/// A fourth row and third column value.
double get m43 => storage[14];

/// A fourth row and fourth column value.
double get m44 => storage[15];

/// Translate this matrix by a [Vector2].
void translate2(Vector2 vector) {
return translate(vector.x, vector.y);
}

/// Transform [position] of type [Vector2] using the transformation defined by
/// this.
Vector2 transform2(Vector2 position) {
return Vector2(
(position.x * m11) + (position.y * m21) + m41,
(position.x * m12) + (position.y * m22) + m42,
);
}

/// Transform a copy of [position] of type [Vector2] using the transformation
/// defined by this. If a [out] parameter is supplied, the copy is stored in
/// [out].
Vector2 transformed2(Vector2 position, [Vector2? out]) {
if (out == null) {
// ignore: parameter_assignments
out = Vector2.copy(position);
} else {
out.setFrom(position);
}
return transform2(out);
}

/// Create a scaled matrix.
///
/// Scale by a [Vector3], [Vector4], or x,y,z
static Matrix4 scale(dynamic x, [double? y, double? z]) {
return Matrix4.identity()..scale(x, y, z);
}
}
49 changes: 49 additions & 0 deletions packages/flame/test/extensions/matrix4_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import 'package:flame/extensions.dart';
import 'package:test/test.dart';

import '../util/expect_vector2.dart';

void main() {
group('Matrix4 test', () {
final matrix4 = Matrix4.fromList([
1, 2, 3, 4, // first row
5, 6, 7, 8, // second row
9, 10, 11, 12, // third row
13, 14, 15, 16, // fourth row
]);

test('test m11', () => expect(matrix4.m11, matrix4.storage[0]));
test('test m12', () => expect(matrix4.m12, matrix4.storage[1]));
test('test m13', () => expect(matrix4.m13, matrix4.storage[2]));
test('test m14', () => expect(matrix4.m14, matrix4.storage[3]));
test('test m21', () => expect(matrix4.m21, matrix4.storage[4]));
test('test m22', () => expect(matrix4.m22, matrix4.storage[5]));
test('test m23', () => expect(matrix4.m23, matrix4.storage[6]));
test('test m24', () => expect(matrix4.m24, matrix4.storage[7]));
test('test m31', () => expect(matrix4.m31, matrix4.storage[8]));
test('test m32', () => expect(matrix4.m32, matrix4.storage[9]));
test('test m33', () => expect(matrix4.m33, matrix4.storage[10]));
test('test m34', () => expect(matrix4.m34, matrix4.storage[11]));
test('test m41', () => expect(matrix4.m41, matrix4.storage[12]));
test('test m42', () => expect(matrix4.m42, matrix4.storage[13]));
test('test m43', () => expect(matrix4.m43, matrix4.storage[14]));
test('test m44', () => expect(matrix4.m44, matrix4.storage[15]));

test('test transform2', () {
final matrix4 = Matrix4.translation(Vector3(0, 10, 0));
final input = Vector2.all(10);

expectVector2(matrix4.transform2(input), Vector2(10, 20));
});

test('test transformed2', () {
final matrix4 = Matrix4.translation(Vector3(0, 10, 0));
final input = Vector2.all(10);
final out = Vector2.zero();
final result = matrix4.transformed2(input, out);

expectVector2(out, input);
expectVector2(result, Vector2(10, 20));
});
});
}

0 comments on commit 50ca95a

Please sign in to comment.