use na::{Identity, Translate, Rotate, Transform}; use na; use geometry::algorithms::gjk; use geometry::algorithms::simplex::Simplex; use geometry::algorithms::johnson_simplex::JohnsonSimplex; use entities::shape::{MinkowskiSum, Segment, Cylinder, Cone, Capsule, ConvexHull}; use entities::support_map::SupportMap; use ray::{Ray, RayCast, RayIntersection}; use math::{Point, Vector}; /// 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 na::is_zero(&toi) {
// 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::cast(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.as_vector()));
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< + Translate + Rotate , solid: bool) -> Option ::new_w_tls(), &ls_ray,
solid).map(|mut res| {
res.normal = m.rotate(&res.normal);
res
})
}
}
impl RayCast for Cone< + Translate + Rotate , solid: bool) -> Option ::new_w_tls(), &ls_ray,
solid).map(|mut res| {
res.normal = m.rotate(&res.normal);
res
})
}
}
impl RayCast for Capsule< + Translate + Rotate , solid: bool) -> Option ::new_w_tls(), &ls_ray,
solid).map(|mut res| {
res.normal = m.rotate(&res.normal);
res
})
}
}
impl RayCast for ConvexHull
where P: Point,
M: Transform + Translate + Rotate , solid: bool) -> Option ::new_w_tls(), &ls_ray,
solid).map(|mut res| {
res.normal = m.rotate(&res.normal);
res
})
}
}
impl RayCast for Segment
where P: Point,
M: Transform + Translate + Rotate , solid: bool) -> Option () == 2
let ls_ray = Ray::new(m.inverse_transform(&ray.origin), m.inverse_rotate(&ray.dir));
implicit_toi_and_normal_with_ray(&Identity::new(), self,
&mut JohnsonSimplex:: ::new_w_tls(), &ls_ray,
solid).map(|mut res| {
res.normal = m.rotate(&res.normal);
res
})
}
}
impl<'a, P, M, M2, G1: ?Sized, G2: ?Sized> RayCast for MinkowskiSum<'a, M, G1, G2>
where P: Point,
M2: Transform + Translate + Rotate ,
G2: SupportMap {
fn toi_and_normal_with_ray(&self, m: &M2, ray: &Ray , solid: bool) -> Option () == 2
let ls_ray = Ray::new(m.inverse_transform(&ray.origin), m.inverse_rotate(&ray.dir));
implicit_toi_and_normal_with_ray(&Identity::new(), self,
&mut JohnsonSimplex:: ::new_w_tls(), &ls_ray,
solid).map(|mut res| {
res.normal = m.rotate(&res.normal);
res
})
}
}