@forgeax/engine-physics-rapier3d 0.1.32 → 0.1.34
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/dist/__tests__/state-reconcile.unit.test.d.ts +2 -0
- package/dist/__tests__/state-reconcile.unit.test.d.ts.map +1 -0
- package/dist/index.mjs +60 -153
- package/dist/index.mjs.map +1 -1
- package/dist/rapier-physics-world-3d.d.ts +0 -2
- package/dist/rapier-physics-world-3d.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/__tests__/state-reconcile.unit.test.ts +55 -0
- package/src/rapier-physics-world-3d.ts +81 -203
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-reconcile.unit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/state-reconcile.unit.test.ts"],"names":[],"mappings":""}
|
package/dist/index.mjs
CHANGED
|
@@ -1,38 +1,19 @@
|
|
|
1
1
|
import { defineSystem, FixedTime, componentDefinition, Disabled, FixedUpdate } from '@forgeax/engine-ecs';
|
|
2
|
-
import {
|
|
3
|
-
import { readStructuralEvidence } from '@forgeax/engine-ecs/projection';
|
|
2
|
+
import { createStateProjection } from '@forgeax/engine-ecs/projection';
|
|
4
3
|
import { vec3, quat, mat4 } from '@forgeax/engine-math';
|
|
5
4
|
import { CollidingEntities, DerivedPhysicsError, cloneDerivedPhysicsInput, validateMassProperties, DERIVED_PHYSICS_LIMITS, estimateDerivedPhysicsInputBytes, preserveCenterOfMassVelocity, PhysicsError, PHYSICS_ERROR_HINTS, CharacterController, rigidBodyTypeFromF32, RigidBody, Collider, colliderShapeFromF32, RIGID_BODY_TYPE_STATIC, registerPhysicsComponents, PhysicsSet } from '@forgeax/engine-physics';
|
|
6
5
|
import { ChildOf } from '@forgeax/engine-scene';
|
|
7
6
|
import { err, ok, PhysicsError as PhysicsError$1 } from '@forgeax/engine-types';
|
|
8
7
|
|
|
9
8
|
// src/rapier-physics-world-3d.ts
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
for (const entry of queries) {
|
|
19
|
-
for (const _span of entry.query.spans().unwrap()) {
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
function ensurePhysicsDelta(deltas, entity) {
|
|
24
|
-
let delta = deltas.get(entity);
|
|
25
|
-
if (delta === void 0) {
|
|
26
|
-
delta = {
|
|
27
|
-
transformChanged: false,
|
|
28
|
-
colliderChanged: false,
|
|
29
|
-
rigidBodyChanged: false,
|
|
30
|
-
characterControllerChanged: false,
|
|
31
|
-
characterControllerStructureChanged: false
|
|
32
|
-
};
|
|
33
|
-
deltas.set(entity, delta);
|
|
34
|
-
}
|
|
35
|
-
return delta;
|
|
9
|
+
function samePhysicsValue(left, right) {
|
|
10
|
+
if (Object.is(left, right)) return true;
|
|
11
|
+
if (left === void 0 || right === void 0 || left === null || right === null || typeof left !== "object" || typeof right !== "object")
|
|
12
|
+
return false;
|
|
13
|
+
const a = left;
|
|
14
|
+
const b = right;
|
|
15
|
+
const keys = Object.keys(a);
|
|
16
|
+
return keys.length === Object.keys(b).length && keys.every((key) => samePhysicsValue(a[key], b[key]));
|
|
36
17
|
}
|
|
37
18
|
var DEG_TO_RAD = Math.PI / 180;
|
|
38
19
|
function applyKccTuning(ctrl, cc) {
|
|
@@ -2038,61 +2019,6 @@ var RapierPhysicsWorld3D = class {
|
|
|
2038
2019
|
}
|
|
2039
2020
|
this.removeKccController(entity);
|
|
2040
2021
|
}
|
|
2041
|
-
resetForFullReconcile(transformlessStatic) {
|
|
2042
|
-
for (const entity of [...this.entityMap.keys()]) {
|
|
2043
|
-
if (transformlessStatic.has(entity) && this.isCommittedFixedBody(entity)) {
|
|
2044
|
-
this.removeKccController(entity);
|
|
2045
|
-
continue;
|
|
2046
|
-
}
|
|
2047
|
-
this.removeEntity(entity);
|
|
2048
|
-
}
|
|
2049
|
-
}
|
|
2050
|
-
fullReconcilePhysicsState(state) {
|
|
2051
|
-
const descriptors = [];
|
|
2052
|
-
const transformlessStatic = /* @__PURE__ */ new Set();
|
|
2053
|
-
const committedDerived = this.derivedBodies.size > 0 ? this.captureDerivedPhysicsState() : void 0;
|
|
2054
|
-
for (const query of state.queries)
|
|
2055
|
-
for (const row of query) {
|
|
2056
|
-
if (!row.has(state.transformComponent)) {
|
|
2057
|
-
if (physicsRowIsStatic(row)) transformlessStatic.add(row.entity);
|
|
2058
|
-
continue;
|
|
2059
|
-
}
|
|
2060
|
-
const descriptor = readPhysicsSyncDescriptor(
|
|
2061
|
-
row,
|
|
2062
|
-
state.transformComponent,
|
|
2063
|
-
state.globalTransformComponent
|
|
2064
|
-
);
|
|
2065
|
-
if (descriptor !== void 0) descriptors.push(descriptor);
|
|
2066
|
-
}
|
|
2067
|
-
this.resetForFullReconcile(transformlessStatic);
|
|
2068
|
-
for (const descriptor of descriptors) {
|
|
2069
|
-
this.ensureBody(
|
|
2070
|
-
descriptor.entity,
|
|
2071
|
-
descriptor.transform,
|
|
2072
|
-
descriptor.rigidBody,
|
|
2073
|
-
descriptor.collider
|
|
2074
|
-
);
|
|
2075
|
-
}
|
|
2076
|
-
if (committedDerived !== void 0) {
|
|
2077
|
-
const restorableBodies = committedDerived.bodies.filter(
|
|
2078
|
-
(body) => this.entityMap.has(body.entity) && !this.derivedBodies.has(body.entity)
|
|
2079
|
-
);
|
|
2080
|
-
if (restorableBodies.length > 0) {
|
|
2081
|
-
const restorable = Object.freeze({
|
|
2082
|
-
...committedDerived,
|
|
2083
|
-
bodies: Object.freeze(restorableBodies)
|
|
2084
|
-
});
|
|
2085
|
-
const restored = this.restoreDerivedPhysicsState(restorable);
|
|
2086
|
-
if (!restored.ok) {
|
|
2087
|
-
this.invalidateDerivedShapeCandidates("full-reconcile-restore-failed");
|
|
2088
|
-
}
|
|
2089
|
-
}
|
|
2090
|
-
}
|
|
2091
|
-
drainPhysicsChangeQueries(state.changeQueries);
|
|
2092
|
-
state.structuralCursor = readStructuralEvidence(state.world, state.structuralCursor).cursor;
|
|
2093
|
-
state.structureEpoch = state.world.getStructureEpoch();
|
|
2094
|
-
state.initialized = true;
|
|
2095
|
-
}
|
|
2096
2022
|
reconcilePhysicsDelta(state, entity, delta) {
|
|
2097
2023
|
const row = state.queries.map((query) => query.at(entity)).find((entry) => entry !== void 0);
|
|
2098
2024
|
if (row === void 0) {
|
|
@@ -2218,83 +2144,64 @@ var RapierPhysicsWorld3D = class {
|
|
|
2218
2144
|
transformComponent,
|
|
2219
2145
|
globalTransformComponent,
|
|
2220
2146
|
queries: [queryResult.value, bodyQuery.value],
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2147
|
+
projection: createStateProjection(
|
|
2148
|
+
world,
|
|
2149
|
+
[
|
|
2150
|
+
transformComponent,
|
|
2151
|
+
globalTransformComponent,
|
|
2152
|
+
Collider,
|
|
2153
|
+
RigidBody,
|
|
2154
|
+
CharacterController,
|
|
2155
|
+
ChildOf,
|
|
2156
|
+
Disabled
|
|
2157
|
+
],
|
|
2158
|
+
[Collider, RigidBody]
|
|
2159
|
+
),
|
|
2160
|
+
accepted: /* @__PURE__ */ new Map()
|
|
2232
2161
|
};
|
|
2233
2162
|
this.syncState = state;
|
|
2234
2163
|
}
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
if (structural.status === "overflow") {
|
|
2245
|
-
this.fullReconcilePhysicsState(state);
|
|
2246
|
-
return;
|
|
2164
|
+
const batch = state.projection.read();
|
|
2165
|
+
const updates = [];
|
|
2166
|
+
for (const index of batch.indices) {
|
|
2167
|
+
const entity = state.projection.entity(index);
|
|
2168
|
+
const previous = state.accepted.get(index);
|
|
2169
|
+
if (previous !== void 0 && previous.entity !== entity) this.removeEntity(previous.entity);
|
|
2170
|
+
if (entity === void 0) {
|
|
2171
|
+
updates.push({ index, descriptor: void 0 });
|
|
2172
|
+
continue;
|
|
2247
2173
|
}
|
|
2248
|
-
|
|
2249
|
-
const
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
const characterControllerId = componentId(CharacterController);
|
|
2253
|
-
const childOfId = componentId(ChildOf);
|
|
2254
|
-
const disabledId = componentId(Disabled);
|
|
2255
|
-
for (const evidence of structural.events) {
|
|
2256
|
-
const id = evidence.componentId;
|
|
2257
|
-
if (evidence.kind !== "spawn" && evidence.kind !== "despawn" && id !== transformId && id !== globalTransformId && id !== colliderId && id !== rigidBodyId && id !== characterControllerId && id !== childOfId && id !== disabledId) {
|
|
2258
|
-
continue;
|
|
2259
|
-
}
|
|
2260
|
-
const delta = ensurePhysicsDelta(deltas, evidence.entity);
|
|
2261
|
-
if (evidence.kind === "spawn" || evidence.kind === "despawn") {
|
|
2262
|
-
delta.transformChanged = true;
|
|
2263
|
-
delta.colliderChanged = true;
|
|
2264
|
-
delta.rigidBodyChanged = true;
|
|
2265
|
-
delta.characterControllerChanged = true;
|
|
2266
|
-
delta.characterControllerStructureChanged = true;
|
|
2267
|
-
} else if (id === transformId || id === globalTransformId || id === childOfId) {
|
|
2268
|
-
delta.transformChanged = true;
|
|
2269
|
-
} else if (id === colliderId || id === disabledId) {
|
|
2270
|
-
delta.colliderChanged = true;
|
|
2271
|
-
} else if (id === rigidBodyId) {
|
|
2272
|
-
delta.rigidBodyChanged = true;
|
|
2273
|
-
} else if (id === characterControllerId) {
|
|
2274
|
-
delta.characterControllerChanged = true;
|
|
2275
|
-
delta.characterControllerStructureChanged = true;
|
|
2276
|
-
}
|
|
2174
|
+
let row;
|
|
2175
|
+
for (const query of state.queries) {
|
|
2176
|
+
row = query.at(entity);
|
|
2177
|
+
if (row !== void 0) break;
|
|
2277
2178
|
}
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
const entity = rawEntity;
|
|
2283
|
-
const delta = ensurePhysicsDelta(deltas, entity);
|
|
2284
|
-
if (entry.component === transformComponent || entry.component === globalTransformComponent || entry.component === ChildOf) {
|
|
2285
|
-
delta.transformChanged = true;
|
|
2286
|
-
} else if (entry.component === Collider) {
|
|
2287
|
-
delta.colliderChanged = true;
|
|
2288
|
-
} else if (entry.component === RigidBody) {
|
|
2289
|
-
delta.rigidBodyChanged = true;
|
|
2290
|
-
} else if (entry.component === CharacterController) {
|
|
2291
|
-
delta.characterControllerChanged = true;
|
|
2292
|
-
}
|
|
2293
|
-
}
|
|
2179
|
+
if (row === void 0) {
|
|
2180
|
+
this.removeEntity(entity);
|
|
2181
|
+
updates.push({ index, descriptor: void 0 });
|
|
2182
|
+
continue;
|
|
2294
2183
|
}
|
|
2184
|
+
const descriptor = readPhysicsSyncDescriptor(
|
|
2185
|
+
row,
|
|
2186
|
+
transformComponent,
|
|
2187
|
+
globalTransformComponent
|
|
2188
|
+
);
|
|
2189
|
+
const prior = previous?.entity === entity ? previous : void 0;
|
|
2190
|
+
const delta = {
|
|
2191
|
+
transformChanged: !samePhysicsValue(prior?.transform, descriptor?.transform),
|
|
2192
|
+
colliderChanged: descriptor === void 0 ? state.projection.changed(entity, Collider) : !samePhysicsValue(prior?.collider, descriptor.collider),
|
|
2193
|
+
rigidBodyChanged: descriptor === void 0 ? state.projection.changed(entity, RigidBody) : !samePhysicsValue(prior?.rigidBody, descriptor.rigidBody),
|
|
2194
|
+
characterControllerChanged: prior?.characterControllerOffset !== descriptor?.characterControllerOffset || prior?.hasCharacterController !== descriptor?.hasCharacterController,
|
|
2195
|
+
characterControllerStructureChanged: prior?.hasCharacterController !== descriptor?.hasCharacterController
|
|
2196
|
+
};
|
|
2197
|
+
this.reconcilePhysicsDelta(state, entity, delta);
|
|
2198
|
+
updates.push({ index, descriptor: descriptor ?? (this.hasBody(entity) ? prior : void 0) });
|
|
2199
|
+
}
|
|
2200
|
+
batch.accept();
|
|
2201
|
+
for (const { index, descriptor } of updates) {
|
|
2202
|
+
if (descriptor === void 0) state.accepted.delete(index);
|
|
2203
|
+
else state.accepted.set(index, descriptor);
|
|
2295
2204
|
}
|
|
2296
|
-
if (deltas.size === 0) return;
|
|
2297
|
-
for (const [entity, delta] of deltas) this.reconcilePhysicsDelta(state, entity, delta);
|
|
2298
2205
|
}
|
|
2299
2206
|
/**
|
|
2300
2207
|
* Remove an entity's cached KCC and unregister it from the Rapier world
|