5#include "testing/testing.h"
15TEST(math_matrix, interp_m4_m4m4_regular)
21 float matrix_a[4][4] = {
22 {0.224976f, -0.333770f, 0.765074f, 0.100000f},
23 {0.389669f, 0.647565f, 0.168130f, 0.200000f},
24 {-0.536231f, 0.330541f, 0.443163f, 0.300000f},
25 {0.000000f, 0.000000f, 0.000000f, 1.000000f},
33 const float epsilon = 1
e-6;
35 EXPECT_M4_NEAR(
result, matrix_i, epsilon);
38 EXPECT_M4_NEAR(
result, matrix_a, epsilon);
42 float matrix_halfway[4][4] = {
43 {0.690643f, -0.253244f, 0.484996f, 0.050000f},
44 {0.271924f, 0.852623f, 0.012348f, 0.100000f},
45 {-0.414209f, 0.137484f, 0.816778f, 0.150000f},
46 {0.000000f, 0.000000f, 0.000000f, 1.000000f},
51 EXPECT_M4_NEAR(
result, matrix_halfway, epsilon);
54TEST(math_matrix, interp_m3_m3m3_singularity)
65 float matrix_a[3][3] = {
66 {-0.990737f, -0.098227f, 0.093759f},
67 {-0.104131f, 0.992735f, -0.060286f},
68 {0.087156f, 0.069491f, 0.993768f},
74 float matrix_b[3][3] = {
83 EXPECT_M3_NEAR(
result, matrix_a, 1
e-5);
86 EXPECT_M3_NEAR(
result, matrix_b, 1
e-5);
89 float expect[3][3] = {
90 {-0.997681f, -0.049995f, 0.046186f},
91 {-0.051473f, 0.998181f, -0.031385f},
92 {0.044533f, 0.033689f, 0.998440f},
95 EXPECT_M3_NEAR(
result, expect, 1
e-5);
101 float matrix_i[3][3];
106 EXPECT_M3_NEAR(
result, expect, 1
e-5);
111 float matrix[3][3] = {
117 float const expect[3][3] = {
120 {0.0f, 0.0f, 125.0f},
122 EXPECT_M3_NEAR(matrix, expect, 1
e-5);
127 float matrix[4][4] = {
128 {2.0f, 0.0f, 0.0f, 0.0f},
129 {0.0f, 3.0f, 0.0f, 0.0f},
130 {0.0f, 0.0f, 5.0f, 0.0f},
131 {0.0f, 0.0f, 0.0f, 7.0f},
134 float const expect[4][4] = {
135 {8.0f, 0.0f, 0.0f, 0.0f},
136 {0.0f, 27.0f, 0.0f, 0.0f},
137 {0.0f, 0.0f, 125.0f, 0.0f},
138 {0.0f, 0.0f, 0.0f, 343.0f},
140 EXPECT_M4_NEAR(matrix, expect, 1
e-5);
145using namespace blender::math;
147TEST(math_matrix, MatrixInverse)
151 float3x3 expect =
float3x3({0.5f, 0.0f, 0.0f}, {0.0f, 0.5f, 0.0f}, {0.0f, 0.0f, 0.5f});
152 EXPECT_M3_NEAR(inv, expect, 1e-5f);
158 EXPECT_M3_NEAR(inv2, expect2, 1e-5f);
159 EXPECT_FALSE(success);
162TEST(math_matrix, MatrixPseudoInverse)
165 {0.389669f, 0.647565f, 0.168130f, 0.200000f},
166 {-0.536231f, 0.330541f, 0.443163f, 0.300000f},
167 {0.000000f, 0.000000f, 0.000000f, 1.000000f}));
169 {0.389669f, 0.647565f, 0.168130f, 0.200000f},
170 {-0.536231f, 0.330541f, 0.443163f, 0.300000f},
171 {0.000000f, 0.000000f, 0.000000f, 1.000000f}));
176 EXPECT_M4_NEAR(inv, expect, 1e-5f);
179 {0.000000f, 0.647565f, 0.168130f, 0.200000f},
180 {0.000000f, 0.330541f, 0.443163f, 0.300000f},
181 {0.000000f, 0.000000f, 0.000000f, 1.000000f}));
183 {-0.51311f, 1.02638f, 0.496437f, -0.302896f},
184 {0.952803f, 0.221885f, 0.527413f, -0.297881f},
185 {-0.0275438f, -0.0477073f, 0.0656508f, 0.9926f}));
189 EXPECT_M4_NEAR(inv2, expect2, 1e-5f);
192TEST(math_matrix, MatrixDeterminant)
195 float3x3 m3({1, 2, 3}, {-3, 4, -5}, {5, -6, 7});
196 float4x4 m4({1, 2, -3, 3}, {3, 4, -5, 3}, {5, 6, 7, -3}, {5, 6, 7, 1});
205TEST(math_matrix, MatrixAdjoint)
208 float3x3 m3({1, 2, 3}, {-3, 4, -5}, {5, -6, 7});
209 float4x4 m4({1, 2, -3, 3}, {3, 4, -5, 3}, {5, 6, 7, -3}, {5, 6, 7, 1});
213 float4x4({232, -184, -8, -0}, {-128, 88, 16, 0}, {80, -76, 4, 28}, {-72, 60, -12, -28}));
214 EXPECT_M2_NEAR(
adjoint(m2), expect2, 1e-8f);
215 EXPECT_M3_NEAR(
adjoint(m3), expect3, 1e-8f);
216 EXPECT_M4_NEAR(
adjoint(m4), expect4, 1e-8f);
221 float4x4 m({1, 2, 3, 4}, {5, 6, 7, 8}, {9, 1, 2, 3}, {4, 5, 6, 7});
234 expect =
float4x4({1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {1, 2, 3, 1});
235 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
238 {-0.0587266, -0.426918, 0.902382, 0},
239 {-0.909297, -0.350175, -0.224845, 0},
245 EXPECT_M3_NEAR(m, expect, 1
e-5);
247 EXPECT_M3_NEAR(m, expect, 1
e-5);
249 EXPECT_M3_NEAR(m, expect, 1
e-5);
252 {-0.117453, -0.853835, 1.80476, 5.44925},
253 {-1.81859, -0.700351, -0.44969, -0.330972},
257 EXPECT_M3_NEAR(m, expect, 1
e-5);
260 expect =
float4x4({1, 0, 0, 0}, {0, 2, 0, 0}, {0, 0, 3, 0}, {0, 0, 0, 4});
261 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
264 expect =
float4x4({1, 0, 0, 0}, {0, 2, 0, 0}, {0, 0, 3, 0}, {0, 0, 0, 1});
265 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
268 expect =
float4x4({1, 0, 0, 0}, {0, 2, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1});
269 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
272 expect =
float4x4({0.411982, -0.0587266, -0.909297, 0},
273 {-0.833738, -0.426918, -0.350175, 0},
274 {-0.36763, 0.902382, -0.224845, 0},
276 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
279 expect =
float4x4({0.411982, -0.0587266, -0.909297, 0},
280 {-1.66748, -0.853835, -0.700351, 0},
281 {-1.10289, 2.70714, -0.674535, 0},
283 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
297 const float epsilon = 1
e-6;
299 float4x4 m1 =
float4x4({0, 3, 0, 0}, {2, 0, 0, 0}, {0, 0, 2, 0}, {0, 0, 0, 1});
301 expect =
float4x4({0, 3, 0, 0}, {2, 0, 0, 0}, {0, 0, 2, 0}, {4, 9, 2, 1});
303 EXPECT_M4_NEAR(
result, expect, epsilon);
305 expect =
float4x4({0, 3, 0, 0}, {2, 0, 0, 0}, {0, 0, 2, 0}, {4, 0, 0, 1});
307 EXPECT_M4_NEAR(
result, expect, epsilon);
309 expect =
float4x4({0, 0, -2, 0}, {2, 0, 0, 0}, {0, 3, 0, 0}, {0, 0, 0, 1});
311 EXPECT_M4_NEAR(
result, expect, epsilon);
313 expect =
float4x4({0, 9, 0, 0}, {4, 0, 0, 0}, {0, 0, 8, 0}, {0, 0, 0, 1});
315 EXPECT_M4_NEAR(
result, expect, epsilon);
317 expect =
float4x4({0, 9, 0, 0}, {4, 0, 0, 0}, {0, 0, 2, 0}, {0, 0, 0, 1});
319 EXPECT_M4_NEAR(
result, expect, epsilon);
322TEST(math_matrix, MatrixCompareTest)
324 float4x4 m1 =
float4x4({0, 3, 0, 0}, {2, 0, 0, 0}, {0, 0, 2, 0}, {0, 0, 0, 1});
325 float4x4 m2 =
float4x4({0, 3.001, 0, 0}, {1.999, 0, 0, 0}, {0, 0, 2.001, 0}, {0, 0, 0, 1.001});
326 float4x4 m3 =
float4x4({0, 3.001, 0, 0}, {1, 1, 0, 0}, {0, 0, 2.001, 0}, {0, 0, 0, 1.001});
327 float4x4 m4 =
float4x4({0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1});
328 float4x4 m5 =
float4x4({0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0});
329 float4x4 m6 =
float4x4({1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1});
330 EXPECT_TRUE(
is_equal(m1, m2, 0.01f));
331 EXPECT_FALSE(
is_equal(m1, m2, 0.0001f));
332 EXPECT_FALSE(
is_equal(m1, m3, 0.01f));
347TEST(math_matrix, MatrixMultiply)
352 {1.0, 2.0, 3.0, 4.0},
353 {5.0, 6.0, 7.0, 8.0},
354 {9.0, 10.0, 11.0, 12.0},
355 {13.0, 14.0, 15.0, 16.0},
358 {0.1f, 0.2f, 0.3f, 0.4f},
359 {0.5f, 0.6f, 0.7f, 0.8f},
360 {0.9f, 1.0f, 1.1f, 1.2f},
361 {1.3f, 1.4f, 1.5f, 1.6f},
365 {9.0f, 10.0f, 11.0f, 12.0f},
366 {20.2f, 22.8f, 25.4f, 28.0f},
367 {31.4f, 35.6f, 39.8f, 44.0f},
368 {42.6f, 48.4f, 54.2f, 60.0f},
373 EXPECT_M4_NEAR(
result, expected, 1e-5f);
377TEST(math_matrix, MatrixToNearestEuler)
382 float3x3 mat = {{0.808309, -0.578051, -0.111775},
383 {0.47251, 0.750174, -0.462572},
384 {0.351241, 0.321087, 0.879507}};
390TEST(math_matrix, MatrixMethods)
392 float4x4 m =
float4x4({0, 3, 0, 0}, {2, 0, 0, 0}, {0, 0, 2, 0}, {0, 1, 0, 1});
404 EXPECT_V4_NEAR(
size, expect_size, 0.0002f);
417 EXPECT_V3_NEAR(
scale, expect_scale, 0.00001f);
419 EXPECT_V3_NEAR(
float3(eul),
float3(expect_eul), 0.0002f);
424 EXPECT_V3_NEAR(
scale, expect_scale, 0.00001f);
425 EXPECT_V3_NEAR(loc, expect_location, 0.00001f);
427 EXPECT_V3_NEAR(
float3(eul),
float3(expect_eul), 0.0002f);
430TEST(math_matrix, Transformation2DMatrixDecomposition)
439 float2 decomposed_translation, decomposed_scale;
440 to_loc_rot_scale(transformation, decomposed_translation, decomposed_rotation, decomposed_scale);
442 EXPECT_V2_NEAR(decomposed_translation, translation, 0.00001f);
443 EXPECT_V2_NEAR(decomposed_scale,
scale, 0.00001f);
444 EXPECT_NEAR(decomposed_rotation.
radian(), rotation.
radian(), 0.00001f);
447TEST(math_matrix, MatrixToQuaternionLegacy)
449 float3x3 mat = {{0.808309, -0.578051, -0.111775},
450 {0.47251, 0.750174, -0.462572},
451 {0.351241, 0.321087, 0.879507}};
454 float4(0.927091f, -0.211322f, 0.124857f, -0.283295f),
458TEST(math_matrix, MatrixTranspose)
460 float4x4 m({1, 2, 3, 4}, {5, 6, 7, 8}, {9, 1, 2, 3}, {2, 5, 6, 7});
461 float4x4 expect({1, 5, 9, 2}, {2, 6, 1, 5}, {3, 7, 2, 6}, {4, 8, 3, 7});
465TEST(math_matrix, MatrixInterpolationRegular)
472 {0.389669f, 0.647565f, 0.168130f, 0.200000f},
473 {-0.536231f, 0.330541f, 0.443163f, 0.300000f},
474 {0.000000f, 0.000000f, 0.000000f, 1.000000f}));
477 const float epsilon = 1
e-6;
479 EXPECT_M4_NEAR(
result, m1, epsilon);
481 EXPECT_M4_NEAR(
result, m2, epsilon);
486 {0.271924f, 0.852623f, 0.012348f, 0.100000f},
487 {-0.414209f, 0.137484f, 0.816778f, 0.150000f},
488 {0.000000f, 0.000000f, 0.000000f, 1.000000f}));
490 EXPECT_M4_NEAR(
result, expect, epsilon);
493 EXPECT_M4_NEAR(
result, expect, epsilon);
496TEST(math_matrix, MatrixInterpolationSingularity)
508 {-0.104131f, 0.992735f, -0.060286f},
509 {0.087156f, 0.069491f, 0.993768f}));
514 float3x3({-1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}));
517 EXPECT_M3_NEAR(
result, matrix_a, 1
e-5);
520 EXPECT_M3_NEAR(
result, matrix_b, 1
e-5);
525 {-0.051473f, 0.998181f, -0.031385f},
526 {0.044533f, 0.033689f, 0.998440f}));
527 EXPECT_M3_NEAR(
result, expect, 1
e-5);
530 EXPECT_M3_NEAR(
result, expect, 1
e-5);
540 EXPECT_M3_NEAR(
result, expect, 1
e-5);
543TEST(math_matrix, MatrixTransform)
552 expect = {13, 2, -1};
554 EXPECT_V3_NEAR(
result, expect, 1
e-2);
558 EXPECT_V3_NEAR(
result, expect, 1
e-5);
561 EXPECT_V3_NEAR(
result, expect, 1
e-5);
564 EXPECT_V3_NEAR(
result, expect, 1
e-5);
566 expect = {-0.333333, -0.666666, -1.14814};
568 EXPECT_V3_NEAR(
result, expect, 1
e-5);
570 float2 expect2 = {0.76923, 1.61538};
572 EXPECT_V2_NEAR(result2, expect2, 1
e-5);
575TEST(math_matrix, MatrixTransform2D)
587TEST(math_matrix, MatrixProjection)
591 float4x4 ortho = orthographic(-0.2f, 0.3f, -0.2f, 0.4f, -0.2f, -0.5f);
592 float4x4 pers1 = perspective(-0.2f, 0.3f, -0.2f, 0.4f, -0.2f, -0.5f);
597 {0.0f, 3.33333f, 0.0f, -0.333333f},
598 {0.0f, 0.0f, 6.66667f, -2.33333f},
599 {0.0f, 0.0f, 0.0f, 1.0f}));
600 EXPECT_M4_NEAR(ortho, expect, 1
e-5);
603 {0.0f, -0.666667f, 0.333333f, 0.0f},
604 {0.0f, 0.0f, -2.33333f, 0.666667f},
605 {0.0f, 0.0f, -1.0f, 0.0f}));
606 EXPECT_M4_NEAR(pers1, expect, 1
e-5);
609 {0.0f, 3.33333f, 0.333333f, 0.0f},
610 {0.0f, 0.0f, -2.33333f, 0.666667f},
611 {0.0f, 0.0f, -1.0f, 0.0f}));
612 EXPECT_M4_NEAR(pers2, expect, 1
e-5);
615TEST(math_matrix, ToQuaternionSafe)
618 mat[0] = {0.493316412f, -0.0f, 0.869849861f};
619 mat[1] = {-0.0f, 1.0f, 0.0f};
620 mat[2] = {-0.0176299568f, -0.0f, 0.999844611f};
623 expect[0] = {0.493316f, 0.000000f, 0.869850f};
624 expect[1] = {-0.000000f, 1.000000f, 0.000000f};
625 expect[2] = {-0.869850f, -0.000000f, 0.493316f};
638 EXPECT_NEAR(
math::length(transformed_normals[
i]), 1.0f, 1e-6f);
645 EXPECT_V3_NEAR(transformed_normals[
i], transformed_then_normalized, 1e-6f);
649TEST(math_matrix, TransformNormals)
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
void interp_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4], float t)
void unit_m3(float m[3][3])
void zero_m3(float m[3][3])
#define mul_m4_series(...)
void interp_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3], float t)
float determinant_m3_array(const float m[3][3])
void transpose_m3(float R[3][3])
#define mul_m3_series(...)
void pseudoinverse_m4_m4(float inverse[4][4], const float mat[4][4], float epsilon)
void transpose_m4(float R[4][4])
void unit_m4(float m[4][4])
TEST(math_matrix, interp_m4_m4m4_regular)
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
btMatrix3x3 adjoint() const
Return the adjoint of the matrix.
btScalar determinant() const
Return the determinant of the matrix.
IndexRange index_range() const
static float normals[][3]
VecBase< float, D > normalize(VecOp< float, D >) RET
MatBase< R, C > transpose(MatBase< C, R >) RET
MatBase< T, 4, 4 > perspective(T left, T right, T bottom, T top, T near_clip, T far_clip)
Create a perspective projection matrix using OpenGL coordinate convention: Maps each axis range to [-...
AngleRadianBase< float > AngleRadian
QuaternionBase< float > Quaternion
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
QuaternionBase< T > to_quaternion(const AxisAngleBase< T, AngleT > &axis_angle)
bool is_negative(const MatBase< T, 3, 3 > &mat)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
bool is_orthonormal(const MatT &mat)
Quaternion to_quaternion_legacy(const float3x3 &mat)
MatT from_up_axis(const VectorT up)
T length(const VecBase< T, Size > &a)
MatT from_loc_rot(const typename MatT::loc_type &location, const RotationT &rotation)
AxisAngleBase< float, AngleRadianBase< float > > AxisAngle
bool is_uniformly_scaled(const MatT &mat)
bool is_unit_scale(const MatBase< T, NumCol, NumRow > &m)
MatBase< T, Size, Size > pseudo_invert(const MatBase< T, Size, Size > &mat, T epsilon=1e-8)
EulerXYZBase< float > EulerXYZ
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
CartesianBasis invert(const CartesianBasis &basis)
DualQuaternionBase< float > DualQuaternion
VectorT project_point(const MatT &mat, const VectorT &point)
MatT from_scale(const VecBase< typename MatT::base_type, ScaleDim > &scale)
T interpolate(const T &a, const T &b, const FactorT &t)
void transform_normals(const float3x3 &transform, MutableSpan< float3 > normals)
EulerXYZBase< T > to_nearest_euler(const MatBase< T, 3, 3 > &mat, const EulerXYZBase< T > &reference)
MatBase< T, 3, 3 > interpolate_fast(const MatBase< T, 3, 3 > &a, const MatBase< T, 3, 3 > &b, T t)
MatBase< T, NumCol, NumRow > translate(const MatBase< T, NumCol, NumRow > &mat, const VectorT &translation)
QuaternionBase< T > normalized_to_quaternion_safe(const MatBase< T, 3, 3 > &mat)
MatBase< T, NumCol, NumRow > normalize_and_get_size(const MatBase< T, NumCol, NumRow > &a, VectorT &r_size)
AxisAngleBase< T, AngleT > to_axis_angle(const EulerXYZBase< T > &euler)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > to_scale(const MatBase< T, NumCol, NumRow > &mat)
bool is_equal(const MatBase< T, NumCol, NumRow > &a, const MatBase< T, NumCol, NumRow > &b, const T epsilon=T(0))
void to_rot_scale(const MatBase< T, 2, 2 > &mat, AngleRadianBase< T > &r_rotation, VecBase< T, 2 > &r_scale)
Euler3Base< float > Euler3
MatT from_location(const typename MatT::loc_type &location)
void to_loc_rot_scale(const MatBase< T, 3, 3 > &mat, VecBase< T, 2 > &r_location, AngleRadianBase< T > &r_rotation, VecBase< T, 2 > &r_scale)
VecBase< T, 3 > transform_direction(const MatBase< T, 3, 3 > &mat, const VecBase< T, 3 > &direction)
MatT from_rot_scale(const RotationT &rotation, const VectorT &scale)
MatBase< T, NumCol, NumRow > rotate(const MatBase< T, NumCol, NumRow > &mat, const RotationT &rotation)
MatT from_rotation(const RotationT &rotation)
Euler3Base< T > to_euler(const AxisAngleBase< T, AngleT > &axis_angle, EulerOrder order)
MatT from_loc_rot_scale(const typename MatT::loc_type &location, const RotationT &rotation, const VecBase< typename MatT::base_type, ScaleDim > &scale)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
bool is_orthogonal(const MatT &mat)
static void transform_normals_test(const float3x3 &transform, const Span< float3 > normals)
MatBase< float, 2, 2 > float2x2
MatBase< float, 4, 4 > float4x4
MatBase< double, 3, 3 > double3x3
VecBase< float, 4 > float4
VecBase< float, 2 > float2
MatBase< double, 2, 2 > double2x2
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
MatBase< double, 4, 4 > double4x4
static MatBase diagonal(float value)
const c_style_mat & ptr() const
static MatBase all(float value)
static MatBase identity()