box2d 3.0.0 A 2D physics engine for games
Searching...
No Matches
math.h
1// SPDX-FileCopyrightText: 2023 Erin Catto
3
4#pragma once
5
6#include "api.h"
7#include "types.h"
8
9#include <math.h>
10
12#define B2_MIN(A, B) ((A) < (B) ? (A) : (B))
13
15#define B2_MAX(A, B) ((A) > (B) ? (A) : (B))
16
18#define B2_ABS(A) ((A) > 0.0f ? (A) : -(A))
19
21#define B2_CLAMP(A, B, C) B2_MIN(B2_MAX(A, B), C)
22
23static const b2Vec2 b2Vec2_zero = {0.0f, 0.0f};
24static const b2Rot b2Rot_identity = {0.0f, 1.0f};
25static const b2Transform b2Transform_identity = {{0.0f, 0.0f}, {0.0f, 1.0f}};
26static const b2Mat22 b2Mat22_zero = {{0.0f, 0.0f}, {0.0f, 0.0f}};
27
29static inline float b2Dot(b2Vec2 a, b2Vec2 b)
30{
31 return a.x * b.x + a.y * b.y;
32}
33
35static inline float b2Cross(b2Vec2 a, b2Vec2 b)
36{
37 return a.x * b.y - a.y * b.x;
38}
39
42static inline b2Vec2 b2CrossVS(b2Vec2 v, float s)
43{
44 return B2_LITERAL(b2Vec2){s * v.y, -s * v.x};
45}
46
49static inline b2Vec2 b2CrossSV(float s, b2Vec2 v)
50{
51 return B2_LITERAL(b2Vec2){-s * v.y, s * v.x};
52}
53
55static inline b2Vec2 b2LeftPerp(b2Vec2 v)
56{
57 return B2_LITERAL(b2Vec2){-v.y, v.x};
58}
59
61static inline b2Vec2 b2RightPerp(b2Vec2 v)
62{
63 return B2_LITERAL(b2Vec2){v.y, -v.x};
64}
65
67static inline b2Vec2 b2Add(b2Vec2 a, b2Vec2 b)
68{
69 return B2_LITERAL(b2Vec2){a.x + b.x, a.y + b.y};
70}
71
73static inline b2Vec2 b2Sub(b2Vec2 a, b2Vec2 b)
74{
75 return B2_LITERAL(b2Vec2){a.x - b.x, a.y - b.y};
76}
77
79static inline b2Vec2 b2Neg(b2Vec2 a)
80{
81 return B2_LITERAL(b2Vec2){-a.x, -a.y};
82}
83
85static inline b2Vec2 b2Lerp(b2Vec2 a, b2Vec2 b, float t)
86{
87 return B2_LITERAL(b2Vec2){a.x + t * (b.x - a.x), a.y + t * (b.y - a.y)};
88}
89
91static inline b2Vec2 b2Mul(b2Vec2 a, b2Vec2 b)
92{
93 return B2_LITERAL(b2Vec2){a.x * b.x, a.y * b.y};
94}
95
97static inline b2Vec2 b2MulSV(float s, b2Vec2 v)
98{
99 return B2_LITERAL(b2Vec2){s * v.x, s * v.y};
100}
101
103static inline b2Vec2 b2MulAdd(b2Vec2 a, float s, b2Vec2 b)
104{
105 return B2_LITERAL(b2Vec2){a.x + s * b.x, a.y + s * b.y};
106}
107
109static inline b2Vec2 b2MulSub(b2Vec2 a, float s, b2Vec2 b)
110{
111 return B2_LITERAL(b2Vec2){a.x - s * b.x, a.y - s * b.y};
112}
113
115static inline b2Vec2 b2Abs(b2Vec2 a)
116{
117 b2Vec2 b;
118 b.x = B2_ABS(a.x);
119 b.y = B2_ABS(a.y);
120 return b;
121}
122
124static inline b2Vec2 b2Min(b2Vec2 a, b2Vec2 b)
125{
126 b2Vec2 c;
127 c.x = B2_MIN(a.x, b.x);
128 c.y = B2_MIN(a.y, b.y);
129 return c;
130}
131
133static inline b2Vec2 b2Max(b2Vec2 a, b2Vec2 b)
134{
135 b2Vec2 c;
136 c.x = B2_MAX(a.x, b.x);
137 c.y = B2_MAX(a.y, b.y);
138 return c;
139}
140
142static inline b2Vec2 b2Clamp(b2Vec2 v, b2Vec2 a, b2Vec2 b)
143{
144 b2Vec2 c;
145 c.x = B2_CLAMP(v.x, a.x, b.x);
146 c.y = B2_CLAMP(v.y, a.y, b.y);
147 return c;
148}
149
151static inline float b2Length(b2Vec2 v)
152{
153 return sqrtf(v.x * v.x + v.y * v.y);
154}
155
157static inline float b2LengthSquared(b2Vec2 v)
158{
159 return v.x * v.x + v.y * v.y;
160}
161
162static inline float b2Distance(b2Vec2 a, b2Vec2 b)
163{
164 float dx = b.x - a.x;
165 float dy = b.y - a.y;
166 return sqrtf(dx * dx + dy * dy);
167}
168
170static inline float b2DistanceSquared(b2Vec2 a, b2Vec2 b)
171{
172 b2Vec2 c = {b.x - a.x, b.y - a.y};
173 return c.x * c.x + c.y * c.y;
174}
175
177static inline b2Rot b2MakeRot(float angle)
178{
179 b2Rot q = {sinf(angle), cosf(angle)};
180 return q;
181}
182
184static inline float b2Rot_GetAngle(b2Rot q)
185{
186 return atan2f(q.s, q.c);
187}
188
190static inline b2Vec2 b2Rot_GetXAxis(b2Rot q)
191{
192 b2Vec2 v = {q.c, q.s};
193 return v;
194}
195
197static inline b2Vec2 b2Rot_GetYAxis(b2Rot q)
198{
199 b2Vec2 v = {-q.s, q.c};
200 return v;
201}
202
204static inline b2Rot b2MulRot(b2Rot q, b2Rot r)
205{
206 // [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc]
207 // [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc]
208 // s = qs * rc + qc * rs
209 // c = qc * rc - qs * rs
210 b2Rot qr;
211 qr.s = q.s * r.c + q.c * r.s;
212 qr.c = q.c * r.c - q.s * r.s;
213 return qr;
214}
215
217static inline b2Rot b2InvMulRot(b2Rot q, b2Rot r)
218{
219 // [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc]
220 // [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc]
221 // s = qc * rs - qs * rc
222 // c = qc * rc + qs * rs
223 b2Rot qr;
224 qr.s = q.c * r.s - q.s * r.c;
225 qr.c = q.c * r.c + q.s * r.s;
226 return qr;
227}
228
230static inline b2Vec2 b2RotateVector(b2Rot q, b2Vec2 v)
231{
232 return B2_LITERAL(b2Vec2){q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y};
233}
234
236static inline b2Vec2 b2InvRotateVector(b2Rot q, b2Vec2 v)
237{
238 return B2_LITERAL(b2Vec2){q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y};
239}
240
242static inline b2Vec2 b2TransformPoint(b2Transform xf, const b2Vec2 p)
243{
244 float x = (xf.q.c * p.x - xf.q.s * p.y) + xf.p.x;
245 float y = (xf.q.s * p.x + xf.q.c * p.y) + xf.p.y;
246
247 return B2_LITERAL(b2Vec2){x, y};
248}
249
251static inline b2Vec2 b2InvTransformPoint(b2Transform xf, const b2Vec2 p)
252{
253 float vx = p.x - xf.p.x;
254 float vy = p.y - xf.p.y;
255 return B2_LITERAL(b2Vec2){xf.q.c * vx + xf.q.s * vy, -xf.q.s * vx + xf.q.c * vy};
256}
257
260static inline b2Transform b2MulTransforms(b2Transform A, b2Transform B)
261{
262 b2Transform C;
263 C.q = b2MulRot(A.q, B.q);
264 C.p = b2Add(b2RotateVector(A.q, B.p), A.p);
265 return C;
266}
267
270static inline b2Transform b2InvMulTransforms(b2Transform A, b2Transform B)
271{
272 b2Transform C;
273 C.q = b2InvMulRot(A.q, B.q);
274 C.p = b2InvRotateVector(A.q, b2Sub(B.p, A.p));
275 return C;
276}
277
279static inline b2Vec2 b2MulMV(b2Mat22 A, b2Vec2 v)
280{
281 b2Vec2 u = {
282 A.cx.x * v.x + A.cy.x * v.y,
283 A.cx.y * v.x + A.cy.y * v.y,
284 };
285 return u;
286}
287
289static inline b2Mat22 b2GetInverse22(b2Mat22 A)
290{
291 float a = A.cx.x, b = A.cy.x, c = A.cx.y, d = A.cy.y;
292 float det = a * d - b * c;
293 if (det != 0.0f)
294 {
295 det = 1.0f / det;
296 }
297
298 b2Mat22 B = {
299 {det * d, -det * c},
300 {-det * b, det * a},
301 };
302 return B;
303}
304
306static inline bool b2AABB_Contains(b2AABB a, b2AABB b)
307{
308 bool s = true;
309 s = s && a.lowerBound.x <= b.lowerBound.x;
310 s = s && a.lowerBound.y <= b.lowerBound.y;
311 s = s && b.upperBound.x <= a.upperBound.x;
312 s = s && b.upperBound.y <= a.upperBound.y;
313 return s;
314}
315
316BOX2D_API bool b2IsValid(float a);
317BOX2D_API bool b2IsValidVec2(b2Vec2 v);
318
320BOX2D_API b2Vec2 b2Normalize(b2Vec2 v);
321
323BOX2D_API b2Vec2 b2NormalizeChecked(b2Vec2 v);
324
325BOX2D_API b2Vec2 b2GetLengthAndNormalize(float* length, b2Vec2 v);
types used by the Box2D API
float s
Sine and cosine.
Definition types.h:56
float x
coordinates
Definition types.h:49
#define B2_LITERAL(T)
Used for C literals like (b2Vec2){1.0f, 2.0f} where C++ requires b2Vec2{1.0f, 2.0f}.
Definition types.h:29
b2Vec2 cx
columns
Definition types.h:70
Axis-aligned bounding box.
Definition types.h:75
A 2-by-2 Matrix.
Definition types.h:68
2D rotation
Definition types.h:54
A 2D rigid transform.
Definition types.h:61
Definition types.h:47