@threlte/rapier 3.0.0-next.1 → 3.0.0-next.10
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/components/Attractor/Attractor.svelte +2 -2
- package/dist/components/Attractor/Attractor.svelte.d.ts +2 -10
- package/dist/components/Colliders/AutoColliders.svelte +23 -13
- package/dist/components/Colliders/AutoColliders.svelte.d.ts +16 -12
- package/dist/components/Colliders/Collider.svelte +23 -10
- package/dist/components/Colliders/Collider.svelte.d.ts +6 -9
- package/dist/components/CollisionGroups/CollisionGroups.svelte +2 -2
- package/dist/components/CollisionGroups/CollisionGroups.svelte.d.ts +5 -1
- package/dist/components/RigidBody/RigidBody.svelte +39 -9
- package/dist/components/RigidBody/RigidBody.svelte.d.ts +5 -15
- package/dist/components/RigidBody/overrideTeleportMethods.d.ts +14 -0
- package/dist/components/RigidBody/overrideTeleportMethods.js +31 -0
- package/dist/components/World/InnerWorld.svelte +27 -5
- package/dist/components/World/InnerWorld.svelte.d.ts +2 -8
- package/dist/components/World/World.svelte +9 -57
- package/dist/components/World/World.svelte.d.ts +13 -2
- package/dist/lib/applyColliderActiveEvents.d.ts +2 -1
- package/dist/lib/applyColliderActiveEvents.js +9 -9
- package/dist/lib/createPhysicsStages.d.ts +15 -0
- package/dist/lib/createPhysicsStages.js +43 -0
- package/dist/lib/createPhysicsTasks.d.ts +19 -0
- package/dist/{hooks/useFrameHandler.js → lib/createPhysicsTasks.js} +132 -65
- package/dist/lib/createRapierContext.d.ts +14 -20
- package/dist/lib/createRapierContext.js +37 -13
- package/dist/lib/initRapier.svelte.d.ts +1 -0
- package/dist/lib/initRapier.svelte.js +16 -0
- package/dist/lib/keys.d.ts +2 -0
- package/dist/lib/keys.js +2 -0
- package/dist/lib/rigidBodyObjectContext.d.ts +3 -2
- package/dist/lib/useCreateEvent.d.ts +2 -1
- package/dist/lib/useCreateEvent.js +3 -3
- package/dist/recipes/BasicPlayerController.svelte +6 -5
- package/dist/recipes/BasicPlayerController.svelte.d.ts +3 -3
- package/dist/types/types.d.ts +55 -28
- package/package.json +28 -9
- package/dist/hooks/useFixedJoint.d.ts +0 -8
- package/dist/hooks/useFrameHandler.d.ts +0 -3
- package/dist/hooks/useHasEventListener.d.ts +0 -3
- package/dist/hooks/useHasEventListener.js +0 -11
- package/dist/hooks/useJoint.d.ts +0 -8
- package/dist/hooks/usePrismaticJoint.d.ts +0 -8
- package/dist/hooks/useRevoluteJoint.d.ts +0 -8
- package/dist/hooks/useSphericalJoint.d.ts +0 -8
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { ActiveEvents } from '@dimforge/rapier3d-compat';
|
|
2
2
|
export const applyColliderActiveEvents = (collider, colliderEvents = {}, rigidBodyEvents = {}) => {
|
|
3
3
|
let events = 0;
|
|
4
|
-
if (colliderEvents.
|
|
5
|
-
colliderEvents.
|
|
6
|
-
rigidBodyEvents.
|
|
7
|
-
rigidBodyEvents.
|
|
8
|
-
colliderEvents.
|
|
9
|
-
colliderEvents.
|
|
10
|
-
rigidBodyEvents.
|
|
11
|
-
rigidBodyEvents.
|
|
4
|
+
if (colliderEvents.oncollisionenter ||
|
|
5
|
+
colliderEvents.oncollisionexit ||
|
|
6
|
+
rigidBodyEvents.oncollisionenter ||
|
|
7
|
+
rigidBodyEvents.oncollisionexit ||
|
|
8
|
+
colliderEvents.onsensorenter ||
|
|
9
|
+
colliderEvents.onsensorexit ||
|
|
10
|
+
rigidBodyEvents.onsensorenter ||
|
|
11
|
+
rigidBodyEvents.onsensorexit) {
|
|
12
12
|
events = events | ActiveEvents.COLLISION_EVENTS;
|
|
13
13
|
}
|
|
14
|
-
if (colliderEvents.
|
|
14
|
+
if (colliderEvents.oncontact || rigidBodyEvents.oncontact) {
|
|
15
15
|
events = events | ActiveEvents.CONTACT_FORCE_EVENTS;
|
|
16
16
|
}
|
|
17
17
|
if (events > 0) {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type CurrentWritable, type Key, type Stage } from '@threlte/core';
|
|
2
|
+
import type { Framerate } from '../types/types';
|
|
3
|
+
export declare const createPhysicsStages: (framerate: CurrentWritable<Framerate>, simulationOffset: CurrentWritable<number>, updateRigidBodySimulationData: CurrentWritable<boolean>, options?: {
|
|
4
|
+
simulationStageOptions?: {
|
|
5
|
+
before?: (Key | Stage) | (Key | Stage)[];
|
|
6
|
+
after?: (Key | Stage) | (Key | Stage)[];
|
|
7
|
+
};
|
|
8
|
+
synchronizationStageOptions?: {
|
|
9
|
+
before?: (Key | Stage) | (Key | Stage)[];
|
|
10
|
+
after?: (Key | Stage) | (Key | Stage)[];
|
|
11
|
+
};
|
|
12
|
+
}) => {
|
|
13
|
+
simulationStage: Stage;
|
|
14
|
+
synchronizationStage: Stage;
|
|
15
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useStage, useThrelte } from '@threlte/core';
|
|
2
|
+
import { simulationKey, synchronizationKey } from './keys';
|
|
3
|
+
export const createPhysicsStages = (framerate, simulationOffset, updateRigidBodySimulationData, options) => {
|
|
4
|
+
let fixedStepTimeAccumulator = 0;
|
|
5
|
+
let simulationTime = 0;
|
|
6
|
+
let lastSimulationTime = 0;
|
|
7
|
+
const { renderStage } = useThrelte();
|
|
8
|
+
const simulationStage = useStage(simulationKey, {
|
|
9
|
+
after: options?.simulationStageOptions?.after,
|
|
10
|
+
before: options?.simulationStageOptions?.before,
|
|
11
|
+
callback(delta, runTasks) {
|
|
12
|
+
if (framerate.current === 'varying') {
|
|
13
|
+
runTasks();
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
const rate = 1 / framerate.current;
|
|
17
|
+
simulationTime += delta;
|
|
18
|
+
fixedStepTimeAccumulator += delta;
|
|
19
|
+
const iterations = Math.ceil(fixedStepTimeAccumulator / rate);
|
|
20
|
+
for (let iteration = 0; iteration < iterations; iteration++) {
|
|
21
|
+
updateRigidBodySimulationData.set(iteration >= iterations - 2);
|
|
22
|
+
runTasks(rate);
|
|
23
|
+
fixedStepTimeAccumulator -= rate;
|
|
24
|
+
lastSimulationTime += rate;
|
|
25
|
+
}
|
|
26
|
+
simulationOffset.set((simulationTime - lastSimulationTime) / rate + 1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const synchronizationStage = useStage(synchronizationKey, {
|
|
31
|
+
after: options?.synchronizationStageOptions?.after
|
|
32
|
+
? Array.isArray(options.synchronizationStageOptions.after)
|
|
33
|
+
? [...options.synchronizationStageOptions.after, simulationKey]
|
|
34
|
+
: [options.synchronizationStageOptions.after, simulationKey]
|
|
35
|
+
: simulationKey,
|
|
36
|
+
before: options?.synchronizationStageOptions?.before
|
|
37
|
+
? Array.isArray(options.synchronizationStageOptions.before)
|
|
38
|
+
? [...options.synchronizationStageOptions.before, renderStage]
|
|
39
|
+
: [options.synchronizationStageOptions.before, renderStage]
|
|
40
|
+
: renderStage
|
|
41
|
+
});
|
|
42
|
+
return { simulationStage, synchronizationStage };
|
|
43
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type World } from '@dimforge/rapier3d-compat';
|
|
2
|
+
import { type CurrentWritable, type Stage } from '@threlte/core';
|
|
3
|
+
import { Object3D, Quaternion, Vector3 } from 'three';
|
|
4
|
+
import type { ColliderEvents, Framerate, RigidBodyEvents } from '../types/types';
|
|
5
|
+
type PhysicsUserData = {
|
|
6
|
+
currentPosition: Vector3;
|
|
7
|
+
currentQuaternion: Quaternion;
|
|
8
|
+
lastPosition: Vector3;
|
|
9
|
+
lastQuaternion: Quaternion;
|
|
10
|
+
resetPosition: boolean;
|
|
11
|
+
resetRotation: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare const initializeRigidBodyUserData: (obj: Object3D) => PhysicsUserData;
|
|
14
|
+
export declare const setInitialRigidBodyState: (obj: Object3D, initialPosition: Vector3, initialQuaternion: Quaternion) => void;
|
|
15
|
+
export declare const createPhysicsTasks: (world: World, framerate: CurrentWritable<Framerate>, simulationOffset: CurrentWritable<number>, rigidBodyObjects: Map<number, Object3D>, updateRigidBodySimulationData: CurrentWritable<boolean>, colliderEventDispatchers: Map<number, ColliderEvents>, rigidBodyEventDispatchers: Map<number, RigidBodyEvents>, simulationStage: Stage, synchronizationStage: Stage) => {
|
|
16
|
+
simulationTask: import("@threlte/core").Task;
|
|
17
|
+
synchronizationTask: import("@threlte/core").Task;
|
|
18
|
+
};
|
|
19
|
+
export {};
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import { EventQueue } from '@dimforge/rapier3d-compat';
|
|
2
2
|
import { useTask } from '@threlte/core';
|
|
3
|
-
import { derived } from 'svelte/store';
|
|
4
3
|
import { Object3D, Quaternion, Vector3 } from 'three';
|
|
4
|
+
import { simulationKey, synchronizationKey } from './keys';
|
|
5
5
|
const tempObject = new Object3D();
|
|
6
6
|
const tempVector3 = new Vector3();
|
|
7
7
|
const tempQuaternion = new Quaternion();
|
|
8
|
-
const getEventDispatchers = (
|
|
9
|
-
const collider1Events =
|
|
10
|
-
const collider2Events =
|
|
8
|
+
const getEventDispatchers = (collider1, collider2, colliderEventDispatchers, rigidBodyEventDispatchers) => {
|
|
9
|
+
const collider1Events = colliderEventDispatchers.get(collider1.handle);
|
|
10
|
+
const collider2Events = colliderEventDispatchers.get(collider2.handle);
|
|
11
11
|
const rigidBody1 = collider1.parent();
|
|
12
12
|
const rigidBody2 = collider2.parent();
|
|
13
|
-
const rigidBody1Events = rigidBody1
|
|
14
|
-
|
|
15
|
-
: undefined;
|
|
16
|
-
const rigidBody2Events = rigidBody2
|
|
17
|
-
? ctx.rigidBodyEventDispatchers.get(rigidBody2.handle)
|
|
18
|
-
: undefined;
|
|
13
|
+
const rigidBody1Events = rigidBody1 ? rigidBodyEventDispatchers.get(rigidBody1.handle) : undefined;
|
|
14
|
+
const rigidBody2Events = rigidBody2 ? rigidBodyEventDispatchers.get(rigidBody2.handle) : undefined;
|
|
19
15
|
return {
|
|
20
16
|
collider1Events,
|
|
21
17
|
collider2Events,
|
|
@@ -23,50 +19,89 @@ const getEventDispatchers = (ctx, collider1, collider2) => {
|
|
|
23
19
|
rigidBody2Events
|
|
24
20
|
};
|
|
25
21
|
};
|
|
26
|
-
|
|
22
|
+
const objectHasPhysicsUserData = (obj) => {
|
|
23
|
+
return obj.userData.physics !== undefined;
|
|
24
|
+
};
|
|
25
|
+
export const initializeRigidBodyUserData = (obj) => {
|
|
26
|
+
const userData = {
|
|
27
|
+
currentPosition: new Vector3(),
|
|
28
|
+
currentQuaternion: new Quaternion(),
|
|
29
|
+
lastPosition: new Vector3(),
|
|
30
|
+
lastQuaternion: new Quaternion(),
|
|
31
|
+
resetPosition: false,
|
|
32
|
+
resetRotation: false
|
|
33
|
+
};
|
|
34
|
+
obj.userData.physics = userData;
|
|
35
|
+
return userData;
|
|
36
|
+
};
|
|
37
|
+
export const setInitialRigidBodyState = (obj, initialPosition, initialQuaternion) => {
|
|
38
|
+
if (!objectHasPhysicsUserData(obj)) {
|
|
39
|
+
initializeRigidBodyUserData(obj);
|
|
40
|
+
}
|
|
41
|
+
const userData = obj.userData.physics;
|
|
42
|
+
userData.currentPosition.copy(initialPosition);
|
|
43
|
+
userData.lastPosition.copy(initialPosition);
|
|
44
|
+
userData.currentQuaternion.copy(initialQuaternion);
|
|
45
|
+
userData.lastQuaternion.copy(initialQuaternion);
|
|
46
|
+
};
|
|
47
|
+
export const createPhysicsTasks = (world, framerate, simulationOffset, rigidBodyObjects, updateRigidBodySimulationData, colliderEventDispatchers, rigidBodyEventDispatchers, simulationStage, synchronizationStage) => {
|
|
27
48
|
const eventQueue = new EventQueue(false);
|
|
28
|
-
const
|
|
29
|
-
// if (!eventQueue) return
|
|
30
|
-
const { world } = ctx;
|
|
49
|
+
const simulation = useTask(simulationKey, (delta) => {
|
|
31
50
|
// Set timestep to current delta, to allow for variable frame rates
|
|
32
51
|
// We cap the delta at 100, so that the physics simulation doesn't get wild
|
|
33
|
-
|
|
52
|
+
if (framerate.current === 'varying') {
|
|
53
|
+
world.timestep = Math.min(delta, 0.1);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
world.timestep = delta;
|
|
57
|
+
}
|
|
34
58
|
world.step(eventQueue);
|
|
35
|
-
|
|
36
|
-
ctx.rigidBodyObjects.forEach((mesh, handle) => {
|
|
59
|
+
rigidBodyObjects.forEach((mesh, handle) => {
|
|
37
60
|
const rigidBody = world.getRigidBody(handle);
|
|
38
|
-
if (!rigidBody)
|
|
39
|
-
return;
|
|
40
|
-
const events = ctx.rigidBodyEventDispatchers.get(handle);
|
|
41
61
|
if (!rigidBody || !rigidBody.isValid())
|
|
42
62
|
return;
|
|
63
|
+
const events = rigidBodyEventDispatchers.get(handle);
|
|
43
64
|
if (events) {
|
|
44
65
|
if (rigidBody.isSleeping() && !mesh.userData.isSleeping) {
|
|
45
|
-
events.
|
|
66
|
+
events.onsleep?.();
|
|
46
67
|
}
|
|
47
68
|
if (!rigidBody.isSleeping() && mesh.userData.isSleeping) {
|
|
48
|
-
events.
|
|
69
|
+
events.onwake?.();
|
|
49
70
|
}
|
|
50
71
|
mesh.userData.isSleeping = rigidBody.isSleeping();
|
|
51
72
|
}
|
|
52
|
-
if (
|
|
73
|
+
if (rigidBody.isSleeping() || rigidBody.isFixed() || !mesh.parent) {
|
|
53
74
|
return;
|
|
54
75
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
if (updateRigidBodySimulationData.current) {
|
|
77
|
+
const translation = rigidBody.translation();
|
|
78
|
+
const rotation = rigidBody.rotation();
|
|
79
|
+
if (objectHasPhysicsUserData(mesh)) {
|
|
80
|
+
const userData = mesh.userData.physics;
|
|
81
|
+
if (userData.resetPosition) {
|
|
82
|
+
userData.resetPosition = false;
|
|
83
|
+
userData.lastPosition.set(translation.x, translation.y, translation.z);
|
|
84
|
+
userData.currentPosition.set(translation.x, translation.y, translation.z);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
userData.lastPosition.copy(userData.currentPosition);
|
|
88
|
+
userData.currentPosition.set(translation.x, translation.y, translation.z);
|
|
89
|
+
}
|
|
90
|
+
if (userData.resetRotation) {
|
|
91
|
+
userData.resetRotation = false;
|
|
92
|
+
userData.lastQuaternion.set(rotation.x, rotation.y, rotation.z, rotation.w);
|
|
93
|
+
userData.currentQuaternion.set(rotation.x, rotation.y, rotation.z, rotation.w);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
userData.lastQuaternion.copy(userData.currentQuaternion);
|
|
97
|
+
userData.currentQuaternion.set(rotation.x, rotation.y, rotation.z, rotation.w);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
initializeRigidBodyUserData(mesh);
|
|
102
|
+
setInitialRigidBodyState(mesh, tempVector3.set(translation.x, translation.y, translation.z), tempQuaternion.set(rotation.x, rotation.y, rotation.z, rotation.w));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
70
105
|
});
|
|
71
106
|
eventQueue.drainContactForceEvents((e) => {
|
|
72
107
|
const collider1 = world.getCollider(e.collider1());
|
|
@@ -75,11 +110,11 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
75
110
|
if (!collider1 || !collider2) {
|
|
76
111
|
return;
|
|
77
112
|
}
|
|
78
|
-
const { collider1Events, collider2Events, rigidBody1Events, rigidBody2Events } = getEventDispatchers(
|
|
113
|
+
const { collider1Events, collider2Events, rigidBody1Events, rigidBody2Events } = getEventDispatchers(collider1, collider2, colliderEventDispatchers, rigidBodyEventDispatchers);
|
|
79
114
|
const rigidBody1 = collider1.parent();
|
|
80
115
|
const rigidBody2 = collider2.parent();
|
|
81
116
|
// Collider events
|
|
82
|
-
collider1Events?.
|
|
117
|
+
collider1Events?.oncontact?.({
|
|
83
118
|
targetCollider: collider2,
|
|
84
119
|
targetRigidBody: rigidBody2,
|
|
85
120
|
maxForceDirection: e.maxForceDirection(),
|
|
@@ -87,7 +122,7 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
87
122
|
totalForce: e.totalForce(),
|
|
88
123
|
totalForceMagnitude: e.totalForceMagnitude()
|
|
89
124
|
});
|
|
90
|
-
collider2Events?.
|
|
125
|
+
collider2Events?.oncontact?.({
|
|
91
126
|
targetCollider: collider1,
|
|
92
127
|
targetRigidBody: rigidBody1,
|
|
93
128
|
maxForceDirection: e.maxForceDirection(),
|
|
@@ -96,7 +131,7 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
96
131
|
totalForceMagnitude: e.totalForceMagnitude()
|
|
97
132
|
});
|
|
98
133
|
// RigidBody Events
|
|
99
|
-
rigidBody1Events?.
|
|
134
|
+
rigidBody1Events?.oncontact?.({
|
|
100
135
|
targetCollider: collider2,
|
|
101
136
|
targetRigidBody: rigidBody2,
|
|
102
137
|
maxForceDirection: e.maxForceDirection(),
|
|
@@ -104,7 +139,7 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
104
139
|
totalForce: e.totalForce(),
|
|
105
140
|
totalForceMagnitude: e.totalForceMagnitude()
|
|
106
141
|
});
|
|
107
|
-
rigidBody2Events?.
|
|
142
|
+
rigidBody2Events?.oncontact?.({
|
|
108
143
|
targetCollider: collider1,
|
|
109
144
|
targetRigidBody: rigidBody1,
|
|
110
145
|
maxForceDirection: e.maxForceDirection(),
|
|
@@ -121,7 +156,7 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
121
156
|
if (!collider1 || !collider2) {
|
|
122
157
|
return;
|
|
123
158
|
}
|
|
124
|
-
const { collider1Events, collider2Events, rigidBody1Events, rigidBody2Events } = getEventDispatchers(
|
|
159
|
+
const { collider1Events, collider2Events, rigidBody1Events, rigidBody2Events } = getEventDispatchers(collider1, collider2, colliderEventDispatchers, rigidBodyEventDispatchers);
|
|
125
160
|
if (!collider1Events && !collider2Events && !rigidBody1Events && !rigidBody2Events) {
|
|
126
161
|
return;
|
|
127
162
|
}
|
|
@@ -132,20 +167,20 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
132
167
|
const isIntersection = world.intersectionPair(collider1, collider2);
|
|
133
168
|
if (isIntersection) {
|
|
134
169
|
// Collider Events
|
|
135
|
-
collider1Events?.
|
|
170
|
+
collider1Events?.onsensorenter?.({
|
|
136
171
|
targetCollider: collider2,
|
|
137
172
|
targetRigidBody: rigidBody2
|
|
138
173
|
});
|
|
139
|
-
collider2Events?.
|
|
174
|
+
collider2Events?.onsensorenter?.({
|
|
140
175
|
targetCollider: collider1,
|
|
141
176
|
targetRigidBody: rigidBody1
|
|
142
177
|
});
|
|
143
178
|
// RigidBody Events
|
|
144
|
-
rigidBody1Events?.
|
|
179
|
+
rigidBody1Events?.onsensorenter?.({
|
|
145
180
|
targetCollider: collider2,
|
|
146
181
|
targetRigidBody: rigidBody2
|
|
147
182
|
});
|
|
148
|
-
rigidBody2Events?.
|
|
183
|
+
rigidBody2Events?.onsensorenter?.({
|
|
149
184
|
targetCollider: collider1,
|
|
150
185
|
targetRigidBody: rigidBody1
|
|
151
186
|
});
|
|
@@ -154,26 +189,26 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
154
189
|
}
|
|
155
190
|
world.contactPair(collider1, collider2, (manifold, flipped) => {
|
|
156
191
|
// Collider events
|
|
157
|
-
collider1Events?.
|
|
192
|
+
collider1Events?.oncollisionenter?.({
|
|
158
193
|
flipped,
|
|
159
194
|
manifold,
|
|
160
195
|
targetCollider: collider2,
|
|
161
196
|
targetRigidBody: rigidBody2
|
|
162
197
|
});
|
|
163
|
-
collider2Events?.
|
|
198
|
+
collider2Events?.oncollisionenter?.({
|
|
164
199
|
flipped,
|
|
165
200
|
manifold,
|
|
166
201
|
targetCollider: collider1,
|
|
167
202
|
targetRigidBody: rigidBody1
|
|
168
203
|
});
|
|
169
204
|
// RigidBody Events
|
|
170
|
-
rigidBody1Events?.
|
|
205
|
+
rigidBody1Events?.oncollisionenter?.({
|
|
171
206
|
flipped,
|
|
172
207
|
manifold,
|
|
173
208
|
targetCollider: collider2,
|
|
174
209
|
targetRigidBody: rigidBody2
|
|
175
210
|
});
|
|
176
|
-
rigidBody2Events?.
|
|
211
|
+
rigidBody2Events?.oncollisionenter?.({
|
|
177
212
|
flipped,
|
|
178
213
|
manifold,
|
|
179
214
|
targetCollider: collider1,
|
|
@@ -188,20 +223,20 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
188
223
|
collider1.isSensor() ||
|
|
189
224
|
collider2.isSensor();
|
|
190
225
|
if (isIntersection) {
|
|
191
|
-
collider1Events?.
|
|
226
|
+
collider1Events?.onsensorexit?.({
|
|
192
227
|
targetCollider: collider2,
|
|
193
228
|
targetRigidBody: rigidBody2
|
|
194
229
|
});
|
|
195
|
-
collider2Events?.
|
|
230
|
+
collider2Events?.onsensorexit?.({
|
|
196
231
|
targetCollider: collider1,
|
|
197
232
|
targetRigidBody: rigidBody1
|
|
198
233
|
});
|
|
199
234
|
// RigidBody Events
|
|
200
|
-
rigidBody1Events?.
|
|
235
|
+
rigidBody1Events?.onsensorexit?.({
|
|
201
236
|
targetCollider: collider2,
|
|
202
237
|
targetRigidBody: rigidBody2
|
|
203
238
|
});
|
|
204
|
-
rigidBody2Events?.
|
|
239
|
+
rigidBody2Events?.onsensorexit?.({
|
|
205
240
|
targetCollider: collider1,
|
|
206
241
|
targetRigidBody: rigidBody1
|
|
207
242
|
});
|
|
@@ -209,28 +244,60 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
209
244
|
return;
|
|
210
245
|
}
|
|
211
246
|
// Collider events
|
|
212
|
-
collider1Events?.
|
|
247
|
+
collider1Events?.oncollisionexit?.({
|
|
213
248
|
targetCollider: collider2,
|
|
214
249
|
targetRigidBody: rigidBody2
|
|
215
250
|
});
|
|
216
|
-
collider2Events?.
|
|
251
|
+
collider2Events?.oncollisionexit?.({
|
|
217
252
|
targetCollider: collider1,
|
|
218
253
|
targetRigidBody: rigidBody1
|
|
219
254
|
});
|
|
220
255
|
// RigidBody Events
|
|
221
|
-
rigidBody1Events?.
|
|
256
|
+
rigidBody1Events?.oncollisionexit?.({
|
|
222
257
|
targetCollider: collider2,
|
|
223
258
|
targetRigidBody: rigidBody2
|
|
224
259
|
});
|
|
225
|
-
rigidBody2Events?.
|
|
260
|
+
rigidBody2Events?.oncollisionexit?.({
|
|
226
261
|
targetCollider: collider1,
|
|
227
262
|
targetRigidBody: rigidBody1
|
|
228
263
|
});
|
|
229
264
|
}
|
|
230
265
|
});
|
|
231
|
-
}, {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
266
|
+
}, {
|
|
267
|
+
stage: simulationStage
|
|
268
|
+
});
|
|
269
|
+
const synchronization = useTask(synchronizationKey, () => {
|
|
270
|
+
rigidBodyObjects.forEach((mesh) => {
|
|
271
|
+
if (!objectHasPhysicsUserData(mesh))
|
|
272
|
+
return;
|
|
273
|
+
const userData = mesh.userData.physics;
|
|
274
|
+
if (framerate.current === 'varying') {
|
|
275
|
+
tempObject.position.copy(userData.currentPosition);
|
|
276
|
+
tempObject.quaternion.copy(userData.currentQuaternion);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
tempObject.position
|
|
280
|
+
.copy(userData.lastPosition)
|
|
281
|
+
.lerp(userData.currentPosition, simulationOffset.current);
|
|
282
|
+
tempObject.quaternion
|
|
283
|
+
.copy(userData.lastQuaternion)
|
|
284
|
+
.slerp(userData.currentQuaternion, simulationOffset.current);
|
|
285
|
+
}
|
|
286
|
+
// Rapier has no concept of scale, so we use the mesh's scale
|
|
287
|
+
mesh.getWorldScale(tempVector3);
|
|
288
|
+
tempObject.scale.copy(tempVector3);
|
|
289
|
+
tempObject.updateMatrix();
|
|
290
|
+
if (mesh.parent)
|
|
291
|
+
tempObject.applyMatrix4(mesh.parent.matrixWorld.clone().invert());
|
|
292
|
+
tempObject.updateMatrix();
|
|
293
|
+
mesh.position.setFromMatrixPosition(tempObject.matrix);
|
|
294
|
+
mesh.rotation.setFromRotationMatrix(tempObject.matrix);
|
|
295
|
+
});
|
|
296
|
+
}, {
|
|
297
|
+
stage: synchronizationStage
|
|
298
|
+
});
|
|
299
|
+
return {
|
|
300
|
+
simulationTask: simulation.task,
|
|
301
|
+
synchronizationTask: synchronization.task
|
|
302
|
+
};
|
|
236
303
|
};
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
/// <reference types="svelte" />
|
|
2
|
-
import type { Collider, RigidBody } from '@dimforge/rapier3d-compat';
|
|
3
1
|
import RAPIER from '@dimforge/rapier3d-compat';
|
|
4
|
-
import type
|
|
5
|
-
import type {
|
|
6
|
-
export declare const createRapierContext: (gravity: RAPIER.Vector, rawIntegrationParameters?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawIntegrationParameters | undefined, rawIslands?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawIslandManager | undefined, rawBroadPhase?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawBroadPhase | undefined, rawNarrowPhase?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawNarrowPhase | undefined, rawBodies?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawRigidBodySet | undefined, rawColliders?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawColliderSet | undefined, rawImpulseJoints?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawImpulseJointSet | undefined, rawMultibodyJoints?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawMultibodyJointSet | undefined, rawCCDSolver?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawCCDSolver | undefined, rawQueryPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawQueryPipeline | undefined, rawPhysicsPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawPhysicsPipeline | undefined, rawSerializationPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawSerializationPipeline | undefined, rawDebugRenderPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawDebugRenderPipeline | undefined
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
pause: () => void;
|
|
19
|
-
resume: () => void;
|
|
20
|
-
paused: import("svelte/store").Readable<boolean>;
|
|
21
|
-
};
|
|
2
|
+
import { type Key, type Stage } from '@threlte/core';
|
|
3
|
+
import type { Framerate, RapierContext } from '../types/types';
|
|
4
|
+
export declare const createRapierContext: (worldArgs: [gravity: RAPIER.Vector, rawIntegrationParameters?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawIntegrationParameters | undefined, rawIslands?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawIslandManager | undefined, rawBroadPhase?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawBroadPhase | undefined, rawNarrowPhase?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawNarrowPhase | undefined, rawBodies?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawRigidBodySet | undefined, rawColliders?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawColliderSet | undefined, rawImpulseJoints?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawImpulseJointSet | undefined, rawMultibodyJoints?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawMultibodyJointSet | undefined, rawCCDSolver?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawCCDSolver | undefined, rawQueryPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawQueryPipeline | undefined, rawPhysicsPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawPhysicsPipeline | undefined, rawSerializationPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawSerializationPipeline | undefined, rawDebugRenderPipeline?: import("@dimforge/rapier3d-compat/rapier_wasm3d").RawDebugRenderPipeline | undefined], options: {
|
|
5
|
+
framerate?: Framerate;
|
|
6
|
+
autoStart?: boolean;
|
|
7
|
+
simulationStageOptions?: {
|
|
8
|
+
before?: (Key | Stage) | (Key | Stage)[];
|
|
9
|
+
after?: (Key | Stage) | (Key | Stage)[];
|
|
10
|
+
};
|
|
11
|
+
synchronizationStageOptions?: {
|
|
12
|
+
before?: (Key | Stage) | (Key | Stage)[];
|
|
13
|
+
after?: (Key | Stage) | (Key | Stage)[];
|
|
14
|
+
};
|
|
15
|
+
}) => RapierContext;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import RAPIER from '@dimforge/rapier3d-compat';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { currentWritable } from '@threlte/core';
|
|
3
|
+
import { derived, writable } from 'svelte/store';
|
|
4
|
+
import { createPhysicsStages } from './createPhysicsStages';
|
|
5
|
+
import { createPhysicsTasks } from './createPhysicsTasks';
|
|
6
|
+
export const createRapierContext = (worldArgs, options) => {
|
|
7
|
+
const world = new RAPIER.World(...worldArgs);
|
|
5
8
|
const colliderObjects = new Map();
|
|
6
9
|
const rigidBodyObjects = new Map();
|
|
7
10
|
const rigidBodyEventDispatchers = new Map();
|
|
@@ -12,9 +15,9 @@ export const createRapierContext = (...args) => {
|
|
|
12
15
|
* @param object
|
|
13
16
|
* @param eventDispatcher
|
|
14
17
|
*/
|
|
15
|
-
const addColliderToContext = (collider, object,
|
|
18
|
+
const addColliderToContext = (collider, object, props) => {
|
|
16
19
|
colliderObjects.set(collider.handle, object);
|
|
17
|
-
colliderEventDispatchers.set(collider.handle,
|
|
20
|
+
colliderEventDispatchers.set(collider.handle, props);
|
|
18
21
|
};
|
|
19
22
|
/**
|
|
20
23
|
* Removes the collider from the context
|
|
@@ -42,11 +45,17 @@ export const createRapierContext = (...args) => {
|
|
|
42
45
|
rigidBodyObjects.delete(rigidBody.handle);
|
|
43
46
|
rigidBodyEventDispatchers.delete(rigidBody.handle);
|
|
44
47
|
};
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
const
|
|
48
|
+
const framerate = currentWritable(options.framerate ?? 'varying');
|
|
49
|
+
const simulationOffset = currentWritable(1);
|
|
50
|
+
const updateRigidBodySimulationData = currentWritable(framerate.current === 'varying');
|
|
51
|
+
const { simulationStage, synchronizationStage } = createPhysicsStages(framerate, simulationOffset, updateRigidBodySimulationData, options);
|
|
52
|
+
const autostart = options.autoStart ?? true;
|
|
53
|
+
const paused = writable(!autostart);
|
|
54
|
+
if (!autostart) {
|
|
55
|
+
simulationStage.stop();
|
|
56
|
+
synchronizationStage.stop();
|
|
57
|
+
}
|
|
58
|
+
const { simulationTask, synchronizationTask } = createPhysicsTasks(world, framerate, simulationOffset, rigidBodyObjects, updateRigidBodySimulationData, colliderEventDispatchers, rigidBodyEventDispatchers, simulationStage, synchronizationStage);
|
|
50
59
|
return {
|
|
51
60
|
rapier: RAPIER,
|
|
52
61
|
world,
|
|
@@ -59,8 +68,23 @@ export const createRapierContext = (...args) => {
|
|
|
59
68
|
addRigidBodyToContext,
|
|
60
69
|
removeRigidBodyFromContext,
|
|
61
70
|
debug: writable(false),
|
|
62
|
-
pause
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
pause: () => {
|
|
72
|
+
paused.set(true);
|
|
73
|
+
simulationStage.stop();
|
|
74
|
+
synchronizationStage.stop();
|
|
75
|
+
},
|
|
76
|
+
resume: () => {
|
|
77
|
+
paused.set(false);
|
|
78
|
+
simulationStage.start();
|
|
79
|
+
synchronizationStage.start();
|
|
80
|
+
},
|
|
81
|
+
paused: derived(paused, (a) => a),
|
|
82
|
+
framerate,
|
|
83
|
+
simulationOffset,
|
|
84
|
+
simulationStage,
|
|
85
|
+
synchronizationStage,
|
|
86
|
+
updateRigidBodySimulationData,
|
|
87
|
+
simulationTask,
|
|
88
|
+
synchronizationTask
|
|
65
89
|
};
|
|
66
90
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const initRapier: () => true | Promise<void>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
2
|
+
let initialized = false;
|
|
3
|
+
let promise;
|
|
4
|
+
export const initRapier = () => {
|
|
5
|
+
if (initialized)
|
|
6
|
+
return true;
|
|
7
|
+
if (!promise) {
|
|
8
|
+
promise = new Promise((resolve) => {
|
|
9
|
+
RAPIER.init().then(() => {
|
|
10
|
+
initialized = true;
|
|
11
|
+
resolve();
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return promise;
|
|
16
|
+
};
|
package/dist/lib/keys.js
ADDED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const
|
|
1
|
+
import type { Object3D } from 'three';
|
|
2
|
+
export declare const useParentRigidbodyObject: () => Object3D | undefined;
|
|
3
|
+
export declare const setParentRigidbodyObject: (object3d: Object3D) => void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ColliderEvents } from '../types/types';
|
|
2
|
+
export declare const useCreateEvent: <T>(oncreate?: ColliderEvents['oncreate']) => {
|
|
2
3
|
updateRef: (newRef: T) => void;
|
|
3
4
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { onDestroy } from 'svelte';
|
|
2
|
-
export const useCreateEvent = (
|
|
2
|
+
export const useCreateEvent = (oncreate) => {
|
|
3
3
|
const cleanupFunctions = [];
|
|
4
|
-
let ref
|
|
4
|
+
let ref;
|
|
5
5
|
const dispatchCreateEvent = () => {
|
|
6
6
|
// call every cleanup function
|
|
7
7
|
cleanupFunctions.forEach((cleanup) => cleanup());
|
|
@@ -13,7 +13,7 @@ export const useCreateEvent = (events) => {
|
|
|
13
13
|
};
|
|
14
14
|
if (ref === undefined)
|
|
15
15
|
return;
|
|
16
|
-
|
|
16
|
+
oncreate?.({ ref, cleanup });
|
|
17
17
|
};
|
|
18
18
|
const updateRef = (newRef) => {
|
|
19
19
|
ref = newRef;
|