From e7018a84eda65deb5a03505937715b0c08153964 Mon Sep 17 00:00:00 2001 From: djairoh Date: Sat, 2 May 2026 11:59:23 +0200 Subject: [PATCH] ft: made materials referenceable or by ref --- scenes/scene.json | 46 +++++++++++----------- scenes/withTriangle.json | 38 ------------------- src/scenes/scene.rs | 82 +++++++++++++++++++++------------------- 3 files changed, 65 insertions(+), 101 deletions(-) delete mode 100644 scenes/withTriangle.json diff --git a/scenes/scene.json b/scenes/scene.json index e0fe06a..0dc79ed 100644 --- a/scenes/scene.json +++ b/scenes/scene.json @@ -2,35 +2,33 @@ "camera": { "image_width": 1920, "image_height": 1080, - "anti_alias_rate": 2, - "max_depth": 10, - "fov": 20.0, - "look_from": { "x": -10, "y": 5, "z": 10 }, - "look_at": { "x": 0.0, "y": 0.0, "z": -1.0 }, - "vup": { "x": 0.0, "y": 1.0, "z": 0.0 }, - "defocus_blur": false, - "defocus_angle": 2, + "anti_alias_rate": 1, + "max_depth": 50, + "fov": 50.0, + "look_from": [0, 2, 10], + "look_at": [0.0, 0.0, -1.0 ], + "vup": [0.0, 1.0, 0.0], + "defocus_angle": 0, "focus_dist": 15.68 }, "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": "lambertian", "albedo": [0.2, 0.2, 0.2], "prob": 0.8 }, + { "type": "lambertian", "albedo": [0.9, 0.9, 0.0], "prob": 1.0, "fuzz": 0.1 }, { "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 } - - ], + { "type": "metal", "albedo": [0.8, 0.6, 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}, - { "type": "sphere", "center": { "x": 20, "y": 7, "z": -15 }, "radius": 10.5, "material": 0} - ] + { "type": "sphere", "center": [0.0, 0.0, -1.2], "radius": 0.5, "material": { "type": "metal", "albedo": [0.7, 0.4, 0.2], "prob": 1.0, "fuzz": 0.1 }}, + { "type": "sphere", "center": [-1, 0, -1], "radius": 0.4, "material": 2}, + { "type": "sphere", "center": [1, 0, -1], "radius": 0.5, "material": 3}, + { "type": "triangle", "p1": [-4, 0, -4], "p2": [0, 0, -4], "p3": [-2, 2, -4], "material": 1}, + { "type": "triangle", "p1": [0, 0, -4], "p2": [4, 0, -4], "p3": [2, 2, -4], "material": 1}, + { "type": "triangle", "p1": [-2, 2, -4], "p2": [2, 2, -4], "p3": [0, 4, -4], "material": 1}, + { "type": "quad", "p1": [-20, -1, -20], "p2": [20, -1, -20], "p3": [20, 20, -20], "p4": [-20, 20, -20], "material": 0}, + { "type": "quad", "p1": [-20, -1, 20], "p2": [-20, -1, -20], "p3": [-20, 20, -20], "p4": [-20, 20, 20], "material": 0}, + { "type": "quad", "p1": [20, -1, 20], "p2": [20, -1, -20], "p3": [20, 20, -20], "p4": [20, 20, 20], "material": 0}, + { "type": "quad", "p1": [-20, -1, 20], "p2": [20, -1, 20], "p3": [20, -1, -20], "p4": [-20, -1, -20], "material": 0} + ] } diff --git a/scenes/withTriangle.json b/scenes/withTriangle.json deleted file mode 100644 index 07b7f1c..0000000 --- a/scenes/withTriangle.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "camera": { - "image_width": 400, - "image_height": 300, - "anti_alias_rate": 23, - "max_depth": 10, - "fov": 20.0, - "look_from": { "x": 20, "y": 25, "z": 40 }, - "look_at": { "x": 0.0, "y": 0.0, "z": -1.0 }, - "vup": { "x": 0.0, "y": 1.0, "z": 0.0 }, - "defocus_blur": false, - "defocus_angle": 0, - "focus_dist": 15.68 - }, - "materials": [ - { "type": "metal", "albedo": { "x": 0.9, "y": 0.4, "z": 0.2 }, "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}, - { "type": "sphere", "center": { "x": 20, "y": 7, "z": -15 }, "radius": 10.5, "material": 0}, - { "type": "triangle", "p1": { "x": 0, "y": 0, "z": -4}, "p2": { "x": 0, "y": 0, "z": 4 }, "p3": { "x": 0, "y": 7, "z": 0 }, "material": 0} - ] -} - - - diff --git a/src/scenes/scene.rs b/src/scenes/scene.rs index 5321243..d310ad1 100644 --- a/src/scenes/scene.rs +++ b/src/scenes/scene.rs @@ -1,6 +1,7 @@ use std::fmt::Debug; use std::sync::Arc; +use serde_json::error::Error; use log::warn; use serde::Deserialize; @@ -90,11 +91,35 @@ impl<'de> Deserialize<'de> for Scene { } } +#[derive(Deserialize)] +#[serde(untagged)] +enum RawMaterial { + Ref(u32), + Direct(MaterialDef), +} + +impl RawMaterial { + pub fn into_arc(self, materials: &Vec>) -> Option> { + match self { + RawMaterial::Ref(r) => { + if r as usize >= materials.len() { + warn!("Sphere specified nonexistent material {}; skipping...", r); + return None; + } + Some(materials.get(r as usize).unwrap().clone()) + } + RawMaterial::Direct(m) => Some(m.into_arc()), + } + } +} + + + #[derive(Deserialize)] struct RawSphere { pub center: Vec3, pub radius: f32, - pub material: u32, + pub material: RawMaterial, } #[derive(Deserialize)] @@ -102,7 +127,7 @@ struct RawTriangle { pub p1: Vec3, pub p2: Vec3, pub p3: Vec3, - pub material: u32, + pub material: RawMaterial, } #[derive(Deserialize)] @@ -111,7 +136,7 @@ struct RawQuad { pub p2: Vec3, pub p3: Vec3, pub p4: Vec3, - pub material: u32, + pub material: RawMaterial, } #[derive(Deserialize)] @@ -127,49 +152,28 @@ impl HittableDef { // THOUGHT: i think this can be done better; in the map/filter call up there? match self { HittableDef::Sphere(s) => { - if s.material as usize >= materials.len() { - warn!( - "Sphere specified nonexistent material {}; skipping...", - s.material - ); - return None; + let material = s.material.into_arc(materials); + if let Some(m) = material { + Some(Arc::new(Sphere::new(s.center, s.radius, m))) + } else { + None } - Some(Arc::new(Sphere::new( - s.center, - s.radius, - materials.get(s.material as usize).unwrap().clone(), - ))) } HittableDef::Triangle(t) => { - if t.material as usize >= materials.len() { - warn!( - "Triangle specified nonexistent material {}; skipping...", - t.material - ); - return None; + let material = t.material.into_arc(materials); + if let Some(m) = material { + Some(Arc::new(Triangle::new(t.p1, t.p2, t.p3, m))) + } else { + None } - Some(Arc::new(Triangle::new( - t.p1, - t.p2, - t.p3, - materials.get(t.material as usize).unwrap().clone(), - ))) } HittableDef::Quad(q) => { - if q.material as usize >= materials.len() { - warn!( - "Quad specified nonexistent material {}; skipping...", - q.material - ); - return None; + let material = q.material.into_arc(materials); + if let Some(m) = material { + Some(Arc::new(Quad::new(q.p1, q.p2, q.p3, q.p4, m))) + } else { + None } - Some(Arc::new(Quad::new( - q.p1, - q.p2, - q.p3, - q.p4, - materials.get(q.material as usize).unwrap().clone(), - ))) } } }