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