From d026cd90b7e47d10d0f07ba5282dfcc50de7feec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 16 Apr 2025 12:28:04 +0100 Subject: [PATCH 01/21] Add specialized Vector.translate methods based on argument types --- benchmark/matrix_bench.dart | 148 +++++++++++++++++++++++++++++++ lib/src/vector_math/matrix4.dart | 78 ++++++++++++++++ 2 files changed, 226 insertions(+) diff --git a/benchmark/matrix_bench.dart b/benchmark/matrix_bench.dart index 7d0932e0..48fb5238 100644 --- a/benchmark/matrix_bench.dart +++ b/benchmark/matrix_bench.dart @@ -321,6 +321,148 @@ class Matrix3TransposeMultiplyBenchmark extends BenchmarkBase { } } +class Matrix4TranslateByDoubleGenericBenchmark extends BenchmarkBase { + Matrix4TranslateByDoubleGenericBenchmark() + : super('Matrix4.translateByDoubleGeneric'); + + final temp = Matrix4.zero()..setIdentity(); + + static void main() { + Matrix4TranslateByDoubleGenericBenchmark().report(); + } + + @override + void run() { + for (var i = 0; i < 100; i++) { + temp.translate(10.0, 20.0, 30.0); + } + } +} + +class Matrix4TranslateByVector3GenericBenchmark extends BenchmarkBase { + Matrix4TranslateByVector3GenericBenchmark() + : super('Matrix4.translateByVector3Generic'); + + final temp = Matrix4.zero()..setIdentity(); + final vec = Vector3(10.0, 20.0, 30.0); + + static void main() { + Matrix4TranslateByVector3GenericBenchmark().report(); + } + + @override + void run() { + for (var i = 0; i < 100; i++) { + temp.translate(vec); + } + } +} + +class Matrix4TranslateByVector4GenericBenchmark extends BenchmarkBase { + Matrix4TranslateByVector4GenericBenchmark() + : super('Matrix4.translateByVector4Generic'); + + final temp = Matrix4.zero()..setIdentity(); + final vec = Vector4(10.0, 20.0, 30.0, 40.0); + + static void main() { + Matrix4TranslateByVector4GenericBenchmark().report(); + } + + @override + void run() { + for (var i = 0; i < 100; i++) { + temp.translate(vec); + } + } +} + +class Matrix4TranslateByDoubleBenchmark extends BenchmarkBase { + Matrix4TranslateByDoubleBenchmark() : super('Matrix4.translateByDouble'); + + final temp = Matrix4.zero()..setIdentity(); + + static void main() { + Matrix4TranslateByDoubleBenchmark().report(); + } + + // Call the benchmarked method with random arguments to make sure TFA won't + // specialize it based on the arguments passed and wasm-opt won't inline it, + // for fair comparison with the generic case. + @override + void setup() { + for (var i = 0; i < 10; i++) { + temp.translateByDouble( + i.toDouble(), (i * 10).toDouble(), (i * 5).toDouble()); + } + } + + @override + void run() { + for (var i = 0; i < 100; i++) { + temp.translateByDouble(10.0, 20.0, 30.0); + } + } +} + +class Matrix4TranslateByVector3Benchmark extends BenchmarkBase { + Matrix4TranslateByVector3Benchmark() : super('Matrix4.translateByVector3'); + + final temp = Matrix4.zero()..setIdentity(); + final vec = Vector3(10.0, 20.0, 30.0); + + static void main() { + Matrix4TranslateByVector3Benchmark().report(); + } + + // Call the benchmarked method with random arguments to make sure TFA won't + // specialize it based on the arguments passed and wasm-opt won't inline it, + // for fair comparison with the generic case. + @override + void setup() { + for (var i = 0; i < 10; i++) { + temp.translateByVector3( + Vector3(i.toDouble(), (i * 10).toDouble(), (i * 5).toDouble())); + } + } + + @override + void run() { + for (var i = 0; i < 100; i++) { + temp.translateByVector3(vec); + } + } +} + +class Matrix4TranslateByVector4Benchmark extends BenchmarkBase { + Matrix4TranslateByVector4Benchmark() : super('Matrix4.translateByVector4'); + + final temp = Matrix4.zero()..setIdentity(); + final vec = Vector4(10.0, 20.0, 30.0, 40.0); + + static void main() { + Matrix4TranslateByVector4Benchmark().report(); + } + + // Call the benchmarked method with random arguments to make sure TFA won't + // specialize it based on the arguments passed and wasm-opt won't inline it, + // for fair comparison with the generic case. + @override + void setup() { + for (var i = 0; i < 10; i++) { + temp.translateByVector4(Vector4(i.toDouble(), (i * 10).toDouble(), + (i * 5).toDouble(), (i * 20).toDouble())); + } + } + + @override + void run() { + for (var i = 0; i < 100; i++) { + temp.translateByVector4(vec); + } + } +} + void main() { MatrixMultiplyBenchmark.main(); SIMDMatrixMultiplyBenchmark.main(); @@ -335,4 +477,10 @@ void main() { Matrix3TransformVector3Benchmark.main(); Matrix3TransformVector2Benchmark.main(); Matrix3TransposeMultiplyBenchmark.main(); + Matrix4TranslateByDoubleGenericBenchmark.main(); + Matrix4TranslateByVector3GenericBenchmark.main(); + Matrix4TranslateByVector4GenericBenchmark.main(); + Matrix4TranslateByDoubleBenchmark.main(); + Matrix4TranslateByVector3Benchmark.main(); + Matrix4TranslateByVector4Benchmark.main(); } diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index c87081fb..70126c38 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -703,6 +703,84 @@ class Matrix4 { _m4storage[15] = t4; } + void translateByDouble(double tx, [double ty = 0.0, double tz = 0.0]) { + final tw = 1.0; + final t1 = _m4storage[0] * tx + + _m4storage[4] * ty + + _m4storage[8] * tz + + _m4storage[12] * tw; + final t2 = _m4storage[1] * tx + + _m4storage[5] * ty + + _m4storage[9] * tz + + _m4storage[13] * tw; + final t3 = _m4storage[2] * tx + + _m4storage[6] * ty + + _m4storage[10] * tz + + _m4storage[14] * tw; + final t4 = _m4storage[3] * tx + + _m4storage[7] * ty + + _m4storage[11] * tz + + _m4storage[15] * tw; + _m4storage[12] = t1; + _m4storage[13] = t2; + _m4storage[14] = t3; + _m4storage[15] = t4; + } + + void translateByVector3(Vector3 v3) { + final tx = v3.x; + final ty = v3.y; + final tz = v3.z; + final tw = 1.0; + final t1 = _m4storage[0] * tx + + _m4storage[4] * ty + + _m4storage[8] * tz + + _m4storage[12] * tw; + final t2 = _m4storage[1] * tx + + _m4storage[5] * ty + + _m4storage[9] * tz + + _m4storage[13] * tw; + final t3 = _m4storage[2] * tx + + _m4storage[6] * ty + + _m4storage[10] * tz + + _m4storage[14] * tw; + final t4 = _m4storage[3] * tx + + _m4storage[7] * ty + + _m4storage[11] * tz + + _m4storage[15] * tw; + _m4storage[12] = t1; + _m4storage[13] = t2; + _m4storage[14] = t3; + _m4storage[15] = t4; + } + + void translateByVector4(Vector4 v4) { + final tx = v4.x; + final ty = v4.y; + final tz = v4.z; + final tw = v4.w; + final t1 = _m4storage[0] * tx + + _m4storage[4] * ty + + _m4storage[8] * tz + + _m4storage[12] * tw; + final t2 = _m4storage[1] * tx + + _m4storage[5] * ty + + _m4storage[9] * tz + + _m4storage[13] * tw; + final t3 = _m4storage[2] * tx + + _m4storage[6] * ty + + _m4storage[10] * tz + + _m4storage[14] * tw; + final t4 = _m4storage[3] * tx + + _m4storage[7] * ty + + _m4storage[11] * tz + + _m4storage[15] * tw; + _m4storage[12] = t1; + _m4storage[13] = t2; + _m4storage[14] = t3; + _m4storage[15] = t4; + } + /// Multiply this by a translation from the left. /// The translation can be specified with a [Vector3], [Vector4], or x, y, z. void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) { From 2ecfbbf9b19c0ea34212dae1c74ef508a3bc45c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 16 Apr 2025 12:41:28 +0100 Subject: [PATCH 02/21] Update 64-bit classes --- lib/src/vector_math/matrix4.dart | 8 ++- lib/src/vector_math_64/matrix4.dart | 85 +++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index 70126c38..391ee853 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -661,6 +661,9 @@ class Matrix4 { Matrix4 operator -(Matrix4 arg) => clone()..sub(arg); /// Translate this matrix by a [Vector3], [Vector4], or x,y,z + /// + /// If you know the argument types in a call site, prefer [translateByDouble], + /// [translateByVector3], or [translateByVector4] for performance. void translate(dynamic x, [double y = 0.0, double z = 0.0]) { double tx; double ty; @@ -703,7 +706,8 @@ class Matrix4 { _m4storage[15] = t4; } - void translateByDouble(double tx, [double ty = 0.0, double tz = 0.0]) { + /// Translate this matrix by x, y, z. + void translateByDouble(double tx, double ty, double tz) { final tw = 1.0; final t1 = _m4storage[0] * tx + _m4storage[4] * ty + @@ -727,6 +731,7 @@ class Matrix4 { _m4storage[15] = t4; } + /// Translate this matrix by a [Vector3]. void translateByVector3(Vector3 v3) { final tx = v3.x; final ty = v3.y; @@ -754,6 +759,7 @@ class Matrix4 { _m4storage[15] = t4; } + /// Translate this matrix by a [Vector4]. void translateByVector4(Vector4 v4) { final tx = v4.x; final ty = v4.y; diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index 90a2e8cb..64053125 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -661,6 +661,9 @@ class Matrix4 { Matrix4 operator -(Matrix4 arg) => clone()..sub(arg); /// Translate this matrix by a [Vector3], [Vector4], or x,y,z + /// + /// If you know the argument types in a call site, prefer [translateByDouble], + /// [translateByVector3], or [translateByVector4] for performance. void translate(dynamic x, [double y = 0.0, double z = 0.0]) { double tx; double ty; @@ -703,6 +706,88 @@ class Matrix4 { _m4storage[15] = t4; } + /// Translate this matrix by x, y, z. + void translateByDouble(double tx, double ty, double tz) { + final tw = 1.0; + final t1 = _m4storage[0] * tx + + _m4storage[4] * ty + + _m4storage[8] * tz + + _m4storage[12] * tw; + final t2 = _m4storage[1] * tx + + _m4storage[5] * ty + + _m4storage[9] * tz + + _m4storage[13] * tw; + final t3 = _m4storage[2] * tx + + _m4storage[6] * ty + + _m4storage[10] * tz + + _m4storage[14] * tw; + final t4 = _m4storage[3] * tx + + _m4storage[7] * ty + + _m4storage[11] * tz + + _m4storage[15] * tw; + _m4storage[12] = t1; + _m4storage[13] = t2; + _m4storage[14] = t3; + _m4storage[15] = t4; + } + + /// Translate this matrix by a [Vector3]. + void translateByVector3(Vector3 v3) { + final tx = v3.x; + final ty = v3.y; + final tz = v3.z; + final tw = 1.0; + final t1 = _m4storage[0] * tx + + _m4storage[4] * ty + + _m4storage[8] * tz + + _m4storage[12] * tw; + final t2 = _m4storage[1] * tx + + _m4storage[5] * ty + + _m4storage[9] * tz + + _m4storage[13] * tw; + final t3 = _m4storage[2] * tx + + _m4storage[6] * ty + + _m4storage[10] * tz + + _m4storage[14] * tw; + final t4 = _m4storage[3] * tx + + _m4storage[7] * ty + + _m4storage[11] * tz + + _m4storage[15] * tw; + _m4storage[12] = t1; + _m4storage[13] = t2; + _m4storage[14] = t3; + _m4storage[15] = t4; + } + + /// Translate this matrix by a [Vector4]. + void translateByVector4(Vector4 v4) { + final tx = v4.x; + final ty = v4.y; + final tz = v4.z; + final tw = v4.w; + final t1 = _m4storage[0] * tx + + _m4storage[4] * ty + + _m4storage[8] * tz + + _m4storage[12] * tw; + final t2 = _m4storage[1] * tx + + _m4storage[5] * ty + + _m4storage[9] * tz + + _m4storage[13] * tw; + final t3 = _m4storage[2] * tx + + _m4storage[6] * ty + + _m4storage[10] * tz + + _m4storage[14] * tw; + final t4 = _m4storage[3] * tx + + _m4storage[7] * ty + + _m4storage[11] * tz + + _m4storage[15] * tw; + _m4storage[12] = t1; + _m4storage[13] = t2; + _m4storage[14] = t3; + _m4storage[15] = t4; + } + + /// Multiply this by a translation from the left. /// The translation can be specified with a [Vector3], [Vector4], or x, y, z. void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) { From 6814af21870e1107910a3afe32b67a31fb3b5938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 16 Apr 2025 12:42:30 +0100 Subject: [PATCH 03/21] Formatting --- lib/src/vector_math_64/matrix4.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index 64053125..21d6646d 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -787,7 +787,6 @@ class Matrix4 { _m4storage[15] = t4; } - /// Multiply this by a translation from the left. /// The translation can be specified with a [Vector3], [Vector4], or x, y, z. void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) { From cdbed22fd3af4571258736e571b7549c6f371e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Mon, 28 Apr 2025 12:33:53 +0100 Subject: [PATCH 04/21] Add tests --- test/matrix4_test.dart | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/matrix4_test.dart b/test/matrix4_test.dart index e338752a..82d8bb70 100644 --- a/test/matrix4_test.dart +++ b/test/matrix4_test.dart @@ -372,6 +372,36 @@ void testMatrix4Translation() { for (var i = 0; i < inputA.length; i++) { relativeTest(output1[i], output2[i]); } + + final input = Matrix4.fromList([ + 1, 5, 9, 13, // + 2, 6, 10, 14, // + 3, 7, 11, 15, // + 4, 8, 12, 16, // + ]); + final output3 = input.clone(); + output3[12] = input.dotRow(0, Vector4(4, 8, 12, 1)); + output3[13] = input.dotRow(1, Vector4(4, 8, 12, 1)); + output3[14] = input.dotRow(2, Vector4(4, 8, 12, 1)); + output3[15] = input.dotRow(3, Vector4(4, 8, 12, 1)); + relativeTest( + input.clone()..translateByDouble(4.0, 8.0, 12.0), + output3, + ); + relativeTest( + input.clone()..translateByVector3(Vector3(4.0, 8.0, 12.0)), + output3, + ); + + final output4 = input.clone(); + output4[12] = input.dotRow(0, Vector4(4, 8, 12, 16)); + output4[13] = input.dotRow(1, Vector4(4, 8, 12, 16)); + output4[14] = input.dotRow(2, Vector4(4, 8, 12, 16)); + output4[15] = input.dotRow(3, Vector4(4, 8, 12, 16)); + relativeTest( + input.clone()..translateByVector4(Vector4(4, 8, 12, 16)), + output4, + ); } void testMatrix4Scale() { From 581aaea97998998d22713bdc017b022db4addf53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Tue, 29 Apr 2025 12:43:35 +0100 Subject: [PATCH 05/21] Call typed versions from the dynamic version, inline dynamic version --- lib/src/vector_math/matrix4.dart | 38 +++++--------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index 391ee853..4572cc05 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -664,46 +664,18 @@ class Matrix4 { /// /// If you know the argument types in a call site, prefer [translateByDouble], /// [translateByVector3], or [translateByVector4] for performance. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') void translate(dynamic x, [double y = 0.0, double z = 0.0]) { - double tx; - double ty; - double tz; - final tw = x is Vector4 ? x.w : 1.0; if (x is Vector3) { - tx = x.x; - ty = x.y; - tz = x.z; + return translateByVector3(x); } else if (x is Vector4) { - tx = x.x; - ty = x.y; - tz = x.z; + return translateByVector4(x); } else if (x is double) { - tx = x; - ty = y; - tz = z; + return translateByDouble(x, y, z); } else { throw UnimplementedError(); } - final t1 = _m4storage[0] * tx + - _m4storage[4] * ty + - _m4storage[8] * tz + - _m4storage[12] * tw; - final t2 = _m4storage[1] * tx + - _m4storage[5] * ty + - _m4storage[9] * tz + - _m4storage[13] * tw; - final t3 = _m4storage[2] * tx + - _m4storage[6] * ty + - _m4storage[10] * tz + - _m4storage[14] * tw; - final t4 = _m4storage[3] * tx + - _m4storage[7] * ty + - _m4storage[11] * tz + - _m4storage[15] * tw; - _m4storage[12] = t1; - _m4storage[13] = t2; - _m4storage[14] = t3; - _m4storage[15] = t4; } /// Translate this matrix by x, y, z. From f94071703898d1725303209a5fe748cc192b36f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 30 Apr 2025 11:28:44 +0100 Subject: [PATCH 06/21] Do the same for leftTranslate, operator * --- lib/src/vector_math/matrix4.dart | 112 ++++++++++++++++----- lib/src/vector_math_64/matrix4.dart | 150 +++++++++++++++++----------- 2 files changed, 179 insertions(+), 83 deletions(-) diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index 4572cc05..97205f08 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -638,6 +638,14 @@ class Matrix4 { Matrix4 operator -() => clone()..negate(); /// Returns a new vector or matrix by multiplying this with [arg]. + /// + /// [arg] should be a [double] (to scale), [Vector4] (to transform), [Vector3] + /// (to transform), or [Matrix4] (to multiply). + /// + /// If you know the argument type in a call site, prefer [scaled], + /// [transformed], [transformed3], or [multiplied] for performance. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') dynamic operator *(dynamic arg) { if (arg is double) { return scaled(arg); @@ -660,7 +668,7 @@ class Matrix4 { /// Returns new matrix after component wise this - [arg] Matrix4 operator -(Matrix4 arg) => clone()..sub(arg); - /// Translate this matrix by a [Vector3], [Vector4], or x,y,z + /// Translate this matrix by a [Vector3], [Vector4], or x,y,z as [double]s. /// /// If you know the argument types in a call site, prefer [translateByDouble], /// [translateByVector3], or [translateByVector4] for performance. @@ -680,23 +688,22 @@ class Matrix4 { /// Translate this matrix by x, y, z. void translateByDouble(double tx, double ty, double tz) { - final tw = 1.0; final t1 = _m4storage[0] * tx + _m4storage[4] * ty + _m4storage[8] * tz + - _m4storage[12] * tw; + _m4storage[12]; final t2 = _m4storage[1] * tx + _m4storage[5] * ty + _m4storage[9] * tz + - _m4storage[13] * tw; + _m4storage[13]; final t3 = _m4storage[2] * tx + _m4storage[6] * ty + _m4storage[10] * tz + - _m4storage[14] * tw; + _m4storage[14]; final t4 = _m4storage[3] * tx + _m4storage[7] * ty + _m4storage[11] * tz + - _m4storage[15] * tw; + _m4storage[15]; _m4storage[12] = t1; _m4storage[13] = t2; _m4storage[14] = t3; @@ -708,23 +715,22 @@ class Matrix4 { final tx = v3.x; final ty = v3.y; final tz = v3.z; - final tw = 1.0; final t1 = _m4storage[0] * tx + _m4storage[4] * ty + _m4storage[8] * tz + - _m4storage[12] * tw; + _m4storage[12]; final t2 = _m4storage[1] * tx + _m4storage[5] * ty + _m4storage[9] * tz + - _m4storage[13] * tw; + _m4storage[13]; final t3 = _m4storage[2] * tx + _m4storage[6] * ty + _m4storage[10] * tz + - _m4storage[14] * tw; + _m4storage[14]; final t4 = _m4storage[3] * tx + _m4storage[7] * ty + _m4storage[11] * tz + - _m4storage[15] * tw; + _m4storage[15]; _m4storage[12] = t1; _m4storage[13] = t2; _m4storage[14] = t3; @@ -760,27 +766,83 @@ class Matrix4 { } /// Multiply this by a translation from the left. - /// The translation can be specified with a [Vector3], [Vector4], or x, y, z. + /// + /// The translation can be specified with a [Vector3], [Vector4], or x, y, z + /// as [double]s. + /// + /// If you know the argument types in a call site, prefer + /// [leftTranslateByDouble], [leftTranslateByVector3], or + /// [leftTranslateByVector4] for performance. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) { - double tx; - double ty; - double tz; - final tw = x is Vector4 ? x.w : 1.0; if (x is Vector3) { - tx = x.x; - ty = x.y; - tz = x.z; + leftTranslateByVector3(x); } else if (x is Vector4) { - tx = x.x; - ty = x.y; - tz = x.z; + leftTranslateByVector4(x); } else if (x is double) { - tx = x; - ty = y; - tz = z; + leftTranslateByDouble(x, y, z); } else { throw UnimplementedError(); } + } + + /// Multiply this by a translation from the left. + void leftTranslateByDouble(double tx, double ty, double tz) { + // Column 1 + _m4storage[0] += tx * _m4storage[3]; + _m4storage[1] += ty * _m4storage[3]; + _m4storage[2] += tz * _m4storage[3]; + + // Column 2 + _m4storage[4] += tx * _m4storage[7]; + _m4storage[5] += ty * _m4storage[7]; + _m4storage[6] += tz * _m4storage[7]; + + // Column 3 + _m4storage[8] += tx * _m4storage[11]; + _m4storage[9] += ty * _m4storage[11]; + _m4storage[10] += tz * _m4storage[11]; + + // Column 4 + _m4storage[12] += tx * _m4storage[15]; + _m4storage[13] += ty * _m4storage[15]; + _m4storage[14] += tz * _m4storage[15]; + } + + /// Multiply this by a translation from the left. + void leftTranslateByVector3(Vector3 v3) { + final tx = v3.x; + final ty = v3.y; + final tz = v3.z; + + // Column 1 + _m4storage[0] += tx * _m4storage[3]; + _m4storage[1] += ty * _m4storage[3]; + _m4storage[2] += tz * _m4storage[3]; + + // Column 2 + _m4storage[4] += tx * _m4storage[7]; + _m4storage[5] += ty * _m4storage[7]; + _m4storage[6] += tz * _m4storage[7]; + + // Column 3 + _m4storage[8] += tx * _m4storage[11]; + _m4storage[9] += ty * _m4storage[11]; + _m4storage[10] += tz * _m4storage[11]; + + // Column 4 + _m4storage[12] += tx * _m4storage[15]; + _m4storage[13] += ty * _m4storage[15]; + _m4storage[14] += tz * _m4storage[15]; + } + + /// Multiply this by a translation from the left. + void leftTranslateByVector4(Vector4 v4) { + final tx = v4.x; + final ty = v4.y; + final tz = v4.z; + final tw = v4.w; // Column 1 _m4storage[0] += tx * _m4storage[3]; diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index 21d6646d..fb4ca565 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -638,6 +638,14 @@ class Matrix4 { Matrix4 operator -() => clone()..negate(); /// Returns a new vector or matrix by multiplying this with [arg]. + /// + /// [arg] should be a [double] (to scale), [Vector4] (to transform), [Vector3] + /// (to transform), or [Matrix4] (to multiply). + /// + /// If you know the argument type in a call site, prefer [scaled], + /// [transformed], [transformed3], or [multiplied] for performance. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') dynamic operator *(dynamic arg) { if (arg is double) { return scaled(arg); @@ -660,71 +668,42 @@ class Matrix4 { /// Returns new matrix after component wise this - [arg] Matrix4 operator -(Matrix4 arg) => clone()..sub(arg); - /// Translate this matrix by a [Vector3], [Vector4], or x,y,z + /// Translate this matrix by a [Vector3], [Vector4], or x,y,z as [double]s. /// /// If you know the argument types in a call site, prefer [translateByDouble], /// [translateByVector3], or [translateByVector4] for performance. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') void translate(dynamic x, [double y = 0.0, double z = 0.0]) { - double tx; - double ty; - double tz; - final tw = x is Vector4 ? x.w : 1.0; if (x is Vector3) { - tx = x.x; - ty = x.y; - tz = x.z; + return translateByVector3(x); } else if (x is Vector4) { - tx = x.x; - ty = x.y; - tz = x.z; + return translateByVector4(x); } else if (x is double) { - tx = x; - ty = y; - tz = z; + return translateByDouble(x, y, z); } else { throw UnimplementedError(); } - final t1 = _m4storage[0] * tx + - _m4storage[4] * ty + - _m4storage[8] * tz + - _m4storage[12] * tw; - final t2 = _m4storage[1] * tx + - _m4storage[5] * ty + - _m4storage[9] * tz + - _m4storage[13] * tw; - final t3 = _m4storage[2] * tx + - _m4storage[6] * ty + - _m4storage[10] * tz + - _m4storage[14] * tw; - final t4 = _m4storage[3] * tx + - _m4storage[7] * ty + - _m4storage[11] * tz + - _m4storage[15] * tw; - _m4storage[12] = t1; - _m4storage[13] = t2; - _m4storage[14] = t3; - _m4storage[15] = t4; } /// Translate this matrix by x, y, z. void translateByDouble(double tx, double ty, double tz) { - final tw = 1.0; final t1 = _m4storage[0] * tx + _m4storage[4] * ty + _m4storage[8] * tz + - _m4storage[12] * tw; + _m4storage[12]; final t2 = _m4storage[1] * tx + _m4storage[5] * ty + _m4storage[9] * tz + - _m4storage[13] * tw; + _m4storage[13]; final t3 = _m4storage[2] * tx + _m4storage[6] * ty + _m4storage[10] * tz + - _m4storage[14] * tw; + _m4storage[14]; final t4 = _m4storage[3] * tx + _m4storage[7] * ty + _m4storage[11] * tz + - _m4storage[15] * tw; + _m4storage[15]; _m4storage[12] = t1; _m4storage[13] = t2; _m4storage[14] = t3; @@ -736,23 +715,22 @@ class Matrix4 { final tx = v3.x; final ty = v3.y; final tz = v3.z; - final tw = 1.0; final t1 = _m4storage[0] * tx + _m4storage[4] * ty + _m4storage[8] * tz + - _m4storage[12] * tw; + _m4storage[12]; final t2 = _m4storage[1] * tx + _m4storage[5] * ty + _m4storage[9] * tz + - _m4storage[13] * tw; + _m4storage[13]; final t3 = _m4storage[2] * tx + _m4storage[6] * ty + _m4storage[10] * tz + - _m4storage[14] * tw; + _m4storage[14]; final t4 = _m4storage[3] * tx + _m4storage[7] * ty + _m4storage[11] * tz + - _m4storage[15] * tw; + _m4storage[15]; _m4storage[12] = t1; _m4storage[13] = t2; _m4storage[14] = t3; @@ -788,27 +766,83 @@ class Matrix4 { } /// Multiply this by a translation from the left. - /// The translation can be specified with a [Vector3], [Vector4], or x, y, z. + /// + /// The translation can be specified with a [Vector3], [Vector4], or x, y, z + /// as [double]s. + /// + /// If you know the argument types in a call site, prefer + /// [leftTranslateByDouble], [leftTranslateByVector3], or + /// [leftTranslateByVector4] for performance. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) { - double tx; - double ty; - double tz; - final tw = x is Vector4 ? x.w : 1.0; if (x is Vector3) { - tx = x.x; - ty = x.y; - tz = x.z; + leftTranslateByVector3(x); } else if (x is Vector4) { - tx = x.x; - ty = x.y; - tz = x.z; + leftTranslateByVector4(x); } else if (x is double) { - tx = x; - ty = y; - tz = z; + leftTranslateByDouble(x, y, z); } else { throw UnimplementedError(); } + } + + /// Multiply this by a translation from the left. + void leftTranslateByDouble(double tx, double ty, double tz) { + // Column 1 + _m4storage[0] += tx * _m4storage[3]; + _m4storage[1] += ty * _m4storage[3]; + _m4storage[2] += tz * _m4storage[3]; + + // Column 2 + _m4storage[4] += tx * _m4storage[7]; + _m4storage[5] += ty * _m4storage[7]; + _m4storage[6] += tz * _m4storage[7]; + + // Column 3 + _m4storage[8] += tx * _m4storage[11]; + _m4storage[9] += ty * _m4storage[11]; + _m4storage[10] += tz * _m4storage[11]; + + // Column 4 + _m4storage[12] += tx * _m4storage[15]; + _m4storage[13] += ty * _m4storage[15]; + _m4storage[14] += tz * _m4storage[15]; + } + + /// Multiply this by a translation from the left. + void leftTranslateByVector3(Vector3 v3) { + final tx = v3.x; + final ty = v3.y; + final tz = v3.z; + + // Column 1 + _m4storage[0] += tx * _m4storage[3]; + _m4storage[1] += ty * _m4storage[3]; + _m4storage[2] += tz * _m4storage[3]; + + // Column 2 + _m4storage[4] += tx * _m4storage[7]; + _m4storage[5] += ty * _m4storage[7]; + _m4storage[6] += tz * _m4storage[7]; + + // Column 3 + _m4storage[8] += tx * _m4storage[11]; + _m4storage[9] += ty * _m4storage[11]; + _m4storage[10] += tz * _m4storage[11]; + + // Column 4 + _m4storage[12] += tx * _m4storage[15]; + _m4storage[13] += ty * _m4storage[15]; + _m4storage[14] += tz * _m4storage[15]; + } + + /// Multiply this by a translation from the left. + void leftTranslateByVector4(Vector4 v4) { + final tx = v4.x; + final ty = v4.y; + final tz = v4.z; + final tw = v4.w; // Column 1 _m4storage[0] += tx * _m4storage[3]; From e22dead64d2c86cb27ff90daa809d6cdce35a7f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 30 Apr 2025 11:35:19 +0100 Subject: [PATCH 07/21] Do the same for scale --- lib/src/vector_math/matrix4.dart | 66 +++++++++++++++++++++++------ lib/src/vector_math_64/matrix4.dart | 66 +++++++++++++++++++++++------ 2 files changed, 104 insertions(+), 28 deletions(-) diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index 97205f08..3aba0cae 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -982,27 +982,63 @@ class Matrix4 { _m4storage[7] = t8; } - /// Scale this matrix by a [Vector3], [Vector4], or x,y,z + /// Scale this matrix by a [Vector3], [Vector4], or x,y,z as [double]s. + /// + /// If you know the argument types in a call site, prefer [scaleByDouble], + /// [scaleByVector3], or [scaleByVector4] for performance. void scale(dynamic x, [double? y, double? z]) { - double sx; - double sy; - double sz; - final sw = x is Vector4 ? x.w : 1.0; if (x is Vector3) { - sx = x.x; - sy = x.y; - sz = x.z; + scaleByVector3(x); } else if (x is Vector4) { - sx = x.x; - sy = x.y; - sz = x.z; + scaleByVector4(x); } else if (x is double) { - sx = x; - sy = y ?? x; - sz = z ?? x; + scaleByDouble(x, y ?? x, z ?? x); } else { throw UnimplementedError(); } + } + + /// Scale this matrix. + void scaleByDouble(double sx, double sy, double sz) { + _m4storage[0] *= sx; + _m4storage[1] *= sx; + _m4storage[2] *= sx; + _m4storage[3] *= sx; + _m4storage[4] *= sy; + _m4storage[5] *= sy; + _m4storage[6] *= sy; + _m4storage[7] *= sy; + _m4storage[8] *= sz; + _m4storage[9] *= sz; + _m4storage[10] *= sz; + _m4storage[11] *= sz; + } + + /// Scale this matrix. + void scaleByVector3(Vector3 v3) { + final sx = v3.x; + final sy = v3.y; + final sz = v3.z; + _m4storage[0] *= sx; + _m4storage[1] *= sx; + _m4storage[2] *= sx; + _m4storage[3] *= sx; + _m4storage[4] *= sy; + _m4storage[5] *= sy; + _m4storage[6] *= sy; + _m4storage[7] *= sy; + _m4storage[8] *= sz; + _m4storage[9] *= sz; + _m4storage[10] *= sz; + _m4storage[11] *= sz; + } + + /// Scale this matrix. + void scaleByVector4(Vector4 v4) { + final sx = v4.x; + final sy = v4.y; + final sz = v4.z; + final sw = v4.w; _m4storage[0] *= sx; _m4storage[1] *= sx; _m4storage[2] *= sx; @@ -1023,6 +1059,8 @@ class Matrix4 { /// Create a copy of this scaled by a [Vector3], [Vector4] or [x],[y], and /// [z]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') Matrix4 scaled(dynamic x, [double? y, double? z]) => clone()..scale(x, y, z); /// Zeros this. diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index fb4ca565..b6837a0e 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -982,27 +982,63 @@ class Matrix4 { _m4storage[7] = t8; } - /// Scale this matrix by a [Vector3], [Vector4], or x,y,z + /// Scale this matrix by a [Vector3], [Vector4], or x,y,z as [double]s. + /// + /// If you know the argument types in a call site, prefer [scaleByDouble], + /// [scaleByVector3], or [scaleByVector4] for performance. void scale(dynamic x, [double? y, double? z]) { - double sx; - double sy; - double sz; - final sw = x is Vector4 ? x.w : 1.0; if (x is Vector3) { - sx = x.x; - sy = x.y; - sz = x.z; + scaleByVector3(x); } else if (x is Vector4) { - sx = x.x; - sy = x.y; - sz = x.z; + scaleByVector4(x); } else if (x is double) { - sx = x; - sy = y ?? x; - sz = z ?? x; + scaleByDouble(x, y ?? x, z ?? x); } else { throw UnimplementedError(); } + } + + /// Scale this matrix. + void scaleByDouble(double sx, double sy, double sz) { + _m4storage[0] *= sx; + _m4storage[1] *= sx; + _m4storage[2] *= sx; + _m4storage[3] *= sx; + _m4storage[4] *= sy; + _m4storage[5] *= sy; + _m4storage[6] *= sy; + _m4storage[7] *= sy; + _m4storage[8] *= sz; + _m4storage[9] *= sz; + _m4storage[10] *= sz; + _m4storage[11] *= sz; + } + + /// Scale this matrix. + void scaleByVector3(Vector3 v3) { + final sx = v3.x; + final sy = v3.y; + final sz = v3.z; + _m4storage[0] *= sx; + _m4storage[1] *= sx; + _m4storage[2] *= sx; + _m4storage[3] *= sx; + _m4storage[4] *= sy; + _m4storage[5] *= sy; + _m4storage[6] *= sy; + _m4storage[7] *= sy; + _m4storage[8] *= sz; + _m4storage[9] *= sz; + _m4storage[10] *= sz; + _m4storage[11] *= sz; + } + + /// Scale this matrix. + void scaleByVector4(Vector4 v4) { + final sx = v4.x; + final sy = v4.y; + final sz = v4.z; + final sw = v4.w; _m4storage[0] *= sx; _m4storage[1] *= sx; _m4storage[2] *= sx; @@ -1023,6 +1059,8 @@ class Matrix4 { /// Create a copy of this scaled by a [Vector3], [Vector4] or [x],[y], and /// [z]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') Matrix4 scaled(dynamic x, [double? y, double? z]) => clone()..scale(x, y, z); /// Zeros this. From 2973dd65ce17c45d977303591a416e4548def386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 30 Apr 2025 11:38:52 +0100 Subject: [PATCH 08/21] Add missing inlines --- lib/src/vector_math/matrix2.dart | 2 ++ lib/src/vector_math/matrix3.dart | 2 ++ lib/src/vector_math/matrix4.dart | 2 ++ lib/src/vector_math_64/matrix2.dart | 2 ++ lib/src/vector_math_64/matrix3.dart | 2 ++ lib/src/vector_math_64/matrix4.dart | 2 ++ 6 files changed, 12 insertions(+) diff --git a/lib/src/vector_math/matrix2.dart b/lib/src/vector_math/matrix2.dart index 50bb87f1..5367d762 100644 --- a/lib/src/vector_math/matrix2.dart +++ b/lib/src/vector_math/matrix2.dart @@ -215,6 +215,8 @@ class Matrix2 { } /// Returns a new vector or matrix by multiplying this with [arg]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') dynamic operator *(dynamic arg) { if (arg is double) { return scaled(arg); diff --git a/lib/src/vector_math/matrix3.dart b/lib/src/vector_math/matrix3.dart index cea8dd0f..e6025794 100644 --- a/lib/src/vector_math/matrix3.dart +++ b/lib/src/vector_math/matrix3.dart @@ -326,6 +326,8 @@ class Matrix3 { } /// Returns a new vector or matrix by multiplying this with [arg]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') dynamic operator *(dynamic arg) { if (arg is double) { return scaled(arg); diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index 3aba0cae..61d7d3ce 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -986,6 +986,8 @@ class Matrix4 { /// /// If you know the argument types in a call site, prefer [scaleByDouble], /// [scaleByVector3], or [scaleByVector4] for performance. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') void scale(dynamic x, [double? y, double? z]) { if (x is Vector3) { scaleByVector3(x); diff --git a/lib/src/vector_math_64/matrix2.dart b/lib/src/vector_math_64/matrix2.dart index e8f3b40c..61a0e0f8 100644 --- a/lib/src/vector_math_64/matrix2.dart +++ b/lib/src/vector_math_64/matrix2.dart @@ -215,6 +215,8 @@ class Matrix2 { } /// Returns a new vector or matrix by multiplying this with [arg]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') dynamic operator *(dynamic arg) { if (arg is double) { return scaled(arg); diff --git a/lib/src/vector_math_64/matrix3.dart b/lib/src/vector_math_64/matrix3.dart index 89892d33..0a2a633d 100644 --- a/lib/src/vector_math_64/matrix3.dart +++ b/lib/src/vector_math_64/matrix3.dart @@ -326,6 +326,8 @@ class Matrix3 { } /// Returns a new vector or matrix by multiplying this with [arg]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') dynamic operator *(dynamic arg) { if (arg is double) { return scaled(arg); diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index b6837a0e..bdc38ec8 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -986,6 +986,8 @@ class Matrix4 { /// /// If you know the argument types in a call site, prefer [scaleByDouble], /// [scaleByVector3], or [scaleByVector4] for performance. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') void scale(dynamic x, [double? y, double? z]) { if (x is Vector3) { scaleByVector3(x); From 3077223b030a128db3df5096af5ea035b60cafc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 30 Apr 2025 11:53:03 +0100 Subject: [PATCH 09/21] Bump version, update changelog --- CHANGELOG.md | 14 ++++++++++++++ pubspec.yaml | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fc07278..9666619f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## 2.2.0-wip + +- Performance of functions that take `dynamic` arguments improved. +- New `Matrix4` members added with precise argument types (instead of + `dynamic`), with better performance: + - `Matrix4.scaleByDouble`, `Matrix4.scaleByVector3`, `Matrix4.scaleByVector4` + as faster `Matrix4.scale`. + - `Matrix4.translateByDouble`, `Matrix4.translateByVector3`, + `Matrix4.translateByVector4` as faster `Matrix4.translate`. + - `Matrix4.leftTranslateByDouble`, `Matrix4.leftTranslateByVector3`, + `Matrix4.leftTranslateByVector4` as faster `Matrix4.leftTranslate`. + These new functions should be preferred over the old ones when the argument + type is known at a call site. + ## 2.1.5 - Fixed `operator -()` of Quaternion (Contributed by tlserver) diff --git a/pubspec.yaml b/pubspec.yaml index 69f40984..162d06c0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: vector_math -version: 2.1.5 +version: 2.2.0-wip description: A Vector Math library for 2D and 3D applications. repository: https://github.com/google/vector_math.dart From cdb4a005747d35492e50e64828ac4f4f9f98e0fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 30 Apr 2025 12:53:13 +0100 Subject: [PATCH 10/21] Remove multiple returns, add dart2js inlines --- lib/src/vector_math/matrix2.dart | 18 +++++++++------- lib/src/vector_math/matrix3.dart | 18 +++++++++------- lib/src/vector_math/matrix4.dart | 33 +++++++++++++++++------------ lib/src/vector_math_64/matrix2.dart | 18 +++++++++------- lib/src/vector_math_64/matrix3.dart | 18 +++++++++------- lib/src/vector_math_64/matrix4.dart | 33 +++++++++++++++++------------ 6 files changed, 78 insertions(+), 60 deletions(-) diff --git a/lib/src/vector_math/matrix2.dart b/lib/src/vector_math/matrix2.dart index 5367d762..8711a27b 100644 --- a/lib/src/vector_math/matrix2.dart +++ b/lib/src/vector_math/matrix2.dart @@ -217,17 +217,19 @@ class Matrix2 { /// Returns a new vector or matrix by multiplying this with [arg]. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { + final dynamic value; if (arg is double) { - return scaled(arg); - } - if (arg is Vector2) { - return transformed(arg); - } - if (arg is Matrix2) { - return multiplied(arg); + value = scaled(arg); + } else if (arg is Vector2) { + value = transformed(arg); + } else if (arg is Matrix2) { + value = multiplied(arg); + } else { + throw ArgumentError(arg); } - throw ArgumentError(arg); + return value; } /// Returns new matrix after component wise this + [arg] diff --git a/lib/src/vector_math/matrix3.dart b/lib/src/vector_math/matrix3.dart index e6025794..d9df9b65 100644 --- a/lib/src/vector_math/matrix3.dart +++ b/lib/src/vector_math/matrix3.dart @@ -328,17 +328,19 @@ class Matrix3 { /// Returns a new vector or matrix by multiplying this with [arg]. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { + final dynamic value; if (arg is double) { - return scaled(arg); - } - if (arg is Vector3) { - return transformed(arg); - } - if (arg is Matrix3) { - return multiplied(arg); + value = scaled(arg); + } else if (arg is Vector3) { + value = transformed(arg); + } else if (arg is Matrix3) { + value = multiplied(arg); + } else { + throw ArgumentError(arg); } - throw ArgumentError(arg); + return value; } /// Returns new matrix after component wise this + [arg] diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index 61d7d3ce..e526d22c 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -646,20 +646,21 @@ class Matrix4 { /// [transformed], [transformed3], or [multiplied] for performance. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { + final dynamic value; if (arg is double) { - return scaled(arg); - } - if (arg is Vector4) { - return transformed(arg); - } - if (arg is Vector3) { - return transformed3(arg); - } - if (arg is Matrix4) { - return multiplied(arg); + value = scaled(arg); + } else if (arg is Vector4) { + value = transformed(arg); + } else if (arg is Vector3) { + value = transformed3(arg); + } else if (arg is Matrix4) { + value = multiplied(arg); + } else { + throw ArgumentError(arg); } - throw ArgumentError(arg); + return value; } /// Returns new matrix after component wise this + [arg] @@ -674,13 +675,14 @@ class Matrix4 { /// [translateByVector3], or [translateByVector4] for performance. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') void translate(dynamic x, [double y = 0.0, double z = 0.0]) { if (x is Vector3) { - return translateByVector3(x); + translateByVector3(x); } else if (x is Vector4) { - return translateByVector4(x); + translateByVector4(x); } else if (x is double) { - return translateByDouble(x, y, z); + translateByDouble(x, y, z); } else { throw UnimplementedError(); } @@ -775,6 +777,7 @@ class Matrix4 { /// [leftTranslateByVector4] for performance. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) { if (x is Vector3) { leftTranslateByVector3(x); @@ -988,6 +991,7 @@ class Matrix4 { /// [scaleByVector3], or [scaleByVector4] for performance. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') void scale(dynamic x, [double? y, double? z]) { if (x is Vector3) { scaleByVector3(x); @@ -1063,6 +1067,7 @@ class Matrix4 { /// [z]. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') Matrix4 scaled(dynamic x, [double? y, double? z]) => clone()..scale(x, y, z); /// Zeros this. diff --git a/lib/src/vector_math_64/matrix2.dart b/lib/src/vector_math_64/matrix2.dart index 61a0e0f8..5d5726b7 100644 --- a/lib/src/vector_math_64/matrix2.dart +++ b/lib/src/vector_math_64/matrix2.dart @@ -217,17 +217,19 @@ class Matrix2 { /// Returns a new vector or matrix by multiplying this with [arg]. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { + final dynamic value; if (arg is double) { - return scaled(arg); - } - if (arg is Vector2) { - return transformed(arg); - } - if (arg is Matrix2) { - return multiplied(arg); + value = scaled(arg); + } else if (arg is Vector2) { + value = transformed(arg); + } else if (arg is Matrix2) { + value = multiplied(arg); + } else { + throw ArgumentError(arg); } - throw ArgumentError(arg); + return value; } /// Returns new matrix after component wise this + [arg] diff --git a/lib/src/vector_math_64/matrix3.dart b/lib/src/vector_math_64/matrix3.dart index 0a2a633d..6d9338b3 100644 --- a/lib/src/vector_math_64/matrix3.dart +++ b/lib/src/vector_math_64/matrix3.dart @@ -328,17 +328,19 @@ class Matrix3 { /// Returns a new vector or matrix by multiplying this with [arg]. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { + final dynamic value; if (arg is double) { - return scaled(arg); - } - if (arg is Vector3) { - return transformed(arg); - } - if (arg is Matrix3) { - return multiplied(arg); + value = scaled(arg); + } else if (arg is Vector3) { + value = transformed(arg); + } else if (arg is Matrix3) { + value = multiplied(arg); + } else { + throw ArgumentError(arg); } - throw ArgumentError(arg); + return value; } /// Returns new matrix after component wise this + [arg] diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index bdc38ec8..ab7e2c0f 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -646,20 +646,21 @@ class Matrix4 { /// [transformed], [transformed3], or [multiplied] for performance. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { + final dynamic value; if (arg is double) { - return scaled(arg); - } - if (arg is Vector4) { - return transformed(arg); - } - if (arg is Vector3) { - return transformed3(arg); - } - if (arg is Matrix4) { - return multiplied(arg); + value = scaled(arg); + } else if (arg is Vector4) { + value = transformed(arg); + } else if (arg is Vector3) { + value = transformed3(arg); + } else if (arg is Matrix4) { + value = multiplied(arg); + } else { + throw ArgumentError(arg); } - throw ArgumentError(arg); + return value; } /// Returns new matrix after component wise this + [arg] @@ -674,13 +675,14 @@ class Matrix4 { /// [translateByVector3], or [translateByVector4] for performance. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') void translate(dynamic x, [double y = 0.0, double z = 0.0]) { if (x is Vector3) { - return translateByVector3(x); + translateByVector3(x); } else if (x is Vector4) { - return translateByVector4(x); + translateByVector4(x); } else if (x is double) { - return translateByDouble(x, y, z); + translateByDouble(x, y, z); } else { throw UnimplementedError(); } @@ -775,6 +777,7 @@ class Matrix4 { /// [leftTranslateByVector4] for performance. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) { if (x is Vector3) { leftTranslateByVector3(x); @@ -988,6 +991,7 @@ class Matrix4 { /// [scaleByVector3], or [scaleByVector4] for performance. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') void scale(dynamic x, [double? y, double? z]) { if (x is Vector3) { scaleByVector3(x); @@ -1063,6 +1067,7 @@ class Matrix4 { /// [z]. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') Matrix4 scaled(dynamic x, [double? y, double? z]) => clone()..scale(x, y, z); /// Zeros this. From 2fd7aabcaad9cd6735fab696aecc8375ea03c2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 30 Apr 2025 13:08:33 +0100 Subject: [PATCH 11/21] Move loads uppp --- lib/src/vector_math/matrix4.dart | 28 +++++++++++++++++++--------- lib/src/vector_math_64/matrix4.dart | 28 +++++++++++++++++++--------- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index e526d22c..007845ba 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -694,21 +694,24 @@ class Matrix4 { _m4storage[4] * ty + _m4storage[8] * tz + _m4storage[12]; + _m4storage[12] = t1; + final t2 = _m4storage[1] * tx + _m4storage[5] * ty + _m4storage[9] * tz + _m4storage[13]; + _m4storage[13] = t2; + final t3 = _m4storage[2] * tx + _m4storage[6] * ty + _m4storage[10] * tz + _m4storage[14]; + _m4storage[14] = t3; + final t4 = _m4storage[3] * tx + _m4storage[7] * ty + _m4storage[11] * tz + _m4storage[15]; - _m4storage[12] = t1; - _m4storage[13] = t2; - _m4storage[14] = t3; _m4storage[15] = t4; } @@ -721,21 +724,24 @@ class Matrix4 { _m4storage[4] * ty + _m4storage[8] * tz + _m4storage[12]; + _m4storage[12] = t1; + final t2 = _m4storage[1] * tx + _m4storage[5] * ty + _m4storage[9] * tz + _m4storage[13]; + _m4storage[13] = t2; + final t3 = _m4storage[2] * tx + _m4storage[6] * ty + _m4storage[10] * tz + _m4storage[14]; + _m4storage[14] = t3; + final t4 = _m4storage[3] * tx + _m4storage[7] * ty + _m4storage[11] * tz + _m4storage[15]; - _m4storage[12] = t1; - _m4storage[13] = t2; - _m4storage[14] = t3; _m4storage[15] = t4; } @@ -745,25 +751,29 @@ class Matrix4 { final ty = v4.y; final tz = v4.z; final tw = v4.w; + final t1 = _m4storage[0] * tx + _m4storage[4] * ty + _m4storage[8] * tz + _m4storage[12] * tw; + _m4storage[12] = t1; + final t2 = _m4storage[1] * tx + _m4storage[5] * ty + _m4storage[9] * tz + _m4storage[13] * tw; + _m4storage[13] = t2; + final t3 = _m4storage[2] * tx + _m4storage[6] * ty + _m4storage[10] * tz + _m4storage[14] * tw; + _m4storage[14] = t3; + final t4 = _m4storage[3] * tx + _m4storage[7] * ty + _m4storage[11] * tz + _m4storage[15] * tw; - _m4storage[12] = t1; - _m4storage[13] = t2; - _m4storage[14] = t3; _m4storage[15] = t4; } diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index ab7e2c0f..dfa4511b 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -694,21 +694,24 @@ class Matrix4 { _m4storage[4] * ty + _m4storage[8] * tz + _m4storage[12]; + _m4storage[12] = t1; + final t2 = _m4storage[1] * tx + _m4storage[5] * ty + _m4storage[9] * tz + _m4storage[13]; + _m4storage[13] = t2; + final t3 = _m4storage[2] * tx + _m4storage[6] * ty + _m4storage[10] * tz + _m4storage[14]; + _m4storage[14] = t3; + final t4 = _m4storage[3] * tx + _m4storage[7] * ty + _m4storage[11] * tz + _m4storage[15]; - _m4storage[12] = t1; - _m4storage[13] = t2; - _m4storage[14] = t3; _m4storage[15] = t4; } @@ -721,21 +724,24 @@ class Matrix4 { _m4storage[4] * ty + _m4storage[8] * tz + _m4storage[12]; + _m4storage[12] = t1; + final t2 = _m4storage[1] * tx + _m4storage[5] * ty + _m4storage[9] * tz + _m4storage[13]; + _m4storage[13] = t2; + final t3 = _m4storage[2] * tx + _m4storage[6] * ty + _m4storage[10] * tz + _m4storage[14]; + _m4storage[14] = t3; + final t4 = _m4storage[3] * tx + _m4storage[7] * ty + _m4storage[11] * tz + _m4storage[15]; - _m4storage[12] = t1; - _m4storage[13] = t2; - _m4storage[14] = t3; _m4storage[15] = t4; } @@ -745,25 +751,29 @@ class Matrix4 { final ty = v4.y; final tz = v4.z; final tw = v4.w; + final t1 = _m4storage[0] * tx + _m4storage[4] * ty + _m4storage[8] * tz + _m4storage[12] * tw; + _m4storage[12] = t1; + final t2 = _m4storage[1] * tx + _m4storage[5] * ty + _m4storage[9] * tz + _m4storage[13] * tw; + _m4storage[13] = t2; + final t3 = _m4storage[2] * tx + _m4storage[6] * ty + _m4storage[10] * tz + _m4storage[14] * tw; + _m4storage[14] = t3; + final t4 = _m4storage[3] * tx + _m4storage[7] * ty + _m4storage[11] * tz + _m4storage[15] * tw; - _m4storage[12] = t1; - _m4storage[13] = t2; - _m4storage[14] = t3; _m4storage[15] = t4; } From d6d34e488d5daf6808c264167a08b41645aa7524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 30 Apr 2025 13:13:40 +0100 Subject: [PATCH 12/21] Store loads in a local --- lib/src/vector_math/matrix4.dart | 92 ++++++++++++++++------------- lib/src/vector_math_64/matrix4.dart | 92 ++++++++++++++++------------- 2 files changed, 104 insertions(+), 80 deletions(-) diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index 007845ba..482ce666 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -803,24 +803,28 @@ class Matrix4 { /// Multiply this by a translation from the left. void leftTranslateByDouble(double tx, double ty, double tz) { // Column 1 - _m4storage[0] += tx * _m4storage[3]; - _m4storage[1] += ty * _m4storage[3]; - _m4storage[2] += tz * _m4storage[3]; + final r1 = _m4storage[3]; + _m4storage[0] += tx * r1; + _m4storage[1] += ty * r1; + _m4storage[2] += tz * r1; // Column 2 - _m4storage[4] += tx * _m4storage[7]; - _m4storage[5] += ty * _m4storage[7]; - _m4storage[6] += tz * _m4storage[7]; + final r2 = _m4storage[7]; + _m4storage[4] += tx * r2; + _m4storage[5] += ty * r2; + _m4storage[6] += tz * r2; // Column 3 - _m4storage[8] += tx * _m4storage[11]; - _m4storage[9] += ty * _m4storage[11]; - _m4storage[10] += tz * _m4storage[11]; + final r3 = _m4storage[11]; + _m4storage[8] += tx * r3; + _m4storage[9] += ty * r3; + _m4storage[10] += tz * r3; // Column 4 - _m4storage[12] += tx * _m4storage[15]; - _m4storage[13] += ty * _m4storage[15]; - _m4storage[14] += tz * _m4storage[15]; + final r4 = _m4storage[15]; + _m4storage[12] += tx * r4; + _m4storage[13] += ty * r4; + _m4storage[14] += tz * r4; } /// Multiply this by a translation from the left. @@ -830,24 +834,28 @@ class Matrix4 { final tz = v3.z; // Column 1 - _m4storage[0] += tx * _m4storage[3]; - _m4storage[1] += ty * _m4storage[3]; - _m4storage[2] += tz * _m4storage[3]; + final r1 = _m4storage[3]; + _m4storage[0] += tx * r1; + _m4storage[1] += ty * r1; + _m4storage[2] += tz * r1; // Column 2 - _m4storage[4] += tx * _m4storage[7]; - _m4storage[5] += ty * _m4storage[7]; - _m4storage[6] += tz * _m4storage[7]; + final r2 = _m4storage[7]; + _m4storage[4] += tx * r2; + _m4storage[5] += ty * r2; + _m4storage[6] += tz * r2; // Column 3 - _m4storage[8] += tx * _m4storage[11]; - _m4storage[9] += ty * _m4storage[11]; - _m4storage[10] += tz * _m4storage[11]; + final r3 = _m4storage[11]; + _m4storage[8] += tx * r3; + _m4storage[9] += ty * r3; + _m4storage[10] += tz * r3; // Column 4 - _m4storage[12] += tx * _m4storage[15]; - _m4storage[13] += ty * _m4storage[15]; - _m4storage[14] += tz * _m4storage[15]; + final r4 = _m4storage[15]; + _m4storage[12] += tx * r4; + _m4storage[13] += ty * r4; + _m4storage[14] += tz * r4; } /// Multiply this by a translation from the left. @@ -858,28 +866,32 @@ class Matrix4 { final tw = v4.w; // Column 1 - _m4storage[0] += tx * _m4storage[3]; - _m4storage[1] += ty * _m4storage[3]; - _m4storage[2] += tz * _m4storage[3]; - _m4storage[3] = tw * _m4storage[3]; + final r1 = _m4storage[3]; + _m4storage[0] += tx * r1; + _m4storage[1] += ty * r1; + _m4storage[2] += tz * r1; + _m4storage[3] = tw * r1; // Column 2 - _m4storage[4] += tx * _m4storage[7]; - _m4storage[5] += ty * _m4storage[7]; - _m4storage[6] += tz * _m4storage[7]; - _m4storage[7] = tw * _m4storage[7]; + final r2 = _m4storage[7]; + _m4storage[4] += tx * r2; + _m4storage[5] += ty * r2; + _m4storage[6] += tz * r2; + _m4storage[7] = tw * r2; // Column 3 - _m4storage[8] += tx * _m4storage[11]; - _m4storage[9] += ty * _m4storage[11]; - _m4storage[10] += tz * _m4storage[11]; - _m4storage[11] = tw * _m4storage[11]; + final r3 = _m4storage[11]; + _m4storage[8] += tx * r3; + _m4storage[9] += ty * r3; + _m4storage[10] += tz * r3; + _m4storage[11] = tw * r3; // Column 4 - _m4storage[12] += tx * _m4storage[15]; - _m4storage[13] += ty * _m4storage[15]; - _m4storage[14] += tz * _m4storage[15]; - _m4storage[15] = tw * _m4storage[15]; + final r4 = _m4storage[15]; + _m4storage[12] += tx * r4; + _m4storage[13] += ty * r4; + _m4storage[14] += tz * r4; + _m4storage[15] = tw * r4; } /// Rotate this [angle] radians around [axis] diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index dfa4511b..635ae2b6 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -803,24 +803,28 @@ class Matrix4 { /// Multiply this by a translation from the left. void leftTranslateByDouble(double tx, double ty, double tz) { // Column 1 - _m4storage[0] += tx * _m4storage[3]; - _m4storage[1] += ty * _m4storage[3]; - _m4storage[2] += tz * _m4storage[3]; + final r1 = _m4storage[3]; + _m4storage[0] += tx * r1; + _m4storage[1] += ty * r1; + _m4storage[2] += tz * r1; // Column 2 - _m4storage[4] += tx * _m4storage[7]; - _m4storage[5] += ty * _m4storage[7]; - _m4storage[6] += tz * _m4storage[7]; + final r2 = _m4storage[7]; + _m4storage[4] += tx * r2; + _m4storage[5] += ty * r2; + _m4storage[6] += tz * r2; // Column 3 - _m4storage[8] += tx * _m4storage[11]; - _m4storage[9] += ty * _m4storage[11]; - _m4storage[10] += tz * _m4storage[11]; + final r3 = _m4storage[11]; + _m4storage[8] += tx * r3; + _m4storage[9] += ty * r3; + _m4storage[10] += tz * r3; // Column 4 - _m4storage[12] += tx * _m4storage[15]; - _m4storage[13] += ty * _m4storage[15]; - _m4storage[14] += tz * _m4storage[15]; + final r4 = _m4storage[15]; + _m4storage[12] += tx * r4; + _m4storage[13] += ty * r4; + _m4storage[14] += tz * r4; } /// Multiply this by a translation from the left. @@ -830,24 +834,28 @@ class Matrix4 { final tz = v3.z; // Column 1 - _m4storage[0] += tx * _m4storage[3]; - _m4storage[1] += ty * _m4storage[3]; - _m4storage[2] += tz * _m4storage[3]; + final r1 = _m4storage[3]; + _m4storage[0] += tx * r1; + _m4storage[1] += ty * r1; + _m4storage[2] += tz * r1; // Column 2 - _m4storage[4] += tx * _m4storage[7]; - _m4storage[5] += ty * _m4storage[7]; - _m4storage[6] += tz * _m4storage[7]; + final r2 = _m4storage[7]; + _m4storage[4] += tx * r2; + _m4storage[5] += ty * r2; + _m4storage[6] += tz * r2; // Column 3 - _m4storage[8] += tx * _m4storage[11]; - _m4storage[9] += ty * _m4storage[11]; - _m4storage[10] += tz * _m4storage[11]; + final r3 = _m4storage[11]; + _m4storage[8] += tx * r3; + _m4storage[9] += ty * r3; + _m4storage[10] += tz * r3; // Column 4 - _m4storage[12] += tx * _m4storage[15]; - _m4storage[13] += ty * _m4storage[15]; - _m4storage[14] += tz * _m4storage[15]; + final r4 = _m4storage[15]; + _m4storage[12] += tx * r4; + _m4storage[13] += ty * r4; + _m4storage[14] += tz * r4; } /// Multiply this by a translation from the left. @@ -858,28 +866,32 @@ class Matrix4 { final tw = v4.w; // Column 1 - _m4storage[0] += tx * _m4storage[3]; - _m4storage[1] += ty * _m4storage[3]; - _m4storage[2] += tz * _m4storage[3]; - _m4storage[3] = tw * _m4storage[3]; + final r1 = _m4storage[3]; + _m4storage[0] += tx * r1; + _m4storage[1] += ty * r1; + _m4storage[2] += tz * r1; + _m4storage[3] = tw * r1; // Column 2 - _m4storage[4] += tx * _m4storage[7]; - _m4storage[5] += ty * _m4storage[7]; - _m4storage[6] += tz * _m4storage[7]; - _m4storage[7] = tw * _m4storage[7]; + final r2 = _m4storage[7]; + _m4storage[4] += tx * r2; + _m4storage[5] += ty * r2; + _m4storage[6] += tz * r2; + _m4storage[7] = tw * r2; // Column 3 - _m4storage[8] += tx * _m4storage[11]; - _m4storage[9] += ty * _m4storage[11]; - _m4storage[10] += tz * _m4storage[11]; - _m4storage[11] = tw * _m4storage[11]; + final r3 = _m4storage[11]; + _m4storage[8] += tx * r3; + _m4storage[9] += ty * r3; + _m4storage[10] += tz * r3; + _m4storage[11] = tw * r3; // Column 4 - _m4storage[12] += tx * _m4storage[15]; - _m4storage[13] += ty * _m4storage[15]; - _m4storage[14] += tz * _m4storage[15]; - _m4storage[15] = tw * _m4storage[15]; + final r4 = _m4storage[15]; + _m4storage[12] += tx * r4; + _m4storage[13] += ty * r4; + _m4storage[14] += tz * r4; + _m4storage[15] = tw * r4; } /// Rotate this [angle] radians around [axis] From 2fa9abcfa3fe8b5aabb568e7ea74dd943e0a9cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Wed, 30 Apr 2025 13:25:34 +0100 Subject: [PATCH 13/21] Call double fns --- benchmark/matrix_bench.dart | 4 +- lib/src/vector_math/matrix4.dart | 167 +++++++--------------------- lib/src/vector_math_64/matrix4.dart | 167 +++++++--------------------- test/matrix4_test.dart | 2 +- 4 files changed, 79 insertions(+), 261 deletions(-) diff --git a/benchmark/matrix_bench.dart b/benchmark/matrix_bench.dart index 48fb5238..c5dfb5a4 100644 --- a/benchmark/matrix_bench.dart +++ b/benchmark/matrix_bench.dart @@ -393,14 +393,14 @@ class Matrix4TranslateByDoubleBenchmark extends BenchmarkBase { void setup() { for (var i = 0; i < 10; i++) { temp.translateByDouble( - i.toDouble(), (i * 10).toDouble(), (i * 5).toDouble()); + i.toDouble(), (i * 10).toDouble(), (i * 5).toDouble(), 1.0); } } @override void run() { for (var i = 0; i < 100; i++) { - temp.translateByDouble(10.0, 20.0, 30.0); + temp.translateByDouble(10.0, 20.0, 30.0, 1.0); } } } diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index 482ce666..c9382874 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -682,76 +682,17 @@ class Matrix4 { } else if (x is Vector4) { translateByVector4(x); } else if (x is double) { - translateByDouble(x, y, z); + translateByDouble(x, y, z, 1.0); } else { throw UnimplementedError(); } } /// Translate this matrix by x, y, z. - void translateByDouble(double tx, double ty, double tz) { - final t1 = _m4storage[0] * tx + - _m4storage[4] * ty + - _m4storage[8] * tz + - _m4storage[12]; - _m4storage[12] = t1; - - final t2 = _m4storage[1] * tx + - _m4storage[5] * ty + - _m4storage[9] * tz + - _m4storage[13]; - _m4storage[13] = t2; - - final t3 = _m4storage[2] * tx + - _m4storage[6] * ty + - _m4storage[10] * tz + - _m4storage[14]; - _m4storage[14] = t3; - - final t4 = _m4storage[3] * tx + - _m4storage[7] * ty + - _m4storage[11] * tz + - _m4storage[15]; - _m4storage[15] = t4; - } - - /// Translate this matrix by a [Vector3]. - void translateByVector3(Vector3 v3) { - final tx = v3.x; - final ty = v3.y; - final tz = v3.z; - final t1 = _m4storage[0] * tx + - _m4storage[4] * ty + - _m4storage[8] * tz + - _m4storage[12]; - _m4storage[12] = t1; - - final t2 = _m4storage[1] * tx + - _m4storage[5] * ty + - _m4storage[9] * tz + - _m4storage[13]; - _m4storage[13] = t2; - - final t3 = _m4storage[2] * tx + - _m4storage[6] * ty + - _m4storage[10] * tz + - _m4storage[14]; - _m4storage[14] = t3; - - final t4 = _m4storage[3] * tx + - _m4storage[7] * ty + - _m4storage[11] * tz + - _m4storage[15]; - _m4storage[15] = t4; - } - - /// Translate this matrix by a [Vector4]. - void translateByVector4(Vector4 v4) { - final tx = v4.x; - final ty = v4.y; - final tz = v4.z; - final tw = v4.w; - + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void translateByDouble(double tx, double ty, double tz, double tw) { final t1 = _m4storage[0] * tx + _m4storage[4] * ty + _m4storage[8] * tz + @@ -777,6 +718,20 @@ class Matrix4 { _m4storage[15] = t4; } + /// Translate this matrix by a [Vector3]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void translateByVector3(Vector3 v3) => + translateByDouble(v3.x, v3.y, v3.z, 1.0); + + /// Translate this matrix by a [Vector4]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void translateByVector4(Vector4 v4) => + translateByDouble(v4.x, v4.y, v4.z, v4.w); + /// Multiply this by a translation from the left. /// /// The translation can be specified with a [Vector3], [Vector4], or x, y, z @@ -794,77 +749,17 @@ class Matrix4 { } else if (x is Vector4) { leftTranslateByVector4(x); } else if (x is double) { - leftTranslateByDouble(x, y, z); + leftTranslateByDouble(x, y, z, 1.0); } else { throw UnimplementedError(); } } /// Multiply this by a translation from the left. - void leftTranslateByDouble(double tx, double ty, double tz) { - // Column 1 - final r1 = _m4storage[3]; - _m4storage[0] += tx * r1; - _m4storage[1] += ty * r1; - _m4storage[2] += tz * r1; - - // Column 2 - final r2 = _m4storage[7]; - _m4storage[4] += tx * r2; - _m4storage[5] += ty * r2; - _m4storage[6] += tz * r2; - - // Column 3 - final r3 = _m4storage[11]; - _m4storage[8] += tx * r3; - _m4storage[9] += ty * r3; - _m4storage[10] += tz * r3; - - // Column 4 - final r4 = _m4storage[15]; - _m4storage[12] += tx * r4; - _m4storage[13] += ty * r4; - _m4storage[14] += tz * r4; - } - - /// Multiply this by a translation from the left. - void leftTranslateByVector3(Vector3 v3) { - final tx = v3.x; - final ty = v3.y; - final tz = v3.z; - - // Column 1 - final r1 = _m4storage[3]; - _m4storage[0] += tx * r1; - _m4storage[1] += ty * r1; - _m4storage[2] += tz * r1; - - // Column 2 - final r2 = _m4storage[7]; - _m4storage[4] += tx * r2; - _m4storage[5] += ty * r2; - _m4storage[6] += tz * r2; - - // Column 3 - final r3 = _m4storage[11]; - _m4storage[8] += tx * r3; - _m4storage[9] += ty * r3; - _m4storage[10] += tz * r3; - - // Column 4 - final r4 = _m4storage[15]; - _m4storage[12] += tx * r4; - _m4storage[13] += ty * r4; - _m4storage[14] += tz * r4; - } - - /// Multiply this by a translation from the left. - void leftTranslateByVector4(Vector4 v4) { - final tx = v4.x; - final ty = v4.y; - final tz = v4.z; - final tw = v4.w; - + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void leftTranslateByDouble(double tx, double ty, double tz, double tw) { // Column 1 final r1 = _m4storage[3]; _m4storage[0] += tx * r1; @@ -894,6 +789,20 @@ class Matrix4 { _m4storage[15] = tw * r4; } + /// Multiply this by a translation from the left. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void leftTranslateByVector3(Vector3 v3) => + leftTranslateByDouble(v3.x, v3.y, v3.z, 1.0); + + /// Multiply this by a translation from the left. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void leftTranslateByVector4(Vector4 v4) => + leftTranslateByDouble(v4.x, v4.y, v4.z, v4.w); + /// Rotate this [angle] radians around [axis] void rotate(Vector3 axis, double angle) { final len = axis.length; diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index 635ae2b6..8aa8b10b 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -682,76 +682,17 @@ class Matrix4 { } else if (x is Vector4) { translateByVector4(x); } else if (x is double) { - translateByDouble(x, y, z); + translateByDouble(x, y, z, 1.0); } else { throw UnimplementedError(); } } /// Translate this matrix by x, y, z. - void translateByDouble(double tx, double ty, double tz) { - final t1 = _m4storage[0] * tx + - _m4storage[4] * ty + - _m4storage[8] * tz + - _m4storage[12]; - _m4storage[12] = t1; - - final t2 = _m4storage[1] * tx + - _m4storage[5] * ty + - _m4storage[9] * tz + - _m4storage[13]; - _m4storage[13] = t2; - - final t3 = _m4storage[2] * tx + - _m4storage[6] * ty + - _m4storage[10] * tz + - _m4storage[14]; - _m4storage[14] = t3; - - final t4 = _m4storage[3] * tx + - _m4storage[7] * ty + - _m4storage[11] * tz + - _m4storage[15]; - _m4storage[15] = t4; - } - - /// Translate this matrix by a [Vector3]. - void translateByVector3(Vector3 v3) { - final tx = v3.x; - final ty = v3.y; - final tz = v3.z; - final t1 = _m4storage[0] * tx + - _m4storage[4] * ty + - _m4storage[8] * tz + - _m4storage[12]; - _m4storage[12] = t1; - - final t2 = _m4storage[1] * tx + - _m4storage[5] * ty + - _m4storage[9] * tz + - _m4storage[13]; - _m4storage[13] = t2; - - final t3 = _m4storage[2] * tx + - _m4storage[6] * ty + - _m4storage[10] * tz + - _m4storage[14]; - _m4storage[14] = t3; - - final t4 = _m4storage[3] * tx + - _m4storage[7] * ty + - _m4storage[11] * tz + - _m4storage[15]; - _m4storage[15] = t4; - } - - /// Translate this matrix by a [Vector4]. - void translateByVector4(Vector4 v4) { - final tx = v4.x; - final ty = v4.y; - final tz = v4.z; - final tw = v4.w; - + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void translateByDouble(double tx, double ty, double tz, double tw) { final t1 = _m4storage[0] * tx + _m4storage[4] * ty + _m4storage[8] * tz + @@ -777,6 +718,20 @@ class Matrix4 { _m4storage[15] = t4; } + /// Translate this matrix by a [Vector3]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void translateByVector3(Vector3 v3) => + translateByDouble(v3.x, v3.y, v3.z, 1.0); + + /// Translate this matrix by a [Vector4]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void translateByVector4(Vector4 v4) => + translateByDouble(v4.x, v4.y, v4.z, v4.w); + /// Multiply this by a translation from the left. /// /// The translation can be specified with a [Vector3], [Vector4], or x, y, z @@ -794,77 +749,17 @@ class Matrix4 { } else if (x is Vector4) { leftTranslateByVector4(x); } else if (x is double) { - leftTranslateByDouble(x, y, z); + leftTranslateByDouble(x, y, z, 1.0); } else { throw UnimplementedError(); } } /// Multiply this by a translation from the left. - void leftTranslateByDouble(double tx, double ty, double tz) { - // Column 1 - final r1 = _m4storage[3]; - _m4storage[0] += tx * r1; - _m4storage[1] += ty * r1; - _m4storage[2] += tz * r1; - - // Column 2 - final r2 = _m4storage[7]; - _m4storage[4] += tx * r2; - _m4storage[5] += ty * r2; - _m4storage[6] += tz * r2; - - // Column 3 - final r3 = _m4storage[11]; - _m4storage[8] += tx * r3; - _m4storage[9] += ty * r3; - _m4storage[10] += tz * r3; - - // Column 4 - final r4 = _m4storage[15]; - _m4storage[12] += tx * r4; - _m4storage[13] += ty * r4; - _m4storage[14] += tz * r4; - } - - /// Multiply this by a translation from the left. - void leftTranslateByVector3(Vector3 v3) { - final tx = v3.x; - final ty = v3.y; - final tz = v3.z; - - // Column 1 - final r1 = _m4storage[3]; - _m4storage[0] += tx * r1; - _m4storage[1] += ty * r1; - _m4storage[2] += tz * r1; - - // Column 2 - final r2 = _m4storage[7]; - _m4storage[4] += tx * r2; - _m4storage[5] += ty * r2; - _m4storage[6] += tz * r2; - - // Column 3 - final r3 = _m4storage[11]; - _m4storage[8] += tx * r3; - _m4storage[9] += ty * r3; - _m4storage[10] += tz * r3; - - // Column 4 - final r4 = _m4storage[15]; - _m4storage[12] += tx * r4; - _m4storage[13] += ty * r4; - _m4storage[14] += tz * r4; - } - - /// Multiply this by a translation from the left. - void leftTranslateByVector4(Vector4 v4) { - final tx = v4.x; - final ty = v4.y; - final tz = v4.z; - final tw = v4.w; - + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void leftTranslateByDouble(double tx, double ty, double tz, double tw) { // Column 1 final r1 = _m4storage[3]; _m4storage[0] += tx * r1; @@ -894,6 +789,20 @@ class Matrix4 { _m4storage[15] = tw * r4; } + /// Multiply this by a translation from the left. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void leftTranslateByVector3(Vector3 v3) => + leftTranslateByDouble(v3.x, v3.y, v3.z, 1.0); + + /// Multiply this by a translation from the left. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void leftTranslateByVector4(Vector4 v4) => + leftTranslateByDouble(v4.x, v4.y, v4.z, v4.w); + /// Rotate this [angle] radians around [axis] void rotate(Vector3 axis, double angle) { final len = axis.length; diff --git a/test/matrix4_test.dart b/test/matrix4_test.dart index 82d8bb70..480f7a08 100644 --- a/test/matrix4_test.dart +++ b/test/matrix4_test.dart @@ -385,7 +385,7 @@ void testMatrix4Translation() { output3[14] = input.dotRow(2, Vector4(4, 8, 12, 1)); output3[15] = input.dotRow(3, Vector4(4, 8, 12, 1)); relativeTest( - input.clone()..translateByDouble(4.0, 8.0, 12.0), + input.clone()..translateByDouble(4.0, 8.0, 12.0, 1.0), output3, ); relativeTest( From 0ea55e563618735a70ca4bcfc73149048f33f9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Thu, 1 May 2025 10:10:41 +0100 Subject: [PATCH 14/21] Rename return value variables as result, types as Object --- lib/src/vector_math/matrix2.dart | 10 +++++----- lib/src/vector_math/matrix3.dart | 10 +++++----- lib/src/vector_math/matrix4.dart | 12 ++++++------ lib/src/vector_math_64/matrix2.dart | 10 +++++----- lib/src/vector_math_64/matrix3.dart | 10 +++++----- lib/src/vector_math_64/matrix4.dart | 12 ++++++------ 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/lib/src/vector_math/matrix2.dart b/lib/src/vector_math/matrix2.dart index 8711a27b..cd102bdc 100644 --- a/lib/src/vector_math/matrix2.dart +++ b/lib/src/vector_math/matrix2.dart @@ -219,17 +219,17 @@ class Matrix2 { @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { - final dynamic value; + final Object result; if (arg is double) { - value = scaled(arg); + result = scaled(arg); } else if (arg is Vector2) { - value = transformed(arg); + result = transformed(arg); } else if (arg is Matrix2) { - value = multiplied(arg); + result = multiplied(arg); } else { throw ArgumentError(arg); } - return value; + return result; } /// Returns new matrix after component wise this + [arg] diff --git a/lib/src/vector_math/matrix3.dart b/lib/src/vector_math/matrix3.dart index d9df9b65..c61208b1 100644 --- a/lib/src/vector_math/matrix3.dart +++ b/lib/src/vector_math/matrix3.dart @@ -330,17 +330,17 @@ class Matrix3 { @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { - final dynamic value; + final Object result; if (arg is double) { - value = scaled(arg); + result = scaled(arg); } else if (arg is Vector3) { - value = transformed(arg); + result = transformed(arg); } else if (arg is Matrix3) { - value = multiplied(arg); + result = multiplied(arg); } else { throw ArgumentError(arg); } - return value; + return result; } /// Returns new matrix after component wise this + [arg] diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index c9382874..597de507 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -648,19 +648,19 @@ class Matrix4 { @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { - final dynamic value; + final Object result; if (arg is double) { - value = scaled(arg); + result = scaled(arg); } else if (arg is Vector4) { - value = transformed(arg); + result = transformed(arg); } else if (arg is Vector3) { - value = transformed3(arg); + result = transformed3(arg); } else if (arg is Matrix4) { - value = multiplied(arg); + result = multiplied(arg); } else { throw ArgumentError(arg); } - return value; + return result; } /// Returns new matrix after component wise this + [arg] diff --git a/lib/src/vector_math_64/matrix2.dart b/lib/src/vector_math_64/matrix2.dart index 5d5726b7..a35be282 100644 --- a/lib/src/vector_math_64/matrix2.dart +++ b/lib/src/vector_math_64/matrix2.dart @@ -219,17 +219,17 @@ class Matrix2 { @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { - final dynamic value; + final Object result; if (arg is double) { - value = scaled(arg); + result = scaled(arg); } else if (arg is Vector2) { - value = transformed(arg); + result = transformed(arg); } else if (arg is Matrix2) { - value = multiplied(arg); + result = multiplied(arg); } else { throw ArgumentError(arg); } - return value; + return result; } /// Returns new matrix after component wise this + [arg] diff --git a/lib/src/vector_math_64/matrix3.dart b/lib/src/vector_math_64/matrix3.dart index 6d9338b3..e5638f9d 100644 --- a/lib/src/vector_math_64/matrix3.dart +++ b/lib/src/vector_math_64/matrix3.dart @@ -330,17 +330,17 @@ class Matrix3 { @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { - final dynamic value; + final Object result; if (arg is double) { - value = scaled(arg); + result = scaled(arg); } else if (arg is Vector3) { - value = transformed(arg); + result = transformed(arg); } else if (arg is Matrix3) { - value = multiplied(arg); + result = multiplied(arg); } else { throw ArgumentError(arg); } - return value; + return result; } /// Returns new matrix after component wise this + [arg] diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index 8aa8b10b..a4a91af2 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -648,19 +648,19 @@ class Matrix4 { @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') dynamic operator *(dynamic arg) { - final dynamic value; + final Object result; if (arg is double) { - value = scaled(arg); + result = scaled(arg); } else if (arg is Vector4) { - value = transformed(arg); + result = transformed(arg); } else if (arg is Vector3) { - value = transformed3(arg); + result = transformed3(arg); } else if (arg is Matrix4) { - value = multiplied(arg); + result = multiplied(arg); } else { throw ArgumentError(arg); } - return value; + return result; } /// Returns new matrix after component wise this + [arg] From 68f5cf9c8c97fe451b20f54391e00da1ed784ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Thu, 1 May 2025 10:48:12 +0100 Subject: [PATCH 15/21] First round of deprecations --- benchmark/matrix_bench.dart | 2 + lib/src/vector_math/matrix4.dart | 89 +++++++++++++++-------------- lib/src/vector_math/opengl.dart | 2 +- lib/src/vector_math_64/matrix4.dart | 89 +++++++++++++++-------------- lib/src/vector_math_64/opengl.dart | 2 +- test/geometry_test.dart | 2 + test/matrix4_test.dart | 2 + 7 files changed, 98 insertions(+), 90 deletions(-) diff --git a/benchmark/matrix_bench.dart b/benchmark/matrix_bench.dart index c5dfb5a4..3cc7ddd6 100644 --- a/benchmark/matrix_bench.dart +++ b/benchmark/matrix_bench.dart @@ -2,6 +2,8 @@ // All rights reserved. Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:math' as math; import 'dart:typed_data'; diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index 597de507..1ea55c89 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -461,7 +461,7 @@ class Matrix4 { void setFromTranslationRotationScale( Vector3 translation, Quaternion rotation, Vector3 scale) { setFromTranslationRotation(translation, rotation); - this.scale(scale); + scaleByVector3(scale); } /// Sets the upper 2x2 of the matrix to be [arg]. @@ -642,7 +642,7 @@ class Matrix4 { /// [arg] should be a [double] (to scale), [Vector4] (to transform), [Vector3] /// (to transform), or [Matrix4] (to multiply). /// - /// If you know the argument type in a call site, prefer [scaled], + /// If you know the argument type in a call site, prefer [scaledByDouble], /// [transformed], [transformed3], or [multiplied] for performance. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @@ -650,7 +650,7 @@ class Matrix4 { dynamic operator *(dynamic arg) { final Object result; if (arg is double) { - result = scaled(arg); + result = scaledByDouble(arg, arg, arg, 1.0); } else if (arg is Vector4) { result = transformed(arg); } else if (arg is Vector3) { @@ -676,6 +676,8 @@ class Matrix4 { @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') + @Deprecated('Use translateByVector3, translateByVector4, ' + 'or translateByDouble instead') void translate(dynamic x, [double y = 0.0, double z = 0.0]) { if (x is Vector3) { translateByVector3(x); @@ -743,6 +745,8 @@ class Matrix4 { @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') + @Deprecated('Use leftTranslateByVector3, leftTranslateByVector4, ' + 'or leftTranslateByDouble instead') void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) { if (x is Vector3) { leftTranslateByVector3(x); @@ -923,59 +927,24 @@ class Matrix4 { @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') + @Deprecated('Use scaleByVector3, scaleByVector4, or scaleByDouble instead') void scale(dynamic x, [double? y, double? z]) { if (x is Vector3) { scaleByVector3(x); } else if (x is Vector4) { scaleByVector4(x); } else if (x is double) { - scaleByDouble(x, y ?? x, z ?? x); + scaleByDouble(x, y ?? x, z ?? x, 1.0); } else { throw UnimplementedError(); } } /// Scale this matrix. - void scaleByDouble(double sx, double sy, double sz) { - _m4storage[0] *= sx; - _m4storage[1] *= sx; - _m4storage[2] *= sx; - _m4storage[3] *= sx; - _m4storage[4] *= sy; - _m4storage[5] *= sy; - _m4storage[6] *= sy; - _m4storage[7] *= sy; - _m4storage[8] *= sz; - _m4storage[9] *= sz; - _m4storage[10] *= sz; - _m4storage[11] *= sz; - } - - /// Scale this matrix. - void scaleByVector3(Vector3 v3) { - final sx = v3.x; - final sy = v3.y; - final sz = v3.z; - _m4storage[0] *= sx; - _m4storage[1] *= sx; - _m4storage[2] *= sx; - _m4storage[3] *= sx; - _m4storage[4] *= sy; - _m4storage[5] *= sy; - _m4storage[6] *= sy; - _m4storage[7] *= sy; - _m4storage[8] *= sz; - _m4storage[9] *= sz; - _m4storage[10] *= sz; - _m4storage[11] *= sz; - } - - /// Scale this matrix. - void scaleByVector4(Vector4 v4) { - final sx = v4.x; - final sy = v4.y; - final sz = v4.z; - final sw = v4.w; + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void scaleByDouble(double sx, double sy, double sz, double sw) { _m4storage[0] *= sx; _m4storage[1] *= sx; _m4storage[2] *= sx; @@ -994,13 +963,45 @@ class Matrix4 { _m4storage[15] *= sw; } + /// Scale this matrix. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void scaleByVector3(Vector3 v3) => scaleByDouble(v3.x, v3.y, v3.z, 1.0); + + /// Scale this matrix. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void scaleByVector4(Vector4 v4) => scaleByDouble(v4.x, v4.y, v4.z, v4.w); + /// Create a copy of this scaled by a [Vector3], [Vector4] or [x],[y], and /// [z]. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') + @Deprecated('Use scaledByVector3, scaledByVector4, or scaledByDouble instead') Matrix4 scaled(dynamic x, [double? y, double? z]) => clone()..scale(x, y, z); + /// Create a copy of this scaled by [x], [y], [z], and [t]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + Matrix4 scaledByDouble(double x, double y, double z, double t) => + clone()..scaleByDouble(x, y, z, t); + + /// Create a copy of this scaled by a [Vector3]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + Matrix4 scaledByVector3(Vector3 v3) => clone()..scaleByVector3(v3); + + /// Create a copy of this scaled by a [Vector4]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + Matrix4 scaledByVector4(Vector4 v4) => clone()..scaleByVector4(v4); + /// Zeros this. void setZero() { _m4storage[0] = 0.0; diff --git a/lib/src/vector_math/opengl.dart b/lib/src/vector_math/opengl.dart index 935bc1a5..74475f89 100644 --- a/lib/src/vector_math/opengl.dart +++ b/lib/src/vector_math/opengl.dart @@ -278,7 +278,7 @@ Matrix4 makePlaneProjection(Vector3 planeNormal, Vector3 planePoint) { Matrix4 makePlaneReflection(Vector3 planeNormal, Vector3 planePoint) { final v = Vector4(planeNormal.storage[0], planeNormal.storage[1], planeNormal.storage[2], 0.0); - final outer = Matrix4.outer(v, v)..scale(2.0); + final outer = Matrix4.outer(v, v)..scaleByDouble(2.0, 2.0, 2.0, 1.0); var r = Matrix4.zero(); r = r - outer; final scale = 2.0 * planePoint.dot(planeNormal); diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index a4a91af2..b709450a 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -461,7 +461,7 @@ class Matrix4 { void setFromTranslationRotationScale( Vector3 translation, Quaternion rotation, Vector3 scale) { setFromTranslationRotation(translation, rotation); - this.scale(scale); + scaleByVector3(scale); } /// Sets the upper 2x2 of the matrix to be [arg]. @@ -642,7 +642,7 @@ class Matrix4 { /// [arg] should be a [double] (to scale), [Vector4] (to transform), [Vector3] /// (to transform), or [Matrix4] (to multiply). /// - /// If you know the argument type in a call site, prefer [scaled], + /// If you know the argument type in a call site, prefer [scaledByDouble], /// [transformed], [transformed3], or [multiplied] for performance. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @@ -650,7 +650,7 @@ class Matrix4 { dynamic operator *(dynamic arg) { final Object result; if (arg is double) { - result = scaled(arg); + result = scaledByDouble(arg, arg, arg, 1.0); } else if (arg is Vector4) { result = transformed(arg); } else if (arg is Vector3) { @@ -676,6 +676,8 @@ class Matrix4 { @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') + @Deprecated('Use translateByVector3, translateByVector4, ' + 'or translateByDouble instead') void translate(dynamic x, [double y = 0.0, double z = 0.0]) { if (x is Vector3) { translateByVector3(x); @@ -743,6 +745,8 @@ class Matrix4 { @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') + @Deprecated('Use leftTranslateByVector3, leftTranslateByVector4, ' + 'or leftTranslateByDouble instead') void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) { if (x is Vector3) { leftTranslateByVector3(x); @@ -923,59 +927,24 @@ class Matrix4 { @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') + @Deprecated('Use scaleByVector3, scaleByVector4, or scaleByDouble instead') void scale(dynamic x, [double? y, double? z]) { if (x is Vector3) { scaleByVector3(x); } else if (x is Vector4) { scaleByVector4(x); } else if (x is double) { - scaleByDouble(x, y ?? x, z ?? x); + scaleByDouble(x, y ?? x, z ?? x, 1.0); } else { throw UnimplementedError(); } } /// Scale this matrix. - void scaleByDouble(double sx, double sy, double sz) { - _m4storage[0] *= sx; - _m4storage[1] *= sx; - _m4storage[2] *= sx; - _m4storage[3] *= sx; - _m4storage[4] *= sy; - _m4storage[5] *= sy; - _m4storage[6] *= sy; - _m4storage[7] *= sy; - _m4storage[8] *= sz; - _m4storage[9] *= sz; - _m4storage[10] *= sz; - _m4storage[11] *= sz; - } - - /// Scale this matrix. - void scaleByVector3(Vector3 v3) { - final sx = v3.x; - final sy = v3.y; - final sz = v3.z; - _m4storage[0] *= sx; - _m4storage[1] *= sx; - _m4storage[2] *= sx; - _m4storage[3] *= sx; - _m4storage[4] *= sy; - _m4storage[5] *= sy; - _m4storage[6] *= sy; - _m4storage[7] *= sy; - _m4storage[8] *= sz; - _m4storage[9] *= sz; - _m4storage[10] *= sz; - _m4storage[11] *= sz; - } - - /// Scale this matrix. - void scaleByVector4(Vector4 v4) { - final sx = v4.x; - final sy = v4.y; - final sz = v4.z; - final sw = v4.w; + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void scaleByDouble(double sx, double sy, double sz, double sw) { _m4storage[0] *= sx; _m4storage[1] *= sx; _m4storage[2] *= sx; @@ -994,13 +963,45 @@ class Matrix4 { _m4storage[15] *= sw; } + /// Scale this matrix. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void scaleByVector3(Vector3 v3) => scaleByDouble(v3.x, v3.y, v3.z, 1.0); + + /// Scale this matrix. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + void scaleByVector4(Vector4 v4) => scaleByDouble(v4.x, v4.y, v4.z, v4.w); + /// Create a copy of this scaled by a [Vector3], [Vector4] or [x],[y], and /// [z]. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') + @Deprecated('Use scaledByVector3, scaledByVector4, or scaledByDouble instead') Matrix4 scaled(dynamic x, [double? y, double? z]) => clone()..scale(x, y, z); + /// Create a copy of this scaled by [x], [y], [z], and [t]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + Matrix4 scaledByDouble(double x, double y, double z, double t) => + clone()..scaleByDouble(x, y, z, t); + + /// Create a copy of this scaled by a [Vector3]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + Matrix4 scaledByVector3(Vector3 v3) => clone()..scaleByVector3(v3); + + /// Create a copy of this scaled by a [Vector4]. + @pragma('wasm:prefer-inline') + @pragma('vm:prefer-inline') + @pragma('dart2js:prefer-inline') + Matrix4 scaledByVector4(Vector4 v4) => clone()..scaleByVector4(v4); + /// Zeros this. void setZero() { _m4storage[0] = 0.0; diff --git a/lib/src/vector_math_64/opengl.dart b/lib/src/vector_math_64/opengl.dart index 7d7de934..6d25d363 100644 --- a/lib/src/vector_math_64/opengl.dart +++ b/lib/src/vector_math_64/opengl.dart @@ -278,7 +278,7 @@ Matrix4 makePlaneProjection(Vector3 planeNormal, Vector3 planePoint) { Matrix4 makePlaneReflection(Vector3 planeNormal, Vector3 planePoint) { final v = Vector4(planeNormal.storage[0], planeNormal.storage[1], planeNormal.storage[2], 0.0); - final outer = Matrix4.outer(v, v)..scale(2.0); + final outer = Matrix4.outer(v, v)..scaleByDouble(2.0, 2.0, 2.0, 1.0); var r = Matrix4.zero(); r = r - outer; final scale = 2.0 * planePoint.dot(planeNormal); diff --git a/test/geometry_test.dart b/test/geometry_test.dart index 78336cea..6c81de58 100644 --- a/test/geometry_test.dart +++ b/test/geometry_test.dart @@ -2,6 +2,8 @@ // All rights reserved. Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:typed_data'; import 'package:test/test.dart'; diff --git a/test/matrix4_test.dart b/test/matrix4_test.dart index 480f7a08..6900e5ca 100644 --- a/test/matrix4_test.dart +++ b/test/matrix4_test.dart @@ -2,6 +2,8 @@ // All rights reserved. Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +// ignore_for_file: deprecated_member_use_from_same_package + import 'dart:math' as math; import 'dart:typed_data'; From 3881ca6db8102918843b1fe0462642bbe49ee580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Thu, 1 May 2025 10:53:07 +0100 Subject: [PATCH 16/21] Update changelog --- CHANGELOG.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9666619f..c9fe8ffe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,26 @@ ## 2.2.0-wip - Performance of functions that take `dynamic` arguments improved. +- Most of the members that take `dynamic` arguments are deprecated. New members + with non-`dynamic` arguments added. + + Deprecated members: + - `Matrix4.translate` + Instead use: `Matrix4.translateByDouble`, `Matrix4.translateByVector3`, + `Matrix4.translateByVector4`. + + - `Matrix4.leftTranslate` + Instead use: `Matrix4.leftTranslateByDouble`, + `Matrix4.leftTranslateByVector3`, `Matrix4.leftTranslateByVector4`. + + - `Matrix4.scale` + Instead use: `Matrix4.scaleByDouble`, `Matrix4.scaleByVector3`, + `Matrix4.scaleByVector4`. + + - `Matrix4.scaled` + Instead use: `Matrix4.scaledByDouble`, `Matrix4.scaledByVector3`, + `Matrix4.scaledByVector4`. + - New `Matrix4` members added with precise argument types (instead of `dynamic`), with better performance: - `Matrix4.scaleByDouble`, `Matrix4.scaleByVector3`, `Matrix4.scaleByVector4` From cb00e3a0d0c78d927d5591fc4c66c33b0dd1682f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Thu, 1 May 2025 10:55:23 +0100 Subject: [PATCH 17/21] Remove duplicate changelog entry --- CHANGELOG.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9fe8ffe..77b4279a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,17 +21,6 @@ Instead use: `Matrix4.scaledByDouble`, `Matrix4.scaledByVector3`, `Matrix4.scaledByVector4`. -- New `Matrix4` members added with precise argument types (instead of - `dynamic`), with better performance: - - `Matrix4.scaleByDouble`, `Matrix4.scaleByVector3`, `Matrix4.scaleByVector4` - as faster `Matrix4.scale`. - - `Matrix4.translateByDouble`, `Matrix4.translateByVector3`, - `Matrix4.translateByVector4` as faster `Matrix4.translate`. - - `Matrix4.leftTranslateByDouble`, `Matrix4.leftTranslateByVector3`, - `Matrix4.leftTranslateByVector4` as faster `Matrix4.leftTranslate`. - These new functions should be preferred over the old ones when the argument - type is known at a call site. - ## 2.1.5 - Fixed `operator -()` of Quaternion (Contributed by tlserver) From 3d35062869fabf2467d9e8059fb15a9e9dfa1914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Thu, 1 May 2025 10:56:03 +0100 Subject: [PATCH 18/21] Edit changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77b4279a..398ef8f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,18 +6,22 @@ Deprecated members: - `Matrix4.translate` + Instead use: `Matrix4.translateByDouble`, `Matrix4.translateByVector3`, `Matrix4.translateByVector4`. - `Matrix4.leftTranslate` + Instead use: `Matrix4.leftTranslateByDouble`, `Matrix4.leftTranslateByVector3`, `Matrix4.leftTranslateByVector4`. - `Matrix4.scale` + Instead use: `Matrix4.scaleByDouble`, `Matrix4.scaleByVector3`, `Matrix4.scaleByVector4`. - `Matrix4.scaled` + Instead use: `Matrix4.scaledByDouble`, `Matrix4.scaledByVector3`, `Matrix4.scaledByVector4`. From 07d49ee3eeb581debd6d90d9434aa319ef4ff51c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Thu, 1 May 2025 10:58:55 +0100 Subject: [PATCH 19/21] Update docs --- lib/src/vector_math/matrix4.dart | 2 +- lib/src/vector_math_64/matrix4.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/vector_math/matrix4.dart b/lib/src/vector_math/matrix4.dart index 1ea55c89..8c82523c 100644 --- a/lib/src/vector_math/matrix4.dart +++ b/lib/src/vector_math/matrix4.dart @@ -690,7 +690,7 @@ class Matrix4 { } } - /// Translate this matrix by x, y, z. + /// Translate this matrix by x, y, z, w. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') diff --git a/lib/src/vector_math_64/matrix4.dart b/lib/src/vector_math_64/matrix4.dart index b709450a..f1ed9f00 100644 --- a/lib/src/vector_math_64/matrix4.dart +++ b/lib/src/vector_math_64/matrix4.dart @@ -690,7 +690,7 @@ class Matrix4 { } } - /// Translate this matrix by x, y, z. + /// Translate this matrix by x, y, z, w. @pragma('wasm:prefer-inline') @pragma('vm:prefer-inline') @pragma('dart2js:prefer-inline') From 01daccc7b1eb1375e0980680269762e10f535e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Thu, 1 May 2025 11:09:36 +0100 Subject: [PATCH 20/21] Bump major version --- CHANGELOG.md | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 398ef8f8..cbfc6ecf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.2.0-wip +## 3.0.0-wip - Performance of functions that take `dynamic` arguments improved. - Most of the members that take `dynamic` arguments are deprecated. New members diff --git a/pubspec.yaml b/pubspec.yaml index 162d06c0..28959567 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: vector_math -version: 2.2.0-wip +version: 3.0.0-wip description: A Vector Math library for 2D and 3D applications. repository: https://github.com/google/vector_math.dart From 7fb9a0247966f33b30f5f50af8137d4085d9a6e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20A=C4=9Facan?= Date: Thu, 1 May 2025 11:18:40 +0100 Subject: [PATCH 21/21] Revert "Bump major version" This reverts commit 01daccc7b1eb1375e0980680269762e10f535e90. --- CHANGELOG.md | 2 +- pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbfc6ecf..398ef8f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 3.0.0-wip +## 2.2.0-wip - Performance of functions that take `dynamic` arguments improved. - Most of the members that take `dynamic` arguments are deprecated. New members diff --git a/pubspec.yaml b/pubspec.yaml index 28959567..162d06c0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: vector_math -version: 3.0.0-wip +version: 2.2.0-wip description: A Vector Math library for 2D and 3D applications. repository: https://github.com/google/vector_math.dart