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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +336 -0
- data/examples/contact_events.rb +22 -0
- data/examples/debug_draw.rb +15 -0
- data/examples/falling_ball.rb +19 -0
- data/examples/rugl_debug_draw.rb +68 -0
- data/examples/stagecraft_debug_draw.rb +64 -0
- data/examples/support/box2d_debug_lines.rb +125 -0
- data/ext/box2d/CMakeLists.txt +35 -0
- data/ext/box2d/extconf.rb +42 -0
- data/ext/box2d/native.c +9 -0
- data/ext/box2d/vendor/box2d/LICENSE +21 -0
- data/ext/box2d/vendor/box2d/VERSION +1 -0
- data/ext/box2d/vendor/box2d/include/box2d/base.h +131 -0
- data/ext/box2d/vendor/box2d/include/box2d/box2d.h +1222 -0
- data/ext/box2d/vendor/box2d/include/box2d/collision.h +830 -0
- data/ext/box2d/vendor/box2d/include/box2d/id.h +144 -0
- data/ext/box2d/vendor/box2d/include/box2d/math_functions.h +761 -0
- data/ext/box2d/vendor/box2d/include/box2d/types.h +1457 -0
- data/ext/box2d/vendor/box2d/src/CMakeLists.txt +223 -0
- data/ext/box2d/vendor/box2d/src/aabb.c +132 -0
- data/ext/box2d/vendor/box2d/src/aabb.h +56 -0
- data/ext/box2d/vendor/box2d/src/arena_allocator.c +112 -0
- data/ext/box2d/vendor/box2d/src/arena_allocator.h +48 -0
- data/ext/box2d/vendor/box2d/src/array.c +8 -0
- data/ext/box2d/vendor/box2d/src/array.h +179 -0
- data/ext/box2d/vendor/box2d/src/atomic.h +79 -0
- data/ext/box2d/vendor/box2d/src/bitset.c +67 -0
- data/ext/box2d/vendor/box2d/src/bitset.h +65 -0
- data/ext/box2d/vendor/box2d/src/body.c +1884 -0
- data/ext/box2d/vendor/box2d/src/body.h +194 -0
- data/ext/box2d/vendor/box2d/src/box2d.natvis +41 -0
- data/ext/box2d/vendor/box2d/src/broad_phase.c +524 -0
- data/ext/box2d/vendor/box2d/src/broad_phase.h +83 -0
- data/ext/box2d/vendor/box2d/src/constants.h +54 -0
- data/ext/box2d/vendor/box2d/src/constraint_graph.c +322 -0
- data/ext/box2d/vendor/box2d/src/constraint_graph.h +58 -0
- data/ext/box2d/vendor/box2d/src/contact.c +650 -0
- data/ext/box2d/vendor/box2d/src/contact.h +148 -0
- data/ext/box2d/vendor/box2d/src/contact_solver.c +2120 -0
- data/ext/box2d/vendor/box2d/src/contact_solver.h +54 -0
- data/ext/box2d/vendor/box2d/src/core.c +178 -0
- data/ext/box2d/vendor/box2d/src/core.h +149 -0
- data/ext/box2d/vendor/box2d/src/ctz.h +112 -0
- data/ext/box2d/vendor/box2d/src/distance.c +1415 -0
- data/ext/box2d/vendor/box2d/src/distance_joint.c +556 -0
- data/ext/box2d/vendor/box2d/src/dynamic_tree.c +1989 -0
- data/ext/box2d/vendor/box2d/src/geometry.c +1028 -0
- data/ext/box2d/vendor/box2d/src/hull.c +328 -0
- data/ext/box2d/vendor/box2d/src/id_pool.c +79 -0
- data/ext/box2d/vendor/box2d/src/id_pool.h +35 -0
- data/ext/box2d/vendor/box2d/src/island.c +977 -0
- data/ext/box2d/vendor/box2d/src/island.h +89 -0
- data/ext/box2d/vendor/box2d/src/joint.c +1272 -0
- data/ext/box2d/vendor/box2d/src/joint.h +335 -0
- data/ext/box2d/vendor/box2d/src/manifold.c +1726 -0
- data/ext/box2d/vendor/box2d/src/math_functions.c +159 -0
- data/ext/box2d/vendor/box2d/src/motor_joint.c +283 -0
- data/ext/box2d/vendor/box2d/src/mouse_joint.c +214 -0
- data/ext/box2d/vendor/box2d/src/mover.c +73 -0
- data/ext/box2d/vendor/box2d/src/prismatic_joint.c +656 -0
- data/ext/box2d/vendor/box2d/src/revolute_joint.c +534 -0
- data/ext/box2d/vendor/box2d/src/sensor.c +389 -0
- data/ext/box2d/vendor/box2d/src/sensor.h +36 -0
- data/ext/box2d/vendor/box2d/src/shape.c +1714 -0
- data/ext/box2d/vendor/box2d/src/shape.h +123 -0
- data/ext/box2d/vendor/box2d/src/solver.c +2038 -0
- data/ext/box2d/vendor/box2d/src/solver.h +155 -0
- data/ext/box2d/vendor/box2d/src/solver_set.c +613 -0
- data/ext/box2d/vendor/box2d/src/solver_set.h +57 -0
- data/ext/box2d/vendor/box2d/src/table.c +238 -0
- data/ext/box2d/vendor/box2d/src/table.h +37 -0
- data/ext/box2d/vendor/box2d/src/timer.c +185 -0
- data/ext/box2d/vendor/box2d/src/types.c +151 -0
- data/ext/box2d/vendor/box2d/src/weld_joint.c +310 -0
- data/ext/box2d/vendor/box2d/src/wheel_joint.c +551 -0
- data/ext/box2d/vendor/box2d/src/world.c +3301 -0
- data/ext/box2d/vendor/box2d/src/world.h +192 -0
- data/generator/generate.rb +316 -0
- data/generator/layout_probe.c +507 -0
- data/generator/verify_layouts.rb +32 -0
- data/lib/box2d/body.rb +172 -0
- data/lib/box2d/body_definition.rb +38 -0
- data/lib/box2d/body_shapes.rb +135 -0
- data/lib/box2d/chain.rb +61 -0
- data/lib/box2d/debug_draw.rb +118 -0
- data/lib/box2d/events.rb +103 -0
- data/lib/box2d/fixed_stepper.rb +39 -0
- data/lib/box2d/handle.rb +46 -0
- data/lib/box2d/hit.rb +5 -0
- data/lib/box2d/joint.rb +197 -0
- data/lib/box2d/native.rb +1462 -0
- data/lib/box2d/native_loader.rb +45 -0
- data/lib/box2d/pixel_scale.rb +29 -0
- data/lib/box2d/shape.rb +109 -0
- data/lib/box2d/shape_definition.rb +44 -0
- data/lib/box2d/value_conversion.rb +80 -0
- data/lib/box2d/version.rb +7 -0
- data/lib/box2d/world.rb +135 -0
- data/lib/box2d/world_joints.rb +156 -0
- data/lib/box2d/world_queries.rb +122 -0
- data/lib/box2d/world_registry.rb +95 -0
- data/lib/box2d.rb +31 -0
- data/script/build_platform_gem.rb +24 -0
- data/script/deterministic_scene.rb +56 -0
- data/script/update_deterministic_snapshot.rb +11 -0
- data/script/verify_platform_gem.rb +24 -0
- 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
|
+
/**@}*/
|