fix removal issue
This commit is contained in:
parent
a5f02871ef
commit
ec020a03b5
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
|
@ -5,6 +5,8 @@
|
|||
"./Cargo.toml",
|
||||
"./Cargo.toml",
|
||||
"./Cargo.toml",
|
||||
"./Cargo.toml",
|
||||
"./Cargo.toml",
|
||||
"./Cargo.toml"
|
||||
],
|
||||
}
|
|
@ -4,16 +4,17 @@ use bevy::{
|
|||
ecs::system::{Commands, Query, ResMut, Resource},
|
||||
math::Vec3,
|
||||
render::{camera::Camera, color::Color},
|
||||
transform::components::{GlobalTransform, Transform},
|
||||
transform::components::GlobalTransform,
|
||||
window::Window,
|
||||
};
|
||||
use bevy_egui::{egui, EguiContexts, EguiPlugin};
|
||||
use rand::Rng;
|
||||
|
||||
use crate::{
|
||||
vvedit::editor_bevy_input_shim::keybind_codes::REMOVE_VOXEL,
|
||||
vvlib::{
|
||||
inputs::InputRegister, intersections::octtree_ray_overlap, obb::OBB,
|
||||
oct_asset::OctAssetMarker, octtree,
|
||||
oct_asset::OctAssetMarker,
|
||||
},
|
||||
};
|
||||
use crate::{
|
||||
|
@ -53,99 +54,53 @@ pub fn edit_click_events(
|
|||
let paint = input_data.get_binary_input(&PAINT_VOXEL.into());
|
||||
let remove = input_data.get_binary_input(&REMOVE_VOXEL.into());
|
||||
let insert = input_data.get_binary_input(&INSERT_VOXEL.into());
|
||||
// preprep done
|
||||
if let Some(_) = paint.filter(|input| input.pressed()) {
|
||||
for window in &windows {
|
||||
for (trans, oct) in &oct_tree {
|
||||
for (camera, cam_trans) in &camera_query {
|
||||
let Some(cursor_pos) = window.cursor_position() else {
|
||||
continue;
|
||||
};
|
||||
let Some(ray) = camera.viewport_to_world(cam_trans, cursor_pos) else {
|
||||
continue;
|
||||
};
|
||||
let obb = OBB::from_transform(trans.compute_transform());
|
||||
let octtree = oct_assets.get_mut(oct.oct_handle.clone());
|
||||
if octtree.is_none() {
|
||||
continue;
|
||||
}
|
||||
let edit_octtree = &mut octtree.unwrap().model;
|
||||
let collision = octtree_ray_overlap(
|
||||
edit_octtree,
|
||||
&obb,
|
||||
ray.origin,
|
||||
ray.direction.normalize(),
|
||||
);
|
||||
if collision.is_some() {
|
||||
let col = collision.unwrap();
|
||||
let hitloc = col.hit_data.hitpoint.local.clone();
|
||||
let hitnorm = col.hit_data.normal.local.clone();
|
||||
let hitvox = hitloc - (hitnorm * 0.5);
|
||||
edit_octtree.set_voxel_at_location(hitvox.round(), Color::PINK);
|
||||
}
|
||||
for window in &windows {
|
||||
for (trans, oct) in &oct_tree {
|
||||
for (camera, cam_trans) in &camera_query {
|
||||
let mut rng = rand::thread_rng();
|
||||
let r: f32 = rng.gen_range(0.0..1.0);
|
||||
let g: f32 = rng.gen_range(0.0..1.0);
|
||||
let b: f32 = rng.gen_range(0.0..1.0);
|
||||
let Some(cursor_pos) = window.cursor_position() else {
|
||||
continue;
|
||||
};
|
||||
let Some(ray) = camera.viewport_to_world(cam_trans, cursor_pos) else {
|
||||
continue;
|
||||
};
|
||||
let obb = OBB::from_transform(trans.compute_transform());
|
||||
let octtree = oct_assets.get_mut(oct.oct_handle.clone());
|
||||
if octtree.is_none() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(_) = remove.filter(|input| input.pressed()) {
|
||||
for window in &windows {
|
||||
for (trans, oct) in &oct_tree {
|
||||
for (camera, cam_trans) in &camera_query {
|
||||
let Some(cursor_pos) = window.cursor_position() else {
|
||||
continue;
|
||||
};
|
||||
let Some(ray) = camera.viewport_to_world(cam_trans, cursor_pos) else {
|
||||
continue;
|
||||
};
|
||||
let obb = OBB::from_transform(trans.compute_transform());
|
||||
let octtree = oct_assets.get_mut(oct.oct_handle.clone());
|
||||
if octtree.is_none() {
|
||||
continue;
|
||||
let edit_octtree = &mut octtree.unwrap().model;
|
||||
let collision =
|
||||
octtree_ray_overlap(edit_octtree, &obb, ray.origin, ray.direction.normalize());
|
||||
|
||||
if let Some(_) = paint.filter(|input| input.pressed()) {
|
||||
if collision.is_some() {
|
||||
let col = collision.unwrap();
|
||||
edit_octtree
|
||||
.set_voxel_at_location(col.voxel_index_location, Color::rgb(r, g, b));
|
||||
}
|
||||
let edit_octtree = &mut octtree.unwrap().model;
|
||||
let collision = octtree_ray_overlap(
|
||||
edit_octtree,
|
||||
&obb,
|
||||
ray.origin,
|
||||
ray.direction.normalize(),
|
||||
);
|
||||
} else if let Some(_) = remove.filter(|input| input.pressed()) {
|
||||
if collision.is_some() {
|
||||
let col = collision.unwrap();
|
||||
|
||||
let x = edit_octtree.remove_voxel(col.voxel_index_location);
|
||||
if x == 0 {
|
||||
dbg!(edit_octtree);
|
||||
dbg!(col.voxel_index_location);
|
||||
} else {
|
||||
println!("Successfully culled {} voxels!", x);
|
||||
}
|
||||
}
|
||||
} else if let Some(_) = insert.filter(|input| input.pressed()) {
|
||||
if collision.is_some() {
|
||||
let col = collision.unwrap();
|
||||
let hitloc = col.hit_data.hitpoint.local.clone();
|
||||
let hitnorm = col.hit_data.normal.local.clone();
|
||||
let hitvox = hitloc - (hitnorm * 0.5);
|
||||
edit_octtree.remove_voxel(hitvox.round());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let Some(_) = insert.filter(|input| input.pressed()) {
|
||||
for window in &windows {
|
||||
for (trans, oct) in &oct_tree {
|
||||
for (camera, cam_trans) in &camera_query {
|
||||
let Some(cursor_pos) = window.cursor_position() else {
|
||||
continue;
|
||||
};
|
||||
let Some(ray) = camera.viewport_to_world(cam_trans, cursor_pos) else {
|
||||
continue;
|
||||
};
|
||||
let obb = OBB::from_transform(trans.compute_transform());
|
||||
let octtree = oct_assets.get_mut(oct.oct_handle.clone());
|
||||
if octtree.is_none() {
|
||||
continue;
|
||||
}
|
||||
let edit_octtree = &mut octtree.unwrap().model;
|
||||
let collision = octtree_ray_overlap(
|
||||
edit_octtree,
|
||||
&obb,
|
||||
ray.origin,
|
||||
ray.direction.normalize(),
|
||||
);
|
||||
if collision.is_some() {
|
||||
let col = collision.unwrap();
|
||||
let hitloc = col.hit_data.hitpoint.local.clone();
|
||||
let hitnorm = col.hit_data.normal.local.clone();
|
||||
let hitvox = hitloc + (hitnorm * 0.5);
|
||||
edit_octtree.set_voxel_at_location(hitvox.round(), Color::PINK);
|
||||
let hitvox = hitloc + (hitnorm * 0.25);
|
||||
edit_octtree.set_voxel_at_location(hitvox.round(), Color::rgb(r, g, b));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
use std::mem::swap;
|
||||
|
||||
use bevy::math::Vec3;
|
||||
use bevy::math::{vec3, Vec3};
|
||||
use rand::Rng;
|
||||
|
||||
use crate::vvlib::intersections::aa_bounds_contains;
|
||||
|
||||
|
@ -20,8 +21,8 @@ pub enum TreeNode<T> {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct OctTree<T> {
|
||||
pub(crate) size: usize,
|
||||
pub(crate) center: Vec3,
|
||||
pub size: usize,
|
||||
pub center: Vec3,
|
||||
pub(crate) root: TreeNode<T>,
|
||||
pub needs_update: bool,
|
||||
}
|
||||
|
@ -32,9 +33,12 @@ pub struct Path {
|
|||
pub(crate) length: usize,
|
||||
}
|
||||
impl Path {
|
||||
pub fn pop(&mut self) -> usize {
|
||||
pub fn pop(&mut self) -> Option<usize> {
|
||||
if self.length == 0 {
|
||||
return None;
|
||||
}
|
||||
self.length -= 1;
|
||||
return self.get_index(self.length);
|
||||
return Some(self.get_index(self.length));
|
||||
}
|
||||
pub fn parent(&self) -> Path {
|
||||
let mut duplicate = self.clone();
|
||||
|
@ -127,8 +131,26 @@ impl<T: Clone> OctTree<T> {
|
|||
pub fn remove_voxel(&mut self, location: Vec3) -> usize {
|
||||
let result = self.voxel_at_location(location);
|
||||
if result.is_some() {
|
||||
let path = result.unwrap().1;
|
||||
let mut count: usize = 0;
|
||||
Self::prune(&mut self.root, result.unwrap().1, &mut count);
|
||||
if path.length == 0 {
|
||||
if self.root.is_leaf() {
|
||||
self.root = TreeNode::Empty;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
let mut iter = &mut self.root;
|
||||
for i in 0..path.length {
|
||||
let region = path.get_index(i) as usize;
|
||||
if let TreeNode::Branch(branch) = iter {
|
||||
let arr = branch.as_mut();
|
||||
iter = &mut arr[region];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*iter = TreeNode::Empty;
|
||||
count += 1;
|
||||
self.trim(&mut count);
|
||||
self.needs_update = true;
|
||||
return count;
|
||||
|
@ -176,27 +198,6 @@ impl<T: Clone> OctTree<T> {
|
|||
self.trim(removal_count);
|
||||
}
|
||||
}
|
||||
fn prune(element: &mut TreeNode<T>, mut target: Path, count: &mut usize) {
|
||||
match element {
|
||||
TreeNode::Branch(a) => {
|
||||
let i = target.pop();
|
||||
let ar: &mut [TreeNode<T>; 8] = a.as_mut();
|
||||
Self::prune(&mut ar[i], target, count);
|
||||
|
||||
if ar.iter().all(|x| matches!(x, TreeNode::Empty)) {
|
||||
*element = TreeNode::Empty;
|
||||
*count += 1;
|
||||
}
|
||||
}
|
||||
TreeNode::Leaf(_) => {
|
||||
if target.length == 0 {
|
||||
*element = TreeNode::Empty;
|
||||
*count += 1;
|
||||
}
|
||||
}
|
||||
TreeNode::Empty => return,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_voxel_at_path(&mut self, path: &Path, value: T) -> bool {
|
||||
// return value is whether it was successful
|
||||
|
@ -624,3 +625,28 @@ pub fn test_path() {
|
|||
assert_eq!(path_test.get_index(0), 6);
|
||||
println!("{:#?}", dbg!(path_test.clone()));
|
||||
}
|
||||
#[test]
|
||||
pub fn fuzztestpath() {
|
||||
let origin = Vec3::ZERO;
|
||||
let mut test_oct = OctTree::<i32>::new(origin, 1);
|
||||
let range = 10000.;
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut list: Vec<(Vec3, i32)> = Vec::new();
|
||||
|
||||
for _ in 0..10000 {
|
||||
let x: f32 = rng.gen_range(-range..range);
|
||||
let y: f32 = rng.gen_range(-range..range);
|
||||
let z: f32 = rng.gen_range(-range..range);
|
||||
let w: i32 = rng.gen_range(0..range as i32);
|
||||
let vec = Vec3::new(x, y, z);
|
||||
list.push((vec, w));
|
||||
test_oct.set_voxel_at_location(vec, w);
|
||||
}
|
||||
|
||||
for item in list {
|
||||
let get = test_oct.voxel_at_location(item.0);
|
||||
assert_eq!(item.1, get.clone().unwrap().0);
|
||||
let get = test_oct.voxel_at_path(&get.unwrap().1);
|
||||
assert_eq!(item.1, get.unwrap());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue