@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,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">import { T, useTask } from '@threlte/core';
|
|
2
2
|
import { Group, Vector3 } from 'three';
|
|
3
3
|
import { useRapier } from '../../hooks/useRapier';
|
|
4
|
-
let { strength = 1, range = 50, gravityType = 'static', gravitationalConstant = 6.673e-11, ref = $bindable(), ...props } = $props();
|
|
4
|
+
let { strength = 1, range = 50, gravityType = 'static', gravitationalConstant = 6.673e-11, ref = $bindable(), children, ...props } = $props();
|
|
5
5
|
const { world, debug } = useRapier();
|
|
6
6
|
const gravitySource = new Vector3();
|
|
7
7
|
const group = new Group();
|
|
@@ -37,7 +37,7 @@ useTask(() => {
|
|
|
37
37
|
bind:ref
|
|
38
38
|
{...props}
|
|
39
39
|
>
|
|
40
|
-
|
|
40
|
+
{@render children?.({ ref: group })}
|
|
41
41
|
|
|
42
42
|
{#if $debug}
|
|
43
43
|
<T.Mesh>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Props
|
|
1
|
+
import { Props } from '@threlte/core'
|
|
2
2
|
import { SvelteComponent } from 'svelte'
|
|
3
3
|
import type { Group } from 'three'
|
|
4
4
|
import type { GravityType } from '../../types/types'
|
|
@@ -31,12 +31,4 @@ type AttractorProps = Props<Group> & {
|
|
|
31
31
|
gravitationalConstant?: number
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
type AttractorSlots = Slots<Group>
|
|
37
|
-
|
|
38
|
-
export default class Attractor extends SvelteComponent<
|
|
39
|
-
AttractorProps,
|
|
40
|
-
AttractorEvents,
|
|
41
|
-
AttractorSlots
|
|
42
|
-
> {}
|
|
34
|
+
export default class Attractor extends SvelteComponent<AttractorProps> {}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
<script lang="ts">import { ActiveCollisionTypes, CoefficientCombineRule } from '@dimforge/rapier3d-compat';
|
|
2
|
-
import {
|
|
2
|
+
import { createParentObject3DContext, useParentObject3D, watch } from '@threlte/core';
|
|
3
3
|
import { onDestroy, onMount } from 'svelte';
|
|
4
4
|
import { Group } from 'three';
|
|
5
5
|
import { useCollisionGroups } from '../../hooks/useCollisionGroups';
|
|
6
6
|
import { useRapier } from '../../hooks/useRapier';
|
|
7
7
|
import { useRigidBody } from '../../hooks/useRigidBody';
|
|
8
|
-
import { useCreateEvent } from '../../lib/useCreateEvent';
|
|
9
|
-
import { useParentRigidbodyObject } from '../../lib/rigidBodyObjectContext';
|
|
10
8
|
import { applyColliderActiveEvents } from '../../lib/applyColliderActiveEvents';
|
|
11
9
|
import { createCollidersFromChildren } from '../../lib/createCollidersFromChildren';
|
|
12
10
|
import { eulerToQuaternion } from '../../lib/eulerToQuaternion';
|
|
13
|
-
|
|
11
|
+
import { useParentRigidbodyObject } from '../../lib/rigidBodyObjectContext';
|
|
12
|
+
import { useCreateEvent } from '../../lib/useCreateEvent';
|
|
13
|
+
let { shape = 'convexHull', restitution, restitutionCombineRule, friction, frictionCombineRule, sensor, contactForceEventThreshold, density, mass, centerOfMass, principalAngularInertia, angularInertiaLocalFrame, refresh = $bindable(() => create()), colliders = $bindable(), oncreate, oncollisionenter, oncollisionexit, oncontact, onsensorenter, onsensorexit, children } = $props();
|
|
14
14
|
const group = new Group();
|
|
15
|
-
const { updateRef } = useCreateEvent(
|
|
15
|
+
const { updateRef } = useCreateEvent(oncreate);
|
|
16
16
|
const rigidBody = useRigidBody();
|
|
17
17
|
const rigidBodyParentObject = useParentRigidbodyObject();
|
|
18
18
|
const { world, addColliderToContext, removeColliderFromContext } = useRapier();
|
|
@@ -27,13 +27,20 @@ const cleanup = () => {
|
|
|
27
27
|
});
|
|
28
28
|
colliders.length = 0;
|
|
29
29
|
};
|
|
30
|
+
const events = {
|
|
31
|
+
oncollisionenter,
|
|
32
|
+
oncollisionexit,
|
|
33
|
+
oncontact,
|
|
34
|
+
onsensorenter,
|
|
35
|
+
onsensorexit
|
|
36
|
+
};
|
|
30
37
|
const create = () => {
|
|
31
38
|
cleanup();
|
|
32
39
|
colliders = createCollidersFromChildren(group, shape ?? 'convexHull', world, rigidBody, rigidBodyParentObject);
|
|
33
|
-
colliders.forEach((c) => addColliderToContext(c, group,
|
|
40
|
+
colliders.forEach((c) => addColliderToContext(c, group, events));
|
|
34
41
|
collisionGroups.registerColliders(colliders);
|
|
35
42
|
colliders.forEach((collider) => {
|
|
36
|
-
applyColliderActiveEvents(collider,
|
|
43
|
+
applyColliderActiveEvents(collider, events, rigidBody?.userData?.events);
|
|
37
44
|
collider.setActiveCollisionTypes(ActiveCollisionTypes.ALL);
|
|
38
45
|
collider.setRestitution(restitution ?? 0);
|
|
39
46
|
collider.setRestitutionCombineRule(restitutionCombineRule ?? CoefficientCombineRule.Average);
|
|
@@ -63,11 +70,14 @@ onMount(() => {
|
|
|
63
70
|
* Cleanup
|
|
64
71
|
*/
|
|
65
72
|
onDestroy(cleanup);
|
|
73
|
+
const parent3DObject = useParentObject3D();
|
|
74
|
+
createParentObject3DContext(group);
|
|
75
|
+
watch(parent3DObject, (parent) => {
|
|
76
|
+
parent?.add(group);
|
|
77
|
+
return () => {
|
|
78
|
+
parent?.remove(group);
|
|
79
|
+
};
|
|
80
|
+
});
|
|
66
81
|
</script>
|
|
67
82
|
|
|
68
|
-
|
|
69
|
-
<slot
|
|
70
|
-
{colliders}
|
|
71
|
-
{refresh}
|
|
72
|
-
/>
|
|
73
|
-
</SceneGraphObject>
|
|
83
|
+
{@render children?.({ colliders: colliders ?? [], refresh })}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CoefficientCombineRule, Collider } from '@dimforge/rapier3d-compat'
|
|
2
|
-
import { SvelteComponent } from 'svelte'
|
|
2
|
+
import { SvelteComponent, type Snippet } from 'svelte'
|
|
3
3
|
import type { Euler, Vector3 } from 'three'
|
|
4
|
-
import type { AutoCollidersShapes,
|
|
4
|
+
import type { AutoCollidersShapes, ColliderEvents } from '../../types/types'
|
|
5
5
|
|
|
6
6
|
// ------------------ BASE ------------------
|
|
7
7
|
|
|
@@ -14,7 +14,10 @@ type BaseProps = {
|
|
|
14
14
|
sensor?: boolean
|
|
15
15
|
colliders?: Collider[]
|
|
16
16
|
contactForceEventThreshold?: number
|
|
17
|
+
|
|
17
18
|
refresh?: () => void
|
|
19
|
+
|
|
20
|
+
oncreate?: () => void
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
// ------------------ MASS ------------------
|
|
@@ -64,17 +67,18 @@ type MassProps<TMassDef extends MassDef> = TMassDef extends Density
|
|
|
64
67
|
|
|
65
68
|
// ------------------ COLLIDER ------------------
|
|
66
69
|
|
|
67
|
-
export type AutoCollidersProps<TMassDef extends MassDef> = BaseProps &
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
export type AutoCollidersProps<TMassDef extends MassDef> = BaseProps &
|
|
71
|
+
MassProps<TMassDef> & {
|
|
72
|
+
children?: Snippet<
|
|
73
|
+
[
|
|
74
|
+
{
|
|
75
|
+
colliders: Collider[]
|
|
76
|
+
refresh: () => void
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
>
|
|
73
80
|
}
|
|
74
|
-
}
|
|
75
81
|
|
|
76
82
|
export default class AutoColliders<TMassDef extends MassDef> extends SvelteComponent<
|
|
77
|
-
AutoCollidersProps<TMassDef
|
|
78
|
-
ColliderEventMap,
|
|
79
|
-
AutoCollidersSlots
|
|
83
|
+
AutoCollidersProps<TMassDef>
|
|
80
84
|
> {}
|
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
<script lang="ts">import { ActiveCollisionTypes, CoefficientCombineRule, Collider, ColliderDesc } from '@dimforge/rapier3d-compat';
|
|
2
|
-
import {
|
|
2
|
+
import { createParentObject3DContext, useParentObject3D, useTask, watch } from '@threlte/core';
|
|
3
3
|
import { onDestroy, onMount, tick } from 'svelte';
|
|
4
4
|
import { Object3D, Quaternion, Vector3 } from 'three';
|
|
5
5
|
import { useCollisionGroups } from '../../hooks/useCollisionGroups';
|
|
6
6
|
import { useRapier } from '../../hooks/useRapier';
|
|
7
7
|
import { useRigidBody } from '../../hooks/useRigidBody';
|
|
8
|
-
import { useParentRigidbodyObject } from '../../lib/rigidBodyObjectContext';
|
|
9
|
-
import { useCreateEvent } from '../../lib/useCreateEvent';
|
|
10
8
|
import { applyColliderActiveEvents } from '../../lib/applyColliderActiveEvents';
|
|
11
9
|
import { eulerToQuaternion } from '../../lib/eulerToQuaternion';
|
|
12
10
|
import { getWorldPosition, getWorldQuaternion } from '../../lib/getWorldTransforms';
|
|
11
|
+
import { useParentRigidbodyObject } from '../../lib/rigidBodyObjectContext';
|
|
13
12
|
import { scaleColliderArgs } from '../../lib/scaleColliderArgs';
|
|
13
|
+
import { useCreateEvent } from '../../lib/useCreateEvent';
|
|
14
14
|
let { shape, args, type, restitution, restitutionCombineRule, friction, frictionCombineRule, sensor, contactForceEventThreshold, density, mass, centerOfMass, principalAngularInertia, angularInertiaLocalFrame, collider = $bindable(), refresh = $bindable(() => {
|
|
15
15
|
if (!collider)
|
|
16
16
|
return;
|
|
17
17
|
collider.setTranslation(getWorldPosition(object));
|
|
18
18
|
collider.setRotation(getWorldQuaternion(object));
|
|
19
|
-
}),
|
|
19
|
+
}), oncreate, oncollisionenter, oncollisionexit, oncontact, onsensorenter, onsensorexit, children } = $props();
|
|
20
20
|
const object = new Object3D();
|
|
21
|
-
const { updateRef } = useCreateEvent(
|
|
21
|
+
const { updateRef } = useCreateEvent(oncreate);
|
|
22
22
|
const rigidBody = useRigidBody();
|
|
23
23
|
const parentRigidBodyObject = useParentRigidbodyObject();
|
|
24
24
|
const hasRigidBodyParent = !!rigidBody;
|
|
25
25
|
const rapierContext = useRapier();
|
|
26
26
|
const { world } = rapierContext;
|
|
27
27
|
const collisionGroups = useCollisionGroups();
|
|
28
|
+
const events = {
|
|
29
|
+
oncollisionenter,
|
|
30
|
+
oncollisionexit,
|
|
31
|
+
oncontact,
|
|
32
|
+
onsensorenter,
|
|
33
|
+
onsensorexit
|
|
34
|
+
};
|
|
28
35
|
/**
|
|
29
36
|
* Actual collider setup happens onMount as only then
|
|
30
37
|
* the transforms are finished.
|
|
@@ -41,7 +48,7 @@ onMount(async () => {
|
|
|
41
48
|
/**
|
|
42
49
|
* Add collider to context
|
|
43
50
|
*/
|
|
44
|
-
rapierContext.addColliderToContext(collider, object,
|
|
51
|
+
rapierContext.addColliderToContext(collider, object, events);
|
|
45
52
|
/**
|
|
46
53
|
* For use in conjunction with component <CollisionGroups>
|
|
47
54
|
*/
|
|
@@ -98,7 +105,7 @@ $effect.pre(() => {
|
|
|
98
105
|
});
|
|
99
106
|
$effect.pre(() => {
|
|
100
107
|
if (collider) {
|
|
101
|
-
applyColliderActiveEvents(collider,
|
|
108
|
+
applyColliderActiveEvents(collider, events, rigidBody?.userData?.events);
|
|
102
109
|
}
|
|
103
110
|
});
|
|
104
111
|
/**
|
|
@@ -127,8 +134,14 @@ onDestroy(() => {
|
|
|
127
134
|
world.removeCollider(collider, true);
|
|
128
135
|
collider = undefined;
|
|
129
136
|
});
|
|
137
|
+
const parent3DObject = useParentObject3D();
|
|
138
|
+
createParentObject3DContext(object);
|
|
139
|
+
watch(parent3DObject, (parent) => {
|
|
140
|
+
parent?.add(object);
|
|
141
|
+
return () => {
|
|
142
|
+
parent?.remove(object);
|
|
143
|
+
};
|
|
144
|
+
});
|
|
130
145
|
</script>
|
|
131
146
|
|
|
132
|
-
|
|
133
|
-
<slot {collider} />
|
|
134
|
-
</SceneGraphObject>
|
|
147
|
+
{@render children?.({ collider })}
|
|
@@ -3,9 +3,9 @@ import type {
|
|
|
3
3
|
Collider as RapierCollider,
|
|
4
4
|
ColliderDesc
|
|
5
5
|
} from '@dimforge/rapier3d-compat'
|
|
6
|
-
import { SvelteComponent } from 'svelte'
|
|
6
|
+
import { SvelteComponent, type Snippet } from 'svelte'
|
|
7
7
|
import type { Euler, Vector3 } from 'three'
|
|
8
|
-
import type {
|
|
8
|
+
import type { ColliderEvents } from '../../types/types'
|
|
9
9
|
|
|
10
10
|
// ------------------ BASE ------------------
|
|
11
11
|
|
|
@@ -97,16 +97,13 @@ type MassProps<TMassDef extends MassDef> = TMassDef extends Density
|
|
|
97
97
|
// ------------------ COLLIDER ------------------
|
|
98
98
|
|
|
99
99
|
export type ColliderProps<TShape extends Shape, TMassDef extends MassDef> = BaseProps &
|
|
100
|
+
ColliderEvents &
|
|
100
101
|
ShapeProps<TShape> &
|
|
101
|
-
MassProps<TMassDef>
|
|
102
|
-
|
|
103
|
-
export type ColliderSlots = {
|
|
104
|
-
default: {
|
|
105
|
-
collider: RapierCollider
|
|
102
|
+
MassProps<TMassDef> & {
|
|
103
|
+
children?: Snippet<[{ collider?: RapierCollider }]>
|
|
106
104
|
}
|
|
107
|
-
}
|
|
108
105
|
|
|
109
106
|
export default class Collider<
|
|
110
107
|
TShape extends Shape,
|
|
111
108
|
TMassDef extends MassDef
|
|
112
|
-
> extends SvelteComponent<ColliderProps<TShape, TMassDef
|
|
109
|
+
> extends SvelteComponent<ColliderProps<TShape, TMassDef>> {}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
<script lang="ts">import { setContext } from 'svelte';
|
|
2
2
|
import { writable } from 'svelte/store';
|
|
3
3
|
import { computeBitMask } from '../../lib/computeBitMask';
|
|
4
|
-
let { groups, filter, memberships } = $props();
|
|
4
|
+
let { groups, filter, memberships, children } = $props();
|
|
5
5
|
const store = writable(computeBitMask(groups, filter, memberships));
|
|
6
6
|
$effect.pre(() => store.set(computeBitMask(groups, filter, memberships)));
|
|
7
7
|
setContext('threlte-rapier-collision-group', store);
|
|
8
8
|
</script>
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
{@render children?.()}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SvelteComponent } from 'svelte'
|
|
1
|
+
import { SvelteComponent, type Snippet } from 'svelte'
|
|
2
2
|
|
|
3
3
|
type N = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15
|
|
4
4
|
|
|
@@ -11,6 +11,8 @@ type GroupsProps = {
|
|
|
11
11
|
|
|
12
12
|
filter?: never
|
|
13
13
|
memberships?: never
|
|
14
|
+
|
|
15
|
+
children?: Snippet
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
type MembershipsAndFilterProps = {
|
|
@@ -18,6 +20,8 @@ type MembershipsAndFilterProps = {
|
|
|
18
20
|
memberships: N[]
|
|
19
21
|
|
|
20
22
|
groups?: never
|
|
23
|
+
|
|
24
|
+
children?: Snippet
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
type GroupsDef = GroupsProps | MembershipsAndFilterProps
|
|
@@ -1,17 +1,23 @@
|
|
|
1
|
-
<script lang="ts">import {
|
|
1
|
+
<script lang="ts">import { createParentObject3DContext, useParentObject3D, watch } from '@threlte/core';
|
|
2
2
|
import { onDestroy, setContext, tick } from 'svelte';
|
|
3
3
|
import { Object3D, Vector3 } from 'three';
|
|
4
4
|
import { useRapier } from '../../hooks/useRapier';
|
|
5
|
+
import { initializeRigidBodyUserData, setInitialRigidBodyState } from '../../lib/createPhysicsTasks';
|
|
5
6
|
import { getWorldPosition, getWorldQuaternion, getWorldScale } from '../../lib/getWorldTransforms';
|
|
6
7
|
import { parseRigidBodyType } from '../../lib/parseRigidBodyType';
|
|
7
8
|
import { setParentRigidbodyObject } from '../../lib/rigidBodyObjectContext';
|
|
8
9
|
import { useCreateEvent } from '../../lib/useCreateEvent';
|
|
10
|
+
import { overrideTeleportMethods } from './overrideTeleportMethods';
|
|
9
11
|
const { world, rapier, addRigidBodyToContext, removeRigidBodyFromContext } = useRapier();
|
|
10
|
-
let { linearVelocity, angularVelocity, type = 'dynamic', canSleep = true, gravityScale = 1, ccd = false, angularDamping = 0, linearDamping = 0, lockRotations = false, lockTranslations = false, enabledRotations = [true, true, true], enabledTranslations = [true, true, true], dominance = 0, enabled = true, userData = {}, rigidBody = $bindable(),
|
|
11
|
-
|
|
12
|
+
let { linearVelocity, angularVelocity, type = 'dynamic', canSleep = true, gravityScale = 1, ccd = false, angularDamping = 0, linearDamping = 0, lockRotations = false, lockTranslations = false, enabledRotations = [true, true, true], enabledTranslations = [true, true, true], dominance = 0, enabled = true, userData = {}, rigidBody = $bindable(), oncreate, oncollisionenter, oncollisionexit, oncontact, onsensorenter, onsensorexit, onsleep, onwake, children } = $props();
|
|
13
|
+
/**
|
|
14
|
+
* Every RigidBody receives and forwards collision-related events
|
|
15
|
+
*/
|
|
16
|
+
const { updateRef } = useCreateEvent(oncreate);
|
|
12
17
|
const object = new Object3D();
|
|
18
|
+
initializeRigidBodyUserData(object);
|
|
13
19
|
/**
|
|
14
|
-
* isSleeping used for events "sleep" and "wake" in `
|
|
20
|
+
* isSleeping used for events "sleep" and "wake" in `createPhysicsTasks`
|
|
15
21
|
*/
|
|
16
22
|
object.userData.isSleeping = false;
|
|
17
23
|
/**
|
|
@@ -22,6 +28,7 @@ const desc = new rapier.RigidBodyDesc(parseRigidBodyType(type)).setCanSleep(canS
|
|
|
22
28
|
* Temporary RigidBody init
|
|
23
29
|
*/
|
|
24
30
|
let rigidBodyInternal = world.createRigidBody(desc);
|
|
31
|
+
overrideTeleportMethods(rigidBodyInternal, object);
|
|
25
32
|
rigidBody = rigidBodyInternal;
|
|
26
33
|
/**
|
|
27
34
|
* Apply transforms after the parent component added "object" to itself
|
|
@@ -33,6 +40,7 @@ const initPosition = async () => {
|
|
|
33
40
|
const parentWorldScale = object.parent ? getWorldScale(object.parent) : new Vector3(1, 1, 1);
|
|
34
41
|
const worldPosition = getWorldPosition(object).multiply(parentWorldScale);
|
|
35
42
|
const worldQuaternion = getWorldQuaternion(object);
|
|
43
|
+
setInitialRigidBodyState(object, worldPosition, worldQuaternion);
|
|
36
44
|
rigidBodyInternal.setTranslation(worldPosition, true);
|
|
37
45
|
rigidBodyInternal.setRotation(worldQuaternion, true);
|
|
38
46
|
updateRef(rigidBodyInternal);
|
|
@@ -68,7 +76,15 @@ $effect.pre(() => rigidBodyInternal.setEnabled(enabled));
|
|
|
68
76
|
*/
|
|
69
77
|
$effect.pre(() => {
|
|
70
78
|
rigidBodyInternal.userData = {
|
|
71
|
-
events:
|
|
79
|
+
events: {
|
|
80
|
+
oncollisionenter,
|
|
81
|
+
oncollisionexit,
|
|
82
|
+
oncontact,
|
|
83
|
+
onsensorenter,
|
|
84
|
+
onsensorexit,
|
|
85
|
+
onsleep,
|
|
86
|
+
onwake
|
|
87
|
+
},
|
|
72
88
|
...userData
|
|
73
89
|
};
|
|
74
90
|
});
|
|
@@ -84,7 +100,15 @@ setParentRigidbodyObject(object);
|
|
|
84
100
|
/**
|
|
85
101
|
* Add the mesh to the context
|
|
86
102
|
*/
|
|
87
|
-
addRigidBodyToContext(rigidBodyInternal, object,
|
|
103
|
+
addRigidBodyToContext(rigidBodyInternal, object, {
|
|
104
|
+
oncollisionenter,
|
|
105
|
+
oncollisionexit,
|
|
106
|
+
oncontact,
|
|
107
|
+
onsensorenter,
|
|
108
|
+
onsensorexit,
|
|
109
|
+
onsleep,
|
|
110
|
+
onwake
|
|
111
|
+
});
|
|
88
112
|
/**
|
|
89
113
|
* cleanup
|
|
90
114
|
*/
|
|
@@ -92,8 +116,14 @@ onDestroy(() => {
|
|
|
92
116
|
removeRigidBodyFromContext(rigidBodyInternal);
|
|
93
117
|
world.removeRigidBody(rigidBodyInternal);
|
|
94
118
|
});
|
|
119
|
+
const parent3DObject = useParentObject3D();
|
|
120
|
+
createParentObject3DContext(object);
|
|
121
|
+
watch(parent3DObject, (parent) => {
|
|
122
|
+
parent?.add(object);
|
|
123
|
+
return () => {
|
|
124
|
+
parent?.remove(object);
|
|
125
|
+
};
|
|
126
|
+
});
|
|
95
127
|
</script>
|
|
96
128
|
|
|
97
|
-
|
|
98
|
-
<slot rigidBody={rigidBodyInternal} />
|
|
99
|
-
</SceneGraphObject>
|
|
129
|
+
{@render children?.({ rigidBody: rigidBodyInternal })}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { RigidBody as RapierRigidBody } from '@dimforge/rapier3d-compat'
|
|
2
|
-
import { SvelteComponent } from 'svelte'
|
|
2
|
+
import { SvelteComponent, type Snippet } from 'svelte'
|
|
3
3
|
import type { Euler, Vector3 } from 'three'
|
|
4
4
|
import type { RigidBodyTypeString } from '../../lib/parseRigidBodyType'
|
|
5
|
-
import type {
|
|
5
|
+
import type { RigidBodyEvents } from '../../types/types'
|
|
6
6
|
|
|
7
7
|
export type Boolean3Array = [x: boolean, y: boolean, z: boolean]
|
|
8
8
|
|
|
9
9
|
export type RigidBodyProps = {
|
|
10
|
-
rigidBody
|
|
10
|
+
rigidBody?: RapierRigidBody | undefined
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Specify the type of this rigid body
|
|
@@ -95,18 +95,8 @@ export type RigidBodyProps = {
|
|
|
95
95
|
* An arbitrary user-defined object associated with this rigid-body.
|
|
96
96
|
*/
|
|
97
97
|
userData?: Record<string, any>
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
type RigidBodyEvents = RigidBodyEventMap
|
|
101
98
|
|
|
102
|
-
|
|
103
|
-
default: {
|
|
104
|
-
rigidBody: RapierRigidBody
|
|
105
|
-
}
|
|
99
|
+
children?: Snippet<[{ rigidBody: RapierRigidBody }]>
|
|
106
100
|
}
|
|
107
101
|
|
|
108
|
-
export default class RigidBody extends SvelteComponent<
|
|
109
|
-
RigidBodyProps,
|
|
110
|
-
RigidBodyEvents,
|
|
111
|
-
RigidBodySlots
|
|
112
|
-
> {}
|
|
102
|
+
export default class RigidBody extends SvelteComponent<RigidBodyProps & RigidBodyEvents> {}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RigidBody } from '@dimforge/rapier3d-compat';
|
|
2
|
+
import type { Object3D } from 'three';
|
|
3
|
+
export type ExtractMethods<ObjectType> = Pick<ObjectType, {
|
|
4
|
+
[Method in keyof ObjectType]: ObjectType[Method] extends (...args: any[]) => any ? Method : never;
|
|
5
|
+
}[keyof ObjectType]>;
|
|
6
|
+
/**
|
|
7
|
+
* When using a fixed framerate, Threlte is interpolating the position and
|
|
8
|
+
* rotation of RigidBody objects. Sometimes, this is not desirable, especially
|
|
9
|
+
* when using methods on the rigidbody that teleport the object, e.g. should
|
|
10
|
+
* lead to a sudden change in translation/rotation such as `rb.setTranslation`.
|
|
11
|
+
* These methods are overridden to reset the physics simulation position and
|
|
12
|
+
* rotation to the current object position and rotation.
|
|
13
|
+
*/
|
|
14
|
+
export declare const overrideTeleportMethods: (rb: RigidBody, object: Object3D) => void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const overrideMethods = {
|
|
2
|
+
position: ['setTranslation', 'setNextKinematicTranslation'],
|
|
3
|
+
rotation: ['setRotation', 'setNextKinematicRotation']
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* When using a fixed framerate, Threlte is interpolating the position and
|
|
7
|
+
* rotation of RigidBody objects. Sometimes, this is not desirable, especially
|
|
8
|
+
* when using methods on the rigidbody that teleport the object, e.g. should
|
|
9
|
+
* lead to a sudden change in translation/rotation such as `rb.setTranslation`.
|
|
10
|
+
* These methods are overridden to reset the physics simulation position and
|
|
11
|
+
* rotation to the current object position and rotation.
|
|
12
|
+
*/
|
|
13
|
+
export const overrideTeleportMethods = (rb, object) => {
|
|
14
|
+
const originalMethods = {};
|
|
15
|
+
overrideMethods.position.forEach((method) => {
|
|
16
|
+
originalMethods[method] = rb[method].bind(rb);
|
|
17
|
+
const proxy = (...args) => {
|
|
18
|
+
object.userData.physics.resetPosition = true;
|
|
19
|
+
return originalMethods[method](...args);
|
|
20
|
+
};
|
|
21
|
+
rb[method] = proxy;
|
|
22
|
+
});
|
|
23
|
+
overrideMethods.rotation.forEach((method) => {
|
|
24
|
+
originalMethods[method] = rb[method].bind(rb);
|
|
25
|
+
const proxy = (...args) => {
|
|
26
|
+
object.userData.physics.resetRotation = true;
|
|
27
|
+
return originalMethods[method](...args);
|
|
28
|
+
};
|
|
29
|
+
rb[method] = proxy;
|
|
30
|
+
});
|
|
31
|
+
};
|
|
@@ -1,19 +1,41 @@
|
|
|
1
1
|
<script lang="ts">import { onDestroy, setContext, tick } from 'svelte';
|
|
2
|
-
import { useFrameHandler } from '../../hooks/useFrameHandler';
|
|
3
2
|
import { createRapierContext } from '../../lib/createRapierContext';
|
|
4
|
-
let { gravity = [0, -9.81, 0], rawIntegrationParameters, rawIslands, rawBroadPhase, rawNarrowPhase, rawBodies, rawColliders, rawImpulseJoints, rawMultibodyJoints, rawCCDSolver, rawQueryPipeline, rawPhysicsPipeline, rawSerializationPipeline, rawDebugRenderPipeline,
|
|
5
|
-
const rapierContext = createRapierContext(
|
|
3
|
+
let { gravity = [0, -9.81, 0], rawIntegrationParameters, rawIslands, rawBroadPhase, rawNarrowPhase, rawBodies, rawColliders, rawImpulseJoints, rawMultibodyJoints, rawCCDSolver, rawQueryPipeline, rawPhysicsPipeline, rawSerializationPipeline, rawDebugRenderPipeline, framerate, autoStart = true, simulationStageOptions, synchronizationStageOptions, children } = $props();
|
|
4
|
+
const rapierContext = createRapierContext([
|
|
5
|
+
{ x: gravity[0], y: gravity[1], z: gravity[2] },
|
|
6
|
+
rawIntegrationParameters,
|
|
7
|
+
rawIslands,
|
|
8
|
+
rawBroadPhase,
|
|
9
|
+
rawNarrowPhase,
|
|
10
|
+
rawBodies,
|
|
11
|
+
rawColliders,
|
|
12
|
+
rawImpulseJoints,
|
|
13
|
+
rawMultibodyJoints,
|
|
14
|
+
rawCCDSolver,
|
|
15
|
+
rawQueryPipeline,
|
|
16
|
+
rawPhysicsPipeline,
|
|
17
|
+
rawSerializationPipeline,
|
|
18
|
+
rawDebugRenderPipeline
|
|
19
|
+
], {
|
|
20
|
+
framerate,
|
|
21
|
+
autoStart,
|
|
22
|
+
simulationStageOptions,
|
|
23
|
+
synchronizationStageOptions
|
|
24
|
+
});
|
|
6
25
|
setContext('threlte-rapier-context', rapierContext);
|
|
7
26
|
$effect.pre(() => {
|
|
8
27
|
if (gravity !== undefined) {
|
|
9
28
|
rapierContext.world.gravity = { x: gravity[0], y: gravity[1], z: gravity[2] };
|
|
10
29
|
}
|
|
11
30
|
});
|
|
12
|
-
|
|
31
|
+
$effect.pre(() => {
|
|
32
|
+
if (framerate !== undefined)
|
|
33
|
+
rapierContext.framerate.set(framerate);
|
|
34
|
+
});
|
|
13
35
|
onDestroy(async () => {
|
|
14
36
|
await tick();
|
|
15
37
|
rapierContext.world.free();
|
|
16
38
|
});
|
|
17
39
|
</script>
|
|
18
40
|
|
|
19
|
-
|
|
41
|
+
{@render children?.()}
|
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
|
2
2
|
import type { WorldProps } from './World.svelte';
|
|
3
3
|
declare const __propDef: {
|
|
4
|
-
props: WorldProps
|
|
5
|
-
children?: ((this: void) => typeof import("svelte").SnippetReturn & {
|
|
6
|
-
_: "functions passed to {@render ...} tags must use the `Snippet` type imported from \"svelte\"";
|
|
7
|
-
}) | undefined;
|
|
8
|
-
};
|
|
4
|
+
props: WorldProps;
|
|
9
5
|
events: {
|
|
10
6
|
[evt: string]: CustomEvent<any>;
|
|
11
7
|
};
|
|
12
|
-
slots: {
|
|
13
|
-
default: {};
|
|
14
|
-
};
|
|
8
|
+
slots: {};
|
|
15
9
|
};
|
|
16
10
|
export type InnerWorldProps = typeof __propDef.props;
|
|
17
11
|
export type InnerWorldEvents = typeof __propDef.events;
|
|
@@ -1,60 +1,12 @@
|
|
|
1
|
-
<script
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
>import RAPIER from '@dimforge/rapier3d-compat';
|
|
5
|
-
import { onMount } from 'svelte';
|
|
6
|
-
import { writable } from 'svelte/store';
|
|
7
|
-
/**
|
|
8
|
-
* RAPIER.init() should only be called once
|
|
9
|
-
*/
|
|
10
|
-
const initialized = writable(false);
|
|
1
|
+
<script lang="ts">import { initRapier } from '../../lib/initRapier.svelte';
|
|
2
|
+
import InnerWorld from './InnerWorld.svelte';
|
|
3
|
+
let { fallback, children, ...rest } = $props();
|
|
11
4
|
</script>
|
|
12
5
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* This is passed to the useTask handler.
|
|
17
|
-
* Use this to control when the rapier physics engine is updating the scene.
|
|
18
|
-
* @default undefined
|
|
19
|
-
*/
|
|
20
|
-
stage } = $props();
|
|
21
|
-
let error = $state(false);
|
|
22
|
-
const init = async () => {
|
|
23
|
-
if ($initialized)
|
|
24
|
-
return;
|
|
25
|
-
try {
|
|
26
|
-
await RAPIER.init();
|
|
27
|
-
$initialized = true;
|
|
28
|
-
}
|
|
29
|
-
catch (e) {
|
|
30
|
-
error = true;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
onMount(init);
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
{#if $initialized}
|
|
37
|
-
<InnerWorld
|
|
38
|
-
{gravity}
|
|
39
|
-
{rawIntegrationParameters}
|
|
40
|
-
{rawIslands}
|
|
41
|
-
{rawBroadPhase}
|
|
42
|
-
{rawNarrowPhase}
|
|
43
|
-
{rawBodies}
|
|
44
|
-
{rawColliders}
|
|
45
|
-
{rawImpulseJoints}
|
|
46
|
-
{rawMultibodyJoints}
|
|
47
|
-
{rawCCDSolver}
|
|
48
|
-
{rawQueryPipeline}
|
|
49
|
-
{rawPhysicsPipeline}
|
|
50
|
-
{rawSerializationPipeline}
|
|
51
|
-
{rawDebugRenderPipeline}
|
|
52
|
-
{stage}
|
|
53
|
-
>
|
|
54
|
-
<slot />
|
|
6
|
+
{#await initRapier() then _}
|
|
7
|
+
<InnerWorld {...rest}>
|
|
8
|
+
{@render children?.()}
|
|
55
9
|
</InnerWorld>
|
|
56
|
-
{
|
|
57
|
-
|
|
58
|
-
{
|
|
59
|
-
<slot name="fallback" />
|
|
60
|
-
{/if}
|
|
10
|
+
{:catch error}
|
|
11
|
+
{@render fallback?.(error)}
|
|
12
|
+
{/await}
|
|
@@ -13,11 +13,13 @@ import type {
|
|
|
13
13
|
RawRigidBodySet,
|
|
14
14
|
RawSerializationPipeline
|
|
15
15
|
} from '@dimforge/rapier3d-compat/raw'
|
|
16
|
-
import { SvelteComponent } from 'svelte'
|
|
16
|
+
import { SvelteComponent, type Snippet } from 'svelte'
|
|
17
17
|
import type { Vector3 } from 'three'
|
|
18
18
|
import type { Key, Stage } from '@threlte/core'
|
|
19
19
|
|
|
20
20
|
export type WorldProps = {
|
|
21
|
+
framerate?: number | 'varying'
|
|
22
|
+
autoStart?: boolean
|
|
21
23
|
gravity?: Parameters<Vector3['set']>
|
|
22
24
|
rawIntegrationParameters?: RawIntegrationParameters
|
|
23
25
|
rawIslands?: RawIslandManager
|
|
@@ -32,7 +34,16 @@ export type WorldProps = {
|
|
|
32
34
|
rawPhysicsPipeline?: RawPhysicsPipeline
|
|
33
35
|
rawSerializationPipeline?: RawSerializationPipeline
|
|
34
36
|
rawDebugRenderPipeline?: RawDebugRenderPipeline
|
|
35
|
-
|
|
37
|
+
simulationStageOptions?: {
|
|
38
|
+
before?: (Key | Stage) | (Key | Stage)[]
|
|
39
|
+
after?: (Key | Stage) | (Key | Stage)[]
|
|
40
|
+
}
|
|
41
|
+
synchronizationStageOptions?: {
|
|
42
|
+
before?: (Key | Stage) | (Key | Stage)[]
|
|
43
|
+
after?: (Key | Stage) | (Key | Stage)[]
|
|
44
|
+
}
|
|
45
|
+
children?: Snippet
|
|
46
|
+
fallback?: Snippet<[error: any]>
|
|
36
47
|
}
|
|
37
48
|
|
|
38
49
|
export default class World extends SvelteComponent<WorldProps> {}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { type Collider } from '@dimforge/rapier3d-compat';
|
|
2
|
-
|
|
2
|
+
import type { ColliderEvents, RigidBodyEvents } from '../types/types';
|
|
3
|
+
export declare const applyColliderActiveEvents: (collider: Collider, colliderEvents?: ColliderEvents, rigidBodyEvents?: RigidBodyEvents) => void;
|