mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 09:31:58 +00:00
933537b66b
free of diagnostics as long as you filter with "!TODO" R=athom@google.com, jensj@google.com, natebiggs@google.com Change-Id: I73cf3c5ef6dab81808330c4eb5f44cb62e753c81 Tested: manually verified that VSCode is warning free. No changes in functionality. Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/333903 Auto-Submit: Jacob Richman <jacobr@google.com> Reviewed-by: Alexander Thomas <athom@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Nate Biggs <natebiggs@google.com> Commit-Queue: Jacob Richman <jacobr@google.com>
638 lines
17 KiB
Dart
638 lines
17 KiB
Dart
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
// Taken from https://github.com/yjbanov/uimatrix/blob/fd7244e09febe7e1f0dc8967b1e301adf2ebb833/lib/uimatrix.dart
|
|
|
|
library uimatrix;
|
|
|
|
import 'package:meta/meta.dart';
|
|
|
|
// Matrix shapes:
|
|
|
|
// Identity:
|
|
// 1 0 0 0
|
|
// 0 1 0 0
|
|
// 0 0 1 0
|
|
// 0 0 0 1
|
|
|
|
// Translation 2D:
|
|
// 1 0 0 x
|
|
// 0 1 0 y
|
|
// 0 0 1 0
|
|
// 0 0 0 1
|
|
|
|
// General 2D:
|
|
// sx k1 0 x
|
|
// k2 sy 0 y
|
|
// 0 0 1 0
|
|
// 0 0 0 1
|
|
|
|
// Most general case:
|
|
// m00 m01 m02 m03
|
|
// m10 m11 m12 m13
|
|
// m20 m21 m22 m23
|
|
// m30 m31 m32 m33
|
|
//
|
|
// sx k1 m8 x
|
|
// k2 sy m9 y
|
|
// m2 m6 sz z
|
|
// p1 p2 p3 w
|
|
|
|
// class UiMatrix {
|
|
// m00 (scaleX)
|
|
// m11 (scaleY)
|
|
// m03 (dx)
|
|
// m13 (dy)
|
|
// _MatrixExtension? rest
|
|
// }
|
|
//
|
|
// class _MatrixExtension {
|
|
// m01 m02
|
|
// m10 m12
|
|
// m20 m21 m22 m23
|
|
// m30 m31 m32 m33
|
|
// }
|
|
|
|
@immutable
|
|
final class UiMatrix {
|
|
/// The identity transform.
|
|
///
|
|
/// Has the following shape:
|
|
///
|
|
/// 1 0 0 0
|
|
/// 0 1 0 0
|
|
/// 0 0 1 0
|
|
/// 0 0 0 1
|
|
static const UiMatrix identity = UiMatrix._(m00: 1, m11: 1, m03: 0, m13: 0);
|
|
|
|
/// Instantiates a 2D translation matrix.
|
|
///
|
|
/// A 2D translation matrix has the following shape:
|
|
///
|
|
/// 1 0 0 dx
|
|
/// 0 1 0 dy
|
|
/// 0 0 1 0
|
|
/// 0 0 0 1
|
|
///
|
|
/// If both `x` and `y` are zero, returns the [identity] constant.
|
|
static UiMatrix translation2d({required double dx, required double dy}) {
|
|
if (dx == 0 && dy == 0) {
|
|
return identity;
|
|
}
|
|
return UiMatrix._(m00: 1, m11: 1, m03: dx, m13: dy);
|
|
}
|
|
|
|
/// Instantiates a 2D transformation that includes scaling and translation.
|
|
///
|
|
/// A simple 2D transformation has the following shape:
|
|
///
|
|
/// sx 0 0 dx
|
|
/// 0 sy 0 dy
|
|
/// 0 0 1 0
|
|
/// 0 0 0 1
|
|
///
|
|
/// If both `x` and `y` are zero, returns the [identity] constant.
|
|
static UiMatrix simple2d({
|
|
required double scaleX,
|
|
required double scaleY,
|
|
required double dx,
|
|
required double dy,
|
|
}) {
|
|
if (scaleX == 1 && scaleY == 1) {
|
|
return UiMatrix.translation2d(dx: dx, dy: dy);
|
|
}
|
|
return UiMatrix._(m00: scaleX, m11: scaleY, m03: dx, m13: dy);
|
|
}
|
|
|
|
/// Instantiates a general 2D transform matrix.
|
|
///
|
|
/// A general 2D transform matrix has the following shape:
|
|
///
|
|
/// sx k1 0 dx
|
|
/// k2 sy 0 dy
|
|
/// 0 0 1 0
|
|
/// 0 0 0 1
|
|
///
|
|
/// If the values of `sx` and `sy` and equal to 1, and the values of `k1` and
|
|
/// `k2` are equal to zero, this matrix returns the equivalent of invoking
|
|
/// [UiMatrix.translation2d]. If, in addition, the values of `x` and `y` are
|
|
/// zero, returns the [identity] constant.
|
|
static UiMatrix transform2d({
|
|
required double scaleX,
|
|
required double scaleY,
|
|
required double dx,
|
|
required double dy,
|
|
required double k1,
|
|
required double k2,
|
|
}) {
|
|
if (k1 == 0 && k2 == 0) {
|
|
return UiMatrix.simple2d(scaleX: scaleX, scaleY: scaleY, dx: dx, dy: dy);
|
|
}
|
|
|
|
return UiMatrix._(
|
|
m00: scaleX,
|
|
m11: scaleY,
|
|
m03: dx,
|
|
m13: dy,
|
|
rest: _MatrixExtension(
|
|
m01: k1,
|
|
m02: 0,
|
|
m10: k2,
|
|
m12: 0,
|
|
m20: 0,
|
|
m21: 0,
|
|
m22: 1,
|
|
m23: 0,
|
|
m30: 0,
|
|
m31: 0,
|
|
m32: 0,
|
|
m33: 1,
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Instantiates a general 3D transform matrix from its components.
|
|
///
|
|
/// A general 3D transform matrix has the following shape:
|
|
///
|
|
/// m00 m01 m02 m03
|
|
/// m10 m11 m12 m13
|
|
/// m20 m21 m22 m23
|
|
/// m30 m31 m32 m33
|
|
///
|
|
/// If values of `sx`, `sy`, `k1`, and `k2` are all zero, this matrix returns
|
|
/// the equivalent of invoking [UiMatrix.translation2d]. If, in addition, the
|
|
/// values of `x` and `y` are zero, returns the [identity] constant.
|
|
static UiMatrix transform({
|
|
required double m00,
|
|
required double m01,
|
|
required double m02,
|
|
required double m03,
|
|
required double m10,
|
|
required double m11,
|
|
required double m12,
|
|
required double m13,
|
|
required double m20,
|
|
required double m21,
|
|
required double m22,
|
|
required double m23,
|
|
required double m30,
|
|
required double m31,
|
|
required double m32,
|
|
required double m33,
|
|
}) {
|
|
// Lower to simplae 2D if possible to avoid allocation of extension.
|
|
// * 0 0 *
|
|
// 0 * 0 *
|
|
// 0 0 1 0
|
|
// 0 0 0 1
|
|
if (m01 == 0 &&
|
|
m02 == 0 &&
|
|
m10 == 0 &&
|
|
m12 == 0 &&
|
|
m20 == 0 &&
|
|
m21 == 0 &&
|
|
m22 == 1 &&
|
|
m23 == 0 &&
|
|
m30 == 0 &&
|
|
m31 == 0 &&
|
|
m32 == 0 &&
|
|
m33 == 1) {
|
|
return UiMatrix.simple2d(
|
|
scaleX: m00,
|
|
scaleY: m11,
|
|
dx: m03,
|
|
dy: m13,
|
|
);
|
|
}
|
|
|
|
return UiMatrix._(
|
|
m00: m00,
|
|
m11: m11,
|
|
m03: m03,
|
|
m13: m13,
|
|
rest: _MatrixExtension(
|
|
m01: m01,
|
|
m02: m02,
|
|
m10: m10,
|
|
m12: m12,
|
|
m20: m20,
|
|
m21: m21,
|
|
m22: m22,
|
|
m23: m23,
|
|
m30: m30,
|
|
m31: m31,
|
|
m32: m32,
|
|
m33: m33,
|
|
),
|
|
);
|
|
}
|
|
|
|
const UiMatrix._({
|
|
required double m00,
|
|
required double m11,
|
|
required double m03,
|
|
required double m13,
|
|
_MatrixExtension? rest,
|
|
}) : _m00 = m00,
|
|
_m11 = m11,
|
|
_m03 = m03,
|
|
_m13 = m13,
|
|
_rest = rest;
|
|
|
|
final double _m00;
|
|
final double _m11;
|
|
final double _m03;
|
|
final double _m13;
|
|
final _MatrixExtension? _rest;
|
|
|
|
double get scaleX => _m00;
|
|
double get scaleY => _m11;
|
|
double get dx => _m03;
|
|
double get dy => _m13;
|
|
|
|
/// Computes a matrix equal to the negated `this`.
|
|
UiMatrix operator -() {
|
|
return UiMatrix._(
|
|
m00: -_m00,
|
|
m11: -_m11,
|
|
m03: -_m03,
|
|
m13: -_m13,
|
|
rest: _rest?._negate(),
|
|
);
|
|
}
|
|
|
|
/// Computes a matrix equal to the sum of `this` + `other`.
|
|
UiMatrix operator +(UiMatrix other) {
|
|
final _MatrixExtension? selfRest = _rest;
|
|
final _MatrixExtension? otherRest = other._rest;
|
|
|
|
// TODO: possible specializations
|
|
// * We're already paying the branch cost of null checking extensions. If
|
|
// one of extensions is null, extension addition can be avoided for free.
|
|
// * The final result may be simpler than the inputs and can be lowered to
|
|
// enable future specializations.
|
|
_MatrixExtension? rest;
|
|
if (otherRest != null || selfRest != null) {
|
|
rest = (selfRest ?? _MatrixExtension._identityExtension) +
|
|
(otherRest ?? _MatrixExtension._identityExtension);
|
|
}
|
|
|
|
return UiMatrix._(
|
|
m00: _m00 + other._m00,
|
|
m11: _m11 + other._m11,
|
|
m03: _m03 + other._m03,
|
|
m13: _m13 + other._m13,
|
|
rest: rest,
|
|
);
|
|
}
|
|
|
|
/// Computes a matrix equal to the product `this` * `other`.
|
|
UiMatrix operator *(UiMatrix other) {
|
|
if (identical(other, UiMatrix.identity)) {
|
|
return this;
|
|
}
|
|
|
|
if (identical(this, UiMatrix.identity)) {
|
|
return other;
|
|
}
|
|
|
|
final _MatrixExtension? selfRest = _rest;
|
|
final _MatrixExtension? otherRest = other._rest;
|
|
|
|
if (otherRest == null) {
|
|
final double n00 = other._m00;
|
|
final double n11 = other._m11;
|
|
final double n03 = other._m03;
|
|
final double n13 = other._m13;
|
|
if (selfRest == null) {
|
|
return UiMatrix._(
|
|
m00: _m00 * n00,
|
|
m11: _m11 * n11,
|
|
m03: _m03 + _m00 * n03,
|
|
m13: _m13 + _m11 * n13,
|
|
);
|
|
} else {
|
|
return _generalMultiply(
|
|
this, selfRest, other, _MatrixExtension._identityExtension);
|
|
}
|
|
} else {
|
|
if (selfRest == null) {
|
|
return _generalMultiply(
|
|
this, _MatrixExtension._identityExtension, other, otherRest);
|
|
} else {
|
|
return _generalMultiply(this, selfRest, other, otherRest);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Computes the determinant of this matrix.
|
|
double determinant() {
|
|
final _MatrixExtension? rest = _rest;
|
|
if (rest == null) {
|
|
return _m00 * _m11;
|
|
} else {
|
|
return _generalDeterminant(this, rest);
|
|
}
|
|
}
|
|
|
|
/// Inverts this matrix.
|
|
///
|
|
/// If this matrix cannot be inverted, i.e. its [determinant] is zero, returns
|
|
/// null.
|
|
UiMatrix? invert() {
|
|
if (identical(this, UiMatrix.identity)) {
|
|
return this;
|
|
}
|
|
|
|
final _MatrixExtension? rest = _rest;
|
|
if (rest == null) {
|
|
final double a00 = _m00;
|
|
final double a11 = _m11;
|
|
final double a30 = _m03;
|
|
final double a31 = _m13;
|
|
final double det = a00 * a11;
|
|
|
|
if (det == 0.0) {
|
|
return null;
|
|
}
|
|
final double invDet = 1.0 / det;
|
|
|
|
return UiMatrix.simple2d(
|
|
scaleX: a11 * invDet,
|
|
scaleY: a00 * invDet,
|
|
dx: -a11 * a30 * invDet,
|
|
dy: -a00 * a31 * invDet,
|
|
);
|
|
} else {
|
|
return _generalInvert(this, rest);
|
|
}
|
|
}
|
|
}
|
|
|
|
@immutable
|
|
final class _MatrixExtension {
|
|
static const _MatrixExtension _identityExtension = _MatrixExtension(
|
|
m01: 0,
|
|
m02: 0,
|
|
m10: 0,
|
|
m12: 0,
|
|
m20: 0,
|
|
m21: 0,
|
|
m22: 1,
|
|
m23: 0,
|
|
m30: 0,
|
|
m31: 0,
|
|
m32: 0,
|
|
m33: 1,
|
|
);
|
|
|
|
const _MatrixExtension({
|
|
required double m01,
|
|
required double m02,
|
|
required double m10,
|
|
required double m12,
|
|
required double m20,
|
|
required double m21,
|
|
required double m22,
|
|
required double m23,
|
|
required double m30,
|
|
required double m31,
|
|
required double m32,
|
|
required double m33,
|
|
}) : _m01 = m01,
|
|
_m02 = m02,
|
|
_m10 = m10,
|
|
_m12 = m12,
|
|
_m20 = m20,
|
|
_m21 = m21,
|
|
_m22 = m22,
|
|
_m23 = m23,
|
|
_m30 = m30,
|
|
_m31 = m31,
|
|
_m32 = m32,
|
|
_m33 = m33;
|
|
|
|
final double _m01;
|
|
final double _m02;
|
|
final double _m10;
|
|
final double _m12;
|
|
final double _m20;
|
|
final double _m21;
|
|
final double _m22;
|
|
final double _m23;
|
|
final double _m30;
|
|
final double _m31;
|
|
final double _m32;
|
|
final double _m33;
|
|
|
|
_MatrixExtension _negate() {
|
|
return _MatrixExtension(
|
|
m01: -_m01,
|
|
m02: -_m02,
|
|
m10: -_m10,
|
|
m12: -_m12,
|
|
m20: -_m20,
|
|
m21: -_m21,
|
|
m22: -_m22,
|
|
m23: -_m23,
|
|
m30: -_m30,
|
|
m31: -_m31,
|
|
m32: -_m32,
|
|
m33: -_m33,
|
|
);
|
|
}
|
|
|
|
_MatrixExtension operator +(_MatrixExtension other) {
|
|
return _MatrixExtension(
|
|
m01: _m01 + other._m01,
|
|
m02: _m02 + other._m02,
|
|
m10: _m10 + other._m10,
|
|
m12: _m12 + other._m12,
|
|
m20: _m20 + other._m20,
|
|
m21: _m21 + other._m21,
|
|
m22: _m22 + other._m22,
|
|
m23: _m23 + other._m23,
|
|
m30: _m30 + other._m30,
|
|
m31: _m31 + other._m31,
|
|
m32: _m32 + other._m32,
|
|
m33: _m33 + other._m33,
|
|
);
|
|
}
|
|
}
|
|
|
|
UiMatrix _generalMultiply(
|
|
UiMatrix m, _MatrixExtension mExt, UiMatrix n, _MatrixExtension nExt) {
|
|
final double m00 = m._m00;
|
|
final double m01 = mExt._m01;
|
|
final double m02 = mExt._m02;
|
|
final double m03 = m._m03;
|
|
|
|
final double m10 = mExt._m10;
|
|
final double m11 = m._m11;
|
|
final double m12 = mExt._m12;
|
|
final double m13 = m._m13;
|
|
|
|
final double m20 = mExt._m20;
|
|
final double m21 = mExt._m21;
|
|
final double m22 = mExt._m22;
|
|
final double m23 = mExt._m23;
|
|
|
|
final double m30 = mExt._m30;
|
|
final double m31 = mExt._m31;
|
|
final double m32 = mExt._m32;
|
|
final double m33 = mExt._m33;
|
|
|
|
final double n00 = n._m00;
|
|
final double n01 = nExt._m01;
|
|
final double n02 = nExt._m02;
|
|
final double n03 = n._m03;
|
|
|
|
final double n10 = nExt._m10;
|
|
final double n11 = n._m11;
|
|
final double n12 = nExt._m12;
|
|
final double n13 = n._m13;
|
|
|
|
final double n20 = nExt._m20;
|
|
final double n21 = nExt._m21;
|
|
final double n22 = nExt._m22;
|
|
final double n23 = nExt._m23;
|
|
|
|
final double n30 = nExt._m30;
|
|
final double n31 = nExt._m31;
|
|
final double n32 = nExt._m32;
|
|
final double n33 = nExt._m33;
|
|
|
|
final double v00 = (m00 * n00) + (m01 * n10) + (m02 * n20) + (m03 * n30);
|
|
final double v01 = (m00 * n01) + (m01 * n11) + (m02 * n21) + (m03 * n31);
|
|
final double v02 = (m00 * n02) + (m01 * n12) + (m02 * n22) + (m03 * n32);
|
|
final double v03 = (m00 * n03) + (m01 * n13) + (m02 * n23) + (m03 * n33);
|
|
final double v10 = (m10 * n00) + (m11 * n10) + (m12 * n20) + (m13 * n30);
|
|
final double v11 = (m10 * n01) + (m11 * n11) + (m12 * n21) + (m13 * n31);
|
|
final double v12 = (m10 * n02) + (m11 * n12) + (m12 * n22) + (m13 * n32);
|
|
final double v13 = (m10 * n03) + (m11 * n13) + (m12 * n23) + (m13 * n33);
|
|
final double v20 = (m20 * n00) + (m21 * n10) + (m22 * n20) + (m23 * n30);
|
|
final double v21 = (m20 * n01) + (m21 * n11) + (m22 * n21) + (m23 * n31);
|
|
final double v22 = (m20 * n02) + (m21 * n12) + (m22 * n22) + (m23 * n32);
|
|
final double v23 = (m20 * n03) + (m21 * n13) + (m22 * n23) + (m23 * n33);
|
|
final double v30 = (m30 * n00) + (m31 * n10) + (m32 * n20) + (m33 * n30);
|
|
final double v31 = (m30 * n01) + (m31 * n11) + (m32 * n21) + (m33 * n31);
|
|
final double v32 = (m30 * n02) + (m31 * n12) + (m32 * n22) + (m33 * n32);
|
|
final double v33 = (m30 * n03) + (m31 * n13) + (m32 * n23) + (m33 * n33);
|
|
|
|
return UiMatrix.transform(
|
|
m00: v00,
|
|
m01: v01,
|
|
m02: v02,
|
|
m03: v03,
|
|
m10: v10,
|
|
m11: v11,
|
|
m12: v12,
|
|
m13: v13,
|
|
m20: v20,
|
|
m21: v21,
|
|
m22: v22,
|
|
m23: v23,
|
|
m30: v30,
|
|
m31: v31,
|
|
m32: v32,
|
|
m33: v33,
|
|
);
|
|
}
|
|
|
|
double _generalDeterminant(UiMatrix matrix, _MatrixExtension rest) {
|
|
final double a00 = matrix._m00;
|
|
final double a01 = rest._m10;
|
|
final double a02 = rest._m20;
|
|
final double a03 = rest._m30;
|
|
final double a10 = rest._m01;
|
|
final double a11 = matrix._m11;
|
|
final double a12 = rest._m21;
|
|
final double a13 = rest._m31;
|
|
final double a20 = rest._m02;
|
|
final double a21 = rest._m12;
|
|
final double a22 = rest._m22;
|
|
final double a23 = rest._m32;
|
|
final double a30 = matrix._m03;
|
|
final double a31 = matrix._m13;
|
|
final double a32 = rest._m23;
|
|
final double a33 = rest._m33;
|
|
|
|
final double b00 = a00 * a11 - a01 * a10;
|
|
final double b01 = a00 * a12 - a02 * a10;
|
|
final double b02 = a00 * a13 - a03 * a10;
|
|
final double b03 = a01 * a12 - a02 * a11;
|
|
final double b04 = a01 * a13 - a03 * a11;
|
|
final double b05 = a02 * a13 - a03 * a12;
|
|
final double b06 = a20 * a31 - a21 * a30;
|
|
final double b07 = a20 * a32 - a22 * a30;
|
|
final double b08 = a20 * a33 - a23 * a30;
|
|
final double b09 = a21 * a32 - a22 * a31;
|
|
final double b10 = a21 * a33 - a23 * a31;
|
|
final double b11 = a22 * a33 - a23 * a32;
|
|
return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
|
}
|
|
|
|
UiMatrix? _generalInvert(UiMatrix matrix, _MatrixExtension rest) {
|
|
final double a00 = matrix._m00;
|
|
final double a01 = rest._m10;
|
|
final double a02 = rest._m20;
|
|
final double a03 = rest._m30;
|
|
final double a10 = rest._m01;
|
|
final double a11 = matrix._m11;
|
|
final double a12 = rest._m21;
|
|
final double a13 = rest._m31;
|
|
final double a20 = rest._m02;
|
|
final double a21 = rest._m12;
|
|
final double a22 = rest._m22;
|
|
final double a23 = rest._m32;
|
|
final double a30 = matrix._m03;
|
|
final double a31 = matrix._m13;
|
|
final double a32 = rest._m23;
|
|
final double a33 = rest._m33;
|
|
|
|
final double b00 = a00 * a11 - a01 * a10;
|
|
final double b01 = a00 * a12 - a02 * a10;
|
|
final double b02 = a00 * a13 - a03 * a10;
|
|
final double b03 = a01 * a12 - a02 * a11;
|
|
final double b04 = a01 * a13 - a03 * a11;
|
|
final double b05 = a02 * a13 - a03 * a12;
|
|
final double b06 = a20 * a31 - a21 * a30;
|
|
final double b07 = a20 * a32 - a22 * a30;
|
|
final double b08 = a20 * a33 - a23 * a30;
|
|
final double b09 = a21 * a32 - a22 * a31;
|
|
final double b10 = a21 * a33 - a23 * a31;
|
|
final double b11 = a22 * a33 - a23 * a32;
|
|
final double det =
|
|
b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
|
if (det == 0.0) {
|
|
return null;
|
|
}
|
|
final double invDet = 1.0 / det;
|
|
|
|
// Inverse of a general matrix is guaranteed to be a general matrix, so we can
|
|
// instantiate a general matrix directly rather than trying to use
|
|
// constructors that attempt to lower the matrix to simpler kinds.
|
|
return UiMatrix._(
|
|
m00: (a11 * b11 - a12 * b10 + a13 * b09) * invDet,
|
|
m11: (a00 * b11 - a02 * b08 + a03 * b07) * invDet,
|
|
m03: (-a10 * b09 + a11 * b07 - a12 * b06) * invDet,
|
|
m13: (a00 * b09 - a01 * b07 + a02 * b06) * invDet,
|
|
rest: _MatrixExtension(
|
|
m01: (-a10 * b11 + a12 * b08 - a13 * b07) * invDet,
|
|
m02: (a10 * b10 - a11 * b08 + a13 * b06) * invDet,
|
|
m10: (-a01 * b11 + a02 * b10 - a03 * b09) * invDet,
|
|
m12: (-a00 * b10 + a01 * b08 - a03 * b06) * invDet,
|
|
m20: (a31 * b05 - a32 * b04 + a33 * b03) * invDet,
|
|
m21: (-a30 * b05 + a32 * b02 - a33 * b01) * invDet,
|
|
m22: (a30 * b04 - a31 * b02 + a33 * b00) * invDet,
|
|
m23: (-a30 * b03 + a31 * b01 - a32 * b00) * invDet,
|
|
m30: (-a21 * b05 + a22 * b04 - a23 * b03) * invDet,
|
|
m31: (a20 * b05 - a22 * b02 + a23 * b01) * invDet,
|
|
m32: (-a20 * b04 + a21 * b02 - a23 * b00) * invDet,
|
|
m33: (a20 * b03 - a21 * b01 + a22 * b00) * invDet,
|
|
),
|
|
);
|
|
}
|