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,238 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2023 Erin Catto
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
#include "table.h"
|
|
5
|
+
|
|
6
|
+
#include "atomic.h"
|
|
7
|
+
#include "core.h"
|
|
8
|
+
#include "ctz.h"
|
|
9
|
+
|
|
10
|
+
#include <stdbool.h>
|
|
11
|
+
#include <string.h>
|
|
12
|
+
|
|
13
|
+
#if B2_SNOOP_TABLE_COUNTERS
|
|
14
|
+
b2AtomicInt b2_findCount;
|
|
15
|
+
b2AtomicInt b2_probeCount;
|
|
16
|
+
#endif
|
|
17
|
+
|
|
18
|
+
// todo compare with https://github.com/skeeto/scratch/blob/master/set32/set32.h
|
|
19
|
+
|
|
20
|
+
b2HashSet b2CreateSet( int capacity )
|
|
21
|
+
{
|
|
22
|
+
b2HashSet set = { 0 };
|
|
23
|
+
|
|
24
|
+
// Capacity must be a power of 2
|
|
25
|
+
if ( capacity > 16 )
|
|
26
|
+
{
|
|
27
|
+
set.capacity = b2RoundUpPowerOf2( capacity );
|
|
28
|
+
}
|
|
29
|
+
else
|
|
30
|
+
{
|
|
31
|
+
set.capacity = 16;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
set.count = 0;
|
|
35
|
+
set.items = b2Alloc( capacity * sizeof( b2SetItem ) );
|
|
36
|
+
memset( set.items, 0, capacity * sizeof( b2SetItem ) );
|
|
37
|
+
|
|
38
|
+
return set;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
void b2DestroySet( b2HashSet* set )
|
|
42
|
+
{
|
|
43
|
+
b2Free( set->items, set->capacity * sizeof( b2SetItem ) );
|
|
44
|
+
set->items = NULL;
|
|
45
|
+
set->count = 0;
|
|
46
|
+
set->capacity = 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
void b2ClearSet( b2HashSet* set )
|
|
50
|
+
{
|
|
51
|
+
set->count = 0;
|
|
52
|
+
memset( set->items, 0, set->capacity * sizeof( b2SetItem ) );
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// I need a good hash because the keys are built from pairs of increasing integers.
|
|
56
|
+
// A simple hash like hash = (integer1 XOR integer2) has many collisions.
|
|
57
|
+
// https://lemire.me/blog/2018/08/15/fast-strongly-universal-64-bit-hashing-everywhere/
|
|
58
|
+
// https://preshing.com/20130107/this-hash-set-is-faster-than-a-judy-array/
|
|
59
|
+
// todo try: https://www.jandrewrogers.com/2019/02/12/fast-perfect-hashing/
|
|
60
|
+
// todo try: https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
|
|
61
|
+
static uint32_t b2KeyHash( uint64_t key )
|
|
62
|
+
{
|
|
63
|
+
// Murmur hash
|
|
64
|
+
uint64_t h = key;
|
|
65
|
+
h ^= h >> 33;
|
|
66
|
+
h *= 0xff51afd7ed558ccduLL;
|
|
67
|
+
h ^= h >> 33;
|
|
68
|
+
h *= 0xc4ceb9fe1a85ec53uLL;
|
|
69
|
+
h ^= h >> 33;
|
|
70
|
+
|
|
71
|
+
return (uint32_t)h;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static int b2FindSlot( const b2HashSet* set, uint64_t key, uint32_t hash )
|
|
75
|
+
{
|
|
76
|
+
#if B2_SNOOP_TABLE_COUNTERS
|
|
77
|
+
b2AtomicFetchAddInt( &b2_findCount, 1 );
|
|
78
|
+
#endif
|
|
79
|
+
|
|
80
|
+
uint32_t capacity = set->capacity;
|
|
81
|
+
int index = hash & ( capacity - 1 );
|
|
82
|
+
const b2SetItem* items = set->items;
|
|
83
|
+
while ( items[index].hash != 0 && items[index].key != key )
|
|
84
|
+
{
|
|
85
|
+
#if B2_SNOOP_TABLE_COUNTERS
|
|
86
|
+
b2AtomicFetchAddInt( &b2_probeCount, 1 );
|
|
87
|
+
#endif
|
|
88
|
+
index = ( index + 1 ) & ( capacity - 1 );
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return index;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
static void b2AddKeyHaveCapacity( b2HashSet* set, uint64_t key, uint32_t hash )
|
|
95
|
+
{
|
|
96
|
+
int index = b2FindSlot( set, key, hash );
|
|
97
|
+
b2SetItem* items = set->items;
|
|
98
|
+
B2_ASSERT( items[index].hash == 0 );
|
|
99
|
+
|
|
100
|
+
items[index].key = key;
|
|
101
|
+
items[index].hash = hash;
|
|
102
|
+
set->count += 1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static void b2GrowTable( b2HashSet* set )
|
|
106
|
+
{
|
|
107
|
+
uint32_t oldCount = set->count;
|
|
108
|
+
B2_UNUSED( oldCount );
|
|
109
|
+
|
|
110
|
+
uint32_t oldCapacity = set->capacity;
|
|
111
|
+
b2SetItem* oldItems = set->items;
|
|
112
|
+
|
|
113
|
+
set->count = 0;
|
|
114
|
+
// Capacity must be a power of 2
|
|
115
|
+
set->capacity = 2 * oldCapacity;
|
|
116
|
+
set->items = b2Alloc( set->capacity * sizeof( b2SetItem ) );
|
|
117
|
+
memset( set->items, 0, set->capacity * sizeof( b2SetItem ) );
|
|
118
|
+
|
|
119
|
+
// Transfer items into new array
|
|
120
|
+
for ( uint32_t i = 0; i < oldCapacity; ++i )
|
|
121
|
+
{
|
|
122
|
+
b2SetItem* item = oldItems + i;
|
|
123
|
+
if ( item->hash == 0 )
|
|
124
|
+
{
|
|
125
|
+
// this item was empty
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
b2AddKeyHaveCapacity( set, item->key, item->hash );
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
B2_ASSERT( set->count == oldCount );
|
|
133
|
+
|
|
134
|
+
b2Free( oldItems, oldCapacity * sizeof( b2SetItem ) );
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
bool b2ContainsKey( const b2HashSet* set, uint64_t key )
|
|
138
|
+
{
|
|
139
|
+
// key of zero is a sentinel
|
|
140
|
+
B2_ASSERT( key != 0 );
|
|
141
|
+
uint32_t hash = b2KeyHash( key );
|
|
142
|
+
int index = b2FindSlot( set, key, hash );
|
|
143
|
+
return set->items[index].key == key;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
int b2GetHashSetBytes( b2HashSet* set )
|
|
147
|
+
{
|
|
148
|
+
return set->capacity * (int)sizeof( b2SetItem );
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
bool b2AddKey( b2HashSet* set, uint64_t key )
|
|
152
|
+
{
|
|
153
|
+
// key of zero is a sentinel
|
|
154
|
+
B2_ASSERT( key != 0 );
|
|
155
|
+
|
|
156
|
+
uint32_t hash = b2KeyHash( key );
|
|
157
|
+
B2_ASSERT( hash != 0 );
|
|
158
|
+
|
|
159
|
+
int index = b2FindSlot( set, key, hash );
|
|
160
|
+
if ( set->items[index].hash != 0 )
|
|
161
|
+
{
|
|
162
|
+
// Already in set
|
|
163
|
+
B2_ASSERT( set->items[index].hash == hash && set->items[index].key == key );
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if ( 2 * set->count >= set->capacity )
|
|
168
|
+
{
|
|
169
|
+
b2GrowTable( set );
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
b2AddKeyHaveCapacity( set, key, hash );
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// See https://en.wikipedia.org/wiki/Open_addressing
|
|
177
|
+
bool b2RemoveKey( b2HashSet* set, uint64_t key )
|
|
178
|
+
{
|
|
179
|
+
uint32_t hash = b2KeyHash( key );
|
|
180
|
+
int i = b2FindSlot( set, key, hash );
|
|
181
|
+
b2SetItem* items = set->items;
|
|
182
|
+
if ( items[i].hash == 0 )
|
|
183
|
+
{
|
|
184
|
+
// Not in set
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Mark item i as unoccupied
|
|
189
|
+
items[i].key = 0;
|
|
190
|
+
items[i].hash = 0;
|
|
191
|
+
|
|
192
|
+
B2_ASSERT( set->count > 0 );
|
|
193
|
+
set->count -= 1;
|
|
194
|
+
|
|
195
|
+
// Attempt to fill item i
|
|
196
|
+
int j = i;
|
|
197
|
+
uint32_t capacity = set->capacity;
|
|
198
|
+
for ( ;; )
|
|
199
|
+
{
|
|
200
|
+
j = ( j + 1 ) & ( capacity - 1 );
|
|
201
|
+
if ( items[j].hash == 0 )
|
|
202
|
+
{
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// k is the first item for the hash of j
|
|
207
|
+
int k = items[j].hash & ( capacity - 1 );
|
|
208
|
+
|
|
209
|
+
// determine if k lies cyclically in (i,j]
|
|
210
|
+
// i <= j: | i..k..j |
|
|
211
|
+
// i > j: |.k..j i....| or |....j i..k.|
|
|
212
|
+
if ( i <= j )
|
|
213
|
+
{
|
|
214
|
+
if ( i < k && k <= j )
|
|
215
|
+
{
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
else
|
|
220
|
+
{
|
|
221
|
+
if ( i < k || k <= j )
|
|
222
|
+
{
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Move j into i
|
|
228
|
+
items[i] = items[j];
|
|
229
|
+
|
|
230
|
+
// Mark item j as unoccupied
|
|
231
|
+
items[j].key = 0;
|
|
232
|
+
items[j].hash = 0;
|
|
233
|
+
|
|
234
|
+
i = j;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2023 Erin Catto
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include <stdbool.h>
|
|
7
|
+
#include <stdint.h>
|
|
8
|
+
|
|
9
|
+
#define B2_SHAPE_PAIR_KEY( K1, K2 ) K1 < K2 ? (uint64_t)K1 << 32 | (uint64_t)K2 : (uint64_t)K2 << 32 | (uint64_t)K1
|
|
10
|
+
|
|
11
|
+
typedef struct b2SetItem
|
|
12
|
+
{
|
|
13
|
+
uint64_t key;
|
|
14
|
+
uint32_t hash;
|
|
15
|
+
} b2SetItem;
|
|
16
|
+
|
|
17
|
+
typedef struct b2HashSet
|
|
18
|
+
{
|
|
19
|
+
b2SetItem* items;
|
|
20
|
+
uint32_t capacity;
|
|
21
|
+
uint32_t count;
|
|
22
|
+
} b2HashSet;
|
|
23
|
+
|
|
24
|
+
b2HashSet b2CreateSet( int capacity );
|
|
25
|
+
void b2DestroySet( b2HashSet* set );
|
|
26
|
+
|
|
27
|
+
void b2ClearSet( b2HashSet* set );
|
|
28
|
+
|
|
29
|
+
// Returns true if key was already in set
|
|
30
|
+
bool b2AddKey( b2HashSet* set, uint64_t key );
|
|
31
|
+
|
|
32
|
+
// Returns true if the key was found
|
|
33
|
+
bool b2RemoveKey( b2HashSet* set, uint64_t key );
|
|
34
|
+
|
|
35
|
+
bool b2ContainsKey( const b2HashSet* set, uint64_t key );
|
|
36
|
+
|
|
37
|
+
int b2GetHashSetBytes( b2HashSet* set );
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2023 Erin Catto
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
#include "box2d/base.h"
|
|
5
|
+
|
|
6
|
+
#include <stddef.h>
|
|
7
|
+
|
|
8
|
+
#if defined( _MSC_VER )
|
|
9
|
+
|
|
10
|
+
#ifndef WIN32_LEAN_AND_MEAN
|
|
11
|
+
#define WIN32_LEAN_AND_MEAN 1
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
#include <windows.h>
|
|
15
|
+
|
|
16
|
+
static double s_invFrequency = 0.0;
|
|
17
|
+
|
|
18
|
+
uint64_t b2GetTicks( void )
|
|
19
|
+
{
|
|
20
|
+
LARGE_INTEGER counter;
|
|
21
|
+
QueryPerformanceCounter( &counter );
|
|
22
|
+
return (uint64_t)counter.QuadPart;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
float b2GetMilliseconds( uint64_t ticks )
|
|
26
|
+
{
|
|
27
|
+
if ( s_invFrequency == 0.0 )
|
|
28
|
+
{
|
|
29
|
+
LARGE_INTEGER frequency;
|
|
30
|
+
QueryPerformanceFrequency( &frequency );
|
|
31
|
+
|
|
32
|
+
s_invFrequency = (double)frequency.QuadPart;
|
|
33
|
+
if ( s_invFrequency > 0.0 )
|
|
34
|
+
{
|
|
35
|
+
s_invFrequency = 1000.0 / s_invFrequency;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
uint64_t ticksNow = b2GetTicks();
|
|
40
|
+
return (float)( s_invFrequency * ( ticksNow - ticks ) );
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
float b2GetMillisecondsAndReset( uint64_t* ticks )
|
|
44
|
+
{
|
|
45
|
+
if ( s_invFrequency == 0.0 )
|
|
46
|
+
{
|
|
47
|
+
LARGE_INTEGER frequency;
|
|
48
|
+
QueryPerformanceFrequency( &frequency );
|
|
49
|
+
|
|
50
|
+
s_invFrequency = (double)frequency.QuadPart;
|
|
51
|
+
if ( s_invFrequency > 0.0 )
|
|
52
|
+
{
|
|
53
|
+
s_invFrequency = 1000.0 / s_invFrequency;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
uint64_t ticksNow = b2GetTicks();
|
|
58
|
+
float ms = (float)( s_invFrequency * ( ticksNow - *ticks ) );
|
|
59
|
+
*ticks = ticksNow;
|
|
60
|
+
return ms;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void b2Yield( void )
|
|
64
|
+
{
|
|
65
|
+
SwitchToThread();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#elif defined( __linux__ ) || defined( __EMSCRIPTEN__ )
|
|
69
|
+
|
|
70
|
+
#include <sched.h>
|
|
71
|
+
#include <time.h>
|
|
72
|
+
|
|
73
|
+
uint64_t b2GetTicks( void )
|
|
74
|
+
{
|
|
75
|
+
struct timespec ts;
|
|
76
|
+
clock_gettime( CLOCK_MONOTONIC, &ts );
|
|
77
|
+
return ts.tv_sec * 1000000000LL + ts.tv_nsec;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
float b2GetMilliseconds( uint64_t ticks )
|
|
81
|
+
{
|
|
82
|
+
uint64_t ticksNow = b2GetTicks();
|
|
83
|
+
return (float)( (ticksNow - ticks) / 1000000.0 );
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
float b2GetMillisecondsAndReset( uint64_t* ticks )
|
|
87
|
+
{
|
|
88
|
+
uint64_t ticksNow = b2GetTicks();
|
|
89
|
+
float ms = (float)( (ticksNow - *ticks) / 1000000.0 );
|
|
90
|
+
*ticks = ticksNow;
|
|
91
|
+
return ms;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
void b2Yield( void )
|
|
95
|
+
{
|
|
96
|
+
sched_yield();
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
#elif defined( __APPLE__ )
|
|
100
|
+
|
|
101
|
+
#include <mach/mach_time.h>
|
|
102
|
+
#include <sched.h>
|
|
103
|
+
#include <sys/time.h>
|
|
104
|
+
|
|
105
|
+
static double s_invFrequency = 0.0;
|
|
106
|
+
|
|
107
|
+
uint64_t b2GetTicks( void )
|
|
108
|
+
{
|
|
109
|
+
return mach_absolute_time();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
float b2GetMilliseconds( uint64_t ticks )
|
|
113
|
+
{
|
|
114
|
+
if ( s_invFrequency == 0 )
|
|
115
|
+
{
|
|
116
|
+
mach_timebase_info_data_t timebase;
|
|
117
|
+
mach_timebase_info( &timebase );
|
|
118
|
+
|
|
119
|
+
// convert to ns then to ms
|
|
120
|
+
s_invFrequency = 1e-6 * (double)timebase.numer / (double)timebase.denom;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
uint64_t ticksNow = b2GetTicks();
|
|
124
|
+
return (float)( s_invFrequency * (ticksNow - ticks) );
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
float b2GetMillisecondsAndReset( uint64_t* ticks )
|
|
128
|
+
{
|
|
129
|
+
if ( s_invFrequency == 0 )
|
|
130
|
+
{
|
|
131
|
+
mach_timebase_info_data_t timebase;
|
|
132
|
+
mach_timebase_info( &timebase );
|
|
133
|
+
|
|
134
|
+
// convert to ns then to ms
|
|
135
|
+
s_invFrequency = 1e-6 * (double)timebase.numer / (double)timebase.denom;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
uint64_t ticksNow = b2GetTicks();
|
|
139
|
+
float ms = (float)( s_invFrequency * ( ticksNow - *ticks ) );
|
|
140
|
+
*ticks = ticksNow;
|
|
141
|
+
return ms;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
void b2Yield( void )
|
|
145
|
+
{
|
|
146
|
+
sched_yield();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
#else
|
|
150
|
+
|
|
151
|
+
uint64_t b2GetTicks( void )
|
|
152
|
+
{
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
float b2GetMilliseconds( uint64_t ticks )
|
|
157
|
+
{
|
|
158
|
+
( (void)( ticks ) );
|
|
159
|
+
return 0.0f;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
float b2GetMillisecondsAndReset( uint64_t* ticks )
|
|
163
|
+
{
|
|
164
|
+
( (void)( ticks ) );
|
|
165
|
+
return 0.0f;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
void b2Yield( void )
|
|
169
|
+
{
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
#endif
|
|
173
|
+
|
|
174
|
+
// djb2 hash
|
|
175
|
+
// https://en.wikipedia.org/wiki/List_of_hash_functions
|
|
176
|
+
uint32_t b2Hash( uint32_t hash, const uint8_t* data, int count )
|
|
177
|
+
{
|
|
178
|
+
uint32_t result = hash;
|
|
179
|
+
for ( int i = 0; i < count; i++ )
|
|
180
|
+
{
|
|
181
|
+
result = ( result << 5 ) + result + data[i];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2023 Erin Catto
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
#include "box2d/types.h"
|
|
5
|
+
|
|
6
|
+
#include "constants.h"
|
|
7
|
+
#include "core.h"
|
|
8
|
+
|
|
9
|
+
b2WorldDef b2DefaultWorldDef( void )
|
|
10
|
+
{
|
|
11
|
+
b2WorldDef def = { 0 };
|
|
12
|
+
def.gravity.x = 0.0f;
|
|
13
|
+
def.gravity.y = -10.0f;
|
|
14
|
+
def.hitEventThreshold = 1.0f * b2_lengthUnitsPerMeter;
|
|
15
|
+
def.restitutionThreshold = 1.0f * b2_lengthUnitsPerMeter;
|
|
16
|
+
def.maxContactPushSpeed = 3.0f * b2_lengthUnitsPerMeter;
|
|
17
|
+
def.contactHertz = 30.0;
|
|
18
|
+
def.contactDampingRatio = 10.0f;
|
|
19
|
+
def.jointHertz = 60.0;
|
|
20
|
+
def.jointDampingRatio = 2.0f;
|
|
21
|
+
// 400 meters per second, faster than the speed of sound
|
|
22
|
+
def.maximumLinearSpeed = 400.0f * b2_lengthUnitsPerMeter;
|
|
23
|
+
def.enableSleep = true;
|
|
24
|
+
def.enableContinuous = true;
|
|
25
|
+
def.internalValue = B2_SECRET_COOKIE;
|
|
26
|
+
return def;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
b2BodyDef b2DefaultBodyDef( void )
|
|
30
|
+
{
|
|
31
|
+
b2BodyDef def = { 0 };
|
|
32
|
+
def.type = b2_staticBody;
|
|
33
|
+
def.rotation = b2Rot_identity;
|
|
34
|
+
def.sleepThreshold = 0.05f * b2_lengthUnitsPerMeter;
|
|
35
|
+
def.gravityScale = 1.0f;
|
|
36
|
+
def.enableSleep = true;
|
|
37
|
+
def.isAwake = true;
|
|
38
|
+
def.isEnabled = true;
|
|
39
|
+
def.internalValue = B2_SECRET_COOKIE;
|
|
40
|
+
return def;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
b2Filter b2DefaultFilter( void )
|
|
44
|
+
{
|
|
45
|
+
b2Filter filter = { B2_DEFAULT_CATEGORY_BITS, B2_DEFAULT_MASK_BITS, 0 };
|
|
46
|
+
return filter;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
b2QueryFilter b2DefaultQueryFilter( void )
|
|
50
|
+
{
|
|
51
|
+
b2QueryFilter filter = { B2_DEFAULT_CATEGORY_BITS, B2_DEFAULT_MASK_BITS };
|
|
52
|
+
return filter;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
b2ShapeDef b2DefaultShapeDef( void )
|
|
56
|
+
{
|
|
57
|
+
b2ShapeDef def = { 0 };
|
|
58
|
+
def.material.friction = 0.6f;
|
|
59
|
+
def.density = 1.0f;
|
|
60
|
+
def.filter = b2DefaultFilter();
|
|
61
|
+
def.updateBodyMass = true;
|
|
62
|
+
def.invokeContactCreation = true;
|
|
63
|
+
def.internalValue = B2_SECRET_COOKIE;
|
|
64
|
+
return def;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
b2SurfaceMaterial b2DefaultSurfaceMaterial( void )
|
|
68
|
+
{
|
|
69
|
+
b2SurfaceMaterial material = {
|
|
70
|
+
.friction = 0.6f,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return material;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
b2ChainDef b2DefaultChainDef( void )
|
|
77
|
+
{
|
|
78
|
+
static b2SurfaceMaterial defaultMaterial = {
|
|
79
|
+
.friction = 0.6f,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
b2ChainDef def = { 0 };
|
|
83
|
+
def.materials = &defaultMaterial;
|
|
84
|
+
def.materialCount = 1;
|
|
85
|
+
def.filter = b2DefaultFilter();
|
|
86
|
+
def.internalValue = B2_SECRET_COOKIE;
|
|
87
|
+
return def;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static void b2EmptyDrawPolygon( const b2Vec2* vertices, int vertexCount, b2HexColor color, void* context )
|
|
91
|
+
{
|
|
92
|
+
B2_UNUSED( vertices, vertexCount, color, context );
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static void b2EmptyDrawSolidPolygon( b2Transform transform, const b2Vec2* vertices, int vertexCount, float radius,
|
|
96
|
+
b2HexColor color, void* context )
|
|
97
|
+
{
|
|
98
|
+
B2_UNUSED( transform, vertices, vertexCount, radius, color, context );
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static void b2EmptyDrawCircle( b2Vec2 center, float radius, b2HexColor color, void* context )
|
|
102
|
+
{
|
|
103
|
+
B2_UNUSED( center, radius, color, context );
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
static void b2EmptyDrawSolidCircle( b2Transform transform, float radius, b2HexColor color, void* context )
|
|
107
|
+
{
|
|
108
|
+
B2_UNUSED( transform, radius, color, context );
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
static void b2EmptyDrawSolidCapsule( b2Vec2 p1, b2Vec2 p2, float radius, b2HexColor color, void* context )
|
|
112
|
+
{
|
|
113
|
+
B2_UNUSED( p1, p2, radius, color, context );
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static void b2EmptyDrawSegment( b2Vec2 p1, b2Vec2 p2, b2HexColor color, void* context )
|
|
117
|
+
{
|
|
118
|
+
B2_UNUSED( p1, p2, color, context );
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
static void b2EmptyDrawTransform( b2Transform transform, void* context )
|
|
122
|
+
{
|
|
123
|
+
B2_UNUSED( transform, context );
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
static void b2EmptyDrawPoint( b2Vec2 p, float size, b2HexColor color, void* context )
|
|
127
|
+
{
|
|
128
|
+
B2_UNUSED( p, size, color, context );
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static void b2EmptyDrawString( b2Vec2 p, const char* s, b2HexColor color, void* context )
|
|
132
|
+
{
|
|
133
|
+
B2_UNUSED( p, s, color, context );
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
b2DebugDraw b2DefaultDebugDraw( void )
|
|
137
|
+
{
|
|
138
|
+
b2DebugDraw draw = { 0 };
|
|
139
|
+
|
|
140
|
+
// These allow the user to skip some implementations and not hit null exceptions.
|
|
141
|
+
draw.DrawPolygonFcn = b2EmptyDrawPolygon;
|
|
142
|
+
draw.DrawSolidPolygonFcn = b2EmptyDrawSolidPolygon;
|
|
143
|
+
draw.DrawCircleFcn = b2EmptyDrawCircle;
|
|
144
|
+
draw.DrawSolidCircleFcn = b2EmptyDrawSolidCircle;
|
|
145
|
+
draw.DrawSolidCapsuleFcn = b2EmptyDrawSolidCapsule;
|
|
146
|
+
draw.DrawSegmentFcn = b2EmptyDrawSegment;
|
|
147
|
+
draw.DrawTransformFcn = b2EmptyDrawTransform;
|
|
148
|
+
draw.DrawPointFcn = b2EmptyDrawPoint;
|
|
149
|
+
draw.DrawStringFcn = b2EmptyDrawString;
|
|
150
|
+
return draw;
|
|
151
|
+
}
|