camera movement with drag + scroll zoom

This commit is contained in:
Arkitu 2025-05-23 22:18:11 +02:00
parent c6e8a3e232
commit 4a401182fb
7 changed files with 68 additions and 49 deletions

10
Cargo.lock generated
View File

@ -352,6 +352,7 @@ version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eaad7fe854258047680c51c3cacb804468553c04241912f6254c841c67c0198" checksum = "2eaad7fe854258047680c51c3cacb804468553c04241912f6254c841c67c0198"
dependencies = [ dependencies = [
"bevy_dylib",
"bevy_internal", "bevy_internal",
] ]
@ -583,6 +584,15 @@ dependencies = [
"sysinfo", "sysinfo",
] ]
[[package]]
name = "bevy_dylib"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "381b2a0773cfe9d27256fba1e5005a14968b34f751c09397ee4e278f0fb235db"
dependencies = [
"bevy_internal",
]
[[package]] [[package]]
name = "bevy_ecs" name = "bevy_ecs"
version = "0.15.3" version = "0.15.3"

View File

@ -12,6 +12,9 @@ crate-type = ["cdylib"]
path = "src/lib.rs" path = "src/lib.rs"
name = "forestiles" name = "forestiles"
[features]
debug = ["dep:bevy_editor_pls"]
[dependencies] [dependencies]
bevy = { version = "0.15", default-features = false, features = [ bevy = { version = "0.15", default-features = false, features = [
"android-native-activity", "android-native-activity",
@ -33,6 +36,7 @@ bevy = { version = "0.15", default-features = false, features = [
"png", "png",
"tonemapping_luts", "tonemapping_luts",
"bevy_pbr", "bevy_pbr",
"dynamic_linking",
] } ] }
#bevy-inspector-egui = { version = "0.28", default-features = false, features = [ #bevy-inspector-egui = { version = "0.28", default-features = false, features = [
# "bevy_image", # "bevy_image",
@ -44,7 +48,7 @@ log = "0.4"
rand = { version = "0.8", features = ["small_rng"] } rand = { version = "0.8", features = ["small_rng"] }
voronoice = "0.2" voronoice = "0.2"
noise = "0.9" noise = "0.9"
bevy_editor_pls = { version = "0.11", git = "https://github.com/jakobhellermann/bevy_editor_pls.git" } bevy_editor_pls = { version = "0.11", git = "https://github.com/jakobhellermann/bevy_editor_pls.git", optional = true }
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]
console_error_panic_hook = "0.1.6" console_error_panic_hook = "0.1.6"
@ -78,4 +82,4 @@ build_targets = ["aarch64-linux-android", "armv7-linux-androideabi"]
target_sdk_version = 31 target_sdk_version = 31
[package.metadata.android.application] [package.metadata.android.application]
label = "Forestiles" label = "Forestiles"

View File

@ -1,4 +1,4 @@
use bevy::prelude::*; use bevy::{prelude::*, render::camera::ScalingMode};
pub struct Plugin; pub struct Plugin;
impl bevy::prelude::Plugin for Plugin { impl bevy::prelude::Plugin for Plugin {
@ -11,26 +11,22 @@ impl bevy::prelude::Plugin for Plugin {
pub struct CameraMarker; pub struct CameraMarker;
fn setup(mut cmds: Commands, window: Query<&Window>) { fn setup(mut cmds: Commands, window: Query<&Window>) {
let zoom = 2. / window.single().width().min(window.single().height());
cmds.spawn(( cmds.spawn((
CameraMarker, CameraMarker,
Camera3d { Camera3d {
..Default::default() ..Default::default()
}, },
Transform::from_scale(Vec3::new(zoom, zoom, zoom)) PerspectiveProjection::default(),
.with_translation(Vec3::new(0., -1., 1.)) Transform::from_translation(Vec3::new(0., -1., 1.))
.looking_to(Vec3::new(0., 1., -1.), Vec3::Y), .looking_to(Vec3::new(0., 1., -1.), Vec3::Y),
)); ));
cmds.spawn( cmds.spawn((
DirectionalLightBundle { DirectionalLight {
directional_light: DirectionalLight { color: Color::WHITE,
color: Color::WHITE, illuminance: 17000.,
illuminance: 17000., //shadows_enabled: true,
//shadows_enabled: true,
..Default::default()
},
transform: Transform::default().looking_to(Vec3::new(1., -1., -1.), Vec3::ZERO),
..Default::default() ..Default::default()
} },
); Transform::default().looking_to(Vec3::new(1., -1., -1.), Vec3::ZERO),
));
} }

View File

@ -3,7 +3,6 @@ use bevy::{
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}, diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
prelude::*, prelude::*,
}; };
//use bevy_inspector_egui::quick::WorldInspectorPlugin;
pub mod camera; pub mod camera;
pub mod map; pub mod map;
@ -16,8 +15,8 @@ pub fn main() {
.add_plugins(( .add_plugins((
DefaultPlugins, DefaultPlugins,
// bevy_inspector_egui::DefaultInspectorConfigPlugin, // bevy_inspector_egui::DefaultInspectorConfigPlugin,
//bevy_editor_pls::EditorPlugin::default(), // for debug #[cfg(feature = "debug")]
// WorldInspectorPlugin::default(), bevy_editor_pls::EditorPlugin::default(), // for debug
camera::Plugin, camera::Plugin,
map::Plugin, map::Plugin,
ui::Plugin, ui::Plugin,

View File

@ -31,8 +31,8 @@ impl bevy::prelude::Plugin for Plugin {
pub const HEIGHT: f32 = 2.; pub const HEIGHT: f32 = 2.;
pub const WIDTH: f32 = 2.; pub const WIDTH: f32 = 2.;
pub const REAL_HEIGHT: f32 = 500.; pub const REAL_HEIGHT: f32 = 2000.;
pub const REAL_WIDTH: f32 = 500.; pub const REAL_WIDTH: f32 = 2000.;
pub const CELL_AREA: f32 = REAL_HEIGHT * REAL_WIDTH / SIZE as f32; pub const CELL_AREA: f32 = REAL_HEIGHT * REAL_WIDTH / SIZE as f32;
pub const SIZE: usize = 10000; pub const SIZE: usize = 10000;
@ -80,23 +80,18 @@ fn setup(
for i in 0..SIZE { for i in 0..SIZE {
let c = voronoi.cell(i); let c = voronoi.cell(i);
let site = c.site_position(); let site = c.site_position();
let z = ( let z = get_altitude(&z_noise, &[site.x as f32, site.y as f32]);
0.3 // Arbitrary value info!(z);
+ ((z_noise.get([site.x, site.y])+1.)/2.) // Noise + [0; 1]
- ((site.x.powi(2)+site.y.powi(2)).sqrt()*0.5)
// Distance - [0; sqrt(2)] * 0.5
)
.clamp(0., 1.);
let _m = ( let _m = (
(moisture_noise.get([site.x, site.y]) + 1.) / 2. (moisture_noise.get([site.x, site.y]) + 1.) / 2.
// Noise + [0; 1] // Noise + [0; 1]
) )
.clamp(0., 1.) as f32; .clamp(0., 1.) as f32;
let k = if z <= 0.5 { let k = if z <= 0. {
CellKind::Sea CellKind::Sea
} else if z <= 0.52 { } else if z <= 0.04 {
CellKind::Beach CellKind::Beach
} else if z < 0.8 { } else if z < 0.6 {
CellKind::Dirt CellKind::Dirt
} else { } else {
CellKind::Stone CellKind::Stone
@ -104,7 +99,6 @@ fn setup(
cells.push(Cell { cells.push(Cell {
kind: k, kind: k,
voronoi_id: i, voronoi_id: i,
altitude: (z * 255.) as u8,
vertices: vec![], vertices: vec![],
}); });
} }
@ -113,14 +107,15 @@ fn setup(
let mut indices = Vec::new(); let mut indices = Vec::new();
let mut normals = Vec::new(); let mut normals = Vec::new();
for (c, cd) in voronoi for (c, cd) in voronoi.iter_cells().zip(cells.iter_mut()) {
.iter_cells()
.zip(cells.iter_mut())
{
let vs = c.iter_vertices().collect::<Vec<_>>(); let vs = c.iter_vertices().collect::<Vec<_>>();
let i = poss.len(); let i = poss.len();
for v in vs.iter() { for v in vs.iter() {
poss.push(Vec3::new(v.x as f32, v.y as f32, (cd.altitude as f32)/255./4.)); poss.push(Vec3::new(
v.x as f32,
v.y as f32,
(get_altitude(&z_noise, &[v.x as f32, v.y as f32]) / 1.),
));
normals.push(Vec3::new(0., 0., 1.)); normals.push(Vec3::new(0., 0., 1.));
} }
for v in 1..(vs.len() - 1) { for v in 1..(vs.len() - 1) {
@ -198,3 +193,16 @@ fn update_map_mesh(
needs_update.0 = false; needs_update.0 = false;
} }
} }
/// Between 0 and 1
fn get_altitude(z_noise: &Fbm<Perlin>, pos: &[f32; 2]) -> f32 {
let z_noise = ((z_noise.get([pos[0] as f64, pos[1] as f64]) as f32) + 1.) / 2.; // Noise [0; 1]
(
-0.2// Arbitrary value
+ (z_noise.exp() / 1f32.exp())
// Noise + [0; 1]
// - ((pos[0].powi(2)+pos[1].powi(2)).sqrt()*0.3)
// Distance - [0; sqrt(2)] * 0.5
)
// .clamp(-1., 1.)
}

View File

@ -36,7 +36,6 @@ impl CellKind {
pub struct Cell { pub struct Cell {
pub kind: CellKind, pub kind: CellKind,
pub voronoi_id: usize, pub voronoi_id: usize,
pub altitude: u8,
pub vertices: Vec<usize>, pub vertices: Vec<usize>,
} }
impl Cell { impl Cell {

View File

@ -9,8 +9,8 @@ use bevy::{
}; };
use mevy::*; use mevy::*;
use crate::map::{AnimalKind, CellKind};
use crate::camera::CameraMarker; use crate::camera::CameraMarker;
use crate::map::{AnimalKind, CellKind};
// #77767b // #77767b
const TABBAR_COLOR: Color = Color::srgb(119. / 255., 118. / 255., 123. / 255.); const TABBAR_COLOR: Color = Color::srgb(119. / 255., 118. / 255., 123. / 255.);
@ -65,7 +65,7 @@ fn setup(mut world: Commands, asset_server: Res<AssetServer>) {
.observe(| .observe(|
trigger: Trigger<Pointer<Drag>>, trigger: Trigger<Pointer<Drag>>,
mut ptrs: Query<&mut PointersDragging>, mut ptrs: Query<&mut PointersDragging>,
mut cam: Query<&mut Transform, With<CameraMarker>>, mut cam: Query<(&mut Transform, &PerspectiveProjection), With<CameraMarker>>,
| { | {
if trigger.button == PointerButton::Primary { if trigger.button == PointerButton::Primary {
let mut ptrs = ptrs.single_mut(); let mut ptrs = ptrs.single_mut();
@ -81,12 +81,12 @@ fn setup(mut world: Commands, asset_server: Res<AssetServer>) {
let new_d_to_midpoint = ptrs.0.values().fold(0., |acc, pos| acc + (new_midpoint-pos).norm()); let new_d_to_midpoint = ptrs.0.values().fold(0., |acc, pos| acc + (new_midpoint-pos).norm());
// move camera // move camera
cam.translation.x -= (new_midpoint.x - old_midpoint.x)*cam.scale.x; cam.0.translation.x -= (new_midpoint.x - old_midpoint.x)*cam.1.fov*0.001;
cam.translation.y += (new_midpoint.y - old_midpoint.y)*cam.scale.y; cam.0.translation.y += (new_midpoint.y - old_midpoint.y)*cam.1.fov*0.001;
if ptrs.0.len() > 1 { // if ptrs.0.len() > 1 {
cam.scale *= old_d_to_midpoint/new_d_to_midpoint; // cam.scale *= old_d_to_midpoint/new_d_to_midpoint;
} // }
} }
} }
); );
@ -199,9 +199,12 @@ fn zoom_with_scroll(
let window = window.single(); let window = window.single();
let mut cam = cam.single_mut(); let mut cam = cam.single_mut();
for ev in ev_scroll.read() { for ev in ev_scroll.read() {
let scale = (cam.scale.x - (ev.y * 0.1 / window.width().min(window.height()))) dbg!(ev.y);
.clamp(0.0001, 2. / window.width().min(window.height())); let forward = cam.forward();
cam.scale = Vec3::new(scale, scale, scale); cam.translation += forward * (ev.y * 0.1);
// cam.fov = cam.fov + (ev.y * 0.1);
// let scale = (cam.scale.x - (ev.y * 0.1 / window.width().min(window.height())))
// .clamp(0.0001, 2. / window.width().min(window.height()));
} }
} }
} }