mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 04:31:06 +00:00
gl/utils: Fix NDC conversion matrices for column-majorness
The matrices were converting the wrong values with non-diagonal-only matrices. e.g. a typical yflip matrix in [-1,1]^3 such as 1 0 0 0 0 -1 0 0 0 0 1 0 0 0 0 1 Would have actually required a matrix like this in [0,1]^3 1 0 0 0 0 -1 0 0 0 0 1 0 0 -2 0 1 Which is 1. not consistent with our multiplication convention and would require transposing matrices or changing our multiplication order (from what is generally used on opengl matrix guides/tutorials). 2. Produces incorrect values when input with actual vertices accounting for the difference in multiplication order. e.g. some vertices multiplied by the yflip matrix using vertex * yflip(== transpose(yflip) * vertex): vertex: -> result: expected: vec4(1,0,1,1) -> vec4(1,-2,1,1) vec4(1,1,1,1) vec4(1,1,1,1) -> vec4(1,-3,1,1) vec4(1,0,1,1) With the updated values, we now get the expected values. Includes a test for this behaviour and the example above
This commit is contained in:
parent
a7e8f16df3
commit
e4bf9ed8f0
3 changed files with 130 additions and 49 deletions
|
@ -115,17 +115,17 @@ static const gfloat identity_matrix[] = {
|
|||
};
|
||||
|
||||
static const gfloat from_ndc_matrix[] = {
|
||||
0.5, 0.0, 0.0, 0.0,
|
||||
0.0, 0.5, 0.0, 0.0,
|
||||
0.0, 0.0, 0.5, 0.0,
|
||||
0.5, 0.5, 0.5, 1.0,
|
||||
0.5, 0.0, 0.0, 0.5,
|
||||
0.0, 0.5, 0.0, 0.5,
|
||||
0.0, 0.0, 0.5, 0.5,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
};
|
||||
|
||||
static const gfloat to_ndc_matrix[] = {
|
||||
2.0, 0.0, 0.0, 0.0,
|
||||
0.0, 2.0, 0.0, 0.0,
|
||||
0.0, 0.0, 2.0, 0.0,
|
||||
-1.0, -1.0, -1.0, 1.0,
|
||||
2.0, 0.0, 0.0, -1.0,
|
||||
0.0, 2.0, 0.0, -1.0,
|
||||
0.0, 0.0, 2.0, -1.0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
@ -793,17 +793,17 @@ static const gfloat identity_matrix[] = {
|
|||
};
|
||||
|
||||
static const gfloat from_ndc_matrix[] = {
|
||||
0.5, 0.0, 0.0, 0.0,
|
||||
0.0, 0.5, 0.0, 0.0,
|
||||
0.0, 0.0, 0.5, 0.0,
|
||||
0.5, 0.5, 0.5, 1.0,
|
||||
0.5, 0.0, 0.0, 0.5,
|
||||
0.0, 0.5, 0.0, 0.5,
|
||||
0.0, 0.0, 0.5, 0.5,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
};
|
||||
|
||||
static const gfloat to_ndc_matrix[] = {
|
||||
2.0, 0.0, 0.0, 0.0,
|
||||
0.0, 2.0, 0.0, 0.0,
|
||||
0.0, 0.0, 2.0, 0.0,
|
||||
-1.0, -1.0, -1.0, 1.0,
|
||||
2.0, 0.0, 0.0, -1.0,
|
||||
0.0, 2.0, 0.0, -1.0,
|
||||
0.0, 0.0, 2.0, -1.0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
};
|
||||
|
||||
/* multiplies two 4x4 matrices, @a X @b, and stores the result in @result
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#undef GST_CAT_DEFAULT
|
||||
#include <gst/check/gstcheck.h>
|
||||
|
||||
#define VEC4_FORMAT "10.4f %10.4f %10.4f %10.4f"
|
||||
#define VEC4_ARGS(v) (v)[0], (v)[1], (v)[2], (v)[3]
|
||||
#define EPSILON 0.0001f
|
||||
#define FEQ(a,b) (fabs(a-b) < EPSILON)
|
||||
|
||||
|
@ -34,8 +36,7 @@ debug_matrix (const float *m)
|
|||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
GST_DEBUG ("%10.4f %10.4f %10.4f %10.4f", m[i * 4 + 0], m[i * 4 + 1],
|
||||
m[i * 4 + 2], m[i * 4 + 3]);
|
||||
GST_DEBUG ("%" VEC4_FORMAT, VEC4_ARGS (&m[i * 4]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,7 +68,13 @@ GST_START_TEST (test_matrix_multiply)
|
|||
int i;
|
||||
|
||||
gst_gl_multiply_matrix4 (A, B, res);
|
||||
GST_DEBUG ("result");
|
||||
GST_DEBUG ("Matrix A:");
|
||||
debug_matrix (A);
|
||||
GST_DEBUG ("Matrix B:");
|
||||
debug_matrix (B);
|
||||
GST_DEBUG ("Matrix C:");
|
||||
debug_matrix (C);
|
||||
GST_DEBUG ("Multiplication Result == C == A * B:");
|
||||
debug_matrix (res);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (res); i++) {
|
||||
|
@ -103,7 +110,7 @@ GST_START_TEST (test_matrix_ndc)
|
|||
|
||||
/* test default identity matrix */
|
||||
gst_gl_get_affine_transformation_meta_as_ndc (aff_meta, res);
|
||||
GST_DEBUG ("result");
|
||||
GST_DEBUG ("Default matrix in the affine meta:");
|
||||
debug_matrix (res);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (res); i++) {
|
||||
|
@ -112,10 +119,13 @@ GST_START_TEST (test_matrix_ndc)
|
|||
}
|
||||
|
||||
/* test setting and receiving the same values */
|
||||
GST_DEBUG ("Set matrix on the affine transformation meta:");
|
||||
debug_matrix (n);
|
||||
|
||||
gst_gl_set_affine_transformation_meta_from_ndc (aff_meta, n);
|
||||
gst_gl_get_affine_transformation_meta_as_ndc (aff_meta, res);
|
||||
|
||||
GST_DEBUG ("result");
|
||||
GST_DEBUG ("Retrieve the matrix set on the affine meta:");
|
||||
debug_matrix (res);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (res); i++) {
|
||||
|
@ -145,7 +155,7 @@ transpose_matrix4 (float *m, float *res)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
static float
|
||||
dot4 (float *v1, float *v2)
|
||||
{
|
||||
|
@ -164,16 +174,21 @@ _matrix_mult_vertex4 (float *m, float *v, float *res)
|
|||
res[3] = dot4 (&m[12], v);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* v * m */
|
||||
/* Not the prevailing multiplication convention and not really used in
|
||||
* GStreamer. Kept around for extra testing */
|
||||
static void
|
||||
_vertex_mult_matrix4 (float *v, float *m, float *res)
|
||||
{
|
||||
float tmp[16] = { 0., };
|
||||
|
||||
transpose_matrix4 (m, tmp);
|
||||
GST_TRACE ("transposed matrix");
|
||||
debug_matrix (tmp);
|
||||
_matrix_mult_vertex4 (tmp, v, res);
|
||||
}
|
||||
|
||||
#endif
|
||||
GST_START_TEST (test_matrix_vertex_identity)
|
||||
{
|
||||
float identity[] = {
|
||||
|
@ -187,18 +202,9 @@ GST_START_TEST (test_matrix_vertex_identity)
|
|||
float res[4] = { 0., };
|
||||
int i;
|
||||
|
||||
_vertex_mult_matrix4 (v, identity, res);
|
||||
GST_DEBUG ("vertex: %.4f %.4f %.4f %.4f", v[0], v[1], v[2], v[3]);
|
||||
GST_DEBUG ("result: %.4f %.4f %.4f %.4f", res[0], res[1], res[2], res[3]);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
fail_unless (FEQ (res[i], v[i]), "value %f at index %u does not match "
|
||||
"expected value %f", res[i], i, v[i]);
|
||||
}
|
||||
|
||||
_matrix_mult_vertex4 (identity, v, res);
|
||||
GST_DEBUG ("vertex: %.4f %.4f %.4f %.4f", v[0], v[1], v[2], v[3]);
|
||||
GST_DEBUG ("result: %.4f %.4f %.4f %.4f", res[0], res[1], res[2], res[3]);
|
||||
GST_DEBUG ("vertex: %" VEC4_FORMAT, VEC4_ARGS (v));
|
||||
GST_DEBUG ("result: %" VEC4_FORMAT, VEC4_ARGS (res));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
fail_unless (FEQ (res[i], v[i]), "value %f at index %u does not match "
|
||||
|
@ -222,19 +228,92 @@ GST_START_TEST (test_matrix_vertex_scale)
|
|||
float res[4] = { 0., };
|
||||
int i;
|
||||
|
||||
_vertex_mult_matrix4 (v, scale, res);
|
||||
GST_DEBUG ("vertex: %.4f %.4f %.4f %.4f", v[0], v[1], v[2], v[3]);
|
||||
GST_DEBUG ("result: %.4f %.4f %.4f %.4f", res[0], res[1], res[2], res[3]);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
fail_unless (FEQ (res[i], expected[i]),
|
||||
"value %f at index %u does not match " "expected value %f", res[i], i,
|
||||
expected[i]);
|
||||
}
|
||||
|
||||
_matrix_mult_vertex4 (scale, v, res);
|
||||
GST_DEBUG ("vertex: %.4f %.4f %.4f %.4f", v[0], v[1], v[2], v[3]);
|
||||
GST_DEBUG ("result: %.4f %.4f %.4f %.4f", res[0], res[1], res[2], res[3]);
|
||||
GST_DEBUG ("vertex: %" VEC4_FORMAT, VEC4_ARGS (v));
|
||||
GST_DEBUG ("result: %" VEC4_FORMAT, VEC4_ARGS (res));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
fail_unless (FEQ (res[i], expected[i]),
|
||||
"value %f at index %u does not match " "expected value %f", res[i], i,
|
||||
expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
GST_START_TEST (test_matrix_vertex_y_invert)
|
||||
{
|
||||
float y_invert[] = {
|
||||
1., 0., 0., 0.,
|
||||
0., -1., 0., 0.,
|
||||
0., 0., 1., 0.,
|
||||
0., 0., 0., 1.,
|
||||
};
|
||||
|
||||
/* These two matrices are copied from
|
||||
* gst_gl_set_affine_transformation_meta_from_ndc{,_ext}() gstglutils.c
|
||||
* in ext/gl and gst-libs/gst/gl */
|
||||
static const gfloat from_ndc_matrix[] = {
|
||||
0.5, 0.0, 0.0, 0.5,
|
||||
0.0, 0.5, 0.0, 0.5,
|
||||
0.0, 0.0, 0.5, 0.5,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
};
|
||||
|
||||
static const gfloat to_ndc_matrix[] = {
|
||||
2.0, 0.0, 0.0, -1.0,
|
||||
0.0, 2.0, 0.0, -1.0,
|
||||
0.0, 0.0, 2.0, -1.0,
|
||||
0.0, 0.0, 0.0, 1.0,
|
||||
};
|
||||
|
||||
float v[] = { 1., 1., 1., 1. };
|
||||
float expected[] = { 1., -1., 1., 1. };
|
||||
float res[4] = { 0., };
|
||||
int i;
|
||||
|
||||
/* The y_invert matrix but with a coordinate space of [0, 1]^3 instead
|
||||
* of [-1, 1]^3 */
|
||||
float y_invert_0_1[16] = { 0., };
|
||||
float m1[16] = { 0., };
|
||||
|
||||
GST_DEBUG ("y-invert");
|
||||
debug_matrix (y_invert);
|
||||
|
||||
_matrix_mult_vertex4 (y_invert, v, res);
|
||||
GST_DEBUG ("vertex: %" VEC4_FORMAT, VEC4_ARGS (v));
|
||||
GST_DEBUG ("result: %" VEC4_FORMAT, VEC4_ARGS (res));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
fail_unless (FEQ (res[i], expected[i]),
|
||||
"value %f at index %u does not match " "expected value %f", res[i], i,
|
||||
expected[i]);
|
||||
}
|
||||
|
||||
/* now test the [0, 1]^3 matrix and update the test values acoordingly */
|
||||
expected[1] = 0.;
|
||||
gst_gl_multiply_matrix4 (from_ndc_matrix, y_invert, m1);
|
||||
gst_gl_multiply_matrix4 (m1, to_ndc_matrix, y_invert_0_1);
|
||||
|
||||
GST_DEBUG ("y-invert from ndc [-1,1]^3 to [0,1]^3");
|
||||
debug_matrix (y_invert_0_1);
|
||||
|
||||
_matrix_mult_vertex4 (y_invert_0_1, v, res);
|
||||
GST_DEBUG ("vertex: %" VEC4_FORMAT, VEC4_ARGS (v));
|
||||
GST_DEBUG ("result: %" VEC4_FORMAT, VEC4_ARGS (res));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
fail_unless (FEQ (res[i], expected[i]),
|
||||
"value %f at index %u does not match " "expected value %f", res[i], i,
|
||||
expected[i]);
|
||||
}
|
||||
|
||||
/* test vec4(1,0,1,1) -> vec4(1,1,1,1) */
|
||||
v[1] = 0.;
|
||||
expected[1] = 1.;
|
||||
_matrix_mult_vertex4 (y_invert_0_1, v, res);
|
||||
GST_DEBUG ("vertex: %" VEC4_FORMAT, VEC4_ARGS (v));
|
||||
GST_DEBUG ("result: %" VEC4_FORMAT, VEC4_ARGS (res));
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
fail_unless (FEQ (res[i], expected[i]),
|
||||
|
@ -244,10 +323,9 @@ GST_START_TEST (test_matrix_vertex_scale)
|
|||
}
|
||||
|
||||
GST_END_TEST;
|
||||
#endif
|
||||
|
||||
static Suite *
|
||||
gst_gl_upload_suite (void)
|
||||
gst_gl_matrix_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("GstGLMatrix");
|
||||
TCase *tc_chain = tcase_create ("matrix");
|
||||
|
@ -255,8 +333,11 @@ gst_gl_upload_suite (void)
|
|||
suite_add_tcase (s, tc_chain);
|
||||
tcase_add_test (tc_chain, test_matrix_multiply);
|
||||
tcase_add_test (tc_chain, test_matrix_ndc);
|
||||
tcase_add_test (tc_chain, test_matrix_vertex_identity);
|
||||
tcase_add_test (tc_chain, test_matrix_vertex_scale);
|
||||
tcase_add_test (tc_chain, test_matrix_vertex_y_invert);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (gst_gl_upload);
|
||||
GST_CHECK_MAIN (gst_gl_matrix);
|
||||
|
|
Loading…
Reference in a new issue