Skip to content

Commit

Permalink
Merge pull request #114 from plof27/add-trimesh-plane-intersection
Browse files Browse the repository at this point in the history
Add functionality to intersect a `TriMesh` with a plane
  • Loading branch information
sebcrozet authored Jan 4, 2023
2 parents 9a181df + c48cca3 commit f7db007
Show file tree
Hide file tree
Showing 7 changed files with 441 additions and 4 deletions.
1 change: 1 addition & 0 deletions crates/parry3d/tests/geometry/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ mod cylinder_cuboid_contact;
mod epa3;
mod still_objects_toi;
mod time_of_impact3;
mod trimesh_intersection;
mod trimesh_trimesh_toi;
123 changes: 123 additions & 0 deletions crates/parry3d/tests/geometry/trimesh_intersection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
use na::{Point3, Vector3};
use parry3d::math::{Isometry, Real};
use parry3d::query::IntersectResult;
use parry3d::shape::TriMesh;

fn build_diamond(position: &Isometry<Real>) -> TriMesh {
// Two tetrahedrons sharing a face
let points = vec![
position * Point3::new(0.0, 2.0, 0.0),
position * Point3::new(-2.0, -1.0, 0.0),
position * Point3::new(0.0, 0.0, 2.0),
position * Point3::new(2.0, -1.0, 0.0),
position * Point3::new(0.0, 0.0, -2.0),
];

let indices = vec![
[0u32, 1, 2],
[0, 2, 3],
[1, 2, 3],
[0, 1, 4],
[0, 4, 3],
[1, 4, 3],
];

TriMesh::new(points, indices)
}

#[test]
fn trimesh_plane_edge_intersection() {
let mesh = build_diamond(&Isometry::identity());

let result = mesh.intersection_with_local_plane(&Vector3::ith_axis(2), 0.5, std::f32::EPSILON);

assert!(matches!(result, IntersectResult::Intersect(_)));

if let IntersectResult::Intersect(line) = result {
// Need to check points individually since order is not garunteed
let vertices = line.vertices();
assert_eq!(vertices.len(), 3);
assert!(vertices.contains(&Point3::new(-1.5, -0.75, 0.5)));
assert!(vertices.contains(&Point3::new(1.5, -0.75, 0.5)));
assert!(vertices.contains(&Point3::new(0.0, 1.5, 0.5)));
}
}

#[test]
fn trimesh_plane_vertex_intersection() {
let mesh = build_diamond(&Isometry::identity());

let result = mesh.intersection_with_local_plane(&Vector3::ith_axis(2), 0.0, std::f32::EPSILON);

assert!(matches!(result, IntersectResult::Intersect(_)));

if let IntersectResult::Intersect(line) = result {
// Need to check points individually since order is not garunteed
let vertices = line.vertices();
assert_eq!(vertices.len(), 3);
assert!(vertices.contains(&Point3::new(-2.0, -1.0, 0.0)));
assert!(vertices.contains(&Point3::new(2.0, -1.0, 0.0)));
assert!(vertices.contains(&Point3::new(0.0, 2.0, 0.0)));
}
}

#[test]
fn trimesh_plane_mixed_intersection() {
let mesh = build_diamond(&Isometry::identity());

let result = mesh.intersection_with_local_plane(&Vector3::ith_axis(0), 0.0, std::f32::EPSILON);

assert!(matches!(result, IntersectResult::Intersect(_)));

if let IntersectResult::Intersect(line) = result {
// Need to check points individually since order is not garunteed
let vertices = line.vertices();
assert_eq!(vertices.len(), 4);
assert!(vertices.contains(&Point3::new(0.0, 2.0, 0.0)));
assert!(vertices.contains(&Point3::new(0.0, 0.0, 2.0)));
assert!(vertices.contains(&Point3::new(0.0, -1.0, 0.0)));
assert!(vertices.contains(&Point3::new(0.0, 0.0, -2.0)));
}
}

#[test]
fn trimesh_plane_multi_intersection() {
let mut mesh = build_diamond(&Isometry::identity());
mesh.append(&build_diamond(&Isometry::translation(-5.0, 0.0, 0.0)));

let result = mesh.intersection_with_local_plane(&Vector3::ith_axis(2), 0.5, std::f32::EPSILON);

assert!(matches!(result, IntersectResult::Intersect(_)));

if let IntersectResult::Intersect(line) = result {
// Need to check points individually since order is not garunteed
let vertices = line.vertices();
assert_eq!(vertices.len(), 6);

assert!(vertices.contains(&Point3::new(-1.5, -0.75, 0.5)));
assert!(vertices.contains(&Point3::new(1.5, -0.75, 0.5)));
assert!(vertices.contains(&Point3::new(0.0, 1.5, 0.5)));

assert!(vertices.contains(&Point3::new(-6.5, -0.75, 0.5)));
assert!(vertices.contains(&Point3::new(-3.5, -0.75, 0.5)));
assert!(vertices.contains(&Point3::new(-5.0, 1.5, 0.5)));
}
}

#[test]
fn trimesh_plane_above() {
let mesh = build_diamond(&Isometry::identity());

let result = mesh.intersection_with_local_plane(&Vector3::ith_axis(2), -5.0, std::f32::EPSILON);

assert!(matches!(result, IntersectResult::Positive));
}

#[test]
fn trimesh_plane_below() {
let mesh = build_diamond(&Isometry::identity());

let result = mesh.intersection_with_local_plane(&Vector3::ith_axis(2), 5.0, std::f32::EPSILON);

assert!(matches!(result, IntersectResult::Negative));
}
2 changes: 1 addition & 1 deletion src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub use self::point::{PointProjection, PointQuery, PointQueryWithLocation};
pub use self::query_dispatcher::PersistentQueryDispatcher;
pub use self::query_dispatcher::{QueryDispatcher, QueryDispatcherChain};
pub use self::ray::{Ray, RayCast, RayIntersection, SimdRay};
pub use self::split::SplitResult;
pub use self::split::{IntersectResult, SplitResult};
pub use self::time_of_impact::{time_of_impact, TOIStatus, TOI};

mod clip;
Expand Down
2 changes: 1 addition & 1 deletion src/query/split/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub use self::split::SplitResult;
pub use self::split::{IntersectResult, SplitResult};

mod split;
mod split_aabb;
Expand Down
10 changes: 10 additions & 0 deletions src/query/split/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,13 @@ pub enum SplitResult<T> {
/// The shape being split is fully contained in the positive half-space of the plane.
Positive,
}

/// The result of a plane-intersection operation.
pub enum IntersectResult<T> {
/// The intersect operation yielded a result, lying in the plane
Intersect(T),
/// The shape being intersected is fully contained in the negative half-space of the plane.
Negative,
/// The shape being intersected is fully contained in the positive half-space of the plane.
Positive,
}
Loading

0 comments on commit f7db007

Please sign in to comment.