1use crate::{
2 Arena, DirectionalLight, Material, Mesh, MeshId, ObjectId, Texture, TextureId, Transform,
3};
4
5#[derive(Clone, Debug)]
8pub struct RenderObject {
9 pub mesh: MeshId,
10 pub texture: Option<TextureId>,
11 pub transform: Transform,
12 pub material: Material,
13 pub visible: bool,
14}
15
16pub struct Scene {
22 pub meshes: Arena<Mesh>,
23 pub textures: Arena<Texture>,
24 pub objects: Arena<RenderObject>,
25 pub light: DirectionalLight,
26}
27
28impl Scene {
29 pub fn new() -> Self {
30 Self {
31 meshes: Arena::new(),
32 textures: Arena::new(),
33 objects: Arena::new(),
34 light: DirectionalLight::default(),
35 }
36 }
37
38 pub fn spawn(&mut self, object: RenderObject) -> ObjectId {
41 self.objects.insert(object)
42 }
43}
44
45impl Default for Scene {
46 fn default() -> Self {
47 Self::new()
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54 use crate::{Material, Rgb, Transform};
55
56 #[test]
57 fn spawn_returns_reachable_object() {
58 let mut scene = Scene::new();
59 let mesh = scene.meshes.insert(Mesh::triangle(1.0, 1.0).unwrap());
60 let object = scene.spawn(RenderObject {
61 mesh,
62 texture: None,
63 transform: Transform::default(),
64 material: Material::new(Rgb::new(1.0, 0.5, 0.25)),
65 visible: true,
66 });
67 let fetched = scene.objects.get(object).unwrap();
68 assert_eq!(fetched.mesh, mesh);
69 assert!(fetched.visible);
70 assert_eq!(fetched.material.tint, Rgb::new(1.0, 0.5, 0.25));
71 }
72
73 #[test]
74 fn removed_object_does_not_leak_into_scene() {
75 let mut scene = Scene::new();
76 let mesh = scene.meshes.insert(Mesh::plane(1.0, 1.0).unwrap());
77 let object = scene.spawn(RenderObject {
78 mesh,
79 texture: None,
80 transform: Transform::default(),
81 material: Material::default(),
82 visible: true,
83 });
84 assert_eq!(scene.objects.len(), 1);
85 scene.objects.remove(object);
86 assert!(scene.objects.is_empty());
87 }
88}