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

google / vector_math.dart / 14778564080

01 May 2025 03:57PM UTC coverage: 26.388% (+0.02%) from 26.372%
14778564080

push

github

web-flow
Improve performance of functions with dynamic arguments (#345)

* Deprecated functions with dynamic arguments
* Bump version, update changelog

54 of 164 new or added lines in 8 files covered. (32.93%)

5 existing lines in 2 files now uncovered.

4335 of 16428 relevant lines covered (26.39%)

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

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

162
  /// Return index in storage for [row], [col] value.
163
  int index(int row, int col) => (col * 4) + row;
×
164

165
  /// Value at [row], [col].
166
  double entry(int row, int col) {
×
167
    assert((row >= 0) && (row < dimension));
×
168
    assert((col >= 0) && (col < dimension));
×
169

170
    return _m4storage[index(row, col)];
×
171
  }
172

173
  /// Set value at [row], [col] to be [v].
174
  void setEntry(int row, int col, double v) {
×
175
    assert((row >= 0) && (row < dimension));
×
176
    assert((col >= 0) && (col < dimension));
×
177

178
    _m4storage[index(row, col)] = v;
×
179
  }
180

181
  /// Constructs a new mat4.
182
  factory Matrix4(
×
183
          double arg0,
184
          double arg1,
185
          double arg2,
186
          double arg3,
187
          double arg4,
188
          double arg5,
189
          double arg6,
190
          double arg7,
191
          double arg8,
192
          double arg9,
193
          double arg10,
194
          double arg11,
195
          double arg12,
196
          double arg13,
197
          double arg14,
198
          double arg15) =>
199
      Matrix4.zero()
×
200
        ..setValues(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,
×
201
            arg10, arg11, arg12, arg13, arg14, arg15);
202

203
  /// New matrix from [values].
204
  factory Matrix4.fromList(List<double> values) => Matrix4.zero()
×
205
    ..setValues(
×
206
        values[0],
×
207
        values[1],
×
208
        values[2],
×
209
        values[3],
×
210
        values[4],
×
211
        values[5],
×
212
        values[6],
×
213
        values[7],
×
214
        values[8],
×
215
        values[9],
×
216
        values[10],
×
217
        values[11],
×
218
        values[12],
×
219
        values[13],
×
220
        values[14],
×
221
        values[15]);
×
222

223
  /// Zero matrix.
224
  Matrix4.zero() : _m4storage = Float64List(16);
×
225

226
  /// Identity matrix.
227
  factory Matrix4.identity() => Matrix4.zero()..setIdentity();
×
228

229
  /// Copies values from [other].
230
  factory Matrix4.copy(Matrix4 other) => Matrix4.zero()..setFrom(other);
×
231

232
  /// Constructs a matrix that is the inverse of [other].
233
  factory Matrix4.inverted(Matrix4 other) {
×
234
    final r = Matrix4.zero();
×
235
    final determinant = r.copyInverse(other);
×
236
    if (determinant == 0.0) {
×
237
      throw ArgumentError.value(other, 'other', 'Matrix cannot be inverted');
×
238
    }
239
    return r;
240
  }
241

242
  /// Constructs a new mat4 from columns.
243
  factory Matrix4.columns(
×
244
          Vector4 arg0, Vector4 arg1, Vector4 arg2, Vector4 arg3) =>
245
      Matrix4.zero()..setColumns(arg0, arg1, arg2, arg3);
×
246

247
  /// Outer product of [u] and [v].
248
  factory Matrix4.outer(Vector4 u, Vector4 v) => Matrix4.zero()..setOuter(u, v);
×
249

250
  /// Rotation of [radians] around X.
251
  factory Matrix4.rotationX(double radians) => Matrix4.zero()
×
252
    .._m4storage[15] = 1.0
×
253
    ..setRotationX(radians);
×
254

255
  /// Rotation of [radians] around Y.
256
  factory Matrix4.rotationY(double radians) => Matrix4.zero()
×
257
    .._m4storage[15] = 1.0
×
258
    ..setRotationY(radians);
×
259

260
  /// Rotation of [radians] around Z.
261
  factory Matrix4.rotationZ(double radians) => Matrix4.zero()
×
262
    .._m4storage[15] = 1.0
×
263
    ..setRotationZ(radians);
×
264

265
  /// Translation matrix.
266
  factory Matrix4.translation(Vector3 translation) => Matrix4.zero()
×
267
    ..setIdentity()
×
268
    ..setTranslation(translation);
×
269

270
  /// Translation matrix.
271
  factory Matrix4.translationValues(double x, double y, double z) =>
×
272
      Matrix4.zero()
×
273
        ..setIdentity()
×
274
        ..setTranslationRaw(x, y, z);
×
275

276
  /// Scale matrix.
277
  factory Matrix4.diagonal3(Vector3 scale) {
×
278
    final m = Matrix4.zero();
×
279
    final mStorage = m._m4storage;
×
280
    final scaleStorage = scale._v3storage;
×
281
    mStorage[15] = 1.0;
×
282
    mStorage[10] = scaleStorage[2];
×
283
    mStorage[5] = scaleStorage[1];
×
284
    mStorage[0] = scaleStorage[0];
×
285
    return m;
286
  }
287

288
  /// Scale matrix.
289
  factory Matrix4.diagonal3Values(double x, double y, double z) =>
×
290
      Matrix4.zero()
×
291
        .._m4storage[15] = 1.0
×
292
        .._m4storage[10] = z
×
293
        .._m4storage[5] = y
×
294
        .._m4storage[0] = x;
×
295

296
  /// Skew matrix around X axis
297
  factory Matrix4.skewX(double alpha) {
×
298
    final m = Matrix4.identity();
×
299
    m._m4storage[4] = math.tan(alpha);
×
300
    return m;
301
  }
302

303
  /// Skew matrix around Y axis.
304
  factory Matrix4.skewY(double beta) {
×
305
    final m = Matrix4.identity();
×
306
    m._m4storage[1] = math.tan(beta);
×
307
    return m;
308
  }
309

310
  /// Skew matrix around X axis (alpha) and Y axis (beta).
311
  factory Matrix4.skew(double alpha, double beta) {
×
312
    final m = Matrix4.identity();
×
313
    m._m4storage[1] = math.tan(beta);
×
314
    m._m4storage[4] = math.tan(alpha);
×
315
    return m;
316
  }
317

318
  /// Constructs Matrix4 with given [Float64List] as [storage].
319
  Matrix4.fromFloat64List(this._m4storage);
×
320

321
  /// Constructs Matrix4 with a [storage] that views given [buffer] starting at
322
  /// [offset]. [offset] has to be multiple of [Float64List.bytesPerElement].
323
  Matrix4.fromBuffer(ByteBuffer buffer, int offset)
×
324
      : _m4storage = Float64List.view(buffer, offset, 16);
×
325

326
  /// Constructs Matrix4 from [translation], [rotation] and [scale].
327
  factory Matrix4.compose(
×
328
          Vector3 translation, Quaternion rotation, Vector3 scale) =>
329
      Matrix4.zero()
×
330
        ..setFromTranslationRotationScale(translation, rotation, scale);
×
331

332
  /// Sets the diagonal to [arg].
333
  void splatDiagonal(double arg) {
×
334
    _m4storage[0] = arg;
×
335
    _m4storage[5] = arg;
×
336
    _m4storage[10] = arg;
×
337
    _m4storage[15] = arg;
×
338
  }
339

340
  /// Sets the matrix with specified values.
341
  void setValues(
×
342
      double arg0,
343
      double arg1,
344
      double arg2,
345
      double arg3,
346
      double arg4,
347
      double arg5,
348
      double arg6,
349
      double arg7,
350
      double arg8,
351
      double arg9,
352
      double arg10,
353
      double arg11,
354
      double arg12,
355
      double arg13,
356
      double arg14,
357
      double arg15) {
358
    _m4storage[15] = arg15;
×
359
    _m4storage[14] = arg14;
×
360
    _m4storage[13] = arg13;
×
361
    _m4storage[12] = arg12;
×
362
    _m4storage[11] = arg11;
×
363
    _m4storage[10] = arg10;
×
364
    _m4storage[9] = arg9;
×
365
    _m4storage[8] = arg8;
×
366
    _m4storage[7] = arg7;
×
367
    _m4storage[6] = arg6;
×
368
    _m4storage[5] = arg5;
×
369
    _m4storage[4] = arg4;
×
370
    _m4storage[3] = arg3;
×
371
    _m4storage[2] = arg2;
×
372
    _m4storage[1] = arg1;
×
373
    _m4storage[0] = arg0;
×
374
  }
375

376
  /// Sets the entire matrix to the column values.
377
  void setColumns(Vector4 arg0, Vector4 arg1, Vector4 arg2, Vector4 arg3) {
×
378
    final arg0Storage = arg0._v4storage;
×
379
    final arg1Storage = arg1._v4storage;
×
380
    final arg2Storage = arg2._v4storage;
×
381
    final arg3Storage = arg3._v4storage;
×
382
    _m4storage[0] = arg0Storage[0];
×
383
    _m4storage[1] = arg0Storage[1];
×
384
    _m4storage[2] = arg0Storage[2];
×
385
    _m4storage[3] = arg0Storage[3];
×
386
    _m4storage[4] = arg1Storage[0];
×
387
    _m4storage[5] = arg1Storage[1];
×
388
    _m4storage[6] = arg1Storage[2];
×
389
    _m4storage[7] = arg1Storage[3];
×
390
    _m4storage[8] = arg2Storage[0];
×
391
    _m4storage[9] = arg2Storage[1];
×
392
    _m4storage[10] = arg2Storage[2];
×
393
    _m4storage[11] = arg2Storage[3];
×
394
    _m4storage[12] = arg3Storage[0];
×
395
    _m4storage[13] = arg3Storage[1];
×
396
    _m4storage[14] = arg3Storage[2];
×
397
    _m4storage[15] = arg3Storage[3];
×
398
  }
399

400
  /// Sets the entire matrix to the matrix in [arg].
401
  void setFrom(Matrix4 arg) {
×
402
    final argStorage = arg._m4storage;
×
403
    _m4storage[15] = argStorage[15];
×
404
    _m4storage[14] = argStorage[14];
×
405
    _m4storage[13] = argStorage[13];
×
406
    _m4storage[12] = argStorage[12];
×
407
    _m4storage[11] = argStorage[11];
×
408
    _m4storage[10] = argStorage[10];
×
409
    _m4storage[9] = argStorage[9];
×
410
    _m4storage[8] = argStorage[8];
×
411
    _m4storage[7] = argStorage[7];
×
412
    _m4storage[6] = argStorage[6];
×
413
    _m4storage[5] = argStorage[5];
×
414
    _m4storage[4] = argStorage[4];
×
415
    _m4storage[3] = argStorage[3];
×
416
    _m4storage[2] = argStorage[2];
×
417
    _m4storage[1] = argStorage[1];
×
418
    _m4storage[0] = argStorage[0];
×
419
  }
420

421
  /// Sets the matrix from translation [arg0] and rotation [arg1].
422
  void setFromTranslationRotation(Vector3 arg0, Quaternion arg1) {
×
423
    final arg1Storage = arg1._qStorage;
×
424
    final x = arg1Storage[0];
×
425
    final y = arg1Storage[1];
×
426
    final z = arg1Storage[2];
×
427
    final w = arg1Storage[3];
×
428
    final x2 = x + x;
×
429
    final y2 = y + y;
×
430
    final z2 = z + z;
×
431
    final xx = x * x2;
×
432
    final xy = x * y2;
×
433
    final xz = x * z2;
×
434
    final yy = y * y2;
×
435
    final yz = y * z2;
×
436
    final zz = z * z2;
×
437
    final wx = w * x2;
×
438
    final wy = w * y2;
×
439
    final wz = w * z2;
×
440

441
    final arg0Storage = arg0._v3storage;
×
442
    _m4storage[0] = 1.0 - (yy + zz);
×
443
    _m4storage[1] = xy + wz;
×
444
    _m4storage[2] = xz - wy;
×
445
    _m4storage[3] = 0.0;
×
446
    _m4storage[4] = xy - wz;
×
447
    _m4storage[5] = 1.0 - (xx + zz);
×
448
    _m4storage[6] = yz + wx;
×
449
    _m4storage[7] = 0.0;
×
450
    _m4storage[8] = xz + wy;
×
451
    _m4storage[9] = yz - wx;
×
452
    _m4storage[10] = 1.0 - (xx + yy);
×
453
    _m4storage[11] = 0.0;
×
454
    _m4storage[12] = arg0Storage[0];
×
455
    _m4storage[13] = arg0Storage[1];
×
456
    _m4storage[14] = arg0Storage[2];
×
457
    _m4storage[15] = 1.0;
×
458
  }
459

460
  /// Sets the matrix from [translation], [rotation] and [scale].
461
  void setFromTranslationRotationScale(
×
462
      Vector3 translation, Quaternion rotation, Vector3 scale) {
463
    setFromTranslationRotation(translation, rotation);
×
NEW
464
    scaleByVector3(scale);
×
465
  }
466

467
  /// Sets the upper 2x2 of the matrix to be [arg].
468
  void setUpper2x2(Matrix2 arg) {
×
469
    final argStorage = arg._m2storage;
×
470
    _m4storage[0] = argStorage[0];
×
471
    _m4storage[1] = argStorage[1];
×
472
    _m4storage[4] = argStorage[2];
×
473
    _m4storage[5] = argStorage[3];
×
474
  }
475

476
  /// Sets the diagonal of the matrix to be [arg].
477
  void setDiagonal(Vector4 arg) {
×
478
    final argStorage = arg._v4storage;
×
479
    _m4storage[0] = argStorage[0];
×
480
    _m4storage[5] = argStorage[1];
×
481
    _m4storage[10] = argStorage[2];
×
482
    _m4storage[15] = argStorage[3];
×
483
  }
484

485
  void setOuter(Vector4 u, Vector4 v) {
×
486
    final uStorage = u._v4storage;
×
487
    final vStorage = v._v4storage;
×
488
    _m4storage[0] = uStorage[0] * vStorage[0];
×
489
    _m4storage[1] = uStorage[0] * vStorage[1];
×
490
    _m4storage[2] = uStorage[0] * vStorage[2];
×
491
    _m4storage[3] = uStorage[0] * vStorage[3];
×
492
    _m4storage[4] = uStorage[1] * vStorage[0];
×
493
    _m4storage[5] = uStorage[1] * vStorage[1];
×
494
    _m4storage[6] = uStorage[1] * vStorage[2];
×
495
    _m4storage[7] = uStorage[1] * vStorage[3];
×
496
    _m4storage[8] = uStorage[2] * vStorage[0];
×
497
    _m4storage[9] = uStorage[2] * vStorage[1];
×
498
    _m4storage[10] = uStorage[2] * vStorage[2];
×
499
    _m4storage[11] = uStorage[2] * vStorage[3];
×
500
    _m4storage[12] = uStorage[3] * vStorage[0];
×
501
    _m4storage[13] = uStorage[3] * vStorage[1];
×
502
    _m4storage[14] = uStorage[3] * vStorage[2];
×
503
    _m4storage[15] = uStorage[3] * vStorage[3];
×
504
  }
505

506
  /// Returns a printable string
507
  @override
×
508
  String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n'
×
509
      '[2] ${getRow(2)}\n[3] ${getRow(3)}\n';
×
510

511
  /// Dimension of the matrix.
512
  int get dimension => 4;
×
513

514
  /// Access the element of the matrix at the index [i].
515
  double operator [](int i) => _m4storage[i];
×
516

517
  /// Set the element of the matrix at the index [i].
518
  void operator []=(int i, double v) {
×
519
    _m4storage[i] = v;
×
520
  }
521

522
  /// Check if two matrices are the same.
523
  @override
×
524
  bool operator ==(Object other) =>
525
      (other is Matrix4) &&
×
526
      (_m4storage[0] == other._m4storage[0]) &&
×
527
      (_m4storage[1] == other._m4storage[1]) &&
×
528
      (_m4storage[2] == other._m4storage[2]) &&
×
529
      (_m4storage[3] == other._m4storage[3]) &&
×
530
      (_m4storage[4] == other._m4storage[4]) &&
×
531
      (_m4storage[5] == other._m4storage[5]) &&
×
532
      (_m4storage[6] == other._m4storage[6]) &&
×
533
      (_m4storage[7] == other._m4storage[7]) &&
×
534
      (_m4storage[8] == other._m4storage[8]) &&
×
535
      (_m4storage[9] == other._m4storage[9]) &&
×
536
      (_m4storage[10] == other._m4storage[10]) &&
×
537
      (_m4storage[11] == other._m4storage[11]) &&
×
538
      (_m4storage[12] == other._m4storage[12]) &&
×
539
      (_m4storage[13] == other._m4storage[13]) &&
×
540
      (_m4storage[14] == other._m4storage[14]) &&
×
541
      (_m4storage[15] == other._m4storage[15]);
×
542

543
  @override
×
544
  int get hashCode => Object.hashAll(_m4storage);
×
545

546
  /// Returns row 0
547
  Vector4 get row0 => getRow(0);
×
548

549
  /// Returns row 1
550
  Vector4 get row1 => getRow(1);
×
551

552
  /// Returns row 2
553
  Vector4 get row2 => getRow(2);
×
554

555
  /// Returns row 3
556
  Vector4 get row3 => getRow(3);
×
557

558
  /// Sets row 0 to [arg]
559
  set row0(Vector4 arg) => setRow(0, arg);
×
560

561
  /// Sets row 1 to [arg]
562
  set row1(Vector4 arg) => setRow(1, arg);
×
563

564
  /// Sets row 2 to [arg]
565
  set row2(Vector4 arg) => setRow(2, arg);
×
566

567
  /// Sets row 3 to [arg]
568
  set row3(Vector4 arg) => setRow(3, arg);
×
569

570
  /// Assigns the [row] of the matrix [arg]
571
  void setRow(int row, Vector4 arg) {
×
572
    final argStorage = arg._v4storage;
×
573
    _m4storage[index(row, 0)] = argStorage[0];
×
574
    _m4storage[index(row, 1)] = argStorage[1];
×
575
    _m4storage[index(row, 2)] = argStorage[2];
×
576
    _m4storage[index(row, 3)] = argStorage[3];
×
577
  }
578

579
  /// Gets the [row] of the matrix
580
  Vector4 getRow(int row) {
×
581
    final r = Vector4.zero();
×
582
    final rStorage = r._v4storage;
×
583
    rStorage[0] = _m4storage[index(row, 0)];
×
584
    rStorage[1] = _m4storage[index(row, 1)];
×
585
    rStorage[2] = _m4storage[index(row, 2)];
×
586
    rStorage[3] = _m4storage[index(row, 3)];
×
587
    return r;
588
  }
589

590
  /// Assigns the [column] of the matrix [arg]
591
  void setColumn(int column, Vector4 arg) {
×
592
    final entry = column * 4;
×
593
    final argStorage = arg._v4storage;
×
594
    _m4storage[entry + 3] = argStorage[3];
×
595
    _m4storage[entry + 2] = argStorage[2];
×
596
    _m4storage[entry + 1] = argStorage[1];
×
597
    _m4storage[entry + 0] = argStorage[0];
×
598
  }
599

600
  /// Gets the [column] of the matrix
601
  Vector4 getColumn(int column) {
×
602
    final r = Vector4.zero();
×
603
    final rStorage = r._v4storage;
×
604
    final entry = column * 4;
×
605
    rStorage[3] = _m4storage[entry + 3];
×
606
    rStorage[2] = _m4storage[entry + 2];
×
607
    rStorage[1] = _m4storage[entry + 1];
×
608
    rStorage[0] = _m4storage[entry + 0];
×
609
    return r;
610
  }
611

612
  /// Clone matrix.
613
  Matrix4 clone() => Matrix4.copy(this);
×
614

615
  /// Copy into [arg].
616
  Matrix4 copyInto(Matrix4 arg) {
×
617
    final argStorage = arg._m4storage;
×
618
    argStorage[0] = _m4storage[0];
×
619
    argStorage[1] = _m4storage[1];
×
620
    argStorage[2] = _m4storage[2];
×
621
    argStorage[3] = _m4storage[3];
×
622
    argStorage[4] = _m4storage[4];
×
623
    argStorage[5] = _m4storage[5];
×
624
    argStorage[6] = _m4storage[6];
×
625
    argStorage[7] = _m4storage[7];
×
626
    argStorage[8] = _m4storage[8];
×
627
    argStorage[9] = _m4storage[9];
×
628
    argStorage[10] = _m4storage[10];
×
629
    argStorage[11] = _m4storage[11];
×
630
    argStorage[12] = _m4storage[12];
×
631
    argStorage[13] = _m4storage[13];
×
632
    argStorage[14] = _m4storage[14];
×
633
    argStorage[15] = _m4storage[15];
×
634
    return arg;
635
  }
636

637
  /// Returns new matrix -this
638
  Matrix4 operator -() => clone()..negate();
×
639

640
  /// Returns a new vector or matrix by multiplying this with [arg].
641
  ///
642
  /// [arg] should be a [double] (to scale), [Vector4] (to transform), [Vector3]
643
  /// (to transform), or [Matrix4] (to multiply).
644
  ///
645
  /// If you know the argument type in a call site, prefer [scaledByDouble],
646
  /// [transformed], [transformed3], or [multiplied] for performance.
NEW
647
  @pragma('wasm:prefer-inline')
×
648
  @pragma('vm:prefer-inline')
649
  @pragma('dart2js:prefer-inline')
650
  dynamic operator *(dynamic arg) {
651
    final Object result;
652
    if (arg is double) {
×
NEW
653
      result = scaledByDouble(arg, arg, arg, 1.0);
×
NEW
654
    } else if (arg is Vector4) {
×
NEW
655
      result = transformed(arg);
×
NEW
656
    } else if (arg is Vector3) {
×
NEW
657
      result = transformed3(arg);
×
NEW
658
    } else if (arg is Matrix4) {
×
NEW
659
      result = multiplied(arg);
×
660
    } else {
NEW
661
      throw ArgumentError(arg);
×
662
    }
663
    return result;
664
  }
665

666
  /// Returns new matrix after component wise this + [arg]
667
  Matrix4 operator +(Matrix4 arg) => clone()..add(arg);
×
668

669
  /// Returns new matrix after component wise this - [arg]
670
  Matrix4 operator -(Matrix4 arg) => clone()..sub(arg);
×
671

672
  /// Translate this matrix by a [Vector3], [Vector4], or x,y,z as [double]s.
673
  ///
674
  /// If you know the argument types in a call site, prefer [translateByDouble],
675
  /// [translateByVector3], or [translateByVector4] for performance.
NEW
676
  @pragma('wasm:prefer-inline')
×
677
  @pragma('vm:prefer-inline')
678
  @pragma('dart2js:prefer-inline')
679
  @Deprecated('Use translateByVector3, translateByVector4, '
680
      'or translateByDouble instead')
681
  void translate(dynamic x, [double y = 0.0, double z = 0.0]) {
UNCOV
682
    if (x is Vector3) {
×
NEW
683
      translateByVector3(x);
×
684
    } else if (x is Vector4) {
×
NEW
685
      translateByVector4(x);
×
686
    } else if (x is double) {
×
NEW
687
      translateByDouble(x, y, z, 1.0);
×
688
    } else {
689
      throw UnimplementedError();
×
690
    }
691
  }
692

693
  /// Translate this matrix by x, y, z, w.
NEW
694
  @pragma('wasm:prefer-inline')
×
695
  @pragma('vm:prefer-inline')
696
  @pragma('dart2js:prefer-inline')
697
  void translateByDouble(double tx, double ty, double tz, double tw) {
698
    final t1 = _m4storage[0] * tx +
×
699
        _m4storage[4] * ty +
×
700
        _m4storage[8] * tz +
×
701
        _m4storage[12] * tw;
×
NEW
702
    _m4storage[12] = t1;
×
703

704
    final t2 = _m4storage[1] * tx +
×
705
        _m4storage[5] * ty +
×
706
        _m4storage[9] * tz +
×
707
        _m4storage[13] * tw;
×
NEW
708
    _m4storage[13] = t2;
×
709

710
    final t3 = _m4storage[2] * tx +
×
711
        _m4storage[6] * ty +
×
712
        _m4storage[10] * tz +
×
713
        _m4storage[14] * tw;
×
NEW
714
    _m4storage[14] = t3;
×
715

716
    final t4 = _m4storage[3] * tx +
×
717
        _m4storage[7] * ty +
×
718
        _m4storage[11] * tz +
×
719
        _m4storage[15] * tw;
×
720
    _m4storage[15] = t4;
×
721
  }
722

723
  /// Translate this matrix by a [Vector3].
NEW
724
  @pragma('wasm:prefer-inline')
×
725
  @pragma('vm:prefer-inline')
726
  @pragma('dart2js:prefer-inline')
727
  void translateByVector3(Vector3 v3) =>
NEW
728
      translateByDouble(v3.x, v3.y, v3.z, 1.0);
×
729

730
  /// Translate this matrix by a [Vector4].
NEW
731
  @pragma('wasm:prefer-inline')
×
732
  @pragma('vm:prefer-inline')
733
  @pragma('dart2js:prefer-inline')
734
  void translateByVector4(Vector4 v4) =>
NEW
735
      translateByDouble(v4.x, v4.y, v4.z, v4.w);
×
736

737
  /// Multiply this by a translation from the left.
738
  ///
739
  /// The translation can be specified with a [Vector3], [Vector4], or x, y, z
740
  /// as [double]s.
741
  ///
742
  /// If you know the argument types in a call site, prefer
743
  /// [leftTranslateByDouble], [leftTranslateByVector3], or
744
  /// [leftTranslateByVector4] for performance.
NEW
745
  @pragma('wasm:prefer-inline')
×
746
  @pragma('vm:prefer-inline')
747
  @pragma('dart2js:prefer-inline')
748
  @Deprecated('Use leftTranslateByVector3, leftTranslateByVector4, '
749
      'or leftTranslateByDouble instead')
750
  void leftTranslate(dynamic x, [double y = 0.0, double z = 0.0]) {
UNCOV
751
    if (x is Vector3) {
×
NEW
752
      leftTranslateByVector3(x);
×
753
    } else if (x is Vector4) {
×
NEW
754
      leftTranslateByVector4(x);
×
755
    } else if (x is double) {
×
NEW
756
      leftTranslateByDouble(x, y, z, 1.0);
×
757
    } else {
758
      throw UnimplementedError();
×
759
    }
760
  }
761

762
  /// Multiply this by a translation from the left.
NEW
763
  @pragma('wasm:prefer-inline')
×
764
  @pragma('vm:prefer-inline')
765
  @pragma('dart2js:prefer-inline')
766
  void leftTranslateByDouble(double tx, double ty, double tz, double tw) {
767
    // Column 1
NEW
768
    final r1 = _m4storage[3];
×
NEW
769
    _m4storage[0] += tx * r1;
×
NEW
770
    _m4storage[1] += ty * r1;
×
NEW
771
    _m4storage[2] += tz * r1;
×
NEW
772
    _m4storage[3] = tw * r1;
×
773

774
    // Column 2
NEW
775
    final r2 = _m4storage[7];
×
NEW
776
    _m4storage[4] += tx * r2;
×
NEW
777
    _m4storage[5] += ty * r2;
×
NEW
778
    _m4storage[6] += tz * r2;
×
NEW
779
    _m4storage[7] = tw * r2;
×
780

781
    // Column 3
NEW
782
    final r3 = _m4storage[11];
×
NEW
783
    _m4storage[8] += tx * r3;
×
NEW
784
    _m4storage[9] += ty * r3;
×
NEW
785
    _m4storage[10] += tz * r3;
×
NEW
786
    _m4storage[11] = tw * r3;
×
787

788
    // Column 4
NEW
789
    final r4 = _m4storage[15];
×
NEW
790
    _m4storage[12] += tx * r4;
×
NEW
791
    _m4storage[13] += ty * r4;
×
NEW
792
    _m4storage[14] += tz * r4;
×
NEW
793
    _m4storage[15] = tw * r4;
×
794
  }
795

796
  /// Multiply this by a translation from the left.
NEW
797
  @pragma('wasm:prefer-inline')
×
798
  @pragma('vm:prefer-inline')
799
  @pragma('dart2js:prefer-inline')
800
  void leftTranslateByVector3(Vector3 v3) =>
NEW
801
      leftTranslateByDouble(v3.x, v3.y, v3.z, 1.0);
×
802

803
  /// Multiply this by a translation from the left.
NEW
804
  @pragma('wasm:prefer-inline')
×
805
  @pragma('vm:prefer-inline')
806
  @pragma('dart2js:prefer-inline')
807
  void leftTranslateByVector4(Vector4 v4) =>
NEW
808
      leftTranslateByDouble(v4.x, v4.y, v4.z, v4.w);
×
809

810
  /// Rotate this [angle] radians around [axis]
811
  void rotate(Vector3 axis, double angle) {
×
812
    final len = axis.length;
×
813
    final axisStorage = axis._v3storage;
×
814
    final x = axisStorage[0] / len;
×
815
    final y = axisStorage[1] / len;
×
816
    final z = axisStorage[2] / len;
×
817
    final c = math.cos(angle);
×
818
    final s = math.sin(angle);
×
819
    final C = 1.0 - c;
×
820
    final m11 = x * x * C + c;
×
821
    final m12 = x * y * C - z * s;
×
822
    final m13 = x * z * C + y * s;
×
823
    final m21 = y * x * C + z * s;
×
824
    final m22 = y * y * C + c;
×
825
    final m23 = y * z * C - x * s;
×
826
    final m31 = z * x * C - y * s;
×
827
    final m32 = z * y * C + x * s;
×
828
    final m33 = z * z * C + c;
×
829
    final t1 = _m4storage[0] * m11 + _m4storage[4] * m21 + _m4storage[8] * m31;
×
830
    final t2 = _m4storage[1] * m11 + _m4storage[5] * m21 + _m4storage[9] * m31;
×
831
    final t3 = _m4storage[2] * m11 + _m4storage[6] * m21 + _m4storage[10] * m31;
×
832
    final t4 = _m4storage[3] * m11 + _m4storage[7] * m21 + _m4storage[11] * m31;
×
833
    final t5 = _m4storage[0] * m12 + _m4storage[4] * m22 + _m4storage[8] * m32;
×
834
    final t6 = _m4storage[1] * m12 + _m4storage[5] * m22 + _m4storage[9] * m32;
×
835
    final t7 = _m4storage[2] * m12 + _m4storage[6] * m22 + _m4storage[10] * m32;
×
836
    final t8 = _m4storage[3] * m12 + _m4storage[7] * m22 + _m4storage[11] * m32;
×
837
    final t9 = _m4storage[0] * m13 + _m4storage[4] * m23 + _m4storage[8] * m33;
×
838
    final t10 = _m4storage[1] * m13 + _m4storage[5] * m23 + _m4storage[9] * m33;
×
839
    final t11 =
840
        _m4storage[2] * m13 + _m4storage[6] * m23 + _m4storage[10] * m33;
×
841
    final t12 =
842
        _m4storage[3] * m13 + _m4storage[7] * m23 + _m4storage[11] * m33;
×
843
    _m4storage[0] = t1;
×
844
    _m4storage[1] = t2;
×
845
    _m4storage[2] = t3;
×
846
    _m4storage[3] = t4;
×
847
    _m4storage[4] = t5;
×
848
    _m4storage[5] = t6;
×
849
    _m4storage[6] = t7;
×
850
    _m4storage[7] = t8;
×
851
    _m4storage[8] = t9;
×
852
    _m4storage[9] = t10;
×
853
    _m4storage[10] = t11;
×
854
    _m4storage[11] = t12;
×
855
  }
856

857
  /// Rotate this [angle] radians around X
858
  void rotateX(double angle) {
×
859
    final cosAngle = math.cos(angle);
×
860
    final sinAngle = math.sin(angle);
×
861
    final t1 = _m4storage[4] * cosAngle + _m4storage[8] * sinAngle;
×
862
    final t2 = _m4storage[5] * cosAngle + _m4storage[9] * sinAngle;
×
863
    final t3 = _m4storage[6] * cosAngle + _m4storage[10] * sinAngle;
×
864
    final t4 = _m4storage[7] * cosAngle + _m4storage[11] * sinAngle;
×
865
    final t5 = _m4storage[4] * -sinAngle + _m4storage[8] * cosAngle;
×
866
    final t6 = _m4storage[5] * -sinAngle + _m4storage[9] * cosAngle;
×
867
    final t7 = _m4storage[6] * -sinAngle + _m4storage[10] * cosAngle;
×
868
    final t8 = _m4storage[7] * -sinAngle + _m4storage[11] * cosAngle;
×
869
    _m4storage[4] = t1;
×
870
    _m4storage[5] = t2;
×
871
    _m4storage[6] = t3;
×
872
    _m4storage[7] = t4;
×
873
    _m4storage[8] = t5;
×
874
    _m4storage[9] = t6;
×
875
    _m4storage[10] = t7;
×
876
    _m4storage[11] = t8;
×
877
  }
878

879
  /// Rotate this matrix [angle] radians around Y
880
  void rotateY(double angle) {
×
881
    final cosAngle = math.cos(angle);
×
882
    final sinAngle = math.sin(angle);
×
883
    final t1 = _m4storage[0] * cosAngle + _m4storage[8] * -sinAngle;
×
884
    final t2 = _m4storage[1] * cosAngle + _m4storage[9] * -sinAngle;
×
885
    final t3 = _m4storage[2] * cosAngle + _m4storage[10] * -sinAngle;
×
886
    final t4 = _m4storage[3] * cosAngle + _m4storage[11] * -sinAngle;
×
887
    final t5 = _m4storage[0] * sinAngle + _m4storage[8] * cosAngle;
×
888
    final t6 = _m4storage[1] * sinAngle + _m4storage[9] * cosAngle;
×
889
    final t7 = _m4storage[2] * sinAngle + _m4storage[10] * cosAngle;
×
890
    final t8 = _m4storage[3] * sinAngle + _m4storage[11] * cosAngle;
×
891
    _m4storage[0] = t1;
×
892
    _m4storage[1] = t2;
×
893
    _m4storage[2] = t3;
×
894
    _m4storage[3] = t4;
×
895
    _m4storage[8] = t5;
×
896
    _m4storage[9] = t6;
×
897
    _m4storage[10] = t7;
×
898
    _m4storage[11] = t8;
×
899
  }
900

901
  /// Rotate this matrix [angle] radians around Z
902
  void rotateZ(double angle) {
×
903
    final cosAngle = math.cos(angle);
×
904
    final sinAngle = math.sin(angle);
×
905
    final t1 = _m4storage[0] * cosAngle + _m4storage[4] * sinAngle;
×
906
    final t2 = _m4storage[1] * cosAngle + _m4storage[5] * sinAngle;
×
907
    final t3 = _m4storage[2] * cosAngle + _m4storage[6] * sinAngle;
×
908
    final t4 = _m4storage[3] * cosAngle + _m4storage[7] * sinAngle;
×
909
    final t5 = _m4storage[0] * -sinAngle + _m4storage[4] * cosAngle;
×
910
    final t6 = _m4storage[1] * -sinAngle + _m4storage[5] * cosAngle;
×
911
    final t7 = _m4storage[2] * -sinAngle + _m4storage[6] * cosAngle;
×
912
    final t8 = _m4storage[3] * -sinAngle + _m4storage[7] * cosAngle;
×
913
    _m4storage[0] = t1;
×
914
    _m4storage[1] = t2;
×
915
    _m4storage[2] = t3;
×
916
    _m4storage[3] = t4;
×
917
    _m4storage[4] = t5;
×
918
    _m4storage[5] = t6;
×
919
    _m4storage[6] = t7;
×
920
    _m4storage[7] = t8;
×
921
  }
922

923
  /// Scale this matrix by a [Vector3], [Vector4], or x,y,z as [double]s.
924
  ///
925
  /// If you know the argument types in a call site, prefer [scaleByDouble],
926
  /// [scaleByVector3], or [scaleByVector4] for performance.
NEW
927
  @pragma('wasm:prefer-inline')
×
928
  @pragma('vm:prefer-inline')
929
  @pragma('dart2js:prefer-inline')
930
  @Deprecated('Use scaleByVector3, scaleByVector4, or scaleByDouble instead')
931
  void scale(dynamic x, [double? y, double? z]) {
UNCOV
932
    if (x is Vector3) {
×
NEW
933
      scaleByVector3(x);
×
934
    } else if (x is Vector4) {
×
NEW
935
      scaleByVector4(x);
×
936
    } else if (x is double) {
×
NEW
937
      scaleByDouble(x, y ?? x, z ?? x, 1.0);
×
938
    } else {
939
      throw UnimplementedError();
×
940
    }
941
  }
942

943
  /// Scale this matrix.
NEW
944
  @pragma('wasm:prefer-inline')
×
945
  @pragma('vm:prefer-inline')
946
  @pragma('dart2js:prefer-inline')
947
  void scaleByDouble(double sx, double sy, double sz, double sw) {
948
    _m4storage[0] *= sx;
×
949
    _m4storage[1] *= sx;
×
950
    _m4storage[2] *= sx;
×
951
    _m4storage[3] *= sx;
×
952
    _m4storage[4] *= sy;
×
953
    _m4storage[5] *= sy;
×
954
    _m4storage[6] *= sy;
×
955
    _m4storage[7] *= sy;
×
956
    _m4storage[8] *= sz;
×
957
    _m4storage[9] *= sz;
×
958
    _m4storage[10] *= sz;
×
959
    _m4storage[11] *= sz;
×
960
    _m4storage[12] *= sw;
×
961
    _m4storage[13] *= sw;
×
962
    _m4storage[14] *= sw;
×
963
    _m4storage[15] *= sw;
×
964
  }
965

966
  /// Scale this matrix.
NEW
967
  @pragma('wasm:prefer-inline')
×
968
  @pragma('vm:prefer-inline')
969
  @pragma('dart2js:prefer-inline')
NEW
970
  void scaleByVector3(Vector3 v3) => scaleByDouble(v3.x, v3.y, v3.z, 1.0);
×
971

972
  /// Scale this matrix.
NEW
973
  @pragma('wasm:prefer-inline')
×
974
  @pragma('vm:prefer-inline')
975
  @pragma('dart2js:prefer-inline')
NEW
976
  void scaleByVector4(Vector4 v4) => scaleByDouble(v4.x, v4.y, v4.z, v4.w);
×
977

978
  /// Create a copy of this scaled by a [Vector3], [Vector4] or [x],[y], and
979
  /// [z].
NEW
980
  @pragma('wasm:prefer-inline')
×
981
  @pragma('vm:prefer-inline')
982
  @pragma('dart2js:prefer-inline')
983
  @Deprecated('Use scaledByVector3, scaledByVector4, or scaledByDouble instead')
UNCOV
984
  Matrix4 scaled(dynamic x, [double? y, double? z]) => clone()..scale(x, y, z);
×
985

986
  /// Create a copy of this scaled by [x], [y], [z], and [t].
NEW
987
  @pragma('wasm:prefer-inline')
×
988
  @pragma('vm:prefer-inline')
989
  @pragma('dart2js:prefer-inline')
990
  Matrix4 scaledByDouble(double x, double y, double z, double t) =>
NEW
991
      clone()..scaleByDouble(x, y, z, t);
×
992

993
  /// Create a copy of this scaled by a [Vector3].
NEW
994
  @pragma('wasm:prefer-inline')
×
995
  @pragma('vm:prefer-inline')
996
  @pragma('dart2js:prefer-inline')
NEW
997
  Matrix4 scaledByVector3(Vector3 v3) => clone()..scaleByVector3(v3);
×
998

999
  /// Create a copy of this scaled by a [Vector4].
NEW
1000
  @pragma('wasm:prefer-inline')
×
1001
  @pragma('vm:prefer-inline')
1002
  @pragma('dart2js:prefer-inline')
NEW
1003
  Matrix4 scaledByVector4(Vector4 v4) => clone()..scaleByVector4(v4);
×
1004

1005
  /// Zeros this.
1006
  void setZero() {
×
1007
    _m4storage[0] = 0.0;
×
1008
    _m4storage[1] = 0.0;
×
1009
    _m4storage[2] = 0.0;
×
1010
    _m4storage[3] = 0.0;
×
1011
    _m4storage[4] = 0.0;
×
1012
    _m4storage[5] = 0.0;
×
1013
    _m4storage[6] = 0.0;
×
1014
    _m4storage[7] = 0.0;
×
1015
    _m4storage[8] = 0.0;
×
1016
    _m4storage[9] = 0.0;
×
1017
    _m4storage[10] = 0.0;
×
1018
    _m4storage[11] = 0.0;
×
1019
    _m4storage[12] = 0.0;
×
1020
    _m4storage[13] = 0.0;
×
1021
    _m4storage[14] = 0.0;
×
1022
    _m4storage[15] = 0.0;
×
1023
  }
1024

1025
  /// Makes this into the identity matrix.
1026
  void setIdentity() {
×
1027
    _m4storage[0] = 1.0;
×
1028
    _m4storage[1] = 0.0;
×
1029
    _m4storage[2] = 0.0;
×
1030
    _m4storage[3] = 0.0;
×
1031
    _m4storage[4] = 0.0;
×
1032
    _m4storage[5] = 1.0;
×
1033
    _m4storage[6] = 0.0;
×
1034
    _m4storage[7] = 0.0;
×
1035
    _m4storage[8] = 0.0;
×
1036
    _m4storage[9] = 0.0;
×
1037
    _m4storage[10] = 1.0;
×
1038
    _m4storage[11] = 0.0;
×
1039
    _m4storage[12] = 0.0;
×
1040
    _m4storage[13] = 0.0;
×
1041
    _m4storage[14] = 0.0;
×
1042
    _m4storage[15] = 1.0;
×
1043
  }
1044

1045
  /// Returns the tranpose of this.
1046
  Matrix4 transposed() => clone()..transpose();
×
1047

1048
  void transpose() {
×
1049
    double temp;
1050
    temp = _m4storage[4];
×
1051
    _m4storage[4] = _m4storage[1];
×
1052
    _m4storage[1] = temp;
×
1053
    temp = _m4storage[8];
×
1054
    _m4storage[8] = _m4storage[2];
×
1055
    _m4storage[2] = temp;
×
1056
    temp = _m4storage[12];
×
1057
    _m4storage[12] = _m4storage[3];
×
1058
    _m4storage[3] = temp;
×
1059
    temp = _m4storage[9];
×
1060
    _m4storage[9] = _m4storage[6];
×
1061
    _m4storage[6] = temp;
×
1062
    temp = _m4storage[13];
×
1063
    _m4storage[13] = _m4storage[7];
×
1064
    _m4storage[7] = temp;
×
1065
    temp = _m4storage[14];
×
1066
    _m4storage[14] = _m4storage[11];
×
1067
    _m4storage[11] = temp;
×
1068
  }
1069

1070
  /// Returns the component wise absolute value of this.
1071
  Matrix4 absolute() {
×
1072
    final r = Matrix4.zero();
×
1073
    final rStorage = r._m4storage;
×
1074
    rStorage[0] = _m4storage[0].abs();
×
1075
    rStorage[1] = _m4storage[1].abs();
×
1076
    rStorage[2] = _m4storage[2].abs();
×
1077
    rStorage[3] = _m4storage[3].abs();
×
1078
    rStorage[4] = _m4storage[4].abs();
×
1079
    rStorage[5] = _m4storage[5].abs();
×
1080
    rStorage[6] = _m4storage[6].abs();
×
1081
    rStorage[7] = _m4storage[7].abs();
×
1082
    rStorage[8] = _m4storage[8].abs();
×
1083
    rStorage[9] = _m4storage[9].abs();
×
1084
    rStorage[10] = _m4storage[10].abs();
×
1085
    rStorage[11] = _m4storage[11].abs();
×
1086
    rStorage[12] = _m4storage[12].abs();
×
1087
    rStorage[13] = _m4storage[13].abs();
×
1088
    rStorage[14] = _m4storage[14].abs();
×
1089
    rStorage[15] = _m4storage[15].abs();
×
1090
    return r;
1091
  }
1092

1093
  /// Returns the determinant of this matrix.
1094
  double determinant() {
×
1095
    final det2_01_01 =
1096
        _m4storage[0] * _m4storage[5] - _m4storage[1] * _m4storage[4];
×
1097
    final det2_01_02 =
1098
        _m4storage[0] * _m4storage[6] - _m4storage[2] * _m4storage[4];
×
1099
    final det2_01_03 =
1100
        _m4storage[0] * _m4storage[7] - _m4storage[3] * _m4storage[4];
×
1101
    final det2_01_12 =
1102
        _m4storage[1] * _m4storage[6] - _m4storage[2] * _m4storage[5];
×
1103
    final det2_01_13 =
1104
        _m4storage[1] * _m4storage[7] - _m4storage[3] * _m4storage[5];
×
1105
    final det2_01_23 =
1106
        _m4storage[2] * _m4storage[7] - _m4storage[3] * _m4storage[6];
×
1107
    final det3_201_012 = _m4storage[8] * det2_01_12 -
×
1108
        _m4storage[9] * det2_01_02 +
×
1109
        _m4storage[10] * det2_01_01;
×
1110
    final det3_201_013 = _m4storage[8] * det2_01_13 -
×
1111
        _m4storage[9] * det2_01_03 +
×
1112
        _m4storage[11] * det2_01_01;
×
1113
    final det3_201_023 = _m4storage[8] * det2_01_23 -
×
1114
        _m4storage[10] * det2_01_03 +
×
1115
        _m4storage[11] * det2_01_02;
×
1116
    final det3_201_123 = _m4storage[9] * det2_01_23 -
×
1117
        _m4storage[10] * det2_01_13 +
×
1118
        _m4storage[11] * det2_01_12;
×
1119
    return -det3_201_123 * _m4storage[12] +
×
1120
        det3_201_023 * _m4storage[13] -
×
1121
        det3_201_013 * _m4storage[14] +
×
1122
        det3_201_012 * _m4storage[15];
×
1123
  }
1124

1125
  /// Returns the dot product of row [i] and [v].
1126
  double dotRow(int i, Vector4 v) {
×
1127
    final vStorage = v._v4storage;
×
1128
    return _m4storage[i] * vStorage[0] +
×
1129
        _m4storage[4 + i] * vStorage[1] +
×
1130
        _m4storage[8 + i] * vStorage[2] +
×
1131
        _m4storage[12 + i] * vStorage[3];
×
1132
  }
1133

1134
  /// Returns the dot product of column [j] and [v].
1135
  double dotColumn(int j, Vector4 v) {
×
1136
    final vStorage = v._v4storage;
×
1137
    return _m4storage[j * 4] * vStorage[0] +
×
1138
        _m4storage[j * 4 + 1] * vStorage[1] +
×
1139
        _m4storage[j * 4 + 2] * vStorage[2] +
×
1140
        _m4storage[j * 4 + 3] * vStorage[3];
×
1141
  }
1142

1143
  /// Returns the trace of the matrix. The trace of a matrix is the sum of the
1144
  /// diagonal entries.
1145
  double trace() {
×
1146
    var t = 0.0;
1147
    t += _m4storage[0];
×
1148
    t += _m4storage[5];
×
1149
    t += _m4storage[10];
×
1150
    t += _m4storage[15];
×
1151
    return t;
1152
  }
1153

1154
  /// Returns infinity norm of the matrix. Used for numerical analysis.
1155
  double infinityNorm() {
×
1156
    var norm = 0.0;
1157
    {
1158
      var row_norm = 0.0;
1159
      row_norm += _m4storage[0].abs();
×
1160
      row_norm += _m4storage[1].abs();
×
1161
      row_norm += _m4storage[2].abs();
×
1162
      row_norm += _m4storage[3].abs();
×
1163
      norm = row_norm > norm ? row_norm : norm;
×
1164
    }
1165
    {
1166
      var row_norm = 0.0;
1167
      row_norm += _m4storage[4].abs();
×
1168
      row_norm += _m4storage[5].abs();
×
1169
      row_norm += _m4storage[6].abs();
×
1170
      row_norm += _m4storage[7].abs();
×
1171
      norm = row_norm > norm ? row_norm : norm;
×
1172
    }
1173
    {
1174
      var row_norm = 0.0;
1175
      row_norm += _m4storage[8].abs();
×
1176
      row_norm += _m4storage[9].abs();
×
1177
      row_norm += _m4storage[10].abs();
×
1178
      row_norm += _m4storage[11].abs();
×
1179
      norm = row_norm > norm ? row_norm : norm;
×
1180
    }
1181
    {
1182
      var row_norm = 0.0;
1183
      row_norm += _m4storage[12].abs();
×
1184
      row_norm += _m4storage[13].abs();
×
1185
      row_norm += _m4storage[14].abs();
×
1186
      row_norm += _m4storage[15].abs();
×
1187
      norm = row_norm > norm ? row_norm : norm;
×
1188
    }
1189
    return norm;
1190
  }
1191

1192
  /// Returns relative error between this and [correct]
1193
  double relativeError(Matrix4 correct) {
×
1194
    final diff = correct - this;
×
1195
    final correct_norm = correct.infinityNorm();
×
1196
    final diff_norm = diff.infinityNorm();
×
1197
    return diff_norm / correct_norm;
×
1198
  }
1199

1200
  /// Returns absolute error between this and [correct]
1201
  double absoluteError(Matrix4 correct) {
×
1202
    final this_norm = infinityNorm();
×
1203
    final correct_norm = correct.infinityNorm();
×
1204
    final diff_norm = (this_norm - correct_norm).abs();
×
1205
    return diff_norm;
1206
  }
1207

1208
  /// Returns the translation vector from this homogeneous transformation
1209
  /// matrix.
1210
  Vector3 getTranslation() {
×
1211
    final z = _m4storage[14];
×
1212
    final y = _m4storage[13];
×
1213
    final x = _m4storage[12];
×
1214
    return Vector3(x, y, z);
×
1215
  }
1216

1217
  /// Sets the translation vector in this homogeneous transformation matrix.
1218
  void setTranslation(Vector3 t) {
×
1219
    final tStorage = t._v3storage;
×
1220
    final z = tStorage[2];
×
1221
    final y = tStorage[1];
×
1222
    final x = tStorage[0];
×
1223
    _m4storage[14] = z;
×
1224
    _m4storage[13] = y;
×
1225
    _m4storage[12] = x;
×
1226
  }
1227

1228
  /// Sets the translation vector in this homogeneous transformation matrix.
1229
  void setTranslationRaw(double x, double y, double z) {
×
1230
    _m4storage[14] = z;
×
1231
    _m4storage[13] = y;
×
1232
    _m4storage[12] = x;
×
1233
  }
1234

1235
  /// Returns the rotation matrix from this homogeneous transformation matrix.
1236
  Matrix3 getRotation() {
×
1237
    final r = Matrix3.zero();
×
1238
    copyRotation(r);
×
1239
    return r;
1240
  }
1241

1242
  /// Copies the rotation matrix from this homogeneous transformation matrix
1243
  /// into [rotation].
1244
  void copyRotation(Matrix3 rotation) {
×
1245
    final rStorage = rotation._m3storage;
×
1246
    rStorage[0] = _m4storage[0];
×
1247
    rStorage[1] = _m4storage[1];
×
1248
    rStorage[2] = _m4storage[2];
×
1249
    rStorage[3] = _m4storage[4];
×
1250
    rStorage[4] = _m4storage[5];
×
1251
    rStorage[5] = _m4storage[6];
×
1252
    rStorage[6] = _m4storage[8];
×
1253
    rStorage[7] = _m4storage[9];
×
1254
    rStorage[8] = _m4storage[10];
×
1255
  }
1256

1257
  /// Sets the rotation matrix in this homogeneous transformation matrix.
1258
  void setRotation(Matrix3 r) {
×
1259
    final rStorage = r._m3storage;
×
1260
    _m4storage[0] = rStorage[0];
×
1261
    _m4storage[1] = rStorage[1];
×
1262
    _m4storage[2] = rStorage[2];
×
1263
    _m4storage[4] = rStorage[3];
×
1264
    _m4storage[5] = rStorage[4];
×
1265
    _m4storage[6] = rStorage[5];
×
1266
    _m4storage[8] = rStorage[6];
×
1267
    _m4storage[9] = rStorage[7];
×
1268
    _m4storage[10] = rStorage[8];
×
1269
  }
1270

1271
  /// Returns the normal matrix from this homogeneous transformation matrix.
1272
  ///
1273
  /// The normal matrix is the transpose of the inverse of the top-left 3x3 part
1274
  /// of this 4x4 matrix.
1275
  Matrix3 getNormalMatrix() => Matrix3.identity()..copyNormalMatrix(this);
×
1276

1277
  /// Returns the max scale value of the 3 axes.
1278
  double getMaxScaleOnAxis() {
×
1279
    final scaleXSq = _m4storage[0] * _m4storage[0] +
×
1280
        _m4storage[1] * _m4storage[1] +
×
1281
        _m4storage[2] * _m4storage[2];
×
1282
    final scaleYSq = _m4storage[4] * _m4storage[4] +
×
1283
        _m4storage[5] * _m4storage[5] +
×
1284
        _m4storage[6] * _m4storage[6];
×
1285
    final scaleZSq = _m4storage[8] * _m4storage[8] +
×
1286
        _m4storage[9] * _m4storage[9] +
×
1287
        _m4storage[10] * _m4storage[10];
×
1288
    return math.sqrt(math.max(scaleXSq, math.max(scaleYSq, scaleZSq)));
×
1289
  }
1290

1291
  /// Transposes just the upper 3x3 rotation matrix.
1292
  void transposeRotation() {
×
1293
    double temp;
1294
    temp = _m4storage[1];
×
1295
    _m4storage[1] = _m4storage[4];
×
1296
    _m4storage[4] = temp;
×
1297
    temp = _m4storage[2];
×
1298
    _m4storage[2] = _m4storage[8];
×
1299
    _m4storage[8] = temp;
×
1300
    temp = _m4storage[4];
×
1301
    _m4storage[4] = _m4storage[1];
×
1302
    _m4storage[1] = temp;
×
1303
    temp = _m4storage[6];
×
1304
    _m4storage[6] = _m4storage[9];
×
1305
    _m4storage[9] = temp;
×
1306
    temp = _m4storage[8];
×
1307
    _m4storage[8] = _m4storage[2];
×
1308
    _m4storage[2] = temp;
×
1309
    temp = _m4storage[9];
×
1310
    _m4storage[9] = _m4storage[6];
×
1311
    _m4storage[6] = temp;
×
1312
  }
1313

1314
  /// Invert this.
1315
  double invert() => copyInverse(this);
×
1316

1317
  /// Set this matrix to be the inverse of [arg]
1318
  double copyInverse(Matrix4 arg) {
×
1319
    final argStorage = arg._m4storage;
×
1320
    final a00 = argStorage[0];
×
1321
    final a01 = argStorage[1];
×
1322
    final a02 = argStorage[2];
×
1323
    final a03 = argStorage[3];
×
1324
    final a10 = argStorage[4];
×
1325
    final a11 = argStorage[5];
×
1326
    final a12 = argStorage[6];
×
1327
    final a13 = argStorage[7];
×
1328
    final a20 = argStorage[8];
×
1329
    final a21 = argStorage[9];
×
1330
    final a22 = argStorage[10];
×
1331
    final a23 = argStorage[11];
×
1332
    final a30 = argStorage[12];
×
1333
    final a31 = argStorage[13];
×
1334
    final a32 = argStorage[14];
×
1335
    final a33 = argStorage[15];
×
1336
    final b00 = a00 * a11 - a01 * a10;
×
1337
    final b01 = a00 * a12 - a02 * a10;
×
1338
    final b02 = a00 * a13 - a03 * a10;
×
1339
    final b03 = a01 * a12 - a02 * a11;
×
1340
    final b04 = a01 * a13 - a03 * a11;
×
1341
    final b05 = a02 * a13 - a03 * a12;
×
1342
    final b06 = a20 * a31 - a21 * a30;
×
1343
    final b07 = a20 * a32 - a22 * a30;
×
1344
    final b08 = a20 * a33 - a23 * a30;
×
1345
    final b09 = a21 * a32 - a22 * a31;
×
1346
    final b10 = a21 * a33 - a23 * a31;
×
1347
    final b11 = a22 * a33 - a23 * a32;
×
1348
    final det =
1349
        b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
×
1350
    if (det == 0.0) {
×
1351
      setFrom(arg);
×
1352
      return 0.0;
1353
    }
1354
    final invDet = 1.0 / det;
×
1355
    _m4storage[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;
×
1356
    _m4storage[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;
×
1357
    _m4storage[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;
×
1358
    _m4storage[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;
×
1359
    _m4storage[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;
×
1360
    _m4storage[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;
×
1361
    _m4storage[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;
×
1362
    _m4storage[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;
×
1363
    _m4storage[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;
×
1364
    _m4storage[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;
×
1365
    _m4storage[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;
×
1366
    _m4storage[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;
×
1367
    _m4storage[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;
×
1368
    _m4storage[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;
×
1369
    _m4storage[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;
×
1370
    _m4storage[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;
×
1371
    return det;
1372
  }
1373

1374
  double invertRotation() {
×
1375
    final det = determinant();
×
1376
    if (det == 0.0) {
×
1377
      return 0.0;
1378
    }
1379
    final invDet = 1.0 / det;
×
1380
    double ix;
1381
    double iy;
1382
    double iz;
1383
    double jx;
1384
    double jy;
1385
    double jz;
1386
    double kx;
1387
    double ky;
1388
    double kz;
1389
    ix = invDet *
×
1390
        (_m4storage[5] * _m4storage[10] - _m4storage[6] * _m4storage[9]);
×
1391
    iy = invDet *
×
1392
        (_m4storage[2] * _m4storage[9] - _m4storage[1] * _m4storage[10]);
×
1393
    iz = invDet *
×
1394
        (_m4storage[1] * _m4storage[6] - _m4storage[2] * _m4storage[5]);
×
1395
    jx = invDet *
×
1396
        (_m4storage[6] * _m4storage[8] - _m4storage[4] * _m4storage[10]);
×
1397
    jy = invDet *
×
1398
        (_m4storage[0] * _m4storage[10] - _m4storage[2] * _m4storage[8]);
×
1399
    jz = invDet *
×
1400
        (_m4storage[2] * _m4storage[4] - _m4storage[0] * _m4storage[6]);
×
1401
    kx = invDet *
×
1402
        (_m4storage[4] * _m4storage[9] - _m4storage[5] * _m4storage[8]);
×
1403
    ky = invDet *
×
1404
        (_m4storage[1] * _m4storage[8] - _m4storage[0] * _m4storage[9]);
×
1405
    kz = invDet *
×
1406
        (_m4storage[0] * _m4storage[5] - _m4storage[1] * _m4storage[4]);
×
1407
    _m4storage[0] = ix;
×
1408
    _m4storage[1] = iy;
×
1409
    _m4storage[2] = iz;
×
1410
    _m4storage[4] = jx;
×
1411
    _m4storage[5] = jy;
×
1412
    _m4storage[6] = jz;
×
1413
    _m4storage[8] = kx;
×
1414
    _m4storage[9] = ky;
×
1415
    _m4storage[10] = kz;
×
1416
    return det;
1417
  }
1418

1419
  /// Sets the upper 3x3 to a rotation of [radians] around X
1420
  void setRotationX(double radians) {
×
1421
    final c = math.cos(radians);
×
1422
    final s = math.sin(radians);
×
1423
    _m4storage[0] = 1.0;
×
1424
    _m4storage[1] = 0.0;
×
1425
    _m4storage[2] = 0.0;
×
1426
    _m4storage[4] = 0.0;
×
1427
    _m4storage[5] = c;
×
1428
    _m4storage[6] = s;
×
1429
    _m4storage[8] = 0.0;
×
1430
    _m4storage[9] = -s;
×
1431
    _m4storage[10] = c;
×
1432
    _m4storage[3] = 0.0;
×
1433
    _m4storage[7] = 0.0;
×
1434
    _m4storage[11] = 0.0;
×
1435
  }
1436

1437
  /// Sets the upper 3x3 to a rotation of [radians] around Y
1438
  void setRotationY(double radians) {
×
1439
    final c = math.cos(radians);
×
1440
    final s = math.sin(radians);
×
1441
    _m4storage[0] = c;
×
1442
    _m4storage[1] = 0.0;
×
1443
    _m4storage[2] = -s;
×
1444
    _m4storage[4] = 0.0;
×
1445
    _m4storage[5] = 1.0;
×
1446
    _m4storage[6] = 0.0;
×
1447
    _m4storage[8] = s;
×
1448
    _m4storage[9] = 0.0;
×
1449
    _m4storage[10] = c;
×
1450
    _m4storage[3] = 0.0;
×
1451
    _m4storage[7] = 0.0;
×
1452
    _m4storage[11] = 0.0;
×
1453
  }
1454

1455
  /// Sets the upper 3x3 to a rotation of [radians] around Z
1456
  void setRotationZ(double radians) {
×
1457
    final c = math.cos(radians);
×
1458
    final s = math.sin(radians);
×
1459
    _m4storage[0] = c;
×
1460
    _m4storage[1] = s;
×
1461
    _m4storage[2] = 0.0;
×
1462
    _m4storage[4] = -s;
×
1463
    _m4storage[5] = c;
×
1464
    _m4storage[6] = 0.0;
×
1465
    _m4storage[8] = 0.0;
×
1466
    _m4storage[9] = 0.0;
×
1467
    _m4storage[10] = 1.0;
×
1468
    _m4storage[3] = 0.0;
×
1469
    _m4storage[7] = 0.0;
×
1470
    _m4storage[11] = 0.0;
×
1471
  }
1472

1473
  /// Converts into Adjugate matrix and scales by [scale]
1474
  void scaleAdjoint(double scale) {
×
1475
    // Adapted from code by Richard Carling.
1476
    final a1 = _m4storage[0];
×
1477
    final b1 = _m4storage[4];
×
1478
    final c1 = _m4storage[8];
×
1479
    final d1 = _m4storage[12];
×
1480
    final a2 = _m4storage[1];
×
1481
    final b2 = _m4storage[5];
×
1482
    final c2 = _m4storage[9];
×
1483
    final d2 = _m4storage[13];
×
1484
    final a3 = _m4storage[2];
×
1485
    final b3 = _m4storage[6];
×
1486
    final c3 = _m4storage[10];
×
1487
    final d3 = _m4storage[14];
×
1488
    final a4 = _m4storage[3];
×
1489
    final b4 = _m4storage[7];
×
1490
    final c4 = _m4storage[11];
×
1491
    final d4 = _m4storage[15];
×
1492
    _m4storage[0] = (b2 * (c3 * d4 - c4 * d3) -
×
1493
            c2 * (b3 * d4 - b4 * d3) +
×
1494
            d2 * (b3 * c4 - b4 * c3)) *
×
1495
        scale;
1496
    _m4storage[1] = -(a2 * (c3 * d4 - c4 * d3) -
×
1497
            c2 * (a3 * d4 - a4 * d3) +
×
1498
            d2 * (a3 * c4 - a4 * c3)) *
×
1499
        scale;
1500
    _m4storage[2] = (a2 * (b3 * d4 - b4 * d3) -
×
1501
            b2 * (a3 * d4 - a4 * d3) +
×
1502
            d2 * (a3 * b4 - a4 * b3)) *
×
1503
        scale;
1504
    _m4storage[3] = -(a2 * (b3 * c4 - b4 * c3) -
×
1505
            b2 * (a3 * c4 - a4 * c3) +
×
1506
            c2 * (a3 * b4 - a4 * b3)) *
×
1507
        scale;
1508
    _m4storage[4] = -(b1 * (c3 * d4 - c4 * d3) -
×
1509
            c1 * (b3 * d4 - b4 * d3) +
×
1510
            d1 * (b3 * c4 - b4 * c3)) *
×
1511
        scale;
1512
    _m4storage[5] = (a1 * (c3 * d4 - c4 * d3) -
×
1513
            c1 * (a3 * d4 - a4 * d3) +
×
1514
            d1 * (a3 * c4 - a4 * c3)) *
×
1515
        scale;
1516
    _m4storage[6] = -(a1 * (b3 * d4 - b4 * d3) -
×
1517
            b1 * (a3 * d4 - a4 * d3) +
×
1518
            d1 * (a3 * b4 - a4 * b3)) *
×
1519
        scale;
1520
    _m4storage[7] = (a1 * (b3 * c4 - b4 * c3) -
×
1521
            b1 * (a3 * c4 - a4 * c3) +
×
1522
            c1 * (a3 * b4 - a4 * b3)) *
×
1523
        scale;
1524
    _m4storage[8] = (b1 * (c2 * d4 - c4 * d2) -
×
1525
            c1 * (b2 * d4 - b4 * d2) +
×
1526
            d1 * (b2 * c4 - b4 * c2)) *
×
1527
        scale;
1528
    _m4storage[9] = -(a1 * (c2 * d4 - c4 * d2) -
×
1529
            c1 * (a2 * d4 - a4 * d2) +
×
1530
            d1 * (a2 * c4 - a4 * c2)) *
×
1531
        scale;
1532
    _m4storage[10] = (a1 * (b2 * d4 - b4 * d2) -
×
1533
            b1 * (a2 * d4 - a4 * d2) +
×
1534
            d1 * (a2 * b4 - a4 * b2)) *
×
1535
        scale;
1536
    _m4storage[11] = -(a1 * (b2 * c4 - b4 * c2) -
×
1537
            b1 * (a2 * c4 - a4 * c2) +
×
1538
            c1 * (a2 * b4 - a4 * b2)) *
×
1539
        scale;
1540
    _m4storage[12] = -(b1 * (c2 * d3 - c3 * d2) -
×
1541
            c1 * (b2 * d3 - b3 * d2) +
×
1542
            d1 * (b2 * c3 - b3 * c2)) *
×
1543
        scale;
1544
    _m4storage[13] = (a1 * (c2 * d3 - c3 * d2) -
×
1545
            c1 * (a2 * d3 - a3 * d2) +
×
1546
            d1 * (a2 * c3 - a3 * c2)) *
×
1547
        scale;
1548
    _m4storage[14] = -(a1 * (b2 * d3 - b3 * d2) -
×
1549
            b1 * (a2 * d3 - a3 * d2) +
×
1550
            d1 * (a2 * b3 - a3 * b2)) *
×
1551
        scale;
1552
    _m4storage[15] = (a1 * (b2 * c3 - b3 * c2) -
×
1553
            b1 * (a2 * c3 - a3 * c2) +
×
1554
            c1 * (a2 * b3 - a3 * b2)) *
×
1555
        scale;
1556
  }
1557

1558
  /// Rotates [arg] by the absolute rotation of this
1559
  /// Returns [arg].
1560
  /// Primarily used by AABB transformation code.
1561
  Vector3 absoluteRotate(Vector3 arg) {
×
1562
    final m00 = _m4storage[0].abs();
×
1563
    final m01 = _m4storage[4].abs();
×
1564
    final m02 = _m4storage[8].abs();
×
1565
    final m10 = _m4storage[1].abs();
×
1566
    final m11 = _m4storage[5].abs();
×
1567
    final m12 = _m4storage[9].abs();
×
1568
    final m20 = _m4storage[2].abs();
×
1569
    final m21 = _m4storage[6].abs();
×
1570
    final m22 = _m4storage[10].abs();
×
1571
    final argStorage = arg._v3storage;
×
1572
    final x = argStorage[0];
×
1573
    final y = argStorage[1];
×
1574
    final z = argStorage[2];
×
1575
    argStorage[0] = x * m00 + y * m01 + z * m02 + 0.0 * 0.0;
×
1576
    argStorage[1] = x * m10 + y * m11 + z * m12 + 0.0 * 0.0;
×
1577
    argStorage[2] = x * m20 + y * m21 + z * m22 + 0.0 * 0.0;
×
1578
    return arg;
1579
  }
1580

1581
  /// Adds [o] to this.
1582
  void add(Matrix4 o) {
×
1583
    final oStorage = o._m4storage;
×
1584
    _m4storage[0] = _m4storage[0] + oStorage[0];
×
1585
    _m4storage[1] = _m4storage[1] + oStorage[1];
×
1586
    _m4storage[2] = _m4storage[2] + oStorage[2];
×
1587
    _m4storage[3] = _m4storage[3] + oStorage[3];
×
1588
    _m4storage[4] = _m4storage[4] + oStorage[4];
×
1589
    _m4storage[5] = _m4storage[5] + oStorage[5];
×
1590
    _m4storage[6] = _m4storage[6] + oStorage[6];
×
1591
    _m4storage[7] = _m4storage[7] + oStorage[7];
×
1592
    _m4storage[8] = _m4storage[8] + oStorage[8];
×
1593
    _m4storage[9] = _m4storage[9] + oStorage[9];
×
1594
    _m4storage[10] = _m4storage[10] + oStorage[10];
×
1595
    _m4storage[11] = _m4storage[11] + oStorage[11];
×
1596
    _m4storage[12] = _m4storage[12] + oStorage[12];
×
1597
    _m4storage[13] = _m4storage[13] + oStorage[13];
×
1598
    _m4storage[14] = _m4storage[14] + oStorage[14];
×
1599
    _m4storage[15] = _m4storage[15] + oStorage[15];
×
1600
  }
1601

1602
  /// Subtracts [o] from this.
1603
  void sub(Matrix4 o) {
×
1604
    final oStorage = o._m4storage;
×
1605
    _m4storage[0] = _m4storage[0] - oStorage[0];
×
1606
    _m4storage[1] = _m4storage[1] - oStorage[1];
×
1607
    _m4storage[2] = _m4storage[2] - oStorage[2];
×
1608
    _m4storage[3] = _m4storage[3] - oStorage[3];
×
1609
    _m4storage[4] = _m4storage[4] - oStorage[4];
×
1610
    _m4storage[5] = _m4storage[5] - oStorage[5];
×
1611
    _m4storage[6] = _m4storage[6] - oStorage[6];
×
1612
    _m4storage[7] = _m4storage[7] - oStorage[7];
×
1613
    _m4storage[8] = _m4storage[8] - oStorage[8];
×
1614
    _m4storage[9] = _m4storage[9] - oStorage[9];
×
1615
    _m4storage[10] = _m4storage[10] - oStorage[10];
×
1616
    _m4storage[11] = _m4storage[11] - oStorage[11];
×
1617
    _m4storage[12] = _m4storage[12] - oStorage[12];
×
1618
    _m4storage[13] = _m4storage[13] - oStorage[13];
×
1619
    _m4storage[14] = _m4storage[14] - oStorage[14];
×
1620
    _m4storage[15] = _m4storage[15] - oStorage[15];
×
1621
  }
1622

1623
  /// Negate this.
1624
  void negate() {
×
1625
    _m4storage[0] = -_m4storage[0];
×
1626
    _m4storage[1] = -_m4storage[1];
×
1627
    _m4storage[2] = -_m4storage[2];
×
1628
    _m4storage[3] = -_m4storage[3];
×
1629
    _m4storage[4] = -_m4storage[4];
×
1630
    _m4storage[5] = -_m4storage[5];
×
1631
    _m4storage[6] = -_m4storage[6];
×
1632
    _m4storage[7] = -_m4storage[7];
×
1633
    _m4storage[8] = -_m4storage[8];
×
1634
    _m4storage[9] = -_m4storage[9];
×
1635
    _m4storage[10] = -_m4storage[10];
×
1636
    _m4storage[11] = -_m4storage[11];
×
1637
    _m4storage[12] = -_m4storage[12];
×
1638
    _m4storage[13] = -_m4storage[13];
×
1639
    _m4storage[14] = -_m4storage[14];
×
1640
    _m4storage[15] = -_m4storage[15];
×
1641
  }
1642

1643
  /// Multiply this by [arg].
1644
  void multiply(Matrix4 arg) {
×
1645
    final m00 = _m4storage[0];
×
1646
    final m01 = _m4storage[4];
×
1647
    final m02 = _m4storage[8];
×
1648
    final m03 = _m4storage[12];
×
1649
    final m10 = _m4storage[1];
×
1650
    final m11 = _m4storage[5];
×
1651
    final m12 = _m4storage[9];
×
1652
    final m13 = _m4storage[13];
×
1653
    final m20 = _m4storage[2];
×
1654
    final m21 = _m4storage[6];
×
1655
    final m22 = _m4storage[10];
×
1656
    final m23 = _m4storage[14];
×
1657
    final m30 = _m4storage[3];
×
1658
    final m31 = _m4storage[7];
×
1659
    final m32 = _m4storage[11];
×
1660
    final m33 = _m4storage[15];
×
1661
    final argStorage = arg._m4storage;
×
1662
    final n00 = argStorage[0];
×
1663
    final n01 = argStorage[4];
×
1664
    final n02 = argStorage[8];
×
1665
    final n03 = argStorage[12];
×
1666
    final n10 = argStorage[1];
×
1667
    final n11 = argStorage[5];
×
1668
    final n12 = argStorage[9];
×
1669
    final n13 = argStorage[13];
×
1670
    final n20 = argStorage[2];
×
1671
    final n21 = argStorage[6];
×
1672
    final n22 = argStorage[10];
×
1673
    final n23 = argStorage[14];
×
1674
    final n30 = argStorage[3];
×
1675
    final n31 = argStorage[7];
×
1676
    final n32 = argStorage[11];
×
1677
    final n33 = argStorage[15];
×
1678
    _m4storage[0] = (m00 * n00) + (m01 * n10) + (m02 * n20) + (m03 * n30);
×
1679
    _m4storage[4] = (m00 * n01) + (m01 * n11) + (m02 * n21) + (m03 * n31);
×
1680
    _m4storage[8] = (m00 * n02) + (m01 * n12) + (m02 * n22) + (m03 * n32);
×
1681
    _m4storage[12] = (m00 * n03) + (m01 * n13) + (m02 * n23) + (m03 * n33);
×
1682
    _m4storage[1] = (m10 * n00) + (m11 * n10) + (m12 * n20) + (m13 * n30);
×
1683
    _m4storage[5] = (m10 * n01) + (m11 * n11) + (m12 * n21) + (m13 * n31);
×
1684
    _m4storage[9] = (m10 * n02) + (m11 * n12) + (m12 * n22) + (m13 * n32);
×
1685
    _m4storage[13] = (m10 * n03) + (m11 * n13) + (m12 * n23) + (m13 * n33);
×
1686
    _m4storage[2] = (m20 * n00) + (m21 * n10) + (m22 * n20) + (m23 * n30);
×
1687
    _m4storage[6] = (m20 * n01) + (m21 * n11) + (m22 * n21) + (m23 * n31);
×
1688
    _m4storage[10] = (m20 * n02) + (m21 * n12) + (m22 * n22) + (m23 * n32);
×
1689
    _m4storage[14] = (m20 * n03) + (m21 * n13) + (m22 * n23) + (m23 * n33);
×
1690
    _m4storage[3] = (m30 * n00) + (m31 * n10) + (m32 * n20) + (m33 * n30);
×
1691
    _m4storage[7] = (m30 * n01) + (m31 * n11) + (m32 * n21) + (m33 * n31);
×
1692
    _m4storage[11] = (m30 * n02) + (m31 * n12) + (m32 * n22) + (m33 * n32);
×
1693
    _m4storage[15] = (m30 * n03) + (m31 * n13) + (m32 * n23) + (m33 * n33);
×
1694
  }
1695

1696
  /// Multiply a copy of this with [arg].
1697
  Matrix4 multiplied(Matrix4 arg) => clone()..multiply(arg);
×
1698

1699
  /// Multiply a transposed this with [arg].
1700
  void transposeMultiply(Matrix4 arg) {
×
1701
    final m00 = _m4storage[0];
×
1702
    final m01 = _m4storage[1];
×
1703
    final m02 = _m4storage[2];
×
1704
    final m03 = _m4storage[3];
×
1705
    final m10 = _m4storage[4];
×
1706
    final m11 = _m4storage[5];
×
1707
    final m12 = _m4storage[6];
×
1708
    final m13 = _m4storage[7];
×
1709
    final m20 = _m4storage[8];
×
1710
    final m21 = _m4storage[9];
×
1711
    final m22 = _m4storage[10];
×
1712
    final m23 = _m4storage[11];
×
1713
    final m30 = _m4storage[12];
×
1714
    final m31 = _m4storage[13];
×
1715
    final m32 = _m4storage[14];
×
1716
    final m33 = _m4storage[15];
×
1717
    final argStorage = arg._m4storage;
×
1718
    _m4storage[0] = (m00 * argStorage[0]) +
×
1719
        (m01 * argStorage[1]) +
×
1720
        (m02 * argStorage[2]) +
×
1721
        (m03 * argStorage[3]);
×
1722
    _m4storage[4] = (m00 * argStorage[4]) +
×
1723
        (m01 * argStorage[5]) +
×
1724
        (m02 * argStorage[6]) +
×
1725
        (m03 * argStorage[7]);
×
1726
    _m4storage[8] = (m00 * argStorage[8]) +
×
1727
        (m01 * argStorage[9]) +
×
1728
        (m02 * argStorage[10]) +
×
1729
        (m03 * argStorage[11]);
×
1730
    _m4storage[12] = (m00 * argStorage[12]) +
×
1731
        (m01 * argStorage[13]) +
×
1732
        (m02 * argStorage[14]) +
×
1733
        (m03 * argStorage[15]);
×
1734
    _m4storage[1] = (m10 * argStorage[0]) +
×
1735
        (m11 * argStorage[1]) +
×
1736
        (m12 * argStorage[2]) +
×
1737
        (m13 * argStorage[3]);
×
1738
    _m4storage[5] = (m10 * argStorage[4]) +
×
1739
        (m11 * argStorage[5]) +
×
1740
        (m12 * argStorage[6]) +
×
1741
        (m13 * argStorage[7]);
×
1742
    _m4storage[9] = (m10 * argStorage[8]) +
×
1743
        (m11 * argStorage[9]) +
×
1744
        (m12 * argStorage[10]) +
×
1745
        (m13 * argStorage[11]);
×
1746
    _m4storage[13] = (m10 * argStorage[12]) +
×
1747
        (m11 * argStorage[13]) +
×
1748
        (m12 * argStorage[14]) +
×
1749
        (m13 * argStorage[15]);
×
1750
    _m4storage[2] = (m20 * argStorage[0]) +
×
1751
        (m21 * argStorage[1]) +
×
1752
        (m22 * argStorage[2]) +
×
1753
        (m23 * argStorage[3]);
×
1754
    _m4storage[6] = (m20 * argStorage[4]) +
×
1755
        (m21 * argStorage[5]) +
×
1756
        (m22 * argStorage[6]) +
×
1757
        (m23 * argStorage[7]);
×
1758
    _m4storage[10] = (m20 * argStorage[8]) +
×
1759
        (m21 * argStorage[9]) +
×
1760
        (m22 * argStorage[10]) +
×
1761
        (m23 * argStorage[11]);
×
1762
    _m4storage[14] = (m20 * argStorage[12]) +
×
1763
        (m21 * argStorage[13]) +
×
1764
        (m22 * argStorage[14]) +
×
1765
        (m23 * argStorage[15]);
×
1766
    _m4storage[3] = (m30 * argStorage[0]) +
×
1767
        (m31 * argStorage[1]) +
×
1768
        (m32 * argStorage[2]) +
×
1769
        (m33 * argStorage[3]);
×
1770
    _m4storage[7] = (m30 * argStorage[4]) +
×
1771
        (m31 * argStorage[5]) +
×
1772
        (m32 * argStorage[6]) +
×
1773
        (m33 * argStorage[7]);
×
1774
    _m4storage[11] = (m30 * argStorage[8]) +
×
1775
        (m31 * argStorage[9]) +
×
1776
        (m32 * argStorage[10]) +
×
1777
        (m33 * argStorage[11]);
×
1778
    _m4storage[15] = (m30 * argStorage[12]) +
×
1779
        (m31 * argStorage[13]) +
×
1780
        (m32 * argStorage[14]) +
×
1781
        (m33 * argStorage[15]);
×
1782
  }
1783

1784
  /// Multiply this with a transposed [arg].
1785
  void multiplyTranspose(Matrix4 arg) {
×
1786
    final m00 = _m4storage[0];
×
1787
    final m01 = _m4storage[4];
×
1788
    final m02 = _m4storage[8];
×
1789
    final m03 = _m4storage[12];
×
1790
    final m10 = _m4storage[1];
×
1791
    final m11 = _m4storage[5];
×
1792
    final m12 = _m4storage[9];
×
1793
    final m13 = _m4storage[13];
×
1794
    final m20 = _m4storage[2];
×
1795
    final m21 = _m4storage[6];
×
1796
    final m22 = _m4storage[10];
×
1797
    final m23 = _m4storage[14];
×
1798
    final m30 = _m4storage[3];
×
1799
    final m31 = _m4storage[7];
×
1800
    final m32 = _m4storage[11];
×
1801
    final m33 = _m4storage[15];
×
1802
    final argStorage = arg._m4storage;
×
1803
    _m4storage[0] = (m00 * argStorage[0]) +
×
1804
        (m01 * argStorage[4]) +
×
1805
        (m02 * argStorage[8]) +
×
1806
        (m03 * argStorage[12]);
×
1807
    _m4storage[4] = (m00 * argStorage[1]) +
×
1808
        (m01 * argStorage[5]) +
×
1809
        (m02 * argStorage[9]) +
×
1810
        (m03 * argStorage[13]);
×
1811
    _m4storage[8] = (m00 * argStorage[2]) +
×
1812
        (m01 * argStorage[6]) +
×
1813
        (m02 * argStorage[10]) +
×
1814
        (m03 * argStorage[14]);
×
1815
    _m4storage[12] = (m00 * argStorage[3]) +
×
1816
        (m01 * argStorage[7]) +
×
1817
        (m02 * argStorage[11]) +
×
1818
        (m03 * argStorage[15]);
×
1819
    _m4storage[1] = (m10 * argStorage[0]) +
×
1820
        (m11 * argStorage[4]) +
×
1821
        (m12 * argStorage[8]) +
×
1822
        (m13 * argStorage[12]);
×
1823
    _m4storage[5] = (m10 * argStorage[1]) +
×
1824
        (m11 * argStorage[5]) +
×
1825
        (m12 * argStorage[9]) +
×
1826
        (m13 * argStorage[13]);
×
1827
    _m4storage[9] = (m10 * argStorage[2]) +
×
1828
        (m11 * argStorage[6]) +
×
1829
        (m12 * argStorage[10]) +
×
1830
        (m13 * argStorage[14]);
×
1831
    _m4storage[13] = (m10 * argStorage[3]) +
×
1832
        (m11 * argStorage[7]) +
×
1833
        (m12 * argStorage[11]) +
×
1834
        (m13 * argStorage[15]);
×
1835
    _m4storage[2] = (m20 * argStorage[0]) +
×
1836
        (m21 * argStorage[4]) +
×
1837
        (m22 * argStorage[8]) +
×
1838
        (m23 * argStorage[12]);
×
1839
    _m4storage[6] = (m20 * argStorage[1]) +
×
1840
        (m21 * argStorage[5]) +
×
1841
        (m22 * argStorage[9]) +
×
1842
        (m23 * argStorage[13]);
×
1843
    _m4storage[10] = (m20 * argStorage[2]) +
×
1844
        (m21 * argStorage[6]) +
×
1845
        (m22 * argStorage[10]) +
×
1846
        (m23 * argStorage[14]);
×
1847
    _m4storage[14] = (m20 * argStorage[3]) +
×
1848
        (m21 * argStorage[7]) +
×
1849
        (m22 * argStorage[11]) +
×
1850
        (m23 * argStorage[15]);
×
1851
    _m4storage[3] = (m30 * argStorage[0]) +
×
1852
        (m31 * argStorage[4]) +
×
1853
        (m32 * argStorage[8]) +
×
1854
        (m33 * argStorage[12]);
×
1855
    _m4storage[7] = (m30 * argStorage[1]) +
×
1856
        (m31 * argStorage[5]) +
×
1857
        (m32 * argStorage[9]) +
×
1858
        (m33 * argStorage[13]);
×
1859
    _m4storage[11] = (m30 * argStorage[2]) +
×
1860
        (m31 * argStorage[6]) +
×
1861
        (m32 * argStorage[10]) +
×
1862
        (m33 * argStorage[14]);
×
1863
    _m4storage[15] = (m30 * argStorage[3]) +
×
1864
        (m31 * argStorage[7]) +
×
1865
        (m32 * argStorage[11]) +
×
1866
        (m33 * argStorage[15]);
×
1867
  }
1868

1869
  /// Decomposes this into [translation], [rotation] and [scale] components.
1870
  void decompose(Vector3 translation, Quaternion rotation, Vector3 scale) {
×
1871
    final v = _decomposeV ??= Vector3.zero();
×
1872
    var sx = (v..setValues(_m4storage[0], _m4storage[1], _m4storage[2])).length;
×
1873
    final sy =
1874
        (v..setValues(_m4storage[4], _m4storage[5], _m4storage[6])).length;
×
1875
    final sz =
1876
        (v..setValues(_m4storage[8], _m4storage[9], _m4storage[10])).length;
×
1877

1878
    if (determinant() < 0) {
×
1879
      sx = -sx;
×
1880
    }
1881

1882
    translation._v3storage[0] = _m4storage[12];
×
1883
    translation._v3storage[1] = _m4storage[13];
×
1884
    translation._v3storage[2] = _m4storage[14];
×
1885

1886
    final invSX = 1.0 / sx;
×
1887
    final invSY = 1.0 / sy;
×
1888
    final invSZ = 1.0 / sz;
×
1889

1890
    final m = _decomposeM ??= Matrix4.zero();
×
1891
    m.setFrom(this);
×
1892
    m._m4storage[0] *= invSX;
×
1893
    m._m4storage[1] *= invSX;
×
1894
    m._m4storage[2] *= invSX;
×
1895
    m._m4storage[4] *= invSY;
×
1896
    m._m4storage[5] *= invSY;
×
1897
    m._m4storage[6] *= invSY;
×
1898
    m._m4storage[8] *= invSZ;
×
1899
    m._m4storage[9] *= invSZ;
×
1900
    m._m4storage[10] *= invSZ;
×
1901

1902
    final r = _decomposeR ??= Matrix3.zero();
×
1903
    m.copyRotation(r);
×
1904
    rotation.setFromRotation(r);
×
1905

1906
    scale._v3storage[0] = sx;
×
1907
    scale._v3storage[1] = sy;
×
1908
    scale._v3storage[2] = sz;
×
1909
  }
1910

1911
  static Vector3? _decomposeV;
1912
  static Matrix4? _decomposeM;
1913
  static Matrix3? _decomposeR;
1914

1915
  /// Rotate [arg] of type [Vector3] using the rotation defined by this.
1916
  Vector3 rotate3(Vector3 arg) {
×
1917
    final argStorage = arg._v3storage;
×
1918
    final x_ = (_m4storage[0] * argStorage[0]) +
×
1919
        (_m4storage[4] * argStorage[1]) +
×
1920
        (_m4storage[8] * argStorage[2]);
×
1921
    final y_ = (_m4storage[1] * argStorage[0]) +
×
1922
        (_m4storage[5] * argStorage[1]) +
×
1923
        (_m4storage[9] * argStorage[2]);
×
1924
    final z_ = (_m4storage[2] * argStorage[0]) +
×
1925
        (_m4storage[6] * argStorage[1]) +
×
1926
        (_m4storage[10] * argStorage[2]);
×
1927
    argStorage[0] = x_;
×
1928
    argStorage[1] = y_;
×
1929
    argStorage[2] = z_;
×
1930
    return arg;
1931
  }
1932

1933
  /// Rotate a copy of [arg] of type [Vector3] using the rotation defined by
1934
  /// this. If a [out] parameter is supplied, the copy is stored in [out].
1935
  Vector3 rotated3(Vector3 arg, [Vector3? out]) {
×
1936
    if (out == null) {
1937
      out = Vector3.copy(arg);
×
1938
    } else {
1939
      out.setFrom(arg);
×
1940
    }
1941
    return rotate3(out);
×
1942
  }
1943

1944
  /// Transform [arg] of type [Vector3] using the transformation defined by
1945
  /// this.
1946
  Vector3 transform3(Vector3 arg) {
×
1947
    final argStorage = arg._v3storage;
×
1948
    final x_ = (_m4storage[0] * argStorage[0]) +
×
1949
        (_m4storage[4] * argStorage[1]) +
×
1950
        (_m4storage[8] * argStorage[2]) +
×
1951
        _m4storage[12];
×
1952
    final y_ = (_m4storage[1] * argStorage[0]) +
×
1953
        (_m4storage[5] * argStorage[1]) +
×
1954
        (_m4storage[9] * argStorage[2]) +
×
1955
        _m4storage[13];
×
1956
    final z_ = (_m4storage[2] * argStorage[0]) +
×
1957
        (_m4storage[6] * argStorage[1]) +
×
1958
        (_m4storage[10] * argStorage[2]) +
×
1959
        _m4storage[14];
×
1960
    argStorage[0] = x_;
×
1961
    argStorage[1] = y_;
×
1962
    argStorage[2] = z_;
×
1963
    return arg;
1964
  }
1965

1966
  /// Transform a copy of [arg] of type [Vector3] using the transformation
1967
  /// defined by this. If a [out] parameter is supplied, the copy is stored in
1968
  /// [out].
1969
  Vector3 transformed3(Vector3 arg, [Vector3? out]) {
×
1970
    if (out == null) {
1971
      out = Vector3.copy(arg);
×
1972
    } else {
1973
      out.setFrom(arg);
×
1974
    }
1975
    return transform3(out);
×
1976
  }
1977

1978
  /// Transform [arg] of type [Vector4] using the transformation defined by
1979
  /// this.
1980
  Vector4 transform(Vector4 arg) {
×
1981
    final argStorage = arg._v4storage;
×
1982
    final x_ = (_m4storage[0] * argStorage[0]) +
×
1983
        (_m4storage[4] * argStorage[1]) +
×
1984
        (_m4storage[8] * argStorage[2]) +
×
1985
        (_m4storage[12] * argStorage[3]);
×
1986
    final y_ = (_m4storage[1] * argStorage[0]) +
×
1987
        (_m4storage[5] * argStorage[1]) +
×
1988
        (_m4storage[9] * argStorage[2]) +
×
1989
        (_m4storage[13] * argStorage[3]);
×
1990
    final z_ = (_m4storage[2] * argStorage[0]) +
×
1991
        (_m4storage[6] * argStorage[1]) +
×
1992
        (_m4storage[10] * argStorage[2]) +
×
1993
        (_m4storage[14] * argStorage[3]);
×
1994
    final w_ = (_m4storage[3] * argStorage[0]) +
×
1995
        (_m4storage[7] * argStorage[1]) +
×
1996
        (_m4storage[11] * argStorage[2]) +
×
1997
        (_m4storage[15] * argStorage[3]);
×
1998
    argStorage[0] = x_;
×
1999
    argStorage[1] = y_;
×
2000
    argStorage[2] = z_;
×
2001
    argStorage[3] = w_;
×
2002
    return arg;
2003
  }
2004

2005
  /// Transform [arg] of type [Vector3] using the perspective transformation
2006
  /// defined by this.
2007
  Vector3 perspectiveTransform(Vector3 arg) {
×
2008
    final argStorage = arg._v3storage;
×
2009
    final x_ = (_m4storage[0] * argStorage[0]) +
×
2010
        (_m4storage[4] * argStorage[1]) +
×
2011
        (_m4storage[8] * argStorage[2]) +
×
2012
        _m4storage[12];
×
2013
    final y_ = (_m4storage[1] * argStorage[0]) +
×
2014
        (_m4storage[5] * argStorage[1]) +
×
2015
        (_m4storage[9] * argStorage[2]) +
×
2016
        _m4storage[13];
×
2017
    final z_ = (_m4storage[2] * argStorage[0]) +
×
2018
        (_m4storage[6] * argStorage[1]) +
×
2019
        (_m4storage[10] * argStorage[2]) +
×
2020
        _m4storage[14];
×
2021
    final w_ = 1.0 /
×
2022
        ((_m4storage[3] * argStorage[0]) +
×
2023
            (_m4storage[7] * argStorage[1]) +
×
2024
            (_m4storage[11] * argStorage[2]) +
×
2025
            _m4storage[15]);
×
2026
    argStorage[0] = x_ * w_;
×
2027
    argStorage[1] = y_ * w_;
×
2028
    argStorage[2] = z_ * w_;
×
2029
    return arg;
2030
  }
2031

2032
  /// Transform a copy of [arg] of type [Vector4] using the transformation
2033
  /// defined by this. If a [out] parameter is supplied, the copy is stored in
2034
  /// [out].
2035
  Vector4 transformed(Vector4 arg, [Vector4? out]) {
×
2036
    if (out == null) {
2037
      out = Vector4.copy(arg);
×
2038
    } else {
2039
      out.setFrom(arg);
×
2040
    }
2041
    return transform(out);
×
2042
  }
2043

2044
  /// Copies this into [array] starting at [offset].
2045
  void copyIntoArray(List<num> array, [int offset = 0]) {
×
2046
    final i = offset;
2047
    array[i + 15] = _m4storage[15];
×
2048
    array[i + 14] = _m4storage[14];
×
2049
    array[i + 13] = _m4storage[13];
×
2050
    array[i + 12] = _m4storage[12];
×
2051
    array[i + 11] = _m4storage[11];
×
2052
    array[i + 10] = _m4storage[10];
×
2053
    array[i + 9] = _m4storage[9];
×
2054
    array[i + 8] = _m4storage[8];
×
2055
    array[i + 7] = _m4storage[7];
×
2056
    array[i + 6] = _m4storage[6];
×
2057
    array[i + 5] = _m4storage[5];
×
2058
    array[i + 4] = _m4storage[4];
×
2059
    array[i + 3] = _m4storage[3];
×
2060
    array[i + 2] = _m4storage[2];
×
2061
    array[i + 1] = _m4storage[1];
×
2062
    array[i + 0] = _m4storage[0];
×
2063
  }
2064

2065
  /// Copies elements from [array] into this starting at [offset].
2066
  void copyFromArray(List<double> array, [int offset = 0]) {
×
2067
    final i = offset;
2068
    _m4storage[15] = array[i + 15];
×
2069
    _m4storage[14] = array[i + 14];
×
2070
    _m4storage[13] = array[i + 13];
×
2071
    _m4storage[12] = array[i + 12];
×
2072
    _m4storage[11] = array[i + 11];
×
2073
    _m4storage[10] = array[i + 10];
×
2074
    _m4storage[9] = array[i + 9];
×
2075
    _m4storage[8] = array[i + 8];
×
2076
    _m4storage[7] = array[i + 7];
×
2077
    _m4storage[6] = array[i + 6];
×
2078
    _m4storage[5] = array[i + 5];
×
2079
    _m4storage[4] = array[i + 4];
×
2080
    _m4storage[3] = array[i + 3];
×
2081
    _m4storage[2] = array[i + 2];
×
2082
    _m4storage[1] = array[i + 1];
×
2083
    _m4storage[0] = array[i + 0];
×
2084
  }
2085

2086
  /// Multiply this to each set of xyz values in [array] starting at [offset].
2087
  List<double> applyToVector3Array(List<double> array, [int offset = 0]) {
×
2088
    for (var i = 0, j = offset; i < array.length; i += 3, j += 3) {
×
2089
      final v = Vector3.array(array, j)..applyMatrix4(this);
×
2090
      array[j] = v.storage[0];
×
2091
      array[j + 1] = v.storage[1];
×
2092
      array[j + 2] = v.storage[2];
×
2093
    }
2094

2095
    return array;
2096
  }
2097

2098
  Vector3 get right {
×
2099
    final x = _m4storage[0];
×
2100
    final y = _m4storage[1];
×
2101
    final z = _m4storage[2];
×
2102
    return Vector3(x, y, z);
×
2103
  }
2104

2105
  Vector3 get up {
×
2106
    final x = _m4storage[4];
×
2107
    final y = _m4storage[5];
×
2108
    final z = _m4storage[6];
×
2109
    return Vector3(x, y, z);
×
2110
  }
2111

2112
  Vector3 get forward {
×
2113
    final x = _m4storage[8];
×
2114
    final y = _m4storage[9];
×
2115
    final z = _m4storage[10];
×
2116
    return Vector3(x, y, z);
×
2117
  }
2118

2119
  /// Is this the identity matrix?
2120
  bool isIdentity() =>
×
2121
      _m4storage[0] == 1.0 // col 1
×
2122
      &&
2123
      _m4storage[1] == 0.0 &&
×
2124
      _m4storage[2] == 0.0 &&
×
2125
      _m4storage[3] == 0.0 &&
×
2126
      _m4storage[4] == 0.0 // col 2
×
2127
      &&
2128
      _m4storage[5] == 1.0 &&
×
2129
      _m4storage[6] == 0.0 &&
×
2130
      _m4storage[7] == 0.0 &&
×
2131
      _m4storage[8] == 0.0 // col 3
×
2132
      &&
2133
      _m4storage[9] == 0.0 &&
×
2134
      _m4storage[10] == 1.0 &&
×
2135
      _m4storage[11] == 0.0 &&
×
2136
      _m4storage[12] == 0.0 // col 4
×
2137
      &&
2138
      _m4storage[13] == 0.0 &&
×
2139
      _m4storage[14] == 0.0 &&
×
2140
      _m4storage[15] == 1.0;
×
2141

2142
  /// Is this the zero matrix?
2143
  bool isZero() =>
×
2144
      _m4storage[0] == 0.0 // col 1
×
2145
      &&
2146
      _m4storage[1] == 0.0 &&
×
2147
      _m4storage[2] == 0.0 &&
×
2148
      _m4storage[3] == 0.0 &&
×
2149
      _m4storage[4] == 0.0 // col 2
×
2150
      &&
2151
      _m4storage[5] == 0.0 &&
×
2152
      _m4storage[6] == 0.0 &&
×
2153
      _m4storage[7] == 0.0 &&
×
2154
      _m4storage[8] == 0.0 // col 3
×
2155
      &&
2156
      _m4storage[9] == 0.0 &&
×
2157
      _m4storage[10] == 0.0 &&
×
2158
      _m4storage[11] == 0.0 &&
×
2159
      _m4storage[12] == 0.0 // col 4
×
2160
      &&
2161
      _m4storage[13] == 0.0 &&
×
2162
      _m4storage[14] == 0.0 &&
×
2163
      _m4storage[15] == 0.0;
×
2164
}
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