mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
This follows our namespace change from shell to flutter: https://github.com/flutter/engine/pull/8520.
155 lines
4.1 KiB
C++
155 lines
4.1 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "flutter/flow/matrix_decomposition.h"
|
|
|
|
namespace flutter {
|
|
|
|
static inline SkVector3 SkVector3Combine(const SkVector3& a,
|
|
float a_scale,
|
|
const SkVector3& b,
|
|
float b_scale) {
|
|
return {
|
|
a_scale * a.fX + b_scale * b.fX, //
|
|
a_scale * a.fY + b_scale * b.fY, //
|
|
a_scale * a.fZ + b_scale * b.fZ, //
|
|
};
|
|
}
|
|
|
|
static inline SkVector3 SkVector3Cross(const SkVector3& a, const SkVector3& b) {
|
|
return {
|
|
(a.fY * b.fZ) - (a.fZ * b.fY), //
|
|
(a.fZ * b.fX) - (a.fX * b.fZ), //
|
|
(a.fX * b.fY) - (a.fY * b.fX) //
|
|
};
|
|
}
|
|
|
|
MatrixDecomposition::MatrixDecomposition(const SkMatrix& matrix)
|
|
: MatrixDecomposition(SkMatrix44{matrix}) {}
|
|
|
|
// Use custom normalize to avoid skia precision loss/normalize() privatization.
|
|
static inline void SkVector3Normalize(SkVector3& v) {
|
|
double mag = sqrt(v.fX * v.fX + v.fY * v.fY + v.fZ * v.fZ);
|
|
double scale = 1.0 / mag;
|
|
v.fX *= scale;
|
|
v.fY *= scale;
|
|
v.fZ *= scale;
|
|
}
|
|
|
|
MatrixDecomposition::MatrixDecomposition(SkMatrix44 matrix) : valid_(false) {
|
|
if (matrix.get(3, 3) == 0) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
for (int j = 0; j < 4; j++) {
|
|
matrix.set(j, i, matrix.get(j, i) / matrix.get(3, 3));
|
|
}
|
|
}
|
|
|
|
SkMatrix44 perpective_matrix = matrix;
|
|
for (int i = 0; i < 3; i++) {
|
|
perpective_matrix.set(3, i, 0.0);
|
|
}
|
|
|
|
perpective_matrix.set(3, 3, 1.0);
|
|
|
|
if (perpective_matrix.determinant() == 0.0) {
|
|
return;
|
|
}
|
|
|
|
if (matrix.get(3, 0) != 0.0 || matrix.get(3, 1) != 0.0 ||
|
|
matrix.get(3, 2) != 0.0) {
|
|
const SkVector4 right_hand_side(matrix.get(3, 0), matrix.get(3, 1),
|
|
matrix.get(3, 2), matrix.get(3, 3));
|
|
|
|
SkMatrix44 inverted_transposed(
|
|
SkMatrix44::Uninitialized_Constructor::kUninitialized_Constructor);
|
|
if (!perpective_matrix.invert(&inverted_transposed)) {
|
|
return;
|
|
}
|
|
inverted_transposed.transpose();
|
|
|
|
perspective_ = inverted_transposed * right_hand_side;
|
|
|
|
matrix.set(3, 0, 0);
|
|
matrix.set(3, 1, 0);
|
|
matrix.set(3, 2, 0);
|
|
matrix.set(3, 3, 1);
|
|
}
|
|
|
|
translation_ = {matrix.get(0, 3), matrix.get(1, 3), matrix.get(2, 3)};
|
|
|
|
matrix.set(0, 3, 0.0);
|
|
matrix.set(1, 3, 0.0);
|
|
matrix.set(2, 3, 0.0);
|
|
|
|
SkVector3 row[3];
|
|
for (int i = 0; i < 3; i++) {
|
|
row[i].set(matrix.get(0, i), matrix.get(1, i), matrix.get(2, i));
|
|
}
|
|
|
|
scale_.fX = row[0].length();
|
|
|
|
SkVector3Normalize(row[0]);
|
|
|
|
shear_.fX = row[0].dot(row[1]);
|
|
row[1] = SkVector3Combine(row[1], 1.0, row[0], -shear_.fX);
|
|
|
|
scale_.fY = row[1].length();
|
|
|
|
SkVector3Normalize(row[1]);
|
|
|
|
shear_.fX /= scale_.fY;
|
|
|
|
shear_.fY = row[0].dot(row[2]);
|
|
row[2] = SkVector3Combine(row[2], 1.0, row[0], -shear_.fY);
|
|
shear_.fZ = row[1].dot(row[2]);
|
|
row[2] = SkVector3Combine(row[2], 1.0, row[1], -shear_.fZ);
|
|
|
|
scale_.fZ = row[2].length();
|
|
|
|
SkVector3Normalize(row[2]);
|
|
|
|
shear_.fY /= scale_.fZ;
|
|
shear_.fZ /= scale_.fZ;
|
|
|
|
if (row[0].dot(SkVector3Cross(row[1], row[2])) < 0) {
|
|
scale_.fX *= -1;
|
|
scale_.fY *= -1;
|
|
scale_.fZ *= -1;
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
row[i].fX *= -1;
|
|
row[i].fY *= -1;
|
|
row[i].fZ *= -1;
|
|
}
|
|
}
|
|
|
|
rotation_.set(0.5 * sqrt(fmax(1.0 + row[0].fX - row[1].fY - row[2].fZ, 0.0)),
|
|
0.5 * sqrt(fmax(1.0 - row[0].fX + row[1].fY - row[2].fZ, 0.0)),
|
|
0.5 * sqrt(fmax(1.0 - row[0].fX - row[1].fY + row[2].fZ, 0.0)),
|
|
0.5 * sqrt(fmax(1.0 + row[0].fX + row[1].fY + row[2].fZ, 0.0)));
|
|
|
|
if (row[2].fY > row[1].fZ) {
|
|
rotation_.fData[0] = -rotation_.fData[0];
|
|
}
|
|
if (row[0].fZ > row[2].fX) {
|
|
rotation_.fData[1] = -rotation_.fData[1];
|
|
}
|
|
if (row[1].fX > row[0].fY) {
|
|
rotation_.fData[2] = -rotation_.fData[2];
|
|
}
|
|
|
|
valid_ = true;
|
|
}
|
|
|
|
MatrixDecomposition::~MatrixDecomposition() = default;
|
|
|
|
bool MatrixDecomposition::IsValid() const {
|
|
return valid_;
|
|
}
|
|
|
|
} // namespace flutter
|