diff --git a/Cargo.toml b/Cargo.toml index c8b9f546..57ad29f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ [package] name = "bevy_gaussian_splatting" description = "bevy gaussian splatting render pipeline plugin" -version = "2.7.2" +version = "2.7.3" edition = "2021" authors = ["mosure "] -license = "MIT" +license = "MIT OR Apache-2.0" keywords = [ "bevy", "gaussian-splatting", @@ -82,6 +82,7 @@ sh0 = [] sh1 = [] sh2 = [] sh3 = [] +sh4 = [] precompute_covariance_3d = [] @@ -141,12 +142,13 @@ webgpu = ["bevy/webgpu"] [dependencies] bevy_args = "1.6" -bevy-inspector-egui = { version = "0.26", optional = true } # update to latest once they upgrade to bevy_egui 0.30 (currently at 0.29) +bevy-inspector-egui = { version = "0.27", optional = true } bevy_mod_picking = { version = "0.20", optional = true } -bevy_panorbit_camera = { version = "0.19", optional = true, features = ["bevy_egui"] } +# bevy_panorbit_camera = { git = "https://github.com/mosure/bevy_panorbit_camera.git", optional = true, features = ["bevy_egui"] } +bevy_panorbit_camera = { version = "0.19.5", optional = true, features = ["bevy_egui"] } bevy_transform_gizmo = { version = "0.12", optional = true } bincode2 = { version = "2.0", optional = true } -byte-unit = { version = "5.0", optional = true } +byte-unit = { version = "5.1", optional = true } bytemuck = "1.19" clap = { version = "4.5", features = ["derive"] } flate2 = { version = "1.0", optional = true } @@ -196,7 +198,7 @@ features = [ [dev-dependencies] criterion = { version = "0.5", features = ["html_reports"] } futures-intrusive = { version = "0.5.0" } -pollster = { version = "0.3.0" } +pollster = { version = "0.4.0" } [profile.dev.package."*"] opt-level = 3 diff --git a/LICENSE-APACHE b/LICENSE-APACHE new file mode 100644 index 00000000..d9a10c0d --- /dev/null +++ b/LICENSE-APACHE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/LICENSE b/LICENSE-MIT similarity index 96% rename from LICENSE rename to LICENSE-MIT index b7864198..9cf10627 100644 --- a/LICENSE +++ b/LICENSE-MIT @@ -1,7 +1,5 @@ MIT License -Copyright (c) 2023 Mitchell Mosure - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights diff --git a/README.md b/README.md index 52a567b9..beeff5e8 100644 --- a/README.md +++ b/README.md @@ -79,3 +79,19 @@ fn setup_gaussian_cloud( | `2.1` | `0.13` | | `0.4 - 2.0` | `0.12` | | `0.1 - 0.3` | `0.11` | + + +## license + +licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +## contribution + +unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any +additional terms or conditions. diff --git a/examples/headless.rs b/examples/headless.rs index 618ee8f1..1e793950 100644 --- a/examples/headless.rs +++ b/examples/headless.rs @@ -408,7 +408,7 @@ fn setup_gaussian_cloud( }, ..default() }, - GaussianCamera, + GaussianCamera::default(), )); } diff --git a/examples/multi_camera.rs b/examples/multi_camera.rs index 6bebf98b..db8d4400 100644 --- a/examples/multi_camera.rs +++ b/examples/multi_camera.rs @@ -69,7 +69,7 @@ fn compare_surfel_app() { app.add_systems( Update, ( - // press_s_swap_cameras, + press_s_to_spawn_camera, set_camera_viewports, ) ); @@ -80,56 +80,53 @@ fn compare_surfel_app() { pub fn setup_surfel_compare( mut commands: Commands, + _asset_server: Res, mut gaussian_assets: ResMut>, ) { let grid_size_x = 10; let grid_size_y = 10; let spacing = 12.0; - let visualize_bounding_box = false; - let mut blue_gaussians = Vec::new(); - let mut blue_sh = SphericalHarmonicCoefficients::default(); - blue_sh.set(2, 5.0); + // let mut blue_gaussians = Vec::new(); + // let mut blue_sh = SphericalHarmonicCoefficients::default(); + // blue_sh.set(2, 5.0); - for i in 0..grid_size_x { - for j in 0..grid_size_y { - let x = i as f32 * spacing - (grid_size_x as f32 * spacing) / 2.0; - let y = j as f32 * spacing - (grid_size_y as f32 * spacing) / 2.0; - let position = [x, y, 0.0, 1.0]; - let scale = [2.0, 1.0, 0.01, 0.5]; + // for i in 0..grid_size_x { + // for j in 0..grid_size_y { + // let x = i as f32 * spacing - (grid_size_x as f32 * spacing) / 2.0; + // let y = j as f32 * spacing - (grid_size_y as f32 * spacing) / 2.0; + // let position = [x, y, 0.0, 1.0]; + // let scale = [2.0, 1.0, 0.01, 0.5]; - let angle = std::f32::consts::PI / 2.0 * i as f32 / grid_size_x as f32; - let rotation = Quat::from_rotation_z(angle).to_array(); - let rotation = [3usize, 0usize, 1usize, 2usize] - .iter() - .map(|i| rotation[*i]) - .collect::>() - .try_into() - .unwrap(); + // let angle = std::f32::consts::PI / 2.0 * i as f32 / grid_size_x as f32; + // let rotation = Quat::from_rotation_z(angle).to_array(); + // let rotation = [3usize, 0usize, 1usize, 2usize] + // .iter() + // .map(|i| rotation[*i]) + // .collect::>() + // .try_into() + // .unwrap(); - let gaussian = Gaussian { - position_visibility: position.into(), - rotation: Rotation { - rotation, - }, - scale_opacity: scale.into(), - spherical_harmonic: blue_sh, - }; - blue_gaussians.push(gaussian); - } - } + // let gaussian = Gaussian { + // position_visibility: position.into(), + // rotation: Rotation { + // rotation, + // }, + // scale_opacity: scale.into(), + // spherical_harmonic: blue_sh, + // }; + // blue_gaussians.push(gaussian); + // } + // } - commands.spawn(( - GaussianSplattingBundle { - cloud: gaussian_assets.add(GaussianCloud::from_gaussians(blue_gaussians)), - settings: GaussianCloudSettings { - visualize_bounding_box, - ..default() - }, - ..default() - }, - Name::new("gaussian_cloud_3dgs"), - )); + // let cloud = asset_server.load("office.ply"); + // commands.spawn(( + // GaussianSplattingBundle { + // cloud,//: gaussian_assets.add(GaussianCloud::from_gaussians(blue_gaussians)), + // ..default() + // }, + // Name::new("gaussian_cloud_3dgs"), + // )); let mut red_gaussians = Vec::new(); let mut red_sh = SphericalHarmonicCoefficients::default(); @@ -167,7 +164,6 @@ pub fn setup_surfel_compare( GaussianSplattingBundle { cloud: gaussian_assets.add(GaussianCloud::from_gaussians(red_gaussians)), settings: GaussianCloudSettings { - visualize_bounding_box, aabb: true, transform: Transform::from_translation(Vec3::new(spacing, spacing, 0.0)), gaussian_mode: GaussianMode::GaussianSurfel, @@ -179,7 +175,9 @@ pub fn setup_surfel_compare( )); commands.spawn(( - GaussianCamera, + GaussianCamera { + warmup: true, + }, Camera3dBundle { camera: Camera{ order: 0, @@ -198,25 +196,65 @@ pub fn setup_surfel_compare( }, )); - commands.spawn(( - GaussianCamera, - Camera3dBundle { - camera: Camera{ - order: 1, + // commands.spawn(( + // GaussianCamera, + // Camera3dBundle { + // camera: Camera{ + // order: 1, + // ..default() + // }, + // transform: Transform::from_translation(Vec3::new(0.0, 0.0, 40.0)), + // tonemapping: Tonemapping::None, + // ..default() + // }, + // CameraPosition { + // pos: UVec2::new(1, 0), + // }, + // PanOrbitCamera { + // allow_upside_down: true, + // ..default() + // }, + // )); +} + + +fn press_s_to_spawn_camera( + keys: Res>, + mut commands: Commands, + windows: Query<&Window>, +) { + if keys.just_pressed(KeyCode::KeyS) { + let window = windows.single(); + let size = window.physical_size() / UVec2::new(2, 1); + let pos = UVec2::new(1, 0); + + commands.spawn(( + GaussianCamera { + warmup: true, + }, + Camera3dBundle { + camera: Camera{ + order: 1, + viewport: Viewport { + physical_position: pos * size, + physical_size: size, + ..default() + }.into(), + ..default() + }, + transform: Transform::from_translation(Vec3::new(0.0, 0.0, 40.0)), + tonemapping: Tonemapping::None, ..default() }, - transform: Transform::from_translation(Vec3::new(0.0, 0.0, 40.0)), - tonemapping: Tonemapping::None, - ..default() - }, - CameraPosition { - pos: UVec2::new(1, 0), - }, - PanOrbitCamera { - allow_upside_down: true, - ..default() - }, - )); + CameraPosition { + pos, + }, + PanOrbitCamera { + allow_upside_down: true, + ..default() + }, + )); + } } @@ -228,13 +266,13 @@ struct CameraPosition { fn set_camera_viewports( windows: Query<&Window>, mut resize_events: EventReader, - mut query: Query<(&CameraPosition, &mut Camera), With>, + mut cameras: Query<(&CameraPosition, &mut Camera), With>, ) { for resize_event in resize_events.read() { let window = windows.get(resize_event.window).unwrap(); let size = window.physical_size() / UVec2::new(2, 1); - for (position, mut camera) in &mut query { + for (position, mut camera) in &mut cameras { camera.viewport = Some(Viewport { physical_position: position.pos * size, physical_size: size, diff --git a/src/camera.rs b/src/camera.rs index 446dcdb0..5814e929 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -1,6 +1,9 @@ use bevy::{ prelude::*, - render::extract_component::ExtractComponent + render::extract_component::{ + ExtractComponent, + ExtractComponentPlugin, + }, }; @@ -12,4 +15,31 @@ use bevy::{ ExtractComponent, Reflect, )] -pub struct GaussianCamera; +pub struct GaussianCamera { + pub warmup: bool, +} + + +#[derive(Default)] +pub struct GaussianCameraPlugin; + +impl Plugin for GaussianCameraPlugin { + fn build(&self, app: &mut App) { + app.add_plugins(ExtractComponentPlugin::::default()); + + app.add_systems(Update, apply_camera_warmup); + } +} + + +// TODO: remove camera warmup when extracted view dynamic uniform offset synchronization is fixed +fn apply_camera_warmup( + mut cameras: Query<&mut GaussianCamera>, +) { + for mut camera in cameras.iter_mut() { + if camera.warmup { + info!("camera warmup..."); + camera.warmup = false; + } + } +} diff --git a/src/io/ply.rs b/src/io/ply.rs index fcf00eb4..48eea211 100644 --- a/src/io/ply.rs +++ b/src/io/ply.rs @@ -99,5 +99,9 @@ pub fn parse_ply(mut reader: &mut dyn BufRead) -> Result, std::io: } } + // pad with empty gaussians to multiple of 32 + let pad = 32 - (cloud.len() % 32); + cloud.extend(std::iter::repeat(Gaussian::default()).take(pad)); + Ok(cloud) } diff --git a/src/lib.rs b/src/lib.rs index beba2182..1bd6bb98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,8 +17,6 @@ pub use material::spherical_harmonics::SphericalHarmonicCoefficients; use io::loader::GaussianCloudLoader; -use render::RenderPipelinePlugin; - pub mod camera; pub mod gaussian; pub mod io; @@ -61,7 +59,8 @@ impl Plugin for GaussianSplattingPlugin { app.register_type::(); app.add_plugins(( - RenderPipelinePlugin, + camera::GaussianCameraPlugin, + render::RenderPipelinePlugin, material::MaterialPlugin, query::QueryPlugin, )); diff --git a/src/material/spherical_harmonics.rs b/src/material/spherical_harmonics.rs index 61bdffad..37d63628 100644 --- a/src/material/spherical_harmonics.rs +++ b/src/material/spherical_harmonics.rs @@ -58,6 +58,9 @@ const SH_DEGREE: usize = 2; #[cfg(feature = "sh3")] const SH_DEGREE: usize = 3; +#[cfg(feature = "sh4")] +const SH_DEGREE: usize = 4; + pub const SH_CHANNELS: usize = 3; pub const SH_COEFF_COUNT_PER_CHANNEL: usize = num_sh_coefficients(SH_DEGREE); pub const SH_COEFF_COUNT: usize = (SH_COEFF_COUNT_PER_CHANNEL * SH_CHANNELS + 3) & !3; diff --git a/src/render/mod.rs b/src/render/mod.rs index 4866d22d..c0cbf8cc 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -19,7 +19,6 @@ use bevy::{ extract_component::{ ComponentUniforms, DynamicUniformIndex, - ExtractComponentPlugin, UniformComponentPlugin, }, globals::{ @@ -165,7 +164,6 @@ impl Plugin for RenderPipelinePlugin { Shader::from_wgsl ); - app.add_plugins(ExtractComponentPlugin::::default()); app.add_plugins(RenderAssetPlugin::::default()); app.add_plugins(UniformComponentPlugin::::default()); @@ -299,12 +297,17 @@ fn queue_gaussians( ( Entity, &ExtractedView, + &GaussianCamera, ), - With, >, msaa: Res, gaussian_splatting_bundles: Query, ) { + let warmup = views.iter().any(|(_, _, camera)| camera.warmup); + if warmup { + return; + } + // TODO: condition this system based on GaussianCloudBindGroup attachment if gaussian_cloud_uniform.buffer().is_none() { return; @@ -312,7 +315,7 @@ fn queue_gaussians( let draw_custom = transparent_3d_draw_functions.read().id::(); - for (view_entity, _view) in &mut views { + for (view_entity, _view, _) in &mut views { let Some(transparent_phase) = transparent_render_phases.get_mut(&view_entity) else { continue; }; @@ -947,7 +950,6 @@ pub struct SetGaussianViewBindGroup; impl RenderCommand

for SetGaussianViewBindGroup { type Param = (); type ViewQuery = ( - Read, Read, Read, ); @@ -957,7 +959,6 @@ impl RenderCommand

for SetGaussianViewBindGroup fn render<'w>( _item: &P, ( - _gaussian_camera, gaussian_view_bind_group, view_uniform, ): ROQueryItem< @@ -1036,6 +1037,8 @@ impl RenderCommand

for DrawGaussianInstanced { &bind_groups.cloud_bind_group, &[], ); + + // TODO: align dynamic offset to `min_storage_buffer_offset_alignment` pass.set_bind_group( 3, &bind_groups.sorted_bind_group, diff --git a/src/sort/mod.rs b/src/sort/mod.rs index 20267b5c..a227fa5b 100644 --- a/src/sort/mod.rs +++ b/src/sort/mod.rs @@ -137,6 +137,7 @@ impl Plugin for SortPlugin { app.init_asset::(); app.register_asset_reflect::(); + app.register_type::(); app.add_plugins(ExtractComponentPlugin::::default()); app.add_plugins(RenderAssetPlugin::::default()); @@ -173,11 +174,13 @@ pub struct SortTrigger { pub last_sort_time: Option, } +#[allow(clippy::type_complexity)] fn update_sort_trigger( mut commands: Commands, new_gaussian_cameras: Query< Entity, ( + With, With, Without, ), @@ -258,7 +261,13 @@ fn auto_insert_sorted_entries( ), Without> >, - gaussian_cameras: Query>, + gaussian_cameras: Query< + Entity, + ( + With, + With + ), + >, #[cfg(feature = "buffer_texture")] mut images: ResMut>, ) { @@ -300,7 +309,13 @@ fn update_sorted_entries_sizes( sorted_entries: Query< &Handle, >, - gaussian_cameras: Query>, + gaussian_cameras: Query< + Entity, + ( + With, + With + ), + >, #[cfg(feature = "buffer_texture")] mut images: ResMut>, ) { diff --git a/src/sort/rayon.rs b/src/sort/rayon.rs index 97c56242..3741ba75 100644 --- a/src/sort/rayon.rs +++ b/src/sort/rayon.rs @@ -53,8 +53,6 @@ pub fn rayon_sort( if !trigger.needs_sort { continue; } - trigger.needs_sort = false; - performed_sort = true; for ( gaussian_cloud_handle, @@ -65,6 +63,9 @@ pub fn rayon_sort( continue; } + trigger.needs_sort = false; + performed_sort = true; + if Some(LoadState::Loading) == asset_server.get_load_state(gaussian_cloud_handle) { continue; } diff --git a/src/sort/std.rs b/src/sort/std.rs index 8dd54f00..70d23522 100644 --- a/src/sort/std.rs +++ b/src/sort/std.rs @@ -53,8 +53,6 @@ pub fn std_sort( if !trigger.needs_sort { continue; } - trigger.needs_sort = false; - performed_sort = true; for ( gaussian_cloud_handle, @@ -65,6 +63,9 @@ pub fn std_sort( continue; } + trigger.needs_sort = false; + performed_sort = true; + if Some(LoadState::Loading) == asset_server.get_load_state(gaussian_cloud_handle) { continue; } diff --git a/tools/compare_aabb_obb.rs b/tools/compare_aabb_obb.rs index 0264b157..fc2111e1 100644 --- a/tools/compare_aabb_obb.rs +++ b/tools/compare_aabb_obb.rs @@ -98,7 +98,7 @@ pub fn setup_aabb_obb_compare( allow_upside_down: true, ..default() }, - GaussianCamera, + GaussianCamera::default(), )); } diff --git a/tools/surfel_plane.rs b/tools/surfel_plane.rs index 129a28a7..42d0bcdd 100644 --- a/tools/surfel_plane.rs +++ b/tools/surfel_plane.rs @@ -143,7 +143,7 @@ pub fn setup_surfel_compare( allow_upside_down: true, ..default() }, - GaussianCamera, + GaussianCamera::default(), )); } diff --git a/viewer/viewer.rs b/viewer/viewer.rs index 9649992b..90a2f33a 100644 --- a/viewer/viewer.rs +++ b/viewer/viewer.rs @@ -100,7 +100,7 @@ fn setup_gaussian_cloud( zoom_smoothness: 0.0, ..default() }, - GaussianCamera, + GaussianCamera::default(), )); }