From 496c5bf673b6415414cd37603063b576518eaaaa Mon Sep 17 00:00:00 2001 From: Elias Stepanik <40958815+eliasstepanik@users.noreply.github.com> Date: Sat, 14 Jun 2025 01:23:37 +0200 Subject: [PATCH] Remove voxel color field --- .../environment/systems/voxel_system.rs | 102 +++++------------ .../environment/systems/voxels/atlas.rs | 2 +- .../environment/systems/voxels/debug.rs | 16 +-- .../environment/systems/voxels/octree.rs | 106 +++++++++--------- .../environment/systems/voxels/structure.rs | 35 +----- client/src/plugins/input/systems/voxels.rs | 64 +++++------ 6 files changed, 128 insertions(+), 197 deletions(-) diff --git a/client/src/plugins/environment/systems/voxel_system.rs b/client/src/plugins/environment/systems/voxel_system.rs index 52683dd..117b284 100644 --- a/client/src/plugins/environment/systems/voxel_system.rs +++ b/client/src/plugins/environment/systems/voxel_system.rs @@ -1,25 +1,21 @@ -use std::path::Path; -use rayon::prelude::*; use crate::plugins::big_space::big_space_plugin::RootGrid; use crate::plugins::environment::systems::voxels::structure::*; +use rayon::prelude::*; +use std::path::Path; use bevy::prelude::*; use bevy::render::mesh::*; use noise::{NoiseFn, Perlin}; -use rand::{thread_rng, Rng}; +use rand::{Rng, thread_rng}; -pub fn setup( - mut commands: Commands, - root: Res, -) { +pub fn setup(mut commands: Commands, root: Res) { // Octree parameters - let unit_size = 1.0_f32; + let unit_size = 1.0_f32; let octree_base_size = 64.0 * unit_size; - let octree_depth = 10; + let octree_depth = 10; let path = Path::new("octree.bin"); - let mut octree = if path.exists() { match SparseVoxelOctree::load_from_file(path) { Ok(tree) => tree, @@ -30,7 +26,6 @@ pub fn setup( } } else { let mut tree = SparseVoxelOctree::new(octree_depth, octree_base_size, false, false, false); - let color = Color::srgb(0.2, 0.8, 0.2); // How many random spheres? /*const NUM_SPHERES: usize = 5; let mut rng = threald_rng(); @@ -44,30 +39,22 @@ pub fn setup( let radius = rng.gen_range(20..=150); // voxels - generate_voxel_sphere_parallel(&mut tree, center, radius, color); + generate_voxel_sphere_parallel(&mut tree, center, radius); }*/ - - generate_voxel_sphere(&mut tree, 200, color); + + generate_voxel_sphere(&mut tree, 200); tree }; - - - // Attach octree to the scene graph commands.entity(root.0).with_children(|parent| { parent.spawn((Transform::default(), octree)); }); } -pub fn generate_voxel_sphere_parallel( - octree: &mut SparseVoxelOctree, - center: Vec3, - radius: i32, - color: Color, -) { - let step = octree.get_spacing_at_depth(octree.max_depth); - let radius_sq = radius * radius; +pub fn generate_voxel_sphere_parallel(octree: &mut SparseVoxelOctree, center: Vec3, radius: i32) { + let step = octree.get_spacing_at_depth(octree.max_depth); + let radius_sq = radius * radius; // 1. Collect voxel positions in parallel let voxels: Vec<(Vec3, Voxel)> = (-radius..=radius) @@ -75,7 +62,7 @@ pub fn generate_voxel_sphere_parallel( .flat_map_iter(|ix| { let dx2 = ix * ix; (-radius..=radius).flat_map(move |iy| { - let dy2 = iy * iy; + let dy2 = iy * iy; let r2_xy = dx2 + dy2; if r2_xy > radius_sq { @@ -83,14 +70,16 @@ pub fn generate_voxel_sphere_parallel( } let max_z = ((radius_sq - r2_xy) as f32).sqrt() as i32; - (-max_z..=max_z).map(move |iz| { - let pos = Vec3::new( - center.x + ix as f32 * step, - center.y + iy as f32 * step, - center.z + iz as f32 * step, - ); - (pos, Voxel { color, textures: [0; 6] }) - }).collect::>() + (-max_z..=max_z) + .map(move |iz| { + let pos = Vec3::new( + center.x + ix as f32 * step, + center.y + iy as f32 * step, + center.z + iz as f32 * step, + ); + (pos, Voxel::new([0; 6])) + }) + .collect::>() }) }) .collect(); @@ -101,12 +90,7 @@ pub fn generate_voxel_sphere_parallel( } } - -fn generate_voxel_sphere( - octree: &mut SparseVoxelOctree, - planet_radius: i32, - voxel_color: Color, -) { +fn generate_voxel_sphere(octree: &mut SparseVoxelOctree, planet_radius: i32) { // For simplicity, we center the sphere around (0,0,0). // We'll loop over a cubic region [-planet_radius, +planet_radius] in x, y, z let min = -planet_radius; @@ -131,10 +115,7 @@ fn generate_voxel_sphere( let position = Vec3::new(wx, wy, wz); // Insert the voxel - let voxel = Voxel { - color: voxel_color, - textures: [0; 6], - }; + let voxel = Voxel::new([0; 6]); octree.insert(position, voxel); } } @@ -142,13 +123,9 @@ fn generate_voxel_sphere( } } - /// Inserts a 16x256x16 "column" of voxels into the octree at (0,0,0) corner. /// If you want it offset or centered differently, just adjust the for-loop ranges or offsets. -fn generate_voxel_rect( - octree: &mut SparseVoxelOctree, - voxel_color: Color, -) { +fn generate_voxel_rect(octree: &mut SparseVoxelOctree) { // The dimensions of our rectangle: 16 x 256 x 16 let size_x = 16; let size_y = 256; @@ -173,22 +150,14 @@ fn generate_voxel_rect( let position = Vec3::new(wx, wy, wz); // Insert the voxel - let voxel = Voxel { - color: voxel_color, - textures: [0; 6], - }; + let voxel = Voxel::new([0; 6]); octree.insert(position, voxel); } } } } -fn generate_large_plane( - octree: &mut SparseVoxelOctree, - width: usize, - depth: usize, - color: Color, -) { +fn generate_large_plane(octree: &mut SparseVoxelOctree, width: usize, depth: usize) { // We'll get the voxel spacing (size at the deepest level). let step = octree.get_spacing_at_depth(octree.max_depth); @@ -209,21 +178,16 @@ fn generate_large_plane( let position = Vec3::new(wx, wy, wz); // Insert the voxel - let voxel = Voxel { - color, - textures: [0; 6], - }; + let voxel = Voxel::new([0; 6]); octree.insert(position, voxel); } } } - pub fn generate_solid_plane_with_noise( octree: &mut SparseVoxelOctree, width: usize, depth: usize, - color: Color, noise: &Perlin, frequency: f32, amplitude: f32, @@ -248,13 +212,9 @@ pub fn generate_solid_plane_with_noise( // Fill from layer 0 up to max_layer for iy in 0..=max_layer { - let position = Vec3::new( - x * step, - iy as f32 * step, - z * step, - ); + let position = Vec3::new(x * step, iy as f32 * step, z * step); - let voxel = Voxel { color, textures: [0; 6] }; + let voxel = Voxel::new([0; 6]); octree.insert(position, voxel); } } diff --git a/client/src/plugins/environment/systems/voxels/atlas.rs b/client/src/plugins/environment/systems/voxels/atlas.rs index 9d8d405..71b9eb9 100644 --- a/client/src/plugins/environment/systems/voxels/atlas.rs +++ b/client/src/plugins/environment/systems/voxels/atlas.rs @@ -1,6 +1,6 @@ use bevy::asset::RenderAssetUsages; use bevy::prelude::*; -use bevy::render::texture::{Extent3d, TextureDimension, TextureFormat}; +use bevy::render::render_resource::{Extent3d, TextureDimension, TextureFormat}; /// Configuration and handle for the voxel texture atlas. #[derive(Resource, Clone)] diff --git a/client/src/plugins/environment/systems/voxels/debug.rs b/client/src/plugins/environment/systems/voxels/debug.rs index 85a2de6..8ca6cd2 100644 --- a/client/src/plugins/environment/systems/voxels/debug.rs +++ b/client/src/plugins/environment/systems/voxels/debug.rs @@ -1,5 +1,5 @@ -use bevy::prelude::*; use crate::plugins::environment::systems::voxels::structure::*; +use bevy::prelude::*; /// Visualize each node of the octree as a scaled cuboid, **center-based**. /// `octree_tf.translation` is the world-space center of the root bounding box. @@ -13,8 +13,7 @@ pub fn visualize_octree_system( // Draw a translucent cuboid for the root gizmos.cuboid( - Transform::from_translation(octree_tf.translation) - .with_scale(Vec3::splat(octree.size)), + Transform::from_translation(octree_tf.translation).with_scale(Vec3::splat(octree.size)), Color::srgba(1.0, 1.0, 0.0, 0.15), ); @@ -85,9 +84,8 @@ fn visualize_recursive_center( // Draw a small cuboid at the same center as the parent node. gizmos.cuboid( - Transform::from_translation(parent_center) - .with_scale(Vec3::splat(leaf_size)), - voxel.color, + Transform::from_translation(parent_center).with_scale(Vec3::splat(leaf_size)), + Color::WHITE, ); } } @@ -100,7 +98,9 @@ pub fn draw_grid( camera_query: Query<&Transform, With>, octree_query: Query<(&SparseVoxelOctree, &Transform)>, ) { - let Ok(camera_tf) = camera_query.get_single() else { return }; + let Ok(camera_tf) = camera_query.get_single() else { + return; + }; let camera_pos = camera_tf.translation; for (octree, octree_tf) in octree_query.iter() { @@ -142,4 +142,4 @@ pub fn draw_grid( gizmos.line(p3, p4, Color::WHITE); } } -} \ No newline at end of file +} diff --git a/client/src/plugins/environment/systems/voxels/octree.rs b/client/src/plugins/environment/systems/voxels/octree.rs index be22069..18b761c 100644 --- a/client/src/plugins/environment/systems/voxels/octree.rs +++ b/client/src/plugins/environment/systems/voxels/octree.rs @@ -1,19 +1,27 @@ -use std::collections::{HashMap, HashSet}; -use std::path::Path; -use std::io; -use bincode; +use crate::plugins::environment::systems::voxels::helper::chunk_key_from_world; +use crate::plugins::environment::systems::voxels::structure::{ + AABB, CHUNK_SIZE, ChunkKey, DirtyVoxel, NEIGHBOR_OFFSETS, OctreeNode, Ray, SparseVoxelOctree, + Voxel, +}; use bevy::asset::Assets; -use bevy::color::Color; use bevy::math::{DQuat, DVec3}; use bevy::prelude::*; use bevy::render::mesh::{Indices, PrimitiveTopology, VertexAttributeValues}; use bevy::render::render_asset::RenderAssetUsages; -use crate::plugins::environment::systems::voxels::helper::chunk_key_from_world; -use crate::plugins::environment::systems::voxels::structure::{DirtyVoxel, OctreeNode, Ray, SparseVoxelOctree, Voxel, AABB, NEIGHBOR_OFFSETS, CHUNK_SIZE, ChunkKey}; +use bincode; +use std::collections::{HashMap, HashSet}; +use std::io; +use std::path::Path; impl SparseVoxelOctree { /// Creates a new octree with the specified max depth, size, and wireframe visibility. - pub fn new(max_depth: u32, size: f32, show_wireframe: bool, show_world_grid: bool, show_chunks: bool) -> Self { + pub fn new( + max_depth: u32, + size: f32, + show_wireframe: bool, + show_world_grid: bool, + show_chunks: bool, + ) -> Self { Self { root: OctreeNode::new(), max_depth, @@ -38,9 +46,7 @@ impl SparseVoxelOctree { world_center = self.denormalize_voxel_center(aligned); } - let dirty_voxel = DirtyVoxel{ - position: aligned, - }; + let dirty_voxel = DirtyVoxel { position: aligned }; self.dirty.push(dirty_voxel); let key = chunk_key_from_world(self, position); @@ -48,7 +54,6 @@ impl SparseVoxelOctree { self.mark_neighbor_chunks_dirty(position); self.occupied_chunks.insert(key); - Self::insert_recursive(&mut self.root, aligned, voxel, self.max_depth); } @@ -147,9 +152,12 @@ impl SparseVoxelOctree { /// Mark all six neighbor chunks of the given key as dirty if they exist. pub fn mark_neighbors_dirty_from_key(&mut self, key: ChunkKey) { let offsets = [ - (-1, 0, 0), (1, 0, 0), - (0, -1, 0), (0, 1, 0), - (0, 0, -1), (0, 0, 1), + (-1, 0, 0), + (1, 0, 0), + (0, -1, 0), + (0, 1, 0), + (0, 0, -1), + (0, 0, 1), ]; for (dx, dy, dz) in offsets { let neighbor = ChunkKey(key.0 + dx, key.1 + dy, key.2 + dz); @@ -159,13 +167,7 @@ impl SparseVoxelOctree { } } - 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 node.voxel.is_some() { node.voxel = None; @@ -222,7 +224,6 @@ impl SparseVoxelOctree { false } - fn expand_root(&mut self, _x: f32, _y: f32, _z: f32) { info!("Root expanding ..."); // Save the old root and its size. @@ -244,7 +245,15 @@ impl SparseVoxelOctree { /// The coordinate system here assumes the node covers [–old_size/2, +old_size/2] in each axis. fn collect_voxels_from_node(node: &OctreeNode, old_size: f32) -> Vec<(Vec3, Voxel, u32)> { let mut voxels = Vec::new(); - Self::collect_voxels_recursive(node, -old_size / 2.0, -old_size / 2.0, -old_size / 2.0, old_size, 0, &mut voxels); + Self::collect_voxels_recursive( + node, + -old_size / 2.0, + -old_size / 2.0, + -old_size / 2.0, + old_size, + 0, + &mut voxels, + ); voxels } @@ -270,14 +279,20 @@ impl SparseVoxelOctree { let offset_x = if (i & 1) != 0 { half } else { 0.0 }; let offset_y = if (i & 2) != 0 { half } else { 0.0 }; let offset_z = if (i & 4) != 0 { half } else { 0.0 }; - Self::collect_voxels_recursive(child, x + offset_x, y + offset_y, z + offset_z, half, depth + 1, out); + Self::collect_voxels_recursive( + child, + x + offset_x, + y + offset_y, + z + offset_z, + half, + depth + 1, + out, + ); } } } - - - pub fn traverse(&self) -> Vec<(Vec3, Color, u32)> { + pub fn traverse(&self) -> Vec<(Vec3, u32)> { let mut voxels = Vec::new(); // Start at the normalized center (0.5, 0.5, 0.5) rather than (0,0,0) Self::traverse_recursive( @@ -296,20 +311,20 @@ impl SparseVoxelOctree { local_center: Vec3, size: f32, depth: u32, - out: &mut Vec<(Vec3, Color, u32)>, + out: &mut Vec<(Vec3, u32)>, octree: &SparseVoxelOctree, ) { // If a leaf contains a voxel, record its world-space center if node.is_leaf { if let Some(voxel) = node.voxel { - out.push((octree.denormalize_voxel_center(local_center), voxel.color, depth)); + out.push((octree.denormalize_voxel_center(local_center), depth)); } } // If the node has children, subdivide the cell into 8 subcells. if let Some(ref children) = node.children { - let offset = size / 4.0; // child center offset from parent center - let new_size = size / 2.0; // each child cell's size in normalized space + let offset = size / 4.0; // child center offset from parent center + let new_size = size / 2.0; // each child cell's size in normalized space for (i, child) in children.iter().enumerate() { // Compute each axis' offset: use +offset if the bit is set, else -offset. let dx = if (i & 1) != 0 { offset } else { -offset }; @@ -322,8 +337,6 @@ impl SparseVoxelOctree { } } - - /// Retrieve a voxel from the octree if it exists (x,y,z in [-0.5..+0.5] range). pub fn get_voxel_at(&self, x: f32, y: f32, z: f32) -> Option<&Voxel> { Self::get_voxel_recursive(&self.root, x, y, z) @@ -388,7 +401,6 @@ impl SparseVoxelOctree { self.get_voxel_at_world_coords(neighbor_world).is_some() } - /// Performs a raycast against the octree and returns the first intersected voxel. pub fn raycast(&self, ray: &Ray) -> Option<(f32, f32, f32, u32, Vec3)> { // Start from the root node @@ -397,12 +409,7 @@ impl SparseVoxelOctree { min: Vec3::new(-half_size as f32, -half_size as f32, -half_size as f32), max: Vec3::new(half_size as f32, half_size as f32, half_size as f32), }; - self.raycast_recursive( - &self.root, - ray, - &root_bounds, - 0, - ) + self.raycast_recursive(&self.root, ray, &root_bounds, 0) } fn raycast_recursive( @@ -435,7 +442,8 @@ impl SparseVoxelOctree { let mut hits = Vec::new(); for (i, child) in children.iter().enumerate() { let child_bounds = self.compute_child_bounds(bounds, i); - if let Some(hit) = self.raycast_recursive(child, ray, &child_bounds, depth + 1) { + if let Some(hit) = self.raycast_recursive(child, ray, &child_bounds, depth + 1) + { hits.push(hit); } } @@ -445,11 +453,11 @@ impl SparseVoxelOctree { let dist_a = ((a.0 as f32 - ray.origin.x).powi(2) + (a.1 as f32 - ray.origin.y).powi(2) + (a.2 as f32 - ray.origin.z).powi(2)) - .sqrt(); + .sqrt(); let dist_b = ((b.0 as f32 - ray.origin.x).powi(2) + (b.1 as f32 - ray.origin.y).powi(2) + (b.2 as f32 - ray.origin.z).powi(2)) - .sqrt(); + .sqrt(); dist_a.partial_cmp(&dist_b).unwrap() }); return Some(hits[0]); @@ -462,16 +470,15 @@ impl SparseVoxelOctree { /// Save the octree to a file using bincode serialization. pub fn save_to_file>(&self, path: P) -> io::Result<()> { - let data = bincode::serialize(self) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + let data = bincode::serialize(self).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; std::fs::write(path, data) } /// Load an octree from a file and rebuild runtime caches. pub fn load_from_file>(path: P) -> io::Result { let bytes = std::fs::read(path)?; - let mut tree: Self = bincode::deserialize(&bytes) - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + let mut tree: Self = + bincode::deserialize(&bytes).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; tree.rebuild_cache(); Ok(tree) } @@ -481,7 +488,7 @@ impl SparseVoxelOctree { self.dirty.clear(); self.dirty_chunks.clear(); self.occupied_chunks.clear(); - + let voxels = Self::collect_voxels_from_node(&self.root, self.size); for (pos, _voxel, _depth) in voxels { let key = chunk_key_from_world(self, pos); @@ -489,4 +496,3 @@ impl SparseVoxelOctree { } } } - diff --git a/client/src/plugins/environment/systems/voxels/structure.rs b/client/src/plugins/environment/systems/voxels/structure.rs index 4327afa..befe22d 100644 --- a/client/src/plugins/environment/systems/voxels/structure.rs +++ b/client/src/plugins/environment/systems/voxels/structure.rs @@ -1,32 +1,10 @@ -use bevy::color::Color; use bevy::prelude::*; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet, VecDeque}; -fn serialize_color(color: &Color, serializer: S) -> Result -where - S: Serializer, -{ - let [r, g, b, a] = color.to_linear().to_f32_array(); - [r, g, b, a].serialize(serializer) -} - -fn deserialize_color<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let arr: [f32; 4] = Deserialize::deserialize(deserializer)?; - Ok(Color::linear_rgba(arr[0], arr[1], arr[2], arr[3])) -} - -/// Represents a single voxel with a color. +/// Represents a single voxel with texture indices for each face. #[derive(Debug, Clone, Copy, Component, PartialEq, Serialize, Deserialize)] pub struct Voxel { - #[serde( - serialize_with = "serialize_color", - deserialize_with = "deserialize_color" - )] - pub color: Color, /// Indexes into the texture atlas for the six faces in the order /// left, right, bottom, top, back, front. #[serde(default)] @@ -35,10 +13,7 @@ pub struct Voxel { impl Default for Voxel { fn default() -> Self { - Self { - color: Color::WHITE, - textures: [0; 6], - } + Self { textures: [0; 6] } } } @@ -90,8 +65,8 @@ impl OctreeNode { impl Voxel { /// Creates a new empty octree node. - pub fn new(color: Color, textures: [usize; 6]) -> Self { - Self { color, textures } + pub fn new(textures: [usize; 6]) -> Self { + Self { textures } } } diff --git a/client/src/plugins/input/systems/voxels.rs b/client/src/plugins/input/systems/voxels.rs index a45de1f..bcae7dd 100644 --- a/client/src/plugins/input/systems/voxels.rs +++ b/client/src/plugins/input/systems/voxels.rs @@ -1,12 +1,11 @@ -use std::path::Path; -use bevy::prelude::*; use crate::plugins::environment::systems::camera_system::CameraController; use crate::plugins::environment::systems::voxels::octree; use crate::plugins::environment::systems::voxels::structure::*; +use bevy::prelude::*; +use std::path::Path; ///TODO pub fn voxel_system( - keyboard_input: Res>, mouse_button_input: Res>, mut octree_query: Query<&mut SparseVoxelOctree>, @@ -14,32 +13,33 @@ pub fn voxel_system( mut query: Query<(&mut Transform, &mut CameraController)>, mut windows: Query<&mut Window>, ) { - let Ok(mut window) = windows.get_single_mut() else { return }; - let Ok((mut transform, _)) = query.get_single_mut() else { return }; + let Ok(mut window) = windows.get_single_mut() else { + return; + }; + let Ok((mut transform, _)) = query.get_single_mut() else { + return; + }; // ======================= // 5) Octree Keys // ======================= - if keyboard_input.just_pressed(KeyCode::F2){ + if keyboard_input.just_pressed(KeyCode::F2) { for mut octree in octree_query.iter_mut() { octree.show_wireframe = !octree.show_wireframe; } } - if keyboard_input.just_pressed(KeyCode::F3){ + if keyboard_input.just_pressed(KeyCode::F3) { for mut octree in octree_query.iter_mut() { octree.show_world_grid = !octree.show_world_grid; } } - if keyboard_input.just_pressed(KeyCode::KeyQ) && window.cursor_options.visible == false{ + if keyboard_input.just_pressed(KeyCode::KeyQ) && window.cursor_options.visible == false { for mut octree in octree_query.iter_mut() { - octree.insert( - transform.translation, - Voxel::new(Color::srgb(1.0, 0.0, 0.0), [0; 6]), - ); + octree.insert(transform.translation, Voxel::new([0; 6])); } } - if keyboard_input.just_pressed(KeyCode::F4){ + if keyboard_input.just_pressed(KeyCode::F4) { let path = Path::new("octree.bin"); for octree in octree_query.iter() { if let Err(e) = octree.save_to_file(path) { @@ -47,7 +47,7 @@ pub fn voxel_system( } } } -/* if keyboard_input.just_pressed(KeyCode::F5){ + /* if keyboard_input.just_pressed(KeyCode::F5){ let path = Path::new("octree.bin"); if path.exists() { let path = Path::new("octree.bin"); @@ -60,17 +60,18 @@ pub fn voxel_system( } } } - + } }*/ - // ======================= // 6) Building // ======================= - if (mouse_button_input.just_pressed(MouseButton::Left) || mouse_button_input.just_pressed(MouseButton::Right)) && !window.cursor_options.visible { - + if (mouse_button_input.just_pressed(MouseButton::Left) + || mouse_button_input.just_pressed(MouseButton::Right)) + && !window.cursor_options.visible + { // Get the mouse position in normalized device coordinates (-1 to 1) if let Some(_) = window.cursor_position() { // Set the ray direction to the camera's forward vector @@ -82,44 +83,33 @@ pub fn voxel_system( direction: ray_direction, }; - - 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) { 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; // Adjust this value as needed (e.g., 0.1 times the voxel size) // 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)); + let offset_position = hit_position + - (normal * Vec3::new(epsilon as f32, epsilon as f32, epsilon as f32)); // Remove the voxel 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 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) // 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)); + 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::new(Color::srgb(1.0, 0.0, 0.0), [0; 6]), - ); + octree.insert(offset_position, Voxel::new([0; 6])); } } } } } - -} \ No newline at end of file +}