raytracer-rs/src/vec3.rs
2026-03-25 19:29:35 -04:00

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()
}
}