@threlte/rapier 3.0.0-next.2 → 3.0.0-next.20
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.d.ts +3 -34
- package/dist/components/Attractor/types.d.ts +30 -0
- package/dist/components/Attractor/types.js +1 -0
- package/dist/components/Colliders/{AutoColliders.svelte → AutoColliders/AutoColliders.svelte} +27 -14
- package/dist/components/Colliders/AutoColliders/AutoColliders.svelte.d.ts +22 -0
- package/dist/components/Colliders/AutoColliders/types.d.ts +74 -0
- package/dist/components/Colliders/AutoColliders/types.js +1 -0
- package/dist/components/Colliders/{Collider.svelte → Collider/Collider.svelte} +30 -20
- package/dist/components/Colliders/Collider/Collider.svelte.d.ts +20 -0
- package/dist/components/Colliders/Collider/types.d.ts +83 -0
- package/dist/components/Colliders/Collider/types.js +1 -0
- package/dist/components/CollisionGroups/CollisionGroups.svelte +4 -1
- package/dist/components/CollisionGroups/CollisionGroups.svelte.d.ts +16 -33
- package/dist/components/CollisionGroups/types.d.ts +19 -0
- package/dist/components/CollisionGroups/types.js +1 -0
- package/dist/components/Debug/Debug.svelte +5 -5
- package/dist/components/Debug/Debug.svelte.d.ts +3 -7
- package/dist/components/Debug/types.d.ts +3 -0
- package/dist/components/Debug/types.js +1 -0
- package/dist/components/RigidBody/RigidBody.svelte +17 -6
- package/dist/components/RigidBody/RigidBody.svelte.d.ts +3 -102
- package/dist/components/RigidBody/overrideTeleportMethods.d.ts +14 -0
- package/dist/components/RigidBody/overrideTeleportMethods.js +31 -0
- package/dist/components/RigidBody/types.d.ts +85 -0
- package/dist/components/RigidBody/types.js +1 -0
- package/dist/components/World/InnerWorld.svelte +27 -5
- package/dist/components/World/InnerWorld.svelte.d.ts +3 -21
- package/dist/components/World/World.svelte +9 -57
- package/dist/components/World/World.svelte.d.ts +3 -38
- package/dist/components/World/types.d.ts +32 -0
- package/dist/components/World/types.js +1 -0
- package/dist/hooks/useFixedJoint.d.ts +2 -3
- package/dist/hooks/useJoint.d.ts +0 -1
- package/dist/hooks/usePhysicsTask.d.ts +16 -0
- package/dist/hooks/usePhysicsTask.js +32 -0
- package/dist/hooks/usePrismaticJoint.d.ts +1 -2
- package/dist/hooks/useRevoluteJoint.d.ts +1 -2
- package/dist/hooks/useRopeJoint.d.ts +10 -0
- package/dist/hooks/useRopeJoint.js +14 -0
- package/dist/hooks/useSphericalJoint.d.ts +1 -2
- package/dist/hooks/utils.js +3 -2
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -4
- package/dist/lib/applyColliderActiveEvents.d.ts +1 -1
- package/dist/lib/applyTransforms.d.ts +1 -1
- package/dist/lib/createCollidersFromChildren.d.ts +1 -1
- package/dist/lib/createCollidersFromChildren.js +18 -3
- 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} +109 -40
- package/dist/lib/createRapierContext.d.ts +14 -20
- package/dist/lib/createRapierContext.js +35 -11
- package/dist/lib/eulerToQuaternion.d.ts +2 -2
- 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/useCreateEvent.d.ts +2 -2
- package/dist/lib/useCreateEvent.js +3 -5
- package/dist/types/types.d.ts +36 -9
- package/package.json +33 -14
- package/dist/components/Colliders/AutoColliders.svelte.d.ts +0 -84
- package/dist/components/Colliders/Collider.svelte.d.ts +0 -109
- 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/recipes/BasicPlayerController.svelte +0 -142
- package/dist/recipes/BasicPlayerController.svelte.d.ts +0 -31
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { ColliderEvents, RigidBodyEvents } from '../types/types';
|
|
2
1
|
import { type Collider } from '@dimforge/rapier3d-compat';
|
|
2
|
+
import type { ColliderEvents, RigidBodyEvents } from '../types/types';
|
|
3
3
|
export declare const applyColliderActiveEvents: (collider: Collider, colliderEvents?: ColliderEvents, rigidBodyEvents?: RigidBodyEvents) => void;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { Euler, Object3D, Vector3 } from 'three';
|
|
2
|
-
export declare const applyTransforms: (object: Object3D, position?: Parameters<Vector3[
|
|
2
|
+
export declare const applyTransforms: (object: Object3D, position?: Parameters<Vector3["set"]>, rotation?: Parameters<Euler["set"]>, scale?: Parameters<Vector3["set"]>) => void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ActiveEvents, ColliderDesc } from '@dimforge/rapier3d-compat';
|
|
2
|
+
import { isInstanceOf } from '@threlte/core';
|
|
2
3
|
import { Quaternion, Vector3 } from 'three';
|
|
3
4
|
const offset = new Vector3();
|
|
4
5
|
const worldPosition = new Vector3();
|
|
@@ -33,7 +34,7 @@ export const createCollidersFromChildren = (object, collidersType, world, rigidB
|
|
|
33
34
|
rigidBodyParentObject?.getWorldPosition(rigidBodyWorldPos);
|
|
34
35
|
rigidBodyParentObject?.getWorldQuaternion(rigidBodyWorldQuatInversed).invert();
|
|
35
36
|
object.traverse((child) => {
|
|
36
|
-
if ('
|
|
37
|
+
if (isInstanceOf(child, 'Mesh')) {
|
|
37
38
|
const { geometry } = child;
|
|
38
39
|
const worldPos = child.getWorldPosition(worldPosition);
|
|
39
40
|
const translation = worldPos.sub(rigidBodyWorldPos);
|
|
@@ -62,7 +63,14 @@ export const createCollidersFromChildren = (object, collidersType, world, rigidB
|
|
|
62
63
|
break;
|
|
63
64
|
case 'trimesh':
|
|
64
65
|
{
|
|
65
|
-
|
|
66
|
+
const scaleX = scale.x;
|
|
67
|
+
const vertices = new Float32Array(geometry.attributes.position.array);
|
|
68
|
+
if (scaleX !== 1) {
|
|
69
|
+
for (let i = 0; i < vertices.length; i++) {
|
|
70
|
+
vertices[i] *= scaleX;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
description = ColliderDesc.trimesh(vertices, new Uint32Array(geometry.index?.array ?? []));
|
|
66
74
|
}
|
|
67
75
|
break;
|
|
68
76
|
case 'capsule':
|
|
@@ -77,7 +85,14 @@ export const createCollidersFromChildren = (object, collidersType, world, rigidB
|
|
|
77
85
|
break;
|
|
78
86
|
case 'convexHull':
|
|
79
87
|
{
|
|
80
|
-
|
|
88
|
+
const scaleX = scale.x;
|
|
89
|
+
const vertices = new Float32Array(geometry.attributes.position.array);
|
|
90
|
+
if (scaleX !== 1) {
|
|
91
|
+
for (let i = 0; i < vertices.length; i++) {
|
|
92
|
+
vertices[i] *= scaleX;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
description = ColliderDesc.convexHull(vertices);
|
|
81
96
|
}
|
|
82
97
|
break;
|
|
83
98
|
}
|
|
@@ -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,21 +19,48 @@ 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
61
|
if (!rigidBody || !rigidBody.isValid())
|
|
39
62
|
return;
|
|
40
|
-
const events =
|
|
63
|
+
const events = rigidBodyEventDispatchers.get(handle);
|
|
41
64
|
if (events) {
|
|
42
65
|
if (rigidBody.isSleeping() && !mesh.userData.isSleeping) {
|
|
43
66
|
events.onsleep?.();
|
|
@@ -50,21 +73,35 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
50
73
|
if (rigidBody.isSleeping() || rigidBody.isFixed() || !mesh.parent) {
|
|
51
74
|
return;
|
|
52
75
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
+
}
|
|
68
105
|
});
|
|
69
106
|
eventQueue.drainContactForceEvents((e) => {
|
|
70
107
|
const collider1 = world.getCollider(e.collider1());
|
|
@@ -73,7 +110,7 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
73
110
|
if (!collider1 || !collider2) {
|
|
74
111
|
return;
|
|
75
112
|
}
|
|
76
|
-
const { collider1Events, collider2Events, rigidBody1Events, rigidBody2Events } = getEventDispatchers(
|
|
113
|
+
const { collider1Events, collider2Events, rigidBody1Events, rigidBody2Events } = getEventDispatchers(collider1, collider2, colliderEventDispatchers, rigidBodyEventDispatchers);
|
|
77
114
|
const rigidBody1 = collider1.parent();
|
|
78
115
|
const rigidBody2 = collider2.parent();
|
|
79
116
|
// Collider events
|
|
@@ -119,7 +156,7 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
119
156
|
if (!collider1 || !collider2) {
|
|
120
157
|
return;
|
|
121
158
|
}
|
|
122
|
-
const { collider1Events, collider2Events, rigidBody1Events, rigidBody2Events } = getEventDispatchers(
|
|
159
|
+
const { collider1Events, collider2Events, rigidBody1Events, rigidBody2Events } = getEventDispatchers(collider1, collider2, colliderEventDispatchers, rigidBodyEventDispatchers);
|
|
123
160
|
if (!collider1Events && !collider2Events && !rigidBody1Events && !rigidBody2Events) {
|
|
124
161
|
return;
|
|
125
162
|
}
|
|
@@ -226,9 +263,41 @@ export const useFrameHandler = (ctx, stage) => {
|
|
|
226
263
|
});
|
|
227
264
|
}
|
|
228
265
|
});
|
|
229
|
-
}, {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
+
};
|
|
234
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: (
|
|
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: ConstructorParameters<typeof RAPIER.World>, 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();
|
|
@@ -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
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Quaternion } from 'three';
|
|
1
|
+
import { Euler, Quaternion } from 'three';
|
|
2
2
|
/**
|
|
3
3
|
* Sets the values of a temporary Euler and returns the quaternion from that
|
|
4
4
|
* @param values
|
|
5
5
|
* @returns
|
|
6
6
|
*/
|
|
7
|
-
export declare const eulerToQuaternion: (values: [
|
|
7
|
+
export declare const eulerToQuaternion: (values: Parameters<Euler["set"]>) => Quaternion;
|
|
@@ -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,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare const useCreateEvent: <T>(oncreate?:
|
|
1
|
+
import type { CreateEvent } from '../types/types';
|
|
2
|
+
export declare const useCreateEvent: <T>(oncreate?: CreateEvent<T>["oncreate"]) => {
|
|
3
3
|
updateRef: (newRef: T) => void;
|
|
4
4
|
};
|
|
@@ -7,13 +7,11 @@ export const useCreateEvent = (oncreate) => {
|
|
|
7
7
|
cleanupFunctions.forEach((cleanup) => cleanup());
|
|
8
8
|
// clear the cleanup functions array
|
|
9
9
|
cleanupFunctions.length = 0;
|
|
10
|
-
const cleanup = (callback) => {
|
|
11
|
-
// add cleanup function to array
|
|
12
|
-
cleanupFunctions.push(callback);
|
|
13
|
-
};
|
|
14
10
|
if (ref === undefined)
|
|
15
11
|
return;
|
|
16
|
-
oncreate?.(
|
|
12
|
+
const cleanup = oncreate?.(ref);
|
|
13
|
+
if (cleanup)
|
|
14
|
+
cleanupFunctions.push(cleanup);
|
|
17
15
|
};
|
|
18
16
|
const updateRef = (newRef) => {
|
|
19
17
|
ref = newRef;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
1
|
+
import { World, type Collider, type RigidBody, type TempContactManifold, type Vector } from '@dimforge/rapier3d-compat';
|
|
2
|
+
import RAPIER from '@dimforge/rapier3d-compat';
|
|
3
|
+
import type { CurrentWritable, Stage, Task } from '@threlte/core';
|
|
4
|
+
import type { Readable, Writable } from 'svelte/store';
|
|
5
|
+
import type { Object3D } from 'three';
|
|
5
6
|
export type ColliderShapes = 'ball' | 'capsule' | 'segment' | 'triangle' | 'roundTriangle' | 'polyline' | 'trimesh' | 'cuboid' | 'roundCuboid' | 'heightfield' | 'cylinder' | 'roundCylinder' | 'cone' | 'roundCone' | 'convexHull' | 'convexMesh' | 'roundConvexHull' | 'roundConvexMesh';
|
|
6
7
|
export type AutoCollidersShapes = 'cuboid' | 'ball' | 'trimesh' | 'convexHull' | 'capsule';
|
|
8
|
+
export type CreateEvent<T> = {
|
|
9
|
+
oncreate?: (ref: T) => void | (() => void);
|
|
10
|
+
};
|
|
7
11
|
export type ColliderEvents = {
|
|
8
|
-
oncreate?: (event: {
|
|
9
|
-
ref: Collider;
|
|
10
|
-
cleanup: (callback: () => void) => void;
|
|
11
|
-
}) => void;
|
|
12
12
|
oncollisionenter?: (event: {
|
|
13
13
|
targetCollider: Collider;
|
|
14
14
|
targetRigidBody: RigidBody | null;
|
|
@@ -45,7 +45,6 @@ export type RigidBodyEvents = ColliderEvents & {
|
|
|
45
45
|
onsleep?: () => void;
|
|
46
46
|
onwake?: () => void;
|
|
47
47
|
};
|
|
48
|
-
export type RapierContext = ReturnType<typeof createRapierContext>;
|
|
49
48
|
export type CollisionGroupsContext = Writable<number> | undefined;
|
|
50
49
|
export type RigidBodyUserData = {
|
|
51
50
|
events?: RigidBodyEvents;
|
|
@@ -59,3 +58,31 @@ export type CollisionGroupsBitMask = (0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
|
|
|
59
58
|
* Used in the <Attractor> component
|
|
60
59
|
*/
|
|
61
60
|
export type GravityType = 'static' | 'linear' | 'newtonian';
|
|
61
|
+
export type Framerate = number | 'varying';
|
|
62
|
+
export type RapierContext = {
|
|
63
|
+
rapier: typeof RAPIER;
|
|
64
|
+
world: World;
|
|
65
|
+
colliderObjects: Map<number, Object3D>;
|
|
66
|
+
rigidBodyObjects: Map<number, Object3D>;
|
|
67
|
+
rigidBodyEventDispatchers: Map<number, RigidBodyEvents>;
|
|
68
|
+
colliderEventDispatchers: Map<number, ColliderEvents>;
|
|
69
|
+
addColliderToContext: (collider: Collider, object: Object3D, props: ColliderEvents) => void;
|
|
70
|
+
removeColliderFromContext: (collider: Collider) => void;
|
|
71
|
+
addRigidBodyToContext: (rigidBody: RigidBody, object: Object3D, events: RigidBodyEvents) => void;
|
|
72
|
+
removeRigidBodyFromContext: (rigidBody: RigidBody) => void;
|
|
73
|
+
debug: Writable<boolean>;
|
|
74
|
+
pause: () => void;
|
|
75
|
+
resume: () => void;
|
|
76
|
+
paused: Readable<boolean>;
|
|
77
|
+
framerate: CurrentWritable<Framerate>;
|
|
78
|
+
simulationStage: Stage;
|
|
79
|
+
simulationTask: Task;
|
|
80
|
+
synchronizationStage: Stage;
|
|
81
|
+
synchronizationTask: Task;
|
|
82
|
+
/**
|
|
83
|
+
* This number tells us how far we're off in the simulation stage as opposed
|
|
84
|
+
* to the render stage
|
|
85
|
+
*/
|
|
86
|
+
simulationOffset: CurrentWritable<number>;
|
|
87
|
+
updateRigidBodySimulationData: CurrentWritable<boolean>;
|
|
88
|
+
};
|