refactor ray collisions to return face normal
This commit is contained in:
parent
471ce62c35
commit
2fe1812f35
146
src/oct_tree.rs
146
src/oct_tree.rs
|
@ -602,7 +602,7 @@ pub fn ray_obb_intersection(
|
|||
ray_origin: Vec3,
|
||||
ray_direction_normalized: Vec3,
|
||||
bounds: &OBB,
|
||||
) -> Option<Vec3> {
|
||||
) -> Option<RayBoundsIntersection> {
|
||||
let transform: Transform = Transform::from_translation(bounds.position)
|
||||
.with_rotation(bounds.orientation)
|
||||
.with_scale(bounds.half_size * 2.);
|
||||
|
@ -612,8 +612,26 @@ pub fn ray_obb_intersection(
|
|||
let passthru =
|
||||
distance_to_ray_bounds_intersection(ro_trans, rd_trans, Vec3::ZERO, Vec3::splat(0.5));
|
||||
if passthru.is_some() {
|
||||
let unwrapped = passthru.unwrap();
|
||||
return Some(ray_origin + (ray_direction_normalized * unwrapped));
|
||||
let hitpoint = ray_origin + (ray_direction_normalized * passthru.unwrap());
|
||||
let mut dist_array: [(Vec3, f32); 6] = Default::default();
|
||||
let mut min_dist: usize = 8;
|
||||
for (index, norm) in constants::cardinal_directions::ORDERED.iter().enumerate() {
|
||||
let pos = norm.clone() * bounds.half_size * 2.;
|
||||
let pos = pos + bounds.position;
|
||||
let pos = matrix.transform_vector3(pos);
|
||||
let dist = pos.distance(hitpoint);
|
||||
dist_array[index] = (norm.clone(), dist);
|
||||
if index == 0 {
|
||||
min_dist = index;
|
||||
} else if dist_array[min_dist].1 > dist {
|
||||
min_dist = index;
|
||||
}
|
||||
}
|
||||
let normal = dist_array[min_dist].0;
|
||||
return Some(RayBoundsIntersection {
|
||||
hitpoint: hitpoint,
|
||||
untransformed_normal: normal,
|
||||
});
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
|
@ -662,13 +680,18 @@ pub fn ray_sphere_intersection(
|
|||
|
||||
return Some(ray_origin + (ray_direction_normalized * t));
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct RayBoundsIntersection {
|
||||
hitpoint: Vec3,
|
||||
untransformed_normal: Vec3,
|
||||
}
|
||||
|
||||
pub fn ray_aabb_intersection(
|
||||
ray_origin: Vec3,
|
||||
ray_direction_normalized: Vec3,
|
||||
bound_center: Vec3,
|
||||
bound_half_size: Vec3,
|
||||
) -> Option<Vec3> {
|
||||
) -> Option<RayBoundsIntersection> {
|
||||
let passthru = distance_to_ray_bounds_intersection(
|
||||
ray_origin,
|
||||
ray_direction_normalized,
|
||||
|
@ -676,7 +699,25 @@ pub fn ray_aabb_intersection(
|
|||
bound_half_size,
|
||||
);
|
||||
if passthru.is_some() {
|
||||
return Some(ray_origin + (ray_direction_normalized * passthru.unwrap()));
|
||||
let hitpoint = ray_origin + (ray_direction_normalized * passthru.unwrap());
|
||||
let mut dist_array: [(Vec3, f32); 6] = Default::default();
|
||||
let mut min_dist: usize = 8;
|
||||
for (index, norm) in constants::cardinal_directions::ORDERED.iter().enumerate() {
|
||||
let pos = norm.clone() * bound_half_size * 2.;
|
||||
let pos = pos + bound_center;
|
||||
let dist = pos.distance(hitpoint);
|
||||
dist_array[index] = (norm.clone(), dist);
|
||||
if index == 0 {
|
||||
min_dist = index;
|
||||
} else if dist_array[min_dist].1 > dist {
|
||||
min_dist = index;
|
||||
}
|
||||
}
|
||||
let normal = dist_array[min_dist].0;
|
||||
return Some(RayBoundsIntersection {
|
||||
hitpoint: hitpoint,
|
||||
untransformed_normal: normal,
|
||||
});
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
|
@ -720,7 +761,7 @@ pub fn sphere_obb_intersection(
|
|||
None
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct OctTreeCollisionPoint {
|
||||
pos_in_oct: Vec3,
|
||||
pos_in_global: Vec3,
|
||||
|
@ -1048,7 +1089,7 @@ mod constants {
|
|||
pub const PPP: Vec3 = Vec3::new(1., 1., 1.);
|
||||
pub const ORDERED: [Vec3; 8] = [NNN, NNP, NPN, NPP, PNN, PNP, PPN, PPP];
|
||||
}
|
||||
mod cardinal_directions {
|
||||
pub(crate) mod cardinal_directions {
|
||||
use bevy::math::Vec3;
|
||||
pub const PX: Vec3 = Vec3::X;
|
||||
pub const NX: Vec3 = Vec3::NEG_X;
|
||||
|
@ -1056,6 +1097,7 @@ mod constants {
|
|||
pub const NY: Vec3 = Vec3::NEG_Y;
|
||||
pub const PZ: Vec3 = Vec3::Z;
|
||||
pub const NZ: Vec3 = Vec3::NEG_Z;
|
||||
pub const ORDERED: [Vec3; 6] = [PX, NX, PY, NY, PZ, NZ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1216,21 +1258,30 @@ pub fn test_ray_x_bounding_collisions() {
|
|||
Quat::from_rotation_z(f32::to_radians(90.)),
|
||||
Vec3::splat(5.),
|
||||
);
|
||||
let aabb_test: Option<Vec3> =
|
||||
let aabb_test: Option<RayBoundsIntersection> =
|
||||
ray_aabb_intersection(Vec3::ZERO, Vec3::X, abounds.position, abounds.half_size);
|
||||
let obb_test: Option<Vec3> = ray_obb_intersection(Vec3::ZERO, Vec3::X, &abounds);
|
||||
let obb_test: Option<RayBoundsIntersection> =
|
||||
ray_obb_intersection(Vec3::ZERO, Vec3::X, &abounds);
|
||||
|
||||
assert_eq!(aabb_test.unwrap(), Vec3::new(5., 0., 0.));
|
||||
assert_eq!(aabb_test.clone().unwrap().hitpoint, Vec3::new(5., 0., 0.));
|
||||
assert_eq!(
|
||||
aabb_test.unwrap().untransformed_normal,
|
||||
Vec3::new(-1., 0., 0.)
|
||||
);
|
||||
|
||||
assert_eq!(obb_test.unwrap().round(), Vec3::new(5., 0., 0.));
|
||||
assert_eq!(obb_test.unwrap().hitpoint.round(), Vec3::new(5., 0., 0.));
|
||||
|
||||
let rotated_bounds: OBB = OBB::new(
|
||||
Vec3::new(20., 0., 0.),
|
||||
Quat::from_rotation_z(f32::to_radians(45.0)),
|
||||
Quat::from_rotation_z(f32::to_radians(-50.0)),
|
||||
Vec3::splat(5.),
|
||||
);
|
||||
let rotated_obb_test = ray_obb_intersection(Vec3::ZERO, Vec3::X, &rotated_bounds).unwrap();
|
||||
assert_eq!(rotated_obb_test.round().x, 13.);
|
||||
assert_eq!(rotated_obb_test.hitpoint.round().x, 13.);
|
||||
assert_eq!(
|
||||
rotated_obb_test.untransformed_normal,
|
||||
Vec3::new(0., -1., 0.)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1267,10 +1318,10 @@ pub fn test_oct_x_oct_collisions() {
|
|||
);
|
||||
assert!(x.is_some());
|
||||
|
||||
let mut oct1 = OctTree::new(Vec3::splat(1.), 10);
|
||||
let mut oct1 = OctTree::new(Vec3::splat(10.), 10);
|
||||
oct1.set_voxel_at_location(Vec3::new(1., 0., 1.), 1);
|
||||
let mut oct2 = OctTree::new(Vec3::splat(0.), 10);
|
||||
oct2.set_voxel_at_location(Vec3::new(0., 1., 0.), 1);
|
||||
oct2.set_voxel_at_location(Vec3::new(0., 10., 0.), 1);
|
||||
|
||||
let x = octtree_overlap(
|
||||
&oct1,
|
||||
|
@ -1283,8 +1334,69 @@ pub fn test_oct_x_oct_collisions() {
|
|||
),
|
||||
);
|
||||
assert!(x.is_some());
|
||||
dbg!(&x.unwrap());
|
||||
panic!();
|
||||
let x = x.unwrap();
|
||||
//dbg!(&x);
|
||||
assert_eq!(
|
||||
x[0],
|
||||
(
|
||||
OctTreeCollisionPoint {
|
||||
pos_in_oct: Vec3::new(1.0, 0.0, 1.0,),
|
||||
pos_in_global: Vec3::new(1.0, 0.0, 1.0,),
|
||||
path: Path {
|
||||
packed: 0,
|
||||
length: 0,
|
||||
},
|
||||
},
|
||||
OctTreeCollisionPoint {
|
||||
pos_in_oct: Vec3::new(0.0, 0.0, 0.0,),
|
||||
pos_in_global: Vec3::new(0.0, 0.0, 0.0,),
|
||||
path: Path {
|
||||
packed: 0,
|
||||
length: 0,
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
{
|
||||
let mut oct1 = OctTree::new(Vec3::splat(10.), 10);
|
||||
let mut oct2 = OctTree::new(Vec3::splat(-10.), 10);
|
||||
oct1.set_voxel_at_location(Vec3::splat(1.), 1);
|
||||
oct2.set_voxel_at_location(Vec3::splat(1.), 1);
|
||||
let orient1 = OBB::new(
|
||||
Vec3::splat(5.),
|
||||
Quat::from_rotation_x(f32::to_radians(10.)),
|
||||
Vec3::splat(1.),
|
||||
);
|
||||
let orient2 = OBB::new(
|
||||
Vec3::splat(5.),
|
||||
Quat::from_rotation_x(f32::to_radians(-10.)),
|
||||
Vec3::splat(1.),
|
||||
);
|
||||
let x = octtree_overlap(&oct1, &orient1, &oct2, &orient2);
|
||||
assert!(x.is_some());
|
||||
assert_eq!(
|
||||
x.unwrap()[0],
|
||||
(
|
||||
OctTreeCollisionPoint {
|
||||
pos_in_oct: Vec3::new(1.0, 1.0, 1.0,),
|
||||
pos_in_global: Vec3::new(7.0, 6.622319, 7.3169117,),
|
||||
path: Path {
|
||||
packed: 0,
|
||||
length: 0,
|
||||
},
|
||||
},
|
||||
OctTreeCollisionPoint {
|
||||
pos_in_oct: Vec3::new(1.0, 1.0, 1.0,),
|
||||
pos_in_global: Vec3::new(7.0, 7.3169117, 6.622319,),
|
||||
path: Path {
|
||||
packed: 0,
|
||||
length: 0,
|
||||
},
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
/*
|
||||
use rand::Rng;
|
||||
|
|
Loading…
Reference in a new issue