Merge pull request #12 from eliasstepanik/codex/fix-rogue-faces-rendering-on-lod-change

Fix chunk boundary updates
This commit is contained in:
Elias Stepanik 2025-06-09 13:33:48 +02:00 committed by GitHub
commit 84b2f8f420
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 48 additions and 2 deletions

View File

@ -19,7 +19,7 @@ pub fn setup(
// 2. Generate sphere in parallel, dropping the cloned Arc inside the function
let color = Color::rgb(0.2, 0.8, 0.2);
generate_voxel_sphere(&mut octree, 100, color);
generate_voxel_sphere(&mut octree, 110, color);
// 4. Spawn entity with both Transform and the real octree component
commands.entity(root.0).with_children(|parent| {

View File

@ -6,7 +6,7 @@ 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};
use crate::plugins::environment::systems::voxels::structure::{DirtyVoxel, OctreeNode, Ray, SparseVoxelOctree, Voxel, AABB, NEIGHBOR_OFFSETS, CHUNK_SIZE, ChunkKey};
impl SparseVoxelOctree {
/// Creates a new octree with the specified max depth, size, and wireframe visibility.
@ -43,6 +43,7 @@ impl SparseVoxelOctree {
self.dirty.push(dirty_voxel);
let key = chunk_key_from_world(self, position);
self.dirty_chunks.insert(key);
self.mark_neighbor_chunks_dirty(position);
self.occupied_chunks.insert(key);
@ -92,6 +93,7 @@ impl SparseVoxelOctree {
// mark the chunk
let key = chunk_key_from_world(self, position);
self.dirty_chunks.insert(key);
self.mark_neighbor_chunks_dirty(position);
Self::remove_recursive(
&mut self.root,
@ -111,6 +113,50 @@ impl SparseVoxelOctree {
self.dirty_chunks.clear();
}
fn mark_neighbor_chunks_dirty(&mut self, position: Vec3) {
let key = chunk_key_from_world(self, position);
let step = self.get_spacing_at_depth(self.max_depth);
let half = self.size * 0.5;
let gx = ((position.x + half) / step).floor() as i32;
let gy = ((position.y + half) / step).floor() as i32;
let gz = ((position.z + half) / step).floor() as i32;
let lx = gx - key.0 * CHUNK_SIZE;
let ly = gy - key.1 * CHUNK_SIZE;
let lz = gz - key.2 * CHUNK_SIZE;
let mut neighbors = [
(lx == 0, ChunkKey(key.0 - 1, key.1, key.2)),
(lx == CHUNK_SIZE - 1, ChunkKey(key.0 + 1, key.1, key.2)),
(ly == 0, ChunkKey(key.0, key.1 - 1, key.2)),
(ly == CHUNK_SIZE - 1, ChunkKey(key.0, key.1 + 1, key.2)),
(lz == 0, ChunkKey(key.0, key.1, key.2 - 1)),
(lz == CHUNK_SIZE - 1, ChunkKey(key.0, key.1, key.2 + 1)),
];
for (cond, n) in neighbors.iter() {
if *cond && self.occupied_chunks.contains(n) {
self.dirty_chunks.insert(*n);
}
}
}
/// 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),
];
for (dx, dy, dz) in offsets {
let neighbor = ChunkKey(key.0 + dx, key.1 + dy, key.2 + dz);
if self.occupied_chunks.contains(&neighbor) {
self.dirty_chunks.insert(neighbor);
}
}
}
fn remove_recursive(
node: &mut OctreeNode,
x: f32,