fix removal issue

This commit is contained in:
Lillian Vixe 2024-04-13 13:49:08 -07:00
parent a5f02871ef
commit ec020a03b5
3 changed files with 99 additions and 116 deletions

View file

@ -5,6 +5,8 @@
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml"
],
}

View file

@ -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));
}
}
}

View file

@ -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());
}
}