ft: made materials referenceable or by ref

This commit is contained in:
2026-05-02 11:59:23 +02:00
parent f1ac226dbb
commit e7018a84ed
3 changed files with 65 additions and 101 deletions

View File

@@ -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<Arc<dyn Material>>) -> Option<Arc<dyn Material>> {
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(),
)))
}
}
}