From 43b36f1dc190de37d5f5007099528eb737a64cb9 Mon Sep 17 00:00:00 2001 From: Luigi Castelli Date: Fri, 23 Aug 2019 09:32:54 +0200 Subject: [PATCH 1/9] squared distance with SIMD support (#96) squared distance for vec4 --- include/cglm/call/vec4.h | 6 +++++- include/cglm/simd/arm.h | 6 ++++++ include/cglm/simd/x86.h | 6 ++++++ include/cglm/struct/vec3.h | 28 ++++++++++++++-------------- include/cglm/struct/vec4.h | 14 ++++++++++++++ include/cglm/vec3.h | 8 ++++---- include/cglm/vec4.h | 33 ++++++++++++++++++++++++++++----- src/vec3.c | 8 ++++---- src/vec4.c | 6 ++++++ 9 files changed, 87 insertions(+), 28 deletions(-) diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index 936bb52..38ed981 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -132,10 +132,14 @@ glmc_vec4_negate(vec4 v); CGLM_EXPORT void glmc_vec4_negate_to(vec4 v, vec4 dest); - + CGLM_EXPORT float glmc_vec4_distance(vec4 a, vec4 b); + +CGLM_EXPORT +float +glmc_vec4_distance2(vec4 a, vec4 b); CGLM_EXPORT void diff --git a/include/cglm/simd/arm.h b/include/cglm/simd/arm.h index 5412461..65dd3bb 100644 --- a/include/cglm/simd/arm.h +++ b/include/cglm/simd/arm.h @@ -37,5 +37,11 @@ glmm_norm(float32x4_t a) { return sqrtf(glmm_dot(a, a)); } +static inline +float +glmm_norm2(float32x4_t a) { + return glmm_dot(a, a); +} + #endif #endif /* cglm_simd_arm_h */ diff --git a/include/cglm/simd/x86.h b/include/cglm/simd/x86.h index 99d2b8a..2e0b7b5 100644 --- a/include/cglm/simd/x86.h +++ b/include/cglm/simd/x86.h @@ -113,6 +113,12 @@ glmm_norm(__m128 a) { return _mm_cvtss_f32(_mm_sqrt_ss(glmm_vhadds(_mm_mul_ps(a, a)))); } +static inline +float +glmm_norm2(__m128 a) { + return _mm_cvtss_f32(glmm_vhadds(_mm_mul_ps(a, a))); +} + static inline __m128 glmm_load3(float v[3]) { diff --git a/include/cglm/struct/vec3.h b/include/cglm/struct/vec3.h index 4e8d677..903ceea 100644 --- a/include/cglm/struct/vec3.h +++ b/include/cglm/struct/vec3.h @@ -45,13 +45,13 @@ CGLM_INLINE vec3s glms_vec3_normalize(vec3s v); CGLM_INLINE vec3s glms_vec3_cross(vec3s a, vec3s b); CGLM_INLINE vec3s glms_vec3_crossn(vec3s a, vec3s b); - CGLM_INLINE float glms_vec3_distance(vec3s a, vec3s b); CGLM_INLINE float glms_vec3_angle(vec3s a, vec3s b); CGLM_INLINE vec3s glms_vec3_rotate(vec3s v, float angle, vec3s axis); CGLM_INLINE vec3s glms_vec3_rotate_m4(mat4s m, vec3s v); CGLM_INLINE vec3s glms_vec3_rotate_m3(mat3s m, vec3s v); CGLM_INLINE vec3s glms_vec3_proj(vec3s a, vec3s b); CGLM_INLINE vec3s glms_vec3_center(vec3s a, vec3s b); + CGLM_INLINE float glms_vec3_distance(vec3s a, vec3s b); CGLM_INLINE float glms_vec3_distance2(vec3s a, vec3s b); CGLM_INLINE vec3s glms_vec3_maxv(vec3s a, vec3s b); CGLM_INLINE vec3s glms_vec3_minv(vec3s a, vec3s b); @@ -598,19 +598,6 @@ glms_vec3_center(vec3s a, vec3s b) { return r; } -/** - * @brief squared distance between two vectors - * - * @param[in] a vector1 - * @param[in] b vector2 - * @return squared distance (distance * distance) - */ -CGLM_INLINE -float -glms_vec3_distance2(vec3s a, vec3s b) { - return glm_vec3_distance2(a.raw, b.raw); -} - /** * @brief distance between two vectors * @@ -624,6 +611,19 @@ glms_vec3_distance(vec3s a, vec3s b) { return glm_vec3_distance(a.raw, b.raw); } +/** + * @brief squared distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return squared distance (distance * distance) + */ +CGLM_INLINE +float +glms_vec3_distance2(vec3s a, vec3s b) { + return glm_vec3_distance2(a.raw, b.raw); +} + /*! * @brief max values of vectors * diff --git a/include/cglm/struct/vec4.h b/include/cglm/struct/vec4.h index 0b403a9..55572b8 100644 --- a/include/cglm/struct/vec4.h +++ b/include/cglm/struct/vec4.h @@ -43,6 +43,7 @@ CGLM_INLINE vec4s glms_vec4_inv(vec4s v); CGLM_INLINE vec4s glms_vec4_normalize(vec4s v); CGLM_INLINE float glms_vec4_distance(vec4s a, vec4s b); + CGLM_INLINE float glms_vec4_distance2(vec4s a, vec4s b); CGLM_INLINE vec4s glms_vec4_maxv(vec4s a, vec4s b); CGLM_INLINE vec4s glms_vec4_minv(vec4s a, vec4s b); CGLM_INLINE vec4s glms_vec4_clamp(vec4s v, float minVal, float maxVal); @@ -501,6 +502,19 @@ glms_vec4_distance(vec4s a, vec4s b) { return glm_vec4_distance(a.raw, b.raw); } +/** + * @brief squared distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns squared distance + */ +CGLM_INLINE +float +glms_vec4_distance2(vec4s a, vec4s b) { + return glm_vec4_distance2(a.raw, b.raw); +} + /*! * @brief max values of vectors * diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 323618a..3c2e36e 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -48,13 +48,13 @@ CGLM_INLINE void glm_vec3_normalize_to(vec3 v, vec3 dest); CGLM_INLINE void glm_vec3_cross(vec3 a, vec3 b, vec3 d); CGLM_INLINE void glm_vec3_crossn(vec3 a, vec3 b, vec3 dest); - CGLM_INLINE float glm_vec3_distance(vec3 a, vec3 b); CGLM_INLINE float glm_vec3_angle(vec3 a, vec3 b); CGLM_INLINE void glm_vec3_rotate(vec3 v, float angle, vec3 axis); CGLM_INLINE void glm_vec3_rotate_m4(mat4 m, vec3 v, vec3 dest); CGLM_INLINE void glm_vec3_rotate_m3(mat3 m, vec3 v, vec3 dest); CGLM_INLINE void glm_vec3_proj(vec3 a, vec3 b, vec3 dest); CGLM_INLINE void glm_vec3_center(vec3 a, vec3 b, vec3 dest); + CGLM_INLINE float glm_vec3_distance(vec3 a, vec3 b); CGLM_INLINE float glm_vec3_distance2(vec3 a, vec3 b); CGLM_INLINE void glm_vec3_maxv(vec3 a, vec3 b, vec3 dest); CGLM_INLINE void glm_vec3_minv(vec3 a, vec3 b, vec3 dest); @@ -694,9 +694,9 @@ glm_vec3_center(vec3 a, vec3 b, vec3 dest) { CGLM_INLINE float glm_vec3_distance2(vec3 a, vec3 b) { - return glm_pow2(b[0] - a[0]) - + glm_pow2(b[1] - a[1]) - + glm_pow2(b[2] - a[2]); + return glm_pow2(a[0] - b[0]) + + glm_pow2(a[1] - b[1]) + + glm_pow2(a[2] - b[2]); } /** diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index abfe22b..a75e75e 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -43,6 +43,7 @@ CGLM_INLINE void glm_vec4_normalize(vec4 v); CGLM_INLINE void glm_vec4_normalize_to(vec4 vec, vec4 dest); CGLM_INLINE float glm_vec4_distance(vec4 a, vec4 b); + CGLM_INLINE float glm_vec4_distance2(vec4 a, vec4 b); CGLM_INLINE void glm_vec4_maxv(vec4 a, vec4 b, vec4 dest); CGLM_INLINE void glm_vec4_minv(vec4 a, vec4 b, vec4 dest); CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal); @@ -697,14 +698,36 @@ CGLM_INLINE float glm_vec4_distance(vec4 a, vec4 b) { #if defined( __SSE__ ) || defined( __SSE2__ ) - return glmm_norm(_mm_sub_ps(glmm_load(b), glmm_load(a))); + return glmm_norm(_mm_sub_ps(glmm_load(a), glmm_load(b))); #elif defined(CGLM_NEON_FP) return glmm_norm(vsubq_f32(glmm_load(a), glmm_load(b))); #else - return sqrtf(glm_pow2(b[0] - a[0]) - + glm_pow2(b[1] - a[1]) - + glm_pow2(b[2] - a[2]) - + glm_pow2(b[3] - a[3])); + return sqrtf(glm_pow2(a[0] - b[0]) + + glm_pow2(a[1] - b[1]) + + glm_pow2(a[2] - b[2]) + + glm_pow2(a[3] - b[3])); +#endif +} + +/** + * @brief squared distance between two vectors + * + * @param[in] a vector1 + * @param[in] b vector2 + * @return returns squared distance + */ +CGLM_INLINE +float +glm_vec4_distance2(vec4 a, vec4 b) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + return glmm_norm2(_mm_sub_ps(glmm_load(a), glmm_load(b))); +#elif defined(CGLM_NEON_FP) + return glmm_norm2(vsubq_f32(glmm_load(a), glmm_load(b))); +#else + return glm_pow2(a[0] - b[0]) + + glm_pow2(a[1] - b[1]) + + glm_pow2(a[2] - b[2]) + + glm_pow2(a[3] - b[3]); #endif } diff --git a/src/vec3.c b/src/vec3.c index 14edaf6..dea7db4 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -214,14 +214,14 @@ glmc_vec3_center(vec3 a, vec3 b, vec3 dest) { CGLM_EXPORT float -glmc_vec3_distance2(vec3 a, vec3 b) { - return glm_vec3_distance2(a, b); +glmc_vec3_distance(vec3 a, vec3 b) { + return glm_vec3_distance(a, b); } CGLM_EXPORT float -glmc_vec3_distance(vec3 a, vec3 b) { - return glm_vec3_distance(a, b); +glmc_vec3_distance2(vec3 a, vec3 b) { + return glm_vec3_distance2(a, b); } CGLM_EXPORT diff --git a/src/vec4.c b/src/vec4.c index 0bb6a6e..e265188 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -182,6 +182,12 @@ glmc_vec4_distance(vec4 a, vec4 b) { return glm_vec4_distance(a, b); } +CGLM_EXPORT +float +glmc_vec4_distance2(vec4 a, vec4 b) { + return glm_vec4_distance2(a, b); +} + CGLM_EXPORT void glmc_vec4_maxv(vec4 a, vec4 b, vec4 dest) { From 4639f3184ac6f5ef4b3ee4dd81e3038205734117 Mon Sep 17 00:00:00 2001 From: Luigi Castelli Date: Sun, 25 Aug 2019 21:17:36 +0200 Subject: [PATCH 2/9] glm_lerpc(), glm_step(), glm_smoothstep(), glm_smoothinterp() (#98) * lerp, step, smoothstep * glm_lerp() and friends are no longer clamped, use glm_lerpc() and friends * mix() function as wrapper of lerp() * no there are clamp and raw version of lerp functions --- include/cglm/call/quat.h | 4 + include/cglm/call/vec3.h | 42 ++++++++- include/cglm/call/vec4.h | 42 ++++++++- include/cglm/quat.h | 18 +++- include/cglm/struct/quat.h | 20 ++++- include/cglm/struct/vec3.h | 167 +++++++++++++++++++++++++++++++++++- include/cglm/struct/vec4.h | 167 +++++++++++++++++++++++++++++++++++- include/cglm/util.h | 117 ++++++++++++++++++++++++- include/cglm/vec3.h | 165 +++++++++++++++++++++++++++++++++++- include/cglm/vec4.h | 169 +++++++++++++++++++++++++++++++++++-- src/quat.c | 6 ++ src/vec3.c | 42 +++++++++ src/vec4.c | 42 +++++++++ 13 files changed, 978 insertions(+), 23 deletions(-) diff --git a/include/cglm/call/quat.h b/include/cglm/call/quat.h index 3080bc7..ad5f82d 100644 --- a/include/cglm/call/quat.h +++ b/include/cglm/call/quat.h @@ -116,6 +116,10 @@ glmc_quat_mat3t(versor q, mat3 dest); CGLM_EXPORT void glmc_quat_lerp(versor from, versor to, float t, versor dest); + +CGLM_EXPORT +void +glmc_quat_lerpc(versor from, versor to, float t, versor dest); CGLM_EXPORT void diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index 9763403..142241f 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -179,10 +179,50 @@ glmc_vec3_clamp(vec3 v, float minVal, float maxVal); CGLM_EXPORT void glmc_vec3_ortho(vec3 v, vec3 dest); - + CGLM_EXPORT void glmc_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest); + +CGLM_INLINE +void +glmc_vec3_mix(vec3 from, vec3 to, float t, vec3 dest) { + glmc_vec3_lerp(from, to, t, dest); +} + +CGLM_INLINE +void +glmc_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest) { + glmc_vec3_lerpc(from, to, t, dest); +} + +CGLM_EXPORT +void +glmc_vec3_step_uni(float edge, vec3 x, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_step(vec3 edge, vec3 x, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest); + +CGLM_EXPORT +void +glmc_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest); /* ext */ diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index 38ed981..04fab81 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -152,10 +152,50 @@ glmc_vec4_minv(vec4 a, vec4 b, vec4 dest); CGLM_EXPORT void glmc_vec4_clamp(vec4 v, float minVal, float maxVal); - + CGLM_EXPORT void glmc_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest); + +CGLM_INLINE +void +glmc_vec4_mix(vec4 from, vec4 to, float t, vec4 dest) { + glmc_vec4_lerp(from, to, t, dest); +} + +CGLM_INLINE +void +glmc_vec4_mixc(vec4 from, vec4 to, float t, vec4 dest) { + glmc_vec4_lerpc(from, to, t, dest); +} + +CGLM_EXPORT +void +glmc_vec4_step_uni(float edge, vec4 x, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_step(vec4 edge, vec4 x, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest); + +CGLM_EXPORT +void +glmc_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest); CGLM_EXPORT void diff --git a/include/cglm/quat.h b/include/cglm/quat.h index 7745ed0..573932f 100644 --- a/include/cglm/quat.h +++ b/include/cglm/quat.h @@ -36,6 +36,7 @@ CGLM_INLINE void glm_quat_mat3(versor q, mat3 dest); CGLM_INLINE void glm_quat_mat3t(versor q, mat3 dest); CGLM_INLINE void glm_quat_lerp(versor from, versor to, float t, versor dest); + CGLM_INLINE void glm_quat_lerpc(versor from, versor to, float t, versor dest); CGLM_INLINE void glm_quat_slerp(versor q, versor r, float t, versor dest); CGLM_INLINE void glm_quat_look(vec3 eye, versor ori, mat4 dest); CGLM_INLINE void glm_quat_for(vec3 dir, vec3 fwd, vec3 up, versor dest); @@ -601,7 +602,7 @@ glm_quat_mat3t(versor q, mat3 dest) { * * @param[in] from from * @param[in] to to - * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[in] t interpolant (amount) * @param[out] dest result quaternion */ CGLM_INLINE @@ -610,6 +611,21 @@ glm_quat_lerp(versor from, versor to, float t, versor dest) { glm_vec4_lerp(from, to, t, dest); } +/*! + * @brief interpolates between two quaternions + * using linear interpolation (LERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest result quaternion + */ +CGLM_INLINE +void +glm_quat_lerpc(versor from, versor to, float t, versor dest) { + glm_vec4_lerpc(from, to, t, dest); +} + /*! * @brief interpolates between two quaternions * using spherical linear interpolation (SLERP) diff --git a/include/cglm/struct/quat.h b/include/cglm/struct/quat.h index c6a4192..3b0c8ee 100644 --- a/include/cglm/struct/quat.h +++ b/include/cglm/struct/quat.h @@ -33,6 +33,7 @@ CGLM_INLINE mat3s glms_quat_mat3(versors q) CGLM_INLINE mat3s glms_quat_mat3t(versors q) CGLM_INLINE versors glms_quat_lerp(versors from, versors to, float t) + CGLM_INLINE versors glms_quat_lerpc(versors from, versors to, float t) CGLM_INLINE versors glms_quat_slerp(versors from, versors to, float t) CGLM_INLINE mat4s. glms_quat_look(vec3s eye, versors ori) CGLM_INLINE versors glms_quat_for(vec3s dir, vec3s fwd, vec3s up) @@ -372,7 +373,7 @@ glms_quat_mat3t(versors q) { * * @param[in] from from * @param[in] to to - * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[in] t interpolant (amount) * @returns result quaternion */ CGLM_INLINE @@ -383,6 +384,23 @@ glms_quat_lerp(versors from, versors to, float t) { return dest; } +/*! + * @brief interpolates between two quaternions + * using linear interpolation (LERP) + * + * @param[in] from from + * @param[in] to to + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns result quaternion + */ +CGLM_INLINE +versors +glms_quat_lerpc(versors from, versors to, float t) { + versors dest; + glm_quat_lerpc(from.raw, to.raw, t, dest.raw); + return dest; +} + /*! * @brief interpolates between two quaternions * using spherical linear interpolation (SLERP) diff --git a/include/cglm/struct/vec3.h b/include/cglm/struct/vec3.h index 903ceea..305ad44 100644 --- a/include/cglm/struct/vec3.h +++ b/include/cglm/struct/vec3.h @@ -58,6 +58,15 @@ CGLM_INLINE vec3s glms_vec3_ortho(vec3s v); CGLM_INLINE vec3s glms_vec3_clamp(vec3s v, float minVal, float maxVal); CGLM_INLINE vec3s glms_vec3_lerp(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_lerpc(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_mix(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_mixc(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_step_uni(float edge, vec3s x); + CGLM_INLINE vec3s glms_vec3_step(vec3s edge, vec3s x); + CGLM_INLINE vec3s glms_vec3_smoothstep_uni(float edge0, float edge1, vec3s x); + CGLM_INLINE vec3s glms_vec3_smoothstep(vec3s edge0, vec3s edge1, vec3s x); + CGLM_INLINE vec3s glms_vec3_smoothinterp(vec3s from, vec3s to, float t); + CGLM_INLINE vec3s glms_vec3_smoothinterpc(vec3s from, vec3s to, float t); CGLM_INLINE vec3s glms_vec3_swizzle(vec3s v, int mask); Convenient: @@ -684,7 +693,25 @@ glms_vec3_clamp(vec3s v, float minVal, float maxVal) { } /*! - * @brief linear interpolation between two vector + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_lerp(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_lerp(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors (clamped) * * formula: from + s * (to - from) * @@ -695,9 +722,143 @@ glms_vec3_clamp(vec3s v, float minVal, float maxVal) { */ CGLM_INLINE vec3s -glms_vec3_lerp(vec3s from, vec3s to, float t) { +glms_vec3_lerpc(vec3s from, vec3s to, float t) { vec3s r; - glm_vec3_lerp(from.raw, to.raw, t, r.raw); + glm_vec3_lerpc(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_mix(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_mix(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_mixc(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_mixc(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief threshold function (unidimensional) + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @returns 0.0 if x < edge, else 1.0 + */ +CGLM_INLINE +vec3s +glms_vec3_step_uni(float edge, vec3s x) { + vec3s r; + glm_vec3_step_uni(edge, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @returns 0.0 if x < edge, else 1.0 + */ +CGLM_INLINE +vec3s +glms_vec3_step(vec3s edge, vec3s x) { + vec3s r; + glm_vec3_step(edge.raw, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold function with a smooth transition (unidimensional) + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_smoothstep_uni(float edge0, float edge1, vec3s x) { + vec3s r; + glm_vec3_smoothstep_uni(edge0, edge1, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold function with a smooth transition + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_smoothstep(vec3s edge0, vec3s edge1, vec3s x) { + vec3s r; + glm_vec3_smoothstep(edge0.raw, edge1.raw, x.raw, r.raw); + return r; +} + +/*! + * @brief smooth Hermite interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_smoothinterp(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_smoothinterp(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief smooth Hermite interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns destination + */ +CGLM_INLINE +vec3s +glms_vec3_smoothinterpc(vec3s from, vec3s to, float t) { + vec3s r; + glm_vec3_smoothinterpc(from.raw, to.raw, t, r.raw); return r; } diff --git a/include/cglm/struct/vec4.h b/include/cglm/struct/vec4.h index 55572b8..17a4898 100644 --- a/include/cglm/struct/vec4.h +++ b/include/cglm/struct/vec4.h @@ -48,6 +48,15 @@ CGLM_INLINE vec4s glms_vec4_minv(vec4s a, vec4s b); CGLM_INLINE vec4s glms_vec4_clamp(vec4s v, float minVal, float maxVal); CGLM_INLINE vec4s glms_vec4_lerp(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_lerpc(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_mix(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_mixc(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_step_uni(float edge, vec4s x); + CGLM_INLINE vec4s glms_vec4_step(vec4s edge, vec4s x); + CGLM_INLINE vec4s glms_vec4_smoothstep_uni(float edge0, float edge1, vec4s x); + CGLM_INLINE vec4s glms_vec4_smoothstep(vec4s edge0, vec4s edge1, vec4s x); + CGLM_INLINE vec4s glms_vec4_smoothinterp(vec4s from, vec4s to, float t); + CGLM_INLINE vec4s glms_vec4_smoothinterpc(vec4s from, vec4s to, float t); CGLM_INLINE vec4s glms_vec4_cubic(float s); CGLM_INLINE vec4s glms_vec4_swizzle(vec4s v, int mask); */ @@ -561,7 +570,25 @@ glms_vec4_clamp(vec4s v, float minVal, float maxVal) { } /*! - * @brief linear interpolation between two vector + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_lerp(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_lerp(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors (clamped) * * formula: from + s * (to - from) * @@ -572,9 +599,143 @@ glms_vec4_clamp(vec4s v, float minVal, float maxVal) { */ CGLM_INLINE vec4s -glms_vec4_lerp(vec4s from, vec4s to, float t) { +glms_vec4_lerpc(vec4s from, vec4s to, float t) { vec4s r; - glm_vec4_lerp(from.raw, to.raw, t, r.raw); + glm_vec4_lerpc(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_mix(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_mix(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_mixc(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_mixc(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief threshold function (unidimensional) + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @returns 0.0 if x < edge, else 1.0 + */ +CGLM_INLINE +vec4s +glms_vec4_step_uni(float edge, vec4s x) { + vec4s r; + glm_vec4_step_uni(edge, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @returns 0.0 if x < edge, else 1.0 + */ +CGLM_INLINE +vec4s +glms_vec4_step(vec4s edge, vec4s x) { + vec4s r; + glm_vec4_step(edge.raw, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold function with a smooth transition (unidimensional) + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_smoothstep_uni(float edge0, float edge1, vec4s x) { + vec4s r; + glm_vec4_smoothstep_uni(edge0, edge1, x.raw, r.raw); + return r; +} + +/*! + * @brief threshold function with a smooth transition + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_smoothstep(vec4s edge0, vec4s edge1, vec4s x) { + vec4s r; + glm_vec4_smoothstep(edge0.raw, edge1.raw, x.raw, r.raw); + return r; +} + +/*! + * @brief smooth Hermite interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_smoothinterp(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_smoothinterp(from.raw, to.raw, t, r.raw); + return r; +} + +/*! + * @brief smooth Hermite interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @returns destination + */ +CGLM_INLINE +vec4s +glms_vec4_smoothinterpc(vec4s from, vec4s to, float t) { + vec4s r; + glm_vec4_smoothinterpc(from.raw, to.raw, t, r.raw); return r; } diff --git a/include/cglm/util.h b/include/cglm/util.h index d1ef21b..7b77cb8 100644 --- a/include/cglm/util.h +++ b/include/cglm/util.h @@ -8,11 +8,26 @@ /* Functions: CGLM_INLINE int glm_sign(int val); + CGLM_INLINE float glm_signf(float val); CGLM_INLINE float glm_rad(float deg); CGLM_INLINE float glm_deg(float rad); CGLM_INLINE void glm_make_rad(float *deg); CGLM_INLINE void glm_make_deg(float *rad); CGLM_INLINE float glm_pow2(float x); + CGLM_INLINE float glm_min(float a, float b); + CGLM_INLINE float glm_max(float a, float b); + CGLM_INLINE float glm_clamp(float val, float minVal, float maxVal); + CGLM_INLINE float glm_clamp_zo(float val, float minVal, float maxVal); + CGLM_INLINE float glm_lerp(float from, float to, float t); + CGLM_INLINE float glm_lerpc(float from, float to, float t); + CGLM_INLINE float glm_step(float edge, float x); + CGLM_INLINE float glm_smooth(float t); + CGLM_INLINE float glm_smoothstep(float edge0, float edge1, float x); + CGLM_INLINE float glm_smoothinterp(float from, float to, float t); + CGLM_INLINE float glm_smoothinterpc(float from, float to, float t); + CGLM_INLINE bool glm_eq(float a, float b); + CGLM_INLINE float glm_percent(float from, float to, float current); + CGLM_INLINE float glm_percentc(float from, float to, float current); */ #ifndef cglm_util_h @@ -157,9 +172,103 @@ glm_clamp_zo(float val) { } /*! - * @brief linear interpolation between two number + * @brief linear interpolation between two numbers * - * formula: from + s * (to - from) + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + */ +CGLM_INLINE +float +glm_lerp(float from, float to, float t) { + return from + t * (to - from); +} + +/*! + * @brief clamped linear interpolation between two numbers + * + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + */ +CGLM_INLINE +float +glm_lerpc(float from, float to, float t) { + return glm_lerp(from, to, glm_clamp_zo(t)); +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @return returns 0.0 if x < edge, else 1.0 + */ +CGLM_INLINE +float +glm_step(float edge, float x) { + /* branching - no type conversion */ + return (x < edge) ? 0.0f : 1.0f; + /* + * An alternative implementation without branching + * but with type conversion could be: + * return !(x < edge); + */ +} + +/*! + * @brief smooth Hermite interpolation + * + * formula: t^2 * (3-2t) + * + * @param[in] t interpolant (amount) + */ +CGLM_INLINE +float +glm_smooth(float t) { + return t * t * (3.0f - 2.0f * t); +} + +/*! + * @brief threshold function with a smooth transition (according to OpenCL specs) + * + * formula: t^2 * (3-2t) + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x interpolant (amount) + */ +CGLM_INLINE +float +glm_smoothstep(float edge0, float edge1, float x) { + float t; + t = glm_clamp_zo((x - edge0) / (edge1 - edge0)); + return glm_smooth(t); +} + +/*! + * @brief smoothstep interpolation between two numbers + * + * formula: from + smoothstep(t) * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + */ +CGLM_INLINE +float +glm_smoothinterp(float from, float to, float t) { + return from + glm_smooth(t) * (to - from); +} + +/*! + * @brief clamped smoothstep interpolation between two numbers + * + * formula: from + smoothstep(t) * (to - from) * * @param[in] from from value * @param[in] to to value @@ -167,8 +276,8 @@ glm_clamp_zo(float val) { */ CGLM_INLINE float -glm_lerp(float from, float to, float t) { - return from + glm_clamp_zo(t) * (to - from); +glm_smoothinterpc(float from, float to, float t) { + return glm_smoothinterp(from, to, glm_clamp_zo(t)); } /*! diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index 3c2e36e..a09c272 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -61,6 +61,15 @@ CGLM_INLINE void glm_vec3_ortho(vec3 v, vec3 dest); CGLM_INLINE void glm_vec3_clamp(vec3 v, float minVal, float maxVal); CGLM_INLINE void glm_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_mix(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_step_uni(float edge, vec3 x, vec3 dest); + CGLM_INLINE void glm_vec3_step(vec3 edge, vec3 x, vec3 dest); + CGLM_INLINE void glm_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest); + CGLM_INLINE void glm_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest); + CGLM_INLINE void glm_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest); + CGLM_INLINE void glm_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest); CGLM_INLINE void glm_vec3_swizzle(vec3 v, int mask, vec3 dest); Convenient: @@ -772,7 +781,29 @@ glm_vec3_clamp(vec3 v, float minVal, float maxVal) { } /*! - * @brief linear interpolation between two vector + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest) { + vec3 s, v; + + /* from + s * (to - from) */ + glm_vec3_broadcast(t, s); + glm_vec3_sub(to, from, v); + glm_vec3_mul(s, v, v); + glm_vec3_add(from, v, dest); +} + +/*! + * @brief linear interpolation between two vectors (clamped) * * formula: from + s * (to - from) * @@ -783,16 +814,142 @@ glm_vec3_clamp(vec3 v, float minVal, float maxVal) { */ CGLM_INLINE void -glm_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest) { - vec3 s, v; +glm_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_lerp(from, to, glm_clamp_zo(t), dest); +} +/*! + * @brief linear interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_mix(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_lerp(from, to, t, dest); +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_mixc(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_lerpc(from, to, t, dest); +} + +/*! + * @brief threshold function (unidimensional) + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_step_uni(float edge, vec3 x, vec3 dest) { + dest[0] = glm_step(edge, x[0]); + dest[1] = glm_step(edge, x[1]); + dest[2] = glm_step(edge, x[2]); +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_step(vec3 edge, vec3 x, vec3 dest) { + dest[0] = glm_step(edge[0], x[0]); + dest[1] = glm_step(edge[1], x[1]); + dest[2] = glm_step(edge[2], x[2]); +} + +/*! + * @brief threshold function with a smooth transition (unidimensional) + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest) { + dest[0] = glm_smoothstep(edge0, edge1, x[0]); + dest[1] = glm_smoothstep(edge0, edge1, x[1]); + dest[2] = glm_smoothstep(edge0, edge1, x[2]); +} + +/*! + * @brief threshold function with a smooth transition + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest) { + dest[0] = glm_smoothstep(edge0[0], edge1[0], x[0]); + dest[1] = glm_smoothstep(edge0[1], edge1[1], x[1]); + dest[2] = glm_smoothstep(edge0[2], edge1[2], x[2]); +} + +/*! + * @brief smooth Hermite interpolation between two vectors + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest) { + vec3 s, v; + /* from + s * (to - from) */ - glm_vec3_broadcast(glm_clamp_zo(t), s); + glm_vec3_broadcast(glm_smooth(t), s); glm_vec3_sub(to, from, v); glm_vec3_mul(s, v, v); glm_vec3_add(from, v, dest); } +/*! + * @brief smooth Hermite interpolation between two vectors (clamped) + * + * formula: from + s * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_smoothinterp(from, to, glm_clamp_zo(t), dest); +} + /*! * @brief vec3 cross product * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index a75e75e..863f646 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -47,7 +47,14 @@ CGLM_INLINE void glm_vec4_maxv(vec4 a, vec4 b, vec4 dest); CGLM_INLINE void glm_vec4_minv(vec4 a, vec4 b, vec4 dest); CGLM_INLINE void glm_vec4_clamp(vec4 v, float minVal, float maxVal); - CGLM_INLINE void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) + CGLM_INLINE void glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest); + CGLM_INLINE void glm_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest); + CGLM_INLINE void glm_vec4_step_uni(float edge, vec4 x, vec4 dest); + CGLM_INLINE void glm_vec4_step(vec4 edge, vec4 x, vec4 dest); + CGLM_INLINE void glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest); + CGLM_INLINE void glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest); + CGLM_INLINE void glm_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest); + CGLM_INLINE void glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest); CGLM_INLINE void glm_vec4_swizzle(vec4 v, int mask, vec4 dest); DEPRECATED: @@ -800,13 +807,13 @@ glm_vec4_clamp(vec4 v, float minVal, float maxVal) { } /*! - * @brief linear interpolation between two vector + * @brief linear interpolation between two vectors * - * formula: from + s * (to - from) + * formula: from + t * (to - from) * * @param[in] from from value * @param[in] to to value - * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[in] t interpolant (amount) * @param[out] dest destination */ CGLM_INLINE @@ -815,12 +822,164 @@ glm_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) { vec4 s, v; /* from + s * (to - from) */ - glm_vec4_broadcast(glm_clamp_zo(t), s); + glm_vec4_broadcast(t, s); glm_vec4_sub(to, from, v); glm_vec4_mul(s, v, v); glm_vec4_add(from, v, dest); } +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_lerp(from, to, glm_clamp_zo(t), dest); +} + +/*! + * @brief linear interpolation between two vectors + * + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_mix(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_lerp(from, to, t, dest); +} + +/*! + * @brief linear interpolation between two vectors (clamped) + * + * formula: from + t * (to - from) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_mixc(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_lerpc(from, to, t, dest); +} + +/*! + * @brief threshold function (unidimensional) + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_step_uni(float edge, vec4 x, vec4 dest) { + dest[0] = glm_step(edge, x[0]); + dest[1] = glm_step(edge, x[1]); + dest[2] = glm_step(edge, x[2]); + dest[3] = glm_step(edge, x[3]); +} + +/*! + * @brief threshold function + * + * @param[in] edge threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_step(vec4 edge, vec4 x, vec4 dest) { + dest[0] = glm_step(edge[0], x[0]); + dest[1] = glm_step(edge[1], x[1]); + dest[2] = glm_step(edge[2], x[2]); + dest[3] = glm_step(edge[3], x[3]); +} + +/*! + * @brief threshold function with a smooth transition (unidimensional) + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest) { + dest[0] = glm_smoothstep(edge0, edge1, x[0]); + dest[1] = glm_smoothstep(edge0, edge1, x[1]); + dest[2] = glm_smoothstep(edge0, edge1, x[2]); + dest[3] = glm_smoothstep(edge0, edge1, x[3]); +} + +/*! + * @brief threshold function with a smooth transition + * + * @param[in] edge0 low threshold + * @param[in] edge1 high threshold + * @param[in] x value to test against threshold + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest) { + dest[0] = glm_smoothstep(edge0[0], edge1[0], x[0]); + dest[1] = glm_smoothstep(edge0[1], edge1[1], x[1]); + dest[2] = glm_smoothstep(edge0[2], edge1[2], x[2]); + dest[3] = glm_smoothstep(edge0[3], edge1[3], x[3]); +} + +/*! + * @brief smooth Hermite interpolation between two vectors + * + * formula: t^2 * (3 - 2*t) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest) { + vec4 s, v; + + /* from + smoothstep * (to - from) */ + glm_vec4_broadcast(glm_smooth(t), s); + glm_vec4_sub(to, from, v); + glm_vec4_mul(s, v, v); + glm_vec4_add(from, v, dest); +} + +/*! + * @brief smooth Hermite interpolation between two vectors (clamped) + * + * formula: t^2 * (3 - 2*t) + * + * @param[in] from from value + * @param[in] to to value + * @param[in] t interpolant (amount) clamped between 0 and 1 + * @param[out] dest destination + */ +CGLM_INLINE +void +glm_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_smoothinterp(from, to, glm_clamp_zo(t), dest); +} + /*! * @brief helper to fill vec4 as [S^3, S^2, S, 1] * diff --git a/src/quat.c b/src/quat.c index 8de4696..bd8c13b 100644 --- a/src/quat.c +++ b/src/quat.c @@ -164,6 +164,12 @@ glmc_quat_lerp(versor from, versor to, float t, versor dest) { glm_quat_lerp(from, to, t, dest); } +CGLM_EXPORT +void +glmc_quat_lerpc(versor from, versor to, float t, versor dest) { + glm_quat_lerpc(from, to, t, dest); +} + CGLM_EXPORT void glmc_quat_slerp(versor from, versor to, float t, versor dest) { diff --git a/src/vec3.c b/src/vec3.c index dea7db4..f05070a 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -254,6 +254,48 @@ glmc_vec3_lerp(vec3 from, vec3 to, float t, vec3 dest) { glm_vec3_lerp(from, to, t, dest); } +CGLM_EXPORT +void +glmc_vec3_lerpc(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_lerpc(from, to, t, dest); +} + +CGLM_EXPORT +void +glmc_vec3_step_uni(float edge, vec3 x, vec3 dest) { + glm_vec3_step_uni(edge, x, dest); +} + +CGLM_EXPORT +void +glmc_vec3_step(vec3 edge, vec3 x, vec3 dest) { + glm_vec3_step(edge, x, dest); +} + +CGLM_EXPORT +void +glmc_vec3_smoothstep_uni(float edge0, float edge1, vec3 x, vec3 dest) { + glm_vec3_smoothstep_uni(edge0, edge1, x, dest); +} + +CGLM_EXPORT +void +glmc_vec3_smoothstep(vec3 edge0, vec3 edge1, vec3 x, vec3 dest) { + glm_vec3_smoothstep(edge0, edge1, x, dest); +} + +CGLM_EXPORT +void +glmc_vec3_smoothinterp(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_smoothinterp(from, to, t, dest); +} + +CGLM_EXPORT +void +glmc_vec3_smoothinterpc(vec3 from, vec3 to, float t, vec3 dest) { + glm_vec3_smoothinterpc(from, to, t, dest); +} + /* ext */ CGLM_EXPORT diff --git a/src/vec4.c b/src/vec4.c index e265188..2296966 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -212,6 +212,48 @@ glmc_vec4_lerp(vec4 from, vec4 to, float t, vec4 dest) { glm_vec4_lerp(from, to, t, dest); } +CGLM_EXPORT +void +glmc_vec4_lerpc(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_lerpc(from, to, t, dest); +} + +CGLM_EXPORT +void +glmc_vec4_step_uni(float edge, vec4 x, vec4 dest) { + glm_vec4_step_uni(edge, x, dest); +} + +CGLM_EXPORT +void +glmc_vec4_step(vec4 edge, vec4 x, vec4 dest) { + glm_vec4_step(edge, x, dest); +} + +CGLM_EXPORT +void +glmc_vec4_smoothstep_uni(float edge0, float edge1, vec4 x, vec4 dest) { + glm_vec4_smoothstep_uni(edge0, edge1, x, dest); +} + +CGLM_EXPORT +void +glmc_vec4_smoothstep(vec4 edge0, vec4 edge1, vec4 x, vec4 dest) { + glm_vec4_smoothstep(edge0, edge1, x, dest); +} + +CGLM_EXPORT +void +glmc_vec4_smoothinterp(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_smoothinterp(from, to, t, dest); +} + +CGLM_EXPORT +void +glmc_vec4_smoothinterpc(vec4 from, vec4 to, float t, vec4 dest) { + glm_vec4_smoothinterpc(from, to, t, dest); +} + CGLM_EXPORT void glmc_vec4_cubic(float s, vec4 dest) { From 144624962af644021cf30fa99de8e1a6b2c0147a Mon Sep 17 00:00:00 2001 From: Luigi Castelli Date: Mon, 26 Aug 2019 08:19:26 +0200 Subject: [PATCH 3/9] added glm_vec_fill() (#100) * alternative name for _broadcast(): _fill() --- include/cglm/call/vec3.h | 4 ++++ include/cglm/call/vec4.h | 4 ++++ include/cglm/struct/vec3-ext.h | 15 +++++++++++++++ include/cglm/struct/vec4-ext.h | 15 +++++++++++++++ include/cglm/vec3-ext.h | 13 +++++++++++++ include/cglm/vec4-ext.h | 17 +++++++++++++++++ src/vec3.c | 6 ++++++ src/vec4.c | 6 ++++++ 8 files changed, 80 insertions(+) diff --git a/include/cglm/call/vec3.h b/include/cglm/call/vec3.h index 142241f..851417f 100644 --- a/include/cglm/call/vec3.h +++ b/include/cglm/call/vec3.h @@ -233,6 +233,10 @@ glmc_vec3_mulv(vec3 a, vec3 b, vec3 d); CGLM_EXPORT void glmc_vec3_broadcast(float val, vec3 d); + +CGLM_EXPORT +void +glmc_vec3_fill(vec3 v, float val); CGLM_EXPORT bool diff --git a/include/cglm/call/vec4.h b/include/cglm/call/vec4.h index 04fab81..c8702e2 100644 --- a/include/cglm/call/vec4.h +++ b/include/cglm/call/vec4.h @@ -210,6 +210,10 @@ glmc_vec4_mulv(vec4 a, vec4 b, vec4 d); CGLM_EXPORT void glmc_vec4_broadcast(float val, vec4 d); + +CGLM_EXPORT +void +glmc_vec4_fill(vec4 v, float val); CGLM_EXPORT bool diff --git a/include/cglm/struct/vec3-ext.h b/include/cglm/struct/vec3-ext.h index 2cd8749..055805e 100644 --- a/include/cglm/struct/vec3-ext.h +++ b/include/cglm/struct/vec3-ext.h @@ -12,6 +12,7 @@ /* Functions: CGLM_INLINE vec3s glms_vec3_broadcast(float val); + CGLM_INLINE vec3s glms_vec3_fill(float val); CGLM_INLINE bool glms_vec3_eq(vec3s v, float val); CGLM_INLINE bool glms_vec3_eq_eps(vec3s v, float val); CGLM_INLINE bool glms_vec3_eq_all(vec3s v); @@ -48,6 +49,20 @@ glms_vec3_broadcast(float val) { return r; } +/*! + * @brief fill a vector with specified value + * + * @param[in] val value + * @returns dest + */ +CGLM_INLINE +vec3s +glms_vec3_fill(float val) { + vec3s r; + glm_vec3_fill(r.raw, val); + return r; +} + /*! * @brief check if vector is equal to value (without epsilon) * diff --git a/include/cglm/struct/vec4-ext.h b/include/cglm/struct/vec4-ext.h index 52c438e..371956d 100644 --- a/include/cglm/struct/vec4-ext.h +++ b/include/cglm/struct/vec4-ext.h @@ -12,6 +12,7 @@ /* Functions: CGLM_INLINE vec4s glms_vec4_broadcast(float val); + CGLM_INLINE vec4s glms_vec4_fill(float val); CGLM_INLINE bool glms_vec4_eq(vec4s v, float val); CGLM_INLINE bool glms_vec4_eq_eps(vec4s v, float val); CGLM_INLINE bool glms_vec4_eq_all(vec4s v); @@ -48,6 +49,20 @@ glms_vec4_broadcast(float val) { return r; } +/*! + * @brief fill a vector with specified value + * + * @param val value + * @returns dest + */ +CGLM_INLINE +vec4s +glms_vec4_fill(float val) { + vec4s r; + glm_vec4_fill(r.raw, val); + return r; +} + /*! * @brief check if vector is equal to value (without epsilon) * diff --git a/include/cglm/vec3-ext.h b/include/cglm/vec3-ext.h index f1cc462..6b8d5f0 100644 --- a/include/cglm/vec3-ext.h +++ b/include/cglm/vec3-ext.h @@ -12,6 +12,7 @@ /* Functions: CGLM_INLINE void glm_vec3_broadcast(float val, vec3 d); + CGLM_INLINE void glm_vec3_fill(vec3 v, float val); CGLM_INLINE bool glm_vec3_eq(vec3 v, float val); CGLM_INLINE bool glm_vec3_eq_eps(vec3 v, float val); CGLM_INLINE bool glm_vec3_eq_all(vec3 v); @@ -44,6 +45,18 @@ glm_vec3_broadcast(float val, vec3 d) { d[0] = d[1] = d[2] = val; } +/*! + * @brief fill a vector with specified value + * + * @param[out] v dest + * @param[in] val value + */ +CGLM_INLINE +void +glm_vec3_fill(vec3 v, float val) { + v[0] = v[1] = v[2] = val; +} + /*! * @brief check if vector is equal to value (without epsilon) * diff --git a/include/cglm/vec4-ext.h b/include/cglm/vec4-ext.h index c545a14..3ef71d6 100644 --- a/include/cglm/vec4-ext.h +++ b/include/cglm/vec4-ext.h @@ -12,6 +12,7 @@ /* Functions: CGLM_INLINE void glm_vec4_broadcast(float val, vec4 d); + CGLM_INLINE void glm_vec4_fill(vec4 v, float val); CGLM_INLINE bool glm_vec4_eq(vec4 v, float val); CGLM_INLINE bool glm_vec4_eq_eps(vec4 v, float val); CGLM_INLINE bool glm_vec4_eq_all(vec4 v); @@ -48,6 +49,22 @@ glm_vec4_broadcast(float val, vec4 d) { #endif } +/*! + * @brief fill a vector with specified value + * + * @param v dest + * @param val value + */ +CGLM_INLINE +void +glm_vec4_fill(vec4 v, float val) { +#if defined( __SSE__ ) || defined( __SSE2__ ) + glmm_store(v, _mm_set1_ps(val)); +#else + v[0] = v[1] = v[2] = v[3] = val; +#endif +} + /*! * @brief check if vector is equal to value (without epsilon) * diff --git a/src/vec3.c b/src/vec3.c index f05070a..5e79260 100644 --- a/src/vec3.c +++ b/src/vec3.c @@ -310,6 +310,12 @@ glmc_vec3_broadcast(float val, vec3 d) { glm_vec3_broadcast(val, d); } +CGLM_EXPORT +void +glmc_vec3_fill(vec3 v, float val) { + glm_vec3_fill(v, val); +} + CGLM_EXPORT bool glmc_vec3_eq(vec3 v, float val) { diff --git a/src/vec4.c b/src/vec4.c index 2296966..d1c4d08 100644 --- a/src/vec4.c +++ b/src/vec4.c @@ -274,6 +274,12 @@ glmc_vec4_broadcast(float val, vec4 d) { glm_vec4_broadcast(val, d); } +CGLM_EXPORT +void +glmc_vec4_fill(vec4 v, float val) { + glm_vec4_fill(v, val); +} + CGLM_EXPORT bool glmc_vec4_eq(vec4 v, float val) { From 1d804781de080f5103a0bf4109b72af3e32ca50f Mon Sep 17 00:00:00 2001 From: Luigi Castelli Date: Mon, 26 Aug 2019 15:37:44 +0200 Subject: [PATCH 4/9] swapped argument order in glmm_store3() (#102) close https://github.com/recp/cglm/issues/101 --- include/cglm/simd/x86.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/cglm/simd/x86.h b/include/cglm/simd/x86.h index 2e0b7b5..418cde0 100644 --- a/include/cglm/simd/x86.h +++ b/include/cglm/simd/x86.h @@ -133,7 +133,7 @@ glmm_load3(float v[3]) { static inline void -glmm_store3(__m128 vx, float v[3]) { +glmm_store3(float v[3], __m128 vx) { _mm_storel_pi((__m64 *)&v[0], vx); _mm_store_ss(&v[2], glmm_shuff1(vx, 2, 2, 2, 2)); } From a450ab2d9cb21d8d8d0913ceb3db8f3e41381168 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 27 Aug 2019 20:00:01 +0300 Subject: [PATCH 5/9] Update ccpp.yml --- .github/workflows/ccpp.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/ccpp.yml diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml new file mode 100644 index 0000000..ff024ff --- /dev/null +++ b/.github/workflows/ccpp.yml @@ -0,0 +1,21 @@ +name: C/C++ CI + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: dependencies + run: sh ./build-deps.sh + - name: configure + run: ./configure + - name: make + run: make + - name: make check + run: make check + - name: make distcheck + run: make distcheck From cfaf01afaa9b823ecde05ce1d171c7d64d9b3c2d Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Tue, 27 Aug 2019 20:01:54 +0300 Subject: [PATCH 6/9] Update ccpp.yml --- .github/workflows/ccpp.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index ff024ff..1b23839 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -11,6 +11,8 @@ jobs: - uses: actions/checkout@v1 - name: dependencies run: sh ./build-deps.sh + - name: autogen + run: sh autogen.sh - name: configure run: ./configure - name: make From 03fda193a5d9f30eb4a508f2a2bd9a204ac399b9 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 30 Aug 2019 14:47:26 +0300 Subject: [PATCH 7/9] vec: update docs for norm --- docs/source/vec3.rst | 3 ++- docs/source/vec4.rst | 3 ++- include/cglm/vec3.h | 3 ++- include/cglm/vec4.h | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/source/vec3.rst b/docs/source/vec3.rst index b431528..100e849 100644 --- a/docs/source/vec3.rst +++ b/docs/source/vec3.rst @@ -158,7 +158,8 @@ Functions documentation .. c:function:: float glm_vec3_norm(vec3 vec) - norm (magnitude) of vec3 + | euclidean norm (magnitude), also called L2 norm + | this will give magnitude of vector in euclidean space Parameters: | *[in]* **vec** vector diff --git a/docs/source/vec4.rst b/docs/source/vec4.rst index f497868..58c861e 100644 --- a/docs/source/vec4.rst +++ b/docs/source/vec4.rst @@ -134,7 +134,8 @@ Functions documentation .. c:function:: float glm_vec4_norm(vec4 vec) - norm (magnitude) of vec4 + | euclidean norm (magnitude), also called L2 norm + | this will give magnitude of vector in euclidean space Parameters: | *[in]* **vec** vector diff --git a/include/cglm/vec3.h b/include/cglm/vec3.h index a09c272..cc6d552 100644 --- a/include/cglm/vec3.h +++ b/include/cglm/vec3.h @@ -200,7 +200,8 @@ glm_vec3_norm2(vec3 v) { } /*! - * @brief norm (magnitude) of vec3 + * @brief euclidean norm (magnitude), also called L2 norm + * this will give magnitude of vector in euclidean space * * @param[in] v vector * diff --git a/include/cglm/vec4.h b/include/cglm/vec4.h index 863f646..05835ff 100644 --- a/include/cglm/vec4.h +++ b/include/cglm/vec4.h @@ -240,7 +240,8 @@ glm_vec4_norm2(vec4 v) { } /*! - * @brief norm (magnitude) of vec4 + * @brief euclidean norm (magnitude), also called L2 norm + * this will give magnitude of vector in euclidean space * * @param[in] v vector * From 62f4685f86b6bd028e83c112807266a28c5086a4 Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 30 Aug 2019 14:55:19 +0300 Subject: [PATCH 8/9] Update ccpp.yml --- .github/workflows/ccpp.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 1b23839..6c8da97 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -5,7 +5,11 @@ on: [push] jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + node_version: [8, 10, 12] + os: [ubuntu-latest, windows-latest, macOS-latest] steps: - uses: actions/checkout@v1 @@ -19,5 +23,3 @@ jobs: run: make - name: make check run: make check - - name: make distcheck - run: make distcheck From 6af1f5af04dd14a39d050417720fc88ffb4d5b8b Mon Sep 17 00:00:00 2001 From: Recep Aslantas Date: Fri, 30 Aug 2019 14:58:47 +0300 Subject: [PATCH 9/9] Update ccpp.yml --- .github/workflows/ccpp.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml index 6c8da97..3621c64 100644 --- a/.github/workflows/ccpp.yml +++ b/.github/workflows/ccpp.yml @@ -8,8 +8,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node_version: [8, 10, 12] - os: [ubuntu-latest, windows-latest, macOS-latest] + os: [ubuntu-latest, macOS-latest] steps: - uses: actions/checkout@v1