From aeab09b1f70a2e205e7f77702b134cd47f294f62 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Tue, 8 Oct 2024 11:48:52 -0700 Subject: [PATCH] desktop: Use instancing in `--rerun=render-mesh`. This seems to be slower to render but significantly cuts down the recording size and gives the viewer more structure to work with. --- Cargo.lock | 1 + all-is-cubes-desktop/Cargo.toml | 1 + all-is-cubes-desktop/src/glue/rerun_mesh.rs | 46 ++++++++++++++----- all-is-cubes-mesh/src/dynamic/chunked_mesh.rs | 2 +- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c516946b2..8c99b0e98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,6 +154,7 @@ dependencies = [ "futures-core", "gilrs", "gltf", + "hashbrown", "indicatif", "itertools 0.13.0", "kira", diff --git a/all-is-cubes-desktop/Cargo.toml b/all-is-cubes-desktop/Cargo.toml index 574ba66e0..548d387b6 100644 --- a/all-is-cubes-desktop/Cargo.toml +++ b/all-is-cubes-desktop/Cargo.toml @@ -77,6 +77,7 @@ clap = { workspace = true } directories-next = "2.0.0" futures-core = { workspace = true } gilrs = { workspace = true } +hashbrown = { workspace = true } indicatif = { version = "0.17.0", default-features = false } itertools = { workspace = true } kira = { version = "0.9.4", optional = true, default-features = false, features = ["cpal"] } diff --git a/all-is-cubes-desktop/src/glue/rerun_mesh.rs b/all-is-cubes-desktop/src/glue/rerun_mesh.rs index a45e27fb0..0f8bb95a3 100644 --- a/all-is-cubes-desktop/src/glue/rerun_mesh.rs +++ b/all-is-cubes-desktop/src/glue/rerun_mesh.rs @@ -7,7 +7,7 @@ use itertools::Itertools as _; use all_is_cubes::euclid::{Point3D, Vector3D}; use all_is_cubes::math::{Cube, GridCoordinate}; use all_is_cubes::rerun_glue as rg; -use all_is_cubes::space::Space; +use all_is_cubes::space::{BlockIndex, Space}; use all_is_cubes::time::DeadlineStd; use all_is_cubes::universe::Handle; use all_is_cubes_mesh as mesh; @@ -27,8 +27,7 @@ impl mesh::dynamic::DynamicMeshTypes for Mt { type Instant = Instant; - // Instances are not supported by Rerun, so we should not generate them. - const MAXIMUM_MERGED_BLOCK_MESH_SIZE: usize = usize::MAX; + const MAXIMUM_MERGED_BLOCK_MESH_SIZE: usize = 300; } const CHUNK_SIZE: GridCoordinate = 32; @@ -85,7 +84,6 @@ struct DroppingMesh { mesh: rg::archetypes::Mesh3D, destination: rg::Destination, } - impl Drop for DroppingMesh { fn drop(&mut self) { // Clear the mesh entity we point to @@ -111,9 +109,7 @@ impl RerunMesher { let _info = self.csm.update(camera, DeadlineStd::Whenever, |u| { assert!(!u.indices_only); - let Some(translation) = u.mesh_id.singleton_translation(CHUNK_SIZE) else { - return; // can't handle instances yet - }; + let singleton_translation = u.mesh_id.singleton_translation(CHUNK_SIZE); let dm = u.render_data.get_or_insert_with(|| { let dm = DroppingMesh { @@ -121,10 +117,14 @@ impl RerunMesher { mesh: rg::archetypes::Mesh3D::new([[0., 0., 0.]; 0]), }; - dm.destination.log( - &rg::entity_path![], - &rg::archetypes::Transform3D::from_translation(rg::convert_vec(translation)), - ); + if let Some(translation) = singleton_translation { + dm.destination.log( + &rg::entity_path![], + &rg::archetypes::Transform3D::from_translation(rg::convert_vec( + translation, + )), + ); + } dm }); @@ -134,6 +134,30 @@ impl RerunMesher { // TODO: this will need different handling for instances dm.destination.log(&rg::entity_path![], &dm.mesh); }); + + // Gather and send all instances. + // TODO: It would be more efficient to do this only if there was a change, but + // `ChunkedSpaceMesh` doesn't have a way to report that. + let mut instances: hashbrown::HashMap> = Default::default(); + for chunk in self.csm.iter_chunks() { + for (i, cubes) in chunk.block_instances() { + instances.entry(i).or_default().extend(cubes); + } + } + for (i, cubes) in instances { + if let Some(mesh) = self.csm.block_instance_mesh(i) { + if let Some(dm) = &mesh.render_data { + dm.destination.log( + &rg::entity_path![], + &rg::archetypes::InstancePoses3D::new().with_translations( + cubes + .into_iter() + .map(|cube| rg::convert_vec(cube.lower_bounds().to_vector())), + ), + ) + } + } + } } } diff --git a/all-is-cubes-mesh/src/dynamic/chunked_mesh.rs b/all-is-cubes-mesh/src/dynamic/chunked_mesh.rs index f4caf3fab..87f3d42e4 100644 --- a/all-is-cubes-mesh/src/dynamic/chunked_mesh.rs +++ b/all-is-cubes-mesh/src/dynamic/chunked_mesh.rs @@ -198,7 +198,7 @@ where /// * `camera`'s view position is used to choose what to update and for depth /// ordering; its graphics options are used for triangulation and view distance. /// * `deadline` is the approximate time at which this should stop. - /// * `render_data_updater` is called for every re-meshed or depth-sorted chunk. + /// * `render_data_updater` is called for every re-meshed or depth-sorted chunk or block. /// It may be called concurrently from multiple threads. /// /// Returns performance information and the chunk the camera is located in.