box2d_rust/math_functions/
transform.rs1use super::*;
5
6pub fn transform_point(t: Transform, p: Vec2) -> Vec2 {
8 let x = (t.q.c * p.x - t.q.s * p.y) + t.p.x;
9 let y = (t.q.s * p.x + t.q.c * p.y) + t.p.y;
10
11 Vec2 { x, y }
12}
13
14pub fn inv_transform_point(t: Transform, p: Vec2) -> Vec2 {
16 let vx = p.x - t.p.x;
17 let vy = p.y - t.p.y;
18 Vec2 {
19 x: t.q.c * vx + t.q.s * vy,
20 y: -t.q.s * vx + t.q.c * vy,
21 }
22}
23
24pub fn mul_transforms(a: Transform, b: Transform) -> Transform {
30 Transform {
31 q: mul_rot(a.q, b.q),
32 p: add(rotate_vector(a.q, b.p), a.p),
33 }
34}
35
36pub fn inv_mul_transforms(a: Transform, b: Transform) -> Transform {
40 Transform {
41 q: inv_mul_rot(a.q, b.q),
42 p: inv_rotate_vector(a.q, sub(b.p, a.p)),
43 }
44}
45
46pub fn to_pos(v: Vec2) -> Pos {
48 Pos {
49 x: v.x as _,
50 y: v.y as _,
51 }
52}
53
54pub fn to_vec2(p: Pos) -> Vec2 {
56 Vec2 {
57 x: p.x as f32,
58 y: p.y as f32,
59 }
60}
61
62#[cfg(feature = "double-precision")]
68pub fn round_down_float(x: f64) -> f32 {
69 let f = x as f32;
70 if f as f64 > x {
71 next_after_f32(f, f32::MIN)
72 } else {
73 f
74 }
75}
76
77#[cfg(feature = "double-precision")]
79pub fn round_up_float(x: f64) -> f32 {
80 let f = x as f32;
81 if (f as f64) < x {
82 next_after_f32(f, f32::MAX)
83 } else {
84 f
85 }
86}
87
88#[cfg(not(feature = "double-precision"))]
89pub fn round_down_float(x: f64) -> f32 {
90 x as f32
91}
92
93#[cfg(not(feature = "double-precision"))]
94pub fn round_up_float(x: f64) -> f32 {
95 x as f32
96}
97
98#[cfg(feature = "double-precision")]
100fn next_after_f32(from: f32, to: f32) -> f32 {
101 if from.is_nan() || to.is_nan() {
102 return f32::NAN;
103 }
104 if from == to {
105 return to;
106 }
107 if from == 0.0 {
108 return if to > 0.0 {
109 f32::from_bits(1)
110 } else {
111 -f32::from_bits(1)
112 };
113 }
114 let bits = from.to_bits();
115 let next = if (from < to) == (from > 0.0) {
116 bits + 1
117 } else {
118 bits - 1
119 };
120 f32::from_bits(next)
121}
122
123pub fn sub_pos(a: Pos, b: Pos) -> Vec2 {
125 Vec2 {
126 x: (a.x - b.x) as f32,
127 y: (a.y - b.y) as f32,
128 }
129}
130
131pub fn offset_pos(p: Pos, d: Vec2) -> Pos {
133 Pos {
134 x: p.x + d.x as PosScalar,
135 y: p.y + d.y as PosScalar,
136 }
137}
138
139pub fn lerp_position(a: Pos, b: Pos, t: f32) -> Pos {
141 Pos {
142 x: (1.0 - t) as PosScalar * a.x + t as PosScalar * b.x,
143 y: (1.0 - t) as PosScalar * a.y + t as PosScalar * b.y,
144 }
145}
146
147#[cfg(feature = "double-precision")]
148type PosScalar = f64;
149#[cfg(not(feature = "double-precision"))]
150type PosScalar = f32;
151
152pub fn transform_world_point(t: WorldTransform, p: Vec2) -> Pos {
154 let rx = t.q.c * p.x - t.q.s * p.y;
155 let ry = t.q.s * p.x + t.q.c * p.y;
156 Pos {
157 x: t.p.x + rx as PosScalar,
158 y: t.p.y + ry as PosScalar,
159 }
160}
161
162pub fn inv_transform_world_point(t: WorldTransform, p: Pos) -> Vec2 {
164 let vx = (p.x - t.p.x) as f32;
165 let vy = (p.y - t.p.y) as f32;
166 Vec2 {
167 x: t.q.c * vx + t.q.s * vy,
168 y: -t.q.s * vx + t.q.c * vy,
169 }
170}
171
172pub fn inv_mul_world_transforms(a: WorldTransform, b: WorldTransform) -> Transform {
174 let d = Vec2 {
175 x: (b.p.x - a.p.x) as f32,
176 y: (b.p.y - a.p.y) as f32,
177 };
178 Transform {
179 q: inv_mul_rot(a.q, b.q),
180 p: inv_rotate_vector(a.q, d),
181 }
182}
183
184pub fn offset_world_transform(a: WorldTransform, b: Transform) -> WorldTransform {
186 WorldTransform {
187 q: mul_rot(a.q, b.q),
188 p: offset_pos(a.p, rotate_vector(a.q, b.p)),
189 }
190}
191
192pub fn to_relative_transform(t: WorldTransform, base: Pos) -> Transform {
194 Transform {
195 q: t.q,
196 p: Vec2 {
197 x: (t.p.x - base.x) as f32,
198 y: (t.p.y - base.y) as f32,
199 },
200 }
201}
202
203pub fn make_world_transform(t: Transform) -> WorldTransform {
205 WorldTransform {
206 p: to_pos(t.p),
207 q: t.q,
208 }
209}
210
211pub fn mul_mv(a: Mat22, v: Vec2) -> Vec2 {
213 Vec2 {
214 x: a.cx.x * v.x + a.cy.x * v.y,
215 y: a.cx.y * v.x + a.cy.y * v.y,
216 }
217}
218
219pub fn get_inverse_22(a: Mat22) -> Mat22 {
221 let (m11, m12, m21, m22) = (a.cx.x, a.cy.x, a.cx.y, a.cy.y);
222 let mut det = m11 * m22 - m12 * m21;
223 if det != 0.0 {
224 det = 1.0 / det;
225 }
226
227 Mat22 {
228 cx: Vec2 {
229 x: det * m22,
230 y: -det * m21,
231 },
232 cy: Vec2 {
233 x: -det * m12,
234 y: det * m11,
235 },
236 }
237}
238
239pub fn solve_22(a: Mat22, b: Vec2) -> Vec2 {
242 let (a11, a12, a21, a22) = (a.cx.x, a.cy.x, a.cx.y, a.cy.y);
243 let mut det = a11 * a22 - a12 * a21;
244 if det != 0.0 {
245 det = 1.0 / det;
246 }
247 Vec2 {
248 x: det * (a22 * b.x - a12 * b.y),
249 y: det * (a11 * b.y - a21 * b.x),
250 }
251}