1use glam::Affine3A;
2use crate::light::LightingEnvironment;
3use crate::material::PbrMaterial;
4use crate::mesh::Mesh;
5use crate::aabb::Aabb;
6
7#[derive(Debug)]
9pub struct SceneNode {
10 pub name: String,
11 pub local_transform: Affine3A,
12 pub mesh_index: Option<usize>,
13 pub children: Vec<SceneNode>,
14 pub visible: bool,
15}
16
17#[derive(Debug)]
19pub struct Scene {
20 pub meshes: Vec<Mesh>,
21 pub materials: Vec<PbrMaterial>,
22 pub nodes: Vec<SceneNode>,
23 pub lighting: LightingEnvironment,
24}
25
26impl Default for Scene {
27 fn default() -> Self {
28 Self {
29 meshes: Vec::new(),
30 materials: vec![PbrMaterial::default()],
31 nodes: Vec::new(),
32 lighting: LightingEnvironment::default(),
33 }
34 }
35}
36
37impl Scene {
39 pub fn single_mesh(name: impl Into<String>, mesh: Mesh, material: PbrMaterial) -> Self {
41 let material_index = 0;
42 let mut mesh = mesh;
43 for sub in &mut mesh.sub_meshes {
44 sub.material_index = material_index;
45 }
46 Self {
47 meshes: vec![mesh],
48 materials: vec![material],
49 nodes: vec![SceneNode {
50 name: name.into(),
51 local_transform: Affine3A::IDENTITY,
52 mesh_index: Some(0),
53 children: Vec::new(),
54 visible: true,
55 }],
56 lighting: LightingEnvironment::default(),
57 }
58 }
59
60 pub fn compute_aabb(&self) -> Aabb {
62 let mut out = Aabb::empty();
63 for node in &self.nodes {
64 out = out.union(&self.compute_node_aabb(node, Affine3A::IDENTITY));
65 }
66 out
67 }
68
69 fn compute_node_aabb(&self, node: &SceneNode, parent_transform: Affine3A) -> Aabb {
70 if !node.visible {
71 return Aabb::empty();
72 }
73 let world = parent_transform * node.local_transform;
74 let mut out = Aabb::empty();
75 if let Some(mesh_idx) = node.mesh_index {
76 if let Some(mesh) = self.meshes.get(mesh_idx) {
77 out = Aabb::from_transformed_aabb(&mesh.aabb, &world);
78 }
79 }
80 for child in &node.children {
81 out = out.union(&self.compute_node_aabb(child, world));
82 }
83 out
84 }
85
86 pub fn with_default_lighting(self) -> Self {
88 Self {
89 lighting: LightingEnvironment::default(),
90 ..self
91 }
92 }
93
94 pub fn with_lighting(mut self, lighting: LightingEnvironment) -> Self {
96 self.lighting = lighting;
97 self
98 }
99}