1use crate::geometry::Mesh;
2use crate::material::Material;
3use glam::{Mat4, Quat, Vec3};
4use std::sync::Arc;
5
6#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
9pub struct Transform {
10 pub translation: Vec3,
11 pub rotation: Quat,
12 pub scale: Vec3,
13}
14
15impl Transform {
16 pub const IDENTITY: Self = Self {
17 translation: Vec3::ZERO,
18 rotation: Quat::IDENTITY,
19 scale: Vec3::ONE,
20 };
21
22 pub fn from_translation(t: Vec3) -> Self {
23 Self { translation: t, ..Self::IDENTITY }
24 }
25
26 pub fn from_rotation(r: Quat) -> Self {
27 Self { rotation: r, ..Self::IDENTITY }
28 }
29
30 pub fn from_scale(s: Vec3) -> Self {
31 Self { scale: s, ..Self::IDENTITY }
32 }
33
34 pub fn from_trs(translation: Vec3, rotation: Quat, scale: Vec3) -> Self {
35 Self { translation, rotation, scale }
36 }
37
38 pub fn matrix(&self) -> Mat4 {
39 Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
40 }
41
42 pub fn global_matrix(&self, parent: &Mat4) -> Mat4 {
43 *parent * self.matrix()
44 }
45
46 pub fn forward(&self) -> Vec3 {
47 self.rotation * -Vec3::Z
48 }
49
50 pub fn right(&self) -> Vec3 {
51 self.rotation * Vec3::X
52 }
53
54 pub fn up(&self) -> Vec3 {
55 self.rotation * Vec3::Y
56 }
57
58 pub fn look_at(&mut self, target: Vec3, world_up: Vec3) {
59 let dir = (target - self.translation).normalize();
60 if dir.length_squared() < 1e-8 {
61 return;
62 }
63 let mat = glam::camera::rh::view::look_at_mat4(self.translation, target, world_up);
64 let (_, rot, _) = mat.inverse().to_scale_rotation_translation();
65 self.rotation = rot;
66 }
67
68 pub fn lerp(&self, other: &Self, t: f32) -> Self {
69 Self {
70 translation: self.translation.lerp(other.translation, t),
71 rotation: self.rotation.slerp(other.rotation, t),
72 scale: self.scale.lerp(other.scale, t),
73 }
74 }
75}
76
77impl Default for Transform {
78 fn default() -> Self {
79 Self::IDENTITY
80 }
81}
82
83pub type NodeId = usize;
86
87#[derive(Debug, Clone)]
88pub struct SceneNode {
89 pub name: String,
90 pub transform: Transform,
91 pub mesh: Option<Arc<Mesh>>,
92 pub material: Option<Arc<Material>>,
93 pub visible: bool,
94 pub children: Vec<NodeId>,
95 pub parent: Option<NodeId>,
96}
97
98impl SceneNode {
99 pub fn new(name: impl Into<String>) -> Self {
100 Self {
101 name: name.into(),
102 transform: Transform::IDENTITY,
103 mesh: None,
104 material: None,
105 visible: true,
106 children: Vec::new(),
107 parent: None,
108 }
109 }
110
111 pub fn with_mesh(mut self, mesh: Arc<Mesh>) -> Self {
112 self.mesh = Some(mesh);
113 self
114 }
115
116 pub fn with_material(mut self, mat: Arc<Material>) -> Self {
117 self.material = Some(mat);
118 self
119 }
120
121 pub fn with_transform(mut self, t: Transform) -> Self {
122 self.transform = t;
123 self
124 }
125}
126
127#[derive(Debug, Default)]
128pub struct Scene {
129 nodes: Vec<SceneNode>,
130 roots: Vec<NodeId>,
131}
132
133impl Scene {
134 pub fn new() -> Self {
135 Self::default()
136 }
137
138 pub fn add_node(&mut self, node: SceneNode) -> NodeId {
139 let id = self.nodes.len();
140 self.nodes.push(node);
141 id
142 }
143
144 pub fn add_root(&mut self, id: NodeId) {
145 self.roots.push(id);
146 }
147
148 pub fn add_child(&mut self, parent: NodeId, child: NodeId) {
149 self.nodes[child].parent = Some(parent);
150 self.nodes[parent].children.push(child);
151 }
152
153 pub fn node(&self, id: NodeId) -> &SceneNode {
154 &self.nodes[id]
155 }
156
157 pub fn node_mut(&mut self, id: NodeId) -> &mut SceneNode {
158 &mut self.nodes[id]
159 }
160
161 pub fn roots(&self) -> &[NodeId] {
162 &self.roots
163 }
164
165 pub fn global_transform(&self, id: NodeId) -> Mat4 {
166 let node = &self.nodes[id];
167 match node.parent {
168 None => node.transform.matrix(),
169 Some(parent_id) => self.global_transform(parent_id) * node.transform.matrix(),
170 }
171 }
172
173 pub fn collect_render_items(&self) -> Vec<(NodeId, Mat4)> {
175 let mut out = Vec::new();
176 for &root in &self.roots {
177 self.collect_recursive(root, Mat4::IDENTITY, &mut out);
178 }
179 out
180 }
181
182 fn collect_recursive(&self, id: NodeId, parent_mat: Mat4, out: &mut Vec<(NodeId, Mat4)>) {
183 let node = &self.nodes[id];
184 if !node.visible {
185 return;
186 }
187 let mat = parent_mat * node.transform.matrix();
188 if node.mesh.is_some() {
189 out.push((id, mat));
190 }
191 for &child in &node.children {
192 self.collect_recursive(child, mat, out);
193 }
194 }
195
196 pub fn spawn_mesh(
198 &mut self,
199 name: impl Into<String>,
200 mesh: Arc<Mesh>,
201 material: Arc<Material>,
202 transform: Transform,
203 ) -> NodeId {
204 let node = SceneNode::new(name)
205 .with_mesh(mesh)
206 .with_material(material)
207 .with_transform(transform);
208 let id = self.add_node(node);
209 self.add_root(id);
210 id
211 }
212}