5#include "testing/testing.h"
12TEST(math_matrix, interp_m4_m4m4_regular)
18 float matrix_a[4][4] = {
19 {0.224976f, -0.333770f, 0.765074f, 0.100000f},
20 {0.389669f, 0.647565f, 0.168130f, 0.200000f},
21 {-0.536231f, 0.330541f, 0.443163f, 0.300000f},
22 {0.000000f, 0.000000f, 0.000000f, 1.000000f},
30 const float epsilon = 1
e-6;
32 EXPECT_M4_NEAR(result, matrix_i, epsilon);
35 EXPECT_M4_NEAR(result, matrix_a, epsilon);
39 float matrix_halfway[4][4] = {
40 {0.690643f, -0.253244f, 0.484996f, 0.050000f},
41 {0.271924f, 0.852623f, 0.012348f, 0.100000f},
42 {-0.414209f, 0.137484f, 0.816778f, 0.150000f},
43 {0.000000f, 0.000000f, 0.000000f, 1.000000f},
48 EXPECT_M4_NEAR(result, matrix_halfway, epsilon);
51TEST(math_matrix, interp_m3_m3m3_singularity)
62 float matrix_a[3][3] = {
63 {-0.990737f, -0.098227f, 0.093759f},
64 {-0.104131f, 0.992735f, -0.060286f},
65 {0.087156f, 0.069491f, 0.993768f},
71 float matrix_b[3][3] = {
80 EXPECT_M3_NEAR(result, matrix_a, 1
e-5);
83 EXPECT_M3_NEAR(result, matrix_b, 1
e-5);
86 float expect[3][3] = {
87 {-0.997681f, -0.049995f, 0.046186f},
88 {-0.051473f, 0.998181f, -0.031385f},
89 {0.044533f, 0.033689f, 0.998440f},
92 EXPECT_M3_NEAR(result, expect, 1
e-5);
103 EXPECT_M3_NEAR(result, expect, 1
e-5);
108 float matrix[3][3] = {
114 float const expect[3][3] = {
117 {0.0f, 0.0f, 125.0f},
119 EXPECT_M3_NEAR(matrix, expect, 1
e-5);
124 float matrix[4][4] = {
125 {2.0f, 0.0f, 0.0f, 0.0f},
126 {0.0f, 3.0f, 0.0f, 0.0f},
127 {0.0f, 0.0f, 5.0f, 0.0f},
128 {0.0f, 0.0f, 0.0f, 7.0f},
131 float const expect[4][4] = {
132 {8.0f, 0.0f, 0.0f, 0.0f},
133 {0.0f, 27.0f, 0.0f, 0.0f},
134 {0.0f, 0.0f, 125.0f, 0.0f},
135 {0.0f, 0.0f, 0.0f, 343.0f},
137 EXPECT_M4_NEAR(matrix, expect, 1
e-5);
144TEST(math_matrix, MatrixInverse)
148 float3x3 expect =
float3x3({0.5f, 0.0f, 0.0f}, {0.0f, 0.5f, 0.0f}, {0.0f, 0.0f, 0.5f});
149 EXPECT_M3_NEAR(inv, expect, 1e-5f);
155 EXPECT_M3_NEAR(inv2, expect2, 1e-5f);
156 EXPECT_FALSE(success);
159TEST(math_matrix, MatrixPseudoInverse)
162 {0.389669f, 0.647565f, 0.168130f, 0.200000f},
163 {-0.536231f, 0.330541f, 0.443163f, 0.300000f},
164 {0.000000f, 0.000000f, 0.000000f, 1.000000f}));
166 {0.389669f, 0.647565f, 0.168130f, 0.200000f},
167 {-0.536231f, 0.330541f, 0.443163f, 0.300000f},
168 {0.000000f, 0.000000f, 0.000000f, 1.000000f}));
173 EXPECT_M4_NEAR(inv, expect, 1e-5f);
176 {0.000000f, 0.647565f, 0.168130f, 0.200000f},
177 {0.000000f, 0.330541f, 0.443163f, 0.300000f},
178 {0.000000f, 0.000000f, 0.000000f, 1.000000f}));
180 {-0.51311f, 1.02638f, 0.496437f, -0.302896f},
181 {0.952803f, 0.221885f, 0.527413f, -0.297881f},
182 {-0.0275438f, -0.0477073f, 0.0656508f, 0.9926f}));
186 EXPECT_M4_NEAR(inv2, expect2, 1e-5f);
189TEST(math_matrix, MatrixDeterminant)
192 float3x3 m3({1, 2, 3}, {-3, 4, -5}, {5, -6, 7});
193 float4x4 m4({1, 2, -3, 3}, {3, 4, -5, 3}, {5, 6, 7, -3}, {5, 6, 7, 1});
202TEST(math_matrix, MatrixAdjoint)
205 float3x3 m3({1, 2, 3}, {-3, 4, -5}, {5, -6, 7});
206 float4x4 m4({1, 2, -3, 3}, {3, 4, -5, 3}, {5, 6, 7, -3}, {5, 6, 7, 1});
210 float4x4({232, -184, -8, -0}, {-128, 88, 16, 0}, {80, -76, 4, 28}, {-72, 60, -12, -28}));
211 EXPECT_M2_NEAR(
adjoint(m2), expect2, 1e-8f);
212 EXPECT_M3_NEAR(
adjoint(m3), expect3, 1e-8f);
213 EXPECT_M4_NEAR(
adjoint(m4), expect4, 1e-8f);
218 float4x4 m({1, 2, 3, 4}, {5, 6, 7, 8}, {9, 1, 2, 3}, {4, 5, 6, 7});
231 expect =
float4x4({1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {1, 2, 3, 1});
232 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
235 {-0.0587266, -0.426918, 0.902382, 0},
236 {-0.909297, -0.350175, -0.224845, 0},
242 EXPECT_M3_NEAR(m, expect, 1
e-5);
244 EXPECT_M3_NEAR(m, expect, 1
e-5);
246 EXPECT_M3_NEAR(m, expect, 1
e-5);
249 {-0.117453, -0.853835, 1.80476, 5.44925},
250 {-1.81859, -0.700351, -0.44969, -0.330972},
254 EXPECT_M3_NEAR(m, expect, 1
e-5);
257 expect =
float4x4({1, 0, 0, 0}, {0, 2, 0, 0}, {0, 0, 3, 0}, {0, 0, 0, 4});
258 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
261 expect =
float4x4({1, 0, 0, 0}, {0, 2, 0, 0}, {0, 0, 3, 0}, {0, 0, 0, 1});
262 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
265 expect =
float4x4({1, 0, 0, 0}, {0, 2, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1});
266 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
269 expect =
float4x4({0.411982, -0.0587266, -0.909297, 0},
270 {-0.833738, -0.426918, -0.350175, 0},
271 {-0.36763, 0.902382, -0.224845, 0},
273 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
276 expect =
float4x4({0.411982, -0.0587266, -0.909297, 0},
277 {-1.66748, -0.853835, -0.700351, 0},
278 {-1.10289, 2.70714, -0.674535, 0},
280 EXPECT_TRUE(
is_equal(m, expect, 0.00001f));
294 const float epsilon = 1
e-6;
296 float4x4 m1 =
float4x4({0, 3, 0, 0}, {2, 0, 0, 0}, {0, 0, 2, 0}, {0, 0, 0, 1});
298 expect =
float4x4({0, 3, 0, 0}, {2, 0, 0, 0}, {0, 0, 2, 0}, {4, 9, 2, 1});
300 EXPECT_M4_NEAR(result, expect, epsilon);
302 expect =
float4x4({0, 3, 0, 0}, {2, 0, 0, 0}, {0, 0, 2, 0}, {4, 0, 0, 1});
304 EXPECT_M4_NEAR(result, expect, epsilon);
306 expect =
float4x4({0, 0, -2, 0}, {2, 0, 0, 0}, {0, 3, 0, 0}, {0, 0, 0, 1});
308 EXPECT_M4_NEAR(result, expect, epsilon);
310 expect =
float4x4({0, 9, 0, 0}, {4, 0, 0, 0}, {0, 0, 8, 0}, {0, 0, 0, 1});
312 EXPECT_M4_NEAR(result, expect, epsilon);
314 expect =
float4x4({0, 9, 0, 0}, {4, 0, 0, 0}, {0, 0, 2, 0}, {0, 0, 0, 1});
316 EXPECT_M4_NEAR(result, expect, epsilon);
319TEST(math_matrix, MatrixCompareTest)
321 float4x4 m1 =
float4x4({0, 3, 0, 0}, {2, 0, 0, 0}, {0, 0, 2, 0}, {0, 0, 0, 1});
322 float4x4 m2 =
float4x4({0, 3.001, 0, 0}, {1.999, 0, 0, 0}, {0, 0, 2.001, 0}, {0, 0, 0, 1.001});
323 float4x4 m3 =
float4x4({0, 3.001, 0, 0}, {1, 1, 0, 0}, {0, 0, 2.001, 0}, {0, 0, 0, 1.001});
324 float4x4 m4 =
float4x4({0, 1, 0, 0}, {1, 0, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1});
325 float4x4 m5 =
float4x4({0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0});
326 float4x4 m6 =
float4x4({1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1});
327 EXPECT_TRUE(
is_equal(m1, m2, 0.01f));
328 EXPECT_FALSE(
is_equal(m1, m2, 0.0001f));
329 EXPECT_FALSE(
is_equal(m1, m3, 0.01f));
344TEST(math_matrix, MatrixMultiply)
349 {1.0, 2.0, 3.0, 4.0},
350 {5.0, 6.0, 7.0, 8.0},
351 {9.0, 10.0, 11.0, 12.0},
352 {13.0, 14.0, 15.0, 16.0},
355 {0.1f, 0.2f, 0.3f, 0.4f},
356 {0.5f, 0.6f, 0.7f, 0.8f},
357 {0.9f, 1.0f, 1.1f, 1.2f},
358 {1.3f, 1.4f, 1.5f, 1.6f},
362 {9.0f, 10.0f, 11.0f, 12.0f},
363 {20.2f, 22.8f, 25.4f, 28.0f},
364 {31.4f, 35.6f, 39.8f, 44.0f},
365 {42.6f, 48.4f, 54.2f, 60.0f},
368 const float4x4 result = matrix_a * matrix_b;
370 EXPECT_M4_NEAR(result, expected, 1e-5f);
374TEST(math_matrix, MatrixToNearestEuler)
379 float3x3 mat = {{0.808309, -0.578051, -0.111775},
380 {0.47251, 0.750174, -0.462572},
381 {0.351241, 0.321087, 0.879507}};
387TEST(math_matrix, MatrixMethods)
389 float4x4 m =
float4x4({0, 3, 0, 0}, {2, 0, 0, 0}, {0, 0, 2, 0}, {0, 1, 0, 1});
401 EXPECT_V4_NEAR(size, expect_size, 0.0002f);
414 EXPECT_V3_NEAR(scale, expect_scale, 0.00001f);
416 EXPECT_V3_NEAR(
float3(eul),
float3(expect_eul), 0.0002f);
421 EXPECT_V3_NEAR(scale, expect_scale, 0.00001f);
422 EXPECT_V3_NEAR(loc, expect_location, 0.00001f);
424 EXPECT_V3_NEAR(
float3(eul),
float3(expect_eul), 0.0002f);
427TEST(math_matrix, Transformation2DMatrixDecomposition)
436 float2 decomposed_translation, decomposed_scale;
437 to_loc_rot_scale(transformation, decomposed_translation, decomposed_rotation, decomposed_scale);
439 EXPECT_V2_NEAR(decomposed_translation, translation, 0.00001f);
440 EXPECT_V2_NEAR(decomposed_scale, scale, 0.00001f);
441 EXPECT_NEAR(decomposed_rotation.
radian(), rotation.radian(), 0.00001f);
444TEST(math_matrix, MatrixToQuaternionLegacy)
446 float3x3 mat = {{0.808309, -0.578051, -0.111775},
447 {0.47251, 0.750174, -0.462572},
448 {0.351241, 0.321087, 0.879507}};
451 float4(0.927091f, -0.211322f, 0.124857f, -0.283295f),
455TEST(math_matrix, MatrixTranspose)
457 float4x4 m({1, 2, 3, 4}, {5, 6, 7, 8}, {9, 1, 2, 3}, {2, 5, 6, 7});
458 float4x4 expect({1, 5, 9, 2}, {2, 6, 1, 5}, {3, 7, 2, 6}, {4, 8, 3, 7});
462TEST(math_matrix, MatrixInterpolationRegular)
469 {0.389669f, 0.647565f, 0.168130f, 0.200000f},
470 {-0.536231f, 0.330541f, 0.443163f, 0.300000f},
471 {0.000000f, 0.000000f, 0.000000f, 1.000000f}));
474 const float epsilon = 1
e-6;
476 EXPECT_M4_NEAR(result, m1, epsilon);
478 EXPECT_M4_NEAR(result, m2, epsilon);
483 {0.271924f, 0.852623f, 0.012348f, 0.100000f},
484 {-0.414209f, 0.137484f, 0.816778f, 0.150000f},
485 {0.000000f, 0.000000f, 0.000000f, 1.000000f}));
487 EXPECT_M4_NEAR(result, expect, epsilon);
490 EXPECT_M4_NEAR(result, expect, epsilon);
493TEST(math_matrix, MatrixInterpolationSingularity)
505 {-0.104131f, 0.992735f, -0.060286f},
506 {0.087156f, 0.069491f, 0.993768f}));
511 float3x3({-1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}));
514 EXPECT_M3_NEAR(result, matrix_a, 1
e-5);
517 EXPECT_M3_NEAR(result, matrix_b, 1
e-5);
522 {-0.051473f, 0.998181f, -0.031385f},
523 {0.044533f, 0.033689f, 0.998440f}));
524 EXPECT_M3_NEAR(result, expect, 1
e-5);
527 EXPECT_M3_NEAR(result, expect, 1
e-5);
537 EXPECT_M3_NEAR(result, expect, 1
e-5);
540TEST(math_matrix, MatrixTransform)
549 expect = {13, 2, -1};
551 EXPECT_V3_NEAR(result, expect, 1
e-2);
555 EXPECT_V3_NEAR(result, expect, 1
e-5);
558 EXPECT_V3_NEAR(result, expect, 1
e-5);
561 EXPECT_V3_NEAR(result, expect, 1
e-5);
563 expect = {-0.333333, -0.666666, -1.14814};
565 EXPECT_V3_NEAR(result, expect, 1
e-5);
567 float2 expect2 = {0.76923, 1.61538};
569 EXPECT_V2_NEAR(result2, expect2, 1
e-5);
572TEST(math_matrix, MatrixProjection)
574 using namespace math::projection;
576 float4x4 ortho = orthographic(-0.2f, 0.3f, -0.2f, 0.4f, -0.2f, -0.5f);
577 float4x4 pers1 = perspective(-0.2f, 0.3f, -0.2f, 0.4f, -0.2f, -0.5f);
582 {0.0f, 3.33333f, 0.0f, -0.333333f},
583 {0.0f, 0.0f, 6.66667f, -2.33333f},
584 {0.0f, 0.0f, 0.0f, 1.0f}));
585 EXPECT_M4_NEAR(ortho, expect, 1
e-5);
588 {0.0f, -0.666667f, 0.333333f, 0.0f},
589 {0.0f, 0.0f, -2.33333f, 0.666667f},
590 {0.0f, 0.0f, -1.0f, 0.0f}));
591 EXPECT_M4_NEAR(pers1, expect, 1
e-5);
594 {0.0f, 3.33333f, 0.333333f, 0.0f},
595 {0.0f, 0.0f, -2.33333f, 0.666667f},
596 {0.0f, 0.0f, -1.0f, 0.0f}));
597 EXPECT_M4_NEAR(pers2, expect, 1
e-5);
600TEST(math_matrix, ToQuaternionSafe)
603 mat[0] = {0.493316412f, -0.0f, 0.869849861f};
604 mat[1] = {-0.0f, 1.0f, 0.0f};
605 mat[2] = {-0.0176299568f, -0.0f, 0.999844611f};
608 expect[0] = {0.493316f, 0.000000f, 0.869850f};
609 expect[1] = {-0.000000f, 1.000000f, 0.000000f};
610 expect[2] = {-0.869850f, -0.000000f, 0.493316f};
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 unit_m4(float m[4][4])
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])
TEST(math_matrix, interp_m4_m4m4_regular)
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
btMatrix3x3 adjoint() const
Return the adjoint of the matrix.
btMatrix3x3 transpose() const
Return the transpose of the matrix.
btScalar determinant() const
Return the determinant of the matrix.
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
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
QuaternionBase< T > to_quaternion(const AxisAngleBase< T, AngleT > &axis_angle)
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)
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)
bool is_negative(const MatBase< T, Size, Size > &mat)
MatBase< T, Size, Size > pseudo_invert(const MatBase< T, Size, Size > &mat, T epsilon=1e-8)
EulerXYZBase< float > EulerXYZ
CartesianBasis invert(const CartesianBasis &basis)
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)
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)
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)
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)
TEST(any, DefaultConstructor)
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()