Skip to content

Commit

Permalink
- add quat * quat and quat * vec operators for different combinations…
Browse files Browse the repository at this point in the history
… of value * ref
  • Loading branch information
polymonster committed Apr 30, 2023
1 parent 1a86cda commit 1dee443
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 0 deletions.
8 changes: 8 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,14 @@ let q6 = -q;
let v = vec3f(1.0, 0.0, 0.0);
let vv = q * v3;

// multiply with refs or values without need to deref
let qref = &q;
let vref = &v3;

let qr = qref * v3;
let qr = q * v3ref;
let qr = qref * vref;

// functions
let rev = q.reverse();
let inv = q.inverse();
Expand Down
64 changes: 64 additions & 0 deletions src/quat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ impl<T> MulAssign<T> for Quat<T> where T: Number {
}
}

// value * value
impl<T> Mul<Self> for Quat<T> where T: Number {
type Output = Self;
fn mul(self, other: Self) -> Self {
Expand All @@ -314,6 +315,45 @@ impl<T> Mul<Self> for Quat<T> where T: Number {
}
}

// ref * value
impl<T> Mul<Quat<T>> for &Quat<T> where T: Number {
type Output = Quat<T>;
fn mul(self, other: Quat<T>) -> Quat<T> {
Quat {
w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z,
x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y,
y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.z,
z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w
}
}
}

// value * ref
impl<T> Mul<&Self> for Quat<T> where T: Number {
type Output = Self;
fn mul(self, other: &Self) -> Self {
Quat {
w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z,
x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y,
y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.z,
z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w
}
}
}

// ref * ref
impl<T> Mul<Self> for &Quat<T> where T: Number {
type Output = Quat<T>;
fn mul(self, other: Self) -> Quat<T> {
Quat {
w: self.w * other.w - self.x * other.x - self.y * other.y - self.z * other.z,
x: self.w * other.x + self.x * other.w + self.y * other.z - self.z * other.y,
y: self.w * other.y - self.x * other.z + self.y * other.w + self.z * other.z,
z: self.w * other.z + self.x * other.y - self.y * other.x + self.z * other.w
}
}
}

impl<T> MulAssign<Self> for Quat<T> where T: Number {
fn mul_assign(&mut self, other: Self) {
*self = Self::mul(*self, other);
Expand Down Expand Up @@ -349,6 +389,30 @@ impl<T> Mul<Vec3<T>> for Quat<T> where T: Number {
}
}

// ref * value
impl<T> Mul<Vec3<T>> for &Quat<T> where T: Number {
type Output = Vec3<T>;
fn mul(self, other: Vec3<T>) -> Vec3<T> {
(*self).mul(other)
}
}

// value * ref
impl<T> Mul<&Vec3<T>> for Quat<T> where T: Number {
type Output = Vec3<T>;
fn mul(self, other: &Vec3<T>) -> Vec3<T> {
self.mul(*other)
}
}

// ref * ref
impl<T> Mul<&Vec3<T>> for &Quat<T> where T: Number {
type Output = Vec3<T>;
fn mul(self, other: &Vec3<T>) -> Vec3<T> {
(*self).mul(*other)
}
}

impl<T> Dot<T> for Quat<T> where T: Float + FloatOps<T> {
fn dot(a: Self, b: Self) -> T {
a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w
Expand Down
29 changes: 29 additions & 0 deletions tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1976,6 +1976,19 @@ fn quat() {
let mut euler_mul_asign = euler_22z;
euler_mul_asign *= euler_22z;
assert_eq!(euler_mul_asign, euler_mul);

// val * ref
let euler_22z_ref = &euler_22z;
let euler_mul = euler_22z * euler_22z_ref;
assert_eq!(approx(Vec3f::from(Quatf::to_euler_angles(euler_45z)), Vec3f::from(Quatf::to_euler_angles(euler_mul)), 0.1), true);

// ref * val
let euler_mul = euler_22z_ref * euler_22z;
assert_eq!(approx(Vec3f::from(Quatf::to_euler_angles(euler_45z)), Vec3f::from(Quatf::to_euler_angles(euler_mul)), 0.1), true);

// ref * ref
let euler_mul = euler_22z_ref * euler_22z_ref;
assert_eq!(approx(Vec3f::from(Quatf::to_euler_angles(euler_45z)), Vec3f::from(Quatf::to_euler_angles(euler_mul)), 0.1), true);
}

#[test]
Expand All @@ -1997,6 +2010,22 @@ fn quat_vec() {
// rotate 45 degrees clockwise about x
let r1 = euler_45x * v2;
assert_eq!(approx(r1, normalize(vec3f(0.0, 0.5, -0.5)), 0.01), true);

// refs
let euler_45x_ref = &euler_45x;
let v2_ref = &v2;

// quat * vec ref
let r1 = euler_45x * v2_ref;
assert_eq!(approx(r1, normalize(vec3f(0.0, 0.5, -0.5)), 0.01), true);

// quat ref * vec
let r1 = euler_45x_ref * v2;
assert_eq!(approx(r1, normalize(vec3f(0.0, 0.5, -0.5)), 0.01), true);

// quat ref * vec ref
let r1 = euler_45x_ref * v2_ref;
assert_eq!(approx(r1, normalize(vec3f(0.0, 0.5, -0.5)), 0.01), true);
}

#[test]
Expand Down

0 comments on commit 1dee443

Please sign in to comment.