diff --git a/include/cglm/affine2d-post.h b/include/cglm/affine2d-post.h new file mode 100644 index 0000000..c6605a8 --- /dev/null +++ b/include/cglm/affine2d-post.h @@ -0,0 +1,132 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#ifndef cglm_affine2d_post_h +#define cglm_affine2d_post_h + +/* + Functions: + CGLM_INLINE void glm_translated2d(mat3 m, vec2 v); + CGLM_INLINE void glm_translated2d_x(mat3 m, float to); + CGLM_INLINE void glm_translated2d_y(mat3 m, float to); + CGLM_INLINE void glm_rotated2d(mat3 m, float angle); + CGLM_INLINE void glm_scaled2d(mat3 m, vec2 v); + CGLM_INLINE void glm_scaled2d_uni(mat3 m, float s); + */ + +#include "vec2.h" + +/*! + * @brief translate existing transform matrix by v vector + * and store result in same matrix + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] v translate vector [x, y] + */ +CGLM_INLINE +void +glm_translated2d(mat3 m, vec2 v) { + glm_vec2_add(m[2], v, m[2]); +} + +/*! + * @brief translate existing transform matrix by x factor + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] x x factor + */ +CGLM_INLINE +void +glm_translated2d_x(mat3 m, float x) { + m[2][0] += x; +} + +/*! + * @brief translate existing transform matrix by y factor + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] y y factor + */ +CGLM_INLINE +void +glm_translated2d_y(mat3 m, float y) { + m[2][1] += y; +} + +/*! + * @brief rotate existing transform matrix by angle + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] angle angle (radians) + */ +CGLM_INLINE +void +glm_rotated2d(mat3 m, float angle) { + float c = cosf(angle), + s = sinf(angle), + + m00 = m[0][0], m10 = m[1][0], m20 = m[2][0], + m01 = m[0][1], m11 = m[1][1], m21 = m[2][1]; + + m[0][0] = c * m00 - s * m01; + m[1][0] = c * m10 - s * m11; + m[2][0] = c * m20 - s * m21; + + m[0][1] = s * m00 + c * m01; + m[1][1] = s * m10 + c * m11; + m[2][1] = s * m20 + c * m21; +} + +/*! + * @brief scale existing 2d transform matrix by v vector + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] v scale vector [x, y] + */ +CGLM_INLINE +void +glm_scaled2d(mat3 m, vec2 v) { + m[0][0] *= v[0]; + m[1][0] *= v[0]; + m[2][0] *= v[0]; + + m[0][1] *= v[1]; + m[1][1] *= v[1]; + m[2][1] *= v[1]; +} + +/*! + * @brief applies uniform scale to existing 2d transform matrix v = [s, s] + * + * this is POST transform, applies to existing transform as last transform + * + * @param[in, out] m affine transform + * @param[in] s scale factor + */ +CGLM_INLINE +void +glm_scaled2d_uni(mat3 m, float s) { + m[0][0] *= s; + m[1][0] *= s; + m[2][0] *= s; + + m[0][1] *= s; + m[1][1] *= s; + m[2][1] *= s; +} + +#endif /* cglm_affine2d_post_h */ diff --git a/include/cglm/cglm.h b/include/cglm/cglm.h index 146ded0..3532830 100644 --- a/include/cglm/cglm.h +++ b/include/cglm/cglm.h @@ -43,5 +43,6 @@ #include "bezier.h" #include "ray.h" #include "affine2d.h" +#include "affine2d-post.h" #endif /* cglm_h */ diff --git a/test/src/test_affine2d_post.h b/test/src/test_affine2d_post.h new file mode 100644 index 0000000..881270b --- /dev/null +++ b/test/src/test_affine2d_post.h @@ -0,0 +1,104 @@ +/* + * Copyright (c), Recep Aslantas. + * + * MIT License (MIT), http://opensource.org/licenses/MIT + * Full license can be found in the LICENSE file + */ + +#include "test_common.h" + +TEST_IMPL(GLM_PREFIX, translated2d) { + mat3 m1, m2, tmp; + vec2 v = { 1.2f, 3.4f }; + + test_rand_transform2d(m1); + glm_mat3_copy(m1, m2); + GLM(translated2d)(m2, v); + + glm_translate2d_make(tmp, v); + glm_mat3_mul(tmp, m1, m1); + + test_assert_mat3_eq(m1, m2); + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, translated2d_x) { + mat3 m1, m2, tmp; + float x = test_rand(); + + test_rand_transform2d(m1); + glm_mat3_copy(m1, m2); + GLM(translated2d_x)(m2, x); + + glm_translate2d_make(tmp, (vec2) { x, 0.0f }); + glm_mat3_mul(tmp, m1, m1); + + test_assert_mat3_eq(m1, m2); + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, translated2d_y) { + mat3 m1, m2, tmp; + float y = test_rand(); + + test_rand_transform2d(m1); + glm_mat3_copy(m1, m2); + GLM(translated2d_y)(m2, y); + + glm_translate2d_make(tmp, (vec2) { 0.0f, y }); + glm_mat3_mul(tmp, m1, m1); + + test_assert_mat3_eq(m1, m2); + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, rotated2d) { + mat3 m1, m2, tmp; + float a = test_rand(); + + test_rand_transform2d(m1); + glm_mat3_copy(m1, m2); + GLM(rotated2d)(m2, a); + + glm_rotate2d_make(tmp, a); + glm_mat3_mul(tmp, m1, m1); + + test_assert_mat3_eq(m1, m2); + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, scaled2d) { + mat3 m1, m2, tmp; + vec2 v = { test_rand(), test_rand() }; + + test_rand_transform2d(m1); + glm_mat3_copy(m1, m2); + GLM(scaled2d)(m2, v); + + glm_scale2d_make(tmp, v); + glm_mat3_mul(tmp, m1, m1); + + test_assert_mat3_eq(m1, m2); + + TEST_SUCCESS +} + +TEST_IMPL(GLM_PREFIX, scaled2d_uni) { + mat3 m1, m2, tmp; + float s = test_rand(); + + test_rand_transform2d(m1); + glm_mat3_copy(m1, m2); + GLM(scaled2d_uni)(m2, s); + + glm_scale2d_make(tmp, (vec2) { s, s }); + glm_mat3_mul(tmp, m1, m1); + + test_assert_mat3_eq(m1, m2); + + TEST_SUCCESS +} diff --git a/test/src/test_common.c b/test/src/test_common.c index a6c31c6..6f44c27 100644 --- a/test/src/test_common.c +++ b/test/src/test_common.c @@ -123,6 +123,13 @@ test_rand_mat2x4(mat2x4 dest) { dest[1][3] = drand48(); } +void +test_rand_transform2d(mat3 dest) { + glm_translate2d_make(dest, (vec2) { drand48(), drand48() }); + glm_rotate2d(dest, drand48()); + glm_scale2d(dest, (vec2) { drand48(), drand48() }); +} + void test_rand_vec3(vec3 dest) { dest[0] = drand48(); diff --git a/test/src/test_common.h b/test/src/test_common.h index 4fff040..7471dbb 100644 --- a/test/src/test_common.h +++ b/test/src/test_common.h @@ -41,6 +41,9 @@ test_rand_mat2x3(mat2x3 dest); void test_rand_mat2x4(mat2x4 dest); +void +test_rand_transform2d(mat3 dest); + test_status_t test_assert_eqf(float a, float b); diff --git a/test/src/tests.c b/test/src/tests.c index bc24668..297d309 100644 --- a/test/src/tests.c +++ b/test/src/tests.c @@ -33,6 +33,7 @@ #include "test_noise.h" #include "test_affine.h" #include "test_affine2d.h" +#include "test_affine2d_post.h" #include "test_affine_mat.h" #include "test_aabb2d.h" #include "test_ray.h" diff --git a/test/tests.h b/test/tests.h index b959ad6..effe137 100644 --- a/test/tests.h +++ b/test/tests.h @@ -97,6 +97,14 @@ TEST_DECLARE(glmc_rotate2d_make) TEST_DECLARE(glmc_rotate2d) TEST_DECLARE(glmc_rotate2d_to) +/* affine 2d post */ +TEST_DECLARE(glm_translated2d) +TEST_DECLARE(glm_translated2d_x) +TEST_DECLARE(glm_translated2d_y) +TEST_DECLARE(glm_rotated2d) +TEST_DECLARE(glm_scaled2d) +TEST_DECLARE(glm_scaled2d_uni) + /* aabb2d */ TEST_DECLARE(glm_aabb2d_sizev) @@ -1308,6 +1316,14 @@ TEST_LIST { TEST_ENTRY(glmc_rotate2d) TEST_ENTRY(glmc_rotate2d_to) + /* affine 2d post */ + TEST_ENTRY(glm_translated2d) + TEST_ENTRY(glm_translated2d_x) + TEST_ENTRY(glm_translated2d_y) + TEST_ENTRY(glm_rotated2d) + TEST_ENTRY(glm_scaled2d) + TEST_ENTRY(glm_scaled2d_uni) + /* aabb2d */ TEST_ENTRY(glm_aabb2d_sizev)