diff --git a/Cargo.toml b/Cargo.toml index ca3a88ba..a338163c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "bevy_gaussian_splatting" description = "bevy gaussian splatting render pipeline plugin" -version = "2.7.0" +version = "2.7.1" edition = "2021" authors = ["mosure "] license = "MIT" diff --git a/README.md b/README.md index 5992de43..52a567b9 100644 --- a/README.md +++ b/README.md @@ -79,40 +79,3 @@ fn setup_gaussian_cloud( | `2.1` | `0.13` | | `0.4 - 2.0` | `0.12` | | `0.1 - 0.3` | `0.11` | - -## projects using this plugin -- [kitt2](https://github.com/cs50victor/kitt2) - -# credits - -- [2d-gaussian-splatting](https://github.com/hbb1/2d-gaussian-splatting) -- [4d gaussians](https://github.com/hustvl/4DGaussians) -- [4d-gaussian-splatting](https://fudan-zvg.github.io/4d-gaussian-splatting/) -- [bevy](https://github.com/bevyengine/bevy) -- [bevy-hanabi](https://github.com/djeedai/bevy_hanabi) -- [d3ga](https://zielon.github.io/d3ga/) -- [deformable-3d-gaussians](https://github.com/ingra14m/Deformable-3D-Gaussians) -- [diff-gaussian-rasterization](https://github.com/graphdeco-inria/diff-gaussian-rasterization) -- [dreamgaussian](https://github.com/dreamgaussian/dreamgaussian) -- [dynamic-3d-gaussians](https://github.com/JonathonLuiten/Dynamic3DGaussians) -- [ewa splatting](https://www.cs.umd.edu/~zwicker/publications/EWASplatting-TVCG02.pdf) -- [gaussian-grouping](https://github.com/lkeab/gaussian-grouping) -- [gaussian-splatting](https://github.com/graphdeco-inria/gaussian-splatting) -- [gaussian-splatting-viewer](https://github.com/limacv/GaussianSplattingViewer/tree/main) -- [gaussian-splatting-web](https://github.com/cvlab-epfl/gaussian-splatting-web) -- [gir](https://3dgir.github.io/) -- [making gaussian splats smaller](https://aras-p.info/blog/2023/09/13/Making-Gaussian-Splats-smaller/) -- [masked-spacetime-hashing](https://github.com/masked-spacetime-hashing/msth) -- [onesweep](https://arxiv.org/ftp/arxiv/papers/2206/2206.01784.pdf) -- [pasture](https://github.com/Mortano/pasture) -- [phys-gaussian](https://xpandora.github.io/PhysGaussian/) -- [point-visualizer](https://github.com/mosure/point-visualizer) -- [rusty-automata](https://github.com/mosure/rusty-automata) -- [scaffold-gs](https://city-super.github.io/scaffold-gs/) -- [shader-one-sweep](https://github.com/b0nes164/ShaderOneSweep) -- [spacetime-gaussians](https://github.com/oppo-us-research/SpacetimeGaussians) -- [splat](https://github.com/antimatter15/splat) -- [splatter](https://github.com/Lichtso/splatter) -- [sturdy-dollop](https://github.com/mosure/sturdy-dollop) -- [sugar](https://github.com/Anttwo/SuGaR) -- [taichi_3d_gaussian_splatting](https://github.com/wanmeihuali/taichi_3d_gaussian_splatting) diff --git a/docs/credits.md b/docs/credits.md new file mode 100644 index 00000000..f9b222aa --- /dev/null +++ b/docs/credits.md @@ -0,0 +1,31 @@ +- [2d-gaussian-splatting](https://github.com/hbb1/2d-gaussian-splatting) +- [4d gaussians](https://github.com/hustvl/4DGaussians) +- [4d-gaussian-splatting](https://fudan-zvg.github.io/4d-gaussian-splatting/) +- [bevy](https://github.com/bevyengine/bevy) +- [bevy-hanabi](https://github.com/djeedai/bevy_hanabi) +- [d3ga](https://zielon.github.io/d3ga/) +- [deformable-3d-gaussians](https://github.com/ingra14m/Deformable-3D-Gaussians) +- [diff-gaussian-rasterization](https://github.com/graphdeco-inria/diff-gaussian-rasterization) +- [dreamgaussian](https://github.com/dreamgaussian/dreamgaussian) +- [dynamic-3d-gaussians](https://github.com/JonathonLuiten/Dynamic3DGaussians) +- [ewa splatting](https://www.cs.umd.edu/~zwicker/publications/EWASplatting-TVCG02.pdf) +- [gaussian-grouping](https://github.com/lkeab/gaussian-grouping) +- [gaussian-splatting](https://github.com/graphdeco-inria/gaussian-splatting) +- [gaussian-splatting-viewer](https://github.com/limacv/GaussianSplattingViewer/tree/main) +- [gaussian-splatting-web](https://github.com/cvlab-epfl/gaussian-splatting-web) +- [gir](https://3dgir.github.io/) +- [making gaussian splats smaller](https://aras-p.info/blog/2023/09/13/Making-Gaussian-Splats-smaller/) +- [masked-spacetime-hashing](https://github.com/masked-spacetime-hashing/msth) +- [onesweep](https://arxiv.org/ftp/arxiv/papers/2206/2206.01784.pdf) +- [pasture](https://github.com/Mortano/pasture) +- [phys-gaussian](https://xpandora.github.io/PhysGaussian/) +- [point-visualizer](https://github.com/mosure/point-visualizer) +- [rusty-automata](https://github.com/mosure/rusty-automata) +- [scaffold-gs](https://city-super.github.io/scaffold-gs/) +- [shader-one-sweep](https://github.com/b0nes164/ShaderOneSweep) +- [spacetime-gaussians](https://github.com/oppo-us-research/SpacetimeGaussians) +- [splat](https://github.com/antimatter15/splat) +- [splatter](https://github.com/Lichtso/splatter) +- [sturdy-dollop](https://github.com/mosure/sturdy-dollop) +- [sugar](https://github.com/Anttwo/SuGaR) +- [taichi_3d_gaussian_splatting](https://github.com/wanmeihuali/taichi_3d_gaussian_splatting) diff --git a/src/gaussian/settings.rs b/src/gaussian/settings.rs index 2215b278..70386b99 100644 --- a/src/gaussian/settings.rs +++ b/src/gaussian/settings.rs @@ -1,4 +1,9 @@ use bevy::prelude::*; +use bevy_args::{ + Deserialize, + Serialize, + ValueEnum, +}; use crate::sort::SortMode; @@ -30,6 +35,9 @@ pub enum GaussianCloudDrawMode { Hash, PartialEq, Reflect, + Serialize, + Deserialize, + ValueEnum, )] pub enum GaussianMode { #[default] diff --git a/src/sort/std.rs b/src/sort/std.rs index 2b366536..8dd54f00 100644 --- a/src/sort/std.rs +++ b/src/sort/std.rs @@ -6,11 +6,14 @@ use bevy::{ }; use crate::{ + camera::GaussianCamera, GaussianCloud, GaussianCloudSettings, sort::{ - SortedEntries, + SortConfig, SortMode, + SortTrigger, + SortedEntries, }, }; @@ -29,54 +32,29 @@ impl Plugin for StdSortPlugin { pub fn std_sort( asset_server: Res, gaussian_clouds_res: Res>, - mut sorted_entries_res: ResMut>, gaussian_clouds: Query<( &Handle, &Handle, &GaussianCloudSettings, )>, - cameras: Query<( - &Transform, - &Camera3d, - )>, - mut last_camera_position: Local, - mut last_sort_time: Local>, - mut period: Local, - mut camera_debounce: Local, - mut sort_done: Local, + mut sorted_entries_res: ResMut>, + mut cameras: Query< + &mut SortTrigger, + With, + >, + mut sort_config: ResMut, ) { - if last_sort_time.is_none() { - *period = std::time::Duration::from_millis(100); - } - - if let Some(last_sort_time) = last_sort_time.as_ref() { - if last_sort_time.elapsed() < *period { - return; - } - } + // TODO: move sort to render world, use extracted views and update the existing buffer instead of creating new let sort_start_time = Instant::now(); let mut performed_sort = false; - for ( - camera_transform, - _camera, - ) in cameras.iter() { - let camera_position = camera_transform.compute_affine().translation; - let camera_movement = *last_camera_position != camera_position; - - if camera_movement { - *sort_done = false; - *camera_debounce = true; - } else if *sort_done { - return; - } - - if *camera_debounce { - *last_camera_position = camera_position; - *camera_debounce = false; - return; + for mut trigger in cameras.iter_mut() { + if !trigger.needs_sort { + continue; } + trigger.needs_sort = false; + performed_sort = true; for ( gaussian_cloud_handle, @@ -97,28 +75,25 @@ pub fn std_sort( if let Some(gaussian_cloud) = gaussian_clouds_res.get(gaussian_cloud_handle) { if let Some(sorted_entries) = sorted_entries_res.get_mut(sorted_entries_handle) { - assert_eq!(gaussian_cloud.len(), sorted_entries.sorted.len()); - - *sort_done = true; - *last_sort_time = Some(Instant::now()); - - performed_sort = true; + let gaussians = gaussian_cloud.len(); + let mut chunks = sorted_entries.sorted.chunks_mut(gaussians); + let chunk = chunks.nth(trigger.camera_index).unwrap(); gaussian_cloud.position_iter() - .zip(sorted_entries.sorted.iter_mut()) + .zip(chunk.iter_mut()) .enumerate() .for_each(|(idx, (position, sort_entry))| { let position = Vec3A::from_slice(position.as_ref()); let position = settings.transform.compute_affine().transform_point3a(position); - let delta = camera_position - position; + let delta = trigger.last_camera_position - position; sort_entry.key = bytemuck::cast(delta.length_squared()); sort_entry.index = idx as u32; }); - sorted_entries.sorted.sort_unstable_by(|a, b| { - bytemuck::cast::(b.key).partial_cmp(&bytemuck::cast::(a.key)).unwrap() + chunk.sort_unstable_by(|a, b| { + bytemuck::cast::(b.key).partial_cmp(&bytemuck::cast::(a.key)).unwrap_or(std::cmp::Ordering::Equal) }); // TODO: update DrawIndirect buffer during sort phase (GPU sort will override default DrawIndirect) @@ -131,10 +106,9 @@ pub fn std_sort( let delta = sort_end_time - sort_start_time; if performed_sort { - *period = std::time::Duration::from_millis( - 100 - .max(period.as_millis() as u64 * 4 / 5) - .max(10 * delta.as_millis() as u64) - ); + sort_config.period_ms = sort_config.period_ms + .max(sort_config.period_ms * 4 / 5) + .max(4 * delta.as_millis() as usize); } } + diff --git a/src/utils.rs b/src/utils.rs index 6ea029e5..06cfe50e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -5,6 +5,8 @@ use bevy_args::{ Serialize, }; +use crate::gaussian::settings::GaussianMode; + #[derive( Debug, @@ -45,6 +47,9 @@ pub struct GaussianSplattingViewer { #[arg(long, default_value = "0")] pub gaussian_count: usize, + #[arg(long, value_enum, default_value_t = GaussianMode::Gaussian3d)] + pub gaussian_mode: GaussianMode, + #[arg(long, default_value = "0")] pub particle_count: usize, } @@ -62,6 +67,7 @@ impl Default for GaussianSplattingViewer { msaa_samples: 1, input_file: "".to_string(), gaussian_count: 0, + gaussian_mode: GaussianMode::Gaussian3d, particle_count: 0, } }