From 420b60f203872d89e79be7f928733b35a5dee00d Mon Sep 17 00:00:00 2001 From: Simon Ser <contact@emersion.fr> Date: Mon, 27 Jan 2025 17:54:55 +0100 Subject: [PATCH] util/matrix: add matrix_invert() --- include/util/matrix.h | 7 +++++++ util/matrix.c | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/include/util/matrix.h b/include/util/matrix.h index 059a3bb1f..c45c99a06 100644 --- a/include/util/matrix.h +++ b/include/util/matrix.h @@ -39,4 +39,11 @@ void wlr_matrix_project_box(float mat[static 9], const struct wlr_box *box, void matrix_projection(float mat[static 9], int width, int height, enum wl_output_transform transform); +/** + * Compute the inverse of a matrix. + * + * The matrix needs to be inversible. + */ +void matrix_invert(float out[static 9], float m[static 9]); + #endif diff --git a/util/matrix.c b/util/matrix.c index 86b434c64..640787c95 100644 --- a/util/matrix.c +++ b/util/matrix.c @@ -1,3 +1,4 @@ +#include <assert.h> #include <string.h> #include <wayland-server-protocol.h> #include <wlr/util/box.h> @@ -139,3 +140,26 @@ void wlr_matrix_project_box(float mat[static 9], const struct wlr_box *box, wlr_matrix_multiply(mat, projection, mat); } + +void matrix_invert(float out[static 9], float m[static 9]) { + float a = m[0], b = m[1], c = m[2], d = m[3], e = m[4], f = m[5], g = m[6], h = m[7], i = m[8]; + + // See: https://en.wikipedia.org/wiki/Determinant + float det = a*e*i + b*f*g + c*d*h - c*e*g - b*d*i - a*f*h; + assert(det != 0); + float inv_det = 1 / det; + + // See: https://en.wikipedia.org/wiki/Invertible_matrix#Inversion_of_3_%C3%97_3_matrices + float result[] = { + inv_det * (e*i - f*h), + inv_det * -(b*i - c*h), + inv_det * (b*f - c*e), + inv_det * -(d*i - f*g), + inv_det * (a*i - c*g), + inv_det * -(a*f - c*d), + inv_det * (d*h - e*g), + inv_det * -(a*h - b*g), + inv_det * (a*e - b*d), + }; + memcpy(out, result, sizeof(result)); +}