///|
/// Scene description system for loading scenes from structured data.
/// Includes a simple scene builder and JSON-like scene representation.
pub(all) struct SceneObject {
shape : String
center : Vec3
params : (Double, Double, Double)
material_name : String
material_params : (Double, Double, Double)
} derive(Debug)
pub fn make_scene_from_objects(
objects~ : Array[SceneObject],
cam_origin~ : Vec3,
cam_lookat~ : Vec3,
cam_fov~ : Double,
cam_aspect~ : Double
) -> (HitableList, Camera) {
let mut world = HitableList::new()
for i in 0.. {
let mp = obj.material_params
Material::Lambertian({ x: mp.0, y: mp.1, z: mp.2 })
}
"metal" => {
let mp = obj.material_params
Material::Metal({ x: mp.0, y: mp.1, z: mp.2 }, p.0)
}
"dielectric" | "glass" => {
Material::Dielectric(p.0)
}
"emissive" | "light" => {
let mp = obj.material_params
Material::Emissive({ x: mp.0, y: mp.1, z: mp.2 })
}
"diffuselight" => {
let mp = obj.material_params
Material::DiffuseLight(Texture::Solid({ x: mp.0, y: mp.1, z: mp.2 }))
}
_ => Material::Lambertian({ x: 0.5, y: 0.5, z: 0.5 })
}
match obj.shape {
"sphere" => {
world = world.add(Hitable::Sphere(Sphere::new(
center=c, radius=p.1, material=mat,
)))
}
"box" => {
let size = { x: p.0, y: p.1, z: p.2 }
world = world.add(Hitable::BoxShape(BoxShape::new(
center=c, size=size, material=mat,
)))
}
"plane" => {
let normal = { x: p.0, y: p.1, z: p.2 }
world = world.add(Hitable::Plane(Plane::new(
center=c, normal=normal, material=mat,
)))
}
"cylinder" => {
world = world.add(Hitable::Cylinder(Cylinder::new(
center=c, radius=p.0, height=p.1, material=mat,
)))
}
"disk" => {
let normal = { x: p.0, y: p.1, z: p.2 }
world = world.add(Hitable::Disk(Disk::new(
center=c, normal=normal, radius=p.1, material=mat,
)))
}
_ => ()
}
}
let cam = Camera::new(
lookfrom=cam_origin,
lookat=cam_lookat,
vup={ x: 0.0, y: 1.0, z: 0.0 },
vfov=cam_fov,
aspect_ratio=cam_aspect,
aperture=0.0,
focus_dist=1.0,
time0=0.0,
time1=0.0,
)
(world, cam)
}
pub fn scene_empty() -> Array[SceneObject] {
Array::new(capacity=32)
}
pub fn scene_add_sphere(
objects : Array[SceneObject],
center~ : Vec3,
radius~ : Double,
material~ : String,
param1~ : Double,
param2~ : Double,
param3~ : Double
) -> Array[SceneObject] {
let obj = {
shape: "sphere",
center,
params: (0.0, radius, 0.0),
material_name: material,
material_params: (param1, param2, param3),
}
let result = objects
result.push(obj)
result
}
pub fn scene_add_box(
objects : Array[SceneObject],
center~ : Vec3,
size~ : Vec3,
material~ : String,
r~ : Double,
g~ : Double,
b~ : Double
) -> Array[SceneObject] {
let obj = {
shape: "box",
center,
params: (size.x, size.y, size.z),
material_name: material,
material_params: (r, g, b),
}
let result = objects
result.push(obj)
result
}
pub fn scene_add_cylinder(
objects : Array[SceneObject],
center~ : Vec3,
radius~ : Double,
height~ : Double,
material~ : String,
r~ : Double,
g~ : Double,
b~ : Double
) -> Array[SceneObject] {
let obj = {
shape: "cylinder",
center,
params: (radius, height, 0.0),
material_name: material,
material_params: (r, g, b),
}
let result = objects
result.push(obj)
result
}
pub fn scene_add_plane(
objects : Array[SceneObject],
center~ : Vec3,
normal~ : Vec3,
material~ : String,
r~ : Double,
g~ : Double,
b~ : Double
) -> Array[SceneObject] {
let obj = {
shape: "plane",
center,
params: (normal.x, normal.y, normal.z),
material_name: material,
material_params: (r, g, b),
}
let result = objects
result.push(obj)
result
}