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

google / vector_math.dart / 23308729438

19 Mar 2026 05:45PM UTC coverage: 27.129% (-0.06%) from 27.188%
23308729438

Pull #365

github

web-flow
Merge 6f9d85ec9 into 932d81447
Pull Request #365: Optimize creating an identity matrix

15 of 30 new or added lines in 6 files covered. (50.0%)

15 existing lines in 2 files now uncovered.

4440 of 16366 relevant lines covered (27.13%)

1.2 hits per line

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

70.69
/lib/src/vector_math/matrix3.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.dart';
6

7
/// 3D Matrix.
8
/// Values are stored in column major order.
9
class Matrix3 {
10
  final Float32List _m3storage;
11

12
  /// The components of the matrix.
13
  Float32List get storage => _m3storage;
6✔
14

15
  /// Solve [A] * [x] = [b].
16
  static void solve2(Matrix3 A, Vector2 x, Vector2 b) {
1✔
17
    final a11 = A.entry(0, 0);
1✔
18
    final a12 = A.entry(0, 1);
1✔
19
    final a21 = A.entry(1, 0);
1✔
20
    final a22 = A.entry(1, 1);
1✔
21
    final bx = b.x - A.storage[6];
4✔
22
    final by = b.y - A.storage[7];
4✔
23
    var det = a11 * a22 - a12 * a21;
3✔
24

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

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

34
  /// Solve [A] * [x] = [b].
35
  static void solve(Matrix3 A, Vector3 x, Vector3 b) {
1✔
36
    final A0x = A.entry(0, 0);
1✔
37
    final A0y = A.entry(1, 0);
1✔
38
    final A0z = A.entry(2, 0);
1✔
39
    final A1x = A.entry(0, 1);
1✔
40
    final A1y = A.entry(1, 1);
1✔
41
    final A1z = A.entry(2, 1);
1✔
42
    final A2x = A.entry(0, 2);
1✔
43
    final A2y = A.entry(1, 2);
1✔
44
    final A2z = A.entry(2, 2);
1✔
45
    double rx, ry, rz;
46
    double det;
47

48
    // Column1 cross Column 2
49
    rx = A1y * A2z - A1z * A2y;
3✔
50
    ry = A1z * A2x - A1x * A2z;
3✔
51
    rz = A1x * A2y - A1y * A2x;
3✔
52

53
    // A.getColumn(0).dot(x)
54
    det = A0x * rx + A0y * ry + A0z * rz;
5✔
55
    if (det != 0.0) {
1✔
56
      det = 1.0 / det;
1✔
57
    }
58

59
    // b dot [Column1 cross Column 2]
60
    final x_ = det * (b.x * rx + b.y * ry + b.z * rz);
9✔
61

62
    // Column2 cross b
63
    rx = -(A2y * b.z - A2z * b.y);
6✔
64
    ry = -(A2z * b.x - A2x * b.z);
6✔
65
    rz = -(A2x * b.y - A2y * b.x);
6✔
66
    // Column0 dot -[Column2 cross b (Column3)]
67
    final y_ = det * (A0x * rx + A0y * ry + A0z * rz);
6✔
68

69
    // b cross Column 1
70
    rx = -(b.y * A1z - b.z * A1y);
6✔
71
    ry = -(b.z * A1x - b.x * A1z);
6✔
72
    rz = -(b.x * A1y - b.y * A1x);
6✔
73
    // Column0 dot -[b cross Column 1]
74
    final z_ = det * (A0x * rx + A0y * ry + A0z * rz);
6✔
75

76
    x
77
      ..x = x_
1✔
78
      ..y = y_
1✔
79
      ..z = z_;
1✔
80
  }
81

82
  /// Return index in storage for [row], [col] value.
83
  int index(int row, int col) => (col * 3) + row;
12✔
84

85
  /// Value at [row], [col].
86
  double entry(int row, int col) {
2✔
87
    assert((row >= 0) && (row < dimension));
8✔
88
    assert((col >= 0) && (col < dimension));
8✔
89

90
    return _m3storage[index(row, col)];
6✔
91
  }
92

93
  /// Set value at [row], [col] to be [v].
94
  void setEntry(int row, int col, double v) {
2✔
95
    assert((row >= 0) && (row < dimension));
8✔
96
    assert((col >= 0) && (col < dimension));
8✔
97

98
    _m3storage[index(row, col)] = v;
6✔
99
  }
100

101
  /// New matrix with specified values.
102
  factory Matrix3(
2✔
103
    double arg0,
104
    double arg1,
105
    double arg2,
106
    double arg3,
107
    double arg4,
108
    double arg5,
109
    double arg6,
110
    double arg7,
111
    double arg8,
112
  ) =>
113
      Matrix3.zero()
2✔
114
        ..setValues(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
2✔
115

116
  /// New matrix from [values].
117
  factory Matrix3.fromList(List<double> values) =>
1✔
118
      Matrix3.zero()..setValues(
2✔
119
        values[0],
1✔
120
        values[1],
1✔
121
        values[2],
1✔
122
        values[3],
1✔
123
        values[4],
1✔
124
        values[5],
1✔
125
        values[6],
1✔
126
        values[7],
1✔
127
        values[8],
1✔
128
      );
129

130
  /// Constructs a new [Matrix3] filled with zeros.
131
  Matrix3.zero() : _m3storage = Float32List(9);
12✔
132

133
  /// Identity matrix.
134
  factory Matrix3.identity() =>
1✔
135
      Matrix3.zero()
1✔
136
        .._m3storage[0] = 1.0
2✔
137
        .._m3storage[4] = 1.0
2✔
138
        .._m3storage[8] = 1.0;
2✔
139

140
  /// Copes values from [other].
141
  factory Matrix3.copy(Matrix3 other) => Matrix3.zero()..setFrom(other);
9✔
142

143
  /// Constructs a new mat3 from columns.
144
  factory Matrix3.columns(Vector3 arg0, Vector3 arg1, Vector3 arg2) =>
1✔
145
      Matrix3.zero()..setColumns(arg0, arg1, arg2);
2✔
146

147
  /// Outer product of [u] and [v].
148
  factory Matrix3.outer(Vector3 u, Vector3 v) => Matrix3.zero()..setOuter(u, v);
×
149

150
  /// Rotation of [radians] around X axis.
151
  factory Matrix3.rotationX(double radians) =>
4✔
152
      Matrix3.zero()..setRotationX(radians);
8✔
153

154
  /// Rotation of [radians] around Y axis.
155
  factory Matrix3.rotationY(double radians) =>
3✔
156
      Matrix3.zero()..setRotationY(radians);
6✔
157

158
  /// Rotation of [radians] around Z axis.
159
  factory Matrix3.rotationZ(double radians) =>
5✔
160
      Matrix3.zero()..setRotationZ(radians);
10✔
161

162
  /// Sets the matrix with specified values.
163
  void setValues(
2✔
164
    double arg0,
165
    double arg1,
166
    double arg2,
167
    double arg3,
168
    double arg4,
169
    double arg5,
170
    double arg6,
171
    double arg7,
172
    double arg8,
173
  ) {
174
    _m3storage[8] = arg8;
4✔
175
    _m3storage[7] = arg7;
4✔
176
    _m3storage[6] = arg6;
4✔
177
    _m3storage[5] = arg5;
4✔
178
    _m3storage[4] = arg4;
4✔
179
    _m3storage[3] = arg3;
4✔
180
    _m3storage[2] = arg2;
4✔
181
    _m3storage[1] = arg1;
4✔
182
    _m3storage[0] = arg0;
4✔
183
  }
184

185
  /// Sets the entire matrix to the column values.
186
  void setColumns(Vector3 arg0, Vector3 arg1, Vector3 arg2) {
1✔
187
    final arg0Storage = arg0._v3storage;
1✔
188
    final arg1Storage = arg1._v3storage;
1✔
189
    final arg2Storage = arg2._v3storage;
1✔
190
    _m3storage[0] = arg0Storage[0];
3✔
191
    _m3storage[1] = arg0Storage[1];
3✔
192
    _m3storage[2] = arg0Storage[2];
3✔
193
    _m3storage[3] = arg1Storage[0];
3✔
194
    _m3storage[4] = arg1Storage[1];
3✔
195
    _m3storage[5] = arg1Storage[2];
3✔
196
    _m3storage[6] = arg2Storage[0];
3✔
197
    _m3storage[7] = arg2Storage[1];
3✔
198
    _m3storage[8] = arg2Storage[2];
3✔
199
  }
200

201
  /// Sets the entire matrix to the matrix in [arg].
202
  void setFrom(Matrix3 arg) {
3✔
203
    final argStorage = arg._m3storage;
3✔
204
    _m3storage[8] = argStorage[8];
9✔
205
    _m3storage[7] = argStorage[7];
9✔
206
    _m3storage[6] = argStorage[6];
9✔
207
    _m3storage[5] = argStorage[5];
9✔
208
    _m3storage[4] = argStorage[4];
9✔
209
    _m3storage[3] = argStorage[3];
9✔
210
    _m3storage[2] = argStorage[2];
9✔
211
    _m3storage[1] = argStorage[1];
9✔
212
    _m3storage[0] = argStorage[0];
9✔
213
  }
214

215
  /// Set this to the outer product of [u] and [v].
216
  void setOuter(Vector3 u, Vector3 v) {
×
217
    final uStorage = u._v3storage;
×
218
    final vStorage = v._v3storage;
×
219
    _m3storage[0] = uStorage[0] * vStorage[0];
×
220
    _m3storage[1] = uStorage[0] * vStorage[1];
×
221
    _m3storage[2] = uStorage[0] * vStorage[2];
×
222
    _m3storage[3] = uStorage[1] * vStorage[0];
×
223
    _m3storage[4] = uStorage[1] * vStorage[1];
×
224
    _m3storage[5] = uStorage[1] * vStorage[2];
×
225
    _m3storage[6] = uStorage[2] * vStorage[0];
×
226
    _m3storage[7] = uStorage[2] * vStorage[1];
×
227
    _m3storage[8] = uStorage[2] * vStorage[2];
×
228
  }
229

230
  /// Set the diagonal of the matrix.
231
  void splatDiagonal(double arg) {
×
232
    _m3storage[0] = arg;
×
233
    _m3storage[4] = arg;
×
234
    _m3storage[8] = arg;
×
235
  }
236

237
  /// Set the diagonal of the matrix.
238
  void setDiagonal(Vector3 arg) {
×
239
    _m3storage[0] = arg.storage[0];
×
240
    _m3storage[4] = arg.storage[1];
×
241
    _m3storage[8] = arg.storage[2];
×
242
  }
243

244
  /// Sets the upper 2x2 of the matrix to be [arg].
245
  void setUpper2x2(Matrix2 arg) {
×
246
    final argStorage = arg._m2storage;
×
247
    _m3storage[0] = argStorage[0];
×
248
    _m3storage[1] = argStorage[1];
×
249
    _m3storage[3] = argStorage[2];
×
250
    _m3storage[4] = argStorage[3];
×
251
  }
252

253
  /// Returns a printable string
254
  @override
2✔
255
  String toString() => '[0] ${getRow(0)}\n[1] ${getRow(1)}\n[2] ${getRow(2)}\n';
8✔
256

257
  /// Dimension of the matrix.
258
  int get dimension => 3;
2✔
259

260
  /// Access the element of the matrix at the index [i].
261
  double operator [](int i) => _m3storage[i];
×
262

263
  /// Set the element of the matrix at the index [i].
264
  void operator []=(int i, double v) {
1✔
265
    _m3storage[i] = v;
2✔
266
  }
267

268
  /// Check if two matrices are the same.
269
  @override
1✔
270
  bool operator ==(Object other) =>
271
      (other is Matrix3) &&
1✔
272
      (_m3storage[0] == other._m3storage[0]) &&
5✔
273
      (_m3storage[1] == other._m3storage[1]) &&
5✔
274
      (_m3storage[2] == other._m3storage[2]) &&
5✔
275
      (_m3storage[3] == other._m3storage[3]) &&
5✔
276
      (_m3storage[4] == other._m3storage[4]) &&
5✔
277
      (_m3storage[5] == other._m3storage[5]) &&
5✔
278
      (_m3storage[6] == other._m3storage[6]) &&
5✔
279
      (_m3storage[7] == other._m3storage[7]) &&
5✔
280
      (_m3storage[8] == other._m3storage[8]);
5✔
281

282
  @override
1✔
283
  int get hashCode => Object.hashAll(_m3storage);
2✔
284

285
  /// Returns row 0
286
  Vector3 get row0 => getRow(0);
×
287

288
  /// Returns row 1
289
  Vector3 get row1 => getRow(1);
×
290

291
  /// Returns row 2
292
  Vector3 get row2 => getRow(2);
×
293

294
  /// Sets row 0 to [arg]
295
  set row0(Vector3 arg) => setRow(0, arg);
×
296

297
  /// Sets row 1 to [arg]
298
  set row1(Vector3 arg) => setRow(1, arg);
×
299

300
  /// Sets row 2 to [arg]
301
  set row2(Vector3 arg) => setRow(2, arg);
×
302

303
  /// Assigns the [row] of to [arg].
304
  void setRow(int row, Vector3 arg) {
×
305
    final argStorage = arg._v3storage;
×
306
    _m3storage[index(row, 0)] = argStorage[0];
×
307
    _m3storage[index(row, 1)] = argStorage[1];
×
308
    _m3storage[index(row, 2)] = argStorage[2];
×
309
  }
310

311
  /// Gets the [row] of the matrix
312
  Vector3 getRow(int row) {
2✔
313
    final r = Vector3.zero();
2✔
314
    final rStorage = r._v3storage;
2✔
315
    rStorage[0] = _m3storage[index(row, 0)];
8✔
316
    rStorage[1] = _m3storage[index(row, 1)];
8✔
317
    rStorage[2] = _m3storage[index(row, 2)];
8✔
318
    return r;
319
  }
320

321
  /// Assigns the [column] of the matrix [arg]
322
  void setColumn(int column, Vector3 arg) {
×
323
    final argStorage = arg._v3storage;
×
324
    final entry = column * 3;
×
325
    _m3storage[entry + 2] = argStorage[2];
×
326
    _m3storage[entry + 1] = argStorage[1];
×
327
    _m3storage[entry + 0] = argStorage[0];
×
328
  }
329

330
  /// Gets the [column] of the matrix
331
  Vector3 getColumn(int column) {
×
332
    final r = Vector3.zero();
×
333
    final rStorage = r._v3storage;
×
334
    final entry = column * 3;
×
335
    rStorage[2] = _m3storage[entry + 2];
×
336
    rStorage[1] = _m3storage[entry + 1];
×
337
    rStorage[0] = _m3storage[entry + 0];
×
338
    return r;
339
  }
340

341
  /// Clone of this.
342
  Matrix3 clone() => Matrix3.copy(this);
6✔
343

344
  /// Copy this into [arg].
345
  Matrix3 copyInto(Matrix3 arg) {
×
346
    final argStorage = arg._m3storage;
×
347
    argStorage[0] = _m3storage[0];
×
348
    argStorage[1] = _m3storage[1];
×
349
    argStorage[2] = _m3storage[2];
×
350
    argStorage[3] = _m3storage[3];
×
351
    argStorage[4] = _m3storage[4];
×
352
    argStorage[5] = _m3storage[5];
×
353
    argStorage[6] = _m3storage[6];
×
354
    argStorage[7] = _m3storage[7];
×
355
    argStorage[8] = _m3storage[8];
×
356
    return arg;
357
  }
358

359
  /// Returns a new vector or matrix by multiplying this with [arg].
360
  @pragma('wasm:prefer-inline')
2✔
361
  @pragma('vm:prefer-inline')
362
  @pragma('dart2js:prefer-inline')
363
  dynamic operator *(dynamic arg) {
364
    final Object result;
365
    if (arg is double) {
2✔
366
      result = scaled(arg);
×
367
    } else if (arg is Vector3) {
2✔
368
      result = transformed(arg);
1✔
369
    } else if (arg is Matrix3) {
2✔
370
      result = multiplied(arg);
2✔
371
    } else {
372
      throw ArgumentError(arg);
×
373
    }
374
    return result;
375
  }
376

377
  /// Returns new matrix after component wise this + [arg]
378
  Matrix3 operator +(Matrix3 arg) => clone()..add(arg);
×
379

380
  /// Returns new matrix after component wise this - [arg]
381
  Matrix3 operator -(Matrix3 arg) => clone()..sub(arg);
6✔
382

383
  /// Returns new matrix -this
384
  Matrix3 operator -() => clone()..negate();
×
385

386
  /// Zeros this.
387
  void setZero() {
×
388
    _m3storage[0] = 0.0;
×
389
    _m3storage[1] = 0.0;
×
390
    _m3storage[2] = 0.0;
×
391
    _m3storage[3] = 0.0;
×
392
    _m3storage[4] = 0.0;
×
393
    _m3storage[5] = 0.0;
×
394
    _m3storage[6] = 0.0;
×
395
    _m3storage[7] = 0.0;
×
396
    _m3storage[8] = 0.0;
×
397
  }
398

399
  /// Makes this into the identity matrix.
UNCOV
400
  void setIdentity() {
×
UNCOV
401
    _m3storage[0] = 1.0;
×
UNCOV
402
    _m3storage[1] = 0.0;
×
UNCOV
403
    _m3storage[2] = 0.0;
×
UNCOV
404
    _m3storage[3] = 0.0;
×
UNCOV
405
    _m3storage[4] = 1.0;
×
UNCOV
406
    _m3storage[5] = 0.0;
×
UNCOV
407
    _m3storage[6] = 0.0;
×
UNCOV
408
    _m3storage[7] = 0.0;
×
UNCOV
409
    _m3storage[8] = 1.0;
×
410
  }
411

412
  /// Returns the tranpose of this.
413
  Matrix3 transposed() => clone()..transpose();
3✔
414

415
  /// Transpose this.
416
  void transpose() {
1✔
417
    double temp;
418
    temp = _m3storage[3];
2✔
419
    _m3storage[3] = _m3storage[1];
4✔
420
    _m3storage[1] = temp;
2✔
421
    temp = _m3storage[6];
2✔
422
    _m3storage[6] = _m3storage[2];
4✔
423
    _m3storage[2] = temp;
2✔
424
    temp = _m3storage[7];
2✔
425
    _m3storage[7] = _m3storage[5];
4✔
426
    _m3storage[5] = temp;
2✔
427
  }
428

429
  /// Returns the component wise absolute value of this.
430
  Matrix3 absolute() {
×
431
    final r = Matrix3.zero();
×
432
    final rStorage = r._m3storage;
×
433
    rStorage[0] = _m3storage[0].abs();
×
434
    rStorage[1] = _m3storage[1].abs();
×
435
    rStorage[2] = _m3storage[2].abs();
×
436
    rStorage[3] = _m3storage[3].abs();
×
437
    rStorage[4] = _m3storage[4].abs();
×
438
    rStorage[5] = _m3storage[5].abs();
×
439
    rStorage[6] = _m3storage[6].abs();
×
440
    rStorage[7] = _m3storage[7].abs();
×
441
    rStorage[8] = _m3storage[8].abs();
×
442
    return r;
443
  }
444

445
  /// Returns the determinant of this matrix.
446
  double determinant() {
2✔
447
    final x =
448
        _m3storage[0] *
6✔
449
        ((_m3storage[4] * _m3storage[8]) - (_m3storage[5] * _m3storage[7]));
22✔
450
    final y =
451
        _m3storage[1] *
6✔
452
        ((_m3storage[3] * _m3storage[8]) - (_m3storage[5] * _m3storage[6]));
22✔
453
    final z =
454
        _m3storage[2] *
6✔
455
        ((_m3storage[3] * _m3storage[7]) - (_m3storage[4] * _m3storage[6]));
22✔
456
    return x - y + z;
4✔
457
  }
458

459
  /// Returns the dot product of row [i] and [v].
460
  double dotRow(int i, Vector3 v) {
1✔
461
    final vStorage = v._v3storage;
1✔
462
    return _m3storage[i] * vStorage[0] +
5✔
463
        _m3storage[3 + i] * vStorage[1] +
6✔
464
        _m3storage[6 + i] * vStorage[2];
5✔
465
  }
466

467
  /// Returns the dot product of column [j] and [v].
468
  double dotColumn(int j, Vector3 v) {
1✔
469
    final vStorage = v._v3storage;
1✔
470
    return _m3storage[j * 3] * vStorage[0] +
6✔
471
        _m3storage[j * 3 + 1] * vStorage[1] +
7✔
472
        _m3storage[j * 3 + 2] * vStorage[2];
6✔
473
  }
474

475
  /// Returns the trace of the matrix. The trace of a matrix is the sum of
476
  /// the diagonal entries.
477
  double trace() {
2✔
478
    var t = 0.0;
479
    t += _m3storage[0];
6✔
480
    t += _m3storage[4];
6✔
481
    t += _m3storage[8];
6✔
482
    return t;
483
  }
484

485
  /// Returns infinity norm of the matrix. Used for numerical analysis.
486
  double infinityNorm() {
2✔
487
    var norm = 0.0;
488
    {
489
      var row_norm = 0.0;
490
      row_norm += _m3storage[0].abs();
8✔
491
      row_norm += _m3storage[1].abs();
8✔
492
      row_norm += _m3storage[2].abs();
8✔
493
      norm = row_norm > norm ? row_norm : norm;
2✔
494
    }
495
    {
496
      var row_norm = 0.0;
497
      row_norm += _m3storage[3].abs();
8✔
498
      row_norm += _m3storage[4].abs();
8✔
499
      row_norm += _m3storage[5].abs();
8✔
500
      norm = row_norm > norm ? row_norm : norm;
2✔
501
    }
502
    {
503
      var row_norm = 0.0;
504
      row_norm += _m3storage[6].abs();
8✔
505
      row_norm += _m3storage[7].abs();
8✔
506
      row_norm += _m3storage[8].abs();
8✔
507
      norm = row_norm > norm ? row_norm : norm;
2✔
508
    }
509
    return norm;
510
  }
511

512
  /// Returns relative error between this and [correct]
513
  double relativeError(Matrix3 correct) {
2✔
514
    final diff = correct - this;
2✔
515
    final correct_norm = correct.infinityNorm();
2✔
516
    final diff_norm = diff.infinityNorm();
2✔
517
    return diff_norm / correct_norm;
2✔
518
  }
519

520
  /// Returns absolute error between this and [correct]
521
  double absoluteError(Matrix3 correct) {
×
522
    final this_norm = infinityNorm();
×
523
    final correct_norm = correct.infinityNorm();
×
524
    final diff_norm = (this_norm - correct_norm).abs();
×
525
    return diff_norm;
526
  }
527

528
  /// Invert the matrix. Returns the determinant.
529
  double invert() => copyInverse(this);
2✔
530

531
  /// Set this matrix to be the inverse of [arg]
532
  double copyInverse(Matrix3 arg) {
2✔
533
    final det = arg.determinant();
2✔
534
    if (det == 0.0) {
2✔
535
      setFrom(arg);
×
536
      return 0.0;
537
    }
538
    final invDet = 1.0 / det;
2✔
539
    final argStorage = arg._m3storage;
2✔
540
    final ix =
541
        invDet *
2✔
542
        (argStorage[4] * argStorage[8] - argStorage[5] * argStorage[7]);
14✔
543
    final iy =
544
        invDet *
2✔
545
        (argStorage[2] * argStorage[7] - argStorage[1] * argStorage[8]);
14✔
546
    final iz =
547
        invDet *
2✔
548
        (argStorage[1] * argStorage[5] - argStorage[2] * argStorage[4]);
14✔
549
    final jx =
550
        invDet *
2✔
551
        (argStorage[5] * argStorage[6] - argStorage[3] * argStorage[8]);
14✔
552
    final jy =
553
        invDet *
2✔
554
        (argStorage[0] * argStorage[8] - argStorage[2] * argStorage[6]);
14✔
555
    final jz =
556
        invDet *
2✔
557
        (argStorage[2] * argStorage[3] - argStorage[0] * argStorage[5]);
14✔
558
    final kx =
559
        invDet *
2✔
560
        (argStorage[3] * argStorage[7] - argStorage[4] * argStorage[6]);
14✔
561
    final ky =
562
        invDet *
2✔
563
        (argStorage[1] * argStorage[6] - argStorage[0] * argStorage[7]);
14✔
564
    final kz =
565
        invDet *
2✔
566
        (argStorage[0] * argStorage[4] - argStorage[1] * argStorage[3]);
14✔
567
    _m3storage[0] = ix;
4✔
568
    _m3storage[1] = iy;
4✔
569
    _m3storage[2] = iz;
4✔
570
    _m3storage[3] = jx;
4✔
571
    _m3storage[4] = jy;
4✔
572
    _m3storage[5] = jz;
4✔
573
    _m3storage[6] = kx;
4✔
574
    _m3storage[7] = ky;
4✔
575
    _m3storage[8] = kz;
4✔
576
    return det;
577
  }
578

579
  /// Set this matrix to be the normal matrix of [arg].
580
  void copyNormalMatrix(Matrix4 arg) {
×
581
    copyInverse(arg.getRotation());
×
582
    transpose();
×
583
  }
584

585
  /// Turns the matrix into a rotation of [radians] around X
586
  void setRotationX(double radians) {
4✔
587
    final c = math.cos(radians);
4✔
588
    final s = math.sin(radians);
4✔
589
    _m3storage[0] = 1.0;
8✔
590
    _m3storage[1] = 0.0;
8✔
591
    _m3storage[2] = 0.0;
8✔
592
    _m3storage[3] = 0.0;
8✔
593
    _m3storage[4] = c;
8✔
594
    _m3storage[5] = s;
8✔
595
    _m3storage[6] = 0.0;
8✔
596
    _m3storage[7] = -s;
12✔
597
    _m3storage[8] = c;
8✔
598
  }
599

600
  /// Turns the matrix into a rotation of [radians] around Y
601
  void setRotationY(double radians) {
3✔
602
    final c = math.cos(radians);
3✔
603
    final s = math.sin(radians);
3✔
604
    _m3storage[0] = c;
6✔
605
    _m3storage[1] = 0.0;
6✔
606
    _m3storage[2] = -s;
9✔
607
    _m3storage[3] = 0.0;
6✔
608
    _m3storage[4] = 1.0;
6✔
609
    _m3storage[5] = 0.0;
6✔
610
    _m3storage[6] = s;
6✔
611
    _m3storage[7] = 0.0;
6✔
612
    _m3storage[8] = c;
6✔
613
  }
614

615
  /// Turns the matrix into a rotation of [radians] around Z
616
  void setRotationZ(double radians) {
5✔
617
    final c = math.cos(radians);
5✔
618
    final s = math.sin(radians);
5✔
619
    _m3storage[0] = c;
10✔
620
    _m3storage[1] = s;
10✔
621
    _m3storage[2] = 0.0;
10✔
622
    _m3storage[3] = -s;
15✔
623
    _m3storage[4] = c;
10✔
624
    _m3storage[5] = 0.0;
10✔
625
    _m3storage[6] = 0.0;
10✔
626
    _m3storage[7] = 0.0;
10✔
627
    _m3storage[8] = 1.0;
10✔
628
  }
629

630
  /// Converts into Adjugate matrix and scales by [scale]
631
  void scaleAdjoint(double scale) {
1✔
632
    final m00 = _m3storage[0];
2✔
633
    final m01 = _m3storage[3];
2✔
634
    final m02 = _m3storage[6];
2✔
635
    final m10 = _m3storage[1];
2✔
636
    final m11 = _m3storage[4];
2✔
637
    final m12 = _m3storage[7];
2✔
638
    final m20 = _m3storage[2];
2✔
639
    final m21 = _m3storage[5];
2✔
640
    final m22 = _m3storage[8];
2✔
641
    _m3storage[0] = (m11 * m22 - m12 * m21) * scale;
6✔
642
    _m3storage[1] = (m12 * m20 - m10 * m22) * scale;
6✔
643
    _m3storage[2] = (m10 * m21 - m11 * m20) * scale;
6✔
644
    _m3storage[3] = (m02 * m21 - m01 * m22) * scale;
6✔
645
    _m3storage[4] = (m00 * m22 - m02 * m20) * scale;
6✔
646
    _m3storage[5] = (m01 * m20 - m00 * m21) * scale;
6✔
647
    _m3storage[6] = (m01 * m12 - m02 * m11) * scale;
6✔
648
    _m3storage[7] = (m02 * m10 - m00 * m12) * scale;
6✔
649
    _m3storage[8] = (m00 * m11 - m01 * m10) * scale;
6✔
650
  }
651

652
  /// Rotates [arg] by the absolute rotation of this
653
  /// Returns [arg].
654
  /// Primarily used by AABB transformation code.
655
  Vector3 absoluteRotate(Vector3 arg) {
×
656
    final m00 = _m3storage[0].abs();
×
657
    final m01 = _m3storage[3].abs();
×
658
    final m02 = _m3storage[6].abs();
×
659
    final m10 = _m3storage[1].abs();
×
660
    final m11 = _m3storage[4].abs();
×
661
    final m12 = _m3storage[7].abs();
×
662
    final m20 = _m3storage[2].abs();
×
663
    final m21 = _m3storage[5].abs();
×
664
    final m22 = _m3storage[8].abs();
×
665
    final argStorage = arg._v3storage;
×
666
    final x = argStorage[0];
×
667
    final y = argStorage[1];
×
668
    final z = argStorage[2];
×
669
    argStorage[0] = x * m00 + y * m01 + z * m02;
×
670
    argStorage[1] = x * m10 + y * m11 + z * m12;
×
671
    argStorage[2] = x * m20 + y * m21 + z * m22;
×
672
    return arg;
673
  }
674

675
  /// Rotates [arg] by the absolute rotation of this
676
  /// Returns [arg].
677
  /// Primarily used by AABB transformation code.
678
  Vector2 absoluteRotate2(Vector2 arg) {
2✔
679
    final m00 = _m3storage[0].abs();
6✔
680
    final m01 = _m3storage[3].abs();
6✔
681
    final m10 = _m3storage[1].abs();
6✔
682
    final m11 = _m3storage[4].abs();
6✔
683
    final argStorage = arg._v2storage;
2✔
684
    final x = argStorage[0];
2✔
685
    final y = argStorage[1];
2✔
686
    argStorage[0] = x * m00 + y * m01;
8✔
687
    argStorage[1] = x * m10 + y * m11;
8✔
688
    return arg;
689
  }
690

691
  /// Transforms [arg] with this.
692
  Vector2 transform2(Vector2 arg) {
3✔
693
    final argStorage = arg._v2storage;
3✔
694
    final x_ =
695
        (_m3storage[0] * argStorage[0]) +
15✔
696
        (_m3storage[3] * argStorage[1]) +
15✔
697
        _m3storage[6];
6✔
698
    final y_ =
699
        (_m3storage[1] * argStorage[0]) +
15✔
700
        (_m3storage[4] * argStorage[1]) +
15✔
701
        _m3storage[7];
6✔
702
    argStorage[0] = x_;
3✔
703
    argStorage[1] = y_;
3✔
704
    return arg;
705
  }
706

707
  /// Scales this by [scale].
708
  void scale(double scale) {
1✔
709
    _m3storage[0] = _m3storage[0] * scale;
5✔
710
    _m3storage[1] = _m3storage[1] * scale;
5✔
711
    _m3storage[2] = _m3storage[2] * scale;
5✔
712
    _m3storage[3] = _m3storage[3] * scale;
5✔
713
    _m3storage[4] = _m3storage[4] * scale;
5✔
714
    _m3storage[5] = _m3storage[5] * scale;
5✔
715
    _m3storage[6] = _m3storage[6] * scale;
5✔
716
    _m3storage[7] = _m3storage[7] * scale;
5✔
717
    _m3storage[8] = _m3storage[8] * scale;
5✔
718
  }
719

720
  /// Create a copy of this and scale it by [scale].
721
  Matrix3 scaled(double scale) => clone()..scale(scale);
3✔
722

723
  /// Add [o] to this.
724
  void add(Matrix3 o) {
×
725
    final oStorage = o._m3storage;
×
726
    _m3storage[0] = _m3storage[0] + oStorage[0];
×
727
    _m3storage[1] = _m3storage[1] + oStorage[1];
×
728
    _m3storage[2] = _m3storage[2] + oStorage[2];
×
729
    _m3storage[3] = _m3storage[3] + oStorage[3];
×
730
    _m3storage[4] = _m3storage[4] + oStorage[4];
×
731
    _m3storage[5] = _m3storage[5] + oStorage[5];
×
732
    _m3storage[6] = _m3storage[6] + oStorage[6];
×
733
    _m3storage[7] = _m3storage[7] + oStorage[7];
×
734
    _m3storage[8] = _m3storage[8] + oStorage[8];
×
735
  }
736

737
  /// Subtract [o] from this.
738
  void sub(Matrix3 o) {
2✔
739
    final oStorage = o._m3storage;
2✔
740
    _m3storage[0] = _m3storage[0] - oStorage[0];
12✔
741
    _m3storage[1] = _m3storage[1] - oStorage[1];
12✔
742
    _m3storage[2] = _m3storage[2] - oStorage[2];
12✔
743
    _m3storage[3] = _m3storage[3] - oStorage[3];
12✔
744
    _m3storage[4] = _m3storage[4] - oStorage[4];
12✔
745
    _m3storage[5] = _m3storage[5] - oStorage[5];
12✔
746
    _m3storage[6] = _m3storage[6] - oStorage[6];
12✔
747
    _m3storage[7] = _m3storage[7] - oStorage[7];
12✔
748
    _m3storage[8] = _m3storage[8] - oStorage[8];
12✔
749
  }
750

751
  /// Negate this.
752
  void negate() {
×
753
    _m3storage[0] = -_m3storage[0];
×
754
    _m3storage[1] = -_m3storage[1];
×
755
    _m3storage[2] = -_m3storage[2];
×
756
    _m3storage[3] = -_m3storage[3];
×
757
    _m3storage[4] = -_m3storage[4];
×
758
    _m3storage[5] = -_m3storage[5];
×
759
    _m3storage[6] = -_m3storage[6];
×
760
    _m3storage[7] = -_m3storage[7];
×
761
    _m3storage[8] = -_m3storage[8];
×
762
  }
763

764
  /// Multiply this by [arg].
765
  void multiply(Matrix3 arg) {
3✔
766
    final m00 = _m3storage[0];
6✔
767
    final m01 = _m3storage[3];
6✔
768
    final m02 = _m3storage[6];
6✔
769
    final m10 = _m3storage[1];
6✔
770
    final m11 = _m3storage[4];
6✔
771
    final m12 = _m3storage[7];
6✔
772
    final m20 = _m3storage[2];
6✔
773
    final m21 = _m3storage[5];
6✔
774
    final m22 = _m3storage[8];
6✔
775
    final argStorage = arg._m3storage;
3✔
776
    final n00 = argStorage[0];
3✔
777
    final n01 = argStorage[3];
3✔
778
    final n02 = argStorage[6];
3✔
779
    final n10 = argStorage[1];
3✔
780
    final n11 = argStorage[4];
3✔
781
    final n12 = argStorage[7];
3✔
782
    final n20 = argStorage[2];
3✔
783
    final n21 = argStorage[5];
3✔
784
    final n22 = argStorage[8];
3✔
785
    _m3storage[0] = (m00 * n00) + (m01 * n10) + (m02 * n20);
21✔
786
    _m3storage[3] = (m00 * n01) + (m01 * n11) + (m02 * n21);
21✔
787
    _m3storage[6] = (m00 * n02) + (m01 * n12) + (m02 * n22);
21✔
788
    _m3storage[1] = (m10 * n00) + (m11 * n10) + (m12 * n20);
21✔
789
    _m3storage[4] = (m10 * n01) + (m11 * n11) + (m12 * n21);
21✔
790
    _m3storage[7] = (m10 * n02) + (m11 * n12) + (m12 * n22);
21✔
791
    _m3storage[2] = (m20 * n00) + (m21 * n10) + (m22 * n20);
21✔
792
    _m3storage[5] = (m20 * n01) + (m21 * n11) + (m22 * n21);
21✔
793
    _m3storage[8] = (m20 * n02) + (m21 * n12) + (m22 * n22);
21✔
794
  }
795

796
  /// Create a copy of this and multiply it by [arg].
797
  Matrix3 multiplied(Matrix3 arg) => clone()..multiply(arg);
6✔
798

799
  void transposeMultiply(Matrix3 arg) {
1✔
800
    final m00 = _m3storage[0];
2✔
801
    final m01 = _m3storage[1];
2✔
802
    final m02 = _m3storage[2];
2✔
803
    final m10 = _m3storage[3];
2✔
804
    final m11 = _m3storage[4];
2✔
805
    final m12 = _m3storage[5];
2✔
806
    final m20 = _m3storage[6];
2✔
807
    final m21 = _m3storage[7];
2✔
808
    final m22 = _m3storage[8];
2✔
809
    final argStorage = arg._m3storage;
1✔
810
    _m3storage[0] =
2✔
811
        (m00 * argStorage[0]) + (m01 * argStorage[1]) + (m02 * argStorage[2]);
8✔
812
    _m3storage[3] =
2✔
813
        (m00 * argStorage[3]) + (m01 * argStorage[4]) + (m02 * argStorage[5]);
8✔
814
    _m3storage[6] =
2✔
815
        (m00 * argStorage[6]) + (m01 * argStorage[7]) + (m02 * argStorage[8]);
8✔
816
    _m3storage[1] =
2✔
817
        (m10 * argStorage[0]) + (m11 * argStorage[1]) + (m12 * argStorage[2]);
8✔
818
    _m3storage[4] =
2✔
819
        (m10 * argStorage[3]) + (m11 * argStorage[4]) + (m12 * argStorage[5]);
8✔
820
    _m3storage[7] =
2✔
821
        (m10 * argStorage[6]) + (m11 * argStorage[7]) + (m12 * argStorage[8]);
8✔
822
    _m3storage[2] =
2✔
823
        (m20 * argStorage[0]) + (m21 * argStorage[1]) + (m22 * argStorage[2]);
8✔
824
    _m3storage[5] =
2✔
825
        (m20 * argStorage[3]) + (m21 * argStorage[4]) + (m22 * argStorage[5]);
8✔
826
    _m3storage[8] =
2✔
827
        (m20 * argStorage[6]) + (m21 * argStorage[7]) + (m22 * argStorage[8]);
8✔
828
  }
829

830
  void multiplyTranspose(Matrix3 arg) {
1✔
831
    final m00 = _m3storage[0];
2✔
832
    final m01 = _m3storage[3];
2✔
833
    final m02 = _m3storage[6];
2✔
834
    final m10 = _m3storage[1];
2✔
835
    final m11 = _m3storage[4];
2✔
836
    final m12 = _m3storage[7];
2✔
837
    final m20 = _m3storage[2];
2✔
838
    final m21 = _m3storage[5];
2✔
839
    final m22 = _m3storage[8];
2✔
840
    final argStorage = arg._m3storage;
1✔
841
    _m3storage[0] =
2✔
842
        (m00 * argStorage[0]) + (m01 * argStorage[3]) + (m02 * argStorage[6]);
8✔
843
    _m3storage[3] =
2✔
844
        (m00 * argStorage[1]) + (m01 * argStorage[4]) + (m02 * argStorage[7]);
8✔
845
    _m3storage[6] =
2✔
846
        (m00 * argStorage[2]) + (m01 * argStorage[5]) + (m02 * argStorage[8]);
8✔
847
    _m3storage[1] =
2✔
848
        (m10 * argStorage[0]) + (m11 * argStorage[3]) + (m12 * argStorage[6]);
8✔
849
    _m3storage[4] =
2✔
850
        (m10 * argStorage[1]) + (m11 * argStorage[4]) + (m12 * argStorage[7]);
8✔
851
    _m3storage[7] =
2✔
852
        (m10 * argStorage[2]) + (m11 * argStorage[5]) + (m12 * argStorage[8]);
8✔
853
    _m3storage[2] =
2✔
854
        (m20 * argStorage[0]) + (m21 * argStorage[3]) + (m22 * argStorage[6]);
8✔
855
    _m3storage[5] =
2✔
856
        (m20 * argStorage[1]) + (m21 * argStorage[4]) + (m22 * argStorage[7]);
8✔
857
    _m3storage[8] =
2✔
858
        (m20 * argStorage[2]) + (m21 * argStorage[5]) + (m22 * argStorage[8]);
8✔
859
  }
860

861
  /// Transform [arg] of type [Vector3] using the transformation defined by
862
  /// this.
863
  Vector3 transform(Vector3 arg) {
3✔
864
    final argStorage = arg._v3storage;
3✔
865
    final x_ =
866
        (_m3storage[0] * argStorage[0]) +
15✔
867
        (_m3storage[3] * argStorage[1]) +
15✔
868
        (_m3storage[6] * argStorage[2]);
12✔
869
    final y_ =
870
        (_m3storage[1] * argStorage[0]) +
15✔
871
        (_m3storage[4] * argStorage[1]) +
15✔
872
        (_m3storage[7] * argStorage[2]);
12✔
873
    final z_ =
874
        (_m3storage[2] * argStorage[0]) +
15✔
875
        (_m3storage[5] * argStorage[1]) +
15✔
876
        (_m3storage[8] * argStorage[2]);
12✔
877
    arg
878
      ..x = x_
3✔
879
      ..y = y_
3✔
880
      ..z = z_;
3✔
881
    return arg;
882
  }
883

884
  /// Transform a copy of [arg] of type [Vector3] using the transformation
885
  /// defined by this. If a [out] parameter is supplied, the copy is stored in
886
  /// [out].
887
  Vector3 transformed(Vector3 arg, [Vector3? out]) {
2✔
888
    if (out == null) {
889
      out = Vector3.copy(arg);
2✔
890
    } else {
891
      out.setFrom(arg);
×
892
    }
893
    return transform(out);
2✔
894
  }
895

896
  /// Copies this into [array] starting at [offset].
897
  void copyIntoArray(List<num> array, [int offset = 0]) {
×
898
    final i = offset;
899
    array[i + 8] = _m3storage[8];
×
900
    array[i + 7] = _m3storage[7];
×
901
    array[i + 6] = _m3storage[6];
×
902
    array[i + 5] = _m3storage[5];
×
903
    array[i + 4] = _m3storage[4];
×
904
    array[i + 3] = _m3storage[3];
×
905
    array[i + 2] = _m3storage[2];
×
906
    array[i + 1] = _m3storage[1];
×
907
    array[i + 0] = _m3storage[0];
×
908
  }
909

910
  /// Copies elements from [array] into this starting at [offset].
911
  void copyFromArray(List<double> array, [int offset = 0]) {
×
912
    final i = offset;
913
    _m3storage[8] = array[i + 8];
×
914
    _m3storage[7] = array[i + 7];
×
915
    _m3storage[6] = array[i + 6];
×
916
    _m3storage[5] = array[i + 5];
×
917
    _m3storage[4] = array[i + 4];
×
918
    _m3storage[3] = array[i + 3];
×
919
    _m3storage[2] = array[i + 2];
×
920
    _m3storage[1] = array[i + 1];
×
921
    _m3storage[0] = array[i + 0];
×
922
  }
923

924
  /// Multiply this to each set of xyz values in [array] starting at [offset].
925
  List<double> applyToVector3Array(List<double> array, [int offset = 0]) {
×
926
    for (var i = 0, j = offset; i < array.length; i += 3, j += 3) {
×
927
      final v = Vector3.array(array, j)..applyMatrix3(this);
×
928
      array[j] = v.storage[0];
×
929
      array[j + 1] = v.storage[1];
×
930
      array[j + 2] = v.storage[2];
×
931
    }
932

933
    return array;
934
  }
935

936
  Vector3 get right {
×
937
    final x = _m3storage[0];
×
938
    final y = _m3storage[1];
×
939
    final z = _m3storage[2];
×
940
    return Vector3(x, y, z);
×
941
  }
942

943
  Vector3 get up {
×
944
    final x = _m3storage[3];
×
945
    final y = _m3storage[4];
×
946
    final z = _m3storage[5];
×
947
    return Vector3(x, y, z);
×
948
  }
949

950
  Vector3 get forward {
×
951
    final x = _m3storage[6];
×
952
    final y = _m3storage[7];
×
953
    final z = _m3storage[8];
×
954
    return Vector3(x, y, z);
×
955
  }
956

957
  /// Is this the identity matrix?
958
  bool isIdentity() =>
1✔
959
      _m3storage[0] ==
3✔
960
          1.0 // col 1
961
          &&
962
      _m3storage[1] == 0.0 &&
3✔
963
      _m3storage[2] == 0.0 &&
3✔
964
      _m3storage[3] ==
3✔
965
          0.0 // col 2
966
          &&
967
      _m3storage[4] == 1.0 &&
3✔
968
      _m3storage[5] == 0.0 &&
3✔
969
      _m3storage[6] ==
3✔
970
          0.0 // col 3
971
          &&
972
      _m3storage[7] == 0.0 &&
3✔
973
      _m3storage[8] == 1.0;
3✔
974

975
  /// Is this the zero matrix?
976
  bool isZero() =>
1✔
977
      _m3storage[0] ==
3✔
978
          0.0 // col 1
979
          &&
980
      _m3storage[1] == 0.0 &&
3✔
981
      _m3storage[2] == 0.0 &&
3✔
982
      _m3storage[3] ==
3✔
983
          0.0 // col 2
984
          &&
985
      _m3storage[4] == 0.0 &&
3✔
986
      _m3storage[5] == 0.0 &&
3✔
987
      _m3storage[6] ==
3✔
988
          0.0 // col 3
989
          &&
990
      _m3storage[7] == 0.0 &&
3✔
991
      _m3storage[8] == 0.0;
3✔
992
}
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