From 2abf48d9ce2968f7e999a9e0faf6d0ebfa752c7c Mon Sep 17 00:00:00 2001 From: Sakarias Johansson Date: Wed, 18 Jan 2023 21:01:24 +0100 Subject: =?UTF-8?q?=F0=9F=8F=99=EF=B8=8F=20Add=20support=20for=20reading?= =?UTF-8?q?=20scene=20from=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- racer-tracer/src/scene.rs | 100 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) (limited to 'racer-tracer/src/scene.rs') diff --git a/racer-tracer/src/scene.rs b/racer-tracer/src/scene.rs index c5e76da..91fa252 100644 --- a/racer-tracer/src/scene.rs +++ b/racer-tracer/src/scene.rs @@ -1,4 +1,14 @@ -use crate::geometry::Hittable; +use std::{collections::HashMap, path::Path, sync::Arc}; + +use config::File; +use serde::Deserialize; + +use crate::{ + error::TracerError, + geometry::{sphere::Sphere, Hittable}, + material::{dialectric::Dialectric, lambertian::Lambertian, metal::Metal, SharedMaterial}, + vec3::{Color, Vec3}, +}; pub struct Scene { objects: Vec>, @@ -14,6 +24,10 @@ impl Scene { pub fn add(&mut self, hittable: Box) { self.objects.push(hittable); } + + pub fn from_file>(file: P) -> Result { + SceneData::from_file(file)?.try_into() + } } impl Hittable for Scene { @@ -36,3 +50,87 @@ impl Hittable for Scene { rec } } + +#[derive(Debug, Deserialize)] +enum MaterialData { + Lambertian { color: Color }, + Metal { color: Color, fuzz: f64 }, + Dialectric { refraction_index: f64 }, +} + +#[derive(Debug, Deserialize)] +enum GeometryData { + Sphere { + pos: Vec3, + radius: f64, + material: String, + }, +} + +#[derive(Deserialize)] +struct SceneData { + materials: HashMap, + geometry: Vec, +} + +impl SceneData { + pub fn from_file>(file: P) -> Result { + config::Config::builder() + .add_source(File::from(file.as_ref())) + .build() + .map_err(|e| { + TracerError::Configuration( + file.as_ref().to_string_lossy().into_owned(), + e.to_string(), + ) + })? + .try_deserialize() + .map_err(|e| { + TracerError::Configuration( + file.as_ref().to_string_lossy().into_owned(), + e.to_string(), + ) + }) + } +} + +impl TryInto for SceneData { + type Error = TracerError; + fn try_into(self) -> Result { + let mut materials: HashMap = HashMap::new(); + self.materials + .into_iter() + .for_each(|(id, material)| match material { + MaterialData::Lambertian { color } => { + materials.insert(id, Arc::new(Box::new(Lambertian::new(color)))); + } + MaterialData::Metal { color, fuzz } => { + materials.insert(id, Arc::new(Box::new(Metal::new(color, fuzz)))); + } + MaterialData::Dialectric { refraction_index } => { + materials.insert(id, Arc::new(Box::new(Dialectric::new(refraction_index)))); + } + }); + + let geometry: Vec> = self + .geometry + .into_iter() + .map(|geo| match geo { + GeometryData::Sphere { + pos, + radius, + material, + } => materials + .get(&material) + .ok_or(TracerError::UnknownMaterial(material)) + .map(|mat| { + let apa: Box = + Box::new(Sphere::new(pos, radius, Arc::clone(mat))); + apa + }), + }) + .collect::>, TracerError>>()?; + + Ok(Scene { objects: geometry }) + } +} -- cgit v1.2.3