basic/
basic.rs

1// examples/basic.rs
2use bevy::input::mouse::MouseMotion;
3use bevy::prelude::*;
4use bevy_sculpter::prelude::*;
5use chunky_bevy::prelude::*;
6
7fn main() {
8    App::new()
9        .add_plugins(DefaultPlugins)
10        .add_plugins(SurfaceNetsPlugin)
11        .insert_resource(DensityFieldMeshSize(vec3(10., 10., 10.)))
12        .add_systems(Startup, setup)
13        .add_systems(Update, fly_camera)
14        .run();
15}
16
17#[derive(Component)]
18struct FlyCam {
19    speed: f32,
20    sensitivity: f32,
21    pitch: f32,
22    yaw: f32,
23}
24
25impl Default for FlyCam {
26    fn default() -> Self {
27        Self {
28            speed: 20.0,
29            sensitivity: 0.003,
30            pitch: 0.0,
31            yaw: 0.0,
32        }
33    }
34}
35
36fn setup(mut commands: Commands) {
37    // Spawn a 3x3x3 grid of chunks with density fields
38    for x in -1..=1 {
39        for y in -1..=1 {
40            for z in -1..=1 {
41                let mut field = DensityField::new();
42
43                // Create a sphere that spans multiple chunks
44                let local_center = vec3(16.0, 16.0, 16.0);
45                let global_offset = vec3(x as f32, y as f32, z as f32) * 32.0;
46                let sphere_center = vec3(0.0, 0.0, 0.0);
47                let local_sphere_center = sphere_center - global_offset + local_center;
48
49                bevy_sculpter::helpers::fill_sphere(&mut field, local_sphere_center, 20.0);
50                commands.spawn((Chunk, ChunkPos(ivec3(x, y, z)), field, GenerateMesh));
51            }
52        }
53    }
54
55    // Camera with fly controls
56    commands.spawn((
57        Camera3d::default(),
58        Transform::from_xyz(30.0, 30.0, 30.0).looking_at(Vec3::ZERO, Vec3::Y),
59        FlyCam::default(),
60    ));
61
62    // Light
63    commands.spawn((
64        DirectionalLight {
65            illuminance: 10000.0,
66            shadows_enabled: true,
67            ..default()
68        },
69        Transform::from_xyz(10.0, 20.0, 10.0).looking_at(Vec3::ZERO, Vec3::Y),
70    ));
71}
72
73fn fly_camera(
74    time: Res<Time>,
75    keyboard: Res<ButtonInput<KeyCode>>,
76    mouse_buttons: Res<ButtonInput<MouseButton>>,
77    mut mouse_motion: MessageReader<MouseMotion>,
78    mut query: Query<(&mut Transform, &mut FlyCam)>,
79) {
80    let Ok((mut transform, mut fly_cam)) = query.single_mut() else {
81        return;
82    };
83
84    // Mouse look (only when right mouse button is held)
85    if mouse_buttons.pressed(MouseButton::Left) {
86        for motion in mouse_motion.read() {
87            fly_cam.yaw -= motion.delta.x * fly_cam.sensitivity;
88            fly_cam.pitch -= motion.delta.y * fly_cam.sensitivity;
89            fly_cam.pitch = fly_cam.pitch.clamp(-1.5, 1.5);
90        }
91
92        transform.rotation = Quat::from_euler(EulerRot::YXZ, fly_cam.yaw, fly_cam.pitch, 0.0);
93    } else {
94        mouse_motion.clear();
95    }
96
97    // Keyboard movement
98    let mut velocity = Vec3::ZERO;
99    let forward = transform.forward();
100    let right = transform.right();
101
102    if keyboard.pressed(KeyCode::KeyW) {
103        velocity += *forward;
104    }
105    if keyboard.pressed(KeyCode::KeyS) {
106        velocity -= *forward;
107    }
108    if keyboard.pressed(KeyCode::KeyA) {
109        velocity -= *right;
110    }
111    if keyboard.pressed(KeyCode::KeyD) {
112        velocity += *right;
113    }
114    if keyboard.pressed(KeyCode::Space) {
115        velocity += Vec3::Y;
116    }
117    if keyboard.pressed(KeyCode::ShiftLeft) {
118        velocity -= Vec3::Y;
119    }
120
121    // Speed boost with Ctrl
122    let speed = if keyboard.pressed(KeyCode::ControlLeft) {
123        fly_cam.speed * 3.0
124    } else {
125        fly_cam.speed
126    };
127
128    if velocity.length_squared() > 0.0 {
129        velocity = velocity.normalize() * speed * time.delta_secs();
130        transform.translation += velocity;
131    }
132}