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)]
20pub 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 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 pub fn parent(&self) -> Option<RigidBodyHandle> {
57 self.parent.map(|parent| parent.handle)
58 }
59
60 pub fn is_sensor(&self) -> bool {
62 self.coll_type.is_sensor()
63 }
64
65 pub fn copy_from(&mut self, other: &Collider) {
82 let Collider {
85 coll_type,
86 shape,
87 mprops,
88 changes: _changes, parent: _parent, 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 pub fn active_hooks(&self) -> ActiveHooks {
115 self.flags.active_hooks
116 }
117
118 pub fn set_active_hooks(&mut self, active_hooks: ActiveHooks) {
120 self.flags.active_hooks = active_hooks;
121 }
122
123 pub fn active_events(&self) -> ActiveEvents {
125 self.flags.active_events
126 }
127
128 pub fn set_active_events(&mut self, active_events: ActiveEvents) {
130 self.flags.active_events = active_events;
131 }
132
133 pub fn active_collision_types(&self) -> ActiveCollisionTypes {
135 self.flags.active_collision_types
136 }
137
138 pub fn set_active_collision_types(&mut self, active_collision_types: ActiveCollisionTypes) {
140 self.flags.active_collision_types = active_collision_types;
141 }
142
143 pub fn contact_skin(&self) -> Real {
147 self.contact_skin
148 }
149
150 pub fn set_contact_skin(&mut self, skin_thickness: Real) {
154 self.contact_skin = skin_thickness;
155 }
156
157 pub fn friction(&self) -> Real {
159 self.material.friction
160 }
161
162 pub fn set_friction(&mut self, coefficient: Real) {
164 self.material.friction = coefficient
165 }
166
167 pub fn friction_combine_rule(&self) -> CoefficientCombineRule {
171 self.material.friction_combine_rule
172 }
173
174 pub fn set_friction_combine_rule(&mut self, rule: CoefficientCombineRule) {
178 self.material.friction_combine_rule = rule;
179 }
180
181 pub fn restitution(&self) -> Real {
183 self.material.restitution
184 }
185
186 pub fn set_restitution(&mut self, coefficient: Real) {
188 self.material.restitution = coefficient
189 }
190
191 pub fn restitution_combine_rule(&self) -> CoefficientCombineRule {
195 self.material.restitution_combine_rule
196 }
197
198 pub fn set_restitution_combine_rule(&mut self, rule: CoefficientCombineRule) {
202 self.material.restitution_combine_rule = rule;
203 }
204
205 pub fn set_contact_force_event_threshold(&mut self, threshold: Real) {
207 self.contact_force_event_threshold = threshold;
208 }
209
210 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 pub fn is_enabled(&self) -> bool {
224 matches!(self.flags.enabled, ColliderEnabled::Enabled)
225 }
226
227 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 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 pub fn set_rotation(&mut self, rotation: Rotation<Real>) {
253 self.changes.insert(ColliderChanges::POSITION);
254 self.pos.0.rotation = rotation;
255 }
256
257 pub fn set_position(&mut self, position: Isometry<Real>) {
259 self.changes.insert(ColliderChanges::POSITION);
260 self.pos.0 = position;
261 }
262
263 pub fn position(&self) -> &Isometry<Real> {
265 &self.pos
266 }
267
268 pub fn translation(&self) -> &Vector<Real> {
270 &self.pos.0.translation.vector
271 }
272
273 pub fn rotation(&self) -> &Rotation<Real> {
275 &self.pos.0.rotation
276 }
277
278 pub fn position_wrt_parent(&self) -> Option<&Isometry<Real>> {
280 self.parent.as_ref().map(|p| &p.pos_wrt_parent)
281 }
282
283 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 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 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 pub fn collision_groups(&self) -> InteractionGroups {
311 self.flags.collision_groups
312 }
313
314 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 pub fn solver_groups(&self) -> InteractionGroups {
324 self.flags.solver_groups
325 }
326
327 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 pub fn material(&self) -> &ColliderMaterial {
337 &self.material
338 }
339
340 pub fn volume(&self) -> Real {
342 self.shape.mass_properties(1.0).mass()
343 }
344
345 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 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 pub fn set_density(&mut self, density: Real) {
379 self.do_set_mass_properties(ColliderMassProps::Density(density));
380 }
381
382 pub fn set_mass(&mut self, mass: Real) {
392 self.do_set_mass_properties(ColliderMassProps::Mass(mass));
393 }
394
395 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 pub fn shape(&self) -> &dyn Shape {
414 self.shape.as_ref()
415 }
416
417 pub fn shape_mut(&mut self) -> &mut dyn Shape {
423 self.changes.insert(ColliderChanges::SHAPE);
424 self.shape.make_mut()
425 }
426
427 pub fn set_shape(&mut self, shape: SharedShape) {
429 self.changes.insert(ColliderChanges::SHAPE);
430 self.shape = shape;
431 }
432
433 pub fn shared_shape(&self) -> &SharedShape {
435 &self.shape
436 }
437
438 pub fn compute_aabb(&self) -> Aabb {
443 self.shape.compute_aabb(&self.pos)
444 }
445
446 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 pub fn compute_swept_aabb(&self, next_position: &Isometry<Real>) -> Aabb {
457 self.shape.compute_swept_aabb(&self.pos, next_position)
458 }
459
460 pub fn mass_properties(&self) -> MassProperties {
462 self.mprops.mass_properties(&*self.shape)
463 }
464
465 pub fn contact_force_event_threshold(&self) -> Real {
467 self.contact_force_event_threshold
468 }
469}
470
471#[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 pub shape: SharedShape,
478 pub mass_properties: ColliderMassProps,
480 pub friction: Real,
482 pub friction_combine_rule: CoefficientCombineRule,
484 pub restitution: Real,
486 pub restitution_combine_rule: CoefficientCombineRule,
488 pub position: Isometry<Real>,
490 pub is_sensor: bool,
492 pub active_collision_types: ActiveCollisionTypes,
494 pub active_hooks: ActiveHooks,
496 pub active_events: ActiveEvents,
498 pub user_data: u128,
500 pub collision_groups: InteractionGroups,
502 pub solver_groups: InteractionGroups,
504 pub enabled: bool,
506 pub contact_force_event_threshold: Real,
508 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 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 pub fn compound(shapes: Vec<(Isometry<Real>, SharedShape)>) -> Self {
544 Self::new(SharedShape::compound(shapes))
545 }
546
547 pub fn ball(radius: Real) -> Self {
549 Self::new(SharedShape::ball(radius))
550 }
551
552 pub fn halfspace(outward_normal: Unit<Vector<Real>>) -> Self {
555 Self::new(SharedShape::halfspace(outward_normal))
556 }
557
558 pub fn voxels(voxel_size: Vector<Real>, voxels: &[Point<i32>]) -> Self {
566 Self::new(SharedShape::voxels(voxel_size, voxels))
567 }
568
569 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 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 #[cfg(feature = "dim3")]
593 pub fn cylinder(half_height: Real, radius: Real) -> Self {
594 Self::new(SharedShape::cylinder(half_height, radius))
595 }
596
597 #[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 #[cfg(feature = "dim3")]
612 pub fn cone(half_height: Real, radius: Real) -> Self {
613 Self::new(SharedShape::cone(half_height, radius))
614 }
615
616 #[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 #[cfg(feature = "dim2")]
626 pub fn cuboid(hx: Real, hy: Real) -> Self {
627 Self::new(SharedShape::cuboid(hx, hy))
628 }
629
630 #[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 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 pub fn capsule_x(half_height: Real, radius: Real) -> Self {
649 Self::new(SharedShape::capsule_x(half_height, radius))
650 }
651
652 pub fn capsule_y(half_height: Real, radius: Real) -> Self {
654 Self::new(SharedShape::capsule_y(half_height, radius))
655 }
656
657 #[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 #[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 #[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 pub fn segment(a: Point<Real>, b: Point<Real>) -> Self {
678 Self::new(SharedShape::segment(a, b))
679 }
680
681 pub fn triangle(a: Point<Real>, b: Point<Real>, c: Point<Real>) -> Self {
683 Self::new(SharedShape::triangle(a, b, c))
684 }
685
686 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 pub fn polyline(vertices: Vec<Point<Real>>, indices: Option<Vec<[u32; 2]>>) -> Self {
698 Self::new(SharedShape::polyline(vertices, indices))
699 }
700
701 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 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 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 pub fn convex_decomposition(vertices: &[Point<Real>], indices: &[[u32; DIM]]) -> Self {
739 Self::new(SharedShape::convex_decomposition(vertices, indices))
740 }
741
742 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 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 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 pub fn convex_hull(points: &[Point<Real>]) -> Option<Self> {
787 SharedShape::convex_hull(points).map(Self::new)
788 }
789
790 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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 pub fn default_friction() -> Real {
860 0.5
861 }
862
863 pub fn default_density() -> Real {
865 100.0
866 }
867
868 pub fn user_data(mut self, data: u128) -> Self {
870 self.user_data = data;
871 self
872 }
873
874 pub fn collision_groups(mut self, groups: InteractionGroups) -> Self {
879 self.collision_groups = groups;
880 self
881 }
882
883 pub fn solver_groups(mut self, groups: InteractionGroups) -> Self {
888 self.solver_groups = groups;
889 self
890 }
891
892 pub fn sensor(mut self, is_sensor: bool) -> Self {
894 self.is_sensor = is_sensor;
895 self
896 }
897
898 pub fn active_hooks(mut self, active_hooks: ActiveHooks) -> Self {
900 self.active_hooks = active_hooks;
901 self
902 }
903
904 pub fn active_events(mut self, active_events: ActiveEvents) -> Self {
906 self.active_events = active_events;
907 self
908 }
909
910 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 pub fn friction(mut self, friction: Real) -> Self {
918 self.friction = friction;
919 self
920 }
921
922 pub fn friction_combine_rule(mut self, rule: CoefficientCombineRule) -> Self {
924 self.friction_combine_rule = rule;
925 self
926 }
927
928 pub fn restitution(mut self, restitution: Real) -> Self {
930 self.restitution = restitution;
931 self
932 }
933
934 pub fn restitution_combine_rule(mut self, rule: CoefficientCombineRule) -> Self {
936 self.restitution_combine_rule = rule;
937 self
938 }
939
940 pub fn density(mut self, density: Real) -> Self {
948 self.mass_properties = ColliderMassProps::Density(density);
949 self
950 }
951
952 pub fn mass(mut self, mass: Real) -> Self {
960 self.mass_properties = ColliderMassProps::Mass(mass);
961 self
962 }
963
964 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 pub fn contact_force_event_threshold(mut self, threshold: Real) -> Self {
975 self.contact_force_event_threshold = threshold;
976 self
977 }
978
979 pub fn translation(mut self, translation: Vector<Real>) -> Self {
984 self.position.translation.vector = translation;
985 self
986 }
987
988 pub fn rotation(mut self, angle: AngVector<Real>) -> Self {
993 self.position.rotation = Rotation::new(angle);
994 self
995 }
996
997 pub fn position(mut self, pos: Isometry<Real>) -> Self {
1002 self.position = pos;
1003 self
1004 }
1005
1006 #[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 #[deprecated(note = "Use `.position` instead.")]
1016 pub fn delta(mut self, delta: Isometry<Real>) -> Self {
1017 self.position = delta;
1018 self
1019 }
1020
1021 pub fn contact_skin(mut self, skin_thickness: Real) -> Self {
1031 self.contact_skin = skin_thickness;
1032 self
1033 }
1034
1035 pub fn enabled(mut self, enabled: bool) -> Self {
1037 self.enabled = enabled;
1038 self
1039 }
1040
1041 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}