137 lines
2.8 KiB
Rust
137 lines
2.8 KiB
Rust
use std::ops::{Add, Div, Mul, Sub};
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct Vec3 {
|
|
x: f64,
|
|
y: f64,
|
|
z: f64,
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct Point3 {
|
|
x: f64,
|
|
y: f64,
|
|
z: f64,
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct Ray {
|
|
direction: Vec3,
|
|
origin: Point3,
|
|
}
|
|
|
|
impl Ray {
|
|
pub fn new(origin: Point3, direction: Vec3) -> Ray {
|
|
Ray { direction, origin }
|
|
}
|
|
pub fn at(self, t: f64) -> Point3 {
|
|
(self.origin.to_vec() + Vec3 { x: t, y: t, z: t } * self.direction).to_point()
|
|
}
|
|
pub fn direction(self) -> Vec3 {
|
|
self.direction
|
|
}
|
|
pub fn origin(self) -> Point3 {
|
|
self.origin
|
|
}
|
|
}
|
|
|
|
macro_rules! impl_op {
|
|
($trait:ident, $func:ident, $op:tt, $who:ident) => {
|
|
impl $trait for $who {
|
|
type Output = Self;
|
|
fn $func(self, other: Self) -> Self {
|
|
Self {
|
|
x: self.x $op other.x,
|
|
y: self.y $op other.y,
|
|
z: self.z $op other.z,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl $trait<f64> for $who {
|
|
type Output = Self;
|
|
fn $func(self, value: f64) -> Self {
|
|
Self {
|
|
x: self.x $op value,
|
|
y: self.y $op value,
|
|
z: self.z $op value,
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
impl_op!(Add, add, +,Vec3);
|
|
impl_op!(Sub, sub, -,Vec3);
|
|
impl_op!(Mul, mul, *,Vec3);
|
|
impl_op!(Div, div, /,Vec3);
|
|
|
|
impl_op!(Add, add, +,Point3);
|
|
impl_op!(Sub, sub, -,Point3);
|
|
impl_op!(Mul, mul, *,Point3);
|
|
impl_op!(Div, div, /,Point3);
|
|
|
|
impl Point3 {
|
|
pub fn new(x: f64, y: f64, z: f64) -> Point3 {
|
|
Point3 { x, y, z }
|
|
}
|
|
pub fn to_vec(self) -> Vec3 {
|
|
Vec3 {
|
|
x: self.x,
|
|
y: self.y,
|
|
z: self.z,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Vec3 {
|
|
pub fn new(x: f64, y: f64, z: f64) -> Vec3 {
|
|
Vec3 { x, y, z }
|
|
}
|
|
|
|
pub fn full(v: f64) -> Vec3 {
|
|
Vec3 { x: v, y: v, z: v }
|
|
}
|
|
|
|
pub fn to_point(self) -> Point3 {
|
|
Point3 {
|
|
x: self.x,
|
|
y: self.y,
|
|
z: self.z,
|
|
}
|
|
}
|
|
pub fn dot(self, other: Vec3) -> f64 {
|
|
self.x * other.x + self.y * other.y + self.z * other.z
|
|
}
|
|
|
|
pub fn x(self) -> f64 {
|
|
self.x
|
|
}
|
|
|
|
pub fn y(self) -> f64 {
|
|
self.y
|
|
}
|
|
|
|
pub fn z(self) -> f64 {
|
|
self.z
|
|
}
|
|
|
|
pub fn cross(self, other: Vec3) -> Vec3 {
|
|
let x = self.y * other.z - self.z * other.y;
|
|
let y = self.y * other.x - self.x * other.y;
|
|
let z = self.x * other.y - self.y * other.x;
|
|
Vec3 { x, y, z }
|
|
}
|
|
|
|
pub fn length_squared(self) -> f64 {
|
|
self.x * self.x + self.y * self.y + self.z * self.z
|
|
}
|
|
|
|
pub fn length(self) -> f64 {
|
|
self.length_squared().sqrt()
|
|
}
|
|
|
|
pub fn unit(self) -> Vec3 {
|
|
self / self.length()
|
|
}
|
|
}
|