From 430bdf63bc8421e417f6595dfec5f3c2bc539760 Mon Sep 17 00:00:00 2001 From: djairoh Date: Sat, 25 Apr 2026 14:46:03 +0200 Subject: [PATCH] ft (wip): deserialization --- Cargo.lock | 3 + Cargo.toml | 2 + scenes/scene.json | 33 +++++ src/camera.rs | 58 ++++++-- src/main.rs | 77 +++++----- src/objects/hit.rs | 2 +- src/objects/materials/dielectric.rs | 2 + src/objects/materials/lambertian.rs | 3 + src/objects/materials/traits.rs | 3 +- src/objects/sphere.rs | 13 ++ src/objects/traits.rs | 4 +- src/scenes.rs | 2 + src/scenes/raw_camera.rs | 61 ++++++++ src/scenes/scene.rs | 107 ++++++++++++++ src/vec3.rs | 209 +++++++++++++++------------- 15 files changed, 421 insertions(+), 158 deletions(-) create mode 100644 scenes/scene.json create mode 100644 src/scenes.rs create mode 100644 src/scenes/raw_camera.rs create mode 100644 src/scenes/scene.rs diff --git a/Cargo.lock b/Cargo.lock index 1454cc9..1150ab5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1240,6 +1240,8 @@ dependencies = [ "ops", "pretty_env_logger", "rand 0.10.1", + "serde", + "serde_json", ] [[package]] @@ -1311,6 +1313,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", + "serde_derive", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index c904284..96da94d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,5 @@ log = "0.4.29" ops = "0.6.0" pretty_env_logger = "0.5.0" rand = "0.10.1" +serde = {version = "1.0.228", features = ["derive"]} +serde_json = "1.0.149" diff --git a/scenes/scene.json b/scenes/scene.json new file mode 100644 index 0000000..3f9b7af --- /dev/null +++ b/scenes/scene.json @@ -0,0 +1,33 @@ +{ + "camera": { + "image_width": 1920, + "image_height": 1080, + "anti_alias_rate": 3, + "max_depth": 50, + "fov": 90.0, + "look_from": { "x": 0, "y": 0, "z": 0 }, + "look_at": { "x": 0.0, "y": 0.0, "z": -1.0 }, + "vup": { "x": 0.0, "y": 1.0, "z": 0.0 } + }, + "materials": [ + { "type": "metal", "albedo": { "x": 0.2, "y": 0.4, "z": 0.8 }, "prob": 1.0, "fuzz": 0.1 }, + { "type": "metal", "albedo": { "x": 0.7, "y": 0.4, "z": 0.2 }, "prob": 1.0, "fuzz": 0.1 }, + { "type": "lambertian", "albedo": { "x": 0.8, "y": 0.8, "z": 0.0 }, "prob": 1.0 }, + { "type": "lambertian", "albedo": { "x": 0.1, "y": 0.2, "z": 0.5 }, "prob": 1.0 }, + { "type": "dielectric", "refraction_index": 1.5}, + { "type": "dielectric", "refraction_index": 0.67}, + { "type": "metal", "albedo": { "x": 0.8, "y": 0.6, "z": 0.2 }, "prob": 1.0, "fuzz": 1.0 } + + ], + "objects": [ + { "type": "sphere", "center": { "x": 0, "y": 0.7, "z": -0.4 }, "radius": 0.2, "material": 0}, + { "type": "sphere", "center": { "x": 0.0, "y": 0.5, "z": -0.8 }, "radius": 0.1, "material": 1}, + { "type": "sphere", "center": { "x": 0.0, "y": -100.5, "z": -1.0 }, "radius": 100.0, "material": 2}, + { "type": "sphere", "center": { "x": 0.0, "y": 0.0, "z": -1.2 }, "radius": 0.5, "material": 3}, + { "type": "sphere", "center": { "x": -1, "y": 0, "z": -1 }, "radius": 0.4, "material": 5}, + { "type": "sphere", "center": { "x": 1, "y": 0, "z": -1 }, "radius": 0.5, "material": 6} + ] +} + + + diff --git a/src/camera.rs b/src/camera.rs index 8db90d9..289c990 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,6 +1,7 @@ -use std::f32::consts::PI; +use std::{f32::consts::PI, sync::Arc}; use log::info; +use serde::Deserialize; use crate::{ objects::{hit::Hit, traits::Hittable}, @@ -42,21 +43,50 @@ fn deg_to_rad(deg: f32) -> f32 { impl Camera { pub fn new(image_width: u32, image_height: u32) -> Self { Self { - image_width: image_width, - image_height: image_height, + image_width, + image_height, anti_alias_rate: 1, max_depth: 10, dirty: true, fov: 60., - pixel00_loc: Vec3::nil(), - pixel_delta_u: Vec3::nil(), - pixel_delta_v: Vec3::nil(), + pixel00_loc: Vec3::default(), + pixel_delta_u: Vec3::default(), + pixel_delta_v: Vec3::default(), look_from: Vec3::nil(), look_at: Vec3::new(0., 0., -1.), vup: Vec3::new(0., 1., 0.), - u: Vec3::nil(), - v: Vec3::nil(), - w: Vec3::nil(), + u: Vec3::default(), + v: Vec3::default(), + w: Vec3::default(), + } + } + + pub fn new_full( + image_width: u32, + image_height: u32, + anti_alias_rate: u32, + max_depth: u32, + fov: f32, + look_from: Vec3, + look_at: Vec3, + vup: Vec3, + ) -> Self { + Self { + image_width, + image_height, + anti_alias_rate, + max_depth, + pixel00_loc: Vec3::default(), + pixel_delta_u: Vec3::default(), + pixel_delta_v: Vec3::default(), + dirty: true, + fov, + look_from, + look_at, + vup, + u: Vec3::default(), + v: Vec3::default(), + w: Vec3::default(), } } @@ -125,7 +155,7 @@ impl Camera { } } - pub fn render(&mut self, hittables: &Vec) { + pub fn render(&mut self, hittables: &Vec>) { if self.dirty { self.init() } @@ -139,7 +169,7 @@ impl Camera { let pixel_tl = self.pixel00_loc + (i * self.pixel_delta_u) + (j * self.pixel_delta_v); - let mut pixel_colour = Colour::nil(); + let mut pixel_colour = Colour::default(); for y in 1..(self.anti_alias_rate + 1) { for x in 1..(self.anti_alias_rate + 1) { let pixel_loc = pixel_tl @@ -161,9 +191,9 @@ impl Camera { imgbuf.save("output.png").unwrap(); } - fn ray_colour(&self, hittables: &Vec, r: &Ray, depth: u32) -> Colour { + fn ray_colour(&self, hittables: &Vec>, r: &Ray, depth: u32) -> Colour { if depth <= 0 { - return Colour::nil(); + return Colour::default(); } let closest = Hit::hit_list(hittables, r); @@ -171,7 +201,7 @@ impl Camera { if let Some((scattered, att)) = hit.mat().scatter(&hit, r) { return att * self.ray_colour(hittables, &scattered, depth - 1); } - return Colour::nil(); + return Colour::default(); } // background diff --git a/src/main.rs b/src/main.rs index e12ff8a..6470ffd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,17 +3,19 @@ mod camera; mod objects; mod ray; +mod scenes; mod vec3; +use std::fs; use std::sync::Arc; -use crate::camera::Camera; use crate::objects::materials::dielectric::Dielectric; use crate::objects::materials::lambertian::{Lambertian, Metal}; use crate::objects::materials::traits::Material; use crate::objects::sphere::Sphere; use crate::objects::traits::Hittable; use crate::ray::Ray; +use crate::scenes::scene::Scene; use crate::vec3::Vec3; use dotenv::dotenv; use log::info; @@ -41,7 +43,7 @@ fn random_sphere_on_floor( let r = rng.random_range(0.1..max_size); let mut sphere = Sphere::xyz( rng.random_range((-50.)..50.), - r, + rng.random_range(0.1..max_size), rng.random_range((-50.)..50.), r, materials.choose(&mut rng).unwrap().clone(), @@ -70,49 +72,40 @@ fn random_sphere_on_floor( sphere } +// FIXME: bunch of unwraps/expects in deserialization code +// TODO: implement scene serialization fn main() { dotenv().ok(); pretty_env_logger::init(); - // setup objects - // let blue = Arc::new(Metal::rgb(0.2, 0.4, 0.8, 1., 0.1)); - // let metal = Arc::new(Metal::rgb(0.7, 0.4, 0.2, 1., 0.1)); - // let ground = Arc::new(Lambertian::rgb(0.8, 0.8, 0., 1.0)); - // let center = Arc::new(Lambertian::rgb(0.1, 0.2, 0.5, 1.)); - // let left = Arc::new(Dielectric::new(1.5)); - // let bubble = Arc::new(Dielectric::new(1. / 1.5)); - // let right = Arc::new(Metal::rgb(0.8, 0.6, 0.2, 1., 1.0)); + // TODO: use cli arg for scenefile + let json_str = fs::read_to_string("./scenes/scene.json").expect("waddehell!"); + let mut scene: Scene = serde_json::from_str(&json_str).unwrap(); + scene.render(); + + // random spheres code; thought: make this available as cli flag? + // let mut materials: Vec> = vec![Arc::new(Lambertian::rgb(0.1, 0.1, 0.2, 0.8))]; + // for i in 0..15 { + // info!("Generating {}th material.", i + 1); + // materials.push(random_material()); + // } // - // let mut world = vec![Sphere::xyz(0., 0.5, -0.8, 0.1, metal.clone())]; - // world.push(Sphere::xyz(0., -100.5, -1., 100., ground.clone())); - // world.push(Sphere::xyz(0., 0., -1.2, 0.5, center.clone())); - // world.push(Sphere::xyz(-1., 0., -1.0, 0.5, left.clone())); - // world.push(Sphere::xyz(-1., 0., -1.0, 0.4, bubble.clone())); - // world.push(Sphere::xyz(1., 0., -1.0, 0.5, right.clone())); - // world.push(Sphere::xyz(0., 0.7, -0.4, 0.2, blue.clone())); - - let mut materials: Vec> = vec![Arc::new(Lambertian::rgb(0.1, 0.2, 0.6, 1.))]; - for i in 0..15 { - info!("Generating {}th material.", i + 1); - materials.push(random_material()); - } - - let mut world = vec![Sphere::xyz(0., -1000.5, -1., 1000., materials[0].clone())]; - for i in 0..40 { - info!("Generating {}th sphere.", i + 1); - world.push(random_sphere_on_floor( - &materials, - &world, - (i + 1) as f32 / 3., - )); - } - - // let mut c = Camera::new(400, 300); - let mut c = Camera::new(1920, 1080); - c.set_fov(90.); - c.set_anti_alias_rate(6); - c.set_max_depth(100); - c.set_look_from(Vec3::new(-60., 10., 1.)); - c.set_look_at(Vec3::new(0., 0., 0.)); - c.render(&world); + // let mut world = vec![Sphere::xyz(0., -1000.5, -1., 1000., materials[0].clone())]; + // for i in 0..40 { + // info!("Generating {}th sphere.", i + 1); + // world.push(random_sphere_on_floor( + // &materials, + // &world, + // ((i + 1) as f32).ln() + (15. as f32).log(10.), + // )); + // } + // + // // let mut c = Camera::new(400, 300); + // let mut c = Camera::new(1920, 1080); + // c.set_fov(60.); + // c.set_anti_alias_rate(1); + // c.set_max_depth(10); + // c.set_look_from(Vec3::new(-60., 10., 1.)); + // c.set_look_at(Vec3::new(0., 0., 0.)); + // c.render(&world); } diff --git a/src/objects/hit.rs b/src/objects/hit.rs index b1caaba..a01b067 100644 --- a/src/objects/hit.rs +++ b/src/objects/hit.rs @@ -45,7 +45,7 @@ impl Hit { self.front_face } - pub fn hit_list(hittables: &Vec, r: &Ray) -> Option { + pub fn hit_list(hittables: &Vec>, r: &Ray) -> Option { let mut closest: Option = None; for hittable in hittables { if let Some(hit) = hittable.hit(r) { diff --git a/src/objects/materials/dielectric.rs b/src/objects/materials/dielectric.rs index dfb8fd1..a8344a1 100644 --- a/src/objects/materials/dielectric.rs +++ b/src/objects/materials/dielectric.rs @@ -1,6 +1,7 @@ use core::f32::math::sqrt; use rand::RngExt; +use serde::Deserialize; use crate::{ objects::{hit::Hit, materials::traits::Material}, @@ -8,6 +9,7 @@ use crate::{ vec3::{Colour, Vec3}, }; +#[derive(Debug, Deserialize)] pub struct Dielectric { refraction_index: f32, } diff --git a/src/objects/materials/lambertian.rs b/src/objects/materials/lambertian.rs index 127298e..23a01db 100644 --- a/src/objects/materials/lambertian.rs +++ b/src/objects/materials/lambertian.rs @@ -1,4 +1,5 @@ use rand::RngExt; +use serde::Deserialize; use crate::{ objects::{hit::Hit, materials::traits::Material}, @@ -6,6 +7,7 @@ use crate::{ vec3::{Colour, Vec3}, }; +#[derive(Debug, Deserialize)] pub struct Lambertian { albedo: Colour, prob: f32, @@ -42,6 +44,7 @@ impl Material for Lambertian { } } +#[derive(Debug, Deserialize)] pub struct Metal { albedo: Colour, prob: f32, diff --git a/src/objects/materials/traits.rs b/src/objects/materials/traits.rs index a2024ea..2b7d519 100644 --- a/src/objects/materials/traits.rs +++ b/src/objects/materials/traits.rs @@ -1,5 +1,6 @@ use crate::{objects::hit::Hit, ray::Ray, vec3::Colour}; +use std::fmt::Debug; -pub trait Material { +pub trait Material: Debug { fn scatter(&self, hit: &Hit, ray: &Ray) -> Option<(Ray, Colour)>; } diff --git a/src/objects/sphere.rs b/src/objects/sphere.rs index d21b1a0..0392a12 100644 --- a/src/objects/sphere.rs +++ b/src/objects/sphere.rs @@ -1,6 +1,9 @@ use core::f32::math::sqrt; +use std::fmt::{self, Debug}; use std::sync::Arc; +use serde::Deserialize; + use crate::objects::hit::Hit; use crate::objects::materials::traits::Material; use crate::objects::traits::Hittable; @@ -13,6 +16,16 @@ pub struct Sphere { material: Arc, } +impl Debug for Sphere { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Sphere") + .field("center", &self.center) + .field("radius", &self.radius) + .field("material", &self.material) + .finish() + } +} + impl Sphere { pub fn new(center: Vec3, r: f32, mat: Arc) -> Self { Self { diff --git a/src/objects/traits.rs b/src/objects/traits.rs index 1d7056e..fc4cdc5 100644 --- a/src/objects/traits.rs +++ b/src/objects/traits.rs @@ -1,8 +1,10 @@ +use std::fmt::Debug; + use crate::objects::hit::Hit; use crate::Ray; use crate::Vec3; -pub trait Hittable { +pub trait Hittable: Debug { fn hit(&self, r: &Ray) -> Option; fn normal_at(&self, p: &Vec3) -> Vec3; // fn intersect(&self, o: &H) -> bool; diff --git a/src/scenes.rs b/src/scenes.rs new file mode 100644 index 0000000..11fab98 --- /dev/null +++ b/src/scenes.rs @@ -0,0 +1,2 @@ +pub mod raw_camera; +pub mod scene; diff --git a/src/scenes/raw_camera.rs b/src/scenes/raw_camera.rs new file mode 100644 index 0000000..df69abb --- /dev/null +++ b/src/scenes/raw_camera.rs @@ -0,0 +1,61 @@ +use serde::Deserialize; + +use crate::{camera::Camera, vec3::Vec3}; + +#[derive(Deserialize)] +pub struct RawCamera { + // output + image_width: u32, // TODO: test these are now explicitly required (and that default impl does + // not make these optional) + image_height: u32, + + // raytracing + #[serde(default)] + anti_alias_rate: u32, + #[serde(default)] + max_depth: u32, + + // camera + #[serde(default)] + fov: f32, + #[serde(default)] + look_from: Vec3, + #[serde(default)] + look_at: Vec3, + #[serde(default)] + vup: Vec3, +} + +impl Default for RawCamera { + fn default() -> Self { + Self { + image_width: 400, + image_height: 300, + anti_alias_rate: 1, + max_depth: 10, + fov: 70., + look_from: Vec3::new(0., 0., 0.), + look_at: Vec3::new(0., 0., -1.), + vup: Vec3::new(0., 1., 0.), + } + } +} + +impl TryFrom for Camera { + type Error = String; + + fn try_from(raw: RawCamera) -> Result { + let c = Camera::new_full( + raw.image_width, + raw.image_height, + raw.anti_alias_rate, + raw.max_depth, + raw.fov, + raw.look_from, + raw.look_at, + raw.vup, + ); + + Ok(c) + } +} diff --git a/src/scenes/scene.rs b/src/scenes/scene.rs new file mode 100644 index 0000000..adbe888 --- /dev/null +++ b/src/scenes/scene.rs @@ -0,0 +1,107 @@ +use std::{ + fmt::{self, Debug}, + sync::Arc, +}; + +use serde::Deserialize; + +use crate::{ + camera::Camera, + objects::{ + materials::{ + dielectric::Dielectric, + lambertian::{Lambertian, Metal}, + traits::Material, + }, + sphere::Sphere, + traits::Hittable, + }, + scenes::raw_camera::RawCamera, + vec3::Vec3, +}; + +pub struct Scene { + pub camera: Camera, + pub materials: Vec>, + pub objects: Vec>, +} + +impl Scene { + pub fn render(&mut self) { + self.camera.render(&self.objects); + } +} + +#[derive(Deserialize)] +struct SceneDef { + pub camera: RawCamera, + pub materials: Vec, + pub objects: Vec, +} + +impl<'de> Deserialize<'de> for Scene { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let conc = SceneDef::deserialize(deserializer)?; + let mats: Vec> = conc + .materials + .into_iter() + .map(MaterialDef::into_arc) + .collect(); + let objs: Vec> = conc + .objects + .into_iter() + .map(|h| h.into_arc(&mats)) + .collect(); + Ok(Self { + camera: Camera::try_from(conc.camera).unwrap(), + materials: mats, + objects: objs, + }) + } +} + +#[derive(Deserialize)] +struct RawSphere { + pub center: Vec3, + pub radius: f32, + pub material: u32, +} + +#[derive(Deserialize)] +#[serde(tag = "type", rename_all = "lowercase")] +enum HittableDef { + Sphere(RawSphere), +} + +impl HittableDef { + fn into_arc(self, materials: &Vec>) -> Arc { + match self { + HittableDef::Sphere(s) => Arc::new(Sphere::new( + s.center, + s.radius, + materials.get(s.material as usize).unwrap().clone(), + )), + } + } +} + +#[derive(Deserialize)] +#[serde(tag = "type", rename_all = "lowercase")] +enum MaterialDef { + Lambertian(Lambertian), + Metal(Metal), + Dielectric(Dielectric), +} + +impl MaterialDef { + fn into_arc(self) -> Arc { + match self { + MaterialDef::Lambertian(l) => Arc::new(l), + MaterialDef::Metal(m) => Arc::new(m), + MaterialDef::Dielectric(d) => Arc::new(d), + } + } +} diff --git a/src/vec3.rs b/src/vec3.rs index dcb6d10..0416d32 100644 --- a/src/vec3.rs +++ b/src/vec3.rs @@ -1,39 +1,40 @@ use core::f32::math::sqrt; use is_close::default; use rand::RngExt; +use serde::Deserialize; use std::{ fmt::Display, ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign}, }; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, Deserialize)] pub struct Vec3 { - r: f32, - g: f32, - b: f32, + x: f32, + y: f32, + z: f32, } pub type Colour = Vec3; impl Vec3 { pub fn new(r: f32, g: f32, b: f32) -> Self { - Self { r: r, g: g, b: b } + Self { x: r, y: g, z: b } } pub fn nil() -> Self { Self { - r: 0., - g: 0., - b: 0., + x: 0., + y: 0., + z: 0., } } pub fn random() -> Self { let mut rng = rand::rng(); Self { - r: rng.random_range(-1.0..1.), - g: rng.random_range(-1.0..1.), - b: rng.random_range(-1.0..1.), + x: rng.random_range(-1.0..1.), + y: rng.random_range(-1.0..1.), + z: rng.random_range(-1.0..1.), } } @@ -56,15 +57,15 @@ impl Vec3 { } pub fn x(&self) -> &f32 { - &self.r + &self.x } pub fn y(&self) -> &f32 { - &self.g + &self.y } pub fn z(&self) -> &f32 { - &self.b + &self.z } pub fn length(&self) -> f32 { @@ -72,18 +73,18 @@ impl Vec3 { } pub fn length_squared(&self) -> f32 { - (self.r * self.r + self.g * self.g + self.b * self.b) as f32 + (self.x * self.x + self.y * self.y + self.z * self.z) as f32 } pub fn dot(&self, other: &Self) -> f32 { - self.r * other.r + self.g * other.g + self.b * other.b + self.x * other.x + self.y * other.y + self.z * other.z } pub fn cross(&self, other: &Self) -> Self { Self { - r: self.g * other.b - self.b * other.g, - g: self.b * other.r - self.r * other.b, - b: self.r * other.g - self.g * other.r, + 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, } } @@ -96,9 +97,9 @@ impl Vec3 { } pub fn near_zero(&self) -> bool { - default().is_close(self.r, 0.) - && default().is_close(self.g, 0.) - && default().is_close(self.b, 0.) + default().is_close(self.x, 0.) + && default().is_close(self.y, 0.) + && default().is_close(self.z, 0.) } pub fn reflect(&self, n: &Self) -> Self { @@ -117,18 +118,18 @@ impl Vec3 { pub fn output(self) -> image::Rgb { // gamma correction - let r = if self.r > 0. { - sqrt(self.r).clamp(0., 1.) + let r = if self.x > 0. { + sqrt(self.x).clamp(0., 1.) } else { 0. }; - let g = if self.g > 0. { - sqrt(self.g).clamp(0., 1.) + let g = if self.y > 0. { + sqrt(self.y).clamp(0., 1.) } else { 0. }; - let b = if self.b > 0. { - sqrt(self.b).clamp(0.1, 1.) + let b = if self.z > 0. { + sqrt(self.z).clamp(0.1, 1.) } else { 0. }; @@ -142,9 +143,19 @@ impl Vec3 { pub fn clone(&self) -> Self { Self { - r: self.r, - g: self.g, - b: self.b, + x: self.x, + y: self.y, + z: self.z, + } + } +} + +impl Default for Vec3 { + fn default() -> Self { + Self { + x: 0., + y: 0., + z: 0., } } } @@ -162,9 +173,9 @@ impl Neg for Vec3 { fn neg(self) -> Self::Output { Self { - r: -self.r, - g: -self.g, - b: -self.b, + x: -self.x, + y: -self.y, + z: -self.z, } } } @@ -174,9 +185,9 @@ impl Add for Vec3 { fn add(self, _rhs: Self) -> Self { Self { - r: self.r + _rhs.r, - g: self.g + _rhs.g, - b: self.b + _rhs.b, + x: self.x + _rhs.x, + y: self.y + _rhs.y, + z: self.z + _rhs.z, } } } @@ -186,9 +197,9 @@ impl Add for Vec3 { fn add(self, f: f32) -> Self { Self { - r: self.r + f, - g: self.g + f, - b: self.b + f, + x: self.x + f, + y: self.y + f, + z: self.z + f, } } } @@ -196,9 +207,9 @@ impl Add for Vec3 { impl AddAssign for Vec3 { fn add_assign(&mut self, other: Self) { *self = Self { - r: self.r + other.r, - g: self.g + other.g, - b: self.b + other.b, + x: self.x + other.x, + y: self.y + other.y, + z: self.z + other.z, }; } } @@ -206,9 +217,9 @@ impl AddAssign for Vec3 { impl AddAssign for Vec3 { fn add_assign(&mut self, f: f32) { *self = Self { - r: self.r + f, - g: self.g + f, - b: self.b + f, + x: self.x + f, + y: self.y + f, + z: self.z + f, }; } } @@ -217,9 +228,9 @@ impl Sub<&Vec3> for Vec3 { fn sub(self, rhs: &Self) -> Self { Self { - r: self.r - rhs.r, - g: self.g - rhs.g, - b: self.b - rhs.b, + x: self.x - rhs.x, + y: self.y - rhs.y, + z: self.z - rhs.z, } } } @@ -229,9 +240,9 @@ impl Sub for Vec3 { fn sub(self, rhs: Self) -> Self { Self { - r: self.r - rhs.r, - g: self.g - rhs.g, - b: self.b - rhs.b, + x: self.x - rhs.x, + y: self.y - rhs.y, + z: self.z - rhs.z, } } } @@ -241,9 +252,9 @@ impl Sub for Vec3 { fn sub(self, f: f32) -> Self { Self { - r: self.r - f, - g: self.g - f, - b: self.b - f, + x: self.x - f, + y: self.y - f, + z: self.z - f, } } } @@ -251,9 +262,9 @@ impl Sub for Vec3 { impl SubAssign for Vec3 { fn sub_assign(&mut self, rhs: Self) { *self = Self { - r: self.r - rhs.r, - g: self.g - rhs.g, - b: self.b - rhs.b, + x: self.x - rhs.x, + y: self.y - rhs.y, + z: self.z - rhs.z, }; } } @@ -261,9 +272,9 @@ impl SubAssign for Vec3 { impl SubAssign for Vec3 { fn sub_assign(&mut self, f: f32) { *self = Self { - r: self.r - f, - g: self.g - f, - b: self.b - f, + x: self.x - f, + y: self.y - f, + z: self.z - f, }; } } @@ -273,9 +284,9 @@ impl Mul for Vec3 { fn mul(self, rhs: Self) -> Self::Output { Self { - r: self.r * rhs.r, - g: self.g * rhs.g, - b: self.b * rhs.b, + x: self.x * rhs.x, + y: self.y * rhs.y, + z: self.z * rhs.z, } } } @@ -286,9 +297,9 @@ impl Mul for u32 { fn mul(self, rhs: Vec3) -> Self::Output { let f = self as f32; Vec3 { - r: rhs.r * f, - g: rhs.g * f, - b: rhs.b * f, + x: rhs.x * f, + y: rhs.y * f, + z: rhs.z * f, } } } @@ -298,9 +309,9 @@ impl Mul for Vec3 { fn mul(self, f: f32) -> Self::Output { Self { - r: self.r * f, - g: self.g * f, - b: self.b * f, + x: self.x * f, + y: self.y * f, + z: self.z * f, } } } @@ -310,9 +321,9 @@ impl Mul for f32 { fn mul(self, rhs: Vec3) -> Self::Output { Vec3 { - r: rhs.r * self, - g: rhs.g * self, - b: rhs.b * self, + x: rhs.x * self, + y: rhs.y * self, + z: rhs.z * self, } } } @@ -322,9 +333,9 @@ impl Mul<&Vec3> for f32 { fn mul(self, rhs: &Vec3) -> Self::Output { Vec3 { - r: rhs.r * self, - g: rhs.g * self, - b: rhs.b * self, + x: rhs.x * self, + y: rhs.y * self, + z: rhs.z * self, } } } @@ -332,9 +343,9 @@ impl Mul<&Vec3> for f32 { impl MulAssign for Vec3 { fn mul_assign(&mut self, rhs: Self) { *self = Self { - r: self.r * rhs.r, - g: self.g * rhs.g, - b: self.b * rhs.b, + x: self.x * rhs.x, + y: self.y * rhs.y, + z: self.z * rhs.z, }; } } @@ -342,9 +353,9 @@ impl MulAssign for Vec3 { impl MulAssign for Vec3 { fn mul_assign(&mut self, f: f32) { *self = Self { - r: self.r * f, - g: self.g * f, - b: self.b * f, + x: self.x * f, + y: self.y * f, + z: self.z * f, }; } } @@ -354,9 +365,9 @@ impl Div for Vec3 { fn div(self, rhs: Self) -> Self::Output { Self { - r: self.r / rhs.r, - g: self.g / rhs.g, - b: self.b / rhs.b, + x: self.x / rhs.x, + y: self.y / rhs.y, + z: self.z / rhs.z, } } } @@ -366,9 +377,9 @@ impl Div for Vec3 { fn div(self, i: i32) -> Self::Output { let f: f32 = i as f32; Self { - r: self.r / f, - g: self.g / f, - b: self.b / f, + x: self.x / f, + y: self.y / f, + z: self.z / f, } } } @@ -378,9 +389,9 @@ impl Div for Vec3 { fn div(self, f: f32) -> Self::Output { Self { - r: self.r / f, - g: self.g / f, - b: self.b / f, + x: self.x / f, + y: self.y / f, + z: self.z / f, } } } @@ -388,9 +399,9 @@ impl Div for Vec3 { impl DivAssign for Vec3 { fn div_assign(&mut self, rhs: Self) { *self = Self { - r: self.r / rhs.r, - g: self.g / rhs.g, - b: self.b / rhs.b, + x: self.x / rhs.x, + y: self.y / rhs.y, + z: self.z / rhs.z, }; } } @@ -398,21 +409,21 @@ impl DivAssign for Vec3 { impl DivAssign for Vec3 { fn div_assign(&mut self, f: f32) { *self = Self { - r: self.r / f, - g: self.g / f, - b: self.b / f, + x: self.x / f, + y: self.y / f, + z: self.z / f, }; } } impl PartialEq for Vec3 { fn eq(&self, other: &Self) -> bool { - self.r == other.r && self.g == other.g && self.b == other.b + self.x == other.x && self.y == other.y && self.z == other.z } } impl Display for Vec3 { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "({}, {}, {})", self.r, self.g, self.b) + write!(f, "({}, {}, {})", self.x, self.y, self.z) } }