1#[cfg(feature = "dim2")]
2use na::DVector;
3#[cfg(all(feature = "dim3", feature = "async-collider"))]
4use {
5 bevy::mesh::{Indices, VertexAttributeValues},
6 bevy::prelude::*,
7};
8
9use rapier::{
10 parry::transformation::voxelization::FillMode,
11 prelude::{FeatureId, Point, Ray, SharedShape, Vector, Voxels, DIM},
12};
13
14use super::{get_snapped_scale, shape_views::*};
15#[cfg(all(feature = "dim3", feature = "async-collider"))]
16use crate::geometry::ComputedColliderShape;
17use crate::math::{Real, Rot, Vect};
18use crate::{
19 geometry::{Collider, PointProjection, RayIntersection, TriMeshFlags, VHACDParameters},
20 math::IVect,
21};
22
23impl Collider {
24 pub fn scale(&self) -> Vect {
26 self.scale
27 }
28
29 pub fn promote_scaled_shape(&mut self) {
32 self.unscaled = self.raw.clone();
33 self.scale = Vect::ONE;
34 }
35
36 pub fn compound(shapes: Vec<(Vect, Rot, Collider)>) -> Self {
38 let shapes = shapes
39 .into_iter()
40 .map(|(t, r, s)| ((t, r).into(), s.raw))
41 .collect();
42 SharedShape::compound(shapes).into()
43 }
44
45 pub fn ball(radius: Real) -> Self {
47 SharedShape::ball(radius).into()
48 }
49
50 pub fn halfspace(outward_normal: Vect) -> Option<Self> {
53 use rapier::na::Unit;
54 let normal = Vector::from(outward_normal);
55 Unit::try_new(normal, 1.0e-6).map(|n| SharedShape::halfspace(n).into())
56 }
57
58 #[cfg(feature = "dim3")]
61 pub fn cylinder(half_height: Real, radius: Real) -> Self {
62 SharedShape::cylinder(half_height, radius).into()
63 }
64
65 #[cfg(feature = "dim3")]
69 pub fn round_cylinder(half_height: Real, radius: Real, border_radius: Real) -> Self {
70 SharedShape::round_cylinder(half_height, radius, border_radius).into()
71 }
72
73 #[cfg(feature = "dim3")]
76 pub fn cone(half_height: Real, radius: Real) -> Self {
77 SharedShape::cone(half_height, radius).into()
78 }
79
80 #[cfg(feature = "dim3")]
84 pub fn round_cone(half_height: Real, radius: Real, border_radius: Real) -> Self {
85 SharedShape::round_cone(half_height, radius, border_radius).into()
86 }
87
88 #[cfg(feature = "dim2")]
90 pub fn cuboid(half_x: Real, half_y: Real) -> Self {
91 SharedShape::cuboid(half_x, half_y).into()
92 }
93
94 #[cfg(feature = "dim2")]
97 pub fn round_cuboid(half_x: Real, half_y: Real, border_radius: Real) -> Self {
98 SharedShape::round_cuboid(half_x, half_y, border_radius).into()
99 }
100
101 pub fn capsule(start: Vect, end: Vect, radius: Real) -> Self {
103 SharedShape::capsule(start.into(), end.into(), radius).into()
104 }
105
106 pub fn capsule_x(half_height: Real, radius: Real) -> Self {
108 let p = Point::from(Vector::x() * half_height);
109 SharedShape::capsule(-p, p, radius).into()
110 }
111
112 pub fn capsule_y(half_height: Real, radius: Real) -> Self {
114 let p = Point::from(Vector::y() * half_height);
115 SharedShape::capsule(-p, p, radius).into()
116 }
117
118 #[cfg(feature = "dim3")]
120 pub fn capsule_z(half_height: Real, radius: Real) -> Self {
121 let p = Point::from(Vector::z() * half_height);
122 SharedShape::capsule(-p, p, radius).into()
123 }
124
125 #[cfg(feature = "dim3")]
127 pub fn cuboid(hx: Real, hy: Real, hz: Real) -> Self {
128 SharedShape::cuboid(hx, hy, hz).into()
129 }
130
131 #[cfg(feature = "dim3")]
134 pub fn round_cuboid(half_x: Real, half_y: Real, half_z: Real, border_radius: Real) -> Self {
135 SharedShape::round_cuboid(half_x, half_y, half_z, border_radius).into()
136 }
137
138 pub fn segment(a: Vect, b: Vect) -> Self {
140 SharedShape::segment(a.into(), b.into()).into()
141 }
142
143 pub fn triangle(a: Vect, b: Vect, c: Vect) -> Self {
145 SharedShape::triangle(a.into(), b.into(), c.into()).into()
146 }
147
148 pub fn round_triangle(a: Vect, b: Vect, c: Vect, border_radius: Real) -> Self {
150 SharedShape::round_triangle(a.into(), b.into(), c.into(), border_radius).into()
151 }
152
153 fn ivec_array_from_point_int_array(points: &[IVect]) -> Vec<Point<i32>> {
154 points
155 .iter()
156 .map(|p| {
157 #[cfg(feature = "dim3")]
158 return Point::new(p.x, p.y, p.z);
159 #[cfg(feature = "dim2")]
160 return Point::new(p.x, p.y);
161 })
162 .collect::<Vec<_>>()
163 }
164
165 fn vec_array_from_point_float_array(points: &[Vect]) -> Vec<Point<Real>> {
166 points
167 .iter()
168 .map(|p| {
169 #[cfg(feature = "dim3")]
170 return Point::new(p.x, p.y, p.z);
171 #[cfg(feature = "dim2")]
172 return Point::new(p.x, p.y);
173 })
174 .collect::<Vec<_>>()
175 }
176
177 pub fn voxels(voxel_size: Vect, grid_coordinates: &[IVect]) -> Self {
187 let shape = Voxels::new(
188 voxel_size.into(),
189 &Self::ivec_array_from_point_int_array(grid_coordinates),
190 );
191 SharedShape::new(shape).into()
192 }
193
194 pub fn voxels_from_points(voxel_size: Vect, points: &[Vect]) -> Self {
199 SharedShape::voxels_from_points(
200 voxel_size.into(),
201 &Self::vec_array_from_point_float_array(points),
202 )
203 .into()
204 }
205
206 pub fn voxelized_mesh(
209 vertices: &[Vect],
210 indices: &[[u32; DIM]],
211 voxel_size: Real,
212 fill_mode: FillMode,
213 ) -> Self {
214 let vertices = Self::vec_array_from_point_float_array(vertices);
215 SharedShape::voxelized_mesh(&vertices, indices, voxel_size, fill_mode).into()
216 }
217
218 pub fn voxelized_convex_decomposition(vertices: &[Vect], indices: &[[u32; DIM]]) -> Vec<Self> {
221 Self::voxelized_convex_decomposition_with_params(
222 vertices,
223 indices,
224 &VHACDParameters::default(),
225 )
226 }
227
228 pub fn voxelized_convex_decomposition_with_params(
231 vertices: &[Vect],
232 indices: &[[u32; DIM]],
233 params: &VHACDParameters,
234 ) -> Vec<Self> {
235 SharedShape::voxelized_convex_decomposition_with_params(
236 &Self::vec_array_from_point_float_array(vertices),
237 indices,
238 params,
239 )
240 .into_iter()
241 .map(|c| c.into())
242 .collect()
243 }
244
245 pub fn polyline(vertices: Vec<Vect>, indices: Option<Vec<[u32; 2]>>) -> Self {
247 let vertices = vertices.into_iter().map(|v| v.into()).collect();
248 SharedShape::polyline(vertices, indices).into()
249 }
250
251 pub fn trimesh(
253 vertices: Vec<Vect>,
254 indices: Vec<[u32; 3]>,
255 ) -> Result<Self, crate::rapier::prelude::TriMeshBuilderError> {
256 let vertices = vertices.into_iter().map(|v| v.into()).collect();
257 Ok(SharedShape::trimesh(vertices, indices)?.into())
258 }
259
260 pub fn trimesh_with_flags(
263 vertices: Vec<Vect>,
264 indices: Vec<[u32; 3]>,
265 flags: TriMeshFlags,
266 ) -> Result<Self, crate::rapier::prelude::TriMeshBuilderError> {
267 let vertices = vertices.into_iter().map(|v| v.into()).collect();
268 Ok(SharedShape::trimesh_with_flags(vertices, indices, flags)?.into())
269 }
270
271 #[cfg(all(feature = "dim3", feature = "async-collider"))]
275 pub fn from_bevy_mesh(mesh: &Mesh, collider_shape: &ComputedColliderShape) -> Option<Self> {
276 let (vtx, idx) = extract_mesh_vertices_indices(mesh)?;
277
278 match collider_shape {
279 ComputedColliderShape::TriMesh(flags) => Some(
280 SharedShape::trimesh_with_flags(vtx, idx, *flags)
281 .ok()?
282 .into(),
283 ),
284 ComputedColliderShape::ConvexHull => {
285 SharedShape::convex_hull(&vtx).map(|shape| shape.into())
286 }
287 ComputedColliderShape::ConvexDecomposition(params) => {
288 Some(SharedShape::convex_decomposition_with_params(&vtx, &idx, params).into())
289 }
290 }
291 }
292
293 pub fn convex_decomposition(vertices: &[Vect], indices: &[[u32; DIM]]) -> Self {
296 let vertices: Vec<_> = vertices.iter().map(|v| (*v).into()).collect();
297 SharedShape::convex_decomposition(&vertices, indices).into()
298 }
299
300 pub fn round_convex_decomposition(
303 vertices: &[Vect],
304 indices: &[[u32; DIM]],
305 border_radius: Real,
306 ) -> Self {
307 let vertices: Vec<_> = vertices.iter().map(|v| (*v).into()).collect();
308 SharedShape::round_convex_decomposition(&vertices, indices, border_radius).into()
309 }
310
311 pub fn convex_decomposition_with_params(
314 vertices: &[Vect],
315 indices: &[[u32; DIM]],
316 params: &VHACDParameters,
317 ) -> Self {
318 let vertices: Vec<_> = vertices.iter().map(|v| (*v).into()).collect();
319 SharedShape::convex_decomposition_with_params(&vertices, indices, params).into()
320 }
321
322 pub fn round_convex_decomposition_with_params(
325 vertices: &[Vect],
326 indices: &[[u32; DIM]],
327 params: &VHACDParameters,
328 border_radius: Real,
329 ) -> Self {
330 let vertices: Vec<_> = vertices.iter().map(|v| (*v).into()).collect();
331 SharedShape::round_convex_decomposition_with_params(
332 &vertices,
333 indices,
334 params,
335 border_radius,
336 )
337 .into()
338 }
339
340 pub fn convex_hull(points: &[Vect]) -> Option<Self> {
343 let points: Vec<_> = points.iter().map(|v| (*v).into()).collect();
344 SharedShape::convex_hull(&points).map(Into::into)
345 }
346
347 pub fn round_convex_hull(points: &[Vect], border_radius: Real) -> Option<Self> {
351 let points: Vec<_> = points.iter().map(|v| (*v).into()).collect();
352 SharedShape::round_convex_hull(&points, border_radius).map(Into::into)
353 }
354
355 #[cfg(feature = "dim2")]
359 pub fn convex_polyline(points: Vec<Vect>) -> Option<Self> {
360 let points = points.into_iter().map(|v| v.into()).collect();
361 SharedShape::convex_polyline(points).map(Into::into)
362 }
363
364 #[cfg(feature = "dim2")]
368 pub fn round_convex_polyline(points: Vec<Vect>, border_radius: Real) -> Option<Self> {
369 let points = points.into_iter().map(|v| v.into()).collect();
370 SharedShape::round_convex_polyline(points, border_radius).map(Into::into)
371 }
372
373 #[cfg(feature = "dim3")]
377 pub fn convex_mesh(points: Vec<Vect>, indices: &[[u32; 3]]) -> Option<Self> {
378 let points = points.into_iter().map(|v| v.into()).collect();
379 SharedShape::convex_mesh(points, indices).map(Into::into)
380 }
381
382 #[cfg(feature = "dim3")]
386 pub fn round_convex_mesh(
387 points: Vec<Vect>,
388 indices: &[[u32; 3]],
389 border_radius: Real,
390 ) -> Option<Self> {
391 let points = points.into_iter().map(|v| v.into()).collect();
392 SharedShape::round_convex_mesh(points, indices, border_radius).map(Into::into)
393 }
394
395 #[cfg(feature = "dim2")]
398 pub fn heightfield(heights: Vec<Real>, scale: Vect) -> Self {
399 SharedShape::heightfield(DVector::from_vec(heights), scale.into()).into()
400 }
401
402 #[cfg(feature = "dim3")]
405 pub fn heightfield(heights: Vec<Real>, num_rows: usize, num_cols: usize, scale: Vect) -> Self {
406 assert_eq!(
407 heights.len(),
408 num_rows * num_cols,
409 "Invalid number of heights provided."
410 );
411 let heights = rapier::na::DMatrix::from_vec(num_rows, num_cols, heights);
412 SharedShape::heightfield(heights, scale.into()).into()
413 }
414
415 pub fn as_typed_shape(&self) -> ColliderView<'_> {
417 self.raw.as_typed_shape().into()
418 }
419
420 pub fn as_unscaled_typed_shape(&self) -> ColliderView<'_> {
422 self.unscaled.as_typed_shape().into()
423 }
424
425 pub fn as_ball(&self) -> Option<BallView<'_>> {
427 self.raw.as_ball().map(|s| BallView { raw: s })
428 }
429
430 pub fn as_cuboid(&self) -> Option<CuboidView<'_>> {
432 self.raw.as_cuboid().map(|s| CuboidView { raw: s })
433 }
434
435 pub fn as_capsule(&self) -> Option<CapsuleView<'_>> {
437 self.raw.as_capsule().map(|s| CapsuleView { raw: s })
438 }
439
440 pub fn as_segment(&self) -> Option<SegmentView<'_>> {
442 self.raw.as_segment().map(|s| SegmentView { raw: s })
443 }
444
445 pub fn as_triangle(&self) -> Option<TriangleView<'_>> {
447 self.raw.as_triangle().map(|s| TriangleView { raw: s })
448 }
449
450 pub fn as_voxels(&self) -> Option<VoxelsView<'_>> {
452 self.raw.as_voxels().map(|s| VoxelsView { raw: s })
453 }
454
455 pub fn as_trimesh(&self) -> Option<TriMeshView<'_>> {
457 self.raw.as_trimesh().map(|s| TriMeshView { raw: s })
458 }
459
460 pub fn as_polyline(&self) -> Option<PolylineView<'_>> {
462 self.raw.as_polyline().map(|s| PolylineView { raw: s })
463 }
464
465 pub fn as_halfspace(&self) -> Option<HalfSpaceView<'_>> {
467 self.raw.as_halfspace().map(|s| HalfSpaceView { raw: s })
468 }
469
470 pub fn as_heightfield(&self) -> Option<HeightFieldView<'_>> {
472 self.raw
473 .as_heightfield()
474 .map(|s| HeightFieldView { raw: s })
475 }
476
477 pub fn as_compound(&self) -> Option<CompoundView<'_>> {
479 self.raw.as_compound().map(|s| CompoundView { raw: s })
480 }
481
482 #[cfg(feature = "dim2")]
484 pub fn as_convex_polygon(&self) -> Option<ConvexPolygonView<'_>> {
485 self.raw
486 .as_convex_polygon()
487 .map(|s| ConvexPolygonView { raw: s })
488 }
489
490 #[cfg(feature = "dim3")]
492 pub fn as_convex_polyhedron(&self) -> Option<ConvexPolyhedronView<'_>> {
493 self.raw
494 .as_convex_polyhedron()
495 .map(|s| ConvexPolyhedronView { raw: s })
496 }
497
498 #[cfg(feature = "dim3")]
500 pub fn as_cylinder(&self) -> Option<CylinderView<'_>> {
501 self.raw.as_cylinder().map(|s| CylinderView { raw: s })
502 }
503
504 #[cfg(feature = "dim3")]
506 pub fn as_cone(&self) -> Option<ConeView<'_>> {
507 self.raw.as_cone().map(|s| ConeView { raw: s })
508 }
509
510 pub fn as_ball_mut(&mut self) -> Option<BallViewMut<'_>> {
512 self.raw
513 .make_mut()
514 .as_ball_mut()
515 .map(|s| BallViewMut { raw: s })
516 }
517
518 pub fn as_cuboid_mut(&mut self) -> Option<CuboidViewMut<'_>> {
520 self.raw
521 .make_mut()
522 .as_cuboid_mut()
523 .map(|s| CuboidViewMut { raw: s })
524 }
525
526 pub fn as_capsule_mut(&mut self) -> Option<CapsuleViewMut<'_>> {
528 self.raw
529 .make_mut()
530 .as_capsule_mut()
531 .map(|s| CapsuleViewMut { raw: s })
532 }
533
534 pub fn as_segment_mut(&mut self) -> Option<SegmentViewMut<'_>> {
536 self.raw
537 .make_mut()
538 .as_segment_mut()
539 .map(|s| SegmentViewMut { raw: s })
540 }
541
542 pub fn as_triangle_mut(&mut self) -> Option<TriangleViewMut<'_>> {
544 self.raw
545 .make_mut()
546 .as_triangle_mut()
547 .map(|s| TriangleViewMut { raw: s })
548 }
549
550 pub fn as_voxels_mut(&mut self) -> Option<VoxelsViewMut<'_>> {
552 self.raw
553 .make_mut()
554 .as_voxels_mut()
555 .map(|s| VoxelsViewMut { raw: s })
556 }
557
558 pub fn as_trimesh_mut(&mut self) -> Option<TriMeshViewMut<'_>> {
560 self.raw
561 .make_mut()
562 .as_trimesh_mut()
563 .map(|s| TriMeshViewMut { raw: s })
564 }
565
566 pub fn as_polyline_mut(&mut self) -> Option<PolylineViewMut<'_>> {
568 self.raw
569 .make_mut()
570 .as_polyline_mut()
571 .map(|s| PolylineViewMut { raw: s })
572 }
573
574 pub fn as_halfspace_mut(&mut self) -> Option<HalfSpaceViewMut<'_>> {
576 self.raw
577 .make_mut()
578 .as_halfspace_mut()
579 .map(|s| HalfSpaceViewMut { raw: s })
580 }
581
582 pub fn as_heightfield_mut(&mut self) -> Option<HeightFieldViewMut<'_>> {
584 self.raw
585 .make_mut()
586 .as_heightfield_mut()
587 .map(|s| HeightFieldViewMut { raw: s })
588 }
589
590 #[cfg(feature = "dim3")]
615 pub fn as_cylinder_mut(&mut self) -> Option<CylinderViewMut<'_>> {
616 self.raw
617 .make_mut()
618 .as_cylinder_mut()
619 .map(|s| CylinderViewMut { raw: s })
620 }
621
622 #[cfg(feature = "dim3")]
624 pub fn as_cone_mut(&mut self) -> Option<ConeViewMut<'_>> {
625 self.raw
626 .make_mut()
627 .as_cone_mut()
628 .map(|s| ConeViewMut { raw: s })
629 }
630
631 pub fn set_scale(&mut self, scale: Vect, num_subdivisions: u32) {
639 let scale = get_snapped_scale(scale);
640
641 if scale == self.scale {
642 return;
644 }
645
646 if scale == Vect::ONE {
647 self.raw = self.unscaled.clone();
649 self.scale = Vect::ONE;
650 return;
651 }
652
653 if let Some(scaled) = self
654 .as_unscaled_typed_shape()
655 .raw_scale_by(scale, num_subdivisions)
656 {
657 self.raw = scaled;
658 self.scale = scale;
659 } else {
660 log::error!("Failed to create the scaled convex hull geometry.");
661 }
662 }
663
664 pub fn project_local_point_with_max_dist(
668 &self,
669 point: Vect,
670 solid: bool,
671 max_dist: Real,
672 ) -> Option<PointProjection> {
673 self.raw
674 .project_local_point_with_max_dist(&point.into(), solid, max_dist)
675 .map(Into::into)
676 }
677
678 pub fn project_point_with_max_dist(
680 &self,
681 translation: Vect,
682 rotation: Rot,
683 point: Vect,
684 solid: bool,
685 max_dist: Real,
686 ) -> Option<PointProjection> {
687 let pos = (translation, rotation).into();
688 self.raw
689 .project_point_with_max_dist(&pos, &point.into(), solid, max_dist)
690 .map(Into::into)
691 }
692
693 pub fn project_local_point(&self, point: Vect, solid: bool) -> PointProjection {
697 self.raw.project_local_point(&point.into(), solid).into()
698 }
699
700 pub fn project_local_point_and_get_feature(&self, point: Vect) -> (PointProjection, FeatureId) {
703 let (proj, feat) = self.raw.project_local_point_and_get_feature(&point.into());
704 (proj.into(), feat)
705 }
706
707 pub fn distance_to_local_point(&self, point: Vect, solid: bool) -> Real {
709 self.raw.distance_to_local_point(&point.into(), solid)
710 }
711
712 pub fn contains_local_point(&self, point: Vect) -> bool {
714 self.raw.contains_local_point(&point.into())
715 }
716
717 pub fn project_point(
719 &self,
720 translation: Vect,
721 rotation: Rot,
722 point: Vect,
723 solid: bool,
724 ) -> PointProjection {
725 let pos = (translation, rotation).into();
726 self.raw.project_point(&pos, &point.into(), solid).into()
727 }
728
729 #[inline]
731 pub fn distance_to_point(
732 &self,
733 translation: Vect,
734 rotation: Rot,
735 point: Vect,
736 solid: bool,
737 ) -> Real {
738 let pos = (translation, rotation).into();
739 self.raw.distance_to_point(&pos, &point.into(), solid)
740 }
741
742 pub fn project_point_and_get_feature(
745 &self,
746 translation: Vect,
747 rotation: Rot,
748 point: Vect,
749 ) -> (PointProjection, FeatureId) {
750 let pos = (translation, rotation).into();
751 let (proj, feat) = self.raw.project_point_and_get_feature(&pos, &point.into());
752 (proj.into(), feat)
753 }
754
755 pub fn contains_point(&self, translation: Vect, rotation: Rot, point: Vect) -> bool {
757 let pos = (translation, rotation).into();
758 self.raw.contains_point(&pos, &point.into())
759 }
760
761 pub fn cast_local_ray(
763 &self,
764 ray_origin: Vect,
765 ray_dir: Vect,
766 max_time_of_impact: Real,
767 solid: bool,
768 ) -> Option<Real> {
769 let ray = Ray::new(ray_origin.into(), ray_dir.into());
770 self.raw.cast_local_ray(&ray, max_time_of_impact, solid)
771 }
772
773 pub fn cast_local_ray_and_get_normal(
775 &self,
776 ray_origin: Vect,
777 ray_dir: Vect,
778 max_time_of_impact: Real,
779 solid: bool,
780 ) -> Option<RayIntersection> {
781 let ray = Ray::new(ray_origin.into(), ray_dir.into());
782 self.raw
783 .cast_local_ray_and_get_normal(&ray, max_time_of_impact, solid)
784 .map(|inter| RayIntersection::from_rapier(inter, ray_origin, ray_dir))
785 }
786
787 pub fn intersects_local_ray(
789 &self,
790 ray_origin: Vect,
791 ray_dir: Vect,
792 max_time_of_impact: Real,
793 ) -> bool {
794 let ray = Ray::new(ray_origin.into(), ray_dir.into());
795 self.raw.intersects_local_ray(&ray, max_time_of_impact)
796 }
797
798 pub fn cast_ray(
800 &self,
801 translation: Vect,
802 rotation: Rot,
803 ray_origin: Vect,
804 ray_dir: Vect,
805 max_time_of_impact: Real,
806 solid: bool,
807 ) -> Option<Real> {
808 let pos = (translation, rotation).into();
809 let ray = Ray::new(ray_origin.into(), ray_dir.into());
810 self.raw.cast_ray(&pos, &ray, max_time_of_impact, solid)
811 }
812
813 pub fn cast_ray_and_get_normal(
815 &self,
816 translation: Vect,
817 rotation: Rot,
818 ray_origin: Vect,
819 ray_dir: Vect,
820 max_time_of_impact: Real,
821 solid: bool,
822 ) -> Option<RayIntersection> {
823 let pos = (translation, rotation).into();
824 let ray = Ray::new(ray_origin.into(), ray_dir.into());
825 self.raw
826 .cast_ray_and_get_normal(&pos, &ray, max_time_of_impact, solid)
827 .map(|inter| RayIntersection::from_rapier(inter, ray_origin, ray_dir))
828 }
829
830 pub fn intersects_ray(
832 &self,
833 translation: Vect,
834 rotation: Rot,
835 ray_origin: Vect,
836 ray_dir: Vect,
837 max_time_of_impact: Real,
838 ) -> bool {
839 let pos = (translation, rotation).into();
840 let ray = Ray::new(ray_origin.into(), ray_dir.into());
841 self.raw.intersects_ray(&pos, &ray, max_time_of_impact)
842 }
843}
844
845impl Default for Collider {
846 fn default() -> Self {
847 Self::ball(0.5)
848 }
849}
850
851#[cfg(all(feature = "dim3", feature = "async-collider"))]
852#[allow(clippy::type_complexity)]
853fn extract_mesh_vertices_indices(mesh: &Mesh) -> Option<(Vec<na::Point3<Real>>, Vec<[u32; 3]>)> {
854 use rapier::na::point;
855
856 let vertices = mesh.attribute(Mesh::ATTRIBUTE_POSITION)?;
857 let indices = mesh.indices()?;
858
859 let vtx: Vec<_> = match vertices {
860 VertexAttributeValues::Float32(vtx) => Some(
861 vtx.chunks(3)
862 .map(|v| point![v[0] as Real, v[1] as Real, v[2] as Real])
863 .collect(),
864 ),
865 VertexAttributeValues::Float32x3(vtx) => Some(
866 vtx.iter()
867 .map(|v| point![v[0] as Real, v[1] as Real, v[2] as Real])
868 .collect(),
869 ),
870 _ => None,
871 }?;
872
873 let idx = match indices {
874 Indices::U16(idx) => idx
875 .chunks_exact(3)
876 .map(|i| [i[0] as u32, i[1] as u32, i[2] as u32])
877 .collect(),
878 Indices::U32(idx) => idx.chunks_exact(3).map(|i| [i[0], i[1], i[2]]).collect(),
879 };
880
881 Some((vtx, idx))
882}