box2d-ruby 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +336 -0
  4. data/examples/contact_events.rb +22 -0
  5. data/examples/debug_draw.rb +15 -0
  6. data/examples/falling_ball.rb +19 -0
  7. data/examples/rugl_debug_draw.rb +68 -0
  8. data/examples/stagecraft_debug_draw.rb +64 -0
  9. data/examples/support/box2d_debug_lines.rb +125 -0
  10. data/ext/box2d/CMakeLists.txt +35 -0
  11. data/ext/box2d/extconf.rb +42 -0
  12. data/ext/box2d/native.c +9 -0
  13. data/ext/box2d/vendor/box2d/LICENSE +21 -0
  14. data/ext/box2d/vendor/box2d/VERSION +1 -0
  15. data/ext/box2d/vendor/box2d/include/box2d/base.h +131 -0
  16. data/ext/box2d/vendor/box2d/include/box2d/box2d.h +1222 -0
  17. data/ext/box2d/vendor/box2d/include/box2d/collision.h +830 -0
  18. data/ext/box2d/vendor/box2d/include/box2d/id.h +144 -0
  19. data/ext/box2d/vendor/box2d/include/box2d/math_functions.h +761 -0
  20. data/ext/box2d/vendor/box2d/include/box2d/types.h +1457 -0
  21. data/ext/box2d/vendor/box2d/src/CMakeLists.txt +223 -0
  22. data/ext/box2d/vendor/box2d/src/aabb.c +132 -0
  23. data/ext/box2d/vendor/box2d/src/aabb.h +56 -0
  24. data/ext/box2d/vendor/box2d/src/arena_allocator.c +112 -0
  25. data/ext/box2d/vendor/box2d/src/arena_allocator.h +48 -0
  26. data/ext/box2d/vendor/box2d/src/array.c +8 -0
  27. data/ext/box2d/vendor/box2d/src/array.h +179 -0
  28. data/ext/box2d/vendor/box2d/src/atomic.h +79 -0
  29. data/ext/box2d/vendor/box2d/src/bitset.c +67 -0
  30. data/ext/box2d/vendor/box2d/src/bitset.h +65 -0
  31. data/ext/box2d/vendor/box2d/src/body.c +1884 -0
  32. data/ext/box2d/vendor/box2d/src/body.h +194 -0
  33. data/ext/box2d/vendor/box2d/src/box2d.natvis +41 -0
  34. data/ext/box2d/vendor/box2d/src/broad_phase.c +524 -0
  35. data/ext/box2d/vendor/box2d/src/broad_phase.h +83 -0
  36. data/ext/box2d/vendor/box2d/src/constants.h +54 -0
  37. data/ext/box2d/vendor/box2d/src/constraint_graph.c +322 -0
  38. data/ext/box2d/vendor/box2d/src/constraint_graph.h +58 -0
  39. data/ext/box2d/vendor/box2d/src/contact.c +650 -0
  40. data/ext/box2d/vendor/box2d/src/contact.h +148 -0
  41. data/ext/box2d/vendor/box2d/src/contact_solver.c +2120 -0
  42. data/ext/box2d/vendor/box2d/src/contact_solver.h +54 -0
  43. data/ext/box2d/vendor/box2d/src/core.c +178 -0
  44. data/ext/box2d/vendor/box2d/src/core.h +149 -0
  45. data/ext/box2d/vendor/box2d/src/ctz.h +112 -0
  46. data/ext/box2d/vendor/box2d/src/distance.c +1415 -0
  47. data/ext/box2d/vendor/box2d/src/distance_joint.c +556 -0
  48. data/ext/box2d/vendor/box2d/src/dynamic_tree.c +1989 -0
  49. data/ext/box2d/vendor/box2d/src/geometry.c +1028 -0
  50. data/ext/box2d/vendor/box2d/src/hull.c +328 -0
  51. data/ext/box2d/vendor/box2d/src/id_pool.c +79 -0
  52. data/ext/box2d/vendor/box2d/src/id_pool.h +35 -0
  53. data/ext/box2d/vendor/box2d/src/island.c +977 -0
  54. data/ext/box2d/vendor/box2d/src/island.h +89 -0
  55. data/ext/box2d/vendor/box2d/src/joint.c +1272 -0
  56. data/ext/box2d/vendor/box2d/src/joint.h +335 -0
  57. data/ext/box2d/vendor/box2d/src/manifold.c +1726 -0
  58. data/ext/box2d/vendor/box2d/src/math_functions.c +159 -0
  59. data/ext/box2d/vendor/box2d/src/motor_joint.c +283 -0
  60. data/ext/box2d/vendor/box2d/src/mouse_joint.c +214 -0
  61. data/ext/box2d/vendor/box2d/src/mover.c +73 -0
  62. data/ext/box2d/vendor/box2d/src/prismatic_joint.c +656 -0
  63. data/ext/box2d/vendor/box2d/src/revolute_joint.c +534 -0
  64. data/ext/box2d/vendor/box2d/src/sensor.c +389 -0
  65. data/ext/box2d/vendor/box2d/src/sensor.h +36 -0
  66. data/ext/box2d/vendor/box2d/src/shape.c +1714 -0
  67. data/ext/box2d/vendor/box2d/src/shape.h +123 -0
  68. data/ext/box2d/vendor/box2d/src/solver.c +2038 -0
  69. data/ext/box2d/vendor/box2d/src/solver.h +155 -0
  70. data/ext/box2d/vendor/box2d/src/solver_set.c +613 -0
  71. data/ext/box2d/vendor/box2d/src/solver_set.h +57 -0
  72. data/ext/box2d/vendor/box2d/src/table.c +238 -0
  73. data/ext/box2d/vendor/box2d/src/table.h +37 -0
  74. data/ext/box2d/vendor/box2d/src/timer.c +185 -0
  75. data/ext/box2d/vendor/box2d/src/types.c +151 -0
  76. data/ext/box2d/vendor/box2d/src/weld_joint.c +310 -0
  77. data/ext/box2d/vendor/box2d/src/wheel_joint.c +551 -0
  78. data/ext/box2d/vendor/box2d/src/world.c +3301 -0
  79. data/ext/box2d/vendor/box2d/src/world.h +192 -0
  80. data/generator/generate.rb +316 -0
  81. data/generator/layout_probe.c +507 -0
  82. data/generator/verify_layouts.rb +32 -0
  83. data/lib/box2d/body.rb +172 -0
  84. data/lib/box2d/body_definition.rb +38 -0
  85. data/lib/box2d/body_shapes.rb +135 -0
  86. data/lib/box2d/chain.rb +61 -0
  87. data/lib/box2d/debug_draw.rb +118 -0
  88. data/lib/box2d/events.rb +103 -0
  89. data/lib/box2d/fixed_stepper.rb +39 -0
  90. data/lib/box2d/handle.rb +46 -0
  91. data/lib/box2d/hit.rb +5 -0
  92. data/lib/box2d/joint.rb +197 -0
  93. data/lib/box2d/native.rb +1462 -0
  94. data/lib/box2d/native_loader.rb +45 -0
  95. data/lib/box2d/pixel_scale.rb +29 -0
  96. data/lib/box2d/shape.rb +109 -0
  97. data/lib/box2d/shape_definition.rb +44 -0
  98. data/lib/box2d/value_conversion.rb +80 -0
  99. data/lib/box2d/version.rb +7 -0
  100. data/lib/box2d/world.rb +135 -0
  101. data/lib/box2d/world_joints.rb +156 -0
  102. data/lib/box2d/world_queries.rb +122 -0
  103. data/lib/box2d/world_registry.rb +95 -0
  104. data/lib/box2d.rb +31 -0
  105. data/script/build_platform_gem.rb +24 -0
  106. data/script/deterministic_scene.rb +56 -0
  107. data/script/update_deterministic_snapshot.rb +11 -0
  108. data/script/verify_platform_gem.rb +24 -0
  109. metadata +164 -0
@@ -0,0 +1,761 @@
1
+ // SPDX-FileCopyrightText: 2023 Erin Catto
2
+ // SPDX-License-Identifier: MIT
3
+
4
+ #pragma once
5
+
6
+ #include "base.h"
7
+
8
+ #include <float.h>
9
+ #include <math.h>
10
+ #include <stdbool.h>
11
+
12
+ /**
13
+ * @defgroup math Math
14
+ * @brief Vector math types and functions
15
+ * @{
16
+ */
17
+
18
+ /// 2D vector
19
+ /// This can be used to represent a point or free vector
20
+ typedef struct b2Vec2
21
+ {
22
+ /// coordinates
23
+ float x, y;
24
+ } b2Vec2;
25
+
26
+ /// Cosine and sine pair
27
+ /// This uses a custom implementation designed for cross-platform determinism
28
+ typedef struct b2CosSin
29
+ {
30
+ /// cosine and sine
31
+ float cosine;
32
+ float sine;
33
+ } b2CosSin;
34
+
35
+ /// 2D rotation
36
+ /// This is similar to using a complex number for rotation
37
+ typedef struct b2Rot
38
+ {
39
+ /// cosine and sine
40
+ float c, s;
41
+ } b2Rot;
42
+
43
+ /// A 2D rigid transform
44
+ typedef struct b2Transform
45
+ {
46
+ b2Vec2 p;
47
+ b2Rot q;
48
+ } b2Transform;
49
+
50
+ /// A 2-by-2 Matrix
51
+ typedef struct b2Mat22
52
+ {
53
+ /// columns
54
+ b2Vec2 cx, cy;
55
+ } b2Mat22;
56
+
57
+ /// Axis-aligned bounding box
58
+ typedef struct b2AABB
59
+ {
60
+ b2Vec2 lowerBound;
61
+ b2Vec2 upperBound;
62
+ } b2AABB;
63
+
64
+ /// separation = dot(normal, point) - offset
65
+ typedef struct b2Plane
66
+ {
67
+ b2Vec2 normal;
68
+ float offset;
69
+ } b2Plane;
70
+
71
+ /**@}*/
72
+
73
+ /**
74
+ * @addtogroup math
75
+ * @{
76
+ */
77
+
78
+ /// https://en.wikipedia.org/wiki/Pi
79
+ #define B2_PI 3.14159265359f
80
+
81
+ static const b2Vec2 b2Vec2_zero = { 0.0f, 0.0f };
82
+ static const b2Rot b2Rot_identity = { 1.0f, 0.0f };
83
+ static const b2Transform b2Transform_identity = { { 0.0f, 0.0f }, { 1.0f, 0.0f } };
84
+ static const b2Mat22 b2Mat22_zero = { { 0.0f, 0.0f }, { 0.0f, 0.0f } };
85
+
86
+ /// @return the minimum of two integers
87
+ B2_INLINE int b2MinInt( int a, int b )
88
+ {
89
+ return a < b ? a : b;
90
+ }
91
+
92
+ /// @return the maximum of two integers
93
+ B2_INLINE int b2MaxInt( int a, int b )
94
+ {
95
+ return a > b ? a : b;
96
+ }
97
+
98
+ /// @return the absolute value of an integer
99
+ B2_INLINE int b2AbsInt( int a )
100
+ {
101
+ return a < 0 ? -a : a;
102
+ }
103
+
104
+ /// @return an integer clamped between a lower and upper bound
105
+ B2_INLINE int b2ClampInt( int a, int lower, int upper )
106
+ {
107
+ return a < lower ? lower : ( a > upper ? upper : a );
108
+ }
109
+
110
+ /// @return the minimum of two floats
111
+ B2_INLINE float b2MinFloat( float a, float b )
112
+ {
113
+ return a < b ? a : b;
114
+ }
115
+
116
+ /// @return the maximum of two floats
117
+ B2_INLINE float b2MaxFloat( float a, float b )
118
+ {
119
+ return a > b ? a : b;
120
+ }
121
+
122
+ /// @return the absolute value of a float
123
+ B2_INLINE float b2AbsFloat( float a )
124
+ {
125
+ return a < 0 ? -a : a;
126
+ }
127
+
128
+ /// @return a float clamped between a lower and upper bound
129
+ B2_INLINE float b2ClampFloat( float a, float lower, float upper )
130
+ {
131
+ return a < lower ? lower : ( a > upper ? upper : a );
132
+ }
133
+
134
+ /// Compute an approximate arctangent in the range [-pi, pi]
135
+ /// This is hand coded for cross-platform determinism. The atan2f
136
+ /// function in the standard library is not cross-platform deterministic.
137
+ /// Accurate to around 0.0023 degrees
138
+ B2_API float b2Atan2( float y, float x );
139
+
140
+ /// Compute the cosine and sine of an angle in radians. Implemented
141
+ /// for cross-platform determinism.
142
+ B2_API b2CosSin b2ComputeCosSin( float radians );
143
+
144
+ /// Vector dot product
145
+ B2_INLINE float b2Dot( b2Vec2 a, b2Vec2 b )
146
+ {
147
+ return a.x * b.x + a.y * b.y;
148
+ }
149
+
150
+ /// Vector cross product. In 2D this yields a scalar.
151
+ B2_INLINE float b2Cross( b2Vec2 a, b2Vec2 b )
152
+ {
153
+ return a.x * b.y - a.y * b.x;
154
+ }
155
+
156
+ /// Perform the cross product on a vector and a scalar. In 2D this produces a vector.
157
+ B2_INLINE b2Vec2 b2CrossVS( b2Vec2 v, float s )
158
+ {
159
+ return B2_LITERAL( b2Vec2 ){ s * v.y, -s * v.x };
160
+ }
161
+
162
+ /// Perform the cross product on a scalar and a vector. In 2D this produces a vector.
163
+ B2_INLINE b2Vec2 b2CrossSV( float s, b2Vec2 v )
164
+ {
165
+ return B2_LITERAL( b2Vec2 ){ -s * v.y, s * v.x };
166
+ }
167
+
168
+ /// Get a left pointing perpendicular vector. Equivalent to b2CrossSV(1.0f, v)
169
+ B2_INLINE b2Vec2 b2LeftPerp( b2Vec2 v )
170
+ {
171
+ return B2_LITERAL( b2Vec2 ){ -v.y, v.x };
172
+ }
173
+
174
+ /// Get a right pointing perpendicular vector. Equivalent to b2CrossVS(v, 1.0f)
175
+ B2_INLINE b2Vec2 b2RightPerp( b2Vec2 v )
176
+ {
177
+ return B2_LITERAL( b2Vec2 ){ v.y, -v.x };
178
+ }
179
+
180
+ /// Vector addition
181
+ B2_INLINE b2Vec2 b2Add( b2Vec2 a, b2Vec2 b )
182
+ {
183
+ return B2_LITERAL( b2Vec2 ){ a.x + b.x, a.y + b.y };
184
+ }
185
+
186
+ /// Vector subtraction
187
+ B2_INLINE b2Vec2 b2Sub( b2Vec2 a, b2Vec2 b )
188
+ {
189
+ return B2_LITERAL( b2Vec2 ){ a.x - b.x, a.y - b.y };
190
+ }
191
+
192
+ /// Vector negation
193
+ B2_INLINE b2Vec2 b2Neg( b2Vec2 a )
194
+ {
195
+ return B2_LITERAL( b2Vec2 ){ -a.x, -a.y };
196
+ }
197
+
198
+ /// Vector linear interpolation
199
+ /// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
200
+ B2_INLINE b2Vec2 b2Lerp( b2Vec2 a, b2Vec2 b, float t )
201
+ {
202
+ return B2_LITERAL( b2Vec2 ){ ( 1.0f - t ) * a.x + t * b.x, ( 1.0f - t ) * a.y + t * b.y };
203
+ }
204
+
205
+ /// Component-wise multiplication
206
+ B2_INLINE b2Vec2 b2Mul( b2Vec2 a, b2Vec2 b )
207
+ {
208
+ return B2_LITERAL( b2Vec2 ){ a.x * b.x, a.y * b.y };
209
+ }
210
+
211
+ /// Multiply a scalar and vector
212
+ B2_INLINE b2Vec2 b2MulSV( float s, b2Vec2 v )
213
+ {
214
+ return B2_LITERAL( b2Vec2 ){ s * v.x, s * v.y };
215
+ }
216
+
217
+ /// a + s * b
218
+ B2_INLINE b2Vec2 b2MulAdd( b2Vec2 a, float s, b2Vec2 b )
219
+ {
220
+ return B2_LITERAL( b2Vec2 ){ a.x + s * b.x, a.y + s * b.y };
221
+ }
222
+
223
+ /// a - s * b
224
+ B2_INLINE b2Vec2 b2MulSub( b2Vec2 a, float s, b2Vec2 b )
225
+ {
226
+ return B2_LITERAL( b2Vec2 ){ a.x - s * b.x, a.y - s * b.y };
227
+ }
228
+
229
+ /// Component-wise absolute vector
230
+ B2_INLINE b2Vec2 b2Abs( b2Vec2 a )
231
+ {
232
+ b2Vec2 b;
233
+ b.x = b2AbsFloat( a.x );
234
+ b.y = b2AbsFloat( a.y );
235
+ return b;
236
+ }
237
+
238
+ /// Component-wise minimum vector
239
+ B2_INLINE b2Vec2 b2Min( b2Vec2 a, b2Vec2 b )
240
+ {
241
+ b2Vec2 c;
242
+ c.x = b2MinFloat( a.x, b.x );
243
+ c.y = b2MinFloat( a.y, b.y );
244
+ return c;
245
+ }
246
+
247
+ /// Component-wise maximum vector
248
+ B2_INLINE b2Vec2 b2Max( b2Vec2 a, b2Vec2 b )
249
+ {
250
+ b2Vec2 c;
251
+ c.x = b2MaxFloat( a.x, b.x );
252
+ c.y = b2MaxFloat( a.y, b.y );
253
+ return c;
254
+ }
255
+
256
+ /// Component-wise clamp vector v into the range [a, b]
257
+ B2_INLINE b2Vec2 b2Clamp( b2Vec2 v, b2Vec2 a, b2Vec2 b )
258
+ {
259
+ b2Vec2 c;
260
+ c.x = b2ClampFloat( v.x, a.x, b.x );
261
+ c.y = b2ClampFloat( v.y, a.y, b.y );
262
+ return c;
263
+ }
264
+
265
+ /// Get the length of this vector (the norm)
266
+ B2_INLINE float b2Length( b2Vec2 v )
267
+ {
268
+ return sqrtf( v.x * v.x + v.y * v.y );
269
+ }
270
+
271
+ /// Get the distance between two points
272
+ B2_INLINE float b2Distance( b2Vec2 a, b2Vec2 b )
273
+ {
274
+ float dx = b.x - a.x;
275
+ float dy = b.y - a.y;
276
+ return sqrtf( dx * dx + dy * dy );
277
+ }
278
+
279
+ /// Convert a vector into a unit vector if possible, otherwise returns the zero vector.
280
+ /// todo MSVC is not inlining this function in several places per warning 4710
281
+ B2_INLINE b2Vec2 b2Normalize( b2Vec2 v )
282
+ {
283
+ float length = sqrtf( v.x * v.x + v.y * v.y );
284
+ if ( length < FLT_EPSILON )
285
+ {
286
+ return B2_LITERAL( b2Vec2 ){ 0.0f, 0.0f };
287
+ }
288
+
289
+ float invLength = 1.0f / length;
290
+ b2Vec2 n = { invLength * v.x, invLength * v.y };
291
+ return n;
292
+ }
293
+
294
+ /// Determines if the provided vector is normalized (norm(a) == 1).
295
+ B2_INLINE bool b2IsNormalized( b2Vec2 a )
296
+ {
297
+ float aa = b2Dot( a, a );
298
+ return b2AbsFloat( 1.0f - aa ) < 10.0f * FLT_EPSILON;
299
+ }
300
+
301
+ /// Convert a vector into a unit vector if possible, otherwise returns the zero vector. Also
302
+ /// outputs the length.
303
+ B2_INLINE b2Vec2 b2GetLengthAndNormalize( float* length, b2Vec2 v )
304
+ {
305
+ *length = sqrtf( v.x * v.x + v.y * v.y );
306
+ if ( *length < FLT_EPSILON )
307
+ {
308
+ return B2_LITERAL( b2Vec2 ){ 0.0f, 0.0f };
309
+ }
310
+
311
+ float invLength = 1.0f / *length;
312
+ b2Vec2 n = { invLength * v.x, invLength * v.y };
313
+ return n;
314
+ }
315
+
316
+ /// Normalize rotation
317
+ B2_INLINE b2Rot b2NormalizeRot( b2Rot q )
318
+ {
319
+ float mag = sqrtf( q.s * q.s + q.c * q.c );
320
+ float invMag = mag > 0.0 ? 1.0f / mag : 0.0f;
321
+ b2Rot qn = { q.c * invMag, q.s * invMag };
322
+ return qn;
323
+ }
324
+
325
+ /// Integrate rotation from angular velocity
326
+ /// @param q1 initial rotation
327
+ /// @param deltaAngle the angular displacement in radians
328
+ B2_INLINE b2Rot b2IntegrateRotation( b2Rot q1, float deltaAngle )
329
+ {
330
+ // dc/dt = -omega * sin(t)
331
+ // ds/dt = omega * cos(t)
332
+ // c2 = c1 - omega * h * s1
333
+ // s2 = s1 + omega * h * c1
334
+ b2Rot q2 = { q1.c - deltaAngle * q1.s, q1.s + deltaAngle * q1.c };
335
+ float mag = sqrtf( q2.s * q2.s + q2.c * q2.c );
336
+ float invMag = mag > 0.0 ? 1.0f / mag : 0.0f;
337
+ b2Rot qn = { q2.c * invMag, q2.s * invMag };
338
+ return qn;
339
+ }
340
+
341
+ /// Get the length squared of this vector
342
+ B2_INLINE float b2LengthSquared( b2Vec2 v )
343
+ {
344
+ return v.x * v.x + v.y * v.y;
345
+ }
346
+
347
+ /// Get the distance squared between points
348
+ B2_INLINE float b2DistanceSquared( b2Vec2 a, b2Vec2 b )
349
+ {
350
+ b2Vec2 c = { b.x - a.x, b.y - a.y };
351
+ return c.x * c.x + c.y * c.y;
352
+ }
353
+
354
+ /// Make a rotation using an angle in radians
355
+ B2_INLINE b2Rot b2MakeRot( float radians )
356
+ {
357
+ b2CosSin cs = b2ComputeCosSin( radians );
358
+ return B2_LITERAL( b2Rot ){ cs.cosine, cs.sine };
359
+ }
360
+
361
+ /// Compute the rotation between two unit vectors
362
+ B2_API b2Rot b2ComputeRotationBetweenUnitVectors( b2Vec2 v1, b2Vec2 v2 );
363
+
364
+ /// Is this rotation normalized?
365
+ B2_INLINE bool b2IsNormalizedRot( b2Rot q )
366
+ {
367
+ // larger tolerance due to failure on mingw 32-bit
368
+ float qq = q.s * q.s + q.c * q.c;
369
+ return 1.0f - 0.0006f < qq && qq < 1.0f + 0.0006f;
370
+ }
371
+
372
+ /// Normalized linear interpolation
373
+ /// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
374
+ /// https://web.archive.org/web/20170825184056/http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/
375
+ B2_INLINE b2Rot b2NLerp( b2Rot q1, b2Rot q2, float t )
376
+ {
377
+ float omt = 1.0f - t;
378
+ b2Rot q = {
379
+ omt * q1.c + t * q2.c,
380
+ omt * q1.s + t * q2.s,
381
+ };
382
+
383
+ float mag = sqrtf( q.s * q.s + q.c * q.c );
384
+ float invMag = mag > 0.0 ? 1.0f / mag : 0.0f;
385
+ b2Rot qn = { q.c * invMag, q.s * invMag };
386
+ return qn;
387
+ }
388
+
389
+ /// Compute the angular velocity necessary to rotate between two rotations over a give time
390
+ /// @param q1 initial rotation
391
+ /// @param q2 final rotation
392
+ /// @param inv_h inverse time step
393
+ B2_INLINE float b2ComputeAngularVelocity( b2Rot q1, b2Rot q2, float inv_h )
394
+ {
395
+ // ds/dt = omega * cos(t)
396
+ // dc/dt = -omega * sin(t)
397
+ // s2 = s1 + omega * h * c1
398
+ // c2 = c1 - omega * h * s1
399
+
400
+ // omega * h * s1 = c1 - c2
401
+ // omega * h * c1 = s2 - s1
402
+ // omega * h = (c1 - c2) * s1 + (s2 - s1) * c1;
403
+ // omega * h = s1 * c1 - c2 * s1 + s2 * c1 - s1 * c1
404
+ // omega * h = s2 * c1 - c2 * s1 = sin(a2 - a1) ~= a2 - a1 for small delta
405
+ float omega = inv_h * ( q2.s * q1.c - q2.c * q1.s );
406
+ return omega;
407
+ }
408
+
409
+ /// Get the angle in radians in the range [-pi, pi]
410
+ B2_INLINE float b2Rot_GetAngle( b2Rot q )
411
+ {
412
+ return b2Atan2( q.s, q.c );
413
+ }
414
+
415
+ /// Get the x-axis
416
+ B2_INLINE b2Vec2 b2Rot_GetXAxis( b2Rot q )
417
+ {
418
+ b2Vec2 v = { q.c, q.s };
419
+ return v;
420
+ }
421
+
422
+ /// Get the y-axis
423
+ B2_INLINE b2Vec2 b2Rot_GetYAxis( b2Rot q )
424
+ {
425
+ b2Vec2 v = { -q.s, q.c };
426
+ return v;
427
+ }
428
+
429
+ /// Multiply two rotations: q * r
430
+ B2_INLINE b2Rot b2MulRot( b2Rot q, b2Rot r )
431
+ {
432
+ // [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc]
433
+ // [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc]
434
+ // s(q + r) = qs * rc + qc * rs
435
+ // c(q + r) = qc * rc - qs * rs
436
+ b2Rot qr;
437
+ qr.s = q.s * r.c + q.c * r.s;
438
+ qr.c = q.c * r.c - q.s * r.s;
439
+ return qr;
440
+ }
441
+
442
+ /// Transpose multiply two rotations: qT * r
443
+ B2_INLINE b2Rot b2InvMulRot( b2Rot q, b2Rot r )
444
+ {
445
+ // [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc]
446
+ // [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc]
447
+ // s(q - r) = qc * rs - qs * rc
448
+ // c(q - r) = qc * rc + qs * rs
449
+ b2Rot qr;
450
+ qr.s = q.c * r.s - q.s * r.c;
451
+ qr.c = q.c * r.c + q.s * r.s;
452
+ return qr;
453
+ }
454
+
455
+ /// relative angle between b and a (rot_b * inv(rot_a))
456
+ B2_INLINE float b2RelativeAngle( b2Rot b, b2Rot a )
457
+ {
458
+ // sin(b - a) = bs * ac - bc * as
459
+ // cos(b - a) = bc * ac + bs * as
460
+ float s = b.s * a.c - b.c * a.s;
461
+ float c = b.c * a.c + b.s * a.s;
462
+ return b2Atan2( s, c );
463
+ }
464
+
465
+ /// Convert an angle in the range [-2*pi, 2*pi] into the range [-pi, pi]
466
+ B2_INLINE float b2UnwindAngle( float radians )
467
+ {
468
+ if ( radians < -B2_PI )
469
+ {
470
+ return radians + 2.0f * B2_PI;
471
+ }
472
+ else if ( radians > B2_PI )
473
+ {
474
+ return radians - 2.0f * B2_PI;
475
+ }
476
+
477
+ return radians;
478
+ }
479
+
480
+ /// Convert any into the range [-pi, pi] (slow)
481
+ B2_INLINE float b2UnwindLargeAngle( float radians )
482
+ {
483
+ while ( radians > B2_PI )
484
+ {
485
+ radians -= 2.0f * B2_PI;
486
+ }
487
+
488
+ while ( radians < -B2_PI )
489
+ {
490
+ radians += 2.0f * B2_PI;
491
+ }
492
+
493
+ return radians;
494
+ }
495
+
496
+ /// Rotate a vector
497
+ B2_INLINE b2Vec2 b2RotateVector( b2Rot q, b2Vec2 v )
498
+ {
499
+ return B2_LITERAL( b2Vec2 ){ q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y };
500
+ }
501
+
502
+ /// Inverse rotate a vector
503
+ B2_INLINE b2Vec2 b2InvRotateVector( b2Rot q, b2Vec2 v )
504
+ {
505
+ return B2_LITERAL( b2Vec2 ){ q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y };
506
+ }
507
+
508
+ /// Transform a point (e.g. local space to world space)
509
+ B2_INLINE b2Vec2 b2TransformPoint( b2Transform t, const b2Vec2 p )
510
+ {
511
+ float x = ( t.q.c * p.x - t.q.s * p.y ) + t.p.x;
512
+ float y = ( t.q.s * p.x + t.q.c * p.y ) + t.p.y;
513
+
514
+ return B2_LITERAL( b2Vec2 ){ x, y };
515
+ }
516
+
517
+ /// Inverse transform a point (e.g. world space to local space)
518
+ B2_INLINE b2Vec2 b2InvTransformPoint( b2Transform t, const b2Vec2 p )
519
+ {
520
+ float vx = p.x - t.p.x;
521
+ float vy = p.y - t.p.y;
522
+ return B2_LITERAL( b2Vec2 ){ t.q.c * vx + t.q.s * vy, -t.q.s * vx + t.q.c * vy };
523
+ }
524
+
525
+ /// Multiply two transforms. If the result is applied to a point p local to frame B,
526
+ /// the transform would first convert p to a point local to frame A, then into a point
527
+ /// in the world frame.
528
+ /// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p
529
+ /// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p
530
+ B2_INLINE b2Transform b2MulTransforms( b2Transform A, b2Transform B )
531
+ {
532
+ b2Transform C;
533
+ C.q = b2MulRot( A.q, B.q );
534
+ C.p = b2Add( b2RotateVector( A.q, B.p ), A.p );
535
+ return C;
536
+ }
537
+
538
+ /// Creates a transform that converts a local point in frame B to a local point in frame A.
539
+ /// v2 = A.q' * (B.q * v1 + B.p - A.p)
540
+ /// = A.q' * B.q * v1 + A.q' * (B.p - A.p)
541
+ B2_INLINE b2Transform b2InvMulTransforms( b2Transform A, b2Transform B )
542
+ {
543
+ b2Transform C;
544
+ C.q = b2InvMulRot( A.q, B.q );
545
+ C.p = b2InvRotateVector( A.q, b2Sub( B.p, A.p ) );
546
+ return C;
547
+ }
548
+
549
+ /// Multiply a 2-by-2 matrix times a 2D vector
550
+ B2_INLINE b2Vec2 b2MulMV( b2Mat22 A, b2Vec2 v )
551
+ {
552
+ b2Vec2 u = {
553
+ A.cx.x * v.x + A.cy.x * v.y,
554
+ A.cx.y * v.x + A.cy.y * v.y,
555
+ };
556
+ return u;
557
+ }
558
+
559
+ /// Get the inverse of a 2-by-2 matrix
560
+ B2_INLINE b2Mat22 b2GetInverse22( b2Mat22 A )
561
+ {
562
+ float a = A.cx.x, b = A.cy.x, c = A.cx.y, d = A.cy.y;
563
+ float det = a * d - b * c;
564
+ if ( det != 0.0f )
565
+ {
566
+ det = 1.0f / det;
567
+ }
568
+
569
+ b2Mat22 B = {
570
+ { det * d, -det * c },
571
+ { -det * b, det * a },
572
+ };
573
+ return B;
574
+ }
575
+
576
+ /// Solve A * x = b, where b is a column vector. This is more efficient
577
+ /// than computing the inverse in one-shot cases.
578
+ B2_INLINE b2Vec2 b2Solve22( b2Mat22 A, b2Vec2 b )
579
+ {
580
+ float a11 = A.cx.x, a12 = A.cy.x, a21 = A.cx.y, a22 = A.cy.y;
581
+ float det = a11 * a22 - a12 * a21;
582
+ if ( det != 0.0f )
583
+ {
584
+ det = 1.0f / det;
585
+ }
586
+ b2Vec2 x = { det * ( a22 * b.x - a12 * b.y ), det * ( a11 * b.y - a21 * b.x ) };
587
+ return x;
588
+ }
589
+
590
+ /// Does a fully contain b
591
+ B2_INLINE bool b2AABB_Contains( b2AABB a, b2AABB b )
592
+ {
593
+ bool s = true;
594
+ s = s && a.lowerBound.x <= b.lowerBound.x;
595
+ s = s && a.lowerBound.y <= b.lowerBound.y;
596
+ s = s && b.upperBound.x <= a.upperBound.x;
597
+ s = s && b.upperBound.y <= a.upperBound.y;
598
+ return s;
599
+ }
600
+
601
+ /// Get the center of the AABB.
602
+ B2_INLINE b2Vec2 b2AABB_Center( b2AABB a )
603
+ {
604
+ b2Vec2 b = { 0.5f * ( a.lowerBound.x + a.upperBound.x ), 0.5f * ( a.lowerBound.y + a.upperBound.y ) };
605
+ return b;
606
+ }
607
+
608
+ /// Get the extents of the AABB (half-widths).
609
+ B2_INLINE b2Vec2 b2AABB_Extents( b2AABB a )
610
+ {
611
+ b2Vec2 b = { 0.5f * ( a.upperBound.x - a.lowerBound.x ), 0.5f * ( a.upperBound.y - a.lowerBound.y ) };
612
+ return b;
613
+ }
614
+
615
+ /// Union of two AABBs
616
+ B2_INLINE b2AABB b2AABB_Union( b2AABB a, b2AABB b )
617
+ {
618
+ b2AABB c;
619
+ c.lowerBound.x = b2MinFloat( a.lowerBound.x, b.lowerBound.x );
620
+ c.lowerBound.y = b2MinFloat( a.lowerBound.y, b.lowerBound.y );
621
+ c.upperBound.x = b2MaxFloat( a.upperBound.x, b.upperBound.x );
622
+ c.upperBound.y = b2MaxFloat( a.upperBound.y, b.upperBound.y );
623
+ return c;
624
+ }
625
+
626
+ /// Compute the bounding box of an array of circles
627
+ B2_INLINE b2AABB b2MakeAABB( const b2Vec2* points, int count, float radius )
628
+ {
629
+ B2_ASSERT( count > 0 );
630
+ b2AABB a = { points[0], points[0] };
631
+ for ( int i = 1; i < count; ++i )
632
+ {
633
+ a.lowerBound = b2Min( a.lowerBound, points[i] );
634
+ a.upperBound = b2Max( a.upperBound, points[i] );
635
+ }
636
+
637
+ b2Vec2 r = { radius, radius };
638
+ a.lowerBound = b2Sub( a.lowerBound, r );
639
+ a.upperBound = b2Add( a.upperBound, r );
640
+
641
+ return a;
642
+ }
643
+
644
+ /// Signed separation of a point from a plane
645
+ B2_INLINE float b2PlaneSeparation( b2Plane plane, b2Vec2 point )
646
+ {
647
+ return b2Dot( plane.normal, point ) - plane.offset;
648
+ }
649
+
650
+ /// Is this a valid number? Not NaN or infinity.
651
+ B2_API bool b2IsValidFloat( float a );
652
+
653
+ /// Is this a valid vector? Not NaN or infinity.
654
+ B2_API bool b2IsValidVec2( b2Vec2 v );
655
+
656
+ /// Is this a valid rotation? Not NaN or infinity. Is normalized.
657
+ B2_API bool b2IsValidRotation( b2Rot q );
658
+
659
+ /// Is this a valid bounding box? Not Nan or infinity. Upper bound greater than or equal to lower bound.
660
+ B2_API bool b2IsValidAABB( b2AABB aabb );
661
+
662
+ /// Is this a valid plane? Normal is a unit vector. Not Nan or infinity.
663
+ B2_API bool b2IsValidPlane( b2Plane a );
664
+
665
+ /// Box2D bases all length units on meters, but you may need different units for your game.
666
+ /// You can set this value to use different units. This should be done at application startup
667
+ /// and only modified once. Default value is 1.
668
+ /// For example, if your game uses pixels for units you can use pixels for all length values
669
+ /// sent to Box2D. There should be no extra cost. However, Box2D has some internal tolerances
670
+ /// and thresholds that have been tuned for meters. By calling this function, Box2D is able
671
+ /// to adjust those tolerances and thresholds to improve accuracy.
672
+ /// A good rule of thumb is to pass the height of your player character to this function. So
673
+ /// if your player character is 32 pixels high, then pass 32 to this function. Then you may
674
+ /// confidently use pixels for all the length values sent to Box2D. All length values returned
675
+ /// from Box2D will also be pixels because Box2D does not do any scaling internally.
676
+ /// However, you are now on the hook for coming up with good values for gravity, density, and
677
+ /// forces.
678
+ /// @warning This must be modified before any calls to Box2D
679
+ B2_API void b2SetLengthUnitsPerMeter( float lengthUnits );
680
+
681
+ /// Get the current length units per meter.
682
+ B2_API float b2GetLengthUnitsPerMeter( void );
683
+
684
+ /**@}*/
685
+
686
+ /**
687
+ * @defgroup math_cpp C++ Math
688
+ * @brief Math operator overloads for C++
689
+ *
690
+ * See math_functions.h for details.
691
+ * @{
692
+ */
693
+
694
+ #ifdef __cplusplus
695
+
696
+ /// Unary add one vector to another
697
+ inline void operator+=( b2Vec2& a, b2Vec2 b )
698
+ {
699
+ a.x += b.x;
700
+ a.y += b.y;
701
+ }
702
+
703
+ /// Unary subtract one vector from another
704
+ inline void operator-=( b2Vec2& a, b2Vec2 b )
705
+ {
706
+ a.x -= b.x;
707
+ a.y -= b.y;
708
+ }
709
+
710
+ /// Unary multiply a vector by a scalar
711
+ inline void operator*=( b2Vec2& a, float b )
712
+ {
713
+ a.x *= b;
714
+ a.y *= b;
715
+ }
716
+
717
+ /// Unary negate a vector
718
+ inline b2Vec2 operator-( b2Vec2 a )
719
+ {
720
+ return { -a.x, -a.y };
721
+ }
722
+
723
+ /// Binary vector addition
724
+ inline b2Vec2 operator+( b2Vec2 a, b2Vec2 b )
725
+ {
726
+ return { a.x + b.x, a.y + b.y };
727
+ }
728
+
729
+ /// Binary vector subtraction
730
+ inline b2Vec2 operator-( b2Vec2 a, b2Vec2 b )
731
+ {
732
+ return { a.x - b.x, a.y - b.y };
733
+ }
734
+
735
+ /// Binary scalar and vector multiplication
736
+ inline b2Vec2 operator*( float a, b2Vec2 b )
737
+ {
738
+ return { a * b.x, a * b.y };
739
+ }
740
+
741
+ /// Binary scalar and vector multiplication
742
+ inline b2Vec2 operator*( b2Vec2 a, float b )
743
+ {
744
+ return { a.x * b, a.y * b };
745
+ }
746
+
747
+ /// Binary vector equality
748
+ inline bool operator==( b2Vec2 a, b2Vec2 b )
749
+ {
750
+ return a.x == b.x && a.y == b.y;
751
+ }
752
+
753
+ /// Binary vector inequality
754
+ inline bool operator!=( b2Vec2 a, b2Vec2 b )
755
+ {
756
+ return a.x != b.x || a.y != b.y;
757
+ }
758
+
759
+ #endif
760
+
761
+ /**@}*/