Skip to content

Commit

Permalink
time based smoothing
Browse files Browse the repository at this point in the history
  • Loading branch information
aevyrie committed Jan 4, 2024
1 parent 387f0cc commit b9744f2
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 183 deletions.
24 changes: 2 additions & 22 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ keywords = ["editor, camera, bevy"]
bevy = { version = "0.12.1", default-features = false, features = [
"bevy_render",
"bevy_gizmos",
"bevy_asset",
"bevy_core_pipeline",
] }
bevy_picking_core = "0.17"

Expand All @@ -31,25 +33,3 @@ bevy_mod_picking = { version = "0.17", default-features = false, features = [
"backend_raycast",
] }
bevy_framepace = "0.14"

[patch.crates-io]
bevy = { path = "../bevy" }
bevy_a11y = { path = "../bevy/crates/bevy_a11y" }
bevy_app = { path = "../bevy/crates/bevy_app" }
bevy_asset = { path = "../bevy/crates/bevy_asset" }
bevy_core = { path = "../bevy/crates/bevy_core" }
bevy_core_pipeline = { path = "../bevy/crates/bevy_core_pipeline" }
bevy_ecs = { path = "../bevy/crates/bevy_ecs" }
bevy_gizmos = { path = "../bevy/crates/bevy_gizmos" }
bevy_hierarchy = { path = "../bevy/crates/bevy_hierarchy" }
bevy_input = { path = "../bevy/crates/bevy_input" }
bevy_math = { path = "../bevy/crates/bevy_math" }
bevy_reflect = { path = "../bevy/crates/bevy_reflect" }
bevy_render = { path = "../bevy/crates/bevy_render" }
bevy_sprite = { path = "../bevy/crates/bevy_sprite" }
bevy_text = { path = "../bevy/crates/bevy_text" }
bevy_transform = { path = "../bevy/crates/bevy_transform" }
bevy_ui = { path = "../bevy/crates/bevy_ui" }
bevy_utils = { path = "../bevy/crates/bevy_utils" }
bevy_window = { path = "../bevy/crates/bevy_window" }
bevy_winit = { path = "../bevy/crates/bevy_winit" }
Binary file not shown.
Binary file not shown.
198 changes: 53 additions & 145 deletions examples/demo.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,22 @@
use std::f32::consts::FRAC_PI_2;
use std::time::Duration;

use bevy::{
core_pipeline::{
bloom::BloomSettings,
experimental::taa::{TemporalAntiAliasBundle, TemporalAntiAliasPlugin},
fxaa::Fxaa,
tonemapping::Tonemapping,
},
pbr::{
ScreenSpaceAmbientOcclusionBundle, ScreenSpaceAmbientOcclusionQualityLevel,
ScreenSpaceAmbientOcclusionSettings, TransmittedShadowReceiver,
},
core_pipeline::{bloom::BloomSettings, tonemapping::Tonemapping},
prelude::*,
render::view::ColorGrading,
};
use bevy_editor_cam::{prelude::*, skybox::SkyboxCamConfig};

fn main() {
App::new()
.insert_resource(AmbientLight {
brightness: 0.0,
..default()
})
.insert_resource(bevy::winit::WinitSettings::desktop_app())
.add_plugins((
DefaultPlugins,
bevy_mod_picking::DefaultPickingPlugins,
TemporalAntiAliasPlugin,
bevy_framepace::FramepacePlugin,
EditorCamPlugin,
))
.add_systems(Startup, setup)
.add_systems(Update, (send_events, print_cam_location, update_ssao))
.add_systems(Update, send_events)
.run()
}

Expand All @@ -41,55 +26,10 @@ fn send_events(keyboard: Res<Input<KeyCode>>) {
}
}

fn print_cam_location(cam: Query<(&Camera, &Transform), Changed<Transform>>) {
for cam in cam.iter() {
// dbg!(cam.1.translation, cam.1.rotation);
}
}

fn update_ssao(
camera: Query<Entity, With<EditorCam>>,
mut commands: Commands,
keycode: Res<Input<KeyCode>>,
) {
let camera_entity = camera.single();

let mut commands = commands.entity(camera_entity);
if keycode.just_pressed(KeyCode::Key1) {
info!("Off");
commands.remove::<ScreenSpaceAmbientOcclusionSettings>();
}
if keycode.just_pressed(KeyCode::Key2) {
commands.insert(ScreenSpaceAmbientOcclusionSettings {
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::Low,
});
}
if keycode.just_pressed(KeyCode::Key3) {
commands.insert(ScreenSpaceAmbientOcclusionSettings {
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::Medium,
});
}
if keycode.just_pressed(KeyCode::Key4) {
commands.insert(ScreenSpaceAmbientOcclusionSettings {
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::High,
});
}
if keycode.just_pressed(KeyCode::Key5) {
commands.insert(ScreenSpaceAmbientOcclusionSettings {
quality_level: ScreenSpaceAmbientOcclusionQualityLevel::Ultra,
});
}
}

fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut meshes: ResMut<Assets<Mesh>>,
mut matls: ResMut<Assets<StandardMaterial>>,
) {
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(DirectionalLightBundle {
directional_light: DirectionalLight {
illuminance: 10_000.0,
illuminance: 5_000.0,
shadows_enabled: true,
// color: Color::rgb(1.0, 0.7, 0.2),
..default()
Expand All @@ -98,29 +38,8 @@ fn setup(
..default()
});

let mesh = meshes.add(shape::Circle::new(2.0).into());
let material = matls.add(StandardMaterial {
reflectance: 1.0,
perceptual_roughness: 1.0,
metallic: 1.0,
base_color: Color::rgba(1.0, 1.0, 1.0, 0.4),
diffuse_transmission: 1.0,
alpha_mode: AlphaMode::Multiply,
// double_sided: true,
// cull_mode: None,
..default()
});
commands.spawn((PbrBundle {
mesh: mesh.clone(),
material: material.clone(),
transform: Transform::from_xyz(0.0, -0.0, 0.0)
.with_rotation(Quat::from_axis_angle(Vec3::X, -FRAC_PI_2)),
..default()
},));

let scene = asset_server.load("models/FlightHelmet/FlightHelmet.gltf#Scene0");
// let scene = asset_server.load("models/scene/scene.gltf#Scene0");
let half_width = 0;
let half_width = 1;
let width = -half_width..=half_width;
let spacing = 2.0;
for x in width.clone() {
Expand All @@ -136,67 +55,56 @@ fn setup(
}
}

// let diffuse_map = asset_server.load("environment_maps/diffuse_rgb9e5_zstd.ktx2");
// let specular_map = asset_server.load("environment_maps/specular_rgb9e5_zstd.ktx2");

let diffuse_map = asset_server.load("environment_maps/pisa_diffuse_rgb9e5_zstd.ktx2");
let specular_map = asset_server.load("environment_maps/pisa_specular_rgb9e5_zstd.ktx2");
let diffuse_map = asset_server.load("environment_maps/diffuse_rgb9e5_zstd.ktx2");
let specular_map = asset_server.load("environment_maps/specular_rgb9e5_zstd.ktx2");

commands
.spawn((
Camera3dBundle {
transform: Transform::from_xyz(-2.1234279, 0.9718327, 0.013100326).with_rotation(
Quat::from_array([-0.03764842, -0.6783554, -0.034844566, 0.732941]),
),
camera: Camera {
hdr: true,
order: 1,
..default()
},
camera_3d: Camera3d {
clear_color: bevy::core_pipeline::clear_color::ClearColorConfig::None,
..default()
},
color_grading: ColorGrading {
exposure: 2.0,
..default()
},
tonemapping: Tonemapping::AcesFitted,
projection: Projection::Perspective(PerspectiveProjection {
near: 1e-1,
..Default::default()
}),
commands.spawn((
Camera3dBundle {
transform: Transform::from_xyz(-0.96555597, 0.3487206, 0.75903153).with_rotation(
Quat::from_array([-0.015417562, -0.45619124, -0.007905196, 0.8897131]),
),
camera: Camera {
hdr: true,
order: 1,
..default()
},
camera_3d: Camera3d {
clear_color: bevy::core_pipeline::clear_color::ClearColorConfig::None,
..default()
},
Fxaa::default(),
BloomSettings::default(),
EnvironmentMapLight {
diffuse_map: diffuse_map.clone(),
specular_map: specular_map.clone(),
tonemapping: Tonemapping::AcesFitted,
projection: Projection::Perspective(PerspectiveProjection {
near: 1e-1,
..Default::default()
}),
..default()
},
BloomSettings::default(),
EnvironmentMapLight {
diffuse_map: diffuse_map.clone(),
specular_map: specular_map.clone(),
},
EditorCam::new(
OrbitMode::Constrained(Vec3::Y),
// OrbitMode::Free,
Smoothness {
pan: Duration::from_millis(20),
orbit: Duration::from_millis(60),
zoom: Duration::from_millis(80),
},
EditorCam::new(
OrbitMode::Constrained(Vec3::Y),
// OrbitMode::Free,
Smoothness {
pan: 1,
orbit: 3,
zoom: 3,
Sensitivity::same(1.0),
Momentum {
// These should all be larger than the base smoothness
smoothness: Smoothness {
pan: Duration::from_millis(80),
orbit: Duration::from_millis(100),
zoom: Duration::from_millis(0),
},
Sensitivity::same(1.0),
Momentum {
// These should all be larger than the base smoothness
smoothness: Smoothness {
pan: 10,
orbit: 12,
zoom: 0,
},
pan: 150,
orbit: 100,
},
2.0,
),
SkyboxCamConfig::new(diffuse_map),
))
.insert(TemporalAntiAliasBundle::default())
.insert(ScreenSpaceAmbientOcclusionBundle::default());
pan: 150,
orbit: 100,
},
2.0,
),
SkyboxCamConfig::new(diffuse_map),
));
}
47 changes: 39 additions & 8 deletions src/cam_component.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
use std::{
collections::VecDeque,
f32::consts::{FRAC_PI_2, PI},
sync::{OnceLock, RwLock},
time::Duration,
};

use bevy::{
ecs::{component::Component, event::EventWriter, system::Query},
diagnostic::{DiagnosticsStore, FrameTimeDiagnosticsPlugin},
ecs::{
component::Component,
event::EventWriter,
system::{Query, Res},
},
gizmos::gizmos::Gizmos,
log::error,
math::{DVec2, DVec3, Quat, Vec2, Vec3},
Expand Down Expand Up @@ -395,9 +402,9 @@ pub enum OrbitMode {

#[derive(Debug, Clone, Copy, Reflect)]
pub struct Smoothness {
pub pan: u8,
pub orbit: u8,
pub zoom: u8,
pub pan: Duration,
pub orbit: Duration,
pub zoom: Duration,
}

#[derive(Debug, Clone, Copy, Reflect)]
Expand Down Expand Up @@ -578,6 +585,26 @@ impl From<&MotionInputs> for MotionKind {
}
}

static FPS: OnceLock<RwLock<f32>> = OnceLock::new();

pub(crate) fn update_fps(diagnostics: Res<DiagnosticsStore>) {
let Ok(mut fps_lock) = FPS.get_or_init(RwLock::default).try_write() else {
return;
};

*fps_lock = diagnostics
.get(FrameTimeDiagnosticsPlugin::FPS)
.and_then(|diag| diag.average())
.unwrap_or(60.0) as f32;
}

fn read_fps() -> f32 {
FPS.get()
.and_then(|f| f.try_read().ok())
.map(|d| *d)
.unwrap_or(60.0)
}

#[derive(Debug, Clone, Reflect)]
pub enum MotionInputs {
/// The camera can orbit and zoom
Expand Down Expand Up @@ -608,7 +635,8 @@ impl MotionInputs {

pub fn orbit_velocity(&self, smoothness: Smoothness) -> DVec2 {
if let Self::OrbitZoom { movement, .. } = self {
let n_elements = movement.len().min(smoothness.orbit as usize + 1);
let smoothness = (smoothness.orbit.as_secs_f32() * read_fps()) as usize;
let n_elements = movement.len().min(smoothness + 1);
movement.iter().take(n_elements).sum::<Vec2>().as_dvec2() / n_elements as f64
} else {
DVec2::ZERO
Expand All @@ -617,7 +645,8 @@ impl MotionInputs {

pub fn pan_velocity(&self, smoothness: Smoothness) -> DVec2 {
if let Self::PanZoom { movement, .. } = self {
let n_elements = movement.len().min(smoothness.pan as usize + 1);
let smoothness = (smoothness.pan.as_secs_f32() * read_fps()) as usize;
let n_elements = movement.len().min(smoothness + 1);
movement.iter().take(n_elements).sum::<Vec2>().as_dvec2() / n_elements as f64
} else {
DVec2::ZERO
Expand All @@ -642,7 +671,8 @@ impl MotionInputs {

pub fn zoom_velocity(&self, smoothness: Smoothness) -> f64 {
let zoom_inputs = self.zoom_inputs();
let n_elements = zoom_inputs.len().min(smoothness.zoom as usize + 1);
let smoothness = (smoothness.zoom.as_secs_f32() * read_fps()) as usize;
let n_elements = zoom_inputs.len().min(smoothness + 1);
let velocity = zoom_inputs.iter().take(n_elements).sum::<f32>() as f64 / n_elements as f64;
if !velocity.is_finite() {
0.0
Expand All @@ -657,7 +687,8 @@ impl MotionInputs {
MotionInputs::PanZoom { zoom_inputs, .. } => zoom_inputs,
MotionInputs::Zoom { zoom_inputs } => zoom_inputs,
};
let n_elements = zoom_inputs.len().min(smoothness.zoom as usize + 1);
let smoothness = (smoothness.zoom.as_secs_f32() * read_fps()) as usize;
let n_elements = zoom_inputs.len().min(smoothness + 1);
let velocity = zoom_inputs
.iter()
.take(n_elements)
Expand Down
10 changes: 2 additions & 8 deletions src/dolly_zoom.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
use std::time::Duration;

use bevy::{
app::prelude::*, ecs::prelude::*, math::Mat4, render::prelude::*, transform::prelude::*,
utils::Instant,
};
use bevy::{app::prelude::*, ecs::prelude::*, render::prelude::*, transform::prelude::*};

use crate::cam_component::EditorCam;

Expand Down Expand Up @@ -58,8 +53,7 @@ impl DollyZoom {
}
}
Projection::Orthographic(_) => {
todo!("calculate fallback depth based on scale and desired fov");
todo!("calcualte new dist to target = max dolly zoom - fallback depth");
todo!("calculate fallback depth based on scale and desired fov, calcualte new dist to target = max dolly zoom - fallback depth");
// dolly.dist_to_target = dolly.maximum_dolly_pull - ;
// *proj = Projection::Perspective(PerspectiveProjection {
// near: dolly.near,
Expand Down
Loading

0 comments on commit b9744f2

Please sign in to comment.