From 71cc075f3553690cbcf73a69b667a83f79721544 Mon Sep 17 00:00:00 2001 From: sebcrozet Date: Sun, 21 Oct 2018 22:11:41 +0200 Subject: [PATCH] Add mix, mix_scalar, mix_vec, lerp, lerp_scalar, lerp_vec. --- nalgebra-glm/src/common.rs | 237 +++++++++++++++++++++++++++++++------ 1 file changed, 203 insertions(+), 34 deletions(-) diff --git a/nalgebra-glm/src/common.rs b/nalgebra-glm/src/common.rs index 45b94336..a21681ba 100644 --- a/nalgebra-glm/src/common.rs +++ b/nalgebra-glm/src/common.rs @@ -1,9 +1,9 @@ -use std::mem; +use na::{self, DefaultAllocator, Real}; use num::FromPrimitive; -use na::{self, Real, DefaultAllocator}; +use std::mem; -use aliases::{TVec, TMat}; -use traits::{Number, Dimension, Alloc}; +use aliases::{TMat, TVec}; +use traits::{Alloc, Dimension, Number}; /// For each matrix or vector component `x` if `x >= 0`; otherwise, it returns `-x`. /// @@ -22,8 +22,10 @@ use traits::{Number, Dimension, Alloc}; /// /// * [`sign`](fn.sign.html) pub fn abs(x: &TMat) -> TMat - where DefaultAllocator: Alloc { - x.abs() +where + DefaultAllocator: Alloc, +{ + x.abs() } /// For each matrix or vector component returns a value equal to the nearest integer that is greater than or equal to `x`. @@ -44,7 +46,9 @@ pub fn abs(x: &TMat) -> TMat(x: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ x.map(|x| x.ceil()) } @@ -94,7 +98,9 @@ pub fn clamp_scalar(x: N, min_val: N, max_val: N) -> N { /// * [`clamp_scalar`](fn.clamp_scalar.html) /// * [`clamp_vec`](fn.clamp_vec.html) pub fn clamp(x: &TVec, min_val: N, max_val: N) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ x.map(|x| na::clamp(x, min_val, max_val)) } @@ -125,8 +131,14 @@ pub fn clamp(x: &TVec, min_val: N, max_val: N) -> /// /// * [`clamp_scalar`](fn.clamp_scalar.html) /// * [`clamp`](fn.clamp.html) -pub fn clamp_vec(x: &TVec, min_val: &TVec, max_val: &TVec) -> TVec - where DefaultAllocator: Alloc { +pub fn clamp_vec( + x: &TVec, + min_val: &TVec, + max_val: &TVec, +) -> TVec +where + DefaultAllocator: Alloc, +{ x.zip_zip_map(min_val, max_val, |a, min, max| na::clamp(a, min, max)) } @@ -161,7 +173,9 @@ pub fn float_bits_to_int(v: f32) -> i32 { /// * [`uint_bits_to_float`](fn.uint_bits_to_float.html) /// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html) pub fn float_bits_to_int_vec(v: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ v.map(float_bits_to_int) } @@ -196,7 +210,9 @@ pub fn float_bits_to_uint(v: f32) -> u32 { /// * [`uint_bits_to_float`](fn.uint_bits_to_float.html) /// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html) pub fn float_bits_to_uint_vec(v: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ v.map(float_bits_to_uint) } @@ -217,7 +233,9 @@ pub fn float_bits_to_uint_vec(v: &TVec) -> TVec /// * [`round`](fn.round.html) /// * [`trunc`](fn.trunc.html) pub fn floor(x: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ x.map(|x| x.floor()) } @@ -244,7 +262,9 @@ pub fn floor(x: &TVec) -> TVec /// * [`round`](fn.round.html) /// * [`trunc`](fn.trunc.html) pub fn fract(x: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ x.map(|x| x.fract()) } @@ -271,7 +291,6 @@ pub fn fract(x: &TVec) -> TVec /// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html) pub fn int_bits_to_float(v: i32) -> f32 { f32::from_bits(v as u32) - } /// For each components of `v`, returns a floating-point value corresponding to a signed integer encoding of a floating-point value. @@ -288,7 +307,9 @@ pub fn int_bits_to_float(v: i32) -> f32 { /// * [`uint_bits_to_float`](fn.uint_bits_to_float.html) /// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html) pub fn int_bits_to_float_vec(v: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ v.map(int_bits_to_float) } @@ -310,13 +331,155 @@ pub fn int_bits_to_float_vec(v: &TVec) -> TVec // x * (exp).exp2() //} -/// Returns `x * (1.0 - a) + y * a`, i.e., the linear blend of x and y using the floating-point value a. +/// Returns `x * (1.0 - a) + y * a`, i.e., the linear blend of the scalars x and y using the scalar value a. /// /// The value for a is not restricted to the range `[0, 1]`. -pub fn mix(x: N, y: N, a: N) -> N { +/// +/// # Examples: +/// +/// ``` +/// # use nalgebra_glm as glm; +/// assert_eq!(glm::mix_scalar(2.0, 20.0, 0.1), 3.8); +/// ``` +/// +/// # See also: +/// +/// * [`mix`](fn.mix.html) +/// * [`mix_vec`](fn.mix_vec.html) +pub fn mix_scalar(x: N, y: N, a: N) -> N { x * (N::one() - a) + y * a } +/// Returns `x * (1.0 - a) + y * a`, i.e., the linear blend of the vectors x and y using the scalar value a. +/// +/// The value for a is not restricted to the range `[0, 1]`. +/// +/// # Examples: +/// +/// ``` +/// # use nalgebra_glm as glm; +/// let x = glm::vec3(1.0, 2.0, 3.0); +/// let y = glm::vec3(10.0, 20.0, 30.0); +/// assert_eq!(glm::mix(&x, &y, 0.1), glm::vec3(1.9, 3.8, 5.7)); +/// ``` +/// +/// # See also: +/// +/// * [`mix_scalar`](fn.mix_scalar.html) +/// * [`mix_vec`](fn.mix_vec.html) +pub fn mix(x: &TVec, y: &TVec, a: N) -> TVec +where + DefaultAllocator: Alloc, +{ + x * (N::one() - a) + y * a +} + +/// Returns `x * (1.0 - a) + y * a`, i.e., the component-wise linear blend of `x` and `y` using the components of +/// the vector `a` as coefficients. +/// +/// The value for a is not restricted to the range `[0, 1]`. +/// +/// # Examples: +/// +/// ``` +/// # use nalgebra_glm as glm; +/// let x = glm::vec3(1.0, 2.0, 3.0); +/// let y = glm::vec3(10.0, 20.0, 30.0); +/// let a = glm::vec3(0.1, 0.2, 0.3); +/// assert_eq!(glm::mix_vec(&x, &y, &a), glm::vec3(1.9, 5.6, 11.1)); +/// ``` +/// +/// # See also: +/// +/// * [`mix_scalar`](fn.mix_scalar.html) +/// * [`mix`](fn.mix.html) +pub fn mix_vec( + x: &TVec, + y: &TVec, + a: &TVec, +) -> TVec +where + DefaultAllocator: Alloc, +{ + x.component_mul(&(TVec::::repeat(N::one()) - a)) + y.component_mul(&a) +} + +/// Returns `x * (1.0 - a) + y * a`, i.e., the linear blend of the scalars x and y using the scalar value a. +/// +/// The value for a is not restricted to the range `[0, 1]`. +/// This is an alias for `mix_scalar`. +/// +/// # Examples: +/// +/// ``` +/// # use nalgebra_glm as glm; +/// assert_eq!(glm::lerp_scalar(2.0, 20.0, 0.1), 3.8); +/// ``` +/// +/// # See also: +/// +/// * [`lerp`](fn.lerp.html) +/// * [`lerp_vec`](fn.lerp_vec.html) +pub fn lerp_scalar(x: N, y: N, a: N) -> N { + mix_scalar(x, y, a) +} + +/// Returns `x * (1.0 - a) + y * a`, i.e., the linear blend of the vectors x and y using the scalar value a. +/// +/// The value for a is not restricted to the range `[0, 1]`. +/// This is an alias for `mix`. +/// +/// # Examples: +/// +/// ``` +/// # use nalgebra_glm as glm; +/// let x = glm::vec3(1.0, 2.0, 3.0); +/// let y = glm::vec3(10.0, 20.0, 30.0); +/// assert_eq!(glm::lerp(&x, &y, 0.1), glm::vec3(1.9, 3.8, 5.7)); +/// ``` +/// +/// # See also: +/// +/// * [`lerp_scalar`](fn.lerp_scalar.html) +/// * [`lerp_vec`](fn.lerp_vec.html) +pub fn lerp(x: &TVec, y: &TVec, a: N) -> TVec +where + DefaultAllocator: Alloc, +{ + mix(x, y, a) +} + +/// Returns `x * (1.0 - a) + y * a`, i.e., the component-wise linear blend of `x` and `y` using the components of +/// the vector `a` as coefficients. +/// +/// The value for a is not restricted to the range `[0, 1]`. +/// This is an alias for `mix_vec`. +/// +/// # Examples: +/// +/// ``` +/// # use nalgebra_glm as glm; +/// let x = glm::vec3(1.0, 2.0, 3.0); +/// let y = glm::vec3(10.0, 20.0, 30.0); +/// let a = glm::vec3(0.1, 0.2, 0.3); +/// assert_eq!(glm::lerp_vec(&x, &y, &a), glm::vec3(1.9, 5.6, 11.1)); +/// ``` +/// +/// # See also: +/// +/// * [`lerp_scalar`](fn.lerp_scalar.html) +/// * [`lerp`](fn.lerp.html) +pub fn lerp_vec( + x: &TVec, + y: &TVec, + a: &TVec, +) -> TVec +where + DefaultAllocator: Alloc, +{ + mix_vec(x, y, a) +} + /// Component-wise modulus. /// /// Returns `x - y * floor(x / y)` for each component in `x` using the corresponding component of `y`. @@ -325,7 +488,9 @@ pub fn mix(x: N, y: N, a: N) -> N { /// /// * [`modf`](fn.modf.html) pub fn modf_vec(x: &TVec, y: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ x.zip_map(y, |x, y| x % y) } @@ -357,9 +522,10 @@ pub fn modf(x: N, i: N) -> N { /// * [`fract`](fn.fract.html) /// * [`trunc`](fn.trunc.html) pub fn round(x: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ x.map(|x| x.round()) - } //pub fn roundEven(x: &TVec) -> TVec @@ -382,14 +548,10 @@ pub fn round(x: &TVec) -> TVec /// * [`abs`](fn.abs.html) /// pub fn sign(x: &TVec) -> TVec - where DefaultAllocator: Alloc { - x.map(|x| { - if x.is_zero() { - N::zero() - } else { - x.signum() - } - }) +where + DefaultAllocator: Alloc, +{ + x.map(|x| if x.is_zero() { N::zero() } else { x.signum() }) } /// Returns 0.0 if `x <= edge0` and `1.0 if x >= edge1` and performs smooth Hermite interpolation between 0 and 1 when `edge0 < x < edge1`. @@ -414,13 +576,17 @@ pub fn step_scalar(edge: N, x: N) -> N { /// Returns 0.0 if `x[i] < edge`, otherwise it returns 1.0. pub fn step(edge: N, x: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ x.map(|x| step_scalar(edge, x)) } /// Returns 0.0 if `x[i] < edge[i]`, otherwise it returns 1.0. pub fn step_vec(edge: &TVec, x: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ edge.zip_map(x, step_scalar) } @@ -441,7 +607,9 @@ pub fn step_vec(edge: &TVec, x: &TVec) -> T /// * [`fract`](fn.fract.html) /// * [`round`](fn.round.html) pub fn trunc(x: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ x.map(|x| x.trunc()) } @@ -460,7 +628,6 @@ pub fn trunc(x: &TVec) -> TVec /// * [`uint_bits_to_float`](fn.uint_bits_to_float.html) pub fn uint_bits_to_float_scalar(v: u32) -> f32 { f32::from_bits(v) - } /// For each component of `v`, returns a floating-point value corresponding to a unsigned integer encoding of a floating-point value. @@ -477,6 +644,8 @@ pub fn uint_bits_to_float_scalar(v: u32) -> f32 { /// * [`int_bits_to_float_vec`](fn.int_bits_to_float_vec.html) /// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html) pub fn uint_bits_to_float(v: &TVec) -> TVec - where DefaultAllocator: Alloc { +where + DefaultAllocator: Alloc, +{ v.map(uint_bits_to_float_scalar) }