Skip to content

Instantly share code, notes, and snippets.

@saethlin
Created October 15, 2018 00:44
Show Gist options
  • Save saethlin/c82e0f62ee4c8400eca472dbd3b528e9 to your computer and use it in GitHub Desktop.
Save saethlin/c82e0f62ee4c8400eca472dbd3b528e9 to your computer and use it in GitHub Desktop.
extern crate dimensioned as dim; // it doesn't compile anyway but you need to know this
use dim::Sqrt;
use dim::si::Unitless;
use dim::typenum::{Diff, Prod, Quot, Sum};
use rand::Rng;
use std::ops::{Add, Div, Mul, Sub};
#[derive(Debug, Clone, Copy)]
pub struct Vec3<T> {
pub x: T,
pub y: T,
pub z: T,
}
impl<T: Div + Mul<T, Output = TT> + Add<T, Output = T> + Copy, TT: Sqrt<Output = T> + Copy> Vec3<T>
where
Prod<T, T>: Add,
TT: Add<TT, Output = TT>,
{
pub fn from_fn<F: FnMut() -> T>(mut f: F) -> Vec3<T> {
Vec3 {
x: f(),
y: f(),
z: f(),
}
}
pub fn normalized(&self) -> Vec3<Quot<T, T>> {
let length = ((self.x * self.x) + (self.y * self.y) + (self.z * self.z)).sqrt();
Vec3 {
x: self.x / length,
y: self.y / length,
z: self.z / length,
}
}
pub fn random_direction<R: Rng>(rng: &mut R) -> Vec3<Unitless<f64>> {
loop {
let v = Vec3::from_fn(|| Unitless::new(rng.gen_range(-1.0f64, 1.0f64)));
if (v.x * v.x + v.y * v.y + v.z * v.z) <= Unitless::new(1.0) {
break v.normalized();
}
}
}
pub fn dot<R: Copy>(&self, other: &Vec3<R>) -> Sum<Prod<T, R>, Prod<T, R>>
where
T: Mul<R>,
Prod<T, R>: Add<Output = Prod<T, R>>,
{
self.x * other.x + self.y * other.y + self.z * other.z
}
pub fn cross<R: Copy>(&self, other: &Vec3<R>) -> Vec3<Diff<Prod<T, R>, Prod<T, R>>>
where
T: Mul<R>,
Prod<T, R>: Sub,
{
Vec3 {
x: self.y * other.z - self.z * other.y,
y: self.z * other.x - self.x * other.z,
z: self.x * other.y - self.y * other.x,
}
}
}
impl<T: Add<R>, R> Add<Vec3<R>> for Vec3<T> {
type Output = Vec3<Sum<T, R>>;
fn add(self, rhs: Vec3<R>) -> Self::Output {
Vec3 {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
impl<T: Sub<R>, R> Sub<Vec3<R>> for Vec3<T> {
type Output = Vec3<Diff<T, R>>;
fn sub(self, rhs: Vec3<R>) -> Self::Output {
Vec3 {
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
}
}
}
impl<T: Mul<R>, R: Copy> Mul<R> for Vec3<T> {
type Output = Vec3<Prod<T, R>>;
fn mul(self, rhs: R) -> Self::Output {
Vec3 {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}
impl<T: Div<R>, R: Copy> Div<R> for Vec3<T> {
type Output = Vec3<Quot<T, R>>;
fn div(self, rhs: R) -> Self::Output {
Vec3 {
x: self.x / rhs,
y: self.y / rhs,
z: self.z / rhs,
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment