use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle}; use crate::geometry::{ ActiveCollisionTypes, ColliderBroadPhaseData, ColliderChanges, ColliderFlags, ColliderMassProperties, ColliderParent, ColliderPosition, ColliderShape, ColliderType, Friction, InteractionGroups, Restitution, SharedShape, }; use crate::math::*; use crate::parry::transformation::vhacd::VHACDParameters; use crate::pipeline::{ActiveEvents, ActiveHooks}; use crate::prelude::ColliderEnabled; use parry::bounding_volume::Aabb; use parry::shape::{Shape, TriMeshFlags}; #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[derive(Clone)] /// A geometric entity that can be attached to a body so it can be affected by contacts and proximity queries. /// /// To build a new collider, use the [`ColliderBuilder`] structure. pub struct Collider { pub(crate) coll_type: ColliderType, pub(crate) shape: ColliderShape, pub(crate) mprops: ColliderMassProperties, pub(crate) changes: ColliderChanges, pub(crate) parent: Option, pub(crate) pos: ColliderPosition, pub(crate) friction: Friction, pub(crate) restitution: Restitution, pub(crate) flags: ColliderFlags, pub(crate) bf_data: ColliderBroadPhaseData, contact_force_event_threshold: Real, /// User-defined data associated to this collider. pub user_data: u128, } impl Collider { pub(crate) fn reset_internal_references(&mut self) { self.bf_data.proxy_index = crate::INVALID_U32; self.changes = ColliderChanges::all(); } pub(crate) fn effective_contact_force_event_threshold(&self) -> Real { if self .flags .active_events .contains(ActiveEvents::CONTACT_FORCE_EVENTS) { self.contact_force_event_threshold } else { Real::MAX } } /// The rigid body this collider is attached to. pub fn parent(&self) -> Option { self.parent.map(|parent| parent.handle) } /// Is this collider a sensor? pub fn is_sensor(&self) -> bool { self.coll_type.is_sensor() } /// The physics hooks enabled for this collider. pub fn active_hooks(&self) -> ActiveHooks { self.flags.active_hooks } /// Sets the physics hooks enabled for this collider. pub fn set_active_hooks(&mut self, active_hooks: ActiveHooks) { self.flags.active_hooks = active_hooks; } /// The events enabled for this collider. pub fn active_events(&self) -> ActiveEvents { self.flags.active_events } /// Sets the events enabled for this collider. pub fn set_active_events(&mut self, active_events: ActiveEvents) { self.flags.active_events = active_events; } /// The collision types enabled for this collider. pub fn active_collision_types(&self) -> ActiveCollisionTypes { self.flags.active_collision_types } /// Sets the collision types enabled for this collider. pub fn set_active_collision_types(&mut self, active_collision_types: ActiveCollisionTypes) { self.flags.active_collision_types = active_collision_types; } /// The friction coefficient of this collider. pub fn friction(&self) -> Real { self.friction.coefficient } /// Sets the friction coefficient of this collider. pub fn set_friction(&mut self, coefficient: Real) { self.friction.coefficient = coefficient } /// The combine rule used by this collider to combine its friction /// coefficient with the friction coefficient of the other collider it /// is in contact with. pub fn friction_combine_rule(&self) -> CoefficientCombineRule { self.friction.combine_rule } /// Sets the combine rule used by this collider to combine its friction /// coefficient with the friction coefficient of the other collider it /// is in contact with. pub fn set_friction_combine_rule(&mut self, rule: CoefficientCombineRule) { self.friction.combine_rule = rule; } /// The restitution coefficient of this collider. pub fn restitution(&self) -> Real { self.restitution.coefficient } /// Sets the restitution coefficient of this collider. pub fn set_restitution(&mut self, coefficient: Real) { self.restitution.coefficient = coefficient } /// The combine rule used by this collider to combine its restitution /// coefficient with the restitution coefficient of the other collider it /// is in contact with. pub fn restitution_combine_rule(&self) -> CoefficientCombineRule { self.restitution.combine_rule } /// Sets the combine rule used by this collider to combine its restitution /// coefficient with the restitution coefficient of the other collider it /// is in contact with. pub fn set_restitution_combine_rule(&mut self, rule: CoefficientCombineRule) { self.restitution.combine_rule = rule; } /// Sets the total force magnitude beyond which a contact force event can be emitted. pub fn set_contact_force_event_threshold(&mut self, threshold: Real) { self.contact_force_event_threshold = threshold; } /// Sets whether or not this is a sensor collider. pub fn set_sensor(&mut self, is_sensor: bool) { if is_sensor != self.is_sensor() { self.changes.insert(ColliderChanges::TYPE); self.coll_type = if is_sensor { ColliderType::Sensor } else { ColliderType::Solid }; } } /// Is this collider enabled? pub fn is_enabled(&self) -> bool { matches!(self.flags.enabled, ColliderEnabled::Enabled) } /// Sets whether or not this collider is enabled. pub fn set_enabled(&mut self, enabled: bool) { match self.flags.enabled { ColliderEnabled::Enabled | ColliderEnabled::DisabledByParent => { if !enabled { self.changes.insert(ColliderChanges::ENABLED_OR_DISABLED); self.flags.enabled = ColliderEnabled::Disabled; } } ColliderEnabled::Disabled => { if enabled { self.changes.insert(ColliderChanges::ENABLED_OR_DISABLED); self.flags.enabled = ColliderEnabled::Enabled; } } } } /// Sets the translational part of this collider's position. pub fn set_translation(&mut self, translation: Vector) { self.changes.insert(ColliderChanges::POSITION); *self.pos.0.translation.as_vector_mut() = translation; } /// Sets the rotational part of this collider's position. pub fn set_rotation(&mut self, rotation: Rotation) { self.changes.insert(ColliderChanges::POSITION); self.pos.0.rotation = rotation; } /// Sets the position of this collider. pub fn set_position(&mut self, position: Isometry) { self.changes.insert(ColliderChanges::POSITION); self.pos.0 = position; } /// The world-space position of this collider. pub fn position(&self) -> &Isometry { &self.pos } /// The translational part of this collider's position. pub fn translation(&self) -> Vector { self.pos.0.translation.into_vector() } /// The rotational part of this collider's position. pub fn rotation(&self) -> &Rotation { &self.pos.0.rotation } /// The position of this collider with respect to the body it is attached to. pub fn position_wrt_parent(&self) -> Option<&Isometry> { self.parent.as_ref().map(|p| &p.pos_wrt_parent) } /// Sets the translational part of this collider's translation relative to its parent rigid-body. pub fn set_translation_wrt_parent(&mut self, translation: Vector) { if let Some(parent) = self.parent.as_mut() { self.changes.insert(ColliderChanges::PARENT); *parent.pos_wrt_parent.translation.as_vector_mut() = translation; } } /// Sets the rotational part of this collider's rotaiton relative to its parent rigid-body. pub fn set_rotation_wrt_parent(&mut self, rotation: AngVector) { if let Some(parent) = self.parent.as_mut() { self.changes.insert(ColliderChanges::PARENT); parent.pos_wrt_parent.rotation = Rotation::from_scaled_axis(rotation.into()); } } /// Sets the position of this collider with respect to its parent rigid-body. /// /// Does nothing if the collider is not attached to a rigid-body. pub fn set_position_wrt_parent(&mut self, pos_wrt_parent: Isometry) { if let Some(parent) = self.parent.as_mut() { self.changes.insert(ColliderChanges::PARENT); parent.pos_wrt_parent = pos_wrt_parent; } } /// The collision groups used by this collider. pub fn collision_groups(&self) -> InteractionGroups { self.flags.collision_groups } /// Sets the collision groups of this collider. pub fn set_collision_groups(&mut self, groups: InteractionGroups) { if self.flags.collision_groups != groups { self.changes.insert(ColliderChanges::GROUPS); self.flags.collision_groups = groups; } } /// The solver groups used by this collider. pub fn solver_groups(&self) -> InteractionGroups { self.flags.solver_groups } /// Sets the solver groups of this collider. pub fn set_solver_groups(&mut self, groups: InteractionGroups) { if self.flags.solver_groups != groups { self.changes.insert(ColliderChanges::GROUPS); self.flags.solver_groups = groups; } } /// The volume (or surface in 2D) of this collider. pub fn volume(&self) -> Real { self.shape.mass_properties(1.0).mass() } /// The density of this collider. pub fn density(&self) -> Real { match &self.mprops { ColliderMassProperties::Density(density) => *density, ColliderMassProperties::Mass(mass) => { let inv_volume = self.shape.mass_properties(1.0).inv_mass; mass * inv_volume } ColliderMassProperties::MassProperties(mprops) => { let inv_volume = self.shape.mass_properties(1.0).inv_mass; mprops.mass() * inv_volume } } } /// The mass of this collider. pub fn mass(&self) -> Real { match &self.mprops { ColliderMassProperties::Density(density) => self.shape.mass_properties(*density).mass(), ColliderMassProperties::Mass(mass) => *mass, ColliderMassProperties::MassProperties(mprops) => mprops.mass(), } } /// Sets the uniform density of this collider. /// /// This will override any previous mass-properties set by [`Self::set_density`], /// [`Self::set_mass`], [`Self::set_mass_properties`], [`ColliderBuilder::density`], /// [`ColliderBuilder::mass`], or [`ColliderBuilder::mass_properties`] /// for this collider. /// /// The mass and angular inertia of this collider will be computed automatically based on its /// shape. pub fn set_density(&mut self, density: Real) { self.do_set_mass_properties(ColliderMassProperties::Density(density)); } /// Sets the mass of this collider. /// /// This will override any previous mass-properties set by [`Self::set_density`], /// [`Self::set_mass`], [`Self::set_mass_properties`], [`ColliderBuilder::density`], /// [`ColliderBuilder::mass`], or [`ColliderBuilder::mass_properties`] /// for this collider. /// /// The angular inertia of this collider will be computed automatically based on its shape /// and this mass value. pub fn set_mass(&mut self, mass: Real) { self.do_set_mass_properties(ColliderMassProperties::Mass(mass)); } /// Sets the mass properties of this collider. /// /// This will override any previous mass-properties set by [`Self::set_density`], /// [`Self::set_mass`], [`Self::set_mass_properties`], [`ColliderBuilder::density`], /// [`ColliderBuilder::mass`], or [`ColliderBuilder::mass_properties`] /// for this collider. pub fn set_mass_properties(&mut self, mass_properties: MassProperties) { self.do_set_mass_properties(ColliderMassProperties::MassProperties(Box::new( mass_properties, ))) } fn do_set_mass_properties(&mut self, mprops: ColliderMassProperties) { if mprops != self.mprops { self.changes |= ColliderChanges::LOCAL_MASS_PROPERTIES; self.mprops = mprops; } } /// The geometric shape of this collider. pub fn shape(&self) -> &dyn Shape { self.shape.as_ref() } /// A mutable reference to the geometric shape of this collider. /// /// If that shape is shared by multiple colliders, it will be /// cloned first so that `self` contains a unique copy of that /// shape that you can modify. pub fn shape_mut(&mut self) -> &mut dyn Shape { self.changes.insert(ColliderChanges::SHAPE); self.shape.make_mut() } /// Sets the shape of this collider. pub fn set_shape(&mut self, shape: SharedShape) { self.changes.insert(ColliderChanges::SHAPE); self.shape = shape; } /// Retrieve the SharedShape. Also see the `shape()` function pub fn shared_shape(&self) -> &SharedShape { &self.shape } /// Compute the axis-aligned bounding box of this collider. pub fn compute_aabb(&self) -> Aabb { self.shape.compute_aabb(&self.pos) } /// Compute the axis-aligned bounding box of this collider moving from its current position /// to the given `next_position` pub fn compute_swept_aabb(&self, next_position: &Isometry) -> Aabb { self.shape.compute_swept_aabb(&self.pos, next_position) } /// Compute the local-space mass properties of this collider. pub fn mass_properties(&self) -> MassProperties { self.mprops.mass_properties(&*self.shape) } /// The total force magnitude beyond which a contact force event can be emitted. pub fn contact_force_event_threshold(&self) -> Real { self.contact_force_event_threshold } } /// A structure responsible for building a new collider. #[derive(Clone)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[must_use = "Builder functions return the updated builder"] pub struct ColliderBuilder { /// The shape of the collider to be built. pub shape: SharedShape, /// Controls the way the collider’s mass-properties are computed. pub mass_properties: ColliderMassProperties, /// The friction coefficient of the collider to be built. pub friction: Real, /// The rule used to combine two friction coefficients. pub friction_combine_rule: CoefficientCombineRule, /// The restitution coefficient of the collider to be built. pub restitution: Real, /// The rule used to combine two restitution coefficients. pub restitution_combine_rule: CoefficientCombineRule, /// The position of this collider. pub position: Isometry, /// Is this collider a sensor? pub is_sensor: bool, /// Contact pairs enabled for this collider. pub active_collision_types: ActiveCollisionTypes, /// Physics hooks enabled for this collider. pub active_hooks: ActiveHooks, /// Events enabled for this collider. pub active_events: ActiveEvents, /// The user-data of the collider being built. pub user_data: u128, /// The collision groups for the collider being built. pub collision_groups: InteractionGroups, /// The solver groups for the collider being built. pub solver_groups: InteractionGroups, /// Will the collider being built be enabled? pub enabled: bool, /// The total force magnitude beyond which a contact force event can be emitted. pub contact_force_event_threshold: Real, } impl ColliderBuilder { /// Initialize a new collider builder with the given shape. pub fn new(shape: SharedShape) -> Self { Self { shape, mass_properties: ColliderMassProperties::default(), friction: Self::default_friction(), restitution: 0.0, position: Isometry::identity(), is_sensor: false, user_data: 0, collision_groups: InteractionGroups::all(), solver_groups: InteractionGroups::all(), friction_combine_rule: CoefficientCombineRule::Average, restitution_combine_rule: CoefficientCombineRule::Average, active_collision_types: ActiveCollisionTypes::default(), active_hooks: ActiveHooks::empty(), active_events: ActiveEvents::empty(), enabled: true, contact_force_event_threshold: 0.0, } } /// Initialize a new collider builder with a compound shape. pub fn compound(shapes: Vec<(Isometry, SharedShape)>) -> Self { Self::new(SharedShape::compound(shapes)) } /// Initialize a new collider builder with a ball shape defined by its radius. pub fn ball(radius: Real) -> Self { Self::new(SharedShape::ball(radius)) } /// Initialize a new collider build with a half-space shape defined by the outward normal /// of its planar boundary. pub fn halfspace(outward_normal: UnitVector) -> Self { Self::new(SharedShape::halfspace(outward_normal)) } /// Initialize a new collider builder with a cylindrical shape defined by its half-height /// (along along the y axis) and its radius. #[cfg(feature = "dim3")] pub fn cylinder(half_height: Real, radius: Real) -> Self { Self::new(SharedShape::cylinder(half_height, radius)) } /// Initialize a new collider builder with a rounded cylindrical shape defined by its half-height /// (along along the y axis), its radius, and its roundedness (the /// radius of the sphere used for dilating the cylinder). #[cfg(feature = "dim3")] pub fn round_cylinder(half_height: Real, radius: Real, border_radius: Real) -> Self { Self::new(SharedShape::round_cylinder( half_height, radius, border_radius, )) } /// Initialize a new collider builder with a cone shape defined by its half-height /// (along along the y axis) and its basis radius. #[cfg(feature = "dim3")] pub fn cone(half_height: Real, radius: Real) -> Self { Self::new(SharedShape::cone(half_height, radius)) } /// Initialize a new collider builder with a rounded cone shape defined by its half-height /// (along along the y axis), its radius, and its roundedness (the /// radius of the sphere used for dilating the cylinder). #[cfg(feature = "dim3")] pub fn round_cone(half_height: Real, radius: Real, border_radius: Real) -> Self { Self::new(SharedShape::round_cone(half_height, radius, border_radius)) } /// Initialize a new collider builder with a cuboid shape defined by its half-extents. #[cfg(feature = "dim2")] pub fn cuboid(hx: Real, hy: Real) -> Self { Self::new(SharedShape::cuboid(hx, hy)) } /// Initialize a new collider builder with a round cuboid shape defined by its half-extents /// and border radius. #[cfg(feature = "dim2")] pub fn round_cuboid(hx: Real, hy: Real, border_radius: Real) -> Self { Self::new(SharedShape::round_cuboid(hx, hy, border_radius)) } /// Initialize a new collider builder with a capsule shape aligned with the `x` axis. pub fn capsule_x(half_height: Real, radius: Real) -> Self { Self::new(SharedShape::capsule_x(half_height, radius)) } /// Initialize a new collider builder with a capsule shape aligned with the `y` axis. pub fn capsule_y(half_height: Real, radius: Real) -> Self { Self::new(SharedShape::capsule_y(half_height, radius)) } /// Initialize a new collider builder with a capsule shape aligned with the `z` axis. #[cfg(feature = "dim3")] pub fn capsule_z(half_height: Real, radius: Real) -> Self { Self::new(SharedShape::capsule_z(half_height, radius)) } /// Initialize a new collider builder with a cuboid shape defined by its half-extents. #[cfg(feature = "dim3")] pub fn cuboid(hx: Real, hy: Real, hz: Real) -> Self { Self::new(SharedShape::cuboid(hx, hy, hz)) } /// Initialize a new collider builder with a round cuboid shape defined by its half-extents /// and border radius. #[cfg(feature = "dim3")] pub fn round_cuboid(hx: Real, hy: Real, hz: Real, border_radius: Real) -> Self { Self::new(SharedShape::round_cuboid(hx, hy, hz, border_radius)) } /// Initializes a collider builder with a segment shape. pub fn segment(a: Point, b: Point) -> Self { Self::new(SharedShape::segment(a, b)) } /// Initializes a collider builder with a triangle shape. pub fn triangle(a: Point, b: Point, c: Point) -> Self { Self::new(SharedShape::triangle(a, b, c)) } /// Initializes a collider builder with a triangle shape with round corners. pub fn round_triangle(a: Point, b: Point, c: Point, border_radius: Real) -> Self { Self::new(SharedShape::round_triangle(a, b, c, border_radius)) } /// Initializes a collider builder with a polyline shape defined by its vertex and index buffers. pub fn polyline(vertices: Vec, indices: Option>) -> Self { Self::new(SharedShape::polyline(vertices, indices)) } /// Initializes a collider builder with a triangle mesh shape defined by its vertex and index buffers. pub fn trimesh(vertices: Vec, indices: Vec<[u32; 3]>) -> Self { Self::new(SharedShape::trimesh(vertices, indices)) } /// Initializes a collider builder with a triangle mesh shape defined by its vertex and index buffers and /// flags controlling its pre-processing. pub fn trimesh_with_flags( vertices: Vec, indices: Vec<[u32; 3]>, flags: TriMeshFlags, ) -> Self { Self::new(SharedShape::trimesh_with_flags(vertices, indices, flags)) } /// Initializes a collider builder with a compound shape obtained from the decomposition of /// the given trimesh (in 3D) or polyline (in 2D) into convex parts. pub fn convex_decomposition(vertices: &[Point], indices: &[[u32; DIM]]) -> Self { Self::new(SharedShape::convex_decomposition(vertices, indices)) } /// Initializes a collider builder with a compound shape obtained from the decomposition of /// the given trimesh (in 3D) or polyline (in 2D) into convex parts dilated with round corners. pub fn round_convex_decomposition( vertices: &[Point], indices: &[[u32; DIM]], border_radius: Real, ) -> Self { Self::new(SharedShape::round_convex_decomposition( vertices, indices, border_radius, )) } /// Initializes a collider builder with a compound shape obtained from the decomposition of /// the given trimesh (in 3D) or polyline (in 2D) into convex parts. pub fn convex_decomposition_with_params( vertices: &[Point], indices: &[[u32; DIM]], params: &VHACDParameters, ) -> Self { Self::new(SharedShape::convex_decomposition_with_params( vertices, indices, params, )) } /// Initializes a collider builder with a compound shape obtained from the decomposition of /// the given trimesh (in 3D) or polyline (in 2D) into convex parts dilated with round corners. pub fn round_convex_decomposition_with_params( vertices: &[Point], indices: &[[u32; DIM]], params: &VHACDParameters, border_radius: Real, ) -> Self { Self::new(SharedShape::round_convex_decomposition_with_params( vertices, indices, params, border_radius, )) } /// Initializes a new collider builder with a 2D convex polygon or 3D convex polyhedron /// obtained after computing the convex-hull of the given points. pub fn convex_hull(points: &[Point]) -> Option { SharedShape::convex_hull(points).map(Self::new) } /// Initializes a new collider builder with a round 2D convex polygon or 3D convex polyhedron /// obtained after computing the convex-hull of the given points. The shape is dilated /// by a sphere of radius `border_radius`. pub fn round_convex_hull(points: &[Point], border_radius: Real) -> Option { SharedShape::round_convex_hull(points, border_radius).map(Self::new) } /// Creates a new collider builder that is a convex polygon formed by the /// given polyline assumed to be convex (no convex-hull will be automatically /// computed). #[cfg(feature = "dim2")] pub fn convex_polyline(points: Vec) -> Option { SharedShape::convex_polyline(points).map(Self::new) } /// Creates a new collider builder that is a round convex polygon formed by the /// given polyline assumed to be convex (no convex-hull will be automatically /// computed). The polygon shape is dilated by a sphere of radius `border_radius`. #[cfg(feature = "dim2")] pub fn round_convex_polyline(points: Vec, border_radius: Real) -> Option { SharedShape::round_convex_polyline(points, border_radius).map(Self::new) } /// Creates a new collider builder that is a convex polyhedron formed by the /// given triangle-mesh assumed to be convex (no convex-hull will be automatically /// computed). #[cfg(feature = "dim3")] pub fn convex_mesh(points: Vec, indices: &[[u32; 3]]) -> Option { SharedShape::convex_mesh(points, indices).map(Self::new) } /// Creates a new collider builder that is a round convex polyhedron formed by the /// given triangle-mesh assumed to be convex (no convex-hull will be automatically /// computed). The triangle mesh shape is dilated by a sphere of radius `border_radius`. #[cfg(feature = "dim3")] pub fn round_convex_mesh( points: Vec, indices: &[[u32; 3]], border_radius: Real, ) -> Option { SharedShape::round_convex_mesh(points, indices, border_radius).map(Self::new) } /// Initializes a collider builder with a heightfield shape defined by its set of height and a scale /// factor along each coordinate axis. #[cfg(feature = "dim2")] pub fn heightfield(heights: na::DVector, scale: Vector) -> Self { Self::new(SharedShape::heightfield(heights, scale)) } /// Initializes a collider builder with a heightfield shape defined by its set of height and a scale /// factor along each coordinate axis. #[cfg(feature = "dim3")] pub fn heightfield(heights: na::DMatrix, scale: Vector) -> Self { Self::new(SharedShape::heightfield(heights, scale)) } /// The default friction coefficient used by the collider builder. pub fn default_friction() -> Real { 0.5 } /// The default density used by the collider builder. pub fn default_density() -> Real { 1.0 } /// Sets an arbitrary user-defined 128-bit integer associated to the colliders built by this builder. pub fn user_data(mut self, data: u128) -> Self { self.user_data = data; self } /// Sets the collision groups used by this collider. /// /// Two colliders will interact iff. their collision groups are compatible. /// See [InteractionGroups::test] for details. pub fn collision_groups(mut self, groups: InteractionGroups) -> Self { self.collision_groups = groups; self } /// Sets the solver groups used by this collider. /// /// Forces between two colliders in contact will be computed iff their solver groups are /// compatible. See [InteractionGroups::test] for details. pub fn solver_groups(mut self, groups: InteractionGroups) -> Self { self.solver_groups = groups; self } /// Sets whether or not the collider built by this builder is a sensor. pub fn sensor(mut self, is_sensor: bool) -> Self { self.is_sensor = is_sensor; self } /// The set of physics hooks enabled for this collider. pub fn active_hooks(mut self, active_hooks: ActiveHooks) -> Self { self.active_hooks = active_hooks; self } /// The set of events enabled for this collider. pub fn active_events(mut self, active_events: ActiveEvents) -> Self { self.active_events = active_events; self } /// The set of active collision types for this collider. pub fn active_collision_types(mut self, active_collision_types: ActiveCollisionTypes) -> Self { self.active_collision_types = active_collision_types; self } /// Sets the friction coefficient of the collider this builder will build. pub fn friction(mut self, friction: Real) -> Self { self.friction = friction; self } /// Sets the rule to be used to combine two friction coefficients in a contact. pub fn friction_combine_rule(mut self, rule: CoefficientCombineRule) -> Self { self.friction_combine_rule = rule; self } /// Sets the restitution coefficient of the collider this builder will build. pub fn restitution(mut self, restitution: Real) -> Self { self.restitution = restitution; self } /// Sets the rule to be used to combine two restitution coefficients in a contact. pub fn restitution_combine_rule(mut self, rule: CoefficientCombineRule) -> Self { self.restitution_combine_rule = rule; self } /// Sets the uniform density of the collider this builder will build. /// /// This will be overridden by a call to [`Self::mass`] or [`Self::mass_properties`] so it only /// makes sense to call either [`Self::density`] or [`Self::mass`] or [`Self::mass_properties`]. /// /// The mass and angular inertia of this collider will be computed automatically based on its /// shape. pub fn density(mut self, density: Real) -> Self { self.mass_properties = ColliderMassProperties::Density(density); self } /// Sets the mass of the collider this builder will build. /// /// This will be overridden by a call to [`Self::density`] or [`Self::mass_properties`] so it only /// makes sense to call either [`Self::density`] or [`Self::mass`] or [`Self::mass_properties`]. /// /// The angular inertia of this collider will be computed automatically based on its shape /// and this mass value. pub fn mass(mut self, mass: Real) -> Self { self.mass_properties = ColliderMassProperties::Mass(mass); self } /// Sets the mass properties of the collider this builder will build. /// /// This will be overridden by a call to [`Self::density`] or [`Self::mass`] so it only /// makes sense to call either [`Self::density`] or [`Self::mass`] or [`Self::mass_properties`]. pub fn mass_properties(mut self, mass_properties: MassProperties) -> Self { self.mass_properties = ColliderMassProperties::MassProperties(Box::new(mass_properties)); self } /// Sets the total force magnitude beyond which a contact force event can be emitted. pub fn contact_force_event_threshold(mut self, threshold: Real) -> Self { self.contact_force_event_threshold = threshold; self } /// Sets the initial translation of the collider to be created. /// /// If the collider will be attached to a rigid-body, this sets the translation relative to the /// rigid-body it will be attached to. pub fn translation(mut self, translation: Vector) -> Self { *self.position.translation.as_vector_mut() = translation; self } /// Sets the initial orientation of the collider to be created. /// /// If the collider will be attached to a rigid-body, this sets the orientation relative to the /// rigid-body it will be attached to. pub fn rotation(mut self, angle: AngVector) -> Self { self.position.rotation = Rotation::from_scaled_axis(angle.into()); self } /// Sets the initial position (translation and orientation) of the collider to be created. /// /// If the collider will be attached to a rigid-body, this sets the position relative /// to the rigid-body it will be attached to. pub fn position(mut self, pos: Isometry) -> Self { self.position = pos; self } /// Sets the initial position (translation and orientation) of the collider to be created, /// relative to the rigid-body it is attached to. #[deprecated(note = "Use `.position` instead.")] pub fn position_wrt_parent(mut self, pos: Isometry) -> Self { self.position = pos; self } /// Set the position of this collider in the local-space of the rigid-body it is attached to. #[deprecated(note = "Use `.position` instead.")] pub fn delta(mut self, delta: Isometry) -> Self { self.position = delta; self } /// Enable or disable the collider after its creation. pub fn enabled(mut self, enabled: bool) -> Self { self.enabled = enabled; self } /// Builds a new collider attached to the given rigid-body. pub fn build(&self) -> Collider { let shape = self.shape.clone(); let friction = Friction { coefficient: self.friction, combine_rule: self.friction_combine_rule, }; let restitution = Restitution { coefficient: self.restitution, combine_rule: self.restitution_combine_rule, }; let flags = ColliderFlags { collision_groups: self.collision_groups, solver_groups: self.solver_groups, active_collision_types: self.active_collision_types, active_hooks: self.active_hooks, active_events: self.active_events, enabled: if self.enabled { ColliderEnabled::Enabled } else { ColliderEnabled::Disabled }, }; let changes = ColliderChanges::all(); let pos = ColliderPosition(self.position); let bf_data = ColliderBroadPhaseData::default(); let coll_type = if self.is_sensor { ColliderType::Sensor } else { ColliderType::Solid }; Collider { shape, mprops: self.mass_properties.clone(), friction, restitution, parent: None, changes, pos, bf_data, flags, coll_type, contact_force_event_threshold: self.contact_force_event_threshold, user_data: self.user_data, } } } impl From for Collider { fn from(val: ColliderBuilder) -> Collider { val.build() } }