diff --git a/src/funs/mix.rs b/src/funs/mix.rs index 6af376e..fa59ece 100644 --- a/src/funs/mix.rs +++ b/src/funs/mix.rs @@ -1,56 +1,137 @@ use num::cast::*; use vec::{Vec2, Vec3, Vec4}; +use extent::{Clamp, clamp}; + pub trait Mix { pure fn mix(other: &self, value: &self) -> self; + pure fn smooth_step(edge0: &self, edge1: &self) -> self; + pure fn step(edge: &self) -> self; } #[inline(always)] pub pure fn mix(a: &T, b: &T, value: &T) -> T { a.mix(b, value) } +#[inline(always)] pub pure fn smooth_step(x: &T, edge0: &T, edge1: &T) -> T { x.smooth_step(edge0, edge1) } +#[inline(always)] pub pure fn step(x: &T, edge: &T) -> T { x.step(edge) } pub impl f32: Mix { #[inline(always)] pure fn mix(other: &f32, value: &f32) -> f32 { - self * (1f32 - (*value)) + (*other) * (*value) + self * (1.0 - (*value)) + (*other) * (*value) + } + + #[inline(always)] + pure fn smooth_step(edge0: &f32, edge1: &f32) -> f32 { + let t = clamp(&((self - *edge0) / (*edge1 - *edge0)), &0.0, &1.0); + return t * t * (3.0 - 2.0 * t); + } + + #[inline(always)] + pure fn step(edge: &f32) -> f32 { + if self < *edge { 0.0 } else { 1.0 } } } pub impl f64: Mix { #[inline(always)] pure fn mix(other: &f64, value: &f64) -> f64 { - self * (1f64 - (*value)) + (*other) * (*value) + self * (1.0 - (*value)) + (*other) * (*value) + } + + #[inline(always)] + pure fn smooth_step(edge0: &f64, edge1: &f64) -> f64 { + let t = clamp(&((self - *edge0) / (*edge1 - *edge0)), &0.0, &1.0); + return t * t * (3.0 - 2.0 * t); + } + + #[inline(always)] + pure fn step(edge: &f64) -> f64 { + if self < *edge { 0.0 } else { 1.0 } } } pub impl float: Mix { #[inline(always)] pure fn mix(other: &float, value: &float) -> float { - self * (1f - (*value)) + (*other) * (*value) + self * (1.0 - (*value)) + (*other) * (*value) + } + + #[inline(always)] + pure fn smooth_step(edge0: &float, edge1: &float) -> float { + let t = clamp(&((self - *edge0) / (*edge1 - *edge0)), &0.0, &1.0); + return t * t * (3.0 - 2.0 * t); + } + + #[inline(always)] + pure fn step(edge: &float) -> float { + if self < *edge { 0.0 } else { 1.0 } } } pub impl Vec2: Mix { #[inline(always)] - pure fn mix(other: &Vec2, values: &Vec2) -> Vec2 { - Vec2::new(self[0].mix(&other[0], &values[0]), - self[1].mix(&other[1], &values[1])) + pure fn mix(other: &Vec2, value: &Vec2) -> Vec2 { + Vec2::new(self[0].mix(&other[0], &value[0]), + self[1].mix(&other[1], &value[1])) + } + + #[inline(always)] + pure fn smooth_step(edge0: &Vec2, edge1: &Vec2) -> Vec2 { + Vec2::new(self[0].smooth_step(&edge0[0], &edge1[0]), + self[1].smooth_step(&edge0[1], &edge1[1])) + } + + #[inline(always)] + pure fn step(edge: &Vec2) -> Vec2 { + Vec2::new(self[0].step(&edge[0]), + self[1].step(&edge[1])) } } pub impl Vec3: Mix { #[inline(always)] - pure fn mix(other: &Vec3, values: &Vec3) -> Vec3 { - Vec3::new(self[0].mix(&other[0], &values[0]), - self[1].mix(&other[1], &values[1]), - self[2].mix(&other[2], &values[2])) + pure fn mix(other: &Vec3, value: &Vec3) -> Vec3 { + Vec3::new(self[0].mix(&other[0], &value[0]), + self[1].mix(&other[1], &value[1]), + self[2].mix(&other[2], &value[2])) + } + + #[inline(always)] + pure fn smooth_step(edge0: &Vec3, edge1: &Vec3) -> Vec3 { + Vec3::new(self[0].smooth_step(&edge0[0], &edge1[0]), + self[1].smooth_step(&edge0[1], &edge1[1]), + self[2].smooth_step(&edge0[2], &edge1[2])) + } + + #[inline(always)] + pure fn step(edge: &Vec3) -> Vec3 { + Vec3::new(self[0].step(&edge[0]), + self[1].step(&edge[1]), + self[2].step(&edge[2])) } } pub impl Vec4: Mix { #[inline(always)] - pure fn mix(other: &Vec4, values: &Vec4) -> Vec4 { - Vec4::new(self[0].mix(&other[0], &values[0]), - self[1].mix(&other[1], &values[1]), - self[2].mix(&other[2], &values[2]), - self[3].mix(&other[3], &values[3])) + pure fn mix(other: &Vec4, value: &Vec4) -> Vec4 { + Vec4::new(self[0].mix(&other[0], &value[0]), + self[1].mix(&other[1], &value[1]), + self[2].mix(&other[2], &value[2]), + self[3].mix(&other[3], &value[3])) + } + + #[inline(always)] + pure fn smooth_step(edge0: &Vec4, edge1: &Vec4) -> Vec4 { + Vec4::new(self[0].smooth_step(&edge0[0], &edge1[0]), + self[1].smooth_step(&edge0[1], &edge1[1]), + self[2].smooth_step(&edge0[2], &edge1[2]), + self[3].smooth_step(&edge0[3], &edge1[3])) + } + + #[inline(always)] + pure fn step(edge: &Vec4) -> Vec4 { + Vec4::new(self[0].step(&edge[0]), + self[1].step(&edge[1]), + self[2].step(&edge[2]), + self[3].step(&edge[3])) } } \ No newline at end of file