• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5part of engine;
6
7class Matrix4 {
8  final Float64List _m4storage;
9
10  /// The components of the matrix.
11  Float64List get storage => _m4storage;
12
13  /// Returns a matrix that is the inverse of [other] if [other] is invertible,
14  /// otherwise `null`.
15  static Matrix4 tryInvert(Matrix4 other) {
16    final Matrix4 r = Matrix4.zero();
17    final double determinant = r.copyInverse(other);
18    if (determinant == 0.0) {
19      return null;
20    }
21    return r;
22  }
23
24  /// Return index in storage for [row], [col] value.
25  int index(int row, int col) => (col * 4) + row;
26
27  /// Value at [row], [col].
28  double entry(int row, int col) {
29    assert((row >= 0) && (row < dimension));
30    assert((col >= 0) && (col < dimension));
31
32    return _m4storage[index(row, col)];
33  }
34
35  /// Set value at [row], [col] to be [v].
36  void setEntry(int row, int col, double v) {
37    assert((row >= 0) && (row < dimension));
38    assert((col >= 0) && (col < dimension));
39
40    _m4storage[index(row, col)] = v;
41  }
42
43  /// Constructs a new mat4.
44  factory Matrix4(
45          double arg0,
46          double arg1,
47          double arg2,
48          double arg3,
49          double arg4,
50          double arg5,
51          double arg6,
52          double arg7,
53          double arg8,
54          double arg9,
55          double arg10,
56          double arg11,
57          double arg12,
58          double arg13,
59          double arg14,
60          double arg15) =>
61      Matrix4.zero()
62        ..setValues(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,
63            arg10, arg11, arg12, arg13, arg14, arg15);
64
65  /// New matrix from [values].
66  factory Matrix4.fromList(List<double> values) => Matrix4.zero()
67    ..setValues(
68        values[0],
69        values[1],
70        values[2],
71        values[3],
72        values[4],
73        values[5],
74        values[6],
75        values[7],
76        values[8],
77        values[9],
78        values[10],
79        values[11],
80        values[12],
81        values[13],
82        values[14],
83        values[15]);
84
85  /// Zero matrix.
86  Matrix4.zero() : _m4storage = Float64List(16);
87
88  /// Identity matrix.
89  factory Matrix4.identity() => Matrix4.zero()..setIdentity();
90
91  /// Copies values from [other].
92  factory Matrix4.copy(Matrix4 other) => Matrix4.zero()..setFrom(other);
93
94  /// Constructs a matrix that is the inverse of [other].
95  factory Matrix4.inverted(Matrix4 other) {
96    final Matrix4 r = Matrix4.zero();
97    final double determinant = r.copyInverse(other);
98    if (determinant == 0.0) {
99      throw ArgumentError.value(other, 'other', 'Matrix cannot be inverted');
100    }
101    return r;
102  }
103
104  /// Rotation of [radians_] around X.
105  factory Matrix4.rotationX(double radians) => Matrix4.zero()
106    .._m4storage[15] = 1.0
107    ..setRotationX(radians);
108
109  /// Rotation of [radians_] around Y.
110  factory Matrix4.rotationY(double radians) => Matrix4.zero()
111    .._m4storage[15] = 1.0
112    ..setRotationY(radians);
113
114  /// Rotation of [radians_] around Z.
115  factory Matrix4.rotationZ(double radians) => Matrix4.zero()
116    .._m4storage[15] = 1.0
117    ..setRotationZ(radians);
118
119  /// Translation matrix.
120  factory Matrix4.translation(Vector3 translation) => Matrix4.zero()
121    ..setIdentity()
122    ..setTranslation(translation);
123
124  /// Translation matrix.
125  factory Matrix4.translationValues(double x, double y, double z) =>
126      Matrix4.zero()
127        ..setIdentity()
128        ..setTranslationRaw(x, y, z);
129
130  /// Scale matrix.
131  factory Matrix4.diagonal3Values(double x, double y, double z) =>
132      Matrix4.zero()
133        .._m4storage[15] = 1.0
134        .._m4storage[10] = z
135        .._m4storage[5] = y
136        .._m4storage[0] = x;
137
138  /// Constructs Matrix4 with given [Float64List] as [storage].
139  Matrix4.fromFloat64List(this._m4storage);
140
141  /// Constructs Matrix4 with a [storage] that views given [buffer] starting at
142  /// [offset]. [offset] has to be multiple of [Float64List.bytesPerElement].
143  Matrix4.fromBuffer(ByteBuffer buffer, int offset)
144      : _m4storage = Float64List.view(buffer, offset, 16);
145
146  /// Sets the matrix with specified values.
147  void setValues(
148      double arg0,
149      double arg1,
150      double arg2,
151      double arg3,
152      double arg4,
153      double arg5,
154      double arg6,
155      double arg7,
156      double arg8,
157      double arg9,
158      double arg10,
159      double arg11,
160      double arg12,
161      double arg13,
162      double arg14,
163      double arg15) {
164    _m4storage[15] = arg15;
165    _m4storage[14] = arg14;
166    _m4storage[13] = arg13;
167    _m4storage[12] = arg12;
168    _m4storage[11] = arg11;
169    _m4storage[10] = arg10;
170    _m4storage[9] = arg9;
171    _m4storage[8] = arg8;
172    _m4storage[7] = arg7;
173    _m4storage[6] = arg6;
174    _m4storage[5] = arg5;
175    _m4storage[4] = arg4;
176    _m4storage[3] = arg3;
177    _m4storage[2] = arg2;
178    _m4storage[1] = arg1;
179    _m4storage[0] = arg0;
180  }
181
182  /// Sets the entire matrix to the matrix in [arg].
183  void setFrom(Matrix4 arg) {
184    final Float64List argStorage = arg._m4storage;
185    _m4storage[15] = argStorage[15];
186    _m4storage[14] = argStorage[14];
187    _m4storage[13] = argStorage[13];
188    _m4storage[12] = argStorage[12];
189    _m4storage[11] = argStorage[11];
190    _m4storage[10] = argStorage[10];
191    _m4storage[9] = argStorage[9];
192    _m4storage[8] = argStorage[8];
193    _m4storage[7] = argStorage[7];
194    _m4storage[6] = argStorage[6];
195    _m4storage[5] = argStorage[5];
196    _m4storage[4] = argStorage[4];
197    _m4storage[3] = argStorage[3];
198    _m4storage[2] = argStorage[2];
199    _m4storage[1] = argStorage[1];
200    _m4storage[0] = argStorage[0];
201  }
202
203  /// Dimension of the matrix.
204  int get dimension => 4;
205
206  /// Access the element of the matrix at the index [i].
207  double operator [](int i) => _m4storage[i];
208
209  /// Set the element of the matrix at the index [i].
210  void operator []=(int i, double v) {
211    _m4storage[i] = v;
212  }
213
214  /// Clone matrix.
215  Matrix4 clone() => Matrix4.copy(this);
216
217  /// Copy into [arg].
218  Matrix4 copyInto(Matrix4 arg) {
219    final Float64List argStorage = arg._m4storage;
220    argStorage[0] = _m4storage[0];
221    argStorage[1] = _m4storage[1];
222    argStorage[2] = _m4storage[2];
223    argStorage[3] = _m4storage[3];
224    argStorage[4] = _m4storage[4];
225    argStorage[5] = _m4storage[5];
226    argStorage[6] = _m4storage[6];
227    argStorage[7] = _m4storage[7];
228    argStorage[8] = _m4storage[8];
229    argStorage[9] = _m4storage[9];
230    argStorage[10] = _m4storage[10];
231    argStorage[11] = _m4storage[11];
232    argStorage[12] = _m4storage[12];
233    argStorage[13] = _m4storage[13];
234    argStorage[14] = _m4storage[14];
235    argStorage[15] = _m4storage[15];
236    return arg;
237  }
238
239  /// Translate this matrix by a [Vector3], [Vector4], or x,y,z
240  void translate(dynamic x, [double y = 0.0, double z = 0.0]) {
241    double tx;
242    double ty;
243    double tz;
244    const double tw = 1.0;
245    if (x is Vector3) {
246      tx = x.x;
247      ty = x.y;
248      tz = x.z;
249    } else if (x is double) {
250      tx = x;
251      ty = y;
252      tz = z;
253    }
254    final double t1 = _m4storage[0] * tx +
255        _m4storage[4] * ty +
256        _m4storage[8] * tz +
257        _m4storage[12] * tw;
258    final double t2 = _m4storage[1] * tx +
259        _m4storage[5] * ty +
260        _m4storage[9] * tz +
261        _m4storage[13] * tw;
262    final double t3 = _m4storage[2] * tx +
263        _m4storage[6] * ty +
264        _m4storage[10] * tz +
265        _m4storage[14] * tw;
266    final double t4 = _m4storage[3] * tx +
267        _m4storage[7] * ty +
268        _m4storage[11] * tz +
269        _m4storage[15] * tw;
270    _m4storage[12] = t1;
271    _m4storage[13] = t2;
272    _m4storage[14] = t3;
273    _m4storage[15] = t4;
274  }
275
276  /// Scale this matrix by a [Vector3], [Vector4], or x,y,z
277  void scale(dynamic x, [double y, double z]) {
278    double sx;
279    double sy;
280    double sz;
281    const double sw = 1.0;
282    if (x is Vector3) {
283      sx = x.x;
284      sy = x.y;
285      sz = x.z;
286    } else if (x is double) {
287      sx = x;
288      sy = y ?? x;
289      sz = z ?? x;
290    }
291    _m4storage[0] *= sx;
292    _m4storage[1] *= sx;
293    _m4storage[2] *= sx;
294    _m4storage[3] *= sx;
295    _m4storage[4] *= sy;
296    _m4storage[5] *= sy;
297    _m4storage[6] *= sy;
298    _m4storage[7] *= sy;
299    _m4storage[8] *= sz;
300    _m4storage[9] *= sz;
301    _m4storage[10] *= sz;
302    _m4storage[11] *= sz;
303    _m4storage[12] *= sw;
304    _m4storage[13] *= sw;
305    _m4storage[14] *= sw;
306    _m4storage[15] *= sw;
307  }
308
309  /// Create a copy of [this] scaled by a [Vector3], [Vector4] or [x],[y], and
310  /// [z].
311  Matrix4 scaled(dynamic x, [double y, double z]) => clone()..scale(x, y, z);
312
313  /// Zeros [this].
314  void setZero() {
315    _m4storage[0] = 0.0;
316    _m4storage[1] = 0.0;
317    _m4storage[2] = 0.0;
318    _m4storage[3] = 0.0;
319    _m4storage[4] = 0.0;
320    _m4storage[5] = 0.0;
321    _m4storage[6] = 0.0;
322    _m4storage[7] = 0.0;
323    _m4storage[8] = 0.0;
324    _m4storage[9] = 0.0;
325    _m4storage[10] = 0.0;
326    _m4storage[11] = 0.0;
327    _m4storage[12] = 0.0;
328    _m4storage[13] = 0.0;
329    _m4storage[14] = 0.0;
330    _m4storage[15] = 0.0;
331  }
332
333  /// Makes [this] into the identity matrix.
334  void setIdentity() {
335    _m4storage[0] = 1.0;
336    _m4storage[1] = 0.0;
337    _m4storage[2] = 0.0;
338    _m4storage[3] = 0.0;
339    _m4storage[4] = 0.0;
340    _m4storage[5] = 1.0;
341    _m4storage[6] = 0.0;
342    _m4storage[7] = 0.0;
343    _m4storage[8] = 0.0;
344    _m4storage[9] = 0.0;
345    _m4storage[10] = 1.0;
346    _m4storage[11] = 0.0;
347    _m4storage[12] = 0.0;
348    _m4storage[13] = 0.0;
349    _m4storage[14] = 0.0;
350    _m4storage[15] = 1.0;
351  }
352
353  /// Returns the tranpose of this.
354  Matrix4 transposed() => clone()..transpose();
355
356  void transpose() {
357    double temp;
358    temp = _m4storage[4];
359    _m4storage[4] = _m4storage[1];
360    _m4storage[1] = temp;
361    temp = _m4storage[8];
362    _m4storage[8] = _m4storage[2];
363    _m4storage[2] = temp;
364    temp = _m4storage[12];
365    _m4storage[12] = _m4storage[3];
366    _m4storage[3] = temp;
367    temp = _m4storage[9];
368    _m4storage[9] = _m4storage[6];
369    _m4storage[6] = temp;
370    temp = _m4storage[13];
371    _m4storage[13] = _m4storage[7];
372    _m4storage[7] = temp;
373    temp = _m4storage[14];
374    _m4storage[14] = _m4storage[11];
375    _m4storage[11] = temp;
376  }
377
378  /// Returns the determinant of this matrix.
379  double determinant() {
380    final double det2_01_01 =
381        _m4storage[0] * _m4storage[5] - _m4storage[1] * _m4storage[4];
382    final double det2_01_02 =
383        _m4storage[0] * _m4storage[6] - _m4storage[2] * _m4storage[4];
384    final double det2_01_03 =
385        _m4storage[0] * _m4storage[7] - _m4storage[3] * _m4storage[4];
386    final double det2_01_12 =
387        _m4storage[1] * _m4storage[6] - _m4storage[2] * _m4storage[5];
388    final double det2_01_13 =
389        _m4storage[1] * _m4storage[7] - _m4storage[3] * _m4storage[5];
390    final double det2_01_23 =
391        _m4storage[2] * _m4storage[7] - _m4storage[3] * _m4storage[6];
392    final double det3_201_012 = _m4storage[8] * det2_01_12 -
393        _m4storage[9] * det2_01_02 +
394        _m4storage[10] * det2_01_01;
395    final double det3_201_013 = _m4storage[8] * det2_01_13 -
396        _m4storage[9] * det2_01_03 +
397        _m4storage[11] * det2_01_01;
398    final double det3_201_023 = _m4storage[8] * det2_01_23 -
399        _m4storage[10] * det2_01_03 +
400        _m4storage[11] * det2_01_02;
401    final double det3_201_123 = _m4storage[9] * det2_01_23 -
402        _m4storage[10] * det2_01_13 +
403        _m4storage[11] * det2_01_12;
404    return -det3_201_123 * _m4storage[12] +
405        det3_201_023 * _m4storage[13] -
406        det3_201_013 * _m4storage[14] +
407        det3_201_012 * _m4storage[15];
408  }
409
410  /// Returns a new vector or matrix by multiplying [this] with [arg].
411  dynamic operator *(dynamic arg) {
412    if (arg is double) {
413      return scaled(arg);
414    }
415    if (arg is Vector3) {
416      return transformed3(arg);
417    }
418    if (arg is Matrix4) {
419      return multiplied(arg);
420    }
421    throw ArgumentError(arg);
422  }
423
424  /// Transform [arg] of type [Vector3] using the perspective transformation
425  /// defined by [this].
426  Vector3 perspectiveTransform(Vector3 arg) {
427    final Float64List argStorage = arg._v3storage;
428    final double x = (_m4storage[0] * argStorage[0]) +
429        (_m4storage[4] * argStorage[1]) +
430        (_m4storage[8] * argStorage[2]) +
431        _m4storage[12];
432    final double y = (_m4storage[1] * argStorage[0]) +
433        (_m4storage[5] * argStorage[1]) +
434        (_m4storage[9] * argStorage[2]) +
435        _m4storage[13];
436    final double z = (_m4storage[2] * argStorage[0]) +
437        (_m4storage[6] * argStorage[1]) +
438        (_m4storage[10] * argStorage[2]) +
439        _m4storage[14];
440    final double w = 1.0 /
441        ((_m4storage[3] * argStorage[0]) +
442            (_m4storage[7] * argStorage[1]) +
443            (_m4storage[11] * argStorage[2]) +
444            _m4storage[15]);
445    argStorage[0] = x * w;
446    argStorage[1] = y * w;
447    argStorage[2] = z * w;
448    return arg;
449  }
450
451  bool isIdentity() =>
452      _m4storage[0] == 1.0 // col 1
453      &&
454      _m4storage[1] == 0.0 &&
455      _m4storage[2] == 0.0 &&
456      _m4storage[3] == 0.0 &&
457      _m4storage[4] == 0.0 // col 2
458      &&
459      _m4storage[5] == 1.0 &&
460      _m4storage[6] == 0.0 &&
461      _m4storage[7] == 0.0 &&
462      _m4storage[8] == 0.0 // col 3
463      &&
464      _m4storage[9] == 0.0 &&
465      _m4storage[10] == 1.0 &&
466      _m4storage[11] == 0.0 &&
467      _m4storage[12] == 0.0 // col 4
468      &&
469      _m4storage[13] == 0.0 &&
470      _m4storage[14] == 0.0 &&
471      _m4storage[15] == 1.0;
472
473  /// Returns the translation vector from this homogeneous transformation matrix.
474  Vector3 getTranslation() {
475    final double z = _m4storage[14];
476    final double y = _m4storage[13];
477    final double x = _m4storage[12];
478    return Vector3(x, y, z);
479  }
480
481  void rotate(Vector3 axis, double angle) {
482    final double len = axis.length;
483    final Float64List axisStorage = axis._v3storage;
484    final double x = axisStorage[0] / len;
485    final double y = axisStorage[1] / len;
486    final double z = axisStorage[2] / len;
487    final double c = math.cos(angle);
488    final double s = math.sin(angle);
489    final double C = 1.0 - c;
490    final double m11 = x * x * C + c;
491    final double m12 = x * y * C - z * s;
492    final double m13 = x * z * C + y * s;
493    final double m21 = y * x * C + z * s;
494    final double m22 = y * y * C + c;
495    final double m23 = y * z * C - x * s;
496    final double m31 = z * x * C - y * s;
497    final double m32 = z * y * C + x * s;
498    final double m33 = z * z * C + c;
499    final double t1 =
500        _m4storage[0] * m11 + _m4storage[4] * m21 + _m4storage[8] * m31;
501    final double t2 =
502        _m4storage[1] * m11 + _m4storage[5] * m21 + _m4storage[9] * m31;
503    final double t3 =
504        _m4storage[2] * m11 + _m4storage[6] * m21 + _m4storage[10] * m31;
505    final double t4 =
506        _m4storage[3] * m11 + _m4storage[7] * m21 + _m4storage[11] * m31;
507    final double t5 =
508        _m4storage[0] * m12 + _m4storage[4] * m22 + _m4storage[8] * m32;
509    final double t6 =
510        _m4storage[1] * m12 + _m4storage[5] * m22 + _m4storage[9] * m32;
511    final double t7 =
512        _m4storage[2] * m12 + _m4storage[6] * m22 + _m4storage[10] * m32;
513    final double t8 =
514        _m4storage[3] * m12 + _m4storage[7] * m22 + _m4storage[11] * m32;
515    final double t9 =
516        _m4storage[0] * m13 + _m4storage[4] * m23 + _m4storage[8] * m33;
517    final double t10 =
518        _m4storage[1] * m13 + _m4storage[5] * m23 + _m4storage[9] * m33;
519    final double t11 =
520        _m4storage[2] * m13 + _m4storage[6] * m23 + _m4storage[10] * m33;
521    final double t12 =
522        _m4storage[3] * m13 + _m4storage[7] * m23 + _m4storage[11] * m33;
523    _m4storage[0] = t1;
524    _m4storage[1] = t2;
525    _m4storage[2] = t3;
526    _m4storage[3] = t4;
527    _m4storage[4] = t5;
528    _m4storage[5] = t6;
529    _m4storage[6] = t7;
530    _m4storage[7] = t8;
531    _m4storage[8] = t9;
532    _m4storage[9] = t10;
533    _m4storage[10] = t11;
534    _m4storage[11] = t12;
535  }
536
537  void rotateZ(double angle) {
538    final double cosAngle = math.cos(angle);
539    final double sinAngle = math.sin(angle);
540    final double t1 = _m4storage[0] * cosAngle + _m4storage[4] * sinAngle;
541    final double t2 = _m4storage[1] * cosAngle + _m4storage[5] * sinAngle;
542    final double t3 = _m4storage[2] * cosAngle + _m4storage[6] * sinAngle;
543    final double t4 = _m4storage[3] * cosAngle + _m4storage[7] * sinAngle;
544    final double t5 = _m4storage[0] * -sinAngle + _m4storage[4] * cosAngle;
545    final double t6 = _m4storage[1] * -sinAngle + _m4storage[5] * cosAngle;
546    final double t7 = _m4storage[2] * -sinAngle + _m4storage[6] * cosAngle;
547    final double t8 = _m4storage[3] * -sinAngle + _m4storage[7] * cosAngle;
548    _m4storage[0] = t1;
549    _m4storage[1] = t2;
550    _m4storage[2] = t3;
551    _m4storage[3] = t4;
552    _m4storage[4] = t5;
553    _m4storage[5] = t6;
554    _m4storage[6] = t7;
555    _m4storage[7] = t8;
556  }
557
558  /// Sets the translation vector in this homogeneous transformation matrix.
559  void setTranslation(Vector3 t) {
560    final Float64List tStorage = t._v3storage;
561    final double z = tStorage[2];
562    final double y = tStorage[1];
563    final double x = tStorage[0];
564    _m4storage[14] = z;
565    _m4storage[13] = y;
566    _m4storage[12] = x;
567  }
568
569  /// Sets the translation vector in this homogeneous transformation matrix.
570  void setTranslationRaw(double x, double y, double z) {
571    _m4storage[14] = z;
572    _m4storage[13] = y;
573    _m4storage[12] = x;
574  }
575
576  /// Transposes just the upper 3x3 rotation matrix.
577  void transposeRotation() {
578    double temp;
579    temp = _m4storage[1];
580    _m4storage[1] = _m4storage[4];
581    _m4storage[4] = temp;
582    temp = _m4storage[2];
583    _m4storage[2] = _m4storage[8];
584    _m4storage[8] = temp;
585    temp = _m4storage[4];
586    _m4storage[4] = _m4storage[1];
587    _m4storage[1] = temp;
588    temp = _m4storage[6];
589    _m4storage[6] = _m4storage[9];
590    _m4storage[9] = temp;
591    temp = _m4storage[8];
592    _m4storage[8] = _m4storage[2];
593    _m4storage[2] = temp;
594    temp = _m4storage[9];
595    _m4storage[9] = _m4storage[6];
596    _m4storage[6] = temp;
597  }
598
599  /// Invert [this].
600  double invert() => copyInverse(this);
601
602  /// Set this matrix to be the inverse of [arg]
603  double copyInverse(Matrix4 arg) {
604    final Float64List argStorage = arg._m4storage;
605    final double a00 = argStorage[0];
606    final double a01 = argStorage[1];
607    final double a02 = argStorage[2];
608    final double a03 = argStorage[3];
609    final double a10 = argStorage[4];
610    final double a11 = argStorage[5];
611    final double a12 = argStorage[6];
612    final double a13 = argStorage[7];
613    final double a20 = argStorage[8];
614    final double a21 = argStorage[9];
615    final double a22 = argStorage[10];
616    final double a23 = argStorage[11];
617    final double a30 = argStorage[12];
618    final double a31 = argStorage[13];
619    final double a32 = argStorage[14];
620    final double a33 = argStorage[15];
621    final double b00 = a00 * a11 - a01 * a10;
622    final double b01 = a00 * a12 - a02 * a10;
623    final double b02 = a00 * a13 - a03 * a10;
624    final double b03 = a01 * a12 - a02 * a11;
625    final double b04 = a01 * a13 - a03 * a11;
626    final double b05 = a02 * a13 - a03 * a12;
627    final double b06 = a20 * a31 - a21 * a30;
628    final double b07 = a20 * a32 - a22 * a30;
629    final double b08 = a20 * a33 - a23 * a30;
630    final double b09 = a21 * a32 - a22 * a31;
631    final double b10 = a21 * a33 - a23 * a31;
632    final double b11 = a22 * a33 - a23 * a32;
633    final double det =
634        b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
635    if (det == 0.0) {
636      setFrom(arg);
637      return 0.0;
638    }
639    final double invDet = 1.0 / det;
640    _m4storage[0] = (a11 * b11 - a12 * b10 + a13 * b09) * invDet;
641    _m4storage[1] = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet;
642    _m4storage[2] = (a31 * b05 - a32 * b04 + a33 * b03) * invDet;
643    _m4storage[3] = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet;
644    _m4storage[4] = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet;
645    _m4storage[5] = (a00 * b11 - a02 * b08 + a03 * b07) * invDet;
646    _m4storage[6] = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet;
647    _m4storage[7] = (a20 * b05 - a22 * b02 + a23 * b01) * invDet;
648    _m4storage[8] = (a10 * b10 - a11 * b08 + a13 * b06) * invDet;
649    _m4storage[9] = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet;
650    _m4storage[10] = (a30 * b04 - a31 * b02 + a33 * b00) * invDet;
651    _m4storage[11] = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet;
652    _m4storage[12] = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet;
653    _m4storage[13] = (a00 * b09 - a01 * b07 + a02 * b06) * invDet;
654    _m4storage[14] = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet;
655    _m4storage[15] = (a20 * b03 - a21 * b01 + a22 * b00) * invDet;
656    return det;
657  }
658
659  double invertRotation() {
660    final double det = determinant();
661    if (det == 0.0) {
662      return 0.0;
663    }
664    final double invDet = 1.0 / det;
665    double ix;
666    double iy;
667    double iz;
668    double jx;
669    double jy;
670    double jz;
671    double kx;
672    double ky;
673    double kz;
674    ix = invDet *
675        (_m4storage[5] * _m4storage[10] - _m4storage[6] * _m4storage[9]);
676    iy = invDet *
677        (_m4storage[2] * _m4storage[9] - _m4storage[1] * _m4storage[10]);
678    iz = invDet *
679        (_m4storage[1] * _m4storage[6] - _m4storage[2] * _m4storage[5]);
680    jx = invDet *
681        (_m4storage[6] * _m4storage[8] - _m4storage[4] * _m4storage[10]);
682    jy = invDet *
683        (_m4storage[0] * _m4storage[10] - _m4storage[2] * _m4storage[8]);
684    jz = invDet *
685        (_m4storage[2] * _m4storage[4] - _m4storage[0] * _m4storage[6]);
686    kx = invDet *
687        (_m4storage[4] * _m4storage[9] - _m4storage[5] * _m4storage[8]);
688    ky = invDet *
689        (_m4storage[1] * _m4storage[8] - _m4storage[0] * _m4storage[9]);
690    kz = invDet *
691        (_m4storage[0] * _m4storage[5] - _m4storage[1] * _m4storage[4]);
692    _m4storage[0] = ix;
693    _m4storage[1] = iy;
694    _m4storage[2] = iz;
695    _m4storage[4] = jx;
696    _m4storage[5] = jy;
697    _m4storage[6] = jz;
698    _m4storage[8] = kx;
699    _m4storage[9] = ky;
700    _m4storage[10] = kz;
701    return det;
702  }
703
704  /// Sets the upper 3x3 to a rotation of [radians] around X
705  void setRotationX(double radians) {
706    final double c = math.cos(radians);
707    final double s = math.sin(radians);
708    _m4storage[0] = 1.0;
709    _m4storage[1] = 0.0;
710    _m4storage[2] = 0.0;
711    _m4storage[4] = 0.0;
712    _m4storage[5] = c;
713    _m4storage[6] = s;
714    _m4storage[8] = 0.0;
715    _m4storage[9] = -s;
716    _m4storage[10] = c;
717    _m4storage[3] = 0.0;
718    _m4storage[7] = 0.0;
719    _m4storage[11] = 0.0;
720  }
721
722  /// Sets the upper 3x3 to a rotation of [radians] around Y
723  void setRotationY(double radians) {
724    final double c = math.cos(radians);
725    final double s = math.sin(radians);
726    _m4storage[0] = c;
727    _m4storage[1] = 0.0;
728    _m4storage[2] = -s;
729    _m4storage[4] = 0.0;
730    _m4storage[5] = 1.0;
731    _m4storage[6] = 0.0;
732    _m4storage[8] = s;
733    _m4storage[9] = 0.0;
734    _m4storage[10] = c;
735    _m4storage[3] = 0.0;
736    _m4storage[7] = 0.0;
737    _m4storage[11] = 0.0;
738  }
739
740  /// Sets the upper 3x3 to a rotation of [radians] around Z
741  void setRotationZ(double radians) {
742    final double c = math.cos(radians);
743    final double s = math.sin(radians);
744    _m4storage[0] = c;
745    _m4storage[1] = s;
746    _m4storage[2] = 0.0;
747    _m4storage[4] = -s;
748    _m4storage[5] = c;
749    _m4storage[6] = 0.0;
750    _m4storage[8] = 0.0;
751    _m4storage[9] = 0.0;
752    _m4storage[10] = 1.0;
753    _m4storage[3] = 0.0;
754    _m4storage[7] = 0.0;
755    _m4storage[11] = 0.0;
756  }
757
758  /// Multiply [this] by [arg].
759  void multiply(Matrix4 arg) {
760    final double m00 = _m4storage[0];
761    final double m01 = _m4storage[4];
762    final double m02 = _m4storage[8];
763    final double m03 = _m4storage[12];
764    final double m10 = _m4storage[1];
765    final double m11 = _m4storage[5];
766    final double m12 = _m4storage[9];
767    final double m13 = _m4storage[13];
768    final double m20 = _m4storage[2];
769    final double m21 = _m4storage[6];
770    final double m22 = _m4storage[10];
771    final double m23 = _m4storage[14];
772    final double m30 = _m4storage[3];
773    final double m31 = _m4storage[7];
774    final double m32 = _m4storage[11];
775    final double m33 = _m4storage[15];
776    final Float64List argStorage = arg._m4storage;
777    final double n00 = argStorage[0];
778    final double n01 = argStorage[4];
779    final double n02 = argStorage[8];
780    final double n03 = argStorage[12];
781    final double n10 = argStorage[1];
782    final double n11 = argStorage[5];
783    final double n12 = argStorage[9];
784    final double n13 = argStorage[13];
785    final double n20 = argStorage[2];
786    final double n21 = argStorage[6];
787    final double n22 = argStorage[10];
788    final double n23 = argStorage[14];
789    final double n30 = argStorage[3];
790    final double n31 = argStorage[7];
791    final double n32 = argStorage[11];
792    final double n33 = argStorage[15];
793    _m4storage[0] = (m00 * n00) + (m01 * n10) + (m02 * n20) + (m03 * n30);
794    _m4storage[4] = (m00 * n01) + (m01 * n11) + (m02 * n21) + (m03 * n31);
795    _m4storage[8] = (m00 * n02) + (m01 * n12) + (m02 * n22) + (m03 * n32);
796    _m4storage[12] = (m00 * n03) + (m01 * n13) + (m02 * n23) + (m03 * n33);
797    _m4storage[1] = (m10 * n00) + (m11 * n10) + (m12 * n20) + (m13 * n30);
798    _m4storage[5] = (m10 * n01) + (m11 * n11) + (m12 * n21) + (m13 * n31);
799    _m4storage[9] = (m10 * n02) + (m11 * n12) + (m12 * n22) + (m13 * n32);
800    _m4storage[13] = (m10 * n03) + (m11 * n13) + (m12 * n23) + (m13 * n33);
801    _m4storage[2] = (m20 * n00) + (m21 * n10) + (m22 * n20) + (m23 * n30);
802    _m4storage[6] = (m20 * n01) + (m21 * n11) + (m22 * n21) + (m23 * n31);
803    _m4storage[10] = (m20 * n02) + (m21 * n12) + (m22 * n22) + (m23 * n32);
804    _m4storage[14] = (m20 * n03) + (m21 * n13) + (m22 * n23) + (m23 * n33);
805    _m4storage[3] = (m30 * n00) + (m31 * n10) + (m32 * n20) + (m33 * n30);
806    _m4storage[7] = (m30 * n01) + (m31 * n11) + (m32 * n21) + (m33 * n31);
807    _m4storage[11] = (m30 * n02) + (m31 * n12) + (m32 * n22) + (m33 * n32);
808    _m4storage[15] = (m30 * n03) + (m31 * n13) + (m32 * n23) + (m33 * n33);
809  }
810
811  /// Multiply a copy of [this] with [arg].
812  Matrix4 multiplied(Matrix4 arg) => clone()..multiply(arg);
813
814  /// Multiply a transposed [this] with [arg].
815  void transposeMultiply(Matrix4 arg) {
816    final double m00 = _m4storage[0];
817    final double m01 = _m4storage[1];
818    final double m02 = _m4storage[2];
819    final double m03 = _m4storage[3];
820    final double m10 = _m4storage[4];
821    final double m11 = _m4storage[5];
822    final double m12 = _m4storage[6];
823    final double m13 = _m4storage[7];
824    final double m20 = _m4storage[8];
825    final double m21 = _m4storage[9];
826    final double m22 = _m4storage[10];
827    final double m23 = _m4storage[11];
828    final double m30 = _m4storage[12];
829    final double m31 = _m4storage[13];
830    final double m32 = _m4storage[14];
831    final double m33 = _m4storage[15];
832    final Float64List argStorage = arg._m4storage;
833    _m4storage[0] = (m00 * argStorage[0]) +
834        (m01 * argStorage[1]) +
835        (m02 * argStorage[2]) +
836        (m03 * argStorage[3]);
837    _m4storage[4] = (m00 * argStorage[4]) +
838        (m01 * argStorage[5]) +
839        (m02 * argStorage[6]) +
840        (m03 * argStorage[7]);
841    _m4storage[8] = (m00 * argStorage[8]) +
842        (m01 * argStorage[9]) +
843        (m02 * argStorage[10]) +
844        (m03 * argStorage[11]);
845    _m4storage[12] = (m00 * argStorage[12]) +
846        (m01 * argStorage[13]) +
847        (m02 * argStorage[14]) +
848        (m03 * argStorage[15]);
849    _m4storage[1] = (m10 * argStorage[0]) +
850        (m11 * argStorage[1]) +
851        (m12 * argStorage[2]) +
852        (m13 * argStorage[3]);
853    _m4storage[5] = (m10 * argStorage[4]) +
854        (m11 * argStorage[5]) +
855        (m12 * argStorage[6]) +
856        (m13 * argStorage[7]);
857    _m4storage[9] = (m10 * argStorage[8]) +
858        (m11 * argStorage[9]) +
859        (m12 * argStorage[10]) +
860        (m13 * argStorage[11]);
861    _m4storage[13] = (m10 * argStorage[12]) +
862        (m11 * argStorage[13]) +
863        (m12 * argStorage[14]) +
864        (m13 * argStorage[15]);
865    _m4storage[2] = (m20 * argStorage[0]) +
866        (m21 * argStorage[1]) +
867        (m22 * argStorage[2]) +
868        (m23 * argStorage[3]);
869    _m4storage[6] = (m20 * argStorage[4]) +
870        (m21 * argStorage[5]) +
871        (m22 * argStorage[6]) +
872        (m23 * argStorage[7]);
873    _m4storage[10] = (m20 * argStorage[8]) +
874        (m21 * argStorage[9]) +
875        (m22 * argStorage[10]) +
876        (m23 * argStorage[11]);
877    _m4storage[14] = (m20 * argStorage[12]) +
878        (m21 * argStorage[13]) +
879        (m22 * argStorage[14]) +
880        (m23 * argStorage[15]);
881    _m4storage[3] = (m30 * argStorage[0]) +
882        (m31 * argStorage[1]) +
883        (m32 * argStorage[2]) +
884        (m33 * argStorage[3]);
885    _m4storage[7] = (m30 * argStorage[4]) +
886        (m31 * argStorage[5]) +
887        (m32 * argStorage[6]) +
888        (m33 * argStorage[7]);
889    _m4storage[11] = (m30 * argStorage[8]) +
890        (m31 * argStorage[9]) +
891        (m32 * argStorage[10]) +
892        (m33 * argStorage[11]);
893    _m4storage[15] = (m30 * argStorage[12]) +
894        (m31 * argStorage[13]) +
895        (m32 * argStorage[14]) +
896        (m33 * argStorage[15]);
897  }
898
899  /// Multiply [this] with a transposed [arg].
900  void multiplyTranspose(Matrix4 arg) {
901    final double m00 = _m4storage[0];
902    final double m01 = _m4storage[4];
903    final double m02 = _m4storage[8];
904    final double m03 = _m4storage[12];
905    final double m10 = _m4storage[1];
906    final double m11 = _m4storage[5];
907    final double m12 = _m4storage[9];
908    final double m13 = _m4storage[13];
909    final double m20 = _m4storage[2];
910    final double m21 = _m4storage[6];
911    final double m22 = _m4storage[10];
912    final double m23 = _m4storage[14];
913    final double m30 = _m4storage[3];
914    final double m31 = _m4storage[7];
915    final double m32 = _m4storage[11];
916    final double m33 = _m4storage[15];
917    final Float64List argStorage = arg._m4storage;
918    _m4storage[0] = (m00 * argStorage[0]) +
919        (m01 * argStorage[4]) +
920        (m02 * argStorage[8]) +
921        (m03 * argStorage[12]);
922    _m4storage[4] = (m00 * argStorage[1]) +
923        (m01 * argStorage[5]) +
924        (m02 * argStorage[9]) +
925        (m03 * argStorage[13]);
926    _m4storage[8] = (m00 * argStorage[2]) +
927        (m01 * argStorage[6]) +
928        (m02 * argStorage[10]) +
929        (m03 * argStorage[14]);
930    _m4storage[12] = (m00 * argStorage[3]) +
931        (m01 * argStorage[7]) +
932        (m02 * argStorage[11]) +
933        (m03 * argStorage[15]);
934    _m4storage[1] = (m10 * argStorage[0]) +
935        (m11 * argStorage[4]) +
936        (m12 * argStorage[8]) +
937        (m13 * argStorage[12]);
938    _m4storage[5] = (m10 * argStorage[1]) +
939        (m11 * argStorage[5]) +
940        (m12 * argStorage[9]) +
941        (m13 * argStorage[13]);
942    _m4storage[9] = (m10 * argStorage[2]) +
943        (m11 * argStorage[6]) +
944        (m12 * argStorage[10]) +
945        (m13 * argStorage[14]);
946    _m4storage[13] = (m10 * argStorage[3]) +
947        (m11 * argStorage[7]) +
948        (m12 * argStorage[11]) +
949        (m13 * argStorage[15]);
950    _m4storage[2] = (m20 * argStorage[0]) +
951        (m21 * argStorage[4]) +
952        (m22 * argStorage[8]) +
953        (m23 * argStorage[12]);
954    _m4storage[6] = (m20 * argStorage[1]) +
955        (m21 * argStorage[5]) +
956        (m22 * argStorage[9]) +
957        (m23 * argStorage[13]);
958    _m4storage[10] = (m20 * argStorage[2]) +
959        (m21 * argStorage[6]) +
960        (m22 * argStorage[10]) +
961        (m23 * argStorage[14]);
962    _m4storage[14] = (m20 * argStorage[3]) +
963        (m21 * argStorage[7]) +
964        (m22 * argStorage[11]) +
965        (m23 * argStorage[15]);
966    _m4storage[3] = (m30 * argStorage[0]) +
967        (m31 * argStorage[4]) +
968        (m32 * argStorage[8]) +
969        (m33 * argStorage[12]);
970    _m4storage[7] = (m30 * argStorage[1]) +
971        (m31 * argStorage[5]) +
972        (m32 * argStorage[9]) +
973        (m33 * argStorage[13]);
974    _m4storage[11] = (m30 * argStorage[2]) +
975        (m31 * argStorage[6]) +
976        (m32 * argStorage[10]) +
977        (m33 * argStorage[14]);
978    _m4storage[15] = (m30 * argStorage[3]) +
979        (m31 * argStorage[7]) +
980        (m32 * argStorage[11]) +
981        (m33 * argStorage[15]);
982  }
983
984  /// Rotate [arg] of type [Vector3] using the rotation defined by [this].
985  Vector3 rotate3(Vector3 arg) {
986    final Float64List argStorage = arg._v3storage;
987    final double x = (_m4storage[0] * argStorage[0]) +
988        (_m4storage[4] * argStorage[1]) +
989        (_m4storage[8] * argStorage[2]);
990    final double y = (_m4storage[1] * argStorage[0]) +
991        (_m4storage[5] * argStorage[1]) +
992        (_m4storage[9] * argStorage[2]);
993    final double z = (_m4storage[2] * argStorage[0]) +
994        (_m4storage[6] * argStorage[1]) +
995        (_m4storage[10] * argStorage[2]);
996    argStorage[0] = x;
997    argStorage[1] = y;
998    argStorage[2] = z;
999    return arg;
1000  }
1001
1002  /// Rotate a copy of [arg] of type [Vector3] using the rotation defined by
1003  /// [this]. If a [out] parameter is supplied, the copy is stored in [out].
1004  Vector3 rotated3(Vector3 arg, [Vector3 out]) {
1005    if (out == null) {
1006      out = Vector3.copy(arg);
1007    } else {
1008      out.setFrom(arg);
1009    }
1010    return rotate3(out);
1011  }
1012
1013  /// Transform [arg] of type [Vector3] using the transformation defined by
1014  /// [this].
1015  Vector3 transform3(Vector3 arg) {
1016    final Float64List argStorage = arg._v3storage;
1017    final double x = (_m4storage[0] * argStorage[0]) +
1018        (_m4storage[4] * argStorage[1]) +
1019        (_m4storage[8] * argStorage[2]) +
1020        _m4storage[12];
1021    final double y = (_m4storage[1] * argStorage[0]) +
1022        (_m4storage[5] * argStorage[1]) +
1023        (_m4storage[9] * argStorage[2]) +
1024        _m4storage[13];
1025    final double z = (_m4storage[2] * argStorage[0]) +
1026        (_m4storage[6] * argStorage[1]) +
1027        (_m4storage[10] * argStorage[2]) +
1028        _m4storage[14];
1029    argStorage[0] = x;
1030    argStorage[1] = y;
1031    argStorage[2] = z;
1032    return arg;
1033  }
1034
1035  /// Transform a copy of [arg] of type [Vector3] using the transformation
1036  /// defined by [this]. If a [out] parameter is supplied, the copy is stored in
1037  /// [out].
1038  Vector3 transformed3(Vector3 arg, [Vector3 out]) {
1039    if (out == null) {
1040      out = Vector3.copy(arg);
1041    } else {
1042      out.setFrom(arg);
1043    }
1044    return transform3(out);
1045  }
1046
1047  /// Copies [this] into [array] starting at [offset].
1048  void copyIntoArray(List<num> array, [int offset = 0]) {
1049    final int i = offset;
1050    array[i + 15] = _m4storage[15];
1051    array[i + 14] = _m4storage[14];
1052    array[i + 13] = _m4storage[13];
1053    array[i + 12] = _m4storage[12];
1054    array[i + 11] = _m4storage[11];
1055    array[i + 10] = _m4storage[10];
1056    array[i + 9] = _m4storage[9];
1057    array[i + 8] = _m4storage[8];
1058    array[i + 7] = _m4storage[7];
1059    array[i + 6] = _m4storage[6];
1060    array[i + 5] = _m4storage[5];
1061    array[i + 4] = _m4storage[4];
1062    array[i + 3] = _m4storage[3];
1063    array[i + 2] = _m4storage[2];
1064    array[i + 1] = _m4storage[1];
1065    array[i + 0] = _m4storage[0];
1066  }
1067
1068  /// Copies elements from [array] into [this] starting at [offset].
1069  void copyFromArray(List<double> array, [int offset = 0]) {
1070    final int i = offset;
1071    _m4storage[15] = array[i + 15];
1072    _m4storage[14] = array[i + 14];
1073    _m4storage[13] = array[i + 13];
1074    _m4storage[12] = array[i + 12];
1075    _m4storage[11] = array[i + 11];
1076    _m4storage[10] = array[i + 10];
1077    _m4storage[9] = array[i + 9];
1078    _m4storage[8] = array[i + 8];
1079    _m4storage[7] = array[i + 7];
1080    _m4storage[6] = array[i + 6];
1081    _m4storage[5] = array[i + 5];
1082    _m4storage[4] = array[i + 4];
1083    _m4storage[3] = array[i + 3];
1084    _m4storage[2] = array[i + 2];
1085    _m4storage[1] = array[i + 1];
1086    _m4storage[0] = array[i + 0];
1087  }
1088}
1089
1090/// 3D column vector.
1091class Vector3 {
1092  final Float64List _v3storage;
1093
1094  /// The components of the vector.
1095  Float64List get storage => _v3storage;
1096
1097  /// Set the values of [result] to the minimum of [a] and [b] for each line.
1098  static void min(Vector3 a, Vector3 b, Vector3 result) {
1099    result
1100      ..x = math.min(a.x, b.x)
1101      ..y = math.min(a.y, b.y)
1102      ..z = math.min(a.z, b.z);
1103  }
1104
1105  /// Set the values of [result] to the maximum of [a] and [b] for each line.
1106  static void max(Vector3 a, Vector3 b, Vector3 result) {
1107    result
1108      ..x = math.max(a.x, b.x)
1109      ..y = math.max(a.y, b.y)
1110      ..z = math.max(a.z, b.z);
1111  }
1112
1113  /// Interpolate between [min] and [max] with the amount of [a] using a linear
1114  /// interpolation and store the values in [result].
1115  static void mix(Vector3 min, Vector3 max, double a, Vector3 result) {
1116    result
1117      ..x = min.x + a * (max.x - min.x)
1118      ..y = min.y + a * (max.y - min.y)
1119      ..z = min.z + a * (max.z - min.z);
1120  }
1121
1122  /// Construct a new vector with the specified values.
1123  factory Vector3(double x, double y, double z) =>
1124      Vector3.zero()..setValues(x, y, z);
1125
1126  /// Zero vector.
1127  Vector3.zero() : _v3storage = Float64List(3);
1128
1129  /// Splat [value] into all lanes of the vector.
1130  factory Vector3.all(double value) => Vector3.zero()..splat(value);
1131
1132  /// Copy of [other].
1133  factory Vector3.copy(Vector3 other) => Vector3.zero()..setFrom(other);
1134
1135  /// Constructs Vector3 with given Float64List as [storage].
1136  Vector3.fromFloat64List(this._v3storage);
1137
1138  /// Constructs Vector3 with a [storage] that views given [buffer] starting at
1139  /// [offset]. [offset] has to be multiple of [Float64List.bytesPerElement].
1140  Vector3.fromBuffer(ByteBuffer buffer, int offset)
1141      : _v3storage = Float64List.view(buffer, offset, 3);
1142
1143  /// Generate random vector in the range (0, 0, 0) to (1, 1, 1). You can
1144  /// optionally pass your own random number generator.
1145  factory Vector3.random([math.Random rng]) {
1146    rng ??= math.Random();
1147    return Vector3(rng.nextDouble(), rng.nextDouble(), rng.nextDouble());
1148  }
1149
1150  /// Set the values of the vector.
1151  void setValues(double x, double y, double z) {
1152    _v3storage[0] = x;
1153    _v3storage[1] = y;
1154    _v3storage[2] = z;
1155  }
1156
1157  /// Zero vector.
1158  void setZero() {
1159    _v3storage[2] = 0.0;
1160    _v3storage[1] = 0.0;
1161    _v3storage[0] = 0.0;
1162  }
1163
1164  /// Set the values by copying them from [other].
1165  void setFrom(Vector3 other) {
1166    final Float64List otherStorage = other._v3storage;
1167    _v3storage[0] = otherStorage[0];
1168    _v3storage[1] = otherStorage[1];
1169    _v3storage[2] = otherStorage[2];
1170  }
1171
1172  /// Splat [arg] into all lanes of the vector.
1173  void splat(double arg) {
1174    _v3storage[2] = arg;
1175    _v3storage[1] = arg;
1176    _v3storage[0] = arg;
1177  }
1178
1179  /// Access the component of the vector at the index [i].
1180  double operator [](int i) => _v3storage[i];
1181
1182  /// Set the component of the vector at the index [i].
1183  void operator []=(int i, double v) {
1184    _v3storage[i] = v;
1185  }
1186
1187  /// Set the length of the vector. A negative [value] will change the vectors
1188  /// orientation and a [value] of zero will set the vector to zero.
1189  set length(double value) {
1190    if (value == 0.0) {
1191      setZero();
1192    } else {
1193      double l = length;
1194      if (l == 0.0) {
1195        return;
1196      }
1197      l = value / l;
1198      _v3storage[0] *= l;
1199      _v3storage[1] *= l;
1200      _v3storage[2] *= l;
1201    }
1202  }
1203
1204  /// Length.
1205  double get length => math.sqrt(length2);
1206
1207  /// Length squared.
1208  double get length2 {
1209    double sum;
1210    sum = _v3storage[0] * _v3storage[0];
1211    sum += _v3storage[1] * _v3storage[1];
1212    sum += _v3storage[2] * _v3storage[2];
1213    return sum;
1214  }
1215
1216  /// Normalizes [this].
1217  double normalize() {
1218    final double l = length;
1219    if (l == 0.0) {
1220      return 0.0;
1221    }
1222    final double d = 1.0 / l;
1223    _v3storage[0] *= d;
1224    _v3storage[1] *= d;
1225    _v3storage[2] *= d;
1226    return l;
1227  }
1228
1229  /// Normalizes copy of [this].
1230  Vector3 normalized() => Vector3.copy(this)..normalize();
1231
1232  /// Normalize vector into [out].
1233  Vector3 normalizeInto(Vector3 out) {
1234    out
1235      ..setFrom(this)
1236      ..normalize();
1237    return out;
1238  }
1239
1240  /// Distance from [this] to [arg]
1241  double distanceTo(Vector3 arg) => math.sqrt(distanceToSquared(arg));
1242
1243  /// Squared distance from [this] to [arg]
1244  double distanceToSquared(Vector3 arg) {
1245    final Float64List argStorage = arg._v3storage;
1246    final double dx = _v3storage[0] - argStorage[0];
1247    final double dy = _v3storage[1] - argStorage[1];
1248    final double dz = _v3storage[2] - argStorage[2];
1249
1250    return dx * dx + dy * dy + dz * dz;
1251  }
1252
1253  /// Returns the angle between [this] vector and [other] in radians.
1254  double angleTo(Vector3 other) {
1255    final Float64List otherStorage = other._v3storage;
1256    if (_v3storage[0] == otherStorage[0] &&
1257        _v3storage[1] == otherStorage[1] &&
1258        _v3storage[2] == otherStorage[2]) {
1259      return 0.0;
1260    }
1261
1262    final double d = dot(other) / (length * other.length);
1263
1264    return math.acos(d.clamp(-1.0, 1.0));
1265  }
1266
1267  /// Inner product.
1268  double dot(Vector3 other) {
1269    final Float64List otherStorage = other._v3storage;
1270    double sum;
1271    sum = _v3storage[0] * otherStorage[0];
1272    sum += _v3storage[1] * otherStorage[1];
1273    sum += _v3storage[2] * otherStorage[2];
1274    return sum;
1275  }
1276
1277  /// Projects [this] using the projection matrix [arg]
1278  void applyProjection(Matrix4 arg) {
1279    final Float64List argStorage = arg.storage;
1280    final double x = _v3storage[0];
1281    final double y = _v3storage[1];
1282    final double z = _v3storage[2];
1283    final double d = 1.0 /
1284        (argStorage[3] * x +
1285            argStorage[7] * y +
1286            argStorage[11] * z +
1287            argStorage[15]);
1288    _v3storage[0] = (argStorage[0] * x +
1289            argStorage[4] * y +
1290            argStorage[8] * z +
1291            argStorage[12]) *
1292        d;
1293    _v3storage[1] = (argStorage[1] * x +
1294            argStorage[5] * y +
1295            argStorage[9] * z +
1296            argStorage[13]) *
1297        d;
1298    _v3storage[2] = (argStorage[2] * x +
1299            argStorage[6] * y +
1300            argStorage[10] * z +
1301            argStorage[14]) *
1302        d;
1303  }
1304
1305  /// True if any component is infinite.
1306  bool get isInfinite {
1307    bool isInfinite = false;
1308    isInfinite = isInfinite || _v3storage[0].isInfinite;
1309    isInfinite = isInfinite || _v3storage[1].isInfinite;
1310    isInfinite = isInfinite || _v3storage[2].isInfinite;
1311    return isInfinite;
1312  }
1313
1314  /// True if any component is NaN.
1315  bool get isNaN {
1316    bool isNan = false;
1317    isNan = isNan || _v3storage[0].isNaN;
1318    isNan = isNan || _v3storage[1].isNaN;
1319    isNan = isNan || _v3storage[2].isNaN;
1320    return isNan;
1321  }
1322
1323  /// Add [arg] to [this].
1324  void add(Vector3 arg) {
1325    final Float64List argStorage = arg._v3storage;
1326    _v3storage[0] = _v3storage[0] + argStorage[0];
1327    _v3storage[1] = _v3storage[1] + argStorage[1];
1328    _v3storage[2] = _v3storage[2] + argStorage[2];
1329  }
1330
1331  /// Add [arg] scaled by [factor] to [this].
1332  void addScaled(Vector3 arg, double factor) {
1333    final Float64List argStorage = arg._v3storage;
1334    _v3storage[0] = _v3storage[0] + argStorage[0] * factor;
1335    _v3storage[1] = _v3storage[1] + argStorage[1] * factor;
1336    _v3storage[2] = _v3storage[2] + argStorage[2] * factor;
1337  }
1338
1339  /// Subtract [arg] from [this].
1340  void sub(Vector3 arg) {
1341    final Float64List argStorage = arg._v3storage;
1342    _v3storage[0] = _v3storage[0] - argStorage[0];
1343    _v3storage[1] = _v3storage[1] - argStorage[1];
1344    _v3storage[2] = _v3storage[2] - argStorage[2];
1345  }
1346
1347  /// Multiply entries in [this] with entries in [arg].
1348  void multiply(Vector3 arg) {
1349    final Float64List argStorage = arg._v3storage;
1350    _v3storage[0] = _v3storage[0] * argStorage[0];
1351    _v3storage[1] = _v3storage[1] * argStorage[1];
1352    _v3storage[2] = _v3storage[2] * argStorage[2];
1353  }
1354
1355  /// Divide entries in [this] with entries in [arg].
1356  void divide(Vector3 arg) {
1357    final Float64List argStorage = arg._v3storage;
1358    _v3storage[0] = _v3storage[0] / argStorage[0];
1359    _v3storage[1] = _v3storage[1] / argStorage[1];
1360    _v3storage[2] = _v3storage[2] / argStorage[2];
1361  }
1362
1363  /// Scale [this].
1364  void scale(double arg) {
1365    _v3storage[2] = _v3storage[2] * arg;
1366    _v3storage[1] = _v3storage[1] * arg;
1367    _v3storage[0] = _v3storage[0] * arg;
1368  }
1369
1370  /// Create a copy of [this] and scale it by [arg].
1371  Vector3 scaled(double arg) => clone()..scale(arg);
1372
1373  /// Clone of [this].
1374  Vector3 clone() => Vector3.copy(this);
1375
1376  /// Copy [this] into [arg].
1377  Vector3 copyInto(Vector3 arg) {
1378    final Float64List argStorage = arg._v3storage;
1379    argStorage[0] = _v3storage[0];
1380    argStorage[1] = _v3storage[1];
1381    argStorage[2] = _v3storage[2];
1382    return arg;
1383  }
1384
1385  /// Copies [this] into [array] starting at [offset].
1386  void copyIntoArray(List<double> array, [int offset = 0]) {
1387    array[offset + 2] = _v3storage[2];
1388    array[offset + 1] = _v3storage[1];
1389    array[offset + 0] = _v3storage[0];
1390  }
1391
1392  set x(double arg) => _v3storage[0] = arg;
1393  set y(double arg) => _v3storage[1] = arg;
1394  set z(double arg) => _v3storage[2] = arg;
1395
1396  double get x => _v3storage[0];
1397  double get y => _v3storage[1];
1398  double get z => _v3storage[2];
1399}
1400