//! //! Shape composed from the union of primitives. //! use std::ops::Mul; use na; use bounding_volume::{BoundingVolume, AABB}; use partitioning::BVT; use shape::{CompositeShape, Shape, ShapeHandle}; use math::{Isometry, Point}; /// A compound shape with an aabb bounding volume. /// /// A compound shape is a shape composed of the union of several simpler shape. This is /// the main way of creating a concave shape from convex parts. Each parts can have its own /// delta transformation to shift or rotate it with regard to the other shapes. pub struct Compound { shapes: Vec<(M, ShapeHandle)>, bvt: BVT>, bvs: Vec>, } impl Clone for Compound { fn clone(&self) -> Compound { Compound { shapes: self.shapes.clone(), bvt: self.bvt.clone(), bvs: self.bvs.clone(), } } } impl> Compound { /// Builds a new compound shape. pub fn new(shapes: Vec<(M, ShapeHandle)>) -> Compound { let mut bvs = Vec::new(); let mut leaves = Vec::new(); for (i, &(ref delta, ref shape)) in shapes.iter().enumerate() { // loosen for better persistancy let bv = shape.as_ref().aabb(delta).loosened(na::convert(0.04f64)); bvs.push(bv.clone()); leaves.push((i, bv)); } let bvt = BVT::new_balanced(leaves); Compound { shapes: shapes, bvt: bvt, bvs: bvs, } } } impl Compound { /// The shapes of this compound shape. #[inline] pub fn shapes(&self) -> &[(M, ShapeHandle)] { &self.shapes[..] } /// The optimization structure used by this compound shape. #[inline] pub fn bvt(&self) -> &BVT> { &self.bvt } /// The shapes bounding volumes. #[inline] pub fn bounding_volumes(&self) -> &[AABB

] { &self.bvs[..] } /// The AABB of the i-th shape compositing this compound. #[inline] pub fn aabb_at(&self, i: usize) -> &AABB

{ &self.bvs[i] } } impl CompositeShape for Compound where P: Point, M: Clone + Mul, { #[inline(always)] fn map_part_at(&self, i: usize, f: &mut FnMut(&M, &Shape)) { let &(ref m, ref g) = &self.shapes()[i]; f(m, g.as_ref()) } #[inline(always)] fn map_transformed_part_at(&self, i: usize, m: &M, f: &mut FnMut(&M, &Shape)) { let elt = &self.shapes()[i]; f(&(m.clone() * elt.0.clone()), elt.1.as_ref()) } #[inline] fn aabb_at(&self, i: usize) -> AABB

{ self.bounding_volumes()[i].clone() } #[inline] fn bvt(&self) -> &BVT> { self.bvt() } }