Renderer/src/vec3.rs
Jonathan Flueren bfa58c6962 Add images
2022-08-02 18:30:39 +02:00

203 lines
4.6 KiB
Rust

use super::utility;
use std::ops::*;
#[derive(Clone, Copy, Debug)]
pub struct Vec3 {
pub e: [f64; 3],
}
pub type Color = Vec3;
pub type Point3 = Vec3;
impl Vec3 {
pub fn new(x: f64, y: f64, z: f64) -> Self {
Vec3 { e: [x, y, z] }
}
pub fn null() -> Self {
Self::new(0.0, 0.0, 0.0)
}
pub fn clone(&self) -> Self {
Self::new(self.x(), self.y(), self.z())
}
pub fn length(&self) -> f64 {
self.length_squared().sqrt()
}
pub fn length_squared(&self) -> f64 {
self.e[0] * self.e[0] + self.e[1] * self.e[1] + self.e[2] * self.e[2]
}
pub fn diff(a: &Self, b: &Self) -> f64 {
(a.x() - b.x()).abs() + (a.y() - b.y()).abs() + (a.z() - b.z()).abs()
}
pub fn cross(a: Vec3, b: Vec3) -> Vec3 {
Vec3::new(
a.y() * b.z() - a.z() * b.y(),
a.z() * b.x() - a.x() * b.z(),
a.x() * b.y() - a.y() * b.x(),
)
}
pub fn dot(a: Vec3, b: Vec3) -> f64 {
a.x() * b.x() + a.y() * b.y() + a.z() * b.z()
}
pub fn unit_vector(a: Vec3) -> Vec3 {
a / a.length()
}
pub fn reflect(v: &Self, n: &Self) -> Self {
*v - 2.0 * Self::dot(*v, *n) * *(n)
}
pub fn refract(uv: &Self, n: &Self, etai_over_etat: f64) -> Self {
let cos_theta = Self::dot(-1.0 * *uv, *n).min(1.0); // Minimum aus 1.0 und Punktprodukt
let r_out_perp = etai_over_etat * (*uv + cos_theta * *n);
let r_out_parallel = -(1.0 - r_out_perp.length_squared()).abs().sqrt() * *n;
return r_out_perp + r_out_parallel;
}
pub fn near_zero(&self) -> bool {
let s = 1e-8;
return (self.e[0].abs() < s) && (self.e[1].abs() < s) && (self.e[2].abs() < s);
}
pub fn random_f64() -> Vec3 {
Vec3::new(
utility::random_f64(),
utility::random_f64(),
utility::random_f64(),
)
}
pub fn random_rng(min: f64, max: f64) -> Self {
Self::new(
utility::random_rng(min, max),
utility::random_rng(min, max),
utility::random_rng(min, max),
)
}
pub fn random_in_unit_sphere() -> Self {
loop {
let p = Vec3::random_rng(-1.0, 1.0);
if p.length_squared() >= 1.0 {
continue;
}
return p;
}
}
pub fn random_in_unit_disk() -> Self {
loop {
let p = Vec3::new(
utility::random_rng(-1.0, 1.0),
utility::random_rng(-1.0, 1.0),
0.0,
);
if p.length_squared() >= 1.0 {
continue;
}
return p;
}
}
pub fn random_unit_vector() -> Self {
Self::unit_vector(Self::random_in_unit_sphere())
}
pub fn random_in_hemisphere(&self) -> Self {
let in_unit_sphere = Self::random_in_unit_sphere();
if Self::dot(in_unit_sphere, *self) > 0.0 {
return in_unit_sphere;
} else {
return -1.0 * in_unit_sphere;
}
}
pub fn x(&self) -> f64 {
self.e[0]
}
pub fn y(&self) -> f64 {
self.e[1]
}
pub fn z(&self) -> f64 {
self.e[2]
}
}
impl Add for Vec3 {
type Output = Vec3;
fn add(self, rhs: Self) -> Vec3 {
Vec3::new(self.x() + rhs.x(), self.y() + rhs.y(), self.z() + rhs.z())
}
}
impl AddAssign for Vec3 {
fn add_assign(&mut self, rhs: Self) {
self.e[0] += rhs.x();
self.e[1] += rhs.y();
self.e[2] += rhs.z();
}
}
impl Sub for Vec3 {
type Output = Vec3;
fn sub(self, rhs: Self) -> Vec3 {
Vec3::new(self.x() - rhs.x(), self.y() - rhs.y(), self.z() - rhs.z())
}
}
impl SubAssign for Vec3 {
fn sub_assign(&mut self, rhs: Self) {
self.e[0] -= rhs.x();
self.e[1] -= rhs.y();
self.e[2] -= rhs.z();
}
}
impl Mul<Vec3> for f64 {
type Output = Vec3;
fn mul(self, rhs: Vec3) -> Vec3 {
Vec3::new(self * rhs.x(), self * rhs.y(), self * rhs.z())
}
}
impl Mul<Self> for Vec3 {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
Self::new(self.x() * rhs.x(), self.y() * rhs.y(), self.z() * rhs.z())
}
}
impl MulAssign<f64> for Vec3 {
fn mul_assign(&mut self, rhs: f64) {
self.e[0] *= rhs;
self.e[1] *= rhs;
self.e[2] *= rhs;
}
}
impl DivAssign<f64> for Vec3 {
fn div_assign(&mut self, rhs: f64) {
self.e[0] /= rhs;
self.e[1] /= rhs;
self.e[2] /= rhs;
}
}
impl Div<f64> for Vec3 {
type Output = Vec3;
fn div(self, rhs: f64) -> Vec3 {
Vec3::new(self.x() / rhs, self.y() / rhs, self.z() / rhs)
}
}