1use super::{Shape, ShapeGeometry};
8use crate::compound::{
9 collide_mover_and_compound, overlap_compound, ray_cast_compound, shape_cast_compound,
10};
11use crate::constants::MAX_SHAPE_CAST_POINTS;
12use crate::distance::{CastOutput, ShapeProxy};
13use crate::geometry::{
14 collide_mover_and_capsule, collide_mover_and_sphere, overlap_capsule, overlap_sphere,
15 ray_cast_capsule, ray_cast_sphere, shape_cast_capsule, shape_cast_sphere, Capsule, PlaneResult,
16 RayCastInput, ShapeCastInput,
17};
18use crate::height_field::{
19 collide_mover_and_height_field, overlap_height_field, ray_cast_height_field,
20 shape_cast_height_field,
21};
22use crate::hull::{
23 collide_mover_and_hull, compute_hull_projected_area, overlap_hull, ray_cast_hull,
24 shape_cast_hull,
25};
26use crate::math_functions::{
27 cross, inv_rotate_vector, inv_transform_point, length, min_int, rotate_vector, sub,
28 transform_point, Transform, Vec3, PI,
29};
30use crate::mesh::{collide_mover_and_mesh, overlap_mesh, ray_cast_mesh, shape_cast_mesh, Mesh};
31
32pub fn get_shape_projected_area(shape: &Shape, plane_normal: Vec3) -> f32 {
35 match &shape.geometry {
36 ShapeGeometry::Capsule(capsule) => {
37 let radius = capsule.radius;
38 let axis = sub(capsule.center2, capsule.center1);
39 let projected_length = length(cross(axis, plane_normal));
40 let cylinder_area = 2.0 * radius * projected_length;
41 let sphere_area = PI * radius * radius;
42 sphere_area + cylinder_area
43 }
44 ShapeGeometry::Hull(hull) => compute_hull_projected_area(hull, plane_normal),
45 ShapeGeometry::Sphere(sphere) => PI * sphere.radius * sphere.radius,
46 _ => 0.0,
47 }
48}
49
50pub fn ray_cast_shape(shape: &Shape, transform: Transform, input: &RayCastInput) -> CastOutput {
53 let local_input = RayCastInput {
54 origin: inv_transform_point(transform, input.origin),
55 translation: inv_rotate_vector(transform.q, input.translation),
56 max_fraction: input.max_fraction,
57 };
58
59 let mut output = match &shape.geometry {
60 ShapeGeometry::Capsule(capsule) => ray_cast_capsule(capsule, &local_input),
61 ShapeGeometry::Compound(compound) => ray_cast_compound(compound, &local_input),
62 ShapeGeometry::Sphere(sphere) => ray_cast_sphere(sphere, &local_input),
63 ShapeGeometry::Hull(hull) => ray_cast_hull(hull, &local_input),
64 ShapeGeometry::Mesh { data, scale } => {
65 let mesh = Mesh::new(data, *scale);
66 ray_cast_mesh(&mesh, &local_input)
67 }
68 ShapeGeometry::HeightField(height_field) => {
69 ray_cast_height_field(height_field, &local_input)
70 }
71 };
72
73 output.point = transform_point(transform, output.point);
74 output.normal = rotate_vector(transform.q, output.normal);
75 output
76}
77
78pub fn shape_cast_shape(shape: &Shape, transform: Transform, input: &ShapeCastInput) -> CastOutput {
80 let mut local_points = [Vec3::default(); MAX_SHAPE_CAST_POINTS];
81 let count = min_int(input.proxy.count, MAX_SHAPE_CAST_POINTS as i32);
82 for i in 0..count {
83 local_points[i as usize] = inv_transform_point(transform, input.proxy.points[i as usize]);
84 }
85
86 let mut local_input = *input;
87 local_input.proxy.count = count;
88 local_input.proxy.points = local_points;
89 local_input.translation = inv_rotate_vector(transform.q, input.translation);
90
91 let mut output = match &shape.geometry {
92 ShapeGeometry::Capsule(capsule) => shape_cast_capsule(capsule, &local_input),
93 ShapeGeometry::Compound(compound) => shape_cast_compound(compound, &local_input),
94 ShapeGeometry::HeightField(height_field) => {
95 shape_cast_height_field(height_field, &local_input)
96 }
97 ShapeGeometry::Hull(hull) => shape_cast_hull(hull, &local_input),
98 ShapeGeometry::Mesh { data, scale } => {
99 let mesh = Mesh::new(data, *scale);
100 shape_cast_mesh(&mesh, &local_input)
101 }
102 ShapeGeometry::Sphere(sphere) => shape_cast_sphere(sphere, &local_input),
103 };
104
105 output.point = transform_point(transform, output.point);
106 output.normal = rotate_vector(transform.q, output.normal);
107 output
108}
109
110pub fn overlap_shape(shape: &Shape, transform: Transform, proxy: &ShapeProxy) -> bool {
112 match &shape.geometry {
113 ShapeGeometry::Capsule(capsule) => overlap_capsule(capsule, transform, proxy),
114 ShapeGeometry::Compound(compound) => overlap_compound(compound, transform, proxy),
115 ShapeGeometry::HeightField(height_field) => {
116 overlap_height_field(height_field, transform, proxy)
117 }
118 ShapeGeometry::Hull(hull) => overlap_hull(hull, transform, proxy),
119 ShapeGeometry::Mesh { data, scale } => {
120 let mesh = Mesh::new(data, *scale);
121 overlap_mesh(&mesh, transform, proxy)
122 }
123 ShapeGeometry::Sphere(sphere) => overlap_sphere(sphere, transform, proxy),
124 }
125}
126
127pub fn collide_mover(
131 planes: &mut [PlaneResult],
132 shape: &Shape,
133 transform: Transform,
134 mover: &Capsule,
135) -> i32 {
136 let plane_capacity = planes.len() as i32;
137 if plane_capacity == 0 {
138 return 0;
139 }
140
141 let local_mover = Capsule {
142 center1: inv_transform_point(transform, mover.center1),
143 center2: inv_transform_point(transform, mover.center2),
144 radius: mover.radius,
145 };
146
147 let plane_count = match &shape.geometry {
148 ShapeGeometry::Capsule(capsule) => {
149 collide_mover_and_capsule(&mut planes[0], capsule, &local_mover)
150 }
151 ShapeGeometry::Compound(compound) => {
152 collide_mover_and_compound(planes, compound, &local_mover)
153 }
154 ShapeGeometry::Sphere(sphere) => {
155 collide_mover_and_sphere(&mut planes[0], sphere, &local_mover)
156 }
157 ShapeGeometry::Hull(hull) => collide_mover_and_hull(&mut planes[0], hull, &local_mover),
158 ShapeGeometry::Mesh { data, scale } => {
159 let mesh = Mesh::new(data, *scale);
160 collide_mover_and_mesh(planes, &mesh, &local_mover)
161 }
162 ShapeGeometry::HeightField(height_field) => {
163 collide_mover_and_height_field(planes, height_field, &local_mover)
164 }
165 };
166
167 for i in 0..plane_count {
168 planes[i as usize].plane.normal =
169 rotate_vector(transform.q, planes[i as usize].plane.normal);
170 planes[i as usize].point = transform_point(transform, planes[i as usize].point);
171 }
172
173 plane_count
174}