Reputation: 637
I'm stuck with how I should best make a world in Rust (it's for a raytracer). I've tried to make a small example here.
See playground here. I get lots of different lifetimes errors so maybe it's easier for you to just look at the code.
trait Material {}
struct Metal {}
impl Material for Metal {}
trait Hit {
fn hit(&self) -> Option<HitRecord>;
}
struct Sphere<'a> {
material: &'a dyn Material,
}
impl<'a> Hit for Sphere<'a> {
fn hit(&self) -> Option<HitRecord> {
Some(HitRecord {
material: self.material,
})
}
}
struct HitRecord<'a> {
material: &'a dyn Material,
}
#[derive(Default)]
struct World {
materials: Vec<Box<dyn Material>>,
hitables: Vec<Box<dyn Hit>>,
}
impl World {
fn add_material(&mut self, mat: impl Material + 'static) -> &dyn Material {
self.materials.push(Box::new(mat));
self.materials.last().unwrap().as_ref()
}
fn add_hitable(&mut self, hitable: impl Hit + 'static) {
self.hitables.push(Box::new(hitable));
}
}
fn make_world() -> World {
let mut world = World::default();
let metal = Metal {};
let metal = world.add_material(metal);
let sphere = Sphere { material: metal };
world.add_hitable(sphere);
world
}
fn main() {
let world = make_world();
}
Upvotes: 0
Views: 46
Reputation: 5325
Rc
is slightly less efficient than bare references, but they are a lot easier to work with.
use std::rc::Rc;
trait Material {}
struct Metal {}
impl Material for Metal {}
trait Hit {
fn hit(&self) -> Option<HitRecord>;
}
struct Sphere {
material: Rc<dyn Material>,
}
impl Hit for Sphere {
fn hit(&self) -> Option<HitRecord> {
Some(HitRecord {
material: Rc::clone(&self.material),
})
}
}
struct HitRecord {
material: Rc<dyn Material>,
}
#[derive(Default)]
struct World {
materials: Vec<Rc<dyn Material>>,
hitables: Vec<Rc<dyn Hit>>,
}
impl World {
fn add_material(&mut self, mat: impl Material + 'static) -> Rc<dyn Material> {
let rc: Rc<dyn Material> = Rc::new(mat);
self.materials.push(Rc::clone(&rc));
rc
}
fn add_hitable(&mut self, hitable: impl Hit + 'static) {
self.hitables.push(Rc::new(hitable));
}
}
fn make_world() -> World {
let mut world = World::default();
let metal = Metal {};
let metal = world.add_material(metal);
let sphere = Sphere { material: metal };
world.add_hitable(sphere);
world
}
fn main() {
let world = make_world();
}
Upvotes: 1