mirror of
https://github.com/eliasstepanik/voxel-simulation.git
synced 2026-01-11 13:58:30 +00:00
Merge branch 'codex/erweitere-voxel-bearbeitungsfunktionen'
This commit is contained in:
commit
93dcdb3379
@ -27,6 +27,7 @@ tools.
|
|||||||
- **F3** – Toggle world grid
|
- **F3** – Toggle world grid
|
||||||
- **Q** – Insert a red voxel at the crosshair
|
- **Q** – Insert a red voxel at the crosshair
|
||||||
- **F4** – Save the current octree to `octree.bin`
|
- **F4** – Save the current octree to `octree.bin`
|
||||||
|
- **F5** – Toggle sphere editing mode
|
||||||
- **Escape** – Quit the application
|
- **Escape** – Quit the application
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|||||||
@ -167,6 +167,54 @@ impl SparseVoxelOctree {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Insert a sphere of voxels with the given radius (in voxels) and center.
|
||||||
|
pub fn insert_sphere(&mut self, center: Vec3, radius: i32, voxel: Voxel) {
|
||||||
|
let step = self.get_spacing_at_depth(self.max_depth);
|
||||||
|
let r2 = radius * radius;
|
||||||
|
|
||||||
|
for x in -radius..=radius {
|
||||||
|
let dx2 = x * x;
|
||||||
|
for y in -radius..=radius {
|
||||||
|
let dy2 = y * y;
|
||||||
|
for z in -radius..=radius {
|
||||||
|
let dz2 = z * z;
|
||||||
|
if dx2 + dy2 + dz2 <= r2 {
|
||||||
|
let pos = Vec3::new(
|
||||||
|
center.x + x as f32 * step,
|
||||||
|
center.y + y as f32 * step,
|
||||||
|
center.z + z as f32 * step,
|
||||||
|
);
|
||||||
|
self.insert(pos, voxel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove all voxels inside a sphere with the given radius (in voxels).
|
||||||
|
pub fn remove_sphere(&mut self, center: Vec3, radius: i32) {
|
||||||
|
let step = self.get_spacing_at_depth(self.max_depth);
|
||||||
|
let r2 = radius * radius;
|
||||||
|
|
||||||
|
for x in -radius..=radius {
|
||||||
|
let dx2 = x * x;
|
||||||
|
for y in -radius..=radius {
|
||||||
|
let dy2 = y * y;
|
||||||
|
for z in -radius..=radius {
|
||||||
|
let dz2 = z * z;
|
||||||
|
if dx2 + dy2 + dz2 <= r2 {
|
||||||
|
let pos = Vec3::new(
|
||||||
|
center.x + x as f32 * step,
|
||||||
|
center.y + y as f32 * step,
|
||||||
|
center.z + z as f32 * step,
|
||||||
|
);
|
||||||
|
self.remove(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn remove_recursive(node: &mut OctreeNode, x: f32, y: f32, z: f32, depth: u32) -> bool {
|
fn remove_recursive(node: &mut OctreeNode, x: f32, y: f32, z: f32, depth: u32) -> bool {
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
if node.voxel.is_some() {
|
if node.voxel.is_some() {
|
||||||
|
|||||||
@ -2,10 +2,12 @@
|
|||||||
use bevy::app::{App, Plugin, PreUpdate, Startup};
|
use bevy::app::{App, Plugin, PreUpdate, Startup};
|
||||||
use bevy::ecs::schedule::IntoScheduleConfigs;
|
use bevy::ecs::schedule::IntoScheduleConfigs;
|
||||||
use bevy::prelude::Update;
|
use bevy::prelude::Update;
|
||||||
|
use crate::plugins::input::systems::voxels::VoxelEditMode;
|
||||||
|
|
||||||
pub struct InputPlugin;
|
pub struct InputPlugin;
|
||||||
impl Plugin for InputPlugin {
|
impl Plugin for InputPlugin {
|
||||||
fn build(&self, _app: &mut App) {
|
fn build(&self, _app: &mut App) {
|
||||||
|
_app.init_resource::<VoxelEditMode>();
|
||||||
_app.add_systems(
|
_app.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
|
|||||||
@ -4,6 +4,20 @@ use crate::plugins::environment::systems::voxels::structure::*;
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
#[derive(Resource, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum VoxelEditMode {
|
||||||
|
Single,
|
||||||
|
Sphere,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for VoxelEditMode {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Single
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const EDIT_SPHERE_RADIUS: i32 = 8;
|
||||||
|
|
||||||
///TODO
|
///TODO
|
||||||
pub fn voxel_system(
|
pub fn voxel_system(
|
||||||
keyboard_input: Res<ButtonInput<KeyCode>>,
|
keyboard_input: Res<ButtonInput<KeyCode>>,
|
||||||
@ -12,6 +26,7 @@ pub fn voxel_system(
|
|||||||
|
|
||||||
mut query: Query<(&mut Transform, &mut CameraController)>,
|
mut query: Query<(&mut Transform, &mut CameraController)>,
|
||||||
mut windows: Query<&mut Window>,
|
mut windows: Query<&mut Window>,
|
||||||
|
mut edit_mode: ResMut<VoxelEditMode>,
|
||||||
) {
|
) {
|
||||||
let Ok(mut window) = windows.get_single_mut() else {
|
let Ok(mut window) = windows.get_single_mut() else {
|
||||||
return;
|
return;
|
||||||
@ -47,22 +62,13 @@ pub fn voxel_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* if keyboard_input.just_pressed(KeyCode::F5){
|
|
||||||
let path = Path::new("octree.bin");
|
|
||||||
if path.exists() {
|
|
||||||
let path = Path::new("octree.bin");
|
|
||||||
|
|
||||||
let mut octree = if path.exists() {
|
if keyboard_input.just_pressed(KeyCode::F5) {
|
||||||
match SparseVoxelOctree::load_from_file(path) {
|
*edit_mode = match *edit_mode {
|
||||||
Ok(tree) => tree,
|
VoxelEditMode::Single => VoxelEditMode::Sphere,
|
||||||
Err(err) => {
|
VoxelEditMode::Sphere => VoxelEditMode::Single,
|
||||||
error!("failed to load octree: {err}");
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// =======================
|
// =======================
|
||||||
// 6) Building
|
// 6) Building
|
||||||
@ -85,30 +91,39 @@ pub fn voxel_system(
|
|||||||
|
|
||||||
for mut octree in octree_query.iter_mut() {
|
for mut octree in octree_query.iter_mut() {
|
||||||
if let Some((hit_x, hit_y, hit_z, depth, normal)) = octree.raycast(&ray) {
|
if let Some((hit_x, hit_y, hit_z, depth, normal)) = octree.raycast(&ray) {
|
||||||
|
match *edit_mode {
|
||||||
|
VoxelEditMode::Single => {
|
||||||
if mouse_button_input.just_pressed(MouseButton::Right) {
|
if mouse_button_input.just_pressed(MouseButton::Right) {
|
||||||
let voxel_size = octree.get_spacing_at_depth(depth);
|
let voxel_size = octree.get_spacing_at_depth(depth);
|
||||||
let hit_position = Vec3::new(hit_x as f32, hit_y as f32, hit_z as f32);
|
let hit_position = Vec3::new(hit_x as f32, hit_y as f32, hit_z as f32);
|
||||||
let epsilon = voxel_size * 0.1; // Adjust this value as needed (e.g., 0.1 times the voxel size)
|
let epsilon = voxel_size * 0.1;
|
||||||
|
let offset_position = hit_position - (normal * Vec3::splat(epsilon));
|
||||||
// Offset position by epsilon in the direction of the normal
|
|
||||||
let offset_position = hit_position
|
|
||||||
- (normal * Vec3::new(epsilon as f32, epsilon as f32, epsilon as f32));
|
|
||||||
|
|
||||||
// Remove the voxel
|
|
||||||
octree.remove(offset_position);
|
octree.remove(offset_position);
|
||||||
} else if mouse_button_input.just_pressed(MouseButton::Left) {
|
} else if mouse_button_input.just_pressed(MouseButton::Left) {
|
||||||
let voxel_size = octree.get_spacing_at_depth(depth);
|
let voxel_size = octree.get_spacing_at_depth(depth);
|
||||||
let hit_position = Vec3::new(hit_x as f32, hit_y as f32, hit_z as f32);
|
let hit_position = Vec3::new(hit_x as f32, hit_y as f32, hit_z as f32);
|
||||||
let epsilon = voxel_size * 0.1; // Adjust this value as needed (e.g., 0.1 times the voxel size)
|
let epsilon = voxel_size * 0.1;
|
||||||
|
let offset_position = hit_position + (normal * Vec3::splat(epsilon));
|
||||||
// Offset position by epsilon in the direction of the normal
|
|
||||||
let offset_position = hit_position
|
|
||||||
+ (normal * Vec3::new(epsilon as f32, epsilon as f32, epsilon as f32));
|
|
||||||
|
|
||||||
// Insert the new voxel
|
|
||||||
octree.insert(offset_position, Voxel::random_sides());
|
octree.insert(offset_position, Voxel::random_sides());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
VoxelEditMode::Sphere => {
|
||||||
|
if mouse_button_input.just_pressed(MouseButton::Right) {
|
||||||
|
let voxel_size = octree.get_spacing_at_depth(depth);
|
||||||
|
let hit_position = Vec3::new(hit_x as f32, hit_y as f32, hit_z as f32);
|
||||||
|
let epsilon = voxel_size * 0.1;
|
||||||
|
let offset = hit_position - normal * Vec3::splat(epsilon);
|
||||||
|
octree.remove_sphere(offset, EDIT_SPHERE_RADIUS);
|
||||||
|
} else if mouse_button_input.just_pressed(MouseButton::Left) {
|
||||||
|
let voxel_size = octree.get_spacing_at_depth(depth);
|
||||||
|
let hit_position = Vec3::new(hit_x as f32, hit_y as f32, hit_z as f32);
|
||||||
|
let epsilon = voxel_size * 0.1;
|
||||||
|
let offset = hit_position + normal * Vec3::splat(epsilon);
|
||||||
|
octree.insert_sphere(offset, EDIT_SPHERE_RADIUS, Voxel::grass_block());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user