1use crate::constants::linear_slop;
7use crate::geometry::{CollisionPlane, PlaneSolverResult};
8use crate::math_functions::{
9 abs_float, clamp_float, dot, min_float, mul_add, mul_sub, plane_separation, Vec3,
10};
11
12pub fn solve_planes(target_delta: Vec3, planes: &mut [CollisionPlane]) -> PlaneSolverResult {
15 for plane in planes.iter_mut() {
16 plane.push = 0.0;
17 }
18
19 let mut delta = target_delta;
20 let tolerance = linear_slop();
21
22 let mut iteration = 0;
23 while iteration < 20 {
24 let mut total_push = 0.0;
25 for plane in planes.iter_mut() {
26 let separation = plane_separation(plane.plane, delta) + linear_slop();
28
29 let mut push = -separation;
30
31 let accumulated_push = plane.push;
33 plane.push = clamp_float(plane.push + push, 0.0, plane.push_limit);
34 push = plane.push - accumulated_push;
35 delta = mul_add(delta, push, plane.plane.normal);
36
37 total_push += abs_float(push);
39 }
40
41 if total_push < tolerance {
42 break;
43 }
44
45 iteration += 1;
46 }
47
48 PlaneSolverResult {
49 delta,
50 iteration_count: iteration,
51 }
52}
53
54pub fn clip_vector(vector: Vec3, planes: &[CollisionPlane]) -> Vec3 {
57 let mut v = vector;
58
59 for plane in planes {
60 if plane.push == 0.0 || !plane.clip_velocity {
61 continue;
62 }
63
64 v = mul_sub(
65 v,
66 min_float(0.0, dot(v, plane.plane.normal)),
67 plane.plane.normal,
68 );
69 }
70
71 v
72}