use alga::general::Id; use bounding_volume::AABB; use shape::Compound; use partitioning::BVTCostFn; use query::{Ray, RayCast, RayIntersection}; use math::{Isometry, Point}; // XXX: if solid == false, this might return internal intersection. impl> RayCast for Compound { fn toi_with_ray(&self, m: &M, ray: &Ray

, solid: bool) -> Option { let ls_ray = ray.inverse_transform_by(m); let mut cost_fn = CompoundRayToiCostFn { compound: self, ray: &ls_ray, solid: solid, }; self.bvt() .best_first_search(&mut cost_fn) .map(|(_, res)| res) } fn toi_and_normal_with_ray( &self, m: &M, ray: &Ray

, solid: bool, ) -> Option> { let ls_ray = ray.inverse_transform_by(m); let mut cost_fn = CompoundRayToiAndNormalCostFn { compound: self, ray: &ls_ray, solid: solid, }; self.bvt() .best_first_search(&mut cost_fn) .map(|(_, mut res)| { res.normal = m.rotate_vector(&res.normal); res }) } // XXX: We have to implement toi_and_normal_and_uv_with_ray! Otherwise, no uv will be computed // for any of the sub-shapes. } /* * Costs functions. */ struct CompoundRayToiCostFn<'a, P: 'a + Point, M: 'a> { compound: &'a Compound, ray: &'a Ray

, solid: bool, } impl<'a, P, M> BVTCostFn> for CompoundRayToiCostFn<'a, P, M> where P: Point, M: Isometry

, { type UserData = P::Real; #[inline] fn compute_bv_cost(&mut self, aabb: &AABB

) -> Option { aabb.toi_with_ray(&Id::new(), self.ray, self.solid) } #[inline] fn compute_b_cost(&mut self, b: &usize) -> Option<(P::Real, P::Real)> { let elt = &self.compound.shapes()[*b]; elt.1 .toi_with_ray(&elt.0, self.ray, self.solid) .map(|toi| (toi, toi)) } } struct CompoundRayToiAndNormalCostFn<'a, P: 'a + Point, M: 'a> { compound: &'a Compound, ray: &'a Ray

, solid: bool, } impl<'a, P: Point, M: Isometry

> BVTCostFn> for CompoundRayToiAndNormalCostFn<'a, P, M> { type UserData = RayIntersection; #[inline] fn compute_bv_cost(&mut self, aabb: &AABB

) -> Option { aabb.toi_with_ray(&Id::new(), self.ray, self.solid) } #[inline] fn compute_b_cost(&mut self, b: &usize) -> Option<(P::Real, RayIntersection)> { let elt = &self.compound.shapes()[*b]; elt.1 .toi_and_normal_with_ray(&elt.0, self.ray, self.solid) .map(|inter| (inter.toi, inter)) } }