diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 563f126d..324f3249 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -78,11 +78,13 @@ jobs: ${{ needs.install-cargo-gpu.outputs.cachepath-Windows }} key: rust-gpu-cache-0-${{ runner.os }} - uses: moonrepo/setup-rust@v1 + - run: rustup component add --toolchain nightly rustfmt - run: cargo gpu show commitsh - run: rm -rf crates/renderling/src/linkage/* crates/renderling/shaders - run: cargo shaders - run: cargo linkage - run: cargo build -p renderling + - run: cargo +nightly fmt - run: git diff --exit-code --no-ext-diff # BAU clippy lints diff --git a/crates/example/src/lib.rs b/crates/example/src/lib.rs index e768debc..7ab6014f 100644 --- a/crates/example/src/lib.rs +++ b/crates/example/src/lib.rs @@ -286,29 +286,8 @@ impl App { let scene = doc.default_scene.unwrap_or(0); log::info!("Displaying scene {scene}"); - fn get_children(doc: &GltfDocument, n: usize) -> Vec { - let mut children = vec![]; - if let Some(parent) = doc.nodes.get(n) { - children.extend(parent.children.iter().copied()); - let descendants = parent - .children - .iter() - .copied() - .flat_map(|n| get_children(doc, n)); - children.extend(descendants); - } - children - } - let nodes = doc.nodes_in_scene(scene).flat_map(|n| { - let mut all_nodes = vec![n]; - for child_index in get_children(&doc, n.index) { - if let Some(child_node) = doc.nodes.get(child_index) { - all_nodes.push(child_node); - } - } - all_nodes - }); + let nodes = doc.recursive_nodes_in_scene(scene); log::trace!(" nodes:"); for node in nodes { let tfrm = Mat4::from(node.global_transform()); diff --git a/crates/renderling/src/gltf.rs b/crates/renderling/src/gltf.rs index 980e67fa..2d9706ee 100644 --- a/crates/renderling/src/gltf.rs +++ b/crates/renderling/src/gltf.rs @@ -2,7 +2,8 @@ //! //! # Loading GLTF files //! -//! Loading GLTF files is accomplished through [`Stage::load_gltf_document_from_path`] +//! Loading GLTF files is accomplished through +//! [`Stage::load_gltf_document_from_path`] //! and [`Stage::load_gltf_document_from_bytes`]. use std::{collections::HashMap, sync::Arc}; @@ -458,8 +459,8 @@ impl GltfPrimitive { // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#morph-targets // // TODO: Generate morph target normals and tangents if absent. - // Although the spec says we have to generate normals or tangents if not specified, - // we are explicitly *not* doing that here. + // Although the spec says we have to generate normals or tangents if not + // specified, we are explicitly *not* doing that here. let morph_targets: Vec> = reader .read_morph_targets() .map(|(may_ps, may_ns, may_ts)| { @@ -1236,7 +1237,24 @@ where self.primitives.iter().flat_map(|(_, rs)| rs.iter()) } - pub fn nodes_in_scene(&self, scene_index: usize) -> impl Iterator { + fn collect_nodes_recursive<'a>(&'a self, node_index: usize, nodes: &mut Vec<&'a GltfNode>) { + if let Some(node) = self.nodes.get(node_index) { + nodes.push(node); + for child_index in node.children.iter() { + self.collect_nodes_recursive(*child_index, nodes); + } + } + } + + /// Returns the root (top-level) nodes in the given scene. + /// + /// This roughly follows [`gltf::Scene::nodes`](https://docs.rs/gltf/latest/gltf/scene/struct.Scene.html#method.nodes), + /// returning only the nodes directly referenced by the scene — not + /// their children. + /// + /// Use [`recursive_nodes_in_scene`](Self::recursive_nodes_in_scene) + /// if you need all nodes (including descendants). + pub fn root_nodes_in_scene(&self, scene_index: usize) -> impl Iterator { let scene = self.scenes.get(scene_index); let mut nodes = vec![]; if let Some(indices) = scene { @@ -1249,9 +1267,26 @@ where nodes.into_iter() } + /// Returns all nodes in the given scene, recursively including + /// children. + /// + /// Root nodes are visited first, followed by their descendants in + /// depth-first order. + pub fn recursive_nodes_in_scene(&self, scene_index: usize) -> impl Iterator { + let scene = self.scenes.get(scene_index); + let mut nodes = vec![]; + if let Some(indices) = scene { + for node_index in indices { + self.collect_nodes_recursive(*node_index, &mut nodes); + } + } + nodes.into_iter() + } + /// Returns the bounding volume of this document, if possible. /// - /// This function will return `None` if this document does not contain meshes. + /// This function will return `None` if this document does not contain + /// meshes. pub fn bounding_volume(&self) -> Option { let mut aabbs = vec![]; for node in self.nodes.iter() { @@ -1505,8 +1540,8 @@ mod test { // .get(0) // .unwrap() // .clone() - // .into_animator(doc.nodes.iter().map(|n| (n.index, n.transform.clone()))); - // animator.progress(0.0).unwrap(); + // .into_animator(doc.nodes.iter().map(|n| (n.index, + // n.transform.clone()))); animator.progress(0.0).unwrap(); // let frame = ctx.get_next_frame().unwrap(); // stage.render(&frame.view()); // let img = frame.read_image().unwrap(); diff --git a/crates/renderling/src/gltf/anime.rs b/crates/renderling/src/gltf/anime.rs index ddaf90e4..939f8688 100644 --- a/crates/renderling/src/gltf/anime.rs +++ b/crates/renderling/src/gltf/anime.rs @@ -787,7 +787,7 @@ mod test { .unwrap(); let nodes = doc - .nodes_in_scene(doc.default_scene.unwrap_or_default()) + .recursive_nodes_in_scene(doc.default_scene.unwrap_or_default()) .collect::>(); let mut animator = Animator::new(nodes, doc.animations.first().unwrap().clone()); diff --git a/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs b/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs index 9c1af43d..8fa577ac 100644 --- a/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs +++ b/crates/renderling/src/linkage/light_tiling_compute_tile_min_and_max_depth_multisampled.rs @@ -6,7 +6,10 @@ mod target { pub const ENTRY_POINT: &str = "light::shader::light_tiling_compute_tile_min_and_max_depth_multisampled"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu :: include_spirv ! ("../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.spv") + wgpu::include_spirv!( + "../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.\ + spv" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!( @@ -24,7 +27,10 @@ mod target { pub const ENTRY_POINT: &str = "lightshaderlight_tiling_compute_tile_min_and_max_depth_multisampled"; pub fn descriptor() -> wgpu::ShaderModuleDescriptor<'static> { - wgpu :: include_wgsl ! ("../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.wgsl") + wgpu::include_wgsl!( + "../../shaders/light-shader-light_tiling_compute_tile_min_and_max_depth_multisampled.\ + wgsl" + ) } pub fn linkage(device: &wgpu::Device) -> super::ShaderLinkage { log::debug!(