ft (wip): deserialization

This commit is contained in:
2026-04-25 14:46:03 +02:00
parent ef8da70436
commit 430bdf63bc
15 changed files with 421 additions and 158 deletions

61
src/scenes/raw_camera.rs Normal file
View File

@@ -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<RawCamera> for Camera {
type Error = String;
fn try_from(raw: RawCamera) -> Result<Self, Self::Error> {
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)
}
}

107
src/scenes/scene.rs Normal file
View File

@@ -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<Arc<dyn Material>>,
pub objects: Vec<Arc<dyn Hittable>>,
}
impl Scene {
pub fn render(&mut self) {
self.camera.render(&self.objects);
}
}
#[derive(Deserialize)]
struct SceneDef {
pub camera: RawCamera,
pub materials: Vec<MaterialDef>,
pub objects: Vec<HittableDef>,
}
impl<'de> Deserialize<'de> for Scene {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let conc = SceneDef::deserialize(deserializer)?;
let mats: Vec<Arc<dyn Material>> = conc
.materials
.into_iter()
.map(MaterialDef::into_arc)
.collect();
let objs: Vec<Arc<dyn Hittable>> = 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<dyn Material>>) -> Arc<dyn Hittable> {
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<dyn Material> {
match self {
MaterialDef::Lambertian(l) => Arc::new(l),
MaterialDef::Metal(m) => Arc::new(m),
MaterialDef::Dielectric(d) => Arc::new(d),
}
}
}