@dice-o-rolla/dice-physics-rapier 0.2.0 → 0.3.1

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.
package/README.md CHANGED
@@ -6,6 +6,10 @@ bodies, tray boundaries, convex colliders, and settled orientation snapshots.
6
6
  Most browser applications should use the preassembled entry point from
7
7
  `@dice-o-rolla/dice-engine/browser`.
8
8
 
9
+ `clear()` restores a deterministic configured baseline: it invalidates dynamic handles, recreates
10
+ the Rapier World and EventQueue, and reapplies the current gravity and tray. This lets repeated
11
+ seeded engine simulations reuse one adapter without inheriting solver state from an earlier run.
12
+
9
13
  ```ts
10
14
  import { RapierPhysicsWorld } from '@dice-o-rolla/dice-physics-rapier';
11
15
  ```
@@ -3,6 +3,15 @@ import { RapierDieBody } from './rapier-die-body.js';
3
3
  import { initializeRapier } from './rapier-module.js';
4
4
  import { assertNonNegative, assertPositive, assertQuaternion, assertVector } from './validation.js';
5
5
  const DEFAULT_GRAVITY = { x: 0, y: -9.81, z: 0 };
6
+ function snapshotVector(value) {
7
+ return Object.freeze({ ...value });
8
+ }
9
+ function snapshotTray(options) {
10
+ return Object.freeze({
11
+ ...options,
12
+ material: Object.freeze({ ...options.material }),
13
+ });
14
+ }
6
15
  export class RapierPhysicsWorld {
7
16
  #rapier;
8
17
  #world;
@@ -10,13 +19,16 @@ export class RapierPhysicsWorld {
10
19
  #dice = new Map();
11
20
  #colliderDice = new Map();
12
21
  #dieColliders = new Map();
22
+ #gravity;
23
+ #tray;
13
24
  #trayBody;
14
25
  #collisionEventsEnabled = false;
15
26
  #destroyed = false;
16
27
  constructor(rapier, gravity) {
17
28
  assertVector(gravity, 'gravity');
18
29
  this.#rapier = rapier;
19
- this.#world = new rapier.World(gravity);
30
+ this.#gravity = snapshotVector(gravity);
31
+ this.#world = new rapier.World(this.#gravity);
20
32
  this.#eventQueue = new rapier.EventQueue(true);
21
33
  }
22
34
  static async create(options = {}) {
@@ -68,6 +80,10 @@ export class RapierPhysicsWorld {
68
80
  assertPositive(options.wallThickness, 'tray.wallThickness');
69
81
  assertNonNegative(options.material.friction, 'tray.material.friction');
70
82
  assertNonNegative(options.material.restitution, 'tray.material.restitution');
83
+ this.#tray = snapshotTray(options);
84
+ this.#configureTray(this.#tray);
85
+ }
86
+ #configureTray(options) {
71
87
  this.#removeTray();
72
88
  const body = this.#world.createRigidBody(this.#rapier.RigidBodyDesc.fixed());
73
89
  const halfWidth = options.width / 2;
@@ -91,7 +107,8 @@ export class RapierPhysicsWorld {
91
107
  setGravity(gravity) {
92
108
  this.#assertAlive();
93
109
  assertVector(gravity, 'gravity');
94
- this.#world.gravity = { x: gravity.x, y: gravity.y, z: gravity.z };
110
+ this.#gravity = snapshotVector(gravity);
111
+ this.#world.gravity = this.#gravity;
95
112
  }
96
113
  setCollisionEventsEnabled(enabled) {
97
114
  this.#assertAlive();
@@ -163,24 +180,32 @@ export class RapierPhysicsWorld {
163
180
  }
164
181
  clear() {
165
182
  this.#assertAlive();
166
- for (const die of this.#dice.values()) {
167
- this.#world.removeRigidBody(die.body);
168
- die.invalidate();
169
- }
170
- this.#dice.clear();
171
- this.#colliderDice.clear();
172
- this.#dieColliders.clear();
173
- this.#eventQueue.clear();
183
+ this.#invalidateDice();
184
+ this.#eventQueue.free();
185
+ this.#world.free();
186
+ this.#world = new this.#rapier.World(this.#gravity);
187
+ this.#eventQueue = new this.#rapier.EventQueue(true);
188
+ this.#trayBody = undefined;
189
+ if (this.#tray !== undefined)
190
+ this.#configureTray(this.#tray);
174
191
  }
175
192
  destroy() {
176
193
  if (this.#destroyed)
177
194
  return;
178
- this.clear();
179
- this.#removeTray();
195
+ this.#invalidateDice();
180
196
  this.#eventQueue.free();
181
197
  this.#world.free();
198
+ this.#trayBody = undefined;
199
+ this.#tray = undefined;
182
200
  this.#destroyed = true;
183
201
  }
202
+ #invalidateDice() {
203
+ for (const die of this.#dice.values())
204
+ die.invalidate();
205
+ this.#dice.clear();
206
+ this.#colliderDice.clear();
207
+ this.#dieColliders.clear();
208
+ }
184
209
  #removeTray() {
185
210
  if (this.#trayBody !== undefined) {
186
211
  this.#world.removeRigidBody(this.#trayBody);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dice-o-rolla/dice-physics-rapier",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Rapier 3D physics backend for physical dice simulation.",
5
5
  "keywords": [
6
6
  "dice",
@@ -40,8 +40,8 @@
40
40
  "registry": "https://registry.npmjs.org/"
41
41
  },
42
42
  "dependencies": {
43
- "@dice-o-rolla/dice-core": "0.2.0",
44
- "@dice-o-rolla/dice-physics": "0.2.0",
43
+ "@dice-o-rolla/dice-core": "0.3.1",
44
+ "@dice-o-rolla/dice-physics": "0.3.1",
45
45
  "@dimforge/rapier3d-compat": "^0.20.0"
46
46
  },
47
47
  "engines": {