Blender  V2.93
armature_test.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2020 Blender Foundation
17  * All rights reserved.
18  */
19 
20 #include "BKE_armature.h"
21 
22 #include "BLI_math.h"
23 
24 #include "testing/testing.h"
25 
27 
28 static const float FLOAT_EPSILON = 1.2e-7;
29 
30 TEST(mat3_vec_to_roll, UnitMatrix)
31 {
32  float unit_matrix[3][3];
33  float roll;
34 
35  unit_m3(unit_matrix);
36 
37  /* Any vector with a unit matrix should return zero roll. */
38  mat3_vec_to_roll(unit_matrix, unit_matrix[0], &roll);
39  EXPECT_FLOAT_EQ(0.0f, roll);
40 
41  mat3_vec_to_roll(unit_matrix, unit_matrix[1], &roll);
42  EXPECT_FLOAT_EQ(0.0f, roll);
43 
44  mat3_vec_to_roll(unit_matrix, unit_matrix[2], &roll);
45  EXPECT_FLOAT_EQ(0.0f, roll);
46 
47  {
48  /* Non-unit vector. */
49  float vector[3] = {1.0f, 1.0f, 1.0f};
50  mat3_vec_to_roll(unit_matrix, vector, &roll);
51  EXPECT_NEAR(0.0f, roll, FLOAT_EPSILON);
52 
53  /* Normalized version of the above vector. */
55  mat3_vec_to_roll(unit_matrix, vector, &roll);
56  EXPECT_NEAR(0.0f, roll, FLOAT_EPSILON);
57  }
58 }
59 
60 TEST(mat3_vec_to_roll, Rotationmatrix)
61 {
62  float rotation_matrix[3][3];
63  float roll;
64 
65  const float rot_around_x[3] = {1.234f, 0.0f, 0.0f};
66  eul_to_mat3(rotation_matrix, rot_around_x);
67 
68  {
69  const float unit_axis_x[3] = {1.0f, 0.0f, 0.0f};
70  mat3_vec_to_roll(rotation_matrix, unit_axis_x, &roll);
71  EXPECT_NEAR(1.234f, roll, FLOAT_EPSILON);
72  }
73 
74  {
75  const float unit_axis_y[3] = {0.0f, 1.0f, 0.0f};
76  mat3_vec_to_roll(rotation_matrix, unit_axis_y, &roll);
77  EXPECT_NEAR(0, roll, FLOAT_EPSILON);
78  }
79 
80  {
81  const float unit_axis_z[3] = {0.0f, 0.0f, 1.0f};
82  mat3_vec_to_roll(rotation_matrix, unit_axis_z, &roll);
83  EXPECT_NEAR(0, roll, FLOAT_EPSILON);
84  }
85 
86  {
87  const float between_x_and_y[3] = {1.0f, 1.0f, 0.0f};
88  mat3_vec_to_roll(rotation_matrix, between_x_and_y, &roll);
89  EXPECT_NEAR(0.57158958f, roll, FLOAT_EPSILON);
90  }
91 }
92 
94 {
95  float negative_y_axis[3][3];
96  unit_m3(negative_y_axis);
97  negative_y_axis[0][0] = negative_y_axis[1][1] = -1.0f;
98 
99  const float roll = 0.0f;
100  float roll_mat[3][3];
101 
102  /* If normalized_vector is -Y, simple symmetry by Z axis. */
103  {
104  const float normalized_vector[3] = {0.0f, -1.0f, 0.0f};
105  vec_roll_to_mat3_normalized(normalized_vector, roll, roll_mat);
106  EXPECT_M3_NEAR(roll_mat, negative_y_axis, FLT_EPSILON);
107  }
108 
109  /* If normalized_vector is far enough from -Y, apply the general case. */
110  {
111  const float expected_roll_mat[3][3] = {{1.000000f, 0.000000f, 0.000000f},
112  {0.000000f, -0.999989986f, -0.000000f},
113  {0.000000f, 0.000000f, 1.000000f}};
114 
115  const float normalized_vector[3] = {0.0f, -1.0f + 1e-5f, 0.0f};
116  vec_roll_to_mat3_normalized(normalized_vector, roll, roll_mat);
117  EXPECT_M3_NEAR(roll_mat, expected_roll_mat, FLT_EPSILON);
118  }
119 
120 #if 0
121  /* TODO: This test will pass after fixing T82455) */
122  /* If normalized_vector is close to -Y and
123  * it has X and Z values above a threshold,
124  * apply the special case. */
125  {
126  const float expected_roll_mat[3][3] = {{0.000000f, -9.99999975e-06f, 1.000000f},
127  {9.99999975e-06f, -0.999999881f, 9.99999975e-06f},
128  {1.000000f, -9.99999975e-06, 0.000000f}};
129  const float normalized_vector[3] = {1e-24, -0.999999881, 0};
130  vec_roll_to_mat3_normalized(normalized_vector, roll, roll_mat);
131  EXPECT_M3_NEAR(roll_mat, expected_roll_mat, FLT_EPSILON);
132  }
133 #endif
134 
135  /* If normalized_vector is in a critical range close to -Y, apply the special case. */
136  {
137  const float expected_roll_mat[3][3] = {{0.000000f, -9.99999975e-06f, 1.000000f},
138  {9.99999975e-06f, -0.999999881f, 9.99999975e-06f},
139  {1.000000f, -9.99999975e-06f, 0.000000f}};
140 
141  const float normalized_vector[3] = {1e-5f, -0.999999881f, 1e-5f}; /* Corner Case. */
142  vec_roll_to_mat3_normalized(normalized_vector, roll, roll_mat);
143  EXPECT_M3_NEAR(roll_mat, expected_roll_mat, FLT_EPSILON);
144  }
145 
146  /* If normalized_vector is far enough from -Y, apply the general case. */
147  {
148  const float expected_roll_mat[3][3] = {{0.788675129f, -0.577350259f, -0.211324856f},
149  {0.577350259f, 0.577350259f, 0.577350259f},
150  {-0.211324856f, -0.577350259f, 0.788675129f}};
151 
152  const float vector[3] = {1.0f, 1.0f, 1.0f}; /* Arbitrary Value. */
153  float normalized_vector[3];
154  normalize_v3_v3(normalized_vector, vector);
155  vec_roll_to_mat3_normalized(normalized_vector, roll, roll_mat);
156  EXPECT_M3_NEAR(roll_mat, expected_roll_mat, FLT_EPSILON);
157  }
158 }
159 
160 } // namespace blender::bke::tests
void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll)
Definition: armature.c:2072
void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3])
Definition: armature.c:2155
void unit_m3(float m[3][3])
Definition: math_matrix.c:58
void eul_to_mat3(float mat[3][3], const float eul[3])
MINLINE float normalize_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
TEST(mat3_vec_to_roll, UnitMatrix)
static const float FLOAT_EPSILON