From f21acd3292669b601eb4fe2b979ef1a5f0f3e194 Mon Sep 17 00:00:00 2001 From: Jesper Lloyd Date: Sat, 14 Dec 2019 21:20:45 +0100 Subject: [PATCH] Add basic matrix transforms Add a row-major order 3x3 float transformation matrix and translation/reflection/rotation operations. --- Makefile.am | 2 ++ mypaint-matrix.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ mypaint-matrix.h | 32 +++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 mypaint-matrix.c create mode 100644 mypaint-matrix.h diff --git a/Makefile.am b/Makefile.am index 4fa1c011..359f2479 100644 --- a/Makefile.am +++ b/Makefile.am @@ -103,6 +103,7 @@ nobase_libmypaint_public_HEADERS = \ mypaint-config.h \ mypaint-glib-compat.h \ mypaint-mapping.h \ + mypaint-matrix.h \ $(MyPaint_introspectable_headers) LIBMYPAINT_SOURCES = \ @@ -116,6 +117,7 @@ LIBMYPAINT_SOURCES = \ mypaint-brush.c \ mypaint-brush-settings.c \ mypaint-fixed-tiled-surface.c \ + mypaint-matrix.c \ mypaint-rectangle.c \ mypaint-surface.c \ mypaint-tiled-surface.c \ diff --git a/mypaint-matrix.c b/mypaint-matrix.c new file mode 100644 index 00000000..3b370415 --- /dev/null +++ b/mypaint-matrix.c @@ -0,0 +1,92 @@ +/* libmypaint - The MyPaint Brush Library + * Copyright (C) 2019 The MyPaint Team + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "mypaint-matrix.h" +#include + +MyPaintTransform +mypaint_matrix_multiply(const MyPaintTransform m1, const MyPaintTransform m2) +{ + MyPaintTransform result; + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 3; ++col) { + result.rows[row][col] = + m1.rows[0][col] * m2.rows[row][0] + + m1.rows[1][col] * m2.rows[row][1] + + m1.rows[2][col] * m2.rows[row][2]; + } + } + return result; +} + +MyPaintTransform +mypaint_transform_unit() +{ + MyPaintTransform m = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}}; + return m; +} + +MyPaintTransform +mypaint_transform_rotate_cw(const MyPaintTransform transform, const float angle_radians) +{ + const float a = angle_radians; + MyPaintTransform factor = {{{cos(a), sin(a), 0}, {-sin(a), cos(a), 0}, {0, 0, 1}}}; + return mypaint_matrix_multiply(transform, factor); +} + +MyPaintTransform +mypaint_transform_rotate_ccw(const MyPaintTransform transform, const float angle_radians) +{ + const float a = angle_radians; + MyPaintTransform factor = {{ + {cos(a), -sin(a), 0}, + {sin(a), cos(a), 0}, + {0, 0, 1}, + }}; + return mypaint_matrix_multiply(transform, factor); +} + +MyPaintTransform +mypaint_transform_reflect(const MyPaintTransform transform, const float angle_radians) +{ + float x = cos(angle_radians); + float y = sin(angle_radians); + MyPaintTransform factor = {{ + {x * x - y * y, 2.0 * x * y, 0}, + {2.0 * x * y, y * y - x * x, 0}, + {0, 0, 1}, + }}; + return mypaint_matrix_multiply(transform, factor); +} + + +MyPaintTransform +mypaint_transform_translate(const MyPaintTransform transform, const float x, const float y) +{ + MyPaintTransform factor = {{ + {1, 0, x}, + {0, 1, y}, + {0, 0, 1}, + }}; + return mypaint_matrix_multiply(transform, factor); +} + +void +mypaint_transform_point(const MyPaintTransform* const t, float x, float y, float* xout, float* yout) +{ + *xout = t->rows[0][0] * x + t->rows[0][1] * y + t->rows[0][2]; + *yout = t->rows[1][0] * x + t->rows[1][1] * y + t->rows[1][2]; +} diff --git a/mypaint-matrix.h b/mypaint-matrix.h new file mode 100644 index 00000000..cd4c445b --- /dev/null +++ b/mypaint-matrix.h @@ -0,0 +1,32 @@ +#ifndef MYPAINTMATRIX_H +#define MYPAINTMATRIX_H + +/* libmypaint - The MyPaint Brush Library + * Copyright (C) 2019 The MyPaint Team + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +typedef struct { + float rows[3][3]; +} MyPaintTransform; + +MyPaintTransform mypaint_transform_unit(); +MyPaintTransform mypaint_transform_rotate_cw(const MyPaintTransform transform, const float angle_radians); +MyPaintTransform mypaint_transform_rotate_ccw(const MyPaintTransform transform, const float angle_radians); +MyPaintTransform mypaint_transform_reflect(const MyPaintTransform transform, const float angle_radians); +MyPaintTransform mypaint_transform_translate(const MyPaintTransform transform, const float x, const float y); + +void mypaint_transform_point(const MyPaintTransform* const t, float x, float y, float* x_out, float* y_out); + +#endif