use num::Zero; use alga::general::Id; use na; use query::algorithms::gjk; use query::algorithms::{Simplex, JohnsonSimplex, VoronoiSimplex2, VoronoiSimplex3}; use query::{Ray, RayCast, RayIntersection}; use shape::{Capsule, Cone, ConvexHull, Cylinder, MinkowskiSum, Segment, SupportMap}; use math::{Isometry, Point}; /// Cast a ray on a shape using the GJK algorithm. pub fn implicit_toi_and_normal_with_ray
( m: &M, shape: &G, simplex: &mut S, ray: &Ray
,
solid: bool,
) -> Option ,
S: Simplex ,
G: SupportMap ,
{
let inter = gjk::cast_ray(m, shape, simplex, ray);
if !solid {
match inter {
None => None,
Some((toi, normal)) => {
if toi.is_zero() {
// the ray is inside of the shape.
let ndir = na::normalize(&ray.dir);
let supp = shape.support_point(m, &ndir);
let shift = na::dot(&(supp - ray.origin), &ndir) + na::convert(0.001f64);
let new_ray = Ray::new(ray.origin + ndir * shift, -ray.dir);
// FIXME: replace by? : simplex.translate_by(&(ray.origin - new_ray.origin));
simplex.reset(supp + (-new_ray.origin.coordinates()));
gjk::cast_ray(m, shape, simplex, &new_ray)
.map(|(toi, normal)| RayIntersection::new(shift - toi, normal))
} else {
Some(RayIntersection::new(toi, normal))
}
}
}
} else {
inter.map(|(toi, normal)| RayIntersection::new(toi, normal))
}
}
impl RayCast for Cylinder ,
{
fn toi_and_normal_with_ray(
&self,
m: &M,
ray: &Ray ,
solid: bool,
) -> Option ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else if na::dimension:: ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else {
implicit_toi_and_normal_with_ray(
&Id::new(),
self,
&mut JohnsonSimplex:: ::new_w_tls(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
}
}
}
impl RayCast for Cone ,
{
fn toi_and_normal_with_ray(
&self,
m: &M,
ray: &Ray ,
solid: bool,
) -> Option ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else if na::dimension:: ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else {
implicit_toi_and_normal_with_ray(
&Id::new(),
self,
&mut JohnsonSimplex:: ::new_w_tls(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
}
}
}
impl RayCast for Capsule ,
{
fn toi_and_normal_with_ray(
&self,
m: &M,
ray: &Ray ,
solid: bool,
) -> Option ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else if na::dimension:: ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else {
implicit_toi_and_normal_with_ray(
&Id::new(),
self,
&mut JohnsonSimplex:: ::new_w_tls(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
}
}
}
impl RayCast for ConvexHull
where
P: Point,
M: Isometry ,
{
fn toi_and_normal_with_ray(
&self,
m: &M,
ray: &Ray ,
solid: bool,
) -> Option ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else if na::dimension:: ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else {
implicit_toi_and_normal_with_ray(
&Id::new(),
self,
&mut JohnsonSimplex:: ::new_w_tls(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
}
}
}
impl RayCast for Segment
where
P: Point,
M: Isometry ,
{
fn toi_and_normal_with_ray(
&self,
m: &M,
ray: &Ray ,
solid: bool,
) -> Option () == 2
let ls_ray = ray.inverse_transform_by(m);
if na::dimension:: ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else if na::dimension:: ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else {
implicit_toi_and_normal_with_ray(
&Id::new(),
self,
&mut JohnsonSimplex:: ::new_w_tls(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
}
}
}
impl<'a, P, M, M2, G1: ?Sized, G2: ?Sized> RayCast for MinkowskiSum<'a, M, G1, G2>
where
P: Point,
M2: Isometry ,
G1: SupportMap ,
G2: SupportMap ,
{
fn toi_and_normal_with_ray(
&self,
m: &M2,
ray: &Ray ,
solid: bool,
) -> Option ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else if na::dimension:: ::new(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
} else {
implicit_toi_and_normal_with_ray(
&Id::new(),
self,
&mut JohnsonSimplex:: ::new_w_tls(),
&ls_ray,
solid,
).map(|mut res| {
res.normal = m.rotate_vector(&res.normal);
res
})
}
}
}