1#![allow(clippy::unnecessary_cast)]
15
16use crate::collision::{Capsule, Circle, Polygon, Segment, ShapeGeometry};
17use crate::math_functions::{
18 round_down_float, round_up_float, transform_world_point, Aabb, Vec2, WorldTransform,
19};
20
21fn compute_circle_fat_aabb(shape: &Circle, xf: WorldTransform, extra: f32) -> Aabb {
22 let c = transform_world_point(xf, shape.center);
23 let r = shape.radius as f64 + extra as f64;
24 Aabb {
25 lower_bound: Vec2 {
26 x: round_down_float(c.x as f64 - r),
27 y: round_down_float(c.y as f64 - r),
28 },
29 upper_bound: Vec2 {
30 x: round_up_float(c.x as f64 + r),
31 y: round_up_float(c.y as f64 + r),
32 },
33 }
34}
35
36fn compute_capsule_fat_aabb(shape: &Capsule, xf: WorldTransform, extra: f32) -> Aabb {
37 let v1 = transform_world_point(xf, shape.center1);
38 let v2 = transform_world_point(xf, shape.center2);
39 let r = shape.radius as f64 + extra as f64;
40 let (v1x, v1y) = (v1.x as f64, v1.y as f64);
41 let (v2x, v2y) = (v2.x as f64, v2.y as f64);
42 Aabb {
43 lower_bound: Vec2 {
44 x: round_down_float(if v1x < v2x { v1x } else { v2x } - r),
45 y: round_down_float(if v1y < v2y { v1y } else { v2y } - r),
46 },
47 upper_bound: Vec2 {
48 x: round_up_float(if v1x > v2x { v1x } else { v2x } + r),
49 y: round_up_float(if v1y > v2y { v1y } else { v2y } + r),
50 },
51 }
52}
53
54fn compute_polygon_fat_aabb(shape: &Polygon, xf: WorldTransform, extra: f32) -> Aabb {
55 debug_assert!(shape.count > 0);
56 let v = transform_world_point(xf, shape.vertices[0]);
57 let (mut lx, mut ly, mut ux, mut uy) = (v.x as f64, v.y as f64, v.x as f64, v.y as f64);
58
59 for i in 1..shape.count as usize {
60 let v = transform_world_point(xf, shape.vertices[i]);
61 let (vx, vy) = (v.x as f64, v.y as f64);
62 lx = if vx < lx { vx } else { lx };
63 ly = if vy < ly { vy } else { ly };
64 ux = if vx > ux { vx } else { ux };
65 uy = if vy > uy { vy } else { uy };
66 }
67
68 let r = shape.radius as f64 + extra as f64;
69 Aabb {
70 lower_bound: Vec2 {
71 x: round_down_float(lx - r),
72 y: round_down_float(ly - r),
73 },
74 upper_bound: Vec2 {
75 x: round_up_float(ux + r),
76 y: round_up_float(uy + r),
77 },
78 }
79}
80
81fn compute_segment_fat_aabb(shape: &Segment, xf: WorldTransform, extra: f32) -> Aabb {
82 let v1 = transform_world_point(xf, shape.point1);
83 let v2 = transform_world_point(xf, shape.point2);
84 let e = extra as f64;
85 let (v1x, v1y) = (v1.x as f64, v1.y as f64);
86 let (v2x, v2y) = (v2.x as f64, v2.y as f64);
87 Aabb {
88 lower_bound: Vec2 {
89 x: round_down_float(if v1x < v2x { v1x } else { v2x } - e),
90 y: round_down_float(if v1y < v2y { v1y } else { v2y } - e),
91 },
92 upper_bound: Vec2 {
93 x: round_up_float(if v1x > v2x { v1x } else { v2x } + e),
94 y: round_up_float(if v1y > v2y { v1y } else { v2y } + e),
95 },
96 }
97}
98
99pub fn compute_circle_aabb(shape: &Circle, xf: WorldTransform) -> Aabb {
101 compute_circle_fat_aabb(shape, xf, 0.0)
102}
103
104pub fn compute_capsule_aabb(shape: &Capsule, xf: WorldTransform) -> Aabb {
106 compute_capsule_fat_aabb(shape, xf, 0.0)
107}
108
109pub fn compute_polygon_aabb(shape: &Polygon, xf: WorldTransform) -> Aabb {
111 compute_polygon_fat_aabb(shape, xf, 0.0)
112}
113
114pub fn compute_segment_aabb(shape: &Segment, xf: WorldTransform) -> Aabb {
116 compute_segment_fat_aabb(shape, xf, 0.0)
117}
118
119pub fn compute_fat_shape_aabb(geometry: &ShapeGeometry, xf: WorldTransform, extra: f32) -> Aabb {
121 match geometry {
122 ShapeGeometry::Capsule(capsule) => compute_capsule_fat_aabb(capsule, xf, extra),
123 ShapeGeometry::Circle(circle) => compute_circle_fat_aabb(circle, xf, extra),
124 ShapeGeometry::Polygon(polygon) => compute_polygon_fat_aabb(polygon, xf, extra),
125 ShapeGeometry::Segment(segment) => compute_segment_fat_aabb(segment, xf, extra),
126 ShapeGeometry::ChainSegment(chain_segment) => {
127 compute_segment_fat_aabb(&chain_segment.segment, xf, extra)
128 }
129 }
130}