Blender  V3.3
BLI_math_matrix_test.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0 */
2 
3 #include "testing/testing.h"
4 
5 #include "BLI_math_matrix.h"
6 
7 TEST(math_matrix, interp_m4_m4m4_regular)
8 {
9  /* Test 4x4 matrix interpolation without singularity, i.e. without axis flip. */
10 
11  /* Transposed matrix, so that the code here is written in the same way as print_m4() outputs. */
12  /* This matrix represents T=(0.1, 0.2, 0.3), R=(40, 50, 60) degrees, S=(0.7, 0.8, 0.9) */
13  float matrix_a[4][4] = {
14  {0.224976f, -0.333770f, 0.765074f, 0.100000f},
15  {0.389669f, 0.647565f, 0.168130f, 0.200000f},
16  {-0.536231f, 0.330541f, 0.443163f, 0.300000f},
17  {0.000000f, 0.000000f, 0.000000f, 1.000000f},
18  };
19  transpose_m4(matrix_a);
20 
21  float matrix_i[4][4];
22  unit_m4(matrix_i);
23 
24  float result[4][4];
25  const float epsilon = 1e-6;
26  interp_m4_m4m4(result, matrix_i, matrix_a, 0.0f);
27  EXPECT_M4_NEAR(result, matrix_i, epsilon);
28 
29  interp_m4_m4m4(result, matrix_i, matrix_a, 1.0f);
30  EXPECT_M4_NEAR(result, matrix_a, epsilon);
31 
32  /* This matrix is based on the current implementation of the code, and isn't guaranteed to be
33  * correct. It's just consistent with the current implementation. */
34  float matrix_halfway[4][4] = {
35  {0.690643f, -0.253244f, 0.484996f, 0.050000f},
36  {0.271924f, 0.852623f, 0.012348f, 0.100000f},
37  {-0.414209f, 0.137484f, 0.816778f, 0.150000f},
38  {0.000000f, 0.000000f, 0.000000f, 1.000000f},
39  };
40 
41  transpose_m4(matrix_halfway);
42  interp_m4_m4m4(result, matrix_i, matrix_a, 0.5f);
43  EXPECT_M4_NEAR(result, matrix_halfway, epsilon);
44 }
45 
46 TEST(math_matrix, interp_m3_m3m3_singularity)
47 {
48  /* A singularity means that there is an axis mirror in the rotation component of the matrix.
49  * This is reflected in its negative determinant.
50  *
51  * The interpolation of 4x4 matrices performs linear interpolation on the translation component,
52  * and then uses the 3x3 interpolation function to handle rotation and scale. As a result, this
53  * test for a singularity in the rotation matrix only needs to test the 3x3 case. */
54 
55  /* Transposed matrix, so that the code here is written in the same way as print_m4() outputs. */
56  /* This matrix represents R=(4, 5, 6) degrees, S=(-1, 1, 1) */
57  float matrix_a[3][3] = {
58  {-0.990737f, -0.098227f, 0.093759f},
59  {-0.104131f, 0.992735f, -0.060286f},
60  {0.087156f, 0.069491f, 0.993768f},
61  };
62  transpose_m3(matrix_a);
63  EXPECT_NEAR(-1.0f, determinant_m3_array(matrix_a), 1e-6);
64 
65  /* This matrix represents R=(0, 0, 0), S=(-1, 0, 0) */
66  float matrix_b[3][3] = {
67  {-1.0f, 0.0f, 0.0f},
68  {0.0f, 1.0f, 0.0f},
69  {0.0f, 0.0f, 1.0f},
70  };
71  transpose_m3(matrix_b);
72 
73  float result[3][3];
74  interp_m3_m3m3(result, matrix_a, matrix_b, 0.0f);
75  EXPECT_M3_NEAR(result, matrix_a, 1e-5);
76 
77  interp_m3_m3m3(result, matrix_a, matrix_b, 1.0f);
78  EXPECT_M3_NEAR(result, matrix_b, 1e-5);
79 
80  interp_m3_m3m3(result, matrix_a, matrix_b, 0.5f);
81  float expect[3][3] = {
82  {-0.997681f, -0.049995f, 0.046186f},
83  {-0.051473f, 0.998181f, -0.031385f},
84  {0.044533f, 0.033689f, 0.998440f},
85  };
86  transpose_m3(expect);
87  EXPECT_M3_NEAR(result, expect, 1e-5);
88 
89  /* Interpolating between a matrix with and without axis flip can cause it to go through a zero
90  * point. The determinant det(A) of a matrix represents the change in volume; interpolating
91  * between matrices with det(A)=-1 and det(B)=1 will have to go through a point where
92  * det(result)=0, so where the volume becomes zero. */
93  float matrix_i[3][3];
94  unit_m3(matrix_i);
95  zero_m3(expect);
96  interp_m3_m3m3(result, matrix_a, matrix_i, 0.5f);
97  EXPECT_NEAR(0.0f, determinant_m3_array(result), 1e-5);
98  EXPECT_M3_NEAR(result, expect, 1e-5);
99 }
void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], float t)
Definition: math_matrix.c:2481
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void unit_m4(float m[4][4])
Definition: rct.c:1090
void zero_m3(float m[3][3])
Definition: math_matrix.c:23
void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], float t)
Definition: math_matrix.c:2436
float determinant_m3_array(const float m[3][3])
Definition: math_matrix.c:1098
void transpose_m3(float R[3][3])
Definition: math_matrix.c:1332
void transpose_m4(float R[4][4])
Definition: math_matrix.c:1377
TEST(math_matrix, interp_m4_m4m4_regular)
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
static double epsilon