matrix_decomposition_unittests.cc 4.8 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#define _USE_MATH_DEFINES
6

7 8
#include <cmath>

9
#include "flutter/flow/matrix_decomposition.h"
10
#include "gtest/gtest.h"
11

12 13 14
namespace flutter {
namespace testing {

15
TEST(MatrixDecomposition, Rotation) {
16
  SkM44 matrix;
17 18

  const auto angle = M_PI_4;
19
  matrix.setRotate({0.0, 0.0, 1.0}, angle);
20

21
  flutter::MatrixDecomposition decomposition(matrix);
22 23 24 25
  ASSERT_TRUE(decomposition.IsValid());

  const auto sine = sin(angle * 0.5);

26 27 28 29
  ASSERT_FLOAT_EQ(0, decomposition.rotation().x);
  ASSERT_FLOAT_EQ(0, decomposition.rotation().y);
  ASSERT_FLOAT_EQ(sine, decomposition.rotation().z);
  ASSERT_FLOAT_EQ(cos(angle * 0.5), decomposition.rotation().w);
30 31 32
}

TEST(MatrixDecomposition, Scale) {
33
  SkM44 matrix;
34 35 36 37

  const auto scale = 5.0;
  matrix.setScale(scale + 0, scale + 1, scale + 2);

38
  flutter::MatrixDecomposition decomposition(matrix);
39 40
  ASSERT_TRUE(decomposition.IsValid());

41 42 43
  ASSERT_FLOAT_EQ(scale + 0, decomposition.scale().x);
  ASSERT_FLOAT_EQ(scale + 1, decomposition.scale().y);
  ASSERT_FLOAT_EQ(scale + 2, decomposition.scale().z);
44 45 46
}

TEST(MatrixDecomposition, Translate) {
47
  SkM44 matrix;
48 49 50 51

  const auto translate = 125.0;
  matrix.setTranslate(translate + 0, translate + 1, translate + 2);

52
  flutter::MatrixDecomposition decomposition(matrix);
53 54
  ASSERT_TRUE(decomposition.IsValid());

55 56 57
  ASSERT_FLOAT_EQ(translate + 0, decomposition.translation().x);
  ASSERT_FLOAT_EQ(translate + 1, decomposition.translation().y);
  ASSERT_FLOAT_EQ(translate + 2, decomposition.translation().z);
58 59 60 61 62 63 64
}

TEST(MatrixDecomposition, Combination) {
  const auto rotation = M_PI_4;
  const auto scale = 5;
  const auto translate = 125.0;

65 66
  SkM44 m1;
  m1.setRotate({0, 0, 1}, rotation);
67

68 69
  SkM44 m2;
  m2.setScale(scale, scale, scale);
70

71
  SkM44 m3;
72 73
  m3.setTranslate(translate, translate, translate);

74
  SkM44 combined = m3 * m2 * m1;
75

76
  flutter::MatrixDecomposition decomposition(combined);
77 78
  ASSERT_TRUE(decomposition.IsValid());

79 80 81
  ASSERT_FLOAT_EQ(translate, decomposition.translation().x);
  ASSERT_FLOAT_EQ(translate, decomposition.translation().y);
  ASSERT_FLOAT_EQ(translate, decomposition.translation().z);
82

83 84 85
  ASSERT_FLOAT_EQ(scale, decomposition.scale().x);
  ASSERT_FLOAT_EQ(scale, decomposition.scale().y);
  ASSERT_FLOAT_EQ(scale, decomposition.scale().z);
86 87 88

  const auto sine = sin(rotation * 0.5);

89 90 91 92
  ASSERT_FLOAT_EQ(0, decomposition.rotation().x);
  ASSERT_FLOAT_EQ(0, decomposition.rotation().y);
  ASSERT_FLOAT_EQ(sine, decomposition.rotation().z);
  ASSERT_FLOAT_EQ(cos(rotation * 0.5), decomposition.rotation().w);
93
}
94

95
TEST(MatrixDecomposition, ScaleFloatError) {
96
  constexpr float scale_increment = 0.00001f;
97 98
  float scale = 0.0001f;
  while (scale < 2.0f) {
99
    SkM44 matrix;
100 101
    matrix.setScale(scale, scale, 1.0f);

102
    flutter::MatrixDecomposition decomposition3(matrix);
103 104
    ASSERT_TRUE(decomposition3.IsValid());

105 106 107 108 109 110
    ASSERT_FLOAT_EQ(scale, decomposition3.scale().x);
    ASSERT_FLOAT_EQ(scale, decomposition3.scale().y);
    ASSERT_FLOAT_EQ(1.f, decomposition3.scale().z);
    ASSERT_FLOAT_EQ(0, decomposition3.rotation().x);
    ASSERT_FLOAT_EQ(0, decomposition3.rotation().y);
    ASSERT_FLOAT_EQ(0, decomposition3.rotation().z);
111
    scale += scale_increment;
112
  }
113

114
  SkM44 matrix;
115 116
  const auto scale1 = 1.7734375f;
  matrix.setScale(scale1, scale1, 1.f);
117

118 119
  // Bug upper bound (empirical)
  const auto scale2 = 1.773437559603f;
120
  SkM44 matrix2;
121 122 123 124
  matrix2.setScale(scale2, scale2, 1.f);

  // Bug lower bound (empirical)
  const auto scale3 = 1.7734374403954f;
125
  SkM44 matrix3;
126 127
  matrix3.setScale(scale3, scale3, 1.f);

128
  flutter::MatrixDecomposition decomposition(matrix);
129 130
  ASSERT_TRUE(decomposition.IsValid());

131
  flutter::MatrixDecomposition decomposition2(matrix2);
132 133
  ASSERT_TRUE(decomposition2.IsValid());

134
  flutter::MatrixDecomposition decomposition3(matrix3);
135 136
  ASSERT_TRUE(decomposition3.IsValid());

137 138
  ASSERT_FLOAT_EQ(scale1, decomposition.scale().x);
  ASSERT_FLOAT_EQ(scale1, decomposition.scale().y);
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
  ASSERT_FLOAT_EQ(1.f, decomposition.scale().z);
  ASSERT_FLOAT_EQ(0, decomposition.rotation().x);
  ASSERT_FLOAT_EQ(0, decomposition.rotation().y);
  ASSERT_FLOAT_EQ(0, decomposition.rotation().z);

  ASSERT_FLOAT_EQ(scale2, decomposition2.scale().x);
  ASSERT_FLOAT_EQ(scale2, decomposition2.scale().y);
  ASSERT_FLOAT_EQ(1.f, decomposition2.scale().z);
  ASSERT_FLOAT_EQ(0, decomposition2.rotation().x);
  ASSERT_FLOAT_EQ(0, decomposition2.rotation().y);
  ASSERT_FLOAT_EQ(0, decomposition2.rotation().z);

  ASSERT_FLOAT_EQ(scale3, decomposition3.scale().x);
  ASSERT_FLOAT_EQ(scale3, decomposition3.scale().y);
  ASSERT_FLOAT_EQ(1.f, decomposition3.scale().z);
  ASSERT_FLOAT_EQ(0, decomposition3.rotation().x);
  ASSERT_FLOAT_EQ(0, decomposition3.rotation().y);
  ASSERT_FLOAT_EQ(0, decomposition3.rotation().z);
157
}
158 159 160

}  // namespace testing
}  // namespace flutter