1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
use number_traits::{Cast, Signed, Sqrt, Trig}; use create::clone; use length::normalize; pub use vec4::inverse; pub use vec4::lerp; pub use vec4::min; pub use vec4::max; pub use vec4::clamp; pub use vec4::eq; pub use vec4::ne; #[inline] pub fn conjugate<'a, 'b, T: Copy + Signed>(out: &'a mut [T; 4], a: &'b [T; 4]) -> &'a mut [T; 4] { out[0] = -a[0]; out[1] = -a[1]; out[2] = -a[2]; out[3] = a[3]; out } #[test] fn test_conjugate() { let mut v = [0, 0, 0, 0]; conjugate(&mut v, &[1, 1, 1, 1]); assert!(v[0] == -1); assert!(v[1] == -1); assert!(v[2] == -1); assert!(v[3] == 1); } #[inline] pub fn calculate_w<'a, 'b, T: Copy + Signed + Sqrt>(out: &'a mut [T; 4], a: &'b [T; 4]) -> &'a mut [T; 4] { out[0] = a[0]; out[1] = a[1]; out[2] = a[2]; out[3] = (T::one() - a[0] * a[0] - a[1] * a[1] - a[2] * a[2]).abs().sqrt(); out } #[inline] pub fn nlerp<'a, 'b, T, F>(out: &'a mut [T; 4], a: &'b [T; 4], b: &'b [T; 4], t: F) -> &'a mut [T; 4] where T: Copy + Signed + Cast<F> + Sqrt, F: Copy + Signed + Cast<T>, { let tmp = clone(lerp(out, a, b, t)); normalize(out, &tmp) } #[test] fn test_nlerp() { use super::create::new; assert_eq!(slerp(&mut new(0, 0, 0, 1), &new(0, 0, 0, 1), &new(0, 0, 0, 1), 0.5), &new(0, 0, 0, 1)); } #[inline] pub fn slerp<'a, 'b, T, F>(out: &'a mut [T; 4], a: &'b [T; 4], b: &'b [T; 4], t: F) -> &'a mut [T; 4] where T: Copy + Signed + Cast<F>, F: Copy + Signed + Cast<T> + Trig, { let ax = a[0].cast(); let ay = a[1].cast(); let az = a[2].cast(); let aw = a[3].cast(); let mut bx = b[0].cast(); let mut by = b[1].cast(); let mut bz = b[2].cast(); let mut bw = b[3].cast(); let mut cosom = ax * bx + ay * by + az * bz + aw * bw; let mut sinom; let omega; let scale0; let scale1; if cosom < F::zero() { cosom = -cosom; bx = -bx; by = -by; bz = -bz; bw = -bw; } if F::one() - cosom > F::zero() { omega = cosom.acos(); sinom = omega.sin(); sinom = if sinom != F::zero() {F::one() / sinom} else {sinom}; scale0 = ((F::one() - t) * omega).sin() * sinom; scale1 = (t * omega).sin() * sinom; } else { scale0 = F::one() - t; scale1 = t; } out[0] = (scale0 * ax + scale1 * bx).cast(); out[1] = (scale0 * ay + scale1 * by).cast(); out[2] = (scale0 * az + scale1 * bz).cast(); out[3] = (scale0 * aw + scale1 * bw).cast(); out } #[test] fn test_slerp() { use super::create::new; assert_eq!(slerp(&mut new(0, 0, 0, 1), &new(0, 0, 0, 1), &new(0, 0, 0, 1), 0.5), &new(0, 0, 0, 1)); }