Blender V5.0
abc_matrix_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "testing/testing.h"
6
7/* Keep first since `BLI_utildefines.h` defines `AT` which conflicts with STL. */
9
10#include "BLI_math_base.h"
11#include "BLI_math_matrix.h"
12
13namespace blender::io::alembic {
14
15TEST(abc_matrix, CreateRotationMatrixY_YfromZ)
16{
17 /* Input variables */
18 float rot_x_mat[3][3];
19 float rot_y_mat[3][3];
20 float rot_z_mat[3][3];
21 float euler[3] = {0.0f, M_PI_4, 0.0f};
22
23 /* Construct expected matrices */
24 float unit[3][3];
25 float rot_z_min_quart_pi[3][3]; /* rotation of -pi/4 radians over z-axis */
26
27 unit_m3(unit);
28 unit_m3(rot_z_min_quart_pi);
29 rot_z_min_quart_pi[0][0] = M_SQRT1_2;
30 rot_z_min_quart_pi[0][1] = -M_SQRT1_2;
31 rot_z_min_quart_pi[1][0] = M_SQRT1_2;
32 rot_z_min_quart_pi[1][1] = M_SQRT1_2;
33
34 /* Run tests */
35 create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, ABC_YUP_FROM_ZUP);
36
37 EXPECT_M3_NEAR(rot_x_mat, unit, 1e-5f);
38 EXPECT_M3_NEAR(rot_y_mat, unit, 1e-5f);
39 EXPECT_M3_NEAR(rot_z_mat, rot_z_min_quart_pi, 1e-5f);
40}
41
42TEST(abc_matrix, CreateRotationMatrixZ_YfromZ)
43{
44 /* Input variables */
45 float rot_x_mat[3][3];
46 float rot_y_mat[3][3];
47 float rot_z_mat[3][3];
48 float euler[3] = {0.0f, 0.0f, M_PI_4};
49
50 /* Construct expected matrices */
51 float unit[3][3];
52 float rot_y_quart_pi[3][3]; /* rotation of pi/4 radians over y-axis */
53
54 unit_m3(unit);
55 unit_m3(rot_y_quart_pi);
56 rot_y_quart_pi[0][0] = M_SQRT1_2;
57 rot_y_quart_pi[0][2] = -M_SQRT1_2;
58 rot_y_quart_pi[2][0] = M_SQRT1_2;
59 rot_y_quart_pi[2][2] = M_SQRT1_2;
60
61 /* Run tests */
62 create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, ABC_YUP_FROM_ZUP);
63
64 EXPECT_M3_NEAR(rot_x_mat, unit, 1e-5f);
65 EXPECT_M3_NEAR(rot_y_mat, rot_y_quart_pi, 1e-5f);
66 EXPECT_M3_NEAR(rot_z_mat, unit, 1e-5f);
67}
68
69TEST(abc_matrix, CreateRotationMatrixXYZ_YfromZ)
70{
71 /* Input variables */
72 float rot_x_mat[3][3];
73 float rot_y_mat[3][3];
74 float rot_z_mat[3][3];
75 /* in degrees: X=10, Y=20, Z=30 */
76 float euler[3] = {0.17453292012214f, 0.34906581044197f, 0.52359879016876f};
77
78 /* Construct expected matrices */
79 float rot_x_p10[3][3]; /* rotation of +10 degrees over x-axis */
80 float rot_y_p30[3][3]; /* rotation of +30 degrees over y-axis */
81 float rot_z_m20[3][3]; /* rotation of -20 degrees over z-axis */
82
83 unit_m3(rot_x_p10);
84 rot_x_p10[1][1] = 0.9848077297210693f;
85 rot_x_p10[1][2] = 0.1736481785774231f;
86 rot_x_p10[2][1] = -0.1736481785774231f;
87 rot_x_p10[2][2] = 0.9848077297210693f;
88
89 unit_m3(rot_y_p30);
90 rot_y_p30[0][0] = 0.8660253882408142f;
91 rot_y_p30[0][2] = -0.5f;
92 rot_y_p30[2][0] = 0.5f;
93 rot_y_p30[2][2] = 0.8660253882408142f;
94
95 unit_m3(rot_z_m20);
96 rot_z_m20[0][0] = 0.9396926164627075f;
97 rot_z_m20[0][1] = -0.3420201241970062f;
98 rot_z_m20[1][0] = 0.3420201241970062f;
99 rot_z_m20[1][1] = 0.9396926164627075f;
100
101 /* Run tests */
102 create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, ABC_YUP_FROM_ZUP);
103
104 EXPECT_M3_NEAR(rot_x_mat, rot_x_p10, 1e-5f);
105 EXPECT_M3_NEAR(rot_y_mat, rot_y_p30, 1e-5f);
106 EXPECT_M3_NEAR(rot_z_mat, rot_z_m20, 1e-5f);
107}
108
109TEST(abc_matrix, CreateRotationMatrixXYZ_ZfromY)
110{
111 /* Input variables */
112 float rot_x_mat[3][3];
113 float rot_y_mat[3][3];
114 float rot_z_mat[3][3];
115 /* in degrees: X=10, Y=20, Z=30 */
116 float euler[3] = {0.1745329201221466f, 0.3490658104419708f, 0.5235987901687622f};
117
118 /* Construct expected matrices */
119 float rot_x_p10[3][3]; /* rotation of +10 degrees over x-axis */
120 float rot_y_m30[3][3]; /* rotation of -30 degrees over y-axis */
121 float rot_z_p20[3][3]; /* rotation of +20 degrees over z-axis */
122
123 unit_m3(rot_x_p10);
124 rot_x_p10[1][1] = 0.9848077297210693f;
125 rot_x_p10[1][2] = 0.1736481785774231f;
126 rot_x_p10[2][1] = -0.1736481785774231f;
127 rot_x_p10[2][2] = 0.9848077297210693f;
128
129 unit_m3(rot_y_m30);
130 rot_y_m30[0][0] = 0.8660253882408142f;
131 rot_y_m30[0][2] = 0.5f;
132 rot_y_m30[2][0] = -0.5f;
133 rot_y_m30[2][2] = 0.8660253882408142f;
134
135 unit_m3(rot_z_p20);
136 rot_z_p20[0][0] = 0.9396926164627075f;
137 rot_z_p20[0][1] = 0.3420201241970062f;
138 rot_z_p20[1][0] = -0.3420201241970062f;
139 rot_z_p20[1][1] = 0.9396926164627075f;
140
141 /* Run tests */
142 create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, ABC_ZUP_FROM_YUP);
143
144 EXPECT_M3_NEAR(rot_x_mat, rot_x_p10, 1e-5f);
145 EXPECT_M3_NEAR(rot_y_mat, rot_y_m30, 1e-5f);
146 EXPECT_M3_NEAR(rot_z_mat, rot_z_p20, 1e-5f);
147}
148
149TEST(abc_matrix, CopyM44AxisSwap_YfromZ)
150{
151 float result[4][4];
152
153 /* Construct an input matrix that performs a rotation like the tests
154 * above. This matrix was created by rotating a cube in Blender over
155 * (X=10, Y=20, Z=30 degrees in XYZ order) and translating over (1, 2, 3) */
156 float input[4][4] = {
157 {0.81379765272f, 0.4698463380336f, -0.342020124197f, 0.0f},
158 {-0.44096961617f, 0.8825641274452f, 0.163175910711f, 0.0f},
159 {0.37852230668f, 0.0180283170193f, 0.925416588783f, 0.0f},
160 {1.0f, 2.0f, 3.0f, 1.0f},
161 };
162
164
165 /* Check the resulting rotation & translation. */
166 const float trans[4] = {1.0f, 3.0f, -2.0f, 1.0f};
167 EXPECT_V4_NEAR(trans, result[3], 1e-5f);
168
169 /* This matrix was created by rotating a cube in Blender over
170 * (X=10, Y=30, Z=-20 degrees in XZY order) and translating over (1, 3, -2) */
171 const float expect[4][4] = {
172 {0.813797652721f, -0.342020124197f, -0.469846338033f, 0.0f},
173 {0.378522306680f, 0.925416588783f, -0.018028317019f, 0.0f},
174 {0.440969616174f, -0.163175910711f, 0.882564127445f, 0.0f},
175 {1.0f, 3.0f, -2.0f, 1.0f},
176 };
177 EXPECT_M4_NEAR(expect, result, 1e-5f);
178}
179
180TEST(abc_matrix, CopyM44AxisSwapWithScale_YfromZ)
181{
182 float result[4][4];
183
184 /* Construct an input matrix that performs a rotation like the tests
185 * above. This matrix was created by rotating a cube in Blender over
186 * (X=10, Y=20, Z=30 degrees in XYZ order), translating over (1, 2, 3),
187 * and scaling by (4, 5, 6). */
188 float input[4][4] = {
189 {3.25519061088f, 1.8793853521347f, -1.368080496788f, 0.0f},
190 {-2.20484805107f, 4.4128208160400f, 0.815879583358f, 0.0f},
191 {2.27113389968f, 0.1081698983907f, 5.552499771118f, 0.0f},
192 {1.0f, 2.0f, 3.0f, 1.0f},
193 };
194
196
197 /* This matrix was created by rotating a cube in Blender over
198 * (X=10, Y=30, Z=-20 degrees in XZY order), translating over (1, 3, -2)
199 * and scaling over (4, 6, 5). */
200 const float expect[4][4] = {
201 {3.255190610885f, -1.368080496788f, -1.879385352134f, 0.0f},
202 {2.271133899688f, 5.552499771118f, -0.108169898390f, 0.0f},
203 {2.204848051071f, -0.815879583358f, 4.412820816040f, 0.0f},
204 {1.0f, 3.0f, -2.0f, 1.0f},
205 };
206 EXPECT_M4_NEAR(expect, result, 1e-5f);
207}
208
209TEST(abc_matrix, CopyM44AxisSwap_ZfromY)
210{
211 float result[4][4];
212
213 /* This matrix was created by rotating a cube in Blender over
214 * (X=10, Y=30, Z=-20 degrees in XZY order) and translating over (1, 3, -2) */
215 float input[4][4] = {
216 {0.813797652721f, -0.342020124197f, -0.469846338033f, 0.0f},
217 {0.378522306680f, 0.925416588783f, -0.018028317019f, 0.0f},
218 {0.440969616174f, -0.163175910711f, 0.882564127445f, 0.0f},
219 {1.0f, 3.0f, -2.0f, 1.0f},
220 };
221
223
224 /* This matrix was created by rotating a cube in Blender over
225 * (X=10, Y=20, Z=30 degrees in XYZ order) and translating over (1, 2, 3) */
226 const float expect[4][4] = {
227 {0.813797652721f, 0.469846338033f, -0.342020124197f, 0.0f},
228 {-0.44096961617f, 0.882564127445f, 0.163175910711f, 0.0f},
229 {0.378522306680f, 0.018028317019f, 0.925416588783f, 0.0f},
230 {1.0f, 2.0f, 3.0f, 1.0f},
231 };
232
233 EXPECT_M4_NEAR(expect, result, 1e-5f);
234}
235
236TEST(abc_matrix, CopyM44AxisSwapWithScale_ZfromY)
237{
238 float result[4][4];
239
240 /* This matrix was created by rotating a cube in Blender over
241 * (X=10, Y=30, Z=-20 degrees in XZY order), translating over (1, 3, -2)
242 * and scaling over (4, 6, 5). */
243 float input[4][4] = {
244 {3.2551906108f, -1.36808049678f, -1.879385352134f, 0.0f},
245 {2.2711338996f, 5.55249977111f, -0.108169898390f, 0.0f},
246 {2.2048480510f, -0.81587958335f, 4.412820816040f, 0.0f},
247 {1.0f, 3.0f, -2.0f, 1.0f},
248 };
249
251
252 /* This matrix was created by rotating a cube in Blender over
253 * (X=10, Y=20, Z=30 degrees in XYZ order), translating over (1, 2, 3),
254 * and scaling by (4, 5, 6). */
255 const float expect[4][4] = {
256 {3.25519061088f, 1.879385352134f, -1.36808049678f, 0.0f},
257 {-2.2048480510f, 4.412820816040f, 0.81587958335f, 0.0f},
258 {2.27113389968f, 0.108169898390f, 5.55249977111f, 0.0f},
259 {1.0f, 2.0f, 3.0f, 1.0f},
260 };
261
262 EXPECT_M4_NEAR(expect, result, 1e-5f);
263}
264
265TEST(abc_matrix, CopyM44AxisSwapWithScale_gimbal_ZfromY)
266{
267 float result[4][4];
268
269 /* This matrix represents a rotation over (-90, -0, -0) degrees,
270 * and a translation over (-0, -0.1, -0). It is in Y=up. */
271 float input[4][4] = {
272 {1.000f, 0.000f, 0.000f, 0.000f},
273 {0.000f, 0.000f, -1.000f, 0.000f},
274 {0.000f, 1.000f, 0.000f, 0.000f},
275 {-0.000f, -0.100f, -0.000f, 1.000f},
276 };
277
279
280 /* Since the rotation is only over the X-axis, it should not change.
281 * The translation does change. */
282 const float expect[4][4] = {
283 {1.000f, 0.000f, 0.000f, 0.000f},
284 {0.000f, 0.000f, -1.000f, 0.000f},
285 {0.000f, 1.000f, 0.000f, 0.000f},
286 {-0.000f, 0.000f, -0.100f, 1.000f},
287 };
288
289 EXPECT_M4_NEAR(expect, result, 1e-5f);
290}
291
292} // namespace blender::io::alembic
#define M_SQRT1_2
#define M_PI_4
void unit_m3(float m[3][3])
#define input
void create_swapped_rotation_matrix(float rot_x_mat[3][3], float rot_y_mat[3][3], float rot_z_mat[3][3], const float euler[3], AbcAxisSwapMode mode)
void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode)
TEST(abc_matrix, CreateRotationMatrixY_YfromZ)