• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

google / vector_math.dart / 20199874437

06 Dec 2025 10:32PM UTC coverage: 27.015% (+0.2%) from 26.849%
20199874437

push

github

web-flow
feat: Add leftTranslateByVector2 method to Matrix4 (#351)

2 of 4 new or added lines in 2 files covered. (50.0%)

4545 of 16824 relevant lines covered (27.01%)

1.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lib/src/vector_math_64/matrix4.dart
1
// Copyright (c) 2015, Google Inc. Please see the AUTHORS file for details.
2
// All rights reserved. Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4

5
part of '../../vector_math_64.dart';
6

7
/// 4D Matrix.
8
/// Values are stored in column major order.
9
class Matrix4 {
10
  final Float64List _m4storage;
11

12
  /// The components of the matrix.
13
  Float64List get storage => _m4storage;
×
14

15
  /// Solve [A] * [x] = [b].
16
  static void solve2(Matrix4 A, Vector2 x, Vector2 b) {
×
17
    final a11 = A.entry(0, 0);
×
18
    final a12 = A.entry(0, 1);
×
19
    final a21 = A.entry(1, 0);
×
20
    final a22 = A.entry(1, 1);
×
21
    final bx = b.x - A._m4storage[8];
×
22
    final by = b.y - A._m4storage[9];
×
23
    var det = a11 * a22 - a12 * a21;
×
24

25
    if (det != 0.0) {
×
26
      det = 1.0 / det;
×
27
    }
28

29
    x
30
      ..x = det * (a22 * bx - a12 * by)
×
31
      ..y = det * (a11 * by - a21 * bx);
×
32
  }
33

34
  /// Solve [A] * [x] = [b].
35
  static void solve3(Matrix4 A, Vector3 x, Vector3 b) {
×
36
    final A0x = A.entry(0, 0);
×
37
    final A0y = A.entry(1, 0);
×
38
    final A0z = A.entry(2, 0);
×
39
    final A1x = A.entry(0, 1);
×
40
    final A1y = A.entry(1, 1);
×
41
    final A1z = A.entry(2, 1);
×
42
    final A2x = A.entry(0, 2);
×
43
    final A2y = A.entry(1, 2);
×
44
    final A2z = A.entry(2, 2);
×
45
    final bx = b.x - A._m4storage[12];
×
46
    final by = b.y - A._m4storage[13];
×
47
    final bz = b.z - A._m4storage[14];
×
48
    double rx, ry, rz;
49
    double det;
50

51
    // Column1 cross Column 2
52
    rx = A1y * A2z - A1z * A2y;
×
53
    ry = A1z * A2x - A1x * A2z;
×
54
    rz = A1x * A2y - A1y * A2x;
×
55

56
    // A.getColumn(0).dot(x)
57
    det = A0x * rx + A0y * ry + A0z * rz;
×
58
    if (det != 0.0) {
×
59
      det = 1.0 / det;
×
60
    }
61

62
    // b dot [Column1 cross Column 2]
63
    final x_ = det * (bx * rx + by * ry + bz * rz);
×
64

65
    // Column2 cross b
66
    rx = -(A2y * bz - A2z * by);
×
67
    ry = -(A2z * bx - A2x * bz);
×
68
    rz = -(A2x * by - A2y * bx);
×
69
    // Column0 dot -[Column2 cross b (Column3)]
70
    final y_ = det * (A0x * rx + A0y * ry + A0z * rz);
×
71

72
    // b cross Column 1
73
    rx = -(by * A1z - bz * A1y);
×
74
    ry = -(bz * A1x - bx * A1z);
×
75
    rz = -(bx * A1y - by * A1x);
×
76
    // Column0 dot -[b cross Column 1]
77
    final z_ = det * (A0x * rx + A0y * ry + A0z * rz);
×
78

79
    x
80
      ..x = x_
×
81
      ..y = y_
×
82
      ..z = z_;
×
83
  }
84

85
  /// Solve [A] * [x] = [b].
86
  static void solve(Matrix4 A, Vector4 x, Vector4 b) {
×
87
    final a00 = A._m4storage[0];
×
88
    final a01 = A._m4storage[1];
×
89
    final a02 = A._m4storage[2];
×
90
    final a03 = A._m4storage[3];
×
91
    final a10 = A._m4storage[4];
×
92
    final a11 = A._m4storage[5];
×
93
    final a12 = A._m4storage[6];
×
94
    final a13 = A._m4storage[7];
×
95
    final a20 = A._m4storage[8];
×
96
    final a21 = A._m4storage[9];
×
97
    final a22 = A._m4storage[10];
×
98
    final a23 = A._m4storage[11];
×
99
    final a30 = A._m4storage[12];
×
100
    final a31 = A._m4storage[13];
×
101
    final a32 = A._m4storage[14];
×
102
    final a33 = A._m4storage[15];
×
103
    final b00 = a00 * a11 - a01 * a10;
×
104
    final b01 = a00 * a12 - a02 * a10;
×
105
    final b02 = a00 * a13 - a03 * a10;
×
106
    final b03 = a01 * a12 - a02 * a11;
×
107
    final b04 = a01 * a13 - a03 * a11;
×
108
    final b05 = a02 * a13 - a03 * a12;
×
109
    final b06 = a20 * a31 - a21 * a30;
×
110
    final b07 = a20 * a32 - a22 * a30;
×
111
    final b08 = a20 * a33 - a23 * a30;
×
112
    final b09 = a21 * a32 - a22 * a31;
×
113
    final b10 = a21 * a33 - a23 * a31;
×
114
    final b11 = a22 * a33 - a23 * a32;
×
115

116
    final bX = b.storage[0];
×
117
    final bY = b.storage[1];
×
118
    final bZ = b.storage[2];
×
119
    final bW = b.storage[3];
×
120

121
    var det =
122
        b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
×
123

124
    if (det != 0.0) {
×
125
      det = 1.0 / det;
×
126
    }
127

128
    x
129
      ..x =
×
130
          det *
×
131
          ((a11 * b11 - a12 * b10 + a13 * b09) * bX -
×
132
              (a10 * b11 - a12 * b08 + a13 * b07) * bY +
×
133
              (a10 * b10 - a11 * b08 + a13 * b06) * bZ -
×
134
              (a10 * b09 - a11 * b07 + a12 * b06) * bW)
×
135
      ..y =
×
136
          det *
×
137
          -((a01 * b11 - a02 * b10 + a03 * b09) * bX -
×
138
              (a00 * b11 - a02 * b08 + a03 * b07) * bY +
×
139
              (a00 * b10 - a01 * b08 + a03 * b06) * bZ -
×
140
              (a00 * b09 - a01 * b07 + a02 * b06) * bW)
×
141
      ..z =
×
142
          det *
×
143
          ((a31 * b05 - a32 * b04 + a33 * b03) * bX -
×
144
              (a30 * b05 - a32 * b02 + a33 * b01) * bY +
×
145
              (a30 * b04 - a31 * b02 + a33 * b00) * bZ -
×
146
              (a30 * b03 - a31 * b01 + a32 * b00) * bW)
×
147
      ..w =
×
148
          det *
×
149
          -((a21 * b05 - a22 * b04 + a23 * b03) * bX -
×
150
              (a20 * b05 - a22 * b02 + a23 * b01) * bY +
×
151
              (a20 * b04 - a21 * b02 + a23 * b00) * bZ -
×
152
              (a20 * b03 - a21 * b01 + a22 * b00) * bW);
×
153
  }
154

155
  /// Returns a matrix that is the inverse of [other] if [other] is invertible,
156
  /// otherwise `null`.
157
  static Matrix4? tryInvert(Matrix4 other) {
×
158
    final r = Matrix4.zero();
×
159
    final determinant = r.copyInverse(other);
×
160
    if (determinant == 0.0) {
×
161
      return null;
162
    }
163
    return r;
164
  }
165

166
  /// Return index in storage for [row], [col] value.
167
  int index(int row, int col) => (col * 4) + row;
×
168

169
  /// Value at [row], [col].
170
  double entry(int row, int col) {
×
171
    assert((row >= 0) && (row < dimension));
×
172
    assert((col >= 0) && (col < dimension));
×
173

174
    return _m4storage[index(row, col)];
×
175
  }
176

177
  /// Set value at [row], [col] to be [v].
178
  void setEntry(int row, int col, double v) {
×
179
    assert((row >= 0) && (row < dimension));
×
180
    assert((col >= 0) && (col < dimension));
×
181

182
    _m4storage[index(row, col)] = v;
×
183
  }
184

185
  /// Constructs a new mat4.
186
  factory Matrix4(
×
187
    double arg0,
188
    double arg1,
189
    double arg2,
190
    double arg3,
191
    double arg4,
192
    double arg5,
193
    double arg6,
194
    double arg7,
195
    double arg8,
196
    double arg9,
197
    double arg10,
198
    double arg11,
199
    double arg12,
200
    double arg13,
201
    double arg14,
202
    double arg15,
203
  ) =>
204
      Matrix4.zero()..setValues(
×
205
        arg0,
206
        arg1,
207
        arg2,
208
        arg3,
209
        arg4,
210
        arg5,
211
        arg6,
212
        arg7,
213
        arg8,
214
        arg9,
215
        arg10,
216
        arg11,
217
        arg12,
218
        arg13,
219
        arg14,
220
        arg15,
221
      );
222

223
  /// New matrix from [values].
224
  factory Matrix4.fromList(List<double> values) =>
×
225
      Matrix4.zero()..setValues(
×
226
        values[0],
×
227
        values[1],
×
228
        values[2],
×
229
        values[3],
×
230
        values[4],
×
231
        values[5],
×
232
        values[6],
×
233
        values[7],
×
234
        values[8],
×
235
        values[9],
×
236
        values[10],
×
237
        values[11],
×
238
        values[12],
×
239
        values[13],
×
240
        values[14],
×
241
        values[15],
×
242
      );
243

244
  /// Zero matrix.
245
  Matrix4.zero() : _m4storage = Float64List(16);
×
246

247
  /// Identity matrix.
248
  factory Matrix4.identity() => Matrix4.zero()..setIdentity();
×
249

250
  /// Copies values from [other].
251
  factory Matrix4.copy(Matrix4 other) => Matrix4.zero()..setFrom(other);
×
252

253
  /// Constructs a matrix that is the inverse of [other].
254
  factory Matrix4.inverted(Matrix4 other) {
×
255
    final r = Matrix4.zero();
×
256
    final determinant = r.copyInverse(other);
×
257
    if (determinant == 0.0) {
×
258
      throw ArgumentError.value(other, 'other', 'Matrix cannot be inverted');
×
259
    }
260
    return r;
261
  }
262

263
  /// Constructs a new mat4 from columns.
264
  factory Matrix4.columns(
×
265
    Vector4 arg0,
266
    Vector4 arg1,
267
    Vector4 arg2,
268
    Vector4 arg3,
269
  ) => Matrix4.zero()..setColumns(arg0, arg1, arg2, arg3);
×
270

271
  /// Outer product of [u] and [v].
272
  factory Matrix4.outer(Vector4 u, Vector4 v) => Matrix4.zero()..setOuter(u, v);
×
273

274
  /// Rotation of [radians] around X.
275
  factory Matrix4.rotationX(double radians) =>
×
276
      Matrix4.zero()
×
277
        .._m4storage[15] = 1.0
×
278
        ..setRotationX(radians);
×
279

280
  /// Rotation of [radians] around Y.
281
  factory Matrix4.rotationY(double radians) =>
×
282
      Matrix4.zero()
×
283
        .._m4storage[15] = 1.0
×
284
        ..setRotationY(radians);
×
285

286
  /// Rotation of [radians] around Z.
287
  factory Matrix4.rotationZ(double radians) =>
×
288
      Matrix4.zero()
×
289
        .._m4storage[15] = 1.0
×
290
        ..setRotationZ(radians);
×
291

292
  /// Translation matrix.
293
  factory Matrix4.translation(Vector3 translation) =>
×
294
      Matrix4.zero()
×
295
        ..setIdentity()
×
296
        ..setTranslation(translation);
×
297

298
  /// Translation matrix.
299
  factory Matrix4.translationValues(double x, double y, double z) =>
×
300
      Matrix4.zero()
×
301
        ..setIdentity()
×
302
        ..setTranslationRaw(x, y, z);
×
303

304
  /// Scale matrix.
305
  factory Matrix4.diagonal3(Vector3 scale) {
×
306
    final m = Matrix4.zero();
×
307
    final mStorage = m._m4storage;
×
308
    final scaleStorage = scale._v3storage;
×
309
    mStorage[15] = 1.0;
×
310
    mStorage[10] = scaleStorage[2];
×
311
    mStorage[5] = scaleStorage[1];
×
312
    mStorage[0] = scaleStorage[0];
×
313
    return m;
314
  }
315

316
  /// Scale matrix.
317
  factory Matrix4.diagonal3Values(double x, double y, double z) =>
×
318
      Matrix4.zero()
×
319
        .._m4storage[15] = 1.0
×
320
        .._m4storage[10] = z
×
321
        .._m4storage[5] = y
×
322
        .._m4storage[0] = x;
×
323

324
  /// Skew matrix around X axis
325
  factory Matrix4.skewX(double alpha) {
×
326
    final m = Matrix4.identity();
×
327
    m._m4storage[4] = math.tan(alpha);
×
328
    return m;
329
  }
330

331
  /// Skew matrix around Y axis.
332
  factory Matrix4.skewY(double beta) {
×
333
    final m = Matrix4.identity();
×
334
    m._m4storage[1] = math.tan(beta);
×
335
    return m;
336
  }
337

338
  /// Skew matrix around X axis (alpha) and Y axis (beta).
339
  factory Matrix4.skew(double alpha, double beta) {
×
340
    final m = Matrix4.identity();
×
341
    m._m4storage[1] = math.tan(beta);
×
342
    m._m4storage[4] = math.tan(alpha);
×
343
    return m;
344
  }
345

346
  /// Constructs Matrix4 with given [Float64List] as [storage].
347
  Matrix4.fromFloat64List(this._m4storage);
×
348

349
  /// Constructs Matrix4 with a [storage] that views given [buffer] starting at
350
  /// [offset]. [offset] has to be multiple of [Float64List.bytesPerElement].
351
  Matrix4.fromBuffer(ByteBuffer buffer, int offset)
×
352
    : _m4storage = Float64List.view(buffer, offset, 16);
×
353

354
  /// Constructs Matrix4 from [translation], [rotation] and [scale].
355
  factory Matrix4.compose(
×
356
    Vector3 translation,
357
    Quaternion rotation,
358
    Vector3 scale,
359
  ) =>
360
      Matrix4.zero()
×
361
        ..setFromTranslationRotationScale(translation, rotation, scale);
×
362

363
  /// Sets the diagonal to [arg].
364
  void splatDiagonal(double arg) {
×
365
    _m4storage[0] = arg;
×
366
    _m4storage[5] = arg;
×
367
    _m4storage[10] = arg;
×
368
    _m4storage[15] = arg;
×
369
  }
370

371
  /// Sets the matrix with specified values.
372
  void setValues(
×
373
    double arg0,
374
    double arg1,
375
    double arg2,
376
    double arg3,
377
    double arg4,
378
    double arg5,
379
    double arg6,
380
    double arg7,
381
    double arg8,
382
    double arg9,
383
    double arg10,
384
    double arg11,
385
    double arg12,
386
    double arg13,
387
    double arg14,
388
    double arg15,
389
  ) {
390
    _m4storage[15] = arg15;
×
391
    _m4storage[14] = arg14;
×
392
    _m4storage[13] = arg13;
×
393
    _m4storage[12] = arg12;
×
394
    _m4storage[11] = arg11;
×
395
    _m4storage[10] = arg10;
×
396
    _m4storage[9] = arg9;
×
397
    _m4storage[8] = arg8;
×
398
    _m4storage[7] = arg7;
×
399
    _m4storage[6] = arg6;
×
400
    _m4storage[5] = arg5;
×
401
    _m4storage[4] = arg4;
×
402
    _m4storage[3] = arg3;
×
403
    _m4storage[2] = arg2;
×
404
    _m4storage[1] = arg1;
×
405
    _m4storage[0] = arg0;
×
406
  }
407

408
  /// Sets the entire matrix to the column values.
409
  void setColumns(Vector4 arg0, Vector4 arg1, Vector4 arg2, Vector4 arg3) {
×
410
    final arg0Storage = arg0._v4storage;
×
411
    final arg1Storage = arg1._v4storage;
×
412
    final arg2Storage = arg2._v4storage;
×
413
    final arg3Storage = arg3._v4storage;
×
414
    _m4storage[0] = arg0Storage[0];
×
415
    _m4storage[1] = arg0Storage[1];
×
416
    _m4storage[2] = arg0Storage[2];
×
417
    _m4storage[3] = arg0Storage[3];
×
418
    _m4storage[4] = arg1Storage[0];
×
419
    _m4storage[5] = arg1Storage[1];
×
420
    _m4storage[6] = arg1Storage[2];
×
421
    _m4storage[7] = arg1Storage[3];
×
422
    _m4storage[8] = arg2Storage[0];
×
423
    _m4storage[9] = arg2Storage[1];
×
424
    _m4storage[10] = arg2Storage[2];
×
425
    _m4storage[11] = arg2Storage[3];
×
426
    _m4storage[12] = arg3Storage[0];
×
427
    _m4storage[13] = arg3Storage[1];
×
428
    _m4storage[14] = arg3Storage[2];
×
429
    _m4storage[15] = arg3Storage[3];
×
430
  }
431

432
  /// Sets the entire matrix to the matrix in [arg].
433
  void setFrom(Matrix4 arg) {
×
434
    final argStorage = arg._m4storage;
×
435
    _m4storage[15] = argStorage[15];
×
436
    _m4storage[14] = argStorage[14];
×
437
    _m4storage[13] = argStorage[13];
×
438
    _m4storage[12] = argStorage[12];
×
439
    _m4storage[11] = argStorage[11];
×
440
    _m4storage[10] = argStorage[10];
×
441
    _m4storage[9] = argStorage[9];
×
442
    _m4storage[8] = argStorage[8];
×
443
    _m4storage[7] = argStorage[7];
×
444
    _m4storage[6] = argStorage[6];
×
445
    _m4storage[5] = argStorage[5];
×
446
    _m4storage[4] = argStorage[4];
×
447
    _m4storage[3] = argStorage[3];
×
448
    _m4storage[2] = argStorage[2];
×
449
    _m4storage[1] = argStorage[1];
×
450
    _m4storage[0] = argStorage[0];
×
451
  }
452

453
  /// Sets the matrix from translation [arg0] and rotation [arg1].
454
  void setFromTranslationRotation(Vector3 arg0, Quaternion arg1) {
×
455
    final arg1Storage = arg1._qStorage;
×
456
    final x = arg1Storage[0];
×
457
    final y = arg1Storage[1];
×
458
    final z = arg1Storage[2];
×
459
    final w = arg1Storage[3];
×
460
    final x2 = x + x;
×
461
    final y2 = y + y;
×
462
    final z2 = z + z;
×
463
    final xx = x * x2;
×
464
    final xy = x * y2;
×
465
    final xz = x * z2;
×
466
    final yy = y * y2;
×
467
    final yz = y * z2;
×
468
    final zz = z * z2;
×
469
    final wx = w * x2;
×
470
    final wy = w * y2;
×
471
    final wz = w * z2;
×
472

473
    final arg0Storage = arg0._v3storage;
×
474
    _m4storage[0] = 1.0 - (yy + zz);
×
475
    _m4storage[1] = xy + wz;
×
476
    _m4storage[2] = xz - wy;
×
477
    _m4storage[3] = 0.0;
×
478
    _m4storage[4] = xy - wz;
×
479
    _m4storage[5] = 1.0 - (xx + zz);
×
480
    _m4storage[6] = yz + wx;
×
481
    _m4storage[7] = 0.0;
×
482
    _m4storage[8] = xz + wy;
×
483
    _m4storage[9] = yz - wx;
×
484
    _m4storage[10] = 1.0 - (xx + yy);
×
485
    _m4storage[11] = 0.0;
×
486
    _m4storage[12] = arg0Storage[0];
×
487
    _m4storage[13] = arg0Storage[1];
×
488
    _m4storage[14] = arg0Storage[2];
×
489
    _m4storage[15] = 1.0;
×
490
  }
491

492
  /// Sets the matrix from [translation], [rotation] and [scale].
493
  void setFromTranslationRotationScale(
×
494
    Vector3 translation,
495
    Quaternion rotation,
496
    Vector3 scale,
497
  ) {
498
    setFromTranslationRotation(translation, rotation);
×
499
    scaleByVector3(scale);
×
500
  }
501

502
  /// Sets the upper 2x2 of the matrix to be [arg].
503
  void setUpper2x2(Matrix2 arg) {
×
504
    final argStorage = arg._m2storage;
×
505
    _m4storage[0] = argStorage[0];
×
506
    _m4storage[1] = argStorage[1];
×
507
    _m4storage[4] = argStorage[2];
×
508
    _m4storage[5] = argStorage[3];
×
509
  }
510

511
  /// Sets the diagonal of the matrix to be [arg].
512
  void setDiagonal(Vector4 arg) {
×
513
    final argStorage = arg._v4storage;
×
514
    _m4storage[0] = argStorage[0];
×
515
    _m4storage[5] = argStorage[1];
×
516
    _m4storage[10] = argStorage[2];
×
517
    _m4storage[15] = argStorage[3];
×
518
  }
519

520
  void setOuter(Vector4 u, Vector4 v) {
×
521
    final uStorage = u._v4storage;
×
522
    final vStorage = v._v4storage;
×
523
    _m4storage[0] = uStorage[0] * vStorage[0];
×
524
    _m4storage[1] = uStorage[0] * vStorage[1];
×
525
    _m4storage[2] = uStorage[0] * vStorage[2];
×
526
    _m4storage[3] = uStorage[0] * vStorage[3];
×
527
    _m4storage[4] = uStorage[1] * vStorage[0];
×
528
    _m4storage[5] = uStorage[1] * vStorage[1];
×
529
    _m4storage[6] = uStorage[1] * vStorage[2];
×
530
    _m4storage[7] = uStorage[1] * vStorage[3];
×
531
    _m4storage[8] = uStorage[2] * vStorage[0];
×
532
    _m4storage[9] = uStorage[2] * vStorage[1];
×
533
    _m4storage[10] = uStorage[2] * vStorage[2];
×
534
    _m4storage[11] = uStorage[2] * vStorage[3];
×
535
    _m4storage[12] = uStorage[3] * vStorage[0];
×
536
    _m4storage[13] = uStorage[3] * vStorage[1];
×
537
    _m4storage[14] = uStorage[3] * vStorage[2];
×
538
    _m4storage[15] = uStorage[3] * vStorage[3];
×
539
  }
540

541
  /// Returns a printable string
542
  @override
×
543
  String toString() =>
×
544
      '[0] ${getRow(0)}\n[1] ${getRow(1)}\n'
×
545
      '[2] ${getRow(2)}\n[3] ${getRow(3)}\n';
×
546

547
  /// Dimension of the matrix.
548
  int get dimension => 4;
×
549

550
  /// Access the element of the matrix at the index [i].
551
  double operator [](int i) => _m4storage[i];
×
552

553
  /// Set the element of the matrix at the index [i].
554
  void operator []=(int i, double v) {
×
555
    _m4storage[i] = v;
×
556
  }
557

558
  /// Check if two matrices are the same.
559
  @override
×
560
  bool operator ==(Object other) =>
561
      (other is Matrix4) &&
×
562
      (_m4storage[0] == other._m4storage[0]) &&
×
563
      (_m4storage[1] == other._m4storage[1]) &&
×
564
      (_m4storage[2] == other._m4storage[2]) &&
×
565
      (_m4storage[3] == other._m4storage[3]) &&
×
566
      (_m4storage[4] == other._m4storage[4]) &&
×
567
      (_m4storage[5] == other._m4storage[5]) &&
×
568
      (_m4storage[6] == other._m4storage[6]) &&
×
569
      (_m4storage[7] == other._m4storage[7]) &&
×
570
      (_m4storage[8] == other._m4storage[8]) &&
×
571
      (_m4storage[9] == other._m4storage[9]) &&
×
572
      (_m4storage[10] == other._m4storage[10]) &&
×
573
      (_m4storage[11] == other._m4storage[11]) &&
×
574
      (_m4storage[12] == other._m4storage[12]) &&
×
575
      (_m4storage[13] == other._m4storage[13]) &&
×
576
      (_m4storage[14] == other._m4storage[14]) &&
×
577
      (_m4storage[15] == other._m4storage[15]);
×
578

579
  @override
×
580
  int get hashCode => Object.hashAll(_m4storage);
×
581

582
  /// Returns row 0
583
  Vector4 get row0 => getRow(0);
×
584

585
  /// Returns row 1
586
  Vector4 get row1 => getRow(1);
×
587

588
  /// Returns row 2
589
  Vector4 get row2 => getRow(2);
×
590

591
  /// Returns row 3
592
  Vector4 get row3 => getRow(3);
×
593

594
  /// Sets row 0 to [arg]
595
  set row0(Vector4 arg) => setRow(0, arg);
×
596

597
  /// Sets row 1 to [arg]
598
  set row1(Vector4 arg) => setRow(1, arg);
×
599

600
  /// Sets row 2 to [arg]
601
  set row2(Vector4 arg) => setRow(2, arg);
×
602

603
  /// Sets row 3 to [arg]
604
  set row3(Vector4 arg) => setRow(3, arg);
×
605

606
  /// Assigns the [row] of the matrix [arg]
607
  void setRow(int row, Vector4 arg) {
×
608
    final argStorage = arg._v4storage;
×
609
    _m4storage[index(row, 0)] = argStorage[0];
×
610
    _m4storage[index(row, 1)] = argStorage[1];
×
611
    _m4storage[index(row, 2)] = argStorage[2];
×
612
    _m4storage[index(row, 3)] = argStorage[3];
×
613
  }
614

615
  /// Gets the [row] of the matrix
616
  Vector4 getRow(int row) {
×
617
    final r = Vector4.zero();
×
618
    final rStorage = r._v4storage;
×
619
    rStorage[0] = _m4storage[index(row, 0)];
×
620
    rStorage[1] = _m4storage[index(row, 1)];
×
621
    rStorage[2] = _m4storage[index(row, 2)];
×
622
    rStorage[3] = _m4storage[index(row, 3)];
×
623
    return r;
624
  }
625

626
  /// Assigns the [column] of the matrix [arg]
627
  void setColumn(int column, Vector4 arg) {
×
628
    final entry = column * 4;
×
629
    final argStorage = arg._v4storage;
×
630
    _m4storage[entry + 3] = argStorage[3];
×
631
    _m4storage[entry + 2] = argStorage[2];
×
632
    _m4storage[entry + 1] = argStorage[1];
×
633
    _m4storage[entry + 0] = argStorage[0];
×
634
  }
635

636
  /// Gets the [column] of the matrix
637
  Vector4 getColumn(int column) {
×
638
    final r = Vector4.zero();
×
639
    final rStorage = r._v4storage;
×
640
    final entry = column * 4;
×
641
    rStorage[3] = _m4storage[entry + 3];
×
642
    rStorage[2] = _m4storage[entry + 2];
×
643
    rStorage[1] = _m4storage[entry + 1];
×
644
    rStorage[0] = _m4storage[entry + 0];
×
645
    return r;
646
  }
647

648
  /// Clone matrix.
649
  Matrix4 clone() => Matrix4.copy(this);
×
650

651
  /// Copy into [arg].
652
  Matrix4 copyInto(Matrix4 arg) {
×
653
    final argStorage = arg._m4storage;
×
654
    argStorage[0] = _m4storage[0];
×
655
    argStorage[1] = _m4storage[1];
×
656
    argStorage[2] = _m4storage[2];
×
657
    argStorage[3] = _m4storage[3];
×
658
    argStorage[4] = _m4storage[4];
×
659
    argStorage[5] = _m4storage[5];
×
660
    argStorage[6] = _m4storage[6];
×
661
    argStorage[7] = _m4storage[7];
×
662
    argStorage[8] = _m4storage[8];
×
663
    argStorage[9] = _m4storage[9];
×
664
    argStorage[10] = _m4storage[10];
×
665
    argStorage[11] = _m4storage[11];
×
666
    argStorage[12] = _m4storage[12];
×
667
    argStorage[13] = _m4storage[13];
×
668
    argStorage[14] = _m4storage[14];
×
669
    argStorage[15] = _m4storage[15];
×
670
    return arg;
671
  }
672

673
  /// Returns new matrix -this
674
  Matrix4 operator -() => clone()..negate();
×
675

676
  /// Returns a new vector or matrix by multiplying this with [arg].
677
  ///
678
  /// [arg] should be a [double] (to scale), [Vector4] (to transform), [Vector3]
679
  /// (to transform), or [Matrix4] (to multiply).
680
  ///
681
  /// If you know the argument type in a call site, prefer [scaledByDouble],
682
  /// [transformed], [transformed3], or [multiplied] for performance.
683
  @pragma('wasm:prefer-inline')
×
684
  @pragma('vm:prefer-inline')
685
  @pragma('dart2js:prefer-inline')
686
  dynamic operator *(dynamic arg) {
687
    final Object result;
688
    if (arg is double) {
×
689
      result = scaledByDouble(arg, arg, arg, 1.0);
×
690
    } else if (arg is Vector4) {
×
691
      result = transformed(arg);
×
692
    } else if (arg is Vector3) {
×
693
      result = transformed3(arg);
×
694
    } else if (arg is Matrix4) {
×
695
      result = multiplied(arg);
×
696
    } else {
697
      throw ArgumentError(arg);
×
698
    }
699
    return result;
700
  }
701

702
  /// Returns new matrix after component wise this + [arg]
703
  Matrix4 operator +(Matrix4 arg) => clone()..add(arg);
×
704

705
  /// Returns new matrix after component wise this - [arg]
706
  Matrix4 operator -(Matrix4 arg) => clone()..sub(arg);
×
707

708
  /// Translate this matrix by a [Vector3], [Vector4], or x,y,z as [double]s.
709
  ///
710
  /// If you know the argument types in a call site, prefer [translateByDouble],
711
  /// [translateByVector3], or [translateByVector4] for performance.
712
  @pragma('wasm:prefer-inline')
×
713
  @pragma('vm:prefer-inline')
714
  @pragma('dart2js:prefer-inline')
715
  @Deprecated(
716
    'Use translateByVector3, translateByVector4, '
717
    'or translateByDouble instead',
718
  )
719
  void translate(dynamic x, [double y = 0.0, double z = 0.0]) {
720
    if (x is Vector3) {
×
721
      translateByVector3(x);
×
722
    } else if (x is Vector4) {
×
723
      translateByVector4(x);
×
724
    } else if (x is double) {
×
725
      translateByDouble(x, y, z, 1.0);
×
726
    } else {
727
      throw UnimplementedError();
×
728
    }
729
  }
730

731
  /// Translate this matrix by x, y, z, w.
732
  void translateByDouble(double tx, double ty, double tz, double tw) {
×
733
    final t1 =
734
        _m4storage[0] * tx +
×
735
        _m4storage[4] * ty +
×
736
        _m4storage[8] * tz +
×
737
        _m4storage[12] * tw;
×
738
    _m4storage[12] = t1;
×
739

740
    final t2 =
741
        _m4storage[1] * tx +
×
742
        _m4storage[5] * ty +
×
743
        _m4storage[9] * tz +
×
744
        _m4storage[13] * tw;
×
745
    _m4storage[13] = t2;
×
746

747
    final t3 =
748
        _m4storage[2] * tx +
×
749
        _m4storage[6] * ty +
×
750
        _m4storage[10] * tz +
×
751
        _m4storage[14] * tw;
×
752
    _m4storage[14] = t3;
×
753

754
    final t4 =
755
        _m4storage[3] * tx +
×
756
        _m4storage[7] * ty +
×
757
        _m4storage[11] * tz +
×
758
        _m4storage[15] * tw;
×
759
    _m4storage[15] = t4;
×
760
  }
761

762
  /// Translate this matrix by a [Vector2].
763
  @pragma('wasm:prefer-inline')
×
764
  @pragma('vm:prefer-inline')
765
  @pragma('dart2js:prefer-inline')
766
  void translateByVector2(Vector2 v2) =>
767
      translateByDouble(v2.x, v2.y, 0.0, 1.0);
×
768

769
  /// Translate this matrix by a [Vector3].
770
  @pragma('wasm:prefer-inline')
×
771
  @pragma('vm:prefer-inline')
772
  @pragma('dart2js:prefer-inline')
773
  void translateByVector3(Vector3 v3) =>
774
      translateByDouble(v3.x, v3.y, v3.z, 1.0);
×
775

776
  /// Translate this matrix by a [Vector4].
777
  @pragma('wasm:prefer-inline')
×
778
  @pragma('vm:prefer-inline')
779
  @pragma('dart2js:prefer-inline')
780
  void translateByVector4(Vector4 v4) =>
781
      translateByDouble(v4.x, v4.y, v4.z, v4.w);
×
782

783
  /// Multiply this by a translation from the left.
784
  ///
785
  /// The translation can be specified with a [Vector3], [Vector4], or x, y, z
786
  /// as [double]s.
787
  ///
788
  /// If you know the argument types in a call site, prefer
789
  /// [leftTranslateByDouble], [leftTranslateByVector3], or
790
  /// [leftTranslateByVector4] for performance.
791
  @pragma('wasm:prefer-inline')
×
792
  @pragma('vm:prefer-inline')
793
  @pragma('dart2js:prefer-inline')
794
  @Deprecated(
795
    'Use leftTranslateByVector3, leftTranslateByVector4, '
796
    'or leftTranslateByDouble instead',
797
  )
798
  void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) {
799
    if (x is Vector3) {
×
800
      leftTranslateByVector3(x);
×
801
    } else if (x is Vector4) {
×
802
      leftTranslateByVector4(x);
×
803
    } else if (x is double) {
×
804
      leftTranslateByDouble(x, y, z, 1.0);
×
805
    } else {
806
      throw UnimplementedError();
×
807
    }
808
  }
809

810
  /// Multiply this by a translation from the left.
811
  void leftTranslateByDouble(double tx, double ty, double tz, double tw) {
×
812
    // Column 1
813
    final r1 = _m4storage[3];
×
814
    _m4storage[0] += tx * r1;
×
815
    _m4storage[1] += ty * r1;
×
816
    _m4storage[2] += tz * r1;
×
817
    _m4storage[3] = tw * r1;
×
818

819
    // Column 2
820
    final r2 = _m4storage[7];
×
821
    _m4storage[4] += tx * r2;
×
822
    _m4storage[5] += ty * r2;
×
823
    _m4storage[6] += tz * r2;
×
824
    _m4storage[7] = tw * r2;
×
825

826
    // Column 3
827
    final r3 = _m4storage[11];
×
828
    _m4storage[8] += tx * r3;
×
829
    _m4storage[9] += ty * r3;
×
830
    _m4storage[10] += tz * r3;
×
831
    _m4storage[11] = tw * r3;
×
832

833
    // Column 4
834
    final r4 = _m4storage[15];
×
835
    _m4storage[12] += tx * r4;
×
836
    _m4storage[13] += ty * r4;
×
837
    _m4storage[14] += tz * r4;
×
838
    _m4storage[15] = tw * r4;
×
839
  }
840

841
  /// Multiply this by a translation from the left.
NEW
842
  @pragma('wasm:prefer-inline')
×
843
  @pragma('vm:prefer-inline')
844
  @pragma('dart2js:prefer-inline')
845
  void leftTranslateByVector2(Vector2 v2) =>
NEW
846
      leftTranslateByDouble(v2.x, v2.y, 0.0, 1.0);
×
847

848
  /// Multiply this by a translation from the left.
849
  @pragma('wasm:prefer-inline')
×
850
  @pragma('vm:prefer-inline')
851
  @pragma('dart2js:prefer-inline')
852
  void leftTranslateByVector3(Vector3 v3) =>
853
      leftTranslateByDouble(v3.x, v3.y, v3.z, 1.0);
×
854

855
  /// Multiply this by a translation from the left.
856
  @pragma('wasm:prefer-inline')
×
857
  @pragma('vm:prefer-inline')
858
  @pragma('dart2js:prefer-inline')
859
  void leftTranslateByVector4(Vector4 v4) =>
860
      leftTranslateByDouble(v4.x, v4.y, v4.z, v4.w);
×
861

862
  /// Rotate this [angle] radians around [axis]
863
  void rotate(Vector3 axis, double angle) {
×
864
    final len = axis.length;
×
865
    final axisStorage = axis._v3storage;
×
866
    final x = axisStorage[0] / len;
×
867
    final y = axisStorage[1] / len;
×
868
    final z = axisStorage[2] / len;
×
869
    final c = math.cos(angle);
×
870
    final s = math.sin(angle);
×
871
    final C = 1.0 - c;
×
872
    final m11 = x * x * C + c;
×
873
    final m12 = x * y * C - z * s;
×
874
    final m13 = x * z * C + y * s;
×
875
    final m21 = y * x * C + z * s;
×
876
    final m22 = y * y * C + c;
×
877
    final m23 = y * z * C - x * s;
×
878
    final m31 = z * x * C - y * s;
×
879
    final m32 = z * y * C + x * s;
×
880
    final m33 = z * z * C + c;
×
881
    final t1 = _m4storage[0] * m11 + _m4storage[4] * m21 + _m4storage[8] * m31;
×
882
    final t2 = _m4storage[1] * m11 + _m4storage[5] * m21 + _m4storage[9] * m31;
×
883
    final t3 = _m4storage[2] * m11 + _m4storage[6] * m21 + _m4storage[10] * m31;
×
884
    final t4 = _m4storage[3] * m11 + _m4storage[7] * m21 + _m4storage[11] * m31;
×
885
    final t5 = _m4storage[0] * m12 + _m4storage[4] * m22 + _m4storage[8] * m32;
×
886
    final t6 = _m4storage[1] * m12 + _m4storage[5] * m22 + _m4storage[9] * m32;
×
887
    final t7 = _m4storage[2] * m12 + _m4storage[6] * m22 + _m4storage[10] * m32;
×
888
    final t8 = _m4storage[3] * m12 + _m4storage[7] * m22 + _m4storage[11] * m32;
×
889
    final t9 = _m4storage[0] * m13 + _m4storage[4] * m23 + _m4storage[8] * m33;
×
890
    final t10 = _m4storage[1] * m13 + _m4storage[5] * m23 + _m4storage[9] * m33;
×
891
    final t11 =
892
        _m4storage[2] * m13 + _m4storage[6] * m23 + _m4storage[10] * m33;
×
893
    final t12 =
894
        _m4storage[3] * m13 + _m4storage[7] * m23 + _m4storage[11] * m33;
×
895
    _m4storage[0] = t1;
×
896
    _m4storage[1] = t2;
×
897
    _m4storage[2] = t3;
×
898
    _m4storage[3] = t4;
×
899
    _m4storage[4] = t5;
×
900
    _m4storage[5] = t6;
×
901
    _m4storage[6] = t7;
×
902
    _m4storage[7] = t8;
×
903
    _m4storage[8] = t9;
×
904
    _m4storage[9] = t10;
×
905
    _m4storage[10] = t11;
×
906
    _m4storage[11] = t12;
×
907
  }
908

909
  /// Rotate this [angle] radians around X
910
  void rotateX(double angle) {
×
911
    final cosAngle = math.cos(angle);
×
912
    final sinAngle = math.sin(angle);
×
913
    final t1 = _m4storage[4] * cosAngle + _m4storage[8] * sinAngle;
×
914
    final t2 = _m4storage[5] * cosAngle + _m4storage[9] * sinAngle;
×
915
    final t3 = _m4storage[6] * cosAngle + _m4storage[10] * sinAngle;
×
916
    final t4 = _m4storage[7] * cosAngle + _m4storage[11] * sinAngle;
×
917
    final t5 = _m4storage[4] * -sinAngle + _m4storage[8] * cosAngle;
×
918
    final t6 = _m4storage[5] * -sinAngle + _m4storage[9] * cosAngle;
×
919
    final t7 = _m4storage[6] * -sinAngle + _m4storage[10] * cosAngle;
×
920
    final t8 = _m4storage[7] * -sinAngle + _m4storage[11] * cosAngle;
×
921
    _m4storage[4] = t1;
×
922
    _m4storage[5] = t2;
×
923
    _m4storage[6] = t3;
×
924
    _m4storage[7] = t4;
×
925
    _m4storage[8] = t5;
×
926
    _m4storage[9] = t6;
×
927
    _m4storage[10] = t7;
×
928
    _m4storage[11] = t8;
×
929
  }
930

931
  /// Rotate this matrix [angle] radians around Y
932
  void rotateY(double angle) {
×
933
    final cosAngle = math.cos(angle);
×
934
    final sinAngle = math.sin(angle);
×
935
    final t1 = _m4storage[0] * cosAngle + _m4storage[8] * -sinAngle;
×
936
    final t2 = _m4storage[1] * cosAngle + _m4storage[9] * -sinAngle;
×
937
    final t3 = _m4storage[2] * cosAngle + _m4storage[10] * -sinAngle;
×
938
    final t4 = _m4storage[3] * cosAngle + _m4storage[11] * -sinAngle;
×
939
    final t5 = _m4storage[0] * sinAngle + _m4storage[8] * cosAngle;
×
940
    final t6 = _m4storage[1] * sinAngle + _m4storage[9] * cosAngle;
×
941
    final t7 = _m4storage[2] * sinAngle + _m4storage[10] * cosAngle;
×
942
    final t8 = _m4storage[3] * sinAngle + _m4storage[11] * cosAngle;
×
943
    _m4storage[0] = t1;
×
944
    _m4storage[1] = t2;
×
945
    _m4storage[2] = t3;
×
946
    _m4storage[3] = t4;
×
947
    _m4storage[8] = t5;
×
948
    _m4storage[9] = t6;
×
949
    _m4storage[10] = t7;
×
950
    _m4storage[11] = t8;
×
951
  }
952

953
  /// Rotate this matrix [angle] radians around Z
954
  void rotateZ(double angle) {
×
955
    final cosAngle = math.cos(angle);
×
956
    final sinAngle = math.sin(angle);
×
957
    final t1 = _m4storage[0] * cosAngle + _m4storage[4] * sinAngle;
×
958
    final t2 = _m4storage[1] * cosAngle + _m4storage[5] * sinAngle;
×
959
    final t3 = _m4storage[2] * cosAngle + _m4storage[6] * sinAngle;
×
960
    final t4 = _m4storage[3] * cosAngle + _m4storage[7] * sinAngle;
×
961
    final t5 = _m4storage[0] * -sinAngle + _m4storage[4] * cosAngle;
×
962
    final t6 = _m4storage[1] * -sinAngle + _m4storage[5] * cosAngle;
×
963
    final t7 = _m4storage[2] * -sinAngle + _m4storage[6] * cosAngle;
×
964
    final t8 = _m4storage[3] * -sinAngle + _m4storage[7] * cosAngle;
×
965
    _m4storage[0] = t1;
×
966
    _m4storage[1] = t2;
×
967
    _m4storage[2] = t3;
×
968
    _m4storage[3] = t4;
×
969
    _m4storage[4] = t5;
×
970
    _m4storage[5] = t6;
×
971
    _m4storage[6] = t7;
×
972
    _m4storage[7] = t8;
×
973
  }
974

975
  /// Scale this matrix by a [Vector3], [Vector4], or x,y,z as [double]s.
976
  ///
977
  /// If you know the argument types in a call site, prefer [scaleByDouble],
978
  /// [scaleByVector3], or [scaleByVector4] for performance.
979
  @pragma('wasm:prefer-inline')
×
980
  @pragma('vm:prefer-inline')
981
  @pragma('dart2js:prefer-inline')
982
  @Deprecated('Use scaleByVector3, scaleByVector4, or scaleByDouble instead')
983
  void scale(dynamic x, [double? y, double? z]) {
984
    if (x is Vector3) {
×
985
      scaleByVector3(x);
×
986
    } else if (x is Vector4) {
×
987
      scaleByVector4(x);
×
988
    } else if (x is double) {
×
989
      scaleByDouble(x, y ?? x, z ?? x, 1.0);
×
990
    } else {
991
      throw UnimplementedError();
×
992
    }
993
  }
994

995
  /// Scale this matrix.
996
  void scaleByDouble(double sx, double sy, double sz, double sw) {
×
997
    _m4storage[0] *= sx;
×
998
    _m4storage[1] *= sx;
×
999
    _m4storage[2] *= sx;
×
1000
    _m4storage[3] *= sx;
×
1001
    _m4storage[4] *= sy;
×
1002
    _m4storage[5] *= sy;
×
1003
    _m4storage[6] *= sy;
×
1004
    _m4storage[7] *= sy;
×
1005
    _m4storage[8] *= sz;
×
1006
    _m4storage[9] *= sz;
×
1007
    _m4storage[10] *= sz;
×
1008
    _m4storage[11] *= sz;
×
1009
    _m4storage[12] *= sw;
×
1010
    _m4storage[13] *= sw;
×
1011
    _m4storage[14] *= sw;
×
1012
    _m4storage[15] *= sw;
×
1013
  }
1014

1015
  /// Scale this matrix.
1016
  @pragma('wasm:prefer-inline')
×
1017
  @pragma('vm:prefer-inline')
1018
  @pragma('dart2js:prefer-inline')
1019
  void scaleByVector3(Vector3 v3) => scaleByDouble(v3.x, v3.y, v3.z, 1.0);
×
1020

1021
  /// Scale this matrix.
1022
  @pragma('wasm:prefer-inline')
×
1023
  @pragma('vm:prefer-inline')
1024
  @pragma('dart2js:prefer-inline')
1025
  void scaleByVector4(Vector4 v4) => scaleByDouble(v4.x, v4.y, v4.z, v4.w);
×
1026

1027
  /// Create a copy of this scaled by a [Vector3], [Vector4] or [x],[y], and
1028
  /// [z].
1029
  @pragma('wasm:prefer-inline')
×
1030
  @pragma('vm:prefer-inline')
1031
  @pragma('dart2js:prefer-inline')
1032
  @Deprecated('Use scaledByVector3, scaledByVector4, or scaledByDouble instead')
1033
  Matrix4 scaled(dynamic x, [double? y, double? z]) => clone()..scale(x, y, z);
×
1034

1035
  /// Create a copy of this scaled by [x], [y], [z], and [t].
1036
  @pragma('wasm:prefer-inline')
×
1037
  @pragma('vm:prefer-inline')
1038
  @pragma('dart2js:prefer-inline')
1039
  Matrix4 scaledByDouble(double x, double y, double z, double t) =>
1040
      clone()..scaleByDouble(x, y, z, t);
×
1041

1042
  /// Create a copy of this scaled by a [Vector3].
1043
  @pragma('wasm:prefer-inline')
×
1044
  @pragma('vm:prefer-inline')
1045
  @pragma('dart2js:prefer-inline')
1046
  Matrix4 scaledByVector3(Vector3 v3) => clone()..scaleByVector3(v3);
×
1047

1048
  /// Create a copy of this scaled by a [Vector4].
1049
  @pragma('wasm:prefer-inline')
×
1050
  @pragma('vm:prefer-inline')
1051
  @pragma('dart2js:prefer-inline')
1052
  Matrix4 scaledByVector4(Vector4 v4) => clone()..scaleByVector4(v4);
×
1053

1054
  /// Zeros this.
1055
  void setZero() {
×
1056
    _m4storage[0] = 0.0;
×
1057
    _m4storage[1] = 0.0;
×
1058
    _m4storage[2] = 0.0;
×
1059
    _m4storage[3] = 0.0;
×
1060
    _m4storage[4] = 0.0;
×
1061
    _m4storage[5] = 0.0;
×
1062
    _m4storage[6] = 0.0;
×
1063
    _m4storage[7] = 0.0;
×
1064
    _m4storage[8] = 0.0;
×
1065
    _m4storage[9] = 0.0;
×
1066
    _m4storage[10] = 0.0;
×
1067
    _m4storage[11] = 0.0;
×
1068
    _m4storage[12] = 0.0;
×
1069
    _m4storage[13] = 0.0;
×
1070
    _m4storage[14] = 0.0;
×
1071
    _m4storage[15] = 0.0;
×
1072
  }
1073

1074
  /// Makes this into the identity matrix.
1075
  void setIdentity() {
×
1076
    _m4storage[0] = 1.0;
×
1077
    _m4storage[1] = 0.0;
×
1078
    _m4storage[2] = 0.0;
×
1079
    _m4storage[3] = 0.0;
×
1080
    _m4storage[4] = 0.0;
×
1081
    _m4storage[5] = 1.0;
×
1082
    _m4storage[6] = 0.0;
×
1083
    _m4storage[7] = 0.0;
×
1084
    _m4storage[8] = 0.0;
×
1085
    _m4storage[9] = 0.0;
×
1086
    _m4storage[10] = 1.0;
×
1087
    _m4storage[11] = 0.0;
×
1088
    _m4storage[12] = 0.0;
×
1089
    _m4storage[13] = 0.0;
×
1090
    _m4storage[14] = 0.0;
×
1091
    _m4storage[15] = 1.0;
×
1092
  }
1093

1094
  /// Returns the tranpose of this.
1095
  Matrix4 transposed() => clone()..transpose();
×
1096

1097
  void transpose() {
×
1098
    double temp;
1099
    temp = _m4storage[4];
×
1100
    _m4storage[4] = _m4storage[1];
×
1101
    _m4storage[1] = temp;
×
1102
    temp = _m4storage[8];
×
1103
    _m4storage[8] = _m4storage[2];
×
1104
    _m4storage[2] = temp;
×
1105
    temp = _m4storage[12];
×
1106
    _m4storage[12] = _m4storage[3];
×
1107
    _m4storage[3] = temp;
×
1108
    temp = _m4storage[9];
×
1109
    _m4storage[9] = _m4storage[6];
×
1110
    _m4storage[6] = temp;
×
1111
    temp = _m4storage[13];
×
1112
    _m4storage[13] = _m4storage[7];
×
1113
    _m4storage[7] = temp;
×
1114
    temp = _m4storage[14];
×
1115
    _m4storage[14] = _m4storage[11];
×
1116
    _m4storage[11] = temp;
×
1117
  }
1118

1119
  /// Returns the component wise absolute value of this.
1120
  Matrix4 absolute() {
×
1121
    final r = Matrix4.zero();
×
1122
    final rStorage = r._m4storage;
×
1123
    rStorage[0] = _m4storage[0].abs();
×
1124
    rStorage[1] = _m4storage[1].abs();
×
1125
    rStorage[2] = _m4storage[2].abs();
×
1126
    rStorage[3] = _m4storage[3].abs();
×
1127
    rStorage[4] = _m4storage[4].abs();
×
1128
    rStorage[5] = _m4storage[5].abs();
×
1129
    rStorage[6] = _m4storage[6].abs();
×
1130
    rStorage[7] = _m4storage[7].abs();
×
1131
    rStorage[8] = _m4storage[8].abs();
×
1132
    rStorage[9] = _m4storage[9].abs();
×
1133
    rStorage[10] = _m4storage[10].abs();
×
1134
    rStorage[11] = _m4storage[11].abs();
×
1135
    rStorage[12] = _m4storage[12].abs();
×
1136
    rStorage[13] = _m4storage[13].abs();
×
1137
    rStorage[14] = _m4storage[14].abs();
×
1138
    rStorage[15] = _m4storage[15].abs();
×
1139
    return r;
1140
  }
1141

1142
  /// Returns the determinant of this matrix.
1143
  double determinant() {
×
1144
    final det2_01_01 =
1145
        _m4storage[0] * _m4storage[5] - _m4storage[1] * _m4storage[4];
×
1146
    final det2_01_02 =
1147
        _m4storage[0] * _m4storage[6] - _m4storage[2] * _m4storage[4];
×
1148
    final det2_01_03 =
1149
        _m4storage[0] * _m4storage[7] - _m4storage[3] * _m4storage[4];
×
1150
    final det2_01_12 =
1151
        _m4storage[1] * _m4storage[6] - _m4storage[2] * _m4storage[5];
×
1152
    final det2_01_13 =
1153
        _m4storage[1] * _m4storage[7] - _m4storage[3] * _m4storage[5];
×
1154
    final det2_01_23 =
1155
        _m4storage[2] * _m4storage[7] - _m4storage[3] * _m4storage[6];
×
1156
    final det3_201_012 =
1157
        _m4storage[8] * det2_01_12 -
×
1158
        _m4storage[9] * det2_01_02 +
×
1159
        _m4storage[10] * det2_01_01;
×
1160
    final det3_201_013 =
1161
        _m4storage[8] * det2_01_13 -
×
1162
        _m4storage[9] * det2_01_03 +
×
1163
        _m4storage[11] * det2_01_01;
×
1164
    final det3_201_023 =
1165
        _m4storage[8] * det2_01_23 -
×
1166
        _m4storage[10] * det2_01_03 +
×
1167
        _m4storage[11] * det2_01_02;
×
1168
    final det3_201_123 =
1169
        _m4storage[9] * det2_01_23 -
×
1170
        _m4storage[10] * det2_01_13 +
×
1171
        _m4storage[11] * det2_01_12;
×
1172
    return -det3_201_123 * _m4storage[12] +
×
1173
        det3_201_023 * _m4storage[13] -
×
1174
        det3_201_013 * _m4storage[14] +
×
1175
        det3_201_012 * _m4storage[15];
×
1176
  }
1177

1178
  /// Returns the dot product of row [i] and [v].
1179
  double dotRow(int i, Vector4 v) {
×
1180
    final vStorage = v._v4storage;
×
1181
    return _m4storage[i] * vStorage[0] +
×
1182
        _m4storage[4 + i] * vStorage[1] +
×
1183
        _m4storage[8 + i] * vStorage[2] +
×
1184
        _m4storage[12 + i] * vStorage[3];
×
1185
  }
1186

1187
  /// Returns the dot product of column [j] and [v].
1188
  double dotColumn(int j, Vector4 v) {
×
1189
    final vStorage = v._v4storage;
×
1190
    return _m4storage[j * 4] * vStorage[0] +
×
1191
        _m4storage[j * 4 + 1] * vStorage[1] +
×
1192
        _m4storage[j * 4 + 2] * vStorage[2] +
×
1193
        _m4storage[j * 4 + 3] * vStorage[3];
×
1194
  }
1195

1196
  /// Returns the trace of the matrix. The trace of a matrix is the sum of the
1197
  /// diagonal entries.
1198
  double trace() {
×
1199
    var t = 0.0;
1200
    t += _m4storage[0];
×
1201
    t += _m4storage[5];
×
1202
    t += _m4storage[10];
×
1203
    t += _m4storage[15];
×
1204
    return t;
1205
  }
1206

1207
  /// Returns infinity norm of the matrix. Used for numerical analysis.
1208
  double infinityNorm() {
×
1209
    var norm = 0.0;
1210
    {
1211
      var row_norm = 0.0;
1212
      row_norm += _m4storage[0].abs();
×
1213
      row_norm += _m4storage[1].abs();
×
1214
      row_norm += _m4storage[2].abs();
×
1215
      row_norm += _m4storage[3].abs();
×
1216
      norm = row_norm > norm ? row_norm : norm;
×
1217
    }
1218
    {
1219
      var row_norm = 0.0;
1220
      row_norm += _m4storage[4].abs();
×
1221
      row_norm += _m4storage[5].abs();
×
1222
      row_norm += _m4storage[6].abs();
×
1223
      row_norm += _m4storage[7].abs();
×
1224
      norm = row_norm > norm ? row_norm : norm;
×
1225
    }
1226
    {
1227
      var row_norm = 0.0;
1228
      row_norm += _m4storage[8].abs();
×
1229
      row_norm += _m4storage[9].abs();
×
1230
      row_norm += _m4storage[10].abs();
×
1231
      row_norm += _m4storage[11].abs();
×
1232
      norm = row_norm > norm ? row_norm : norm;
×
1233
    }
1234
    {
1235
      var row_norm = 0.0;
1236
      row_norm += _m4storage[12].abs();
×
1237
      row_norm += _m4storage[13].abs();
×
1238
      row_norm += _m4storage[14].abs();
×
1239
      row_norm += _m4storage[15].abs();
×
1240
      norm = row_norm > norm ? row_norm : norm;
×
1241
    }
1242
    return norm;
1243
  }
1244

1245
  /// Returns relative error between this and [correct]
1246
  double relativeError(Matrix4 correct) {
×
1247
    final diff = correct - this;
×
1248
    final correct_norm = correct.infinityNorm();
×
1249
    final diff_norm = diff.infinityNorm();
×
1250
    return diff_norm / correct_norm;
×
1251
  }
1252

1253
  /// Returns absolute error between this and [correct]
1254
  double absoluteError(Matrix4 correct) {
×
1255
    final this_norm = infinityNorm();
×
1256
    final correct_norm = correct.infinityNorm();
×
1257
    final diff_norm = (this_norm - correct_norm).abs();
×
1258
    return diff_norm;
1259
  }
1260

1261
  /// Returns the translation vector from this homogeneous transformation
1262
  /// matrix.
1263
  Vector3 getTranslation() {
×
1264
    final z = _m4storage[14];
×
1265
    final y = _m4storage[13];
×
1266
    final x = _m4storage[12];
×
1267
    return Vector3(x, y, z);
×
1268
  }
1269

1270
  /// Sets the translation vector in this homogeneous transformation matrix.
1271
  void setTranslation(Vector3 t) {
×
1272
    final tStorage = t._v3storage;
×
1273
    final z = tStorage[2];
×
1274
    final y = tStorage[1];
×
1275
    final x = tStorage[0];
×
1276
    _m4storage[14] = z;
×
1277
    _m4storage[13] = y;
×
1278
    _m4storage[12] = x;
×
1279
  }
1280

1281
  /// Sets the translation vector in this homogeneous transformation matrix.
1282
  void setTranslationRaw(double x, double y, double z) {
×
1283
    _m4storage[14] = z;
×
1284
    _m4storage[13] = y;
×
1285
    _m4storage[12] = x;
×
1286
  }
1287

1288
  /// Returns the rotation matrix from this homogeneous transformation matrix.
1289
  Matrix3 getRotation() {
×
1290
    final r = Matrix3.zero();
×
1291
    copyRotation(r);
×
1292
    return r;
1293
  }
1294

1295
  /// Copies the rotation matrix from this homogeneous transformation matrix
1296
  /// into [rotation].
1297
  void copyRotation(Matrix3 rotation) {
×
1298
    final rStorage = rotation._m3storage;
×
1299
    rStorage[0] = _m4storage[0];
×
1300
    rStorage[1] = _m4storage[1];
×
1301
    rStorage[2] = _m4storage[2];
×
1302
    rStorage[3] = _m4storage[4];
×
1303
    rStorage[4] = _m4storage[5];
×
1304
    rStorage[5] = _m4storage[6];
×
1305
    rStorage[6] = _m4storage[8];
×
1306
    rStorage[7] = _m4storage[9];
×
1307
    rStorage[8] = _m4storage[10];
×
1308
  }
1309

1310
  /// Sets the rotation matrix in this homogeneous transformation matrix.
1311
  void setRotation(Matrix3 r) {
×
1312
    final rStorage = r._m3storage;
×
1313
    _m4storage[0] = rStorage[0];
×
1314
    _m4storage[1] = rStorage[1];
×
1315
    _m4storage[2] = rStorage[2];
×
1316
    _m4storage[4] = rStorage[3];
×
1317
    _m4storage[5] = rStorage[4];
×
1318
    _m4storage[6] = rStorage[5];
×
1319
    _m4storage[8] = rStorage[6];
×
1320
    _m4storage[9] = rStorage[7];
×
1321
    _m4storage[10] = rStorage[8];
×
1322
  }
1323

1324
  /// Returns the normal matrix from this homogeneous transformation matrix.
1325
  ///
1326
  /// The normal matrix is the transpose of the inverse of the top-left 3x3 part
1327
  /// of this 4x4 matrix.
1328
  Matrix3 getNormalMatrix() => Matrix3.identity()..copyNormalMatrix(this);
×
1329

1330
  /// Returns the max scale value of the 3 axes.
1331
  double getMaxScaleOnAxis() {
×
1332
    final scaleXSq =
1333
        _m4storage[0] * _m4storage[0] +
×
1334
        _m4storage[1] * _m4storage[1] +
×
1335
        _m4storage[2] * _m4storage[2];
×
1336
    final scaleYSq =
1337
        _m4storage[4] * _m4storage[4] +
×
1338
        _m4storage[5] * _m4storage[5] +
×
1339
        _m4storage[6] * _m4storage[6];
×
1340
    final scaleZSq =
1341
        _m4storage[8] * _m4storage[8] +
×
1342
        _m4storage[9] * _m4storage[9] +
×
1343
        _m4storage[10] * _m4storage[10];
×
1344
    return math.sqrt(math.max(scaleXSq, math.max(scaleYSq, scaleZSq)));
×
1345
  }
1346

1347
  /// Transposes just the upper 3x3 rotation matrix.
1348
  void transposeRotation() {
×
1349
    double temp;
1350
    temp = _m4storage[1];
×
1351
    _m4storage[1] = _m4storage[4];
×
1352
    _m4storage[4] = temp;
×
1353
    temp = _m4storage[2];
×
1354
    _m4storage[2] = _m4storage[8];
×
1355
    _m4storage[8] = temp;
×
1356
    temp = _m4storage[4];
×
1357
    _m4storage[4] = _m4storage[1];
×
1358
    _m4storage[1] = temp;
×
1359
    temp = _m4storage[6];
×
1360
    _m4storage[6] = _m4storage[9];
×
1361
    _m4storage[9] = temp;
×
1362
    temp = _m4storage[8];
×
1363
    _m4storage[8] = _m4storage[2];
×
1364
    _m4storage[2] = temp;
×
1365
    temp = _m4storage[9];
×
1366
    _m4storage[9] = _m4storage[6];
×
1367
    _m4storage[6] = temp;
×
1368
  }
1369

1370
  /// Invert this.
1371
  double invert() => copyInverse(this);
×
1372

1373
  /// Set this matrix to be the inverse of [arg]
1374
  double copyInverse(Matrix4 arg) {
×
1375
    final argStorage = arg._m4storage;
×
1376
    final a00 = argStorage[0];
×
1377
    final a01 = argStorage[1];
×
1378
    final a02 = argStorage[2];
×
1379
    final a03 = argStorage[3];
×
1380
    final a10 = argStorage[4];
×
1381
    final a11 = argStorage[5];
×
1382
    final a12 = argStorage[6];
×
1383
    final a13 = argStorage[7];
×
1384
    final a20 = argStorage[8];
×
1385
    final a21 = argStorage[9];
×
1386
    final a22 = argStorage[10];
×
1387
    final a23 = argStorage[11];
×
1388
    final a30 = argStorage[12];
×
1389
    final a31 = argStorage[13];
×
1390
    final a32 = argStorage[14];
×
1391
    final a33 = argStorage[15];
×
1392
    final b00 = a00 * a11 - a01 * a10;
×
1393
    final b01 = a00 * a12 - a02 * a10;
×
1394
    final b02 = a00 * a13 - a03 * a10;
×
1395
    final b03 = a01 * a12 - a02 * a11;
×
1396
    final b04 = a01 * a13 - a03 * a11;
×
1397
    final b05 = a02 * a13 - a03 * a12;
×
1398
    final b06 = a20 * a31 - a21 * a30;
×
1399
    final b07 = a20 * a32 - a22 * a30;
×
1400
    final b08 = a20 * a33 - a23 * a30;
×
1401
    final b09 = a21 * a32 - a22 * a31;
×
1402
    final b10 = a21 * a33 - a23 * a31;
×
1403
    final b11 = a22 * a33 - a23 * a32;
×
1404
    final det =
1405
        b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
×
1406
    if (det == 0.0) {
×
1407
      setFrom(arg);
×
1408
      return 0.0;
1409
    }
1410
    final invDet = 1.0 / det;
×
1411
    _m4storage[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;
×
1412
    _m4storage[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;
×
1413
    _m4storage[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;
×
1414
    _m4storage[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;
×
1415
    _m4storage[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;
×
1416
    _m4storage[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;
×
1417
    _m4storage[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;
×
1418
    _m4storage[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;
×
1419
    _m4storage[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;
×
1420
    _m4storage[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;
×
1421
    _m4storage[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;
×
1422
    _m4storage[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;
×
1423
    _m4storage[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;
×
1424
    _m4storage[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;
×
1425
    _m4storage[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;
×
1426
    _m4storage[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;
×
1427
    return det;
1428
  }
1429

1430
  double invertRotation() {
×
1431
    final det = determinant();
×
1432
    if (det == 0.0) {
×
1433
      return 0.0;
1434
    }
1435
    final invDet = 1.0 / det;
×
1436
    double ix;
1437
    double iy;
1438
    double iz;
1439
    double jx;
1440
    double jy;
1441
    double jz;
1442
    double kx;
1443
    double ky;
1444
    double kz;
1445
    ix =
1446
        invDet *
×
1447
        (_m4storage[5] * _m4storage[10] - _m4storage[6] * _m4storage[9]);
×
1448
    iy =
1449
        invDet *
×
1450
        (_m4storage[2] * _m4storage[9] - _m4storage[1] * _m4storage[10]);
×
1451
    iz =
1452
        invDet *
×
1453
        (_m4storage[1] * _m4storage[6] - _m4storage[2] * _m4storage[5]);
×
1454
    jx =
1455
        invDet *
×
1456
        (_m4storage[6] * _m4storage[8] - _m4storage[4] * _m4storage[10]);
×
1457
    jy =
1458
        invDet *
×
1459
        (_m4storage[0] * _m4storage[10] - _m4storage[2] * _m4storage[8]);
×
1460
    jz =
1461
        invDet *
×
1462
        (_m4storage[2] * _m4storage[4] - _m4storage[0] * _m4storage[6]);
×
1463
    kx =
1464
        invDet *
×
1465
        (_m4storage[4] * _m4storage[9] - _m4storage[5] * _m4storage[8]);
×
1466
    ky =
1467
        invDet *
×
1468
        (_m4storage[1] * _m4storage[8] - _m4storage[0] * _m4storage[9]);
×
1469
    kz =
1470
        invDet *
×
1471
        (_m4storage[0] * _m4storage[5] - _m4storage[1] * _m4storage[4]);
×
1472
    _m4storage[0] = ix;
×
1473
    _m4storage[1] = iy;
×
1474
    _m4storage[2] = iz;
×
1475
    _m4storage[4] = jx;
×
1476
    _m4storage[5] = jy;
×
1477
    _m4storage[6] = jz;
×
1478
    _m4storage[8] = kx;
×
1479
    _m4storage[9] = ky;
×
1480
    _m4storage[10] = kz;
×
1481
    return det;
1482
  }
1483

1484
  /// Sets the upper 3x3 to a rotation of [radians] around X
1485
  void setRotationX(double radians) {
×
1486
    final c = math.cos(radians);
×
1487
    final s = math.sin(radians);
×
1488
    _m4storage[0] = 1.0;
×
1489
    _m4storage[1] = 0.0;
×
1490
    _m4storage[2] = 0.0;
×
1491
    _m4storage[4] = 0.0;
×
1492
    _m4storage[5] = c;
×
1493
    _m4storage[6] = s;
×
1494
    _m4storage[8] = 0.0;
×
1495
    _m4storage[9] = -s;
×
1496
    _m4storage[10] = c;
×
1497
    _m4storage[3] = 0.0;
×
1498
    _m4storage[7] = 0.0;
×
1499
    _m4storage[11] = 0.0;
×
1500
  }
1501

1502
  /// Sets the upper 3x3 to a rotation of [radians] around Y
1503
  void setRotationY(double radians) {
×
1504
    final c = math.cos(radians);
×
1505
    final s = math.sin(radians);
×
1506
    _m4storage[0] = c;
×
1507
    _m4storage[1] = 0.0;
×
1508
    _m4storage[2] = -s;
×
1509
    _m4storage[4] = 0.0;
×
1510
    _m4storage[5] = 1.0;
×
1511
    _m4storage[6] = 0.0;
×
1512
    _m4storage[8] = s;
×
1513
    _m4storage[9] = 0.0;
×
1514
    _m4storage[10] = c;
×
1515
    _m4storage[3] = 0.0;
×
1516
    _m4storage[7] = 0.0;
×
1517
    _m4storage[11] = 0.0;
×
1518
  }
1519

1520
  /// Sets the upper 3x3 to a rotation of [radians] around Z
1521
  void setRotationZ(double radians) {
×
1522
    final c = math.cos(radians);
×
1523
    final s = math.sin(radians);
×
1524
    _m4storage[0] = c;
×
1525
    _m4storage[1] = s;
×
1526
    _m4storage[2] = 0.0;
×
1527
    _m4storage[4] = -s;
×
1528
    _m4storage[5] = c;
×
1529
    _m4storage[6] = 0.0;
×
1530
    _m4storage[8] = 0.0;
×
1531
    _m4storage[9] = 0.0;
×
1532
    _m4storage[10] = 1.0;
×
1533
    _m4storage[3] = 0.0;
×
1534
    _m4storage[7] = 0.0;
×
1535
    _m4storage[11] = 0.0;
×
1536
  }
1537

1538
  /// Converts into Adjugate matrix and scales by [scale]
1539
  void scaleAdjoint(double scale) {
×
1540
    // Adapted from code by Richard Carling.
1541
    final a1 = _m4storage[0];
×
1542
    final b1 = _m4storage[4];
×
1543
    final c1 = _m4storage[8];
×
1544
    final d1 = _m4storage[12];
×
1545
    final a2 = _m4storage[1];
×
1546
    final b2 = _m4storage[5];
×
1547
    final c2 = _m4storage[9];
×
1548
    final d2 = _m4storage[13];
×
1549
    final a3 = _m4storage[2];
×
1550
    final b3 = _m4storage[6];
×
1551
    final c3 = _m4storage[10];
×
1552
    final d3 = _m4storage[14];
×
1553
    final a4 = _m4storage[3];
×
1554
    final b4 = _m4storage[7];
×
1555
    final c4 = _m4storage[11];
×
1556
    final d4 = _m4storage[15];
×
1557
    _m4storage[0] =
×
1558
        (b2 * (c3 * d4 - c4 * d3) -
×
1559
            c2 * (b3 * d4 - b4 * d3) +
×
1560
            d2 * (b3 * c4 - b4 * c3)) *
×
1561
        scale;
1562
    _m4storage[1] =
×
1563
        -(a2 * (c3 * d4 - c4 * d3) -
×
1564
            c2 * (a3 * d4 - a4 * d3) +
×
1565
            d2 * (a3 * c4 - a4 * c3)) *
×
1566
        scale;
1567
    _m4storage[2] =
×
1568
        (a2 * (b3 * d4 - b4 * d3) -
×
1569
            b2 * (a3 * d4 - a4 * d3) +
×
1570
            d2 * (a3 * b4 - a4 * b3)) *
×
1571
        scale;
1572
    _m4storage[3] =
×
1573
        -(a2 * (b3 * c4 - b4 * c3) -
×
1574
            b2 * (a3 * c4 - a4 * c3) +
×
1575
            c2 * (a3 * b4 - a4 * b3)) *
×
1576
        scale;
1577
    _m4storage[4] =
×
1578
        -(b1 * (c3 * d4 - c4 * d3) -
×
1579
            c1 * (b3 * d4 - b4 * d3) +
×
1580
            d1 * (b3 * c4 - b4 * c3)) *
×
1581
        scale;
1582
    _m4storage[5] =
×
1583
        (a1 * (c3 * d4 - c4 * d3) -
×
1584
            c1 * (a3 * d4 - a4 * d3) +
×
1585
            d1 * (a3 * c4 - a4 * c3)) *
×
1586
        scale;
1587
    _m4storage[6] =
×
1588
        -(a1 * (b3 * d4 - b4 * d3) -
×
1589
            b1 * (a3 * d4 - a4 * d3) +
×
1590
            d1 * (a3 * b4 - a4 * b3)) *
×
1591
        scale;
1592
    _m4storage[7] =
×
1593
        (a1 * (b3 * c4 - b4 * c3) -
×
1594
            b1 * (a3 * c4 - a4 * c3) +
×
1595
            c1 * (a3 * b4 - a4 * b3)) *
×
1596
        scale;
1597
    _m4storage[8] =
×
1598
        (b1 * (c2 * d4 - c4 * d2) -
×
1599
            c1 * (b2 * d4 - b4 * d2) +
×
1600
            d1 * (b2 * c4 - b4 * c2)) *
×
1601
        scale;
1602
    _m4storage[9] =
×
1603
        -(a1 * (c2 * d4 - c4 * d2) -
×
1604
            c1 * (a2 * d4 - a4 * d2) +
×
1605
            d1 * (a2 * c4 - a4 * c2)) *
×
1606
        scale;
1607
    _m4storage[10] =
×
1608
        (a1 * (b2 * d4 - b4 * d2) -
×
1609
            b1 * (a2 * d4 - a4 * d2) +
×
1610
            d1 * (a2 * b4 - a4 * b2)) *
×
1611
        scale;
1612
    _m4storage[11] =
×
1613
        -(a1 * (b2 * c4 - b4 * c2) -
×
1614
            b1 * (a2 * c4 - a4 * c2) +
×
1615
            c1 * (a2 * b4 - a4 * b2)) *
×
1616
        scale;
1617
    _m4storage[12] =
×
1618
        -(b1 * (c2 * d3 - c3 * d2) -
×
1619
            c1 * (b2 * d3 - b3 * d2) +
×
1620
            d1 * (b2 * c3 - b3 * c2)) *
×
1621
        scale;
1622
    _m4storage[13] =
×
1623
        (a1 * (c2 * d3 - c3 * d2) -
×
1624
            c1 * (a2 * d3 - a3 * d2) +
×
1625
            d1 * (a2 * c3 - a3 * c2)) *
×
1626
        scale;
1627
    _m4storage[14] =
×
1628
        -(a1 * (b2 * d3 - b3 * d2) -
×
1629
            b1 * (a2 * d3 - a3 * d2) +
×
1630
            d1 * (a2 * b3 - a3 * b2)) *
×
1631
        scale;
1632
    _m4storage[15] =
×
1633
        (a1 * (b2 * c3 - b3 * c2) -
×
1634
            b1 * (a2 * c3 - a3 * c2) +
×
1635
            c1 * (a2 * b3 - a3 * b2)) *
×
1636
        scale;
1637
  }
1638

1639
  /// Rotates [arg] by the absolute rotation of this
1640
  /// Returns [arg].
1641
  /// Primarily used by AABB transformation code.
1642
  Vector3 absoluteRotate(Vector3 arg) {
×
1643
    final m00 = _m4storage[0].abs();
×
1644
    final m01 = _m4storage[4].abs();
×
1645
    final m02 = _m4storage[8].abs();
×
1646
    final m10 = _m4storage[1].abs();
×
1647
    final m11 = _m4storage[5].abs();
×
1648
    final m12 = _m4storage[9].abs();
×
1649
    final m20 = _m4storage[2].abs();
×
1650
    final m21 = _m4storage[6].abs();
×
1651
    final m22 = _m4storage[10].abs();
×
1652
    final argStorage = arg._v3storage;
×
1653
    final x = argStorage[0];
×
1654
    final y = argStorage[1];
×
1655
    final z = argStorage[2];
×
1656
    argStorage[0] = x * m00 + y * m01 + z * m02 + 0.0 * 0.0;
×
1657
    argStorage[1] = x * m10 + y * m11 + z * m12 + 0.0 * 0.0;
×
1658
    argStorage[2] = x * m20 + y * m21 + z * m22 + 0.0 * 0.0;
×
1659
    return arg;
1660
  }
1661

1662
  /// Adds [o] to this.
1663
  void add(Matrix4 o) {
×
1664
    final oStorage = o._m4storage;
×
1665
    _m4storage[0] = _m4storage[0] + oStorage[0];
×
1666
    _m4storage[1] = _m4storage[1] + oStorage[1];
×
1667
    _m4storage[2] = _m4storage[2] + oStorage[2];
×
1668
    _m4storage[3] = _m4storage[3] + oStorage[3];
×
1669
    _m4storage[4] = _m4storage[4] + oStorage[4];
×
1670
    _m4storage[5] = _m4storage[5] + oStorage[5];
×
1671
    _m4storage[6] = _m4storage[6] + oStorage[6];
×
1672
    _m4storage[7] = _m4storage[7] + oStorage[7];
×
1673
    _m4storage[8] = _m4storage[8] + oStorage[8];
×
1674
    _m4storage[9] = _m4storage[9] + oStorage[9];
×
1675
    _m4storage[10] = _m4storage[10] + oStorage[10];
×
1676
    _m4storage[11] = _m4storage[11] + oStorage[11];
×
1677
    _m4storage[12] = _m4storage[12] + oStorage[12];
×
1678
    _m4storage[13] = _m4storage[13] + oStorage[13];
×
1679
    _m4storage[14] = _m4storage[14] + oStorage[14];
×
1680
    _m4storage[15] = _m4storage[15] + oStorage[15];
×
1681
  }
1682

1683
  /// Subtracts [o] from this.
1684
  void sub(Matrix4 o) {
×
1685
    final oStorage = o._m4storage;
×
1686
    _m4storage[0] = _m4storage[0] - oStorage[0];
×
1687
    _m4storage[1] = _m4storage[1] - oStorage[1];
×
1688
    _m4storage[2] = _m4storage[2] - oStorage[2];
×
1689
    _m4storage[3] = _m4storage[3] - oStorage[3];
×
1690
    _m4storage[4] = _m4storage[4] - oStorage[4];
×
1691
    _m4storage[5] = _m4storage[5] - oStorage[5];
×
1692
    _m4storage[6] = _m4storage[6] - oStorage[6];
×
1693
    _m4storage[7] = _m4storage[7] - oStorage[7];
×
1694
    _m4storage[8] = _m4storage[8] - oStorage[8];
×
1695
    _m4storage[9] = _m4storage[9] - oStorage[9];
×
1696
    _m4storage[10] = _m4storage[10] - oStorage[10];
×
1697
    _m4storage[11] = _m4storage[11] - oStorage[11];
×
1698
    _m4storage[12] = _m4storage[12] - oStorage[12];
×
1699
    _m4storage[13] = _m4storage[13] - oStorage[13];
×
1700
    _m4storage[14] = _m4storage[14] - oStorage[14];
×
1701
    _m4storage[15] = _m4storage[15] - oStorage[15];
×
1702
  }
1703

1704
  /// Negate this.
1705
  void negate() {
×
1706
    _m4storage[0] = -_m4storage[0];
×
1707
    _m4storage[1] = -_m4storage[1];
×
1708
    _m4storage[2] = -_m4storage[2];
×
1709
    _m4storage[3] = -_m4storage[3];
×
1710
    _m4storage[4] = -_m4storage[4];
×
1711
    _m4storage[5] = -_m4storage[5];
×
1712
    _m4storage[6] = -_m4storage[6];
×
1713
    _m4storage[7] = -_m4storage[7];
×
1714
    _m4storage[8] = -_m4storage[8];
×
1715
    _m4storage[9] = -_m4storage[9];
×
1716
    _m4storage[10] = -_m4storage[10];
×
1717
    _m4storage[11] = -_m4storage[11];
×
1718
    _m4storage[12] = -_m4storage[12];
×
1719
    _m4storage[13] = -_m4storage[13];
×
1720
    _m4storage[14] = -_m4storage[14];
×
1721
    _m4storage[15] = -_m4storage[15];
×
1722
  }
1723

1724
  /// Multiply this by [arg].
1725
  void multiply(Matrix4 arg) {
×
1726
    final m00 = _m4storage[0];
×
1727
    final m01 = _m4storage[4];
×
1728
    final m02 = _m4storage[8];
×
1729
    final m03 = _m4storage[12];
×
1730
    final m10 = _m4storage[1];
×
1731
    final m11 = _m4storage[5];
×
1732
    final m12 = _m4storage[9];
×
1733
    final m13 = _m4storage[13];
×
1734
    final m20 = _m4storage[2];
×
1735
    final m21 = _m4storage[6];
×
1736
    final m22 = _m4storage[10];
×
1737
    final m23 = _m4storage[14];
×
1738
    final m30 = _m4storage[3];
×
1739
    final m31 = _m4storage[7];
×
1740
    final m32 = _m4storage[11];
×
1741
    final m33 = _m4storage[15];
×
1742
    final argStorage = arg._m4storage;
×
1743
    final n00 = argStorage[0];
×
1744
    final n01 = argStorage[4];
×
1745
    final n02 = argStorage[8];
×
1746
    final n03 = argStorage[12];
×
1747
    final n10 = argStorage[1];
×
1748
    final n11 = argStorage[5];
×
1749
    final n12 = argStorage[9];
×
1750
    final n13 = argStorage[13];
×
1751
    final n20 = argStorage[2];
×
1752
    final n21 = argStorage[6];
×
1753
    final n22 = argStorage[10];
×
1754
    final n23 = argStorage[14];
×
1755
    final n30 = argStorage[3];
×
1756
    final n31 = argStorage[7];
×
1757
    final n32 = argStorage[11];
×
1758
    final n33 = argStorage[15];
×
1759
    _m4storage[0] = (m00 * n00) + (m01 * n10) + (m02 * n20) + (m03 * n30);
×
1760
    _m4storage[4] = (m00 * n01) + (m01 * n11) + (m02 * n21) + (m03 * n31);
×
1761
    _m4storage[8] = (m00 * n02) + (m01 * n12) + (m02 * n22) + (m03 * n32);
×
1762
    _m4storage[12] = (m00 * n03) + (m01 * n13) + (m02 * n23) + (m03 * n33);
×
1763
    _m4storage[1] = (m10 * n00) + (m11 * n10) + (m12 * n20) + (m13 * n30);
×
1764
    _m4storage[5] = (m10 * n01) + (m11 * n11) + (m12 * n21) + (m13 * n31);
×
1765
    _m4storage[9] = (m10 * n02) + (m11 * n12) + (m12 * n22) + (m13 * n32);
×
1766
    _m4storage[13] = (m10 * n03) + (m11 * n13) + (m12 * n23) + (m13 * n33);
×
1767
    _m4storage[2] = (m20 * n00) + (m21 * n10) + (m22 * n20) + (m23 * n30);
×
1768
    _m4storage[6] = (m20 * n01) + (m21 * n11) + (m22 * n21) + (m23 * n31);
×
1769
    _m4storage[10] = (m20 * n02) + (m21 * n12) + (m22 * n22) + (m23 * n32);
×
1770
    _m4storage[14] = (m20 * n03) + (m21 * n13) + (m22 * n23) + (m23 * n33);
×
1771
    _m4storage[3] = (m30 * n00) + (m31 * n10) + (m32 * n20) + (m33 * n30);
×
1772
    _m4storage[7] = (m30 * n01) + (m31 * n11) + (m32 * n21) + (m33 * n31);
×
1773
    _m4storage[11] = (m30 * n02) + (m31 * n12) + (m32 * n22) + (m33 * n32);
×
1774
    _m4storage[15] = (m30 * n03) + (m31 * n13) + (m32 * n23) + (m33 * n33);
×
1775
  }
1776

1777
  /// Computes the result of `arg x this` and stores the result in-place in
1778
  /// `this`.
1779
  ///
1780
  /// This method does not alter the [Matrix4] in [arg].
1781
  void leftMultiply(Matrix4 arg) {
×
1782
    final argStorage = arg._m4storage;
×
1783
    final m00 = argStorage[0];
×
1784
    final m01 = argStorage[4];
×
1785
    final m02 = argStorage[8];
×
1786
    final m03 = argStorage[12];
×
1787
    final m10 = argStorage[1];
×
1788
    final m11 = argStorage[5];
×
1789
    final m12 = argStorage[9];
×
1790
    final m13 = argStorage[13];
×
1791
    final m20 = argStorage[2];
×
1792
    final m21 = argStorage[6];
×
1793
    final m22 = argStorage[10];
×
1794
    final m23 = argStorage[14];
×
1795
    final m30 = argStorage[3];
×
1796
    final m31 = argStorage[7];
×
1797
    final m32 = argStorage[11];
×
1798
    final m33 = argStorage[15];
×
1799
    final bStorage = _m4storage;
×
1800
    final n00 = bStorage[0];
×
1801
    final n01 = bStorage[4];
×
1802
    final n02 = bStorage[8];
×
1803
    final n03 = bStorage[12];
×
1804
    final n10 = bStorage[1];
×
1805
    final n11 = bStorage[5];
×
1806
    final n12 = bStorage[9];
×
1807
    final n13 = bStorage[13];
×
1808
    final n20 = bStorage[2];
×
1809
    final n21 = bStorage[6];
×
1810
    final n22 = bStorage[10];
×
1811
    final n23 = bStorage[14];
×
1812
    final n30 = bStorage[3];
×
1813
    final n31 = bStorage[7];
×
1814
    final n32 = bStorage[11];
×
1815
    final n33 = bStorage[15];
×
1816
    bStorage[0] = (m00 * n00) + (m01 * n10) + (m02 * n20) + (m03 * n30);
×
1817
    bStorage[4] = (m00 * n01) + (m01 * n11) + (m02 * n21) + (m03 * n31);
×
1818
    bStorage[8] = (m00 * n02) + (m01 * n12) + (m02 * n22) + (m03 * n32);
×
1819
    bStorage[12] = (m00 * n03) + (m01 * n13) + (m02 * n23) + (m03 * n33);
×
1820
    bStorage[1] = (m10 * n00) + (m11 * n10) + (m12 * n20) + (m13 * n30);
×
1821
    bStorage[5] = (m10 * n01) + (m11 * n11) + (m12 * n21) + (m13 * n31);
×
1822
    bStorage[9] = (m10 * n02) + (m11 * n12) + (m12 * n22) + (m13 * n32);
×
1823
    bStorage[13] = (m10 * n03) + (m11 * n13) + (m12 * n23) + (m13 * n33);
×
1824
    bStorage[2] = (m20 * n00) + (m21 * n10) + (m22 * n20) + (m23 * n30);
×
1825
    bStorage[6] = (m20 * n01) + (m21 * n11) + (m22 * n21) + (m23 * n31);
×
1826
    bStorage[10] = (m20 * n02) + (m21 * n12) + (m22 * n22) + (m23 * n32);
×
1827
    bStorage[14] = (m20 * n03) + (m21 * n13) + (m22 * n23) + (m23 * n33);
×
1828
    bStorage[3] = (m30 * n00) + (m31 * n10) + (m32 * n20) + (m33 * n30);
×
1829
    bStorage[7] = (m30 * n01) + (m31 * n11) + (m32 * n21) + (m33 * n31);
×
1830
    bStorage[11] = (m30 * n02) + (m31 * n12) + (m32 * n22) + (m33 * n32);
×
1831
    bStorage[15] = (m30 * n03) + (m31 * n13) + (m32 * n23) + (m33 * n33);
×
1832
  }
1833

1834
  /// Multiply a copy of this with [arg].
1835
  Matrix4 multiplied(Matrix4 arg) => clone()..multiply(arg);
×
1836

1837
  /// Multiply a transposed this with [arg].
1838
  void transposeMultiply(Matrix4 arg) {
×
1839
    final m00 = _m4storage[0];
×
1840
    final m01 = _m4storage[1];
×
1841
    final m02 = _m4storage[2];
×
1842
    final m03 = _m4storage[3];
×
1843
    final m10 = _m4storage[4];
×
1844
    final m11 = _m4storage[5];
×
1845
    final m12 = _m4storage[6];
×
1846
    final m13 = _m4storage[7];
×
1847
    final m20 = _m4storage[8];
×
1848
    final m21 = _m4storage[9];
×
1849
    final m22 = _m4storage[10];
×
1850
    final m23 = _m4storage[11];
×
1851
    final m30 = _m4storage[12];
×
1852
    final m31 = _m4storage[13];
×
1853
    final m32 = _m4storage[14];
×
1854
    final m33 = _m4storage[15];
×
1855
    final argStorage = arg._m4storage;
×
1856
    _m4storage[0] =
×
1857
        (m00 * argStorage[0]) +
×
1858
        (m01 * argStorage[1]) +
×
1859
        (m02 * argStorage[2]) +
×
1860
        (m03 * argStorage[3]);
×
1861
    _m4storage[4] =
×
1862
        (m00 * argStorage[4]) +
×
1863
        (m01 * argStorage[5]) +
×
1864
        (m02 * argStorage[6]) +
×
1865
        (m03 * argStorage[7]);
×
1866
    _m4storage[8] =
×
1867
        (m00 * argStorage[8]) +
×
1868
        (m01 * argStorage[9]) +
×
1869
        (m02 * argStorage[10]) +
×
1870
        (m03 * argStorage[11]);
×
1871
    _m4storage[12] =
×
1872
        (m00 * argStorage[12]) +
×
1873
        (m01 * argStorage[13]) +
×
1874
        (m02 * argStorage[14]) +
×
1875
        (m03 * argStorage[15]);
×
1876
    _m4storage[1] =
×
1877
        (m10 * argStorage[0]) +
×
1878
        (m11 * argStorage[1]) +
×
1879
        (m12 * argStorage[2]) +
×
1880
        (m13 * argStorage[3]);
×
1881
    _m4storage[5] =
×
1882
        (m10 * argStorage[4]) +
×
1883
        (m11 * argStorage[5]) +
×
1884
        (m12 * argStorage[6]) +
×
1885
        (m13 * argStorage[7]);
×
1886
    _m4storage[9] =
×
1887
        (m10 * argStorage[8]) +
×
1888
        (m11 * argStorage[9]) +
×
1889
        (m12 * argStorage[10]) +
×
1890
        (m13 * argStorage[11]);
×
1891
    _m4storage[13] =
×
1892
        (m10 * argStorage[12]) +
×
1893
        (m11 * argStorage[13]) +
×
1894
        (m12 * argStorage[14]) +
×
1895
        (m13 * argStorage[15]);
×
1896
    _m4storage[2] =
×
1897
        (m20 * argStorage[0]) +
×
1898
        (m21 * argStorage[1]) +
×
1899
        (m22 * argStorage[2]) +
×
1900
        (m23 * argStorage[3]);
×
1901
    _m4storage[6] =
×
1902
        (m20 * argStorage[4]) +
×
1903
        (m21 * argStorage[5]) +
×
1904
        (m22 * argStorage[6]) +
×
1905
        (m23 * argStorage[7]);
×
1906
    _m4storage[10] =
×
1907
        (m20 * argStorage[8]) +
×
1908
        (m21 * argStorage[9]) +
×
1909
        (m22 * argStorage[10]) +
×
1910
        (m23 * argStorage[11]);
×
1911
    _m4storage[14] =
×
1912
        (m20 * argStorage[12]) +
×
1913
        (m21 * argStorage[13]) +
×
1914
        (m22 * argStorage[14]) +
×
1915
        (m23 * argStorage[15]);
×
1916
    _m4storage[3] =
×
1917
        (m30 * argStorage[0]) +
×
1918
        (m31 * argStorage[1]) +
×
1919
        (m32 * argStorage[2]) +
×
1920
        (m33 * argStorage[3]);
×
1921
    _m4storage[7] =
×
1922
        (m30 * argStorage[4]) +
×
1923
        (m31 * argStorage[5]) +
×
1924
        (m32 * argStorage[6]) +
×
1925
        (m33 * argStorage[7]);
×
1926
    _m4storage[11] =
×
1927
        (m30 * argStorage[8]) +
×
1928
        (m31 * argStorage[9]) +
×
1929
        (m32 * argStorage[10]) +
×
1930
        (m33 * argStorage[11]);
×
1931
    _m4storage[15] =
×
1932
        (m30 * argStorage[12]) +
×
1933
        (m31 * argStorage[13]) +
×
1934
        (m32 * argStorage[14]) +
×
1935
        (m33 * argStorage[15]);
×
1936
  }
1937

1938
  /// Multiply this with a transposed [arg].
1939
  void multiplyTranspose(Matrix4 arg) {
×
1940
    final m00 = _m4storage[0];
×
1941
    final m01 = _m4storage[4];
×
1942
    final m02 = _m4storage[8];
×
1943
    final m03 = _m4storage[12];
×
1944
    final m10 = _m4storage[1];
×
1945
    final m11 = _m4storage[5];
×
1946
    final m12 = _m4storage[9];
×
1947
    final m13 = _m4storage[13];
×
1948
    final m20 = _m4storage[2];
×
1949
    final m21 = _m4storage[6];
×
1950
    final m22 = _m4storage[10];
×
1951
    final m23 = _m4storage[14];
×
1952
    final m30 = _m4storage[3];
×
1953
    final m31 = _m4storage[7];
×
1954
    final m32 = _m4storage[11];
×
1955
    final m33 = _m4storage[15];
×
1956
    final argStorage = arg._m4storage;
×
1957
    _m4storage[0] =
×
1958
        (m00 * argStorage[0]) +
×
1959
        (m01 * argStorage[4]) +
×
1960
        (m02 * argStorage[8]) +
×
1961
        (m03 * argStorage[12]);
×
1962
    _m4storage[4] =
×
1963
        (m00 * argStorage[1]) +
×
1964
        (m01 * argStorage[5]) +
×
1965
        (m02 * argStorage[9]) +
×
1966
        (m03 * argStorage[13]);
×
1967
    _m4storage[8] =
×
1968
        (m00 * argStorage[2]) +
×
1969
        (m01 * argStorage[6]) +
×
1970
        (m02 * argStorage[10]) +
×
1971
        (m03 * argStorage[14]);
×
1972
    _m4storage[12] =
×
1973
        (m00 * argStorage[3]) +
×
1974
        (m01 * argStorage[7]) +
×
1975
        (m02 * argStorage[11]) +
×
1976
        (m03 * argStorage[15]);
×
1977
    _m4storage[1] =
×
1978
        (m10 * argStorage[0]) +
×
1979
        (m11 * argStorage[4]) +
×
1980
        (m12 * argStorage[8]) +
×
1981
        (m13 * argStorage[12]);
×
1982
    _m4storage[5] =
×
1983
        (m10 * argStorage[1]) +
×
1984
        (m11 * argStorage[5]) +
×
1985
        (m12 * argStorage[9]) +
×
1986
        (m13 * argStorage[13]);
×
1987
    _m4storage[9] =
×
1988
        (m10 * argStorage[2]) +
×
1989
        (m11 * argStorage[6]) +
×
1990
        (m12 * argStorage[10]) +
×
1991
        (m13 * argStorage[14]);
×
1992
    _m4storage[13] =
×
1993
        (m10 * argStorage[3]) +
×
1994
        (m11 * argStorage[7]) +
×
1995
        (m12 * argStorage[11]) +
×
1996
        (m13 * argStorage[15]);
×
1997
    _m4storage[2] =
×
1998
        (m20 * argStorage[0]) +
×
1999
        (m21 * argStorage[4]) +
×
2000
        (m22 * argStorage[8]) +
×
2001
        (m23 * argStorage[12]);
×
2002
    _m4storage[6] =
×
2003
        (m20 * argStorage[1]) +
×
2004
        (m21 * argStorage[5]) +
×
2005
        (m22 * argStorage[9]) +
×
2006
        (m23 * argStorage[13]);
×
2007
    _m4storage[10] =
×
2008
        (m20 * argStorage[2]) +
×
2009
        (m21 * argStorage[6]) +
×
2010
        (m22 * argStorage[10]) +
×
2011
        (m23 * argStorage[14]);
×
2012
    _m4storage[14] =
×
2013
        (m20 * argStorage[3]) +
×
2014
        (m21 * argStorage[7]) +
×
2015
        (m22 * argStorage[11]) +
×
2016
        (m23 * argStorage[15]);
×
2017
    _m4storage[3] =
×
2018
        (m30 * argStorage[0]) +
×
2019
        (m31 * argStorage[4]) +
×
2020
        (m32 * argStorage[8]) +
×
2021
        (m33 * argStorage[12]);
×
2022
    _m4storage[7] =
×
2023
        (m30 * argStorage[1]) +
×
2024
        (m31 * argStorage[5]) +
×
2025
        (m32 * argStorage[9]) +
×
2026
        (m33 * argStorage[13]);
×
2027
    _m4storage[11] =
×
2028
        (m30 * argStorage[2]) +
×
2029
        (m31 * argStorage[6]) +
×
2030
        (m32 * argStorage[10]) +
×
2031
        (m33 * argStorage[14]);
×
2032
    _m4storage[15] =
×
2033
        (m30 * argStorage[3]) +
×
2034
        (m31 * argStorage[7]) +
×
2035
        (m32 * argStorage[11]) +
×
2036
        (m33 * argStorage[15]);
×
2037
  }
2038

2039
  /// Decomposes this into [translation], [rotation] and [scale] components.
2040
  void decompose(Vector3 translation, Quaternion rotation, Vector3 scale) {
×
2041
    final v = _decomposeV ??= Vector3.zero();
×
2042
    var sx = (v..setValues(_m4storage[0], _m4storage[1], _m4storage[2])).length;
×
2043
    final sy =
2044
        (v..setValues(_m4storage[4], _m4storage[5], _m4storage[6])).length;
×
2045
    final sz =
2046
        (v..setValues(_m4storage[8], _m4storage[9], _m4storage[10])).length;
×
2047

2048
    if (determinant() < 0) {
×
2049
      sx = -sx;
×
2050
    }
2051

2052
    translation._v3storage[0] = _m4storage[12];
×
2053
    translation._v3storage[1] = _m4storage[13];
×
2054
    translation._v3storage[2] = _m4storage[14];
×
2055

2056
    final invSX = 1.0 / sx;
×
2057
    final invSY = 1.0 / sy;
×
2058
    final invSZ = 1.0 / sz;
×
2059

2060
    final m = _decomposeM ??= Matrix4.zero();
×
2061
    m.setFrom(this);
×
2062
    m._m4storage[0] *= invSX;
×
2063
    m._m4storage[1] *= invSX;
×
2064
    m._m4storage[2] *= invSX;
×
2065
    m._m4storage[4] *= invSY;
×
2066
    m._m4storage[5] *= invSY;
×
2067
    m._m4storage[6] *= invSY;
×
2068
    m._m4storage[8] *= invSZ;
×
2069
    m._m4storage[9] *= invSZ;
×
2070
    m._m4storage[10] *= invSZ;
×
2071

2072
    final r = _decomposeR ??= Matrix3.zero();
×
2073
    m.copyRotation(r);
×
2074
    rotation.setFromRotation(r);
×
2075

2076
    scale._v3storage[0] = sx;
×
2077
    scale._v3storage[1] = sy;
×
2078
    scale._v3storage[2] = sz;
×
2079
  }
2080

2081
  static Vector3? _decomposeV;
2082
  static Matrix4? _decomposeM;
2083
  static Matrix3? _decomposeR;
2084

2085
  /// Rotate [arg] of type [Vector3] using the rotation defined by this.
2086
  Vector3 rotate3(Vector3 arg) {
×
2087
    final argStorage = arg._v3storage;
×
2088
    final x_ =
2089
        (_m4storage[0] * argStorage[0]) +
×
2090
        (_m4storage[4] * argStorage[1]) +
×
2091
        (_m4storage[8] * argStorage[2]);
×
2092
    final y_ =
2093
        (_m4storage[1] * argStorage[0]) +
×
2094
        (_m4storage[5] * argStorage[1]) +
×
2095
        (_m4storage[9] * argStorage[2]);
×
2096
    final z_ =
2097
        (_m4storage[2] * argStorage[0]) +
×
2098
        (_m4storage[6] * argStorage[1]) +
×
2099
        (_m4storage[10] * argStorage[2]);
×
2100
    argStorage[0] = x_;
×
2101
    argStorage[1] = y_;
×
2102
    argStorage[2] = z_;
×
2103
    return arg;
2104
  }
2105

2106
  /// Rotate a copy of [arg] of type [Vector3] using the rotation defined by
2107
  /// this. If a [out] parameter is supplied, the copy is stored in [out].
2108
  Vector3 rotated3(Vector3 arg, [Vector3? out]) {
×
2109
    if (out == null) {
2110
      out = Vector3.copy(arg);
×
2111
    } else {
2112
      out.setFrom(arg);
×
2113
    }
2114
    return rotate3(out);
×
2115
  }
2116

2117
  /// Transform [arg] of type [Vector3] using the transformation defined by
2118
  /// this.
2119
  Vector3 transform3(Vector3 arg) {
×
2120
    final argStorage = arg._v3storage;
×
2121
    final x_ =
2122
        (_m4storage[0] * argStorage[0]) +
×
2123
        (_m4storage[4] * argStorage[1]) +
×
2124
        (_m4storage[8] * argStorage[2]) +
×
2125
        _m4storage[12];
×
2126
    final y_ =
2127
        (_m4storage[1] * argStorage[0]) +
×
2128
        (_m4storage[5] * argStorage[1]) +
×
2129
        (_m4storage[9] * argStorage[2]) +
×
2130
        _m4storage[13];
×
2131
    final z_ =
2132
        (_m4storage[2] * argStorage[0]) +
×
2133
        (_m4storage[6] * argStorage[1]) +
×
2134
        (_m4storage[10] * argStorage[2]) +
×
2135
        _m4storage[14];
×
2136
    argStorage[0] = x_;
×
2137
    argStorage[1] = y_;
×
2138
    argStorage[2] = z_;
×
2139
    return arg;
2140
  }
2141

2142
  /// Transform a copy of [arg] of type [Vector3] using the transformation
2143
  /// defined by this. If a [out] parameter is supplied, the copy is stored in
2144
  /// [out].
2145
  Vector3 transformed3(Vector3 arg, [Vector3? out]) {
×
2146
    if (out == null) {
2147
      out = Vector3.copy(arg);
×
2148
    } else {
2149
      out.setFrom(arg);
×
2150
    }
2151
    return transform3(out);
×
2152
  }
2153

2154
  /// Transform [arg] of type [Vector4] using the transformation defined by
2155
  /// this.
2156
  Vector4 transform(Vector4 arg) {
×
2157
    final argStorage = arg._v4storage;
×
2158
    final x_ =
2159
        (_m4storage[0] * argStorage[0]) +
×
2160
        (_m4storage[4] * argStorage[1]) +
×
2161
        (_m4storage[8] * argStorage[2]) +
×
2162
        (_m4storage[12] * argStorage[3]);
×
2163
    final y_ =
2164
        (_m4storage[1] * argStorage[0]) +
×
2165
        (_m4storage[5] * argStorage[1]) +
×
2166
        (_m4storage[9] * argStorage[2]) +
×
2167
        (_m4storage[13] * argStorage[3]);
×
2168
    final z_ =
2169
        (_m4storage[2] * argStorage[0]) +
×
2170
        (_m4storage[6] * argStorage[1]) +
×
2171
        (_m4storage[10] * argStorage[2]) +
×
2172
        (_m4storage[14] * argStorage[3]);
×
2173
    final w_ =
2174
        (_m4storage[3] * argStorage[0]) +
×
2175
        (_m4storage[7] * argStorage[1]) +
×
2176
        (_m4storage[11] * argStorage[2]) +
×
2177
        (_m4storage[15] * argStorage[3]);
×
2178
    argStorage[0] = x_;
×
2179
    argStorage[1] = y_;
×
2180
    argStorage[2] = z_;
×
2181
    argStorage[3] = w_;
×
2182
    return arg;
2183
  }
2184

2185
  /// Transform [arg] of type [Vector3] using the perspective transformation
2186
  /// defined by this.
2187
  Vector3 perspectiveTransform(Vector3 arg) {
×
2188
    final argStorage = arg._v3storage;
×
2189
    final x_ =
2190
        (_m4storage[0] * argStorage[0]) +
×
2191
        (_m4storage[4] * argStorage[1]) +
×
2192
        (_m4storage[8] * argStorage[2]) +
×
2193
        _m4storage[12];
×
2194
    final y_ =
2195
        (_m4storage[1] * argStorage[0]) +
×
2196
        (_m4storage[5] * argStorage[1]) +
×
2197
        (_m4storage[9] * argStorage[2]) +
×
2198
        _m4storage[13];
×
2199
    final z_ =
2200
        (_m4storage[2] * argStorage[0]) +
×
2201
        (_m4storage[6] * argStorage[1]) +
×
2202
        (_m4storage[10] * argStorage[2]) +
×
2203
        _m4storage[14];
×
2204
    final w_ =
2205
        1.0 /
×
2206
        ((_m4storage[3] * argStorage[0]) +
×
2207
            (_m4storage[7] * argStorage[1]) +
×
2208
            (_m4storage[11] * argStorage[2]) +
×
2209
            _m4storage[15]);
×
2210
    argStorage[0] = x_ * w_;
×
2211
    argStorage[1] = y_ * w_;
×
2212
    argStorage[2] = z_ * w_;
×
2213
    return arg;
2214
  }
2215

2216
  /// Transform a copy of [arg] of type [Vector4] using the transformation
2217
  /// defined by this. If a [out] parameter is supplied, the copy is stored in
2218
  /// [out].
2219
  Vector4 transformed(Vector4 arg, [Vector4? out]) {
×
2220
    if (out == null) {
2221
      out = Vector4.copy(arg);
×
2222
    } else {
2223
      out.setFrom(arg);
×
2224
    }
2225
    return transform(out);
×
2226
  }
2227

2228
  /// Copies this into [array] starting at [offset].
2229
  void copyIntoArray(List<num> array, [int offset = 0]) {
×
2230
    final i = offset;
2231
    array[i + 15] = _m4storage[15];
×
2232
    array[i + 14] = _m4storage[14];
×
2233
    array[i + 13] = _m4storage[13];
×
2234
    array[i + 12] = _m4storage[12];
×
2235
    array[i + 11] = _m4storage[11];
×
2236
    array[i + 10] = _m4storage[10];
×
2237
    array[i + 9] = _m4storage[9];
×
2238
    array[i + 8] = _m4storage[8];
×
2239
    array[i + 7] = _m4storage[7];
×
2240
    array[i + 6] = _m4storage[6];
×
2241
    array[i + 5] = _m4storage[5];
×
2242
    array[i + 4] = _m4storage[4];
×
2243
    array[i + 3] = _m4storage[3];
×
2244
    array[i + 2] = _m4storage[2];
×
2245
    array[i + 1] = _m4storage[1];
×
2246
    array[i + 0] = _m4storage[0];
×
2247
  }
2248

2249
  /// Copies elements from [array] into this starting at [offset].
2250
  void copyFromArray(List<double> array, [int offset = 0]) {
×
2251
    final i = offset;
2252
    _m4storage[15] = array[i + 15];
×
2253
    _m4storage[14] = array[i + 14];
×
2254
    _m4storage[13] = array[i + 13];
×
2255
    _m4storage[12] = array[i + 12];
×
2256
    _m4storage[11] = array[i + 11];
×
2257
    _m4storage[10] = array[i + 10];
×
2258
    _m4storage[9] = array[i + 9];
×
2259
    _m4storage[8] = array[i + 8];
×
2260
    _m4storage[7] = array[i + 7];
×
2261
    _m4storage[6] = array[i + 6];
×
2262
    _m4storage[5] = array[i + 5];
×
2263
    _m4storage[4] = array[i + 4];
×
2264
    _m4storage[3] = array[i + 3];
×
2265
    _m4storage[2] = array[i + 2];
×
2266
    _m4storage[1] = array[i + 1];
×
2267
    _m4storage[0] = array[i + 0];
×
2268
  }
2269

2270
  /// Multiply this to each set of xyz values in [array] starting at [offset].
2271
  List<double> applyToVector3Array(List<double> array, [int offset = 0]) {
×
2272
    for (var i = 0, j = offset; i < array.length; i += 3, j += 3) {
×
2273
      final v = Vector3.array(array, j)..applyMatrix4(this);
×
2274
      array[j] = v.storage[0];
×
2275
      array[j + 1] = v.storage[1];
×
2276
      array[j + 2] = v.storage[2];
×
2277
    }
2278

2279
    return array;
2280
  }
2281

2282
  Vector3 get right {
×
2283
    final x = _m4storage[0];
×
2284
    final y = _m4storage[1];
×
2285
    final z = _m4storage[2];
×
2286
    return Vector3(x, y, z);
×
2287
  }
2288

2289
  Vector3 get up {
×
2290
    final x = _m4storage[4];
×
2291
    final y = _m4storage[5];
×
2292
    final z = _m4storage[6];
×
2293
    return Vector3(x, y, z);
×
2294
  }
2295

2296
  Vector3 get forward {
×
2297
    final x = _m4storage[8];
×
2298
    final y = _m4storage[9];
×
2299
    final z = _m4storage[10];
×
2300
    return Vector3(x, y, z);
×
2301
  }
2302

2303
  /// Is this the identity matrix?
2304
  bool isIdentity() =>
×
2305
      _m4storage[0] ==
×
2306
          1.0 // col 1
2307
          &&
2308
      _m4storage[1] == 0.0 &&
×
2309
      _m4storage[2] == 0.0 &&
×
2310
      _m4storage[3] == 0.0 &&
×
2311
      _m4storage[4] ==
×
2312
          0.0 // col 2
2313
          &&
2314
      _m4storage[5] == 1.0 &&
×
2315
      _m4storage[6] == 0.0 &&
×
2316
      _m4storage[7] == 0.0 &&
×
2317
      _m4storage[8] ==
×
2318
          0.0 // col 3
2319
          &&
2320
      _m4storage[9] == 0.0 &&
×
2321
      _m4storage[10] == 1.0 &&
×
2322
      _m4storage[11] == 0.0 &&
×
2323
      _m4storage[12] ==
×
2324
          0.0 // col 4
2325
          &&
2326
      _m4storage[13] == 0.0 &&
×
2327
      _m4storage[14] == 0.0 &&
×
2328
      _m4storage[15] == 1.0;
×
2329

2330
  /// Is this the zero matrix?
2331
  bool isZero() =>
×
2332
      _m4storage[0] ==
×
2333
          0.0 // col 1
2334
          &&
2335
      _m4storage[1] == 0.0 &&
×
2336
      _m4storage[2] == 0.0 &&
×
2337
      _m4storage[3] == 0.0 &&
×
2338
      _m4storage[4] ==
×
2339
          0.0 // col 2
2340
          &&
2341
      _m4storage[5] == 0.0 &&
×
2342
      _m4storage[6] == 0.0 &&
×
2343
      _m4storage[7] == 0.0 &&
×
2344
      _m4storage[8] ==
×
2345
          0.0 // col 3
2346
          &&
2347
      _m4storage[9] == 0.0 &&
×
2348
      _m4storage[10] == 0.0 &&
×
2349
      _m4storage[11] == 0.0 &&
×
2350
      _m4storage[12] ==
×
2351
          0.0 // col 4
2352
          &&
2353
      _m4storage[13] == 0.0 &&
×
2354
      _m4storage[14] == 0.0 &&
×
2355
      _m4storage[15] == 0.0;
×
2356
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc