1use std::sync::Arc;
2use glam::{Vec3, Quat, Mat4};
3use crate::geometry::Mesh;
4use crate::material::Material;
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 { Self { translation: t, ..Self::IDENTITY } }
23 pub fn from_rotation(r: Quat) -> Self { Self { rotation: r, ..Self::IDENTITY } }
24 pub fn from_scale(s: Vec3) -> Self { Self { scale: s, ..Self::IDENTITY } }
25
26 pub fn from_trs(translation: Vec3, rotation: Quat, scale: Vec3) -> Self {
27 Self { translation, rotation, scale }
28 }
29
30 pub fn matrix(&self) -> Mat4 {
31 Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
32 }
33
34 pub fn global_matrix(&self, parent: &Mat4) -> Mat4 {
35 *parent * self.matrix()
36 }
37
38 pub fn forward(&self) -> Vec3 { self.rotation * -Vec3::Z }
39 pub fn right(&self) -> Vec3 { self.rotation * Vec3::X }
40 pub fn up(&self) -> Vec3 { self.rotation * Vec3::Y }
41
42 pub fn look_at(&mut self, target: Vec3, world_up: Vec3) {
43 let dir = (target - self.translation).normalize();
44 if dir.length_squared() < 1e-8 { return; }
45 let mat = Mat4::look_at_rh(self.translation, target, world_up);
46 let (_, rot, _) = mat.inverse().to_scale_rotation_translation();
47 self.rotation = rot;
48 }
49
50 pub fn lerp(&self, other: &Self, t: f32) -> Self {
51 Self {
52 translation: self.translation.lerp(other.translation, t),
53 rotation: self.rotation.slerp(other.rotation, t),
54 scale: self.scale.lerp(other.scale, t),
55 }
56 }
57}
58
59impl Default for Transform {
60 fn default() -> Self { Self::IDENTITY }
61}
62
63pub type NodeId = usize;
66
67#[derive(Debug, Clone)]
68pub struct SceneNode {
69 pub name: String,
70 pub transform: Transform,
71 pub mesh: Option<Arc<Mesh>>,
72 pub material: Option<Arc<Material>>,
73 pub visible: bool,
74 pub children: Vec<NodeId>,
75 pub parent: Option<NodeId>,
76}
77
78impl SceneNode {
79 pub fn new(name: impl Into<String>) -> Self {
80 Self {
81 name: name.into(),
82 transform: Transform::IDENTITY,
83 mesh: None,
84 material: None,
85 visible: true,
86 children: Vec::new(),
87 parent: None,
88 }
89 }
90
91 pub fn with_mesh(mut self, mesh: Arc<Mesh>) -> Self { self.mesh = Some(mesh); self }
92 pub fn with_material(mut self, mat: Arc<Material>) -> Self { self.material = Some(mat); self }
93 pub fn with_transform(mut self, t: Transform) -> Self { self.transform = t; self }
94}
95
96#[derive(Debug, Default)]
97pub struct Scene {
98 nodes: Vec<SceneNode>,
99 roots: Vec<NodeId>,
100}
101
102impl Scene {
103 pub fn new() -> Self { Self::default() }
104
105 pub fn add_node(&mut self, node: SceneNode) -> NodeId {
106 let id = self.nodes.len();
107 self.nodes.push(node);
108 id
109 }
110
111 pub fn add_root(&mut self, id: NodeId) { self.roots.push(id); }
112
113 pub fn add_child(&mut self, parent: NodeId, child: NodeId) {
114 self.nodes[child].parent = Some(parent);
115 self.nodes[parent].children.push(child);
116 }
117
118 pub fn node(&self, id: NodeId) -> &SceneNode { &self.nodes[id] }
119 pub fn node_mut(&mut self, id: NodeId) -> &mut SceneNode { &mut self.nodes[id] }
120
121 pub fn roots(&self) -> &[NodeId] { &self.roots }
122
123 pub fn global_transform(&self, id: NodeId) -> Mat4 {
124 let node = &self.nodes[id];
125 match node.parent {
126 None => node.transform.matrix(),
127 Some(parent_id) => self.global_transform(parent_id) * node.transform.matrix(),
128 }
129 }
130
131 pub fn collect_render_items(&self) -> Vec<(NodeId, Mat4)> {
133 let mut out = Vec::new();
134 for &root in &self.roots {
135 self.collect_recursive(root, Mat4::IDENTITY, &mut out);
136 }
137 out
138 }
139
140 fn collect_recursive(&self, id: NodeId, parent_mat: Mat4, out: &mut Vec<(NodeId, Mat4)>) {
141 let node = &self.nodes[id];
142 if !node.visible { return; }
143 let mat = parent_mat * node.transform.matrix();
144 if node.mesh.is_some() {
145 out.push((id, mat));
146 }
147 for &child in &node.children {
148 self.collect_recursive(child, mat, out);
149 }
150 }
151
152 pub fn spawn_mesh(&mut self, name: impl Into<String>, mesh: Arc<Mesh>, material: Arc<Material>, transform: Transform) -> NodeId {
154 let node = SceneNode::new(name)
155 .with_mesh(mesh)
156 .with_material(material)
157 .with_transform(transform);
158 let id = self.add_node(node);
159 self.add_root(id);
160 id
161 }
162}