summaryrefslogtreecommitdiff
path: root/racer-tracer/src/scene
diff options
context:
space:
mode:
Diffstat (limited to 'racer-tracer/src/scene')
-rw-r--r--racer-tracer/src/scene/none.rs15
-rw-r--r--racer-tracer/src/scene/random.rs87
-rw-r--r--racer-tracer/src/scene/yml.rs116
3 files changed, 218 insertions, 0 deletions
diff --git a/racer-tracer/src/scene/none.rs b/racer-tracer/src/scene/none.rs
new file mode 100644
index 0000000..2aed105
--- /dev/null
+++ b/racer-tracer/src/scene/none.rs
@@ -0,0 +1,15 @@
+use crate::{error::TracerError, scene::SceneLoader};
+
+pub struct NoneLoader {}
+
+impl NoneLoader {
+ pub fn new() -> Self {
+ Self {}
+ }
+}
+
+impl SceneLoader for NoneLoader {
+ fn load(&self) -> Result<Vec<Box<dyn crate::geometry::Hittable>>, TracerError> {
+ Ok(Vec::new())
+ }
+}
diff --git a/racer-tracer/src/scene/random.rs b/racer-tracer/src/scene/random.rs
new file mode 100644
index 0000000..ddbcfc1
--- /dev/null
+++ b/racer-tracer/src/scene/random.rs
@@ -0,0 +1,87 @@
+use std::sync::Arc;
+
+use crate::{
+ error::TracerError,
+ geometry::{sphere::Sphere, Hittable},
+ material::{dialectric::Dialectric, lambertian::Lambertian, metal::Metal, SharedMaterial},
+ scene::SceneLoader,
+ util::{random_double, random_double_range},
+ vec3::{Color, Vec3},
+};
+
+pub struct Random {}
+
+impl Random {
+ pub fn new() -> Self {
+ Self {}
+ }
+}
+
+impl SceneLoader for Random {
+ fn load(&self) -> Result<Vec<Box<dyn crate::geometry::Hittable>>, TracerError> {
+ let mut geometry: Vec<Box<dyn Hittable>> = Vec::new();
+ let ground_material: SharedMaterial =
+ Arc::new(Box::new(Lambertian::new(Color::new(0.5, 0.5, 0.5))));
+ geometry.push(Box::new(Sphere::new(
+ Vec3::new(0.0, -1000.0, 0.0),
+ 1000.0,
+ ground_material,
+ )));
+
+ for a in -11..11 {
+ for b in -11..11 {
+ let choose_mat = random_double();
+ let center = Vec3::new(
+ a as f64 + 0.9 * random_double(),
+ 0.2,
+ b as f64 + 0.9 * random_double(),
+ );
+
+ if (center - Vec3::new(4.0, 0.2, 0.0)).length() > 0.9 {
+ if choose_mat < 0.8 {
+ // diffuse
+ let albedo = Color::random() * Color::random();
+ let mat: SharedMaterial = Arc::new(Box::new(Lambertian::new(albedo)));
+ geometry.push(Box::new(Sphere::new(center, 0.2, mat)));
+ } else if choose_mat > 0.95 {
+ // metal
+ let albedo = Color::random_range(0.5, 1.0);
+ let fuzz = random_double_range(0.0, 0.5);
+ let mat: SharedMaterial = Arc::new(Box::new(Metal::new(albedo, fuzz)));
+ geometry.push(Box::new(Sphere::new(center, 0.2, mat)));
+ } else {
+ // glass
+ let mat: SharedMaterial = Arc::new(Box::new(Dialectric::new(1.5)));
+ geometry.push(Box::new(Sphere::new(center, 0.2, mat)));
+ }
+ }
+ }
+ }
+
+ let dial_mat: SharedMaterial = Arc::new(Box::new(Dialectric::new(1.5)));
+ geometry.push(Box::new(Sphere::new(
+ Vec3::new(0.0, 1.0, 0.0),
+ 1.0,
+ dial_mat,
+ )));
+
+ let lamb_mat: SharedMaterial =
+ Arc::new(Box::new(Lambertian::new(Color::new(0.4, 0.2, 0.1))));
+ geometry.push(Box::new(Sphere::new(
+ Vec3::new(-4.0, 1.0, 0.0),
+ 1.0,
+ lamb_mat,
+ )));
+
+ let metal_mat: SharedMaterial =
+ Arc::new(Box::new(Metal::new(Color::new(0.7, 0.6, 0.5), 0.0)));
+
+ geometry.push(Box::new(Sphere::new(
+ Vec3::new(4.0, 1.0, 0.0),
+ 1.0,
+ metal_mat,
+ )));
+
+ Ok(geometry)
+ }
+}
diff --git a/racer-tracer/src/scene/yml.rs b/racer-tracer/src/scene/yml.rs
new file mode 100644
index 0000000..3e69786
--- /dev/null
+++ b/racer-tracer/src/scene/yml.rs
@@ -0,0 +1,116 @@
+use std::{
+ collections::HashMap,
+ path::{Path, PathBuf},
+ sync::Arc,
+};
+
+use serde::Deserialize;
+
+use crate::{
+ error::TracerError,
+ geometry::{sphere::Sphere, Hittable},
+ material::{dialectric::Dialectric, lambertian::Lambertian, metal::Metal, SharedMaterial},
+ scene::SceneLoader,
+ vec3::{Color, Vec3},
+};
+
+use config::File;
+
+pub struct YmlLoader {
+ path: PathBuf,
+}
+
+impl YmlLoader {
+ pub fn new(path: PathBuf) -> Self {
+ Self { path }
+ }
+}
+
+impl SceneLoader for YmlLoader {
+ fn load(&self) -> Result<Vec<Box<dyn crate::geometry::Hittable>>, TracerError> {
+ let datta = SceneData::from_file(PathBuf::from(&self.path))?;
+ datta.try_into()
+ }
+}
+
+#[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<String, MaterialData>,
+ geometry: Vec<GeometryData>,
+}
+
+impl SceneData {
+ pub fn from_file<P: AsRef<Path>>(file: P) -> Result<Self, TracerError> {
+ config::Config::builder()
+ .add_source(File::from(file.as_ref()))
+ .build()
+ .map_err(|e| {
+ TracerError::Configuration(
+ file.as_ref().to_string_lossy().into_owned(),
+ dbg!(e).to_string(),
+ )
+ })?
+ .try_deserialize()
+ .map_err(|e| {
+ TracerError::Configuration(
+ file.as_ref().to_string_lossy().into_owned(),
+ dbg!(e).to_string(),
+ )
+ })
+ }
+}
+
+impl TryInto<Vec<Box<dyn Hittable>>> for SceneData {
+ type Error = TracerError;
+ fn try_into(self) -> Result<Vec<Box<dyn Hittable>>, TracerError> {
+ let mut materials: HashMap<String, SharedMaterial> = 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<Box<dyn Hittable>> = self
+ .geometry
+ .into_iter()
+ .map(|geo| match geo {
+ GeometryData::Sphere {
+ pos,
+ radius,
+ material,
+ } => materials
+ .get(&material)
+ .ok_or(TracerError::UnknownMaterial(material))
+ .map(|mat| {
+ Box::new(Sphere::new(pos, radius, Arc::clone(mat))) as Box<dyn Hittable>
+ }),
+ })
+ .collect::<Result<Vec<Box<dyn Hittable>>, TracerError>>()?;
+
+ Ok(geometry)
+ }
+}