Skip to main content

he3d_core/
scene.rs

1use crate::{
2   Arena, DirectionalLight, Material, Mesh, MeshId, ObjectId, Texture, TextureId, Transform,
3};
4
5/// A renderable instance: a mesh, optional texture, transform, and material.
6/// 一个可渲染实例:一个网格、可选纹理、变换和材质。
7#[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
16/// Owns meshes, textures, render objects, and the scene light.
17/// 拥有网格、纹理、渲染对象和场景光。
18///
19/// Resources live in [`Arena`]s; the scene exposes the arenas directly so callers can insert assets and get stable handles back.
20/// 资源存放在 [`Arena`] 中;场景直接暴露这些 arena,以便调用方可以插入资源并获得稳定的句柄。
21pub 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   /// Insert a render object and return its handle.
39   /// 插入一个渲染对象并返回其句柄。
40   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}