1use std::borrow::Cow;
2use std::sync::atomic::{AtomicU32, Ordering};
3
4use myth_animation::{AnimationMixer, AnimationTarget};
5use myth_core::{NodeHandle, SkeletonKey, Transform};
6use myth_resources::Input;
7use myth_resources::bloom::BloomSettings;
8use myth_resources::buffer::CpuBuffer;
9use myth_resources::mesh::Mesh;
10use myth_resources::screen_space::ScreenSpaceSettings;
11use myth_resources::shader_defines::ShaderDefines;
12use myth_resources::ssao::SsaoSettings;
13use myth_resources::tone_mapping::ToneMappingSettings;
14use myth_resources::uniforms::{EnvironmentUniforms, GpuLightStorage};
15
16use crate::background::{BackgroundMode, BackgroundSettings};
17use crate::camera::Camera;
18use crate::environment::Environment;
19use crate::light::Light;
20use crate::light::LightKind;
21use crate::node::Node;
22use crate::skeleton::{BindMode, Skeleton, SkinBinding};
23use crate::transform_system;
24use crate::wrapper::SceneNode;
25use glam::{Affine3A, Quat, Vec3};
26use slotmap::{SecondaryMap, SlotMap, SparseSecondaryMap};
27
28static NEXT_SCENE_ID: AtomicU32 = AtomicU32::new(1);
29
30pub trait SceneLogic: Send + Sync + 'static {
52 fn update(&mut self, scene: &mut Scene, input: &Input, dt: f32);
54}
55
56pub struct CallbackLogic<F>(pub F);
58impl<F> SceneLogic for CallbackLogic<F>
59where
60 F: FnMut(&mut Scene, &Input, f32) + Send + Sync + 'static,
61{
62 fn update(&mut self, scene: &mut Scene, input: &Input, dt: f32) {
63 (self.0)(scene, input, dt);
64 }
65}
66
67#[derive(Debug, Clone, Copy, Default)]
69pub struct SplitPrimitiveTag;
70
71pub struct Scene {
96 id: u32,
98
99 #[doc(hidden)]
102 pub nodes: SlotMap<NodeHandle, Node>,
103 root_nodes: Vec<NodeHandle>,
105
106 pub names: SecondaryMap<NodeHandle, Cow<'static, str>>,
109
110 pub meshes: SparseSecondaryMap<NodeHandle, Mesh>,
113 pub cameras: SparseSecondaryMap<NodeHandle, Camera>,
115 pub lights: SparseSecondaryMap<NodeHandle, Light>,
117 pub skins: SparseSecondaryMap<NodeHandle, SkinBinding>,
119 pub morph_weights: SparseSecondaryMap<NodeHandle, Vec<f32>>,
121 pub animation_mixers: SparseSecondaryMap<NodeHandle, AnimationMixer>,
123 pub rest_transforms: SparseSecondaryMap<NodeHandle, Transform>,
126 pub split_primitive_tags: SparseSecondaryMap<NodeHandle, SplitPrimitiveTag>,
128
129 pub skeleton_pool: SlotMap<SkeletonKey, Skeleton>,
132
133 pub environment: Environment,
136 pub tone_mapping: ToneMappingSettings,
138 pub bloom: BloomSettings,
140 pub ssao: SsaoSettings,
142 pub screen_space: ScreenSpaceSettings,
144 pub background: BackgroundSettings,
146 pub active_camera: Option<NodeHandle>,
148
149 #[doc(hidden)]
151 pub light_storage_buffer: CpuBuffer<Vec<GpuLightStorage>>,
152 #[doc(hidden)]
153 pub uniforms_buffer: CpuBuffer<EnvironmentUniforms>,
154 light_data_cache: Vec<GpuLightStorage>,
155
156 shader_defines: ShaderDefines,
157
158 last_env_version: u64,
159
160 pub(crate) logics: Vec<Box<dyn SceneLogic>>,
162}
163
164impl Default for Scene {
165 fn default() -> Self {
166 Self::new()
167 }
168}
169
170impl Scene {
171 pub fn new() -> Self {
172 Self {
173 id: NEXT_SCENE_ID.fetch_add(1, Ordering::Relaxed),
174
175 nodes: SlotMap::with_key(),
176 root_nodes: Vec::new(),
177
178 names: SecondaryMap::new(),
180
181 meshes: SparseSecondaryMap::new(),
183 cameras: SparseSecondaryMap::new(),
184 lights: SparseSecondaryMap::new(),
185 skins: SparseSecondaryMap::new(),
186 morph_weights: SparseSecondaryMap::new(),
187 animation_mixers: SparseSecondaryMap::new(),
188 rest_transforms: SparseSecondaryMap::new(),
189
190 split_primitive_tags: SparseSecondaryMap::new(),
191
192 skeleton_pool: SlotMap::with_key(),
194
195 environment: Environment::new(),
196 tone_mapping: ToneMappingSettings::default(),
197 bloom: BloomSettings::default(),
198 ssao: SsaoSettings::default(),
199 screen_space: ScreenSpaceSettings::default(),
200 background: BackgroundSettings::default(),
201
202 active_camera: None,
203
204 light_storage_buffer: CpuBuffer::new(
205 [GpuLightStorage::default(); 16].to_vec(),
206 wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
207 Some("SceneLightStorageBuffer"),
208 ),
209 uniforms_buffer: CpuBuffer::new(
210 EnvironmentUniforms::default(),
211 wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
212 Some("SceneEnvironmentUniforms"),
213 ),
214
215 light_data_cache: Vec::with_capacity(16),
216
217 shader_defines: ShaderDefines::default(),
218 last_env_version: 0,
219
220 logics: Vec::new(),
221 }
222 }
223
224 #[inline]
230 #[must_use]
231 pub fn id(&self) -> u32 {
232 self.id
233 }
234
235 #[inline]
237 #[must_use]
238 pub fn root_nodes(&self) -> &[NodeHandle] {
239 &self.root_nodes
240 }
241
242 pub fn push_root_node(&mut self, handle: NodeHandle) {
244 self.root_nodes.push(handle);
245 }
246
247 #[inline]
249 #[must_use]
250 pub fn nodes(&self) -> &SlotMap<NodeHandle, Node> {
251 &self.nodes
252 }
253
254 pub fn create_node(&mut self) -> NodeHandle {
260 self.nodes.insert(Node::new())
261 }
262
263 pub fn create_node_with_name(&mut self, name: &str) -> NodeHandle {
265 let handle = self.nodes.insert(Node::new());
266 self.names.insert(handle, Cow::Owned(name.to_string()));
267 handle
268 }
269
270 pub fn add_node(&mut self, node: Node) -> NodeHandle {
272 let handle = self.nodes.insert(node);
273 self.root_nodes.push(handle);
274 handle
275 }
276
277 pub fn add_to_parent(&mut self, child: Node, parent_handle: NodeHandle) -> NodeHandle {
279 let handle = self.nodes.insert(child);
280
281 if let Some(parent) = self.nodes.get_mut(parent_handle) {
283 parent.children.push(handle);
284 }
285 if let Some(child_node) = self.nodes.get_mut(handle) {
286 child_node.parent = Some(parent_handle);
287 }
288
289 handle
290 }
291
292 pub fn remove_node(&mut self, handle: NodeHandle) {
294 let mut to_remove = Vec::new();
296 self.collect_subtree(handle, &mut to_remove);
297
298 if let Some(node) = self.nodes.get(handle) {
300 if let Some(parent_handle) = node.parent {
301 if let Some(parent) = self.nodes.get_mut(parent_handle) {
302 parent.children.retain(|&h| h != handle);
303 }
304 } else {
305 self.root_nodes.retain(|&h| h != handle);
306 }
307 }
308
309 for node_handle in to_remove {
311 self.meshes.remove(node_handle);
312 self.cameras.remove(node_handle);
313 self.lights.remove(node_handle);
314 self.skins.remove(node_handle);
315 self.morph_weights.remove(node_handle);
316 self.names.remove(node_handle);
317 self.animation_mixers.remove(node_handle);
318 self.rest_transforms.remove(node_handle);
319
320 self.nodes.remove(node_handle);
321 }
322 }
323
324 fn collect_subtree(&self, handle: NodeHandle, result: &mut Vec<NodeHandle>) {
326 result.push(handle);
327 if let Some(node) = self.nodes.get(handle) {
328 for &child in &node.children {
329 self.collect_subtree(child, result);
330 }
331 }
332 }
333
334 pub fn attach(&mut self, child_handle: NodeHandle, parent_handle: NodeHandle) {
336 if child_handle == parent_handle {
337 log::warn!("Cannot attach node to itself!");
338 return;
339 }
340
341 if let Some(child_node) = self.nodes.get(child_handle) {
343 if let Some(old_parent) = child_node.parent {
344 if let Some(parent) = self.nodes.get_mut(old_parent) {
345 parent.children.retain(|&h| h != child_handle);
346 }
347 } else {
348 self.root_nodes.retain(|&h| h != child_handle);
349 }
350 }
351
352 if let Some(parent) = self.nodes.get_mut(parent_handle) {
354 parent.children.push(child_handle);
355 } else {
356 log::error!("Parent node not found during attach!");
357 self.root_nodes.push(child_handle);
358 return;
359 }
360
361 if let Some(child) = self.nodes.get_mut(child_handle) {
363 child.parent = Some(parent_handle);
364 child.transform.mark_dirty();
365 }
366 }
367
368 #[inline]
370 pub fn get_node(&self, handle: NodeHandle) -> Option<&Node> {
371 self.nodes.get(handle)
372 }
373
374 #[inline]
376 pub fn get_node_mut(&mut self, handle: NodeHandle) -> Option<&mut Node> {
377 self.nodes.get_mut(handle)
378 }
379
380 pub fn set_name(&mut self, handle: NodeHandle, name: &str) {
386 self.names.insert(handle, Cow::Owned(name.to_string()));
387 }
388
389 pub fn get_name(&self, handle: NodeHandle) -> Option<&str> {
391 self.names.get(handle).map(std::convert::AsRef::as_ref)
392 }
393
394 pub fn set_mesh(&mut self, handle: NodeHandle, mesh: Mesh) {
396 self.meshes.insert(handle, mesh);
397 }
398
399 pub fn get_mesh(&self, handle: NodeHandle) -> Option<&Mesh> {
401 self.meshes.get(handle)
402 }
403
404 pub fn get_mesh_mut(&mut self, handle: NodeHandle) -> Option<&mut Mesh> {
406 self.meshes.get_mut(handle)
407 }
408
409 pub fn set_camera(&mut self, handle: NodeHandle, camera: Camera) {
411 self.cameras.insert(handle, camera);
412 }
413
414 pub fn get_camera(&self, handle: NodeHandle) -> Option<&Camera> {
416 self.cameras.get(handle)
417 }
418
419 pub fn get_camera_mut(&mut self, handle: NodeHandle) -> Option<&mut Camera> {
421 self.cameras.get_mut(handle)
422 }
423
424 pub fn set_light(&mut self, handle: NodeHandle, light: Light) {
426 self.lights.insert(handle, light);
427 }
428
429 pub fn get_light(&self, handle: NodeHandle) -> Option<&Light> {
431 self.lights.get(handle)
432 }
433
434 pub fn get_light_mut(&mut self, handle: NodeHandle) -> Option<&mut Light> {
436 self.lights.get_mut(handle)
437 }
438
439 pub fn get_light_bundle(&mut self, handle: NodeHandle) -> Option<(&mut Light, &mut Node)> {
441 let light = self.lights.get_mut(handle)?;
442 let node = self.nodes.get_mut(handle)?;
443 Some((light, node))
444 }
445
446 pub fn bind_skeleton(
448 &mut self,
449 handle: NodeHandle,
450 skeleton_key: SkeletonKey,
451 bind_mode: BindMode,
452 ) {
453 if let Some(node) = self.nodes.get(handle) {
454 let bind_matrix_inv = node.transform.world_matrix.inverse();
455 self.skins.insert(
456 handle,
457 SkinBinding {
458 skeleton: skeleton_key,
459 bind_mode,
460 bind_matrix_inv,
461 },
462 );
463 }
464 }
465
466 pub fn get_skin(&self, handle: NodeHandle) -> Option<&SkinBinding> {
468 self.skins.get(handle)
469 }
470
471 pub fn set_morph_weights(&mut self, handle: NodeHandle, weights: Vec<f32>) {
473 self.morph_weights.insert(handle, weights);
474 }
475
476 pub fn get_morph_weights(&self, handle: NodeHandle) -> Option<&Vec<f32>> {
478 self.morph_weights.get(handle)
479 }
480
481 pub fn get_morph_weights_mut(&mut self, handle: NodeHandle) -> Option<&mut Vec<f32>> {
483 self.morph_weights.get_mut(handle)
484 }
485
486 pub fn set_morph_weights_from_pod(
488 &mut self,
489 handle: NodeHandle,
490 data: &myth_animation::values::MorphWeightData,
491 ) {
492 let weights = self.morph_weights.entry(handle).unwrap().or_default();
493
494 if weights.len() != data.weights.len() {
495 weights.resize(data.weights.len(), 0.0);
496 }
497 weights.copy_from_slice(&data.weights);
498 }
499
500 pub fn iter_active_lights(&self) -> impl Iterator<Item = (&Light, &Affine3A)> {
505 self.lights.iter().filter_map(move |(node_handle, light)| {
506 let node = self.nodes.get(node_handle)?;
507 if node.visible {
508 Some((light, &node.transform.world_matrix))
509 } else {
510 None
511 }
512 })
513 }
514
515 pub fn query_main_camera_bundle(&mut self) -> Option<(&mut Transform, &mut Camera)> {
521 let node_handle = self.active_camera?;
522 self.query_camera_bundle(node_handle)
523 }
524
525 pub fn query_camera_bundle(
526 &mut self,
527 node_handle: NodeHandle,
528 ) -> Option<(&mut Transform, &mut Camera)> {
529 if !self.cameras.contains_key(node_handle) {
531 return None;
532 }
533
534 let transform_ptr = self
536 .nodes
537 .get_mut(node_handle)
538 .map(|n| &raw mut n.transform)?;
539 let camera = self.cameras.get_mut(node_handle)?;
540
541 unsafe { Some((&mut *transform_ptr, camera)) }
543 }
544
545 pub fn query_light_bundle(
547 &mut self,
548 node_handle: NodeHandle,
549 ) -> Option<(&mut Transform, &Light)> {
550 let light = self.lights.get(node_handle)?;
551 let transform = &mut self.nodes.get_mut(node_handle)?.transform;
552 Some((transform, light))
553 }
554
555 pub fn query_mesh_bundle(
557 &mut self,
558 node_handle: NodeHandle,
559 ) -> Option<(&mut Transform, &Mesh)> {
560 let mesh = self.meshes.get(node_handle)?;
561 let transform = &mut self.nodes.get_mut(node_handle)?.transform;
562 Some((transform, mesh))
563 }
564
565 pub fn update_matrix_world(&mut self) {
571 transform_system::update_hierarchy_iterative(
572 &mut self.nodes,
573 &mut self.cameras,
574 &self.root_nodes,
575 );
576 }
577
578 pub fn update_subtree(&mut self, root_handle: NodeHandle) {
580 transform_system::update_subtree(&mut self.nodes, &mut self.cameras, root_handle);
581 }
582
583 pub fn add_mesh(&mut self, mesh: Mesh) -> NodeHandle {
588 let node_handle = self.create_node_with_name(&mesh.name);
589 self.meshes.insert(node_handle, mesh);
590 self.root_nodes.push(node_handle);
591 node_handle
592 }
593
594 pub fn add_mesh_to_parent(&mut self, mesh: Mesh, parent: NodeHandle) -> NodeHandle {
595 let node_handle = self.create_node_with_name(&mesh.name);
596 self.meshes.insert(node_handle, mesh);
597 self.attach(node_handle, parent);
598 node_handle
599 }
600
601 pub fn add_skeleton(&mut self, skeleton: Skeleton) -> SkeletonKey {
602 self.skeleton_pool.insert(skeleton)
603 }
604
605 pub fn add_camera(&mut self, camera: Camera) -> NodeHandle {
606 let node_handle = self.create_node_with_name("Camera");
607 self.cameras.insert(node_handle, camera);
608 self.root_nodes.push(node_handle);
609 node_handle
610 }
611
612 pub fn add_camera_to_parent(&mut self, camera: Camera, parent: NodeHandle) -> NodeHandle {
613 let node_handle = self.create_node_with_name("Camera");
614 self.cameras.insert(node_handle, camera);
615 self.attach(node_handle, parent);
616 node_handle
617 }
618
619 pub fn add_light(&mut self, light: Light) -> NodeHandle {
620 let node_handle = self.create_node_with_name("Light");
621 self.lights.insert(node_handle, light);
622 self.root_nodes.push(node_handle);
623 node_handle
624 }
625
626 pub fn add_light_to_parent(&mut self, light: Light, parent: NodeHandle) -> NodeHandle {
627 let node_handle = self.create_node_with_name("Light");
628 self.lights.insert(node_handle, light);
629 self.attach(node_handle, parent);
630 node_handle
631 }
632
633 pub fn mark_as_split_primitive(&mut self, handle: NodeHandle) {
634 self.split_primitive_tags.insert(handle, SplitPrimitiveTag);
635 }
636
637 fn sync_shader_defines(&mut self) {
639 let current_env_version = self.environment.version();
640
641 if self.last_env_version != current_env_version {
643 let mut defines = ShaderDefines::new();
644
645 if self.environment.has_env_map() {
647 defines.set("HAS_ENV_MAP", "1");
648 }
649 self.shader_defines = defines;
652 self.last_env_version = current_env_version;
653 }
654 }
655
656 pub fn shader_defines(&self) -> &ShaderDefines {
660 &self.shader_defines
661 }
662
663 pub fn add_logic<L: SceneLogic>(&mut self, logic: L) {
668 self.logics.push(Box::new(logic));
669 }
670
671 pub fn on_update<F>(&mut self, f: F)
673 where
674 F: FnMut(&mut Scene, &Input, f32) + Send + Sync + 'static,
675 {
676 self.add_logic(CallbackLogic(f));
677 }
678
679 pub fn update(&mut self, input: &Input, dt: f32) {
681 let mut logics = std::mem::take(&mut self.logics);
683 for logic in &mut logics {
684 logic.update(self, input, dt);
685 }
686 self.logics.append(&mut logics);
687
688 {
690 let mut mixers = std::mem::take(&mut self.animation_mixers);
691 for (_handle, mixer) in &mut mixers {
692 mixer.update(dt, self);
693 }
694 self.animation_mixers = mixers;
695 }
696
697 self.update_matrix_world();
699 self.update_skeletons();
700 self.sync_morph_weights();
701 self.sync_shader_defines();
702 self.sync_gpu_buffers();
703 }
704
705 pub fn sync_gpu_buffers(&mut self) {
707 self.sync_light_buffer();
708 self.sync_environment_buffer();
709 }
710
711 fn sync_light_buffer(&mut self) {
713 let mut cache = std::mem::take(&mut self.light_data_cache);
714
715 cache.clear();
716
717 for (light, world_matrix) in self.iter_active_lights() {
718 let pos = world_matrix.translation.to_vec3();
719 let dir = world_matrix.transform_vector3(-Vec3::Z).normalize();
720
721 let mut gpu_light = GpuLightStorage {
722 color: light.color,
723 intensity: light.intensity,
724 position: pos,
725 direction: dir,
726 shadow_layer_index: -1,
727 ..Default::default()
728 };
729
730 match &light.kind {
731 LightKind::Point(point) => {
732 gpu_light.light_type = 1;
733 gpu_light.range = point.range;
734 }
735 LightKind::Spot(spot) => {
736 gpu_light.light_type = 2;
737 gpu_light.range = spot.range;
738 gpu_light.inner_cone_cos = spot.inner_cone.cos();
739 gpu_light.outer_cone_cos = spot.outer_cone.cos();
740 }
741 LightKind::Directional(_) => {
742 gpu_light.light_type = 0;
743 }
744 }
745
746 cache.push(gpu_light);
747 }
748
749 if cache.is_empty() {
750 cache.push(GpuLightStorage::default());
751 }
752
753 self.light_data_cache = cache;
754
755 let needs_update =
756 self.light_storage_buffer.read().as_slice() != self.light_data_cache.as_slice();
757
758 if needs_update {
759 self.light_storage_buffer
760 .write()
761 .clone_from(&self.light_data_cache);
762 }
763 }
764
765 fn sync_environment_buffer(&mut self) {
767 let env = &self.environment;
768 let light_count = self.lights.len();
769
770 let new_uniforms = EnvironmentUniforms {
771 ambient_light: env.ambient,
772 num_lights: light_count as u32,
773 env_map_intensity: env.intensity,
774 env_map_rotation: env.rotation,
775 env_map_max_mip_level: self.uniforms_buffer.read().env_map_max_mip_level,
778 ..Default::default()
779 };
780
781 let needs_update = *self.uniforms_buffer.read() != new_uniforms;
782
783 if needs_update {
784 *self.uniforms_buffer.write() = new_uniforms;
785 }
786 }
787
788 pub fn light_storage(&self) -> &CpuBuffer<Vec<GpuLightStorage>> {
793 &self.light_storage_buffer
794 }
795
796 pub fn environment_uniforms(&self) -> &CpuBuffer<EnvironmentUniforms> {
797 &self.uniforms_buffer
798 }
799
800 pub fn update_skeletons(&mut self) {
801 let mut tasks = Vec::new();
802
803 for (node_handle, binding) in &self.skins {
804 if let Some(node) = self.nodes.get(node_handle) {
805 let root_inv = match binding.bind_mode {
806 BindMode::Attached => node.transform.world_matrix.inverse(),
807 BindMode::Detached => binding.bind_matrix_inv,
808 };
809 tasks.push((binding.skeleton, root_inv));
810 }
811 }
812
813 for (skeleton_id, root_inv) in tasks {
814 if let Some(skeleton) = self.skeleton_pool.get_mut(skeleton_id) {
815 skeleton.compute_joint_matrices(&self.nodes, root_inv);
816 if skeleton.local_bounds.is_none() {
818 skeleton.compute_local_bounds(&self.nodes);
819 }
820 }
821 }
822 }
823
824 pub fn sync_morph_weights(&mut self) {
825 for (handle, weights) in &self.morph_weights {
826 if weights.is_empty() {
827 continue;
828 }
829
830 let weights_slice = weights.as_slice();
831
832 if let Some(mesh) = self.meshes.get_mut(handle) {
833 mesh.set_morph_target_influences(weights_slice);
834 mesh.update_morph_uniforms();
835 } else if let Some(node) = self.nodes.get(handle) {
836 for &child_handle in &node.children {
837 if self.split_primitive_tags.contains_key(child_handle)
839 && let Some(child_mesh) = self.meshes.get_mut(child_handle)
840 {
841 child_mesh.set_morph_target_influences(weights_slice);
842 child_mesh.update_morph_uniforms();
843 }
844 }
845 }
846 }
847 }
848
849 pub fn main_camera_node_mut(&mut self) -> Option<&mut Node> {
850 let handle = self.active_camera?;
851 self.get_node_mut(handle)
852 }
853
854 pub fn main_camera_node(&self) -> Option<&Node> {
855 let handle = self.active_camera?;
856 self.get_node(handle)
857 }
858
859 pub fn set_background_color(&mut self, r: f32, g: f32, b: f32) {
865 self.background.set_mode(BackgroundMode::color(r, g, b));
866 }
867
868 pub fn node(&mut self, handle: &NodeHandle) -> SceneNode<'_> {
885 SceneNode::new(self, *handle)
886 }
887
888 pub fn build_node(&mut self, name: &str) -> NodeBuilder<'_> {
890 NodeBuilder::new(self, name)
891 }
892
893 pub fn find_node_by_name(&self, name: &str) -> Option<NodeHandle> {
895 for (handle, node_name) in &self.names {
896 if node_name.as_ref() == name {
897 return Some(handle);
898 }
899 }
900 None
901 }
902
903 pub fn get_global_transform(&self, handle: NodeHandle) -> Affine3A {
905 self.nodes
906 .get(handle)
907 .map_or(Affine3A::IDENTITY, |n| n.transform.world_matrix)
908 }
909
910 pub fn play_animation(&mut self, node_handle: NodeHandle, clip_name: &str) {
912 if let Some(mixer) = self.animation_mixers.get_mut(node_handle) {
913 mixer.play(clip_name);
914 } else {
915 log::warn!("No animation mixer found for node {node_handle:?}");
916 }
917 }
918
919 pub fn play_if_any_animation(&mut self, node_handle: NodeHandle) {
921 if let Some(mixer) = self.animation_mixers.get_mut(node_handle) {
922 mixer
923 .any_action()
924 .map(myth_animation::mixer::ActionControl::play);
925 } else {
926 log::info!("No animation mixer found for node {node_handle:?}");
927 }
928 }
929
930 fn get_bbox_of_one_node(
938 &self,
939 node_handle: NodeHandle,
940 query: &impl crate::GeometryQuery,
941 ) -> Option<myth_resources::BoundingBox> {
942 let node = self.get_node(node_handle)?;
943 if !node.visible {
944 return None;
945 }
946 let mesh = self.meshes.get(node_handle)?;
947 if !mesh.visible {
948 return None;
949 }
950
951 if let Some(skeleton_binding) = self.skins.get(node_handle)
953 && let Some(skeleton) = self.skeleton_pool.get(skeleton_binding.skeleton)
954 {
955 return skeleton.compute_tight_world_bounds(&self.nodes);
956 }
957
958 let local_bbox = query.get_geometry_bbox(mesh.geometry)?;
960 Some(local_bbox.transform(&node.transform.world_matrix))
961 }
962
963 pub fn get_bbox_of_node(
967 &self,
968 node_handle: NodeHandle,
969 query: &impl crate::GeometryQuery,
970 ) -> Option<myth_resources::BoundingBox> {
971 let mut combined_bbox = self.get_bbox_of_one_node(node_handle, query);
972 let node = self.get_node(node_handle)?;
973 for &child_handle in &node.children {
974 if let Some(child_bbox) = self.get_bbox_of_node(child_handle, query) {
975 combined_bbox = match combined_bbox {
976 Some(existing) => Some(existing.union(&child_bbox)),
977 None => Some(child_bbox),
978 };
979 }
980 }
981
982 combined_bbox
983 }
984}
985
986pub struct NodeBuilder<'a> {
991 scene: &'a mut Scene,
992 handle: NodeHandle,
993 parent: Option<NodeHandle>,
994 mesh: Option<Mesh>,
995}
996
997impl<'a> NodeBuilder<'a> {
998 pub fn new(scene: &'a mut Scene, name: &str) -> Self {
999 let handle = scene.nodes.insert(Node::new());
1000 scene.names.insert(handle, Cow::Owned(name.to_string()));
1001 Self {
1002 scene,
1003 handle,
1004 parent: None,
1005 mesh: None,
1006 }
1007 }
1008
1009 #[must_use]
1010 pub fn with_position(self, x: f32, y: f32, z: f32) -> Self {
1011 if let Some(node) = self.scene.nodes.get_mut(self.handle) {
1012 node.transform.position = glam::Vec3::new(x, y, z);
1013 }
1014 self
1015 }
1016
1017 #[must_use]
1018 pub fn with_scale(self, s: f32) -> Self {
1019 if let Some(node) = self.scene.nodes.get_mut(self.handle) {
1020 node.transform.scale = glam::Vec3::splat(s);
1021 }
1022 self
1023 }
1024
1025 #[must_use]
1026 pub fn with_parent(mut self, parent: NodeHandle) -> Self {
1027 self.parent = Some(parent);
1028 self
1029 }
1030
1031 #[must_use]
1032 pub fn with_mesh(mut self, mesh: Mesh) -> Self {
1033 self.mesh = Some(mesh);
1034 self
1035 }
1036
1037 pub fn build(self) -> NodeHandle {
1038 let handle = self.handle;
1039
1040 if let Some(mesh) = self.mesh {
1042 self.scene.meshes.insert(handle, mesh);
1043 }
1044
1045 if let Some(parent) = self.parent {
1047 self.scene.attach(handle, parent);
1048 } else {
1049 self.scene.root_nodes.push(handle);
1050 }
1051
1052 handle
1053 }
1054}
1055
1056impl AnimationTarget for Scene {
1061 fn node_children(&self, handle: NodeHandle) -> Option<Vec<NodeHandle>> {
1062 self.nodes.get(handle).map(|n| n.children().to_vec())
1063 }
1064
1065 fn node_name(&self, handle: NodeHandle) -> Option<String> {
1066 self.names.get(handle).map(|n| n.as_ref().to_string())
1067 }
1068
1069 fn node_transform(&self, handle: NodeHandle) -> Option<Transform> {
1070 self.nodes.get(handle).map(|n| n.transform)
1071 }
1072
1073 fn set_node_position(&mut self, handle: NodeHandle, position: Vec3) {
1074 if let Some(node) = self.nodes.get_mut(handle) {
1075 node.transform.position = position;
1076 }
1077 }
1078
1079 fn set_node_rotation(&mut self, handle: NodeHandle, rotation: Quat) {
1080 if let Some(node) = self.nodes.get_mut(handle) {
1081 node.transform.rotation = rotation;
1082 }
1083 }
1084
1085 fn set_node_scale(&mut self, handle: NodeHandle, scale: Vec3) {
1086 if let Some(node) = self.nodes.get_mut(handle) {
1087 node.transform.scale = scale;
1088 }
1089 }
1090
1091 fn mark_node_dirty(&mut self, handle: NodeHandle) {
1092 if let Some(node) = self.nodes.get_mut(handle) {
1093 node.transform.mark_dirty();
1094 }
1095 }
1096
1097 fn has_rest_transform(&self, handle: NodeHandle) -> bool {
1098 self.rest_transforms.contains_key(handle)
1099 }
1100
1101 fn rest_transform(&self, handle: NodeHandle) -> Option<Transform> {
1102 self.rest_transforms.get(handle).copied()
1103 }
1104
1105 fn store_rest_transform(&mut self, handle: NodeHandle, transform: Transform) {
1106 self.rest_transforms.insert(handle, transform);
1107 }
1108
1109 fn morph_weights_mut(&mut self, handle: NodeHandle) -> &mut Vec<f32> {
1110 self.morph_weights.entry(handle).unwrap().or_default()
1111 }
1112}