rtiow: add basic Metal material support to parser.

This commit is contained in:
Bill Thiede 2023-02-15 21:32:08 -08:00
parent 35071b06ac
commit d3153032b1
5 changed files with 87 additions and 17 deletions

View File

@ -4,13 +4,13 @@ use crate::{
cuboid::Cuboid, cuboid::Cuboid,
hitable::Hit, hitable::Hit,
hitable_list::HitableList, hitable_list::HitableList,
material::Lambertian, material::{Lambertian, Material, Metal},
renderer::Scene, renderer::Scene,
sphere::Sphere, sphere::Sphere,
texture::{EnvMap, Texture}, texture::{EnvMap, Texture},
}; };
use serde::Deserialize; use serde::Deserialize;
use std::{fs::File, io::BufReader, path::PathBuf, sync::Arc}; use std::{collections::HashMap, fs::File, io::BufReader, path::PathBuf, sync::Arc};
use stl::STL; use stl::STL;
use thiserror::Error; use thiserror::Error;
use vec3::Vec3; use vec3::Vec3;
@ -19,6 +19,7 @@ use vec3::Vec3;
pub struct Config { pub struct Config {
scene: SceneConfig, scene: SceneConfig,
camera: CameraConfig, camera: CameraConfig,
materials: Vec<MaterialConfig>,
hitables: Vec<HitableConfig>, hitables: Vec<HitableConfig>,
envmap: Option<EnvMapConfig>, envmap: Option<EnvMapConfig>,
} }
@ -31,35 +32,59 @@ pub enum ConfigError {
STLError(#[from] stl::ParseError), STLError(#[from] stl::ParseError),
#[error("I/O error")] #[error("I/O error")]
IOError(#[from] std::io::Error), IOError(#[from] std::io::Error),
#[error("duplication material named '{0}'")]
DuplicateMaterial(String),
#[error("unkown material named '{0}'")]
UnknownMaterial(String),
} }
impl TryFrom<Config> for Scene { impl TryFrom<Config> for Scene {
type Error = ConfigError; type Error = ConfigError;
fn try_from(c: Config) -> Result<Scene, Self::Error> { fn try_from(c: Config) -> Result<Scene, Self::Error> {
// TODO(wathiede): make this something that is loaded from the config and referenced by let mut materials = HashMap::new();
// name in the object's config. for mc in c.materials {
let material = Lambertian::new([1., 0., 0.]); let v: Arc<dyn Material> = match mc.material {
Materials::Metal { albedo, fuzzy } => Arc::new(Metal::new(albedo, fuzzy)),
};
if materials.insert(mc.name.clone(), v).is_some() {
return Err(ConfigError::DuplicateMaterial(mc.name));
}
}
let hitables: Result<Vec<Box<dyn Hit>>, Self::Error> = c let hitables: Result<Vec<Box<dyn Hit>>, Self::Error> = c
.hitables .hitables
.into_iter() .into_iter()
.map(|hc| -> Result<Box<dyn Hit>, Self::Error> { .map(|hc| -> Result<Box<dyn Hit>, Self::Error> {
match hc { match hc.hitable {
HitableConfig::Sphere { center, radius } => { Hitables::Sphere { center, radius } => Ok(Box::new(Sphere::new(
Ok(Box::new(Sphere::new(center, radius, material.clone()))) center,
} radius,
HitableConfig::Cuboid { min, max } => Ok(Box::new(Cuboid::new( Arc::clone(
materials
.get(&hc.material_name)
.ok_or(ConfigError::UnknownMaterial(hc.material_name))?,
),
))),
Hitables::Cuboid { min, max } => Ok(Box::new(Cuboid::new(
min.into(), min.into(),
max.into(), max.into(),
Arc::new(material.clone()), Arc::clone(
materials
.get(&hc.material_name)
.ok_or(ConfigError::UnknownMaterial(hc.material_name))?,
),
))), ))),
HitableConfig::STL { path, scale } => { Hitables::STL { path, scale } => {
let r = BufReader::new(File::open(path)?); let r = BufReader::new(File::open(path)?);
let stl = STL::parse(r, false)?; let stl = STL::parse(r, false)?;
Ok(Box::new(BVHTriangles::new( Ok(Box::new(BVHTriangles::new(
&stl, &stl,
material.clone(), Arc::clone(
materials
.get(&hc.material_name)
.ok_or(ConfigError::UnknownMaterial(hc.material_name))?,
),
scale.unwrap_or(1.), scale.unwrap_or(1.),
))) )))
} }
@ -119,7 +144,15 @@ struct SceneConfig {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
#[serde(tag = "type")] #[serde(tag = "type")]
enum HitableConfig { struct HitableConfig {
material_name: String,
#[serde(flatten)]
hitable: Hitables,
}
#[derive(Debug, Deserialize)]
#[serde(tag = "type")]
enum Hitables {
#[serde(rename = "sphere")] #[serde(rename = "sphere")]
Sphere { center: [f32; 3], radius: f32 }, Sphere { center: [f32; 3], radius: f32 },
#[serde(rename = "cuboid")] #[serde(rename = "cuboid")]
@ -128,12 +161,25 @@ enum HitableConfig {
STL { path: PathBuf, scale: Option<f32> }, STL { path: PathBuf, scale: Option<f32> },
} }
#[derive(Debug, Deserialize)]
struct MaterialConfig {
name: String,
#[serde(flatten)]
material: Materials,
}
#[derive(Debug, Deserialize)]
#[serde(tag = "type")]
enum Materials {
#[serde(rename = "metal")]
Metal { albedo: [f32; 3], fuzzy: f32 },
}
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct CameraConfig { pub struct CameraConfig {
lookfrom: [f32; 3], lookfrom: [f32; 3],
lookat: [f32; 3], lookat: [f32; 3],
fov: f32, fov: f32,
aspect: f32,
aperture: f32, aperture: f32,
focus_dist: f32, focus_dist: f32,
time_min: f32, time_min: f32,

View File

@ -1,4 +1,5 @@
use std::{ use std::{
collections::HashMap,
fmt, fmt,
ops::{AddAssign, Range}, ops::{AddAssign, Range},
path::{Path, PathBuf}, path::{Path, PathBuf},
@ -22,7 +23,7 @@ use crate::{
camera::Camera, camera::Camera,
hitable::Hit, hitable::Hit,
human, human,
material::Lambertian, material::{Lambertian, Material},
output, output,
ray::Ray, ray::Ray,
scenes, scenes,
@ -134,6 +135,8 @@ pub fn opt_hash(opt: &Opt) -> String {
pub struct Scene { pub struct Scene {
#[serde(skip)] #[serde(skip)]
pub world: Box<dyn Hit>, pub world: Box<dyn Hit>,
//#[serde(skip)]
//pub materials: HashMap<String, Box<dyn Material>>,
#[serde(skip)] #[serde(skip)]
pub camera: Camera, pub camera: Camera,
pub subsamples: usize, pub subsamples: usize,

View File

@ -52,6 +52,7 @@ pub fn new(opt: &Opt) -> Scene {
height: opt.height, height: opt.height,
global_illumination: true, global_illumination: true,
env_map: Some(EnvMap::new(skybox)), env_map: Some(EnvMap::new(skybox)),
..Default::default()
} }
} }

View File

@ -112,5 +112,6 @@ pub fn new(opt: &Opt) -> Scene {
height: opt.height, height: opt.height,
global_illumination: true, global_illumination: true,
env_map: Some(EnvMap::new(skybox)), env_map: Some(EnvMap::new(skybox)),
..Default::default()
} }
} }

View File

@ -7,24 +7,43 @@ height = 768
lookfrom = [0.0, 30.0, -100.0] lookfrom = [0.0, 30.0, -100.0]
lookat = [0.0, 0.0, 0.0] lookat = [0.0, 0.0, 0.0]
fov = 45 fov = 45
aspect = 1
aperture = 0.0 aperture = 0.0
focus_dist = 10.0 focus_dist = 10.0
time_min = 0.0 time_min = 0.0
time_max = 1.0 time_max = 1.0
[[materials]]
name = "green"
type = "metal"
albedo = [0, 1, 0]
fuzzy = 1.5
[[materials]]
name = "blue"
type = "metal"
albedo = [0, 0, 1]
fuzzy = 1.5
[[materials]]
name = "red"
type = "metal"
albedo = [1, 0, 0]
fuzzy = 1.5
[[hitables]] [[hitables]]
type = "cuboid" type = "cuboid"
min = [-10.0, -10.0, -10.0] min = [-10.0, -10.0, -10.0]
max = [10.0, 10.0, 10.0] max = [10.0, 10.0, 10.0]
material_name = "green"
[[hitables]] [[hitables]]
type = "sphere" type = "sphere"
center = [30.0, 0.0, 0.0] center = [30.0, 0.0, 0.0]
radius = 10 radius = 10
material_name = "blue"
[[hitables]] [[hitables]]
type = "stl" type = "stl"
path = "/net/nasx.h.xinu.tv/x/3dprint/stl/stanford_dragon.stl" path = "/net/nasx.h.xinu.tv/x/3dprint/stl/stanford_dragon.stl"
scale = 200 scale = 200
material_name = "red"
[envmap] [envmap]
path = "/home/wathiede/src/xinu.tv/raytracers/rtiow/renderer/images/52681723945_e1d94d3df9_6k.jpg" path = "/home/wathiede/src/xinu.tv/raytracers/rtiow/renderer/images/52681723945_e1d94d3df9_6k.jpg"