Skip to content

Commit 7ac46f6

Browse files
committed
- fix ray vs capsule case where the ray intersects the end spheres
1 parent e3d4896 commit 7ac46f6

File tree

2 files changed

+40
-46
lines changed

2 files changed

+40
-46
lines changed

src/lib.rs

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -978,10 +978,10 @@ pub fn ray_vs_triangle<T: Float>(r0: Vec3<T>, rv: Vec3<T>, t0: Vec3<T>, t1: Vec3
978978
pub fn ray_vs_capsule<T: Float + FloatOps<T> + NumberOps<T> + SignedNumberOps<T>, V: VecN<T> + Cross<T> + VecFloatOps<T> + SignedNumberOps<T> + FloatOps<T>>(r0: V, rv: V, c0: V, c1: V, cr: T) -> Option<V> {
979979
// shortest line seg within radius will indicate we intersect an infinite cylinder about an axis
980980
let seg = shortest_line_segment_between_line_and_line_segment(r0, r0 + rv, c0, c1);
981+
let mut ipc = V::max_value();
982+
let mut bc = false;
981983
if let Some((l0, l1)) = seg {
982984
// check we intesect the cylinder
983-
let mut ipc = V::max_value();
984-
let mut bc = false;
985985
if dist2(l0, l1) < sqr(cr) {
986986
// intesection of ray and infinite cylinder about axis
987987
// https://stackoverflow.com/questions/4078401/trying-to-optimize-line-vs-cylinder-intersection
@@ -1014,50 +1014,47 @@ pub fn ray_vs_capsule<T: Float + FloatOps<T> + NumberOps<T> + SignedNumberOps<T>
10141014
}
10151015
}
10161016
}
1017+
}
10171018

1018-
// if our line doesnt intersect the cylinder, we might still intersect the top / bottom sphere
1019-
// test intersections with the end spheres
1020-
let bs1 = ray_vs_sphere(r0, rv, c0, cr);
1021-
let bs2 = ray_vs_sphere(r0, rv, c1, cr);
1019+
// if our line doesnt intersect the cylinder, we might still intersect the top / bottom sphere
1020+
// test intersections with the end spheres
1021+
let bs1 = ray_vs_sphere(r0, rv, c0, cr);
1022+
let bs2 = ray_vs_sphere(r0, rv, c1, cr);
10221023

1023-
// get optional intersection points
1024-
let ips1 = if let Some(ip) = bs1 {
1025-
ip
1026-
}
1027-
else {
1028-
V::max_value()
1029-
};
1024+
// get optional intersection points
1025+
let ips1 = if let Some(ip) = bs1 {
1026+
ip
1027+
}
1028+
else {
1029+
V::max_value()
1030+
};
10301031

1031-
let ips2 = if let Some(ip) = bs2 {
1032-
ip
1033-
}
1034-
else {
1035-
V::max_value()
1036-
};
1032+
let ips2 = if let Some(ip) = bs2 {
1033+
ip
1034+
}
1035+
else {
1036+
V::max_value()
1037+
};
10371038

1038-
// we need to choose the closes intersection if we have multiple
1039-
let ips : [V; 3] = [ips1, ips2, ipc];
1040-
let bips : [bool; 3] = [bs1.is_some(), bs2.is_some(), bc];
1041-
1042-
let mut iclosest = -1;
1043-
let mut dclosest = T::max_value();
1044-
for i in 0..3 {
1045-
if bips[i] {
1046-
let dd = distance_on_line(ips[i], r0, r0 + rv);
1047-
if dd < dclosest {
1048-
iclosest = i as i32;
1049-
dclosest = dd;
1050-
}
1039+
// we need to choose the closes intersection if we have multiple
1040+
let ips : [V; 3] = [ips1, ips2, ipc];
1041+
let bips : [bool; 3] = [bs1.is_some(), bs2.is_some(), bc];
1042+
1043+
let mut iclosest = -1;
1044+
let mut dclosest = T::max_value();
1045+
for i in 0..3 {
1046+
if bips[i] {
1047+
let dd = distance_on_line(ips[i], r0, r0 + rv);
1048+
if dd < dclosest {
1049+
iclosest = i as i32;
1050+
dclosest = dd;
10511051
}
10521052
}
1053+
}
10531054

1054-
// if we have a valid closest point
1055-
if iclosest != -1 {
1056-
Some(ips[iclosest as usize])
1057-
}
1058-
else {
1059-
None
1060-
}
1055+
// if we have a valid closest point
1056+
if iclosest != -1 {
1057+
Some(ips[iclosest as usize])
10611058
}
10621059
else {
10631060
None

tests/tests.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3314,11 +3314,9 @@ fn ray_vs_capsule_test() {
33143314
let cp0 = vec3f(-0.230000, -5.680000, -7.720000);
33153315
let cp1 = vec3f(-0.230000, 13.840000, -7.720000);
33163316
let cr = 9.760000;
3317-
let _i = ray_vs_capsule(r0, rv, cp0, cp1, cr);
3318-
3319-
// TODO; this is working in the C++ lib but not here
3320-
// assert_eq!(i.is_some(), true);
3321-
// assert_eq!(approx(i.unwrap(), vec3f(-0.230000, -15.440001, -7.720000), 0.001), true);
3317+
let i = ray_vs_capsule(r0, rv, cp0, cp1, cr);
3318+
assert_eq!(i.is_some(), true);
3319+
assert_eq!(approx(i.unwrap(), vec3f(-0.230000, -15.440001, -7.720000), 0.001), true);
33223320
}
33233321
{
33243322
let r0 = vec3f(-10.537001, -20.226603, -5.503001);
@@ -3400,9 +3398,8 @@ fn ray_vs_capsule_test() {
34003398
}
34013399

34023400
// TODO:
3403-
// edge case ray vs capsule!
3404-
// sphere_vs_capsule
34053401
// ray_vs_cylinder
3402+
// sphere_vs_capsule
34063403
// point_sphere_distance
34073404
// ray_vs_line_segment
34083405
// shortest_line_segment_between_line_segments

0 commit comments

Comments
 (0)