ft: moved random scene code to function; cleaned up tri/quad/cube hit logic; made camera attributes private

This commit is contained in:
2026-05-31 13:51:34 +02:00
parent 71985a6c34
commit 64cad7eda6
11 changed files with 259 additions and 221 deletions

View File

@@ -1,23 +1,35 @@
use std::sync::Arc;
use rand::RngExt;
use serde::Deserialize;
use crate::{
camera::Camera,
objects::{materials::traits::Material, traits::Hittable},
objects::{
materials::{
dielectric::Dielectric,
lambertian::{Lambertian, Metal},
traits::Material,
},
sphere::Sphere,
traits::Hittable,
},
scenes::{hittable_def::HittableDef, material_def::MaterialDef, raw_camera::RawCamera},
vec3::Vec3,
};
#[derive(Debug)]
pub struct Scene {
pub camera: Camera, // FIXME: should not be public
pub objects: Vec<Arc<dyn Hittable>>,
camera: Camera,
objects: Vec<Arc<dyn Hittable>>,
// image
pub filename: String,
pub image_width: u32,
pub image_height: u32,
filename: String,
image_width: u32,
image_height: u32,
// raytracing // TODO: think about organisation of these vars, also in Camera
pub max_depth: u32,
max_depth: u32,
}
impl Scene {
@@ -39,20 +51,127 @@ impl Scene {
}
}
pub fn random() -> Self {
let ground = Lambertian::rgb(-2.5, 0.5, 0.5, 1.);
let mut world: Vec<Arc<dyn Hittable>> = vec![Arc::new(Sphere::xyz(
0.,
-1000.,
0.,
1000.,
Arc::new(ground),
))];
let mut rng = rand::rng();
let point = Vec3::new(4., 0.2, 0.);
for a in -11..11 {
for b in -11..11 {
let mat = rng.random_range((0.)..1.);
let center = Vec3::new(
a as f32 + 0.9 * rng.random_range((0.)..1.),
0.2,
b as f32 + 0.9 * rng.random_range((0.)..1.),
);
if (center - point).length() > 0.9 {
if mat < 0.8 {
// diffuse
world.push(Arc::new(Sphere::new(
center,
0.2,
Arc::new(Lambertian::new(Vec3::random() * Vec3::random(), 1.)),
)));
} else if mat < 0.95 {
// metal
world.push(Arc::new(Sphere::new(
center,
0.2,
Arc::new(Metal::rgb(
rng.random_range(0.5..1.),
rng.random_range(0.5..1.),
rng.random_range(0.5..1.),
1.,
rng.random_range((0.)..0.5),
)),
)));
} else {
// glass
world.push(Arc::new(Sphere::new(
center,
0.2,
Arc::new(Dielectric::new(1.5)),
)));
}
}
}
}
world.push(Arc::new(Sphere::xyz(
0.,
1.,
0.,
1.,
Arc::new(Dielectric::new(1.5)),
)));
world.push(Arc::new(Sphere::xyz(
-4.,
1.,
0.,
1.,
Arc::new(Lambertian::rgb(0.4, 0.2, 0.1, 1.)),
)));
world.push(Arc::new(Sphere::xyz(
4.,
1.,
0.,
1.,
Arc::new(Metal::rgb(0.7, 0.6, 0.5, 1., 0.)),
)));
let mut c = Camera::new();
c.set_fov(20.);
c.set_anti_alias_rate(2);
c.set_vup(Vec3::new(0., 1., 0.));
c.set_look_from(Vec3::new(13., 2., 3.));
c.set_look_at(Vec3::new(0., 0., 0.));
c.add_defocus_blur(0.6, 10.);
Self {
camera: c,
objects: world,
filename: "random.png".to_string(),
image_width: 1920,
image_height: 1080,
max_depth: 50,
}
}
pub fn get_camera(&self) -> &Camera {
&self.camera
}
pub fn get_image_width(&self) -> f32 {
self.image_width as f32
pub fn get_image_width(&self) -> u32 {
self.image_width
}
pub fn get_image_height(&self) -> f32 {
self.image_height as f32
pub fn get_image_height(&self) -> u32 {
self.image_height
}
pub fn get_objects(&self) -> &Vec<Arc<dyn Hittable>> {
&self.objects
}
pub fn get_max_depth(&self) -> u32 {
self.max_depth
}
pub fn get_filename(&self) -> &String {
&self.filename
}
pub fn init(&mut self) {
self.camera.init(self.get_image_width(), self.get_image_height());
self.camera
.init(self.get_image_width(), self.get_image_height());
}
}