rapier3d/geometry/
collider.rs

1use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle};
2#[cfg(feature = "dim3")]
3use crate::geometry::HeightFieldFlags;
4use crate::geometry::{
5    ActiveCollisionTypes, ColliderChanges, ColliderFlags, ColliderMassProps, ColliderMaterial,
6    ColliderParent, ColliderPosition, ColliderShape, ColliderType, InteractionGroups,
7    MeshConverter, MeshConverterError, SharedShape,
8};
9use crate::math::{AngVector, DIM, Isometry, Point, Real, Rotation, Vector};
10use crate::parry::transformation::vhacd::VHACDParameters;
11use crate::pipeline::{ActiveEvents, ActiveHooks};
12use crate::prelude::ColliderEnabled;
13use na::Unit;
14use parry::bounding_volume::{Aabb, BoundingVolume};
15use parry::shape::{Shape, TriMeshBuilderError, TriMeshFlags};
16use parry::transformation::voxelization::FillMode;
17
18#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
19#[derive(Clone, Debug)]
20/// A geometric entity that can be attached to a body so it can be affected by contacts and proximity queries.
21///
22/// To build a new collider, use the [`ColliderBuilder`] structure.
23pub struct Collider {
24    pub(crate) coll_type: ColliderType,
25    pub(crate) shape: ColliderShape,
26    pub(crate) mprops: ColliderMassProps,
27    pub(crate) changes: ColliderChanges,
28    pub(crate) parent: Option<ColliderParent>,
29    pub(crate) pos: ColliderPosition,
30    pub(crate) material: ColliderMaterial,
31    pub(crate) flags: ColliderFlags,
32    contact_skin: Real,
33    contact_force_event_threshold: Real,
34    /// User-defined data associated to this collider.
35    pub user_data: u128,
36}
37
38impl Collider {
39    pub(crate) fn reset_internal_references(&mut self) {
40        self.changes = ColliderChanges::all();
41    }
42
43    pub(crate) fn effective_contact_force_event_threshold(&self) -> Real {
44        if self
45            .flags
46            .active_events
47            .contains(ActiveEvents::CONTACT_FORCE_EVENTS)
48        {
49            self.contact_force_event_threshold
50        } else {
51            Real::MAX
52        }
53    }
54
55    /// The rigid body this collider is attached to.
56    pub fn parent(&self) -> Option<RigidBodyHandle> {
57        self.parent.map(|parent| parent.handle)
58    }
59
60    /// Is this collider a sensor?
61    pub fn is_sensor(&self) -> bool {
62        self.coll_type.is_sensor()
63    }
64
65    /// Copy all the characteristics from `other` to `self`.
66    ///
67    /// If you have a mutable reference to a collider `collider: &mut Collider`, attempting to
68    /// assign it a whole new collider instance, e.g., `*collider = ColliderBuilder::ball(0.5).build()`,
69    /// will crash due to some internal indices being overwritten. Instead, use
70    /// `collider.copy_from(&ColliderBuilder::ball(0.5).build())`.
71    ///
72    /// This method will allow you to set most characteristics of this collider from another
73    /// collider instance without causing any breakage.
74    ///
75    /// This method **cannot** be used for reparenting a collider. Therefore, the parent of the
76    /// `other` (if any), as well as its relative position to that parent will not be copied into
77    /// `self`.
78    ///
79    /// The pose of `other` will only copied into `self` if `self` doesn’t have a parent (if it has
80    /// a parent, its position is directly controlled by the parent rigid-body).
81    pub fn copy_from(&mut self, other: &Collider) {
82        // NOTE: we deconstruct the collider struct to be sure we don’t forget to
83        //       add some copies here if we add more field to Collider in the future.
84        let Collider {
85            coll_type,
86            shape,
87            mprops,
88            changes: _changes, // Will be set to ALL.
89            parent: _parent,   // This function cannot be used to reparent the collider.
90            pos,
91            material,
92            flags,
93            contact_force_event_threshold,
94            user_data,
95            contact_skin,
96        } = other;
97
98        if self.parent.is_none() {
99            self.pos = *pos;
100        }
101
102        self.coll_type = *coll_type;
103        self.shape = shape.clone();
104        self.mprops = mprops.clone();
105        self.material = *material;
106        self.contact_force_event_threshold = *contact_force_event_threshold;
107        self.user_data = *user_data;
108        self.flags = *flags;
109        self.changes = ColliderChanges::all();
110        self.contact_skin = *contact_skin;
111    }
112
113    /// The physics hooks enabled for this collider.
114    pub fn active_hooks(&self) -> ActiveHooks {
115        self.flags.active_hooks
116    }
117
118    /// Sets the physics hooks enabled for this collider.
119    pub fn set_active_hooks(&mut self, active_hooks: ActiveHooks) {
120        self.flags.active_hooks = active_hooks;
121    }
122
123    /// The events enabled for this collider.
124    pub fn active_events(&self) -> ActiveEvents {
125        self.flags.active_events
126    }
127
128    /// Sets the events enabled for this collider.
129    pub fn set_active_events(&mut self, active_events: ActiveEvents) {
130        self.flags.active_events = active_events;
131    }
132
133    /// The collision types enabled for this collider.
134    pub fn active_collision_types(&self) -> ActiveCollisionTypes {
135        self.flags.active_collision_types
136    }
137
138    /// Sets the collision types enabled for this collider.
139    pub fn set_active_collision_types(&mut self, active_collision_types: ActiveCollisionTypes) {
140        self.flags.active_collision_types = active_collision_types;
141    }
142
143    /// The contact skin of this collider.
144    ///
145    /// See the documentation of [`ColliderBuilder::contact_skin`] for details.
146    pub fn contact_skin(&self) -> Real {
147        self.contact_skin
148    }
149
150    /// Sets the contact skin of this collider.
151    ///
152    /// See the documentation of [`ColliderBuilder::contact_skin`] for details.
153    pub fn set_contact_skin(&mut self, skin_thickness: Real) {
154        self.contact_skin = skin_thickness;
155    }
156
157    /// The friction coefficient of this collider.
158    pub fn friction(&self) -> Real {
159        self.material.friction
160    }
161
162    /// Sets the friction coefficient of this collider.
163    pub fn set_friction(&mut self, coefficient: Real) {
164        self.material.friction = coefficient
165    }
166
167    /// The combine rule used by this collider to combine its friction
168    /// coefficient with the friction coefficient of the other collider it
169    /// is in contact with.
170    pub fn friction_combine_rule(&self) -> CoefficientCombineRule {
171        self.material.friction_combine_rule
172    }
173
174    /// Sets the combine rule used by this collider to combine its friction
175    /// coefficient with the friction coefficient of the other collider it
176    /// is in contact with.
177    pub fn set_friction_combine_rule(&mut self, rule: CoefficientCombineRule) {
178        self.material.friction_combine_rule = rule;
179    }
180
181    /// The restitution coefficient of this collider.
182    pub fn restitution(&self) -> Real {
183        self.material.restitution
184    }
185
186    /// Sets the restitution coefficient of this collider.
187    pub fn set_restitution(&mut self, coefficient: Real) {
188        self.material.restitution = coefficient
189    }
190
191    /// The combine rule used by this collider to combine its restitution
192    /// coefficient with the restitution coefficient of the other collider it
193    /// is in contact with.
194    pub fn restitution_combine_rule(&self) -> CoefficientCombineRule {
195        self.material.restitution_combine_rule
196    }
197
198    /// Sets the combine rule used by this collider to combine its restitution
199    /// coefficient with the restitution coefficient of the other collider it
200    /// is in contact with.
201    pub fn set_restitution_combine_rule(&mut self, rule: CoefficientCombineRule) {
202        self.material.restitution_combine_rule = rule;
203    }
204
205    /// Sets the total force magnitude beyond which a contact force event can be emitted.
206    pub fn set_contact_force_event_threshold(&mut self, threshold: Real) {
207        self.contact_force_event_threshold = threshold;
208    }
209
210    /// Sets whether or not this is a sensor collider.
211    pub fn set_sensor(&mut self, is_sensor: bool) {
212        if is_sensor != self.is_sensor() {
213            self.changes.insert(ColliderChanges::TYPE);
214            self.coll_type = if is_sensor {
215                ColliderType::Sensor
216            } else {
217                ColliderType::Solid
218            };
219        }
220    }
221
222    /// Is this collider enabled?
223    pub fn is_enabled(&self) -> bool {
224        matches!(self.flags.enabled, ColliderEnabled::Enabled)
225    }
226
227    /// Sets whether or not this collider is enabled.
228    pub fn set_enabled(&mut self, enabled: bool) {
229        match self.flags.enabled {
230            ColliderEnabled::Enabled | ColliderEnabled::DisabledByParent => {
231                if !enabled {
232                    self.changes.insert(ColliderChanges::ENABLED_OR_DISABLED);
233                    self.flags.enabled = ColliderEnabled::Disabled;
234                }
235            }
236            ColliderEnabled::Disabled => {
237                if enabled {
238                    self.changes.insert(ColliderChanges::ENABLED_OR_DISABLED);
239                    self.flags.enabled = ColliderEnabled::Enabled;
240                }
241            }
242        }
243    }
244
245    /// Sets the translational part of this collider's position.
246    pub fn set_translation(&mut self, translation: Vector<Real>) {
247        self.changes.insert(ColliderChanges::POSITION);
248        self.pos.0.translation.vector = translation;
249    }
250
251    /// Sets the rotational part of this collider's position.
252    pub fn set_rotation(&mut self, rotation: Rotation<Real>) {
253        self.changes.insert(ColliderChanges::POSITION);
254        self.pos.0.rotation = rotation;
255    }
256
257    /// Sets the position of this collider.
258    pub fn set_position(&mut self, position: Isometry<Real>) {
259        self.changes.insert(ColliderChanges::POSITION);
260        self.pos.0 = position;
261    }
262
263    /// The world-space position of this collider.
264    pub fn position(&self) -> &Isometry<Real> {
265        &self.pos
266    }
267
268    /// The translational part of this collider's position.
269    pub fn translation(&self) -> &Vector<Real> {
270        &self.pos.0.translation.vector
271    }
272
273    /// The rotational part of this collider's position.
274    pub fn rotation(&self) -> &Rotation<Real> {
275        &self.pos.0.rotation
276    }
277
278    /// The position of this collider with respect to the body it is attached to.
279    pub fn position_wrt_parent(&self) -> Option<&Isometry<Real>> {
280        self.parent.as_ref().map(|p| &p.pos_wrt_parent)
281    }
282
283    /// Sets the translational part of this collider's translation relative to its parent rigid-body.
284    pub fn set_translation_wrt_parent(&mut self, translation: Vector<Real>) {
285        if let Some(parent) = self.parent.as_mut() {
286            self.changes.insert(ColliderChanges::PARENT);
287            parent.pos_wrt_parent.translation.vector = translation;
288        }
289    }
290
291    /// Sets the rotational part of this collider's rotation relative to its parent rigid-body.
292    pub fn set_rotation_wrt_parent(&mut self, rotation: AngVector<Real>) {
293        if let Some(parent) = self.parent.as_mut() {
294            self.changes.insert(ColliderChanges::PARENT);
295            parent.pos_wrt_parent.rotation = Rotation::new(rotation);
296        }
297    }
298
299    /// Sets the position of this collider with respect to its parent rigid-body.
300    ///
301    /// Does nothing if the collider is not attached to a rigid-body.
302    pub fn set_position_wrt_parent(&mut self, pos_wrt_parent: Isometry<Real>) {
303        if let Some(parent) = self.parent.as_mut() {
304            self.changes.insert(ColliderChanges::PARENT);
305            parent.pos_wrt_parent = pos_wrt_parent;
306        }
307    }
308
309    /// The collision groups used by this collider.
310    pub fn collision_groups(&self) -> InteractionGroups {
311        self.flags.collision_groups
312    }
313
314    /// Sets the collision groups of this collider.
315    pub fn set_collision_groups(&mut self, groups: InteractionGroups) {
316        if self.flags.collision_groups != groups {
317            self.changes.insert(ColliderChanges::GROUPS);
318            self.flags.collision_groups = groups;
319        }
320    }
321
322    /// The solver groups used by this collider.
323    pub fn solver_groups(&self) -> InteractionGroups {
324        self.flags.solver_groups
325    }
326
327    /// Sets the solver groups of this collider.
328    pub fn set_solver_groups(&mut self, groups: InteractionGroups) {
329        if self.flags.solver_groups != groups {
330            self.changes.insert(ColliderChanges::GROUPS);
331            self.flags.solver_groups = groups;
332        }
333    }
334
335    /// The material (friction and restitution properties) of this collider.
336    pub fn material(&self) -> &ColliderMaterial {
337        &self.material
338    }
339
340    /// The volume (or surface in 2D) of this collider.
341    pub fn volume(&self) -> Real {
342        self.shape.mass_properties(1.0).mass()
343    }
344
345    /// The density of this collider.
346    pub fn density(&self) -> Real {
347        match &self.mprops {
348            ColliderMassProps::Density(density) => *density,
349            ColliderMassProps::Mass(mass) => {
350                let inv_volume = self.shape.mass_properties(1.0).inv_mass;
351                mass * inv_volume
352            }
353            ColliderMassProps::MassProperties(mprops) => {
354                let inv_volume = self.shape.mass_properties(1.0).inv_mass;
355                mprops.mass() * inv_volume
356            }
357        }
358    }
359
360    /// The mass of this collider.
361    pub fn mass(&self) -> Real {
362        match &self.mprops {
363            ColliderMassProps::Density(density) => self.shape.mass_properties(*density).mass(),
364            ColliderMassProps::Mass(mass) => *mass,
365            ColliderMassProps::MassProperties(mprops) => mprops.mass(),
366        }
367    }
368
369    /// Sets the uniform density of this collider.
370    ///
371    /// This will override any previous mass-properties set by [`Self::set_density`],
372    /// [`Self::set_mass`], [`Self::set_mass_properties`], [`ColliderBuilder::density`],
373    /// [`ColliderBuilder::mass`], or [`ColliderBuilder::mass_properties`]
374    /// for this collider.
375    ///
376    /// The mass and angular inertia of this collider will be computed automatically based on its
377    /// shape.
378    pub fn set_density(&mut self, density: Real) {
379        self.do_set_mass_properties(ColliderMassProps::Density(density));
380    }
381
382    /// Sets the mass of this collider.
383    ///
384    /// This will override any previous mass-properties set by [`Self::set_density`],
385    /// [`Self::set_mass`], [`Self::set_mass_properties`], [`ColliderBuilder::density`],
386    /// [`ColliderBuilder::mass`], or [`ColliderBuilder::mass_properties`]
387    /// for this collider.
388    ///
389    /// The angular inertia of this collider will be computed automatically based on its shape
390    /// and this mass value.
391    pub fn set_mass(&mut self, mass: Real) {
392        self.do_set_mass_properties(ColliderMassProps::Mass(mass));
393    }
394
395    /// Sets the mass properties of this collider.
396    ///
397    /// This will override any previous mass-properties set by [`Self::set_density`],
398    /// [`Self::set_mass`], [`Self::set_mass_properties`], [`ColliderBuilder::density`],
399    /// [`ColliderBuilder::mass`], or [`ColliderBuilder::mass_properties`]
400    /// for this collider.
401    pub fn set_mass_properties(&mut self, mass_properties: MassProperties) {
402        self.do_set_mass_properties(ColliderMassProps::MassProperties(Box::new(mass_properties)))
403    }
404
405    fn do_set_mass_properties(&mut self, mprops: ColliderMassProps) {
406        if mprops != self.mprops {
407            self.changes |= ColliderChanges::LOCAL_MASS_PROPERTIES;
408            self.mprops = mprops;
409        }
410    }
411
412    /// The geometric shape of this collider.
413    pub fn shape(&self) -> &dyn Shape {
414        self.shape.as_ref()
415    }
416
417    /// A mutable reference to the geometric shape of this collider.
418    ///
419    /// If that shape is shared by multiple colliders, it will be
420    /// cloned first so that `self` contains a unique copy of that
421    /// shape that you can modify.
422    pub fn shape_mut(&mut self) -> &mut dyn Shape {
423        self.changes.insert(ColliderChanges::SHAPE);
424        self.shape.make_mut()
425    }
426
427    /// Sets the shape of this collider.
428    pub fn set_shape(&mut self, shape: SharedShape) {
429        self.changes.insert(ColliderChanges::SHAPE);
430        self.shape = shape;
431    }
432
433    /// Retrieve the SharedShape. Also see the `shape()` function
434    pub fn shared_shape(&self) -> &SharedShape {
435        &self.shape
436    }
437
438    /// Compute the axis-aligned bounding box of this collider.
439    ///
440    /// This AABB doesn’t take into account the collider’s contact skin.
441    /// [`Collider::contact_skin`].
442    pub fn compute_aabb(&self) -> Aabb {
443        self.shape.compute_aabb(&self.pos)
444    }
445
446    /// Compute the axis-aligned bounding box of this collider, taking into account the
447    /// [`Collider::contact_skin`] and prediction distance.
448    pub fn compute_collision_aabb(&self, prediction: Real) -> Aabb {
449        self.shape
450            .compute_aabb(&self.pos)
451            .loosened(self.contact_skin + prediction)
452    }
453
454    /// Compute the axis-aligned bounding box of this collider moving from its current position
455    /// to the given `next_position`
456    pub fn compute_swept_aabb(&self, next_position: &Isometry<Real>) -> Aabb {
457        self.shape.compute_swept_aabb(&self.pos, next_position)
458    }
459
460    /// Compute the local-space mass properties of this collider.
461    pub fn mass_properties(&self) -> MassProperties {
462        self.mprops.mass_properties(&*self.shape)
463    }
464
465    /// The total force magnitude beyond which a contact force event can be emitted.
466    pub fn contact_force_event_threshold(&self) -> Real {
467        self.contact_force_event_threshold
468    }
469}
470
471/// A structure responsible for building a new collider.
472#[derive(Clone, Debug)]
473#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
474#[must_use = "Builder functions return the updated builder"]
475pub struct ColliderBuilder {
476    /// The shape of the collider to be built.
477    pub shape: SharedShape,
478    /// Controls the way the collider’s mass-properties are computed.
479    pub mass_properties: ColliderMassProps,
480    /// The friction coefficient of the collider to be built.
481    pub friction: Real,
482    /// The rule used to combine two friction coefficients.
483    pub friction_combine_rule: CoefficientCombineRule,
484    /// The restitution coefficient of the collider to be built.
485    pub restitution: Real,
486    /// The rule used to combine two restitution coefficients.
487    pub restitution_combine_rule: CoefficientCombineRule,
488    /// The position of this collider.
489    pub position: Isometry<Real>,
490    /// Is this collider a sensor?
491    pub is_sensor: bool,
492    /// Contact pairs enabled for this collider.
493    pub active_collision_types: ActiveCollisionTypes,
494    /// Physics hooks enabled for this collider.
495    pub active_hooks: ActiveHooks,
496    /// Events enabled for this collider.
497    pub active_events: ActiveEvents,
498    /// The user-data of the collider being built.
499    pub user_data: u128,
500    /// The collision groups for the collider being built.
501    pub collision_groups: InteractionGroups,
502    /// The solver groups for the collider being built.
503    pub solver_groups: InteractionGroups,
504    /// Will the collider being built be enabled?
505    pub enabled: bool,
506    /// The total force magnitude beyond which a contact force event can be emitted.
507    pub contact_force_event_threshold: Real,
508    /// An extra thickness around the collider shape to keep them further apart when colliding.
509    pub contact_skin: Real,
510}
511
512impl Default for ColliderBuilder {
513    fn default() -> Self {
514        Self::ball(0.5)
515    }
516}
517
518impl ColliderBuilder {
519    /// Initialize a new collider builder with the given shape.
520    pub fn new(shape: SharedShape) -> Self {
521        Self {
522            shape,
523            mass_properties: ColliderMassProps::default(),
524            friction: Self::default_friction(),
525            restitution: 0.0,
526            position: Isometry::identity(),
527            is_sensor: false,
528            user_data: 0,
529            collision_groups: InteractionGroups::all(),
530            solver_groups: InteractionGroups::all(),
531            friction_combine_rule: CoefficientCombineRule::Average,
532            restitution_combine_rule: CoefficientCombineRule::Average,
533            active_collision_types: ActiveCollisionTypes::default(),
534            active_hooks: ActiveHooks::empty(),
535            active_events: ActiveEvents::empty(),
536            enabled: true,
537            contact_force_event_threshold: 0.0,
538            contact_skin: 0.0,
539        }
540    }
541
542    /// Initialize a new collider builder with a compound shape.
543    pub fn compound(shapes: Vec<(Isometry<Real>, SharedShape)>) -> Self {
544        Self::new(SharedShape::compound(shapes))
545    }
546
547    /// Initialize a new collider builder with a ball shape defined by its radius.
548    pub fn ball(radius: Real) -> Self {
549        Self::new(SharedShape::ball(radius))
550    }
551
552    /// Initialize a new collider build with a half-space shape defined by the outward normal
553    /// of its planar boundary.
554    pub fn halfspace(outward_normal: Unit<Vector<Real>>) -> Self {
555        Self::new(SharedShape::halfspace(outward_normal))
556    }
557
558    /// Initializes a shape made of voxels.
559    ///
560    /// Each voxel has the size `voxel_size` and grid coordinate given by `voxels`.
561    /// The `primitive_geometry` controls the behavior of collision detection at voxels boundaries.
562    ///
563    /// For initializing a voxels shape from points in space, see [`Self::voxels_from_points`].
564    /// For initializing a voxels shape from a mesh to voxelize, see [`Self::voxelized_mesh`].
565    pub fn voxels(voxel_size: Vector<Real>, voxels: &[Point<i32>]) -> Self {
566        Self::new(SharedShape::voxels(voxel_size, voxels))
567    }
568
569    /// Initializes a collider made of voxels.
570    ///
571    /// Each voxel has the size `voxel_size` and contains at least one point from `centers`.
572    /// The `primitive_geometry` controls the behavior of collision detection at voxels boundaries.
573    pub fn voxels_from_points(voxel_size: Vector<Real>, points: &[Point<Real>]) -> Self {
574        Self::new(SharedShape::voxels_from_points(voxel_size, points))
575    }
576
577    /// Initializes a voxels obtained from the decomposition of the given trimesh (in 3D)
578    /// or polyline (in 2D) into voxelized convex parts.
579    pub fn voxelized_mesh(
580        vertices: &[Point<Real>],
581        indices: &[[u32; DIM]],
582        voxel_size: Real,
583        fill_mode: FillMode,
584    ) -> Self {
585        Self::new(SharedShape::voxelized_mesh(
586            vertices, indices, voxel_size, fill_mode,
587        ))
588    }
589
590    /// Initialize a new collider builder with a cylindrical shape defined by its half-height
591    /// (along the Y axis) and its radius.
592    #[cfg(feature = "dim3")]
593    pub fn cylinder(half_height: Real, radius: Real) -> Self {
594        Self::new(SharedShape::cylinder(half_height, radius))
595    }
596
597    /// Initialize a new collider builder with a rounded cylindrical shape defined by its half-height
598    /// (along the Y axis), its radius, and its roundedness (the radius of the sphere used for
599    /// dilating the cylinder).
600    #[cfg(feature = "dim3")]
601    pub fn round_cylinder(half_height: Real, radius: Real, border_radius: Real) -> Self {
602        Self::new(SharedShape::round_cylinder(
603            half_height,
604            radius,
605            border_radius,
606        ))
607    }
608
609    /// Initialize a new collider builder with a cone shape defined by its half-height
610    /// (along the Y axis) and its basis radius.
611    #[cfg(feature = "dim3")]
612    pub fn cone(half_height: Real, radius: Real) -> Self {
613        Self::new(SharedShape::cone(half_height, radius))
614    }
615
616    /// Initialize a new collider builder with a rounded cone shape defined by its half-height
617    /// (along the Y axis), its radius, and its roundedness (the radius of the sphere used for
618    /// dilating the cylinder).
619    #[cfg(feature = "dim3")]
620    pub fn round_cone(half_height: Real, radius: Real, border_radius: Real) -> Self {
621        Self::new(SharedShape::round_cone(half_height, radius, border_radius))
622    }
623
624    /// Initialize a new collider builder with a cuboid shape defined by its half-extents.
625    #[cfg(feature = "dim2")]
626    pub fn cuboid(hx: Real, hy: Real) -> Self {
627        Self::new(SharedShape::cuboid(hx, hy))
628    }
629
630    /// Initialize a new collider builder with a round cuboid shape defined by its half-extents
631    /// and border radius.
632    #[cfg(feature = "dim2")]
633    pub fn round_cuboid(hx: Real, hy: Real, border_radius: Real) -> Self {
634        Self::new(SharedShape::round_cuboid(hx, hy, border_radius))
635    }
636
637    /// Initialize a new collider builder with a capsule defined from its endpoints.
638    ///
639    /// See also [`ColliderBuilder::capsule_x`], [`ColliderBuilder::capsule_y`],
640    /// (and `ColliderBuilder::capsule_z` in 3D only)
641    /// for a simpler way to build capsules with common
642    /// orientations.
643    pub fn capsule_from_endpoints(a: Point<Real>, b: Point<Real>, radius: Real) -> Self {
644        Self::new(SharedShape::capsule(a, b, radius))
645    }
646
647    /// Initialize a new collider builder with a capsule shape aligned with the `x` axis.
648    pub fn capsule_x(half_height: Real, radius: Real) -> Self {
649        Self::new(SharedShape::capsule_x(half_height, radius))
650    }
651
652    /// Initialize a new collider builder with a capsule shape aligned with the `y` axis.
653    pub fn capsule_y(half_height: Real, radius: Real) -> Self {
654        Self::new(SharedShape::capsule_y(half_height, radius))
655    }
656
657    /// Initialize a new collider builder with a capsule shape aligned with the `z` axis.
658    #[cfg(feature = "dim3")]
659    pub fn capsule_z(half_height: Real, radius: Real) -> Self {
660        Self::new(SharedShape::capsule_z(half_height, radius))
661    }
662
663    /// Initialize a new collider builder with a cuboid shape defined by its half-extents.
664    #[cfg(feature = "dim3")]
665    pub fn cuboid(hx: Real, hy: Real, hz: Real) -> Self {
666        Self::new(SharedShape::cuboid(hx, hy, hz))
667    }
668
669    /// Initialize a new collider builder with a round cuboid shape defined by its half-extents
670    /// and border radius.
671    #[cfg(feature = "dim3")]
672    pub fn round_cuboid(hx: Real, hy: Real, hz: Real, border_radius: Real) -> Self {
673        Self::new(SharedShape::round_cuboid(hx, hy, hz, border_radius))
674    }
675
676    /// Initializes a collider builder with a segment shape.
677    pub fn segment(a: Point<Real>, b: Point<Real>) -> Self {
678        Self::new(SharedShape::segment(a, b))
679    }
680
681    /// Initializes a collider builder with a triangle shape.
682    pub fn triangle(a: Point<Real>, b: Point<Real>, c: Point<Real>) -> Self {
683        Self::new(SharedShape::triangle(a, b, c))
684    }
685
686    /// Initializes a collider builder with a triangle shape with round corners.
687    pub fn round_triangle(
688        a: Point<Real>,
689        b: Point<Real>,
690        c: Point<Real>,
691        border_radius: Real,
692    ) -> Self {
693        Self::new(SharedShape::round_triangle(a, b, c, border_radius))
694    }
695
696    /// Initializes a collider builder with a polyline shape defined by its vertex and index buffers.
697    pub fn polyline(vertices: Vec<Point<Real>>, indices: Option<Vec<[u32; 2]>>) -> Self {
698        Self::new(SharedShape::polyline(vertices, indices))
699    }
700
701    /// Initializes a collider builder with a triangle mesh shape defined by its vertex and index buffers.
702    pub fn trimesh(
703        vertices: Vec<Point<Real>>,
704        indices: Vec<[u32; 3]>,
705    ) -> Result<Self, TriMeshBuilderError> {
706        Ok(Self::new(SharedShape::trimesh(vertices, indices)?))
707    }
708
709    /// Initializes a collider builder with a triangle mesh shape defined by its vertex and index buffers and
710    /// flags controlling its pre-processing.
711    pub fn trimesh_with_flags(
712        vertices: Vec<Point<Real>>,
713        indices: Vec<[u32; 3]>,
714        flags: TriMeshFlags,
715    ) -> Result<Self, TriMeshBuilderError> {
716        Ok(Self::new(SharedShape::trimesh_with_flags(
717            vertices, indices, flags,
718        )?))
719    }
720
721    /// Initializes a collider builder with a shape converted from the given triangle mesh index
722    /// and vertex buffer.
723    ///
724    /// All the conversion variants could be achieved with other constructors of [`ColliderBuilder`]
725    /// but having this specified by an enum can occasionally be easier or more flexible (determined
726    /// at runtime).
727    pub fn converted_trimesh(
728        vertices: Vec<Point<Real>>,
729        indices: Vec<[u32; 3]>,
730        converter: MeshConverter,
731    ) -> Result<Self, MeshConverterError> {
732        let (shape, pose) = converter.convert(vertices, indices)?;
733        Ok(Self::new(shape).position(pose))
734    }
735
736    /// Initializes a collider builder with a compound shape obtained from the decomposition of
737    /// the given trimesh (in 3D) or polyline (in 2D) into convex parts.
738    pub fn convex_decomposition(vertices: &[Point<Real>], indices: &[[u32; DIM]]) -> Self {
739        Self::new(SharedShape::convex_decomposition(vertices, indices))
740    }
741
742    /// Initializes a collider builder with a compound shape obtained from the decomposition of
743    /// the given trimesh (in 3D) or polyline (in 2D) into convex parts dilated with round corners.
744    pub fn round_convex_decomposition(
745        vertices: &[Point<Real>],
746        indices: &[[u32; DIM]],
747        border_radius: Real,
748    ) -> Self {
749        Self::new(SharedShape::round_convex_decomposition(
750            vertices,
751            indices,
752            border_radius,
753        ))
754    }
755
756    /// Initializes a collider builder with a compound shape obtained from the decomposition of
757    /// the given trimesh (in 3D) or polyline (in 2D) into convex parts.
758    pub fn convex_decomposition_with_params(
759        vertices: &[Point<Real>],
760        indices: &[[u32; DIM]],
761        params: &VHACDParameters,
762    ) -> Self {
763        Self::new(SharedShape::convex_decomposition_with_params(
764            vertices, indices, params,
765        ))
766    }
767
768    /// Initializes a collider builder with a compound shape obtained from the decomposition of
769    /// the given trimesh (in 3D) or polyline (in 2D) into convex parts dilated with round corners.
770    pub fn round_convex_decomposition_with_params(
771        vertices: &[Point<Real>],
772        indices: &[[u32; DIM]],
773        params: &VHACDParameters,
774        border_radius: Real,
775    ) -> Self {
776        Self::new(SharedShape::round_convex_decomposition_with_params(
777            vertices,
778            indices,
779            params,
780            border_radius,
781        ))
782    }
783
784    /// Initializes a new collider builder with a 2D convex polygon or 3D convex polyhedron
785    /// obtained after computing the convex-hull of the given points.
786    pub fn convex_hull(points: &[Point<Real>]) -> Option<Self> {
787        SharedShape::convex_hull(points).map(Self::new)
788    }
789
790    /// Initializes a new collider builder with a round 2D convex polygon or 3D convex polyhedron
791    /// obtained after computing the convex-hull of the given points. The shape is dilated
792    /// by a sphere of radius `border_radius`.
793    pub fn round_convex_hull(points: &[Point<Real>], border_radius: Real) -> Option<Self> {
794        SharedShape::round_convex_hull(points, border_radius).map(Self::new)
795    }
796
797    /// Creates a new collider builder that is a convex polygon formed by the
798    /// given polyline assumed to be convex (no convex-hull will be automatically
799    /// computed).
800    #[cfg(feature = "dim2")]
801    pub fn convex_polyline(points: Vec<Point<Real>>) -> Option<Self> {
802        SharedShape::convex_polyline(points).map(Self::new)
803    }
804
805    /// Creates a new collider builder that is a round convex polygon formed by the
806    /// given polyline assumed to be convex (no convex-hull will be automatically
807    /// computed). The polygon shape is dilated by a sphere of radius `border_radius`.
808    #[cfg(feature = "dim2")]
809    pub fn round_convex_polyline(points: Vec<Point<Real>>, border_radius: Real) -> Option<Self> {
810        SharedShape::round_convex_polyline(points, border_radius).map(Self::new)
811    }
812
813    /// Creates a new collider builder that is a convex polyhedron formed by the
814    /// given triangle-mesh assumed to be convex (no convex-hull will be automatically
815    /// computed).
816    #[cfg(feature = "dim3")]
817    pub fn convex_mesh(points: Vec<Point<Real>>, indices: &[[u32; 3]]) -> Option<Self> {
818        SharedShape::convex_mesh(points, indices).map(Self::new)
819    }
820
821    /// Creates a new collider builder that is a round convex polyhedron formed by the
822    /// given triangle-mesh assumed to be convex (no convex-hull will be automatically
823    /// computed). The triangle mesh shape is dilated by a sphere of radius `border_radius`.
824    #[cfg(feature = "dim3")]
825    pub fn round_convex_mesh(
826        points: Vec<Point<Real>>,
827        indices: &[[u32; 3]],
828        border_radius: Real,
829    ) -> Option<Self> {
830        SharedShape::round_convex_mesh(points, indices, border_radius).map(Self::new)
831    }
832
833    /// Initializes a collider builder with a heightfield shape defined by its set of height and a scale
834    /// factor along each coordinate axis.
835    #[cfg(feature = "dim2")]
836    pub fn heightfield(heights: na::DVector<Real>, scale: Vector<Real>) -> Self {
837        Self::new(SharedShape::heightfield(heights, scale))
838    }
839
840    /// Initializes a collider builder with a heightfield shape defined by its set of height and a scale
841    /// factor along each coordinate axis.
842    #[cfg(feature = "dim3")]
843    pub fn heightfield(heights: na::DMatrix<Real>, scale: Vector<Real>) -> Self {
844        Self::new(SharedShape::heightfield(heights, scale))
845    }
846
847    /// Initializes a collider builder with a heightfield shape defined by its set of height and a scale
848    /// factor along each coordinate axis.
849    #[cfg(feature = "dim3")]
850    pub fn heightfield_with_flags(
851        heights: na::DMatrix<Real>,
852        scale: Vector<Real>,
853        flags: HeightFieldFlags,
854    ) -> Self {
855        Self::new(SharedShape::heightfield_with_flags(heights, scale, flags))
856    }
857
858    /// The default friction coefficient used by the collider builder.
859    pub fn default_friction() -> Real {
860        0.5
861    }
862
863    /// The default density used by the collider builder.
864    pub fn default_density() -> Real {
865        100.0
866    }
867
868    /// Sets an arbitrary user-defined 128-bit integer associated to the colliders built by this builder.
869    pub fn user_data(mut self, data: u128) -> Self {
870        self.user_data = data;
871        self
872    }
873
874    /// Sets the collision groups used by this collider.
875    ///
876    /// Two colliders will interact iff. their collision groups are compatible.
877    /// See [InteractionGroups::test] for details.
878    pub fn collision_groups(mut self, groups: InteractionGroups) -> Self {
879        self.collision_groups = groups;
880        self
881    }
882
883    /// Sets the solver groups used by this collider.
884    ///
885    /// Forces between two colliders in contact will be computed iff their solver groups are
886    /// compatible. See [InteractionGroups::test] for details.
887    pub fn solver_groups(mut self, groups: InteractionGroups) -> Self {
888        self.solver_groups = groups;
889        self
890    }
891
892    /// Sets whether or not the collider built by this builder is a sensor.
893    pub fn sensor(mut self, is_sensor: bool) -> Self {
894        self.is_sensor = is_sensor;
895        self
896    }
897
898    /// The set of physics hooks enabled for this collider.
899    pub fn active_hooks(mut self, active_hooks: ActiveHooks) -> Self {
900        self.active_hooks = active_hooks;
901        self
902    }
903
904    /// The set of events enabled for this collider.
905    pub fn active_events(mut self, active_events: ActiveEvents) -> Self {
906        self.active_events = active_events;
907        self
908    }
909
910    /// The set of active collision types for this collider.
911    pub fn active_collision_types(mut self, active_collision_types: ActiveCollisionTypes) -> Self {
912        self.active_collision_types = active_collision_types;
913        self
914    }
915
916    /// Sets the friction coefficient of the collider this builder will build.
917    pub fn friction(mut self, friction: Real) -> Self {
918        self.friction = friction;
919        self
920    }
921
922    /// Sets the rule to be used to combine two friction coefficients in a contact.
923    pub fn friction_combine_rule(mut self, rule: CoefficientCombineRule) -> Self {
924        self.friction_combine_rule = rule;
925        self
926    }
927
928    /// Sets the restitution coefficient of the collider this builder will build.
929    pub fn restitution(mut self, restitution: Real) -> Self {
930        self.restitution = restitution;
931        self
932    }
933
934    /// Sets the rule to be used to combine two restitution coefficients in a contact.
935    pub fn restitution_combine_rule(mut self, rule: CoefficientCombineRule) -> Self {
936        self.restitution_combine_rule = rule;
937        self
938    }
939
940    /// Sets the uniform density of the collider this builder will build.
941    ///
942    /// This will be overridden by a call to [`Self::mass`] or [`Self::mass_properties`] so it only
943    /// makes sense to call either [`Self::density`] or [`Self::mass`] or [`Self::mass_properties`].
944    ///
945    /// The mass and angular inertia of this collider will be computed automatically based on its
946    /// shape.
947    pub fn density(mut self, density: Real) -> Self {
948        self.mass_properties = ColliderMassProps::Density(density);
949        self
950    }
951
952    /// Sets the mass of the collider this builder will build.
953    ///
954    /// This will be overridden by a call to [`Self::density`] or [`Self::mass_properties`] so it only
955    /// makes sense to call either [`Self::density`] or [`Self::mass`] or [`Self::mass_properties`].
956    ///
957    /// The angular inertia of this collider will be computed automatically based on its shape
958    /// and this mass value.
959    pub fn mass(mut self, mass: Real) -> Self {
960        self.mass_properties = ColliderMassProps::Mass(mass);
961        self
962    }
963
964    /// Sets the mass properties of the collider this builder will build.
965    ///
966    /// This will be overridden by a call to [`Self::density`] or [`Self::mass`] so it only
967    /// makes sense to call either [`Self::density`] or [`Self::mass`] or [`Self::mass_properties`].
968    pub fn mass_properties(mut self, mass_properties: MassProperties) -> Self {
969        self.mass_properties = ColliderMassProps::MassProperties(Box::new(mass_properties));
970        self
971    }
972
973    /// Sets the total force magnitude beyond which a contact force event can be emitted.
974    pub fn contact_force_event_threshold(mut self, threshold: Real) -> Self {
975        self.contact_force_event_threshold = threshold;
976        self
977    }
978
979    /// Sets the initial translation of the collider to be created.
980    ///
981    /// If the collider will be attached to a rigid-body, this sets the translation relative to the
982    /// rigid-body it will be attached to.
983    pub fn translation(mut self, translation: Vector<Real>) -> Self {
984        self.position.translation.vector = translation;
985        self
986    }
987
988    /// Sets the initial orientation of the collider to be created.
989    ///
990    /// If the collider will be attached to a rigid-body, this sets the orientation relative to the
991    /// rigid-body it will be attached to.
992    pub fn rotation(mut self, angle: AngVector<Real>) -> Self {
993        self.position.rotation = Rotation::new(angle);
994        self
995    }
996
997    /// Sets the initial position (translation and orientation) of the collider to be created.
998    ///
999    /// If the collider will be attached to a rigid-body, this sets the position relative
1000    /// to the rigid-body it will be attached to.
1001    pub fn position(mut self, pos: Isometry<Real>) -> Self {
1002        self.position = pos;
1003        self
1004    }
1005
1006    /// Sets the initial position (translation and orientation) of the collider to be created,
1007    /// relative to the rigid-body it is attached to.
1008    #[deprecated(note = "Use `.position` instead.")]
1009    pub fn position_wrt_parent(mut self, pos: Isometry<Real>) -> Self {
1010        self.position = pos;
1011        self
1012    }
1013
1014    /// Set the position of this collider in the local-space of the rigid-body it is attached to.
1015    #[deprecated(note = "Use `.position` instead.")]
1016    pub fn delta(mut self, delta: Isometry<Real>) -> Self {
1017        self.position = delta;
1018        self
1019    }
1020
1021    /// Sets the contact skin of the collider.
1022    ///
1023    /// The contact skin acts as if the collider was enlarged with a skin of width `skin_thickness`
1024    /// around it, keeping objects further apart when colliding.
1025    ///
1026    /// A non-zero contact skin can increase performance, and in some cases, stability. However
1027    /// it creates a small gap between colliding object (equal to the sum of their skin). If the
1028    /// skin is sufficiently small, this might not be visually significant or can be hidden by the
1029    /// rendering assets.
1030    pub fn contact_skin(mut self, skin_thickness: Real) -> Self {
1031        self.contact_skin = skin_thickness;
1032        self
1033    }
1034
1035    /// Enable or disable the collider after its creation.
1036    pub fn enabled(mut self, enabled: bool) -> Self {
1037        self.enabled = enabled;
1038        self
1039    }
1040
1041    /// Builds a new collider attached to the given rigid-body.
1042    pub fn build(&self) -> Collider {
1043        let shape = self.shape.clone();
1044        let material = ColliderMaterial {
1045            friction: self.friction,
1046            restitution: self.restitution,
1047            friction_combine_rule: self.friction_combine_rule,
1048            restitution_combine_rule: self.restitution_combine_rule,
1049        };
1050        let flags = ColliderFlags {
1051            collision_groups: self.collision_groups,
1052            solver_groups: self.solver_groups,
1053            active_collision_types: self.active_collision_types,
1054            active_hooks: self.active_hooks,
1055            active_events: self.active_events,
1056            enabled: if self.enabled {
1057                ColliderEnabled::Enabled
1058            } else {
1059                ColliderEnabled::Disabled
1060            },
1061        };
1062        let changes = ColliderChanges::all();
1063        let pos = ColliderPosition(self.position);
1064        let coll_type = if self.is_sensor {
1065            ColliderType::Sensor
1066        } else {
1067            ColliderType::Solid
1068        };
1069
1070        Collider {
1071            shape,
1072            mprops: self.mass_properties.clone(),
1073            material,
1074            parent: None,
1075            changes,
1076            pos,
1077            flags,
1078            coll_type,
1079            contact_force_event_threshold: self.contact_force_event_threshold,
1080            contact_skin: self.contact_skin,
1081            user_data: self.user_data,
1082        }
1083    }
1084}
1085
1086impl From<ColliderBuilder> for Collider {
1087    fn from(val: ColliderBuilder) -> Collider {
1088        val.build()
1089    }
1090}