From 4639f3184ac6f5ef4b3ee4dd81e3038205734117 Mon Sep 17 00:00:00 2001 From: Luigi Castelli Date: Sun, 25 Aug 2019 21:17:36 +0200 Subject: [PATCH] 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) {