Skip to content

Commit

Permalink
matrix: Fix interpolation of perspective matrices
Browse files Browse the repository at this point in the history
The code was extracting the 3rd row as perspective, not the 3rd column.

A new test interpolate-perspective has been added.
  • Loading branch information
Benjamin Otte authored and ebassi committed Mar 5, 2019
1 parent 1158e5a commit 1cbd7b4
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 15 deletions.
27 changes: 12 additions & 15 deletions src/graphene-matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -1844,7 +1844,7 @@ matrix_decompose_3d (const graphene_matrix_t *m,
graphene_point3d_t *translate_r,
graphene_vec4_t *perspective_r)
{
graphene_matrix_t local, perspective;
graphene_matrix_t local;
float shear_xy, shear_xz, shear_yz;
float scale_x, scale_y, scale_z;
graphene_simd4f_t perspective_v;
Expand All @@ -1862,17 +1862,20 @@ matrix_decompose_3d (const graphene_matrix_t *m,
* but it also provides an easy way to test for singularity of
* the upper 3x3 component
*/
perspective = local;
perspective.value.w = graphene_simd4f_init (0.f, 0.f, 0.f, 1.f);

if (graphene_approx_val (graphene_matrix_determinant (&perspective), 0.f))
return false;

perspective_v = graphene_simd4f_init (graphene_simd4f_get_w (local.value.x),
graphene_simd4f_get_w (local.value.y),
graphene_simd4f_get_w (local.value.z),
graphene_simd4f_get_w (local.value.w));

/* Clear the perspective component */
local.value.x = graphene_simd4f_merge_w (local.value.x, 0.f);
local.value.y = graphene_simd4f_merge_w (local.value.y, 0.f);
local.value.z = graphene_simd4f_merge_w (local.value.z, 0.f);
local.value.w = graphene_simd4f_merge_w (local.value.w, 1.f);

if (graphene_approx_val (graphene_matrix_determinant (&local), 0.f))
return false;

/* isolate the perspective */
if (!graphene_simd4f_is_zero3 (perspective_v))
{
Expand All @@ -1886,14 +1889,8 @@ matrix_decompose_3d (const graphene_matrix_t *m,
* check if the matrix is invertible here because we just checked
* whether the determinant is not zero.
*/
graphene_matrix_inverse (&perspective, &tmp);
graphene_matrix_transpose_transform_vec4 (&tmp, perspective_r, perspective_r);

/* Clear the perspective component */
local.value.x = graphene_simd4f_merge_w (local.value.x, 0.f);
local.value.y = graphene_simd4f_merge_w (local.value.y, 0.f);
local.value.z = graphene_simd4f_merge_w (local.value.z, 0.f);
local.value.w = graphene_simd4f_merge_w (local.value.w, 1.f);
graphene_matrix_inverse (&local, &tmp);
graphene_matrix_transform_vec4 (&tmp, perspective_r, perspective_r);
}
else
graphene_vec4_init (perspective_r, 0.f, 0.f, 0.f, 1.f);
Expand Down
23 changes: 23 additions & 0 deletions src/tests/matrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,28 @@ GRAPHENE_TEST_UNIT_BEGIN (matrix_interpolate)
}
GRAPHENE_TEST_UNIT_END

GRAPHENE_TEST_UNIT_BEGIN (matrix_interpolate_perspective)
{
graphene_matrix_t m1, m2, m3, mr;

graphene_matrix_init_identity (&m1);
graphene_matrix_perspective (&m1, 200, &m1);
graphene_matrix_init_identity (&m2);
graphene_matrix_perspective (&m2, 800, &m2);

graphene_matrix_interpolate (&m1, &m2, 0.0, &mr);
graphene_assert_fuzzy_matrix_equal (&mr, &m1, 0.1);

graphene_matrix_interpolate (&m1, &m2, 1.0, &mr);
graphene_assert_fuzzy_matrix_equal (&mr, &m2, 0.1);

graphene_matrix_init_identity (&m3);
graphene_matrix_perspective (&m3, 400, &m3);
graphene_matrix_interpolate (&m1, &m2, 0.5, &mr);
graphene_assert_fuzzy_matrix_equal (&mr, &m3, 0.1);
}
GRAPHENE_TEST_UNIT_END

GRAPHENE_TEST_UNIT_BEGIN (matrix_multiply_self)
{
graphene_matrix_t a, b, res, test;
Expand Down Expand Up @@ -584,6 +606,7 @@ GRAPHENE_TEST_SUITE (
GRAPHENE_TEST_UNIT ("/matrix/look_at", matrix_look_at)
GRAPHENE_TEST_UNIT ("/matrix/invert", matrix_invert)
GRAPHENE_TEST_UNIT ("/matrix/interpolate", matrix_interpolate)
GRAPHENE_TEST_UNIT ("/matrix/interpolate-perspective", matrix_interpolate_perspective)
GRAPHENE_TEST_UNIT ("/matrix/multiply_self", matrix_multiply_self)
GRAPHENE_TEST_UNIT ("/matrix/to-2d", matrix_to_2d)
GRAPHENE_TEST_UNIT ("/matrix/2d/identity", matrix_2d_identity)
Expand Down

0 comments on commit 1cbd7b4

Please sign in to comment.