@threlte/rapier 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +19 -0
  3. package/dist/CHANGELOG.md +103 -0
  4. package/dist/LICENSE.md +21 -0
  5. package/dist/README.md +19 -0
  6. package/dist/components/Colliders/AutoColliders.svelte +74 -0
  7. package/dist/components/Colliders/AutoColliders.svelte.d.ts +33 -0
  8. package/dist/components/Colliders/Collider.svelte +119 -0
  9. package/dist/components/Colliders/Collider.svelte.d.ts +32 -0
  10. package/dist/components/CollisionGroups/CollisionGroups.svelte +31 -0
  11. package/dist/components/CollisionGroups/CollisionGroups.svelte.d.ts +21 -0
  12. package/dist/components/Debug/Debug.svelte +30 -0
  13. package/dist/components/Debug/Debug.svelte.d.ts +60 -0
  14. package/dist/components/RigidBody/RigidBody.svelte +111 -0
  15. package/dist/components/RigidBody/RigidBody.svelte.d.ts +39 -0
  16. package/dist/components/World/InnerWorld.svelte +32 -0
  17. package/dist/components/World/InnerWorld.svelte.d.ts +32 -0
  18. package/dist/components/World/World.svelte +63 -0
  19. package/dist/components/World/World.svelte.d.ts +33 -0
  20. package/dist/hooks/useCollisionGroups.d.ts +5 -0
  21. package/dist/hooks/useCollisionGroups.js +52 -0
  22. package/dist/hooks/useFrameHandler.d.ts +2 -0
  23. package/dist/hooks/useFrameHandler.js +176 -0
  24. package/dist/hooks/useRapier.d.ts +2 -0
  25. package/dist/hooks/useRapier.js +4 -0
  26. package/dist/hooks/useRigidBody.d.ts +2 -0
  27. package/dist/hooks/useRigidBody.js +4 -0
  28. package/dist/index.d.ts +12 -0
  29. package/dist/index.js +13 -0
  30. package/dist/lib/applyTransforms.d.ts +3 -0
  31. package/dist/lib/applyTransforms.js +17 -0
  32. package/dist/lib/createCollidersFromChildren.d.ts +16 -0
  33. package/dist/lib/createCollidersFromChildren.js +94 -0
  34. package/dist/lib/createRapierContext.d.ts +16 -0
  35. package/dist/lib/createRapierContext.js +56 -0
  36. package/dist/lib/getWorldTransforms.d.ts +41 -0
  37. package/dist/lib/getWorldTransforms.js +55 -0
  38. package/dist/lib/parseRigidBodyType.d.ts +3 -0
  39. package/dist/lib/parseRigidBodyType.js +10 -0
  40. package/dist/lib/positionToVector3.d.ts +3 -0
  41. package/dist/lib/positionToVector3.js +8 -0
  42. package/dist/lib/rotationToEuler.d.ts +3 -0
  43. package/dist/lib/rotationToEuler.js +8 -0
  44. package/dist/lib/rotationToQuaternion.d.ts +3 -0
  45. package/dist/lib/rotationToQuaternion.js +10 -0
  46. package/dist/lib/scaleColliderArgs.d.ts +5 -0
  47. package/dist/lib/scaleColliderArgs.js +25 -0
  48. package/dist/lib/scaleToVector3.d.ts +3 -0
  49. package/dist/lib/scaleToVector3.js +16 -0
  50. package/dist/recipes/BasicPlayerController.svelte +129 -0
  51. package/dist/recipes/BasicPlayerController.svelte.d.ts +29 -0
  52. package/dist/types/components.d.ts +131 -0
  53. package/dist/types/components.js +1 -0
  54. package/dist/types/types.d.ts +38 -0
  55. package/dist/types/types.js +1 -0
  56. package/package.json +50 -0
@@ -0,0 +1,111 @@
1
+ <script>import { LayerableObject, SceneGraphObject } from '@threlte/core';
2
+ import { createEventDispatcher, onDestroy, setContext } from 'svelte';
3
+ import { Object3D, Vector3 } from 'three';
4
+ import { useRapier } from '../../hooks/useRapier';
5
+ import { applyTransforms } from '../../lib/applyTransforms';
6
+ import { getWorldPosition, getWorldQuaternion } from '../../lib/getWorldTransforms';
7
+ import { parseRigidBodyType } from '../../lib/parseRigidBodyType';
8
+ import { positionToVector3 } from '../../lib/positionToVector3';
9
+ import { rotationToEuler } from '../../lib/rotationToEuler';
10
+ const { world, rapier, addRigidBodyToContext, removeRigidBodyFromContext } = useRapier();
11
+ export let type = 'dynamic';
12
+ export let canSleep = true;
13
+ export let linearVelocity = {};
14
+ export let angularVelocity = {};
15
+ export let gravityScale = 1;
16
+ export let ccd = false;
17
+ export let position = undefined;
18
+ export let rotation = undefined;
19
+ export let scale = undefined;
20
+ export let lookAt = undefined;
21
+ export let lockRotations = false;
22
+ export let lockTranslations = false;
23
+ export let enabledRotations = [
24
+ true,
25
+ true,
26
+ true
27
+ ];
28
+ export let enabledTranslations = [
29
+ true,
30
+ true,
31
+ true
32
+ ];
33
+ export let dominance = 0;
34
+ const dispatcher = createEventDispatcher();
35
+ const object = new Object3D();
36
+ /**
37
+ * Used to traverseAncestors to restore transform
38
+ */
39
+ object.userData.isRigidBody = true;
40
+ /**
41
+ * isSleeping used for events "sleep" and "wake" in `useFrameHandler`
42
+ */
43
+ object.userData.isSleeping = false;
44
+ /**
45
+ * Immediately apply transforms to get the objects
46
+ * world position to apply to the RigidBody.
47
+ * This is a one-off operation as RigidBodies should
48
+ * not be moved around after initialization.
49
+ */
50
+ applyTransforms(object, position, rotation, scale, lookAt);
51
+ /**
52
+ * Update the world matrix of the object before applying
53
+ * the world position to the RigidBody
54
+ */
55
+ object.updateWorldMatrix(true, false);
56
+ const worldPosition = getWorldPosition(object);
57
+ const worldRotation = getWorldQuaternion(object);
58
+ const parentWorldScale = object.parent?.getWorldScale(new Vector3()) || new Vector3(1, 1, 1);
59
+ /**
60
+ * RigidBody Description
61
+ */
62
+ const desc = new rapier.RigidBodyDesc(parseRigidBodyType(type))
63
+ .setCanSleep(canSleep)
64
+ .setTranslation(worldPosition.x * parentWorldScale.x, worldPosition.y * parentWorldScale.y, worldPosition.z * parentWorldScale.z)
65
+ .setRotation({ x: worldRotation.x, y: worldRotation.y, z: worldRotation.z, w: worldRotation.w });
66
+ /**
67
+ * RigidBody init
68
+ */
69
+ export const rigidBody = world.createRigidBody(desc);
70
+ /**
71
+ * Will come in handy in the future for joints
72
+ */
73
+ object.userData.rigidBody = rigidBody;
74
+ /**
75
+ * Reactive RigidBody properties
76
+ */
77
+ $: {
78
+ rigidBody.setBodyType(parseRigidBodyType(type));
79
+ rigidBody.setLinvel(positionToVector3(linearVelocity), true);
80
+ rigidBody.setAngvel(rotationToEuler(angularVelocity), true);
81
+ rigidBody.setGravityScale(gravityScale, true);
82
+ rigidBody.enableCcd(ccd);
83
+ rigidBody.setDominanceGroup(dominance);
84
+ rigidBody.lockRotations(lockRotations, true);
85
+ rigidBody.lockTranslations(lockTranslations, true);
86
+ rigidBody.setEnabledRotations(...enabledRotations, true);
87
+ rigidBody.setEnabledTranslations(...enabledTranslations, true);
88
+ }
89
+ /**
90
+ * Setting the RigidBody context so that colliders can
91
+ * hook onto.
92
+ */
93
+ setContext('threlte-rapier-rigidbody', rigidBody);
94
+ /**
95
+ * Add the mesh to the context
96
+ */
97
+ addRigidBodyToContext(rigidBody, object, dispatcher);
98
+ /**
99
+ * cleanup
100
+ */
101
+ onDestroy(() => {
102
+ removeRigidBodyFromContext(rigidBody);
103
+ world.removeRigidBody(rigidBody);
104
+ });
105
+ </script>
106
+
107
+ <SceneGraphObject {object}>
108
+ <slot />
109
+ </SceneGraphObject>
110
+
111
+ <LayerableObject {object} />
@@ -0,0 +1,39 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { RigidBodyProperties } from '../../types/components';
3
+ import type { RigidBodyEventMap } from '../../types/types';
4
+ declare const __propDef: {
5
+ props: {
6
+ type?: import("../../lib/parseRigidBodyType").RigidBodyTypeString | undefined;
7
+ canSleep?: boolean | undefined;
8
+ linearVelocity?: import("@threlte/core").Position | undefined;
9
+ angularVelocity?: import("@threlte/core").Rotation | undefined;
10
+ gravityScale?: number | undefined;
11
+ ccd?: boolean | undefined;
12
+ position?: RigidBodyProperties['position'];
13
+ rotation?: RigidBodyProperties['rotation'];
14
+ scale?: RigidBodyProperties['scale'];
15
+ lookAt?: RigidBodyProperties['lookAt'];
16
+ lockRotations?: boolean | undefined;
17
+ lockTranslations?: boolean | undefined;
18
+ enabledRotations?: import("../../types/components").Boolean3Array | undefined;
19
+ enabledTranslations?: import("../../types/components").Boolean3Array | undefined;
20
+ dominance?: number | undefined;
21
+ /**
22
+ * RigidBody init
23
+ */ rigidBody?: import("@dimforge/rapier3d-compat").RigidBody | undefined;
24
+ };
25
+ slots: {
26
+ default: {};
27
+ };
28
+ getters: {
29
+ rigidBody: import("@dimforge/rapier3d-compat").RigidBody;
30
+ };
31
+ events: RigidBodyEventMap;
32
+ };
33
+ export declare type RigidBodyProps = typeof __propDef.props;
34
+ export declare type RigidBodyEvents = typeof __propDef.events;
35
+ export declare type RigidBodySlots = typeof __propDef.slots;
36
+ export default class RigidBody extends SvelteComponentTyped<RigidBodyProps, RigidBodyEvents, RigidBodySlots> {
37
+ get rigidBody(): import("@dimforge/rapier3d-compat").RigidBody;
38
+ }
39
+ export {};
@@ -0,0 +1,32 @@
1
+ <script context="module">import { onDestroy, setContext, tick } from 'svelte';
2
+ import { useFrameHandler } from '../../hooks/useFrameHandler';
3
+ import { createRapierContext } from '../../lib/createRapierContext';
4
+ </script>
5
+
6
+ <script>import { positionToVector3 } from '../../lib/positionToVector3';
7
+ export let gravity = { y: -9.81 };
8
+ export let rawIntegrationParameters = undefined;
9
+ export let rawIslands = undefined;
10
+ export let rawBroadPhase = undefined;
11
+ export let rawNarrowPhase = undefined;
12
+ export let rawBodies = undefined;
13
+ export let rawColliders = undefined;
14
+ export let rawImpulseJoints = undefined;
15
+ export let rawMultibodyJoints = undefined;
16
+ export let rawCCDSolver = undefined;
17
+ export let rawQueryPipeline = undefined;
18
+ export let rawPhysicsPipeline = undefined;
19
+ export let rawSerializationPipeline = undefined;
20
+ export let rawDebugRenderPipeline = undefined;
21
+ const rapierContext = createRapierContext(positionToVector3(gravity), rawIntegrationParameters, rawIslands, rawBroadPhase, rawNarrowPhase, rawBodies, rawColliders, rawImpulseJoints, rawMultibodyJoints, rawCCDSolver, rawQueryPipeline, rawPhysicsPipeline, rawSerializationPipeline, rawDebugRenderPipeline);
22
+ setContext('threlte-rapier-context', rapierContext);
23
+ $: if (gravity !== undefined)
24
+ rapierContext.world.gravity = positionToVector3(gravity);
25
+ useFrameHandler(rapierContext);
26
+ onDestroy(async () => {
27
+ await tick();
28
+ rapierContext.world.free();
29
+ });
30
+ </script>
31
+
32
+ <slot />
@@ -0,0 +1,32 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { InnerWorldProperties } from '../../types/components';
3
+ declare const __propDef: {
4
+ props: {
5
+ gravity?: InnerWorldProperties['gravity'];
6
+ rawIntegrationParameters?: InnerWorldProperties['rawIntegrationParameters'];
7
+ rawIslands?: InnerWorldProperties['rawIslands'];
8
+ rawBroadPhase?: InnerWorldProperties['rawBroadPhase'];
9
+ rawNarrowPhase?: InnerWorldProperties['rawNarrowPhase'];
10
+ rawBodies?: InnerWorldProperties['rawBodies'];
11
+ rawColliders?: InnerWorldProperties['rawColliders'];
12
+ rawImpulseJoints?: InnerWorldProperties['rawImpulseJoints'];
13
+ rawMultibodyJoints?: InnerWorldProperties['rawMultibodyJoints'];
14
+ rawCCDSolver?: InnerWorldProperties['rawCCDSolver'];
15
+ rawQueryPipeline?: InnerWorldProperties['rawQueryPipeline'];
16
+ rawPhysicsPipeline?: InnerWorldProperties['rawPhysicsPipeline'];
17
+ rawSerializationPipeline?: InnerWorldProperties['rawSerializationPipeline'];
18
+ rawDebugRenderPipeline?: InnerWorldProperties['rawDebugRenderPipeline'];
19
+ };
20
+ events: {
21
+ [evt: string]: CustomEvent<any>;
22
+ };
23
+ slots: {
24
+ default: {};
25
+ };
26
+ };
27
+ export declare type InnerWorldProps = typeof __propDef.props;
28
+ export declare type InnerWorldEvents = typeof __propDef.events;
29
+ export declare type InnerWorldSlots = typeof __propDef.slots;
30
+ export default class InnerWorld extends SvelteComponentTyped<InnerWorldProps, InnerWorldEvents, InnerWorldSlots> {
31
+ }
32
+ export {};
@@ -0,0 +1,63 @@
1
+ <script context="module">import RAPIER from '@dimforge/rapier3d-compat';
2
+ import { onMount } from 'svelte';
3
+ import { writable } from 'svelte/store';
4
+ /**
5
+ * RAPIER.init() should only be called once
6
+ */
7
+ let initialized = writable(false);
8
+ </script>
9
+
10
+ <script>import InnerWorld from './InnerWorld.svelte';
11
+ export let gravity = undefined;
12
+ export let rawIntegrationParameters = undefined;
13
+ export let rawIslands = undefined;
14
+ export let rawBroadPhase = undefined;
15
+ export let rawNarrowPhase = undefined;
16
+ export let rawBodies = undefined;
17
+ export let rawColliders = undefined;
18
+ export let rawImpulseJoints = undefined;
19
+ export let rawMultibodyJoints = undefined;
20
+ export let rawCCDSolver = undefined;
21
+ export let rawQueryPipeline = undefined;
22
+ export let rawPhysicsPipeline = undefined;
23
+ export let rawSerializationPipeline = undefined;
24
+ export let rawDebugRenderPipeline = undefined;
25
+ let error = false;
26
+ const init = async () => {
27
+ if ($initialized)
28
+ return;
29
+ try {
30
+ await RAPIER.init();
31
+ $initialized = true;
32
+ }
33
+ catch (e) {
34
+ error = true;
35
+ }
36
+ };
37
+ onMount(init);
38
+ </script>
39
+
40
+ {#if $initialized}
41
+ <InnerWorld
42
+ {gravity}
43
+ {rawIntegrationParameters}
44
+ {rawIslands}
45
+ {rawBroadPhase}
46
+ {rawNarrowPhase}
47
+ {rawBodies}
48
+ {rawColliders}
49
+ {rawImpulseJoints}
50
+ {rawMultibodyJoints}
51
+ {rawCCDSolver}
52
+ {rawQueryPipeline}
53
+ {rawPhysicsPipeline}
54
+ {rawSerializationPipeline}
55
+ {rawDebugRenderPipeline}
56
+ >
57
+ <slot />
58
+ </InnerWorld>
59
+ {/if}
60
+
61
+ {#if error}
62
+ <slot name="fallback" />
63
+ {/if}
@@ -0,0 +1,33 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import type { WorldProperties } from '../../types/components';
3
+ declare const __propDef: {
4
+ props: {
5
+ gravity?: WorldProperties['gravity'];
6
+ rawIntegrationParameters?: WorldProperties['rawIntegrationParameters'];
7
+ rawIslands?: WorldProperties['rawIslands'];
8
+ rawBroadPhase?: WorldProperties['rawBroadPhase'];
9
+ rawNarrowPhase?: WorldProperties['rawNarrowPhase'];
10
+ rawBodies?: WorldProperties['rawBodies'];
11
+ rawColliders?: WorldProperties['rawColliders'];
12
+ rawImpulseJoints?: WorldProperties['rawImpulseJoints'];
13
+ rawMultibodyJoints?: WorldProperties['rawMultibodyJoints'];
14
+ rawCCDSolver?: WorldProperties['rawCCDSolver'];
15
+ rawQueryPipeline?: WorldProperties['rawQueryPipeline'];
16
+ rawPhysicsPipeline?: WorldProperties['rawPhysicsPipeline'];
17
+ rawSerializationPipeline?: WorldProperties['rawSerializationPipeline'];
18
+ rawDebugRenderPipeline?: WorldProperties['rawDebugRenderPipeline'];
19
+ };
20
+ events: {
21
+ [evt: string]: CustomEvent<any>;
22
+ };
23
+ slots: {
24
+ default: {};
25
+ fallback: {};
26
+ };
27
+ };
28
+ export declare type WorldProps = typeof __propDef.props;
29
+ export declare type WorldEvents = typeof __propDef.events;
30
+ export declare type WorldSlots = typeof __propDef.slots;
31
+ export default class World extends SvelteComponentTyped<WorldProps, WorldEvents, WorldSlots> {
32
+ }
33
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { Collider } from '@dimforge/rapier3d-compat';
2
+ export declare const useCollisionGroups: () => {
3
+ registerColliders: (colliders: Collider[]) => void;
4
+ removeColliders: (colliders: Collider[]) => void;
5
+ };
@@ -0,0 +1,52 @@
1
+ import { getContext, onDestroy } from 'svelte';
2
+ import { get } from 'svelte/store';
3
+ const applyBitMask = (collidersMap, bitMask) => {
4
+ collidersMap.forEach((c) => {
5
+ if (c && c.collider && c.collider.isValid()) {
6
+ c.collider.setCollisionGroups(bitMask);
7
+ }
8
+ });
9
+ };
10
+ export const useCollisionGroups = () => {
11
+ const collidersMap = new Map();
12
+ const bitMaskStore = getContext('threlte-rapier-collision-group');
13
+ if (!bitMaskStore)
14
+ return {
15
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
16
+ registerColliders: (colliders) => { },
17
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
18
+ removeColliders: (colliders) => { }
19
+ };
20
+ let bitMask = get(bitMaskStore);
21
+ const unsubscribe = bitMaskStore.subscribe((newBitMask) => {
22
+ bitMask = newBitMask;
23
+ applyBitMask(collidersMap, newBitMask);
24
+ });
25
+ onDestroy(unsubscribe);
26
+ const registerColliders = (colliders) => {
27
+ colliders.forEach((c) => {
28
+ if (!collidersMap.has(c.handle)) {
29
+ collidersMap.set(c.handle, {
30
+ collider: c,
31
+ initialCollisionGroup: c.collisionGroups()
32
+ });
33
+ }
34
+ });
35
+ applyBitMask(collidersMap, bitMask);
36
+ };
37
+ const removeColliders = (colliders) => {
38
+ colliders.forEach((c) => {
39
+ const mapItem = collidersMap.get(c.handle);
40
+ if (mapItem) {
41
+ if (c && c.isValid()) {
42
+ c.setCollisionGroups(mapItem.initialCollisionGroup);
43
+ }
44
+ }
45
+ collidersMap.delete(c.handle);
46
+ });
47
+ };
48
+ return {
49
+ registerColliders,
50
+ removeColliders
51
+ };
52
+ };
@@ -0,0 +1,2 @@
1
+ import type { RapierContext } from '../types/types';
2
+ export declare const useFrameHandler: (ctx: RapierContext) => void;
@@ -0,0 +1,176 @@
1
+ import { EventQueue } from '@dimforge/rapier3d-compat';
2
+ import { useFrame } from '@threlte/core';
3
+ import { Object3D, Quaternion, Vector3 } from 'three';
4
+ const tempObject = new Object3D();
5
+ const tempVector3 = new Vector3();
6
+ const tempQuaternion = new Quaternion();
7
+ export const useFrameHandler = (ctx) => {
8
+ const eventQueue = new EventQueue(false);
9
+ let time = performance.now();
10
+ useFrame(() => {
11
+ // if (!eventQueue) return
12
+ const { world } = ctx;
13
+ // Set timestep to current delta, to allow for variable frame rates
14
+ // We cap the delta at 100, so that the physics simulation doesn't get wild
15
+ const now = performance.now();
16
+ const delta = Math.min(100, now - time);
17
+ world.timestep = delta / 1000;
18
+ world.step(eventQueue);
19
+ // Update meshes
20
+ ctx.rigidBodyObjects.forEach((mesh, handle) => {
21
+ const rigidBody = world.getRigidBody(handle);
22
+ if (!rigidBody)
23
+ return;
24
+ const dispatcher = ctx.rigidBodyEventDispatchers.get(handle);
25
+ if (!rigidBody || !rigidBody.isValid())
26
+ return;
27
+ if (dispatcher) {
28
+ if (rigidBody.isSleeping() && !mesh.userData.isSleeping) {
29
+ dispatcher('sleep');
30
+ }
31
+ if (!rigidBody.isSleeping() && mesh.userData.isSleeping) {
32
+ dispatcher('wake');
33
+ }
34
+ mesh.userData.isSleeping = rigidBody.isSleeping();
35
+ }
36
+ if (!rigidBody || rigidBody.isSleeping() || rigidBody.isFixed() || !mesh.parent) {
37
+ return;
38
+ }
39
+ // Position
40
+ const { x, y, z } = rigidBody.translation();
41
+ tempObject.position.set(x, y, z);
42
+ // Rotation
43
+ const rotation = rigidBody.rotation();
44
+ tempQuaternion.set(rotation.x, rotation.y, rotation.z, rotation.w);
45
+ tempObject.rotation.setFromQuaternion(tempQuaternion);
46
+ // Scale
47
+ mesh.getWorldScale(tempVector3);
48
+ tempObject.scale.copy(tempVector3);
49
+ tempObject.updateMatrix();
50
+ tempObject.applyMatrix4(mesh.parent.matrixWorld.clone().invert());
51
+ tempObject.updateMatrix();
52
+ mesh.position.setFromMatrixPosition(tempObject.matrix);
53
+ mesh.rotation.setFromRotationMatrix(tempObject.matrix);
54
+ });
55
+ // Collision events
56
+ eventQueue.drainCollisionEvents((handle1, handle2, started) => {
57
+ const collider1 = world.getCollider(handle1);
58
+ const collider2 = world.getCollider(handle2);
59
+ // Sanity check
60
+ if (!collider1 || !collider2) {
61
+ return;
62
+ }
63
+ const colliderDispatcher1 = ctx.colliderEventDispatchers.get(collider1.handle);
64
+ const colliderDispatcher2 = ctx.colliderEventDispatchers.get(collider2.handle);
65
+ const rigidBody1 = collider1.parent();
66
+ const rigidBody2 = collider2.parent();
67
+ const rigidBodyDispatcher1 = rigidBody1
68
+ ? ctx.rigidBodyEventDispatchers.get(rigidBody1.handle)
69
+ : undefined;
70
+ const rigidBodyDispatcher2 = rigidBody2
71
+ ? ctx.rigidBodyEventDispatchers.get(rigidBody2.handle)
72
+ : undefined;
73
+ if (started) {
74
+ // intersections are triggered by sensors
75
+ const isIntersection = world.intersectionPair(collider1, collider2);
76
+ if (isIntersection) {
77
+ // Collider Events
78
+ colliderDispatcher1?.('sensorenter', {
79
+ targetCollider: collider2,
80
+ targetRigidBody: rigidBody2
81
+ });
82
+ colliderDispatcher2?.('sensorenter', {
83
+ targetCollider: collider1,
84
+ targetRigidBody: rigidBody1
85
+ });
86
+ // RigidBody Events
87
+ rigidBodyDispatcher1?.('sensorenter', {
88
+ targetCollider: collider2,
89
+ targetRigidBody: rigidBody2
90
+ });
91
+ rigidBodyDispatcher2?.('sensorenter', {
92
+ targetCollider: collider1,
93
+ targetRigidBody: rigidBody1
94
+ });
95
+ // intersections with sensors don't trigger contact pairs, returning
96
+ return;
97
+ }
98
+ world.contactPair(collider1, collider2, (manifold, flipped) => {
99
+ // Collider events
100
+ colliderDispatcher1?.('collisionenter', {
101
+ flipped,
102
+ manifold,
103
+ targetCollider: collider2,
104
+ targetRigidBody: rigidBody2
105
+ });
106
+ colliderDispatcher2?.('collisionenter', {
107
+ flipped,
108
+ manifold,
109
+ targetCollider: collider1,
110
+ targetRigidBody: rigidBody1
111
+ });
112
+ // RigidBody Events
113
+ rigidBodyDispatcher1?.('collisionenter', {
114
+ flipped,
115
+ manifold,
116
+ targetCollider: collider2,
117
+ targetRigidBody: rigidBody2
118
+ });
119
+ rigidBodyDispatcher2?.('collisionenter', {
120
+ flipped,
121
+ manifold,
122
+ targetCollider: collider1,
123
+ targetRigidBody: rigidBody1
124
+ });
125
+ });
126
+ }
127
+ else {
128
+ // COLLISION / INTERSECTION ENDED
129
+ // intersections are triggered by sensors, but apparently not on collision exit
130
+ const isIntersection = world.intersectionPair(collider1, collider2) ||
131
+ collider1.isSensor() ||
132
+ collider2.isSensor();
133
+ if (isIntersection) {
134
+ colliderDispatcher1?.('sensorexit', {
135
+ targetCollider: collider2,
136
+ targetRigidBody: rigidBody2
137
+ });
138
+ colliderDispatcher2?.('sensorexit', {
139
+ targetCollider: collider1,
140
+ targetRigidBody: rigidBody1
141
+ });
142
+ // RigidBody Events
143
+ rigidBodyDispatcher1?.('sensorexit', {
144
+ targetCollider: collider2,
145
+ targetRigidBody: rigidBody2
146
+ });
147
+ rigidBodyDispatcher2?.('sensorexit', {
148
+ targetCollider: collider1,
149
+ targetRigidBody: rigidBody1
150
+ });
151
+ // intersections with sensors don't trigger contact pairs, returning
152
+ return;
153
+ }
154
+ // Collider events
155
+ colliderDispatcher1?.('collisionexit', {
156
+ targetCollider: collider2,
157
+ targetRigidBody: rigidBody2
158
+ });
159
+ colliderDispatcher2?.('collisionexit', {
160
+ targetCollider: collider1,
161
+ targetRigidBody: rigidBody1
162
+ });
163
+ // RigidBody Events
164
+ rigidBodyDispatcher1?.('collisionexit', {
165
+ targetCollider: collider2,
166
+ targetRigidBody: rigidBody2
167
+ });
168
+ rigidBodyDispatcher2?.('collisionexit', {
169
+ targetCollider: collider1,
170
+ targetRigidBody: rigidBody1
171
+ });
172
+ }
173
+ });
174
+ time = now;
175
+ });
176
+ };
@@ -0,0 +1,2 @@
1
+ import type { RapierContext } from '../types/types';
2
+ export declare const useRapier: () => RapierContext;
@@ -0,0 +1,4 @@
1
+ import { getContext } from 'svelte';
2
+ export const useRapier = () => {
3
+ return getContext('threlte-rapier-context');
4
+ };
@@ -0,0 +1,2 @@
1
+ import type { RigidBodyContext } from '../types/types';
2
+ export declare const useRigidBody: () => RigidBodyContext;
@@ -0,0 +1,4 @@
1
+ import { getContext } from 'svelte';
2
+ export const useRigidBody = () => {
3
+ return getContext('threlte-rapier-rigidbody');
4
+ };
@@ -0,0 +1,12 @@
1
+ export { useRapier } from './hooks/useRapier';
2
+ export { useCollisionGroups } from './hooks/useCollisionGroups';
3
+ export { useRigidBody } from './hooks/useRigidBody';
4
+ export { default as World } from './components/World/World.svelte';
5
+ export { default as RigidBody } from './components/RigidBody/RigidBody.svelte';
6
+ export { default as Debug } from './components/Debug/Debug.svelte';
7
+ export { default as Collider } from './components/Colliders/Collider.svelte';
8
+ export { default as AutoColliders } from './components/Colliders/AutoColliders.svelte';
9
+ export { default as CollisionGroups } from './components/CollisionGroups/CollisionGroups.svelte';
10
+ export { default as BasicPlayerController } from './recipes/BasicPlayerController.svelte';
11
+ export type { AutoCollidersProperties, ColliderProperties, Boolean3Array, RigidBodyProperties, WorldProperties } from './types/components';
12
+ export type { CollisionGroupsBitMask, AutoCollidersShapes, ColliderEventDispatcher, ColliderShapes, RapierContext, RigidBodyEventDispatcher } from './types/types';
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ // hooks
2
+ export { useRapier } from './hooks/useRapier';
3
+ export { useCollisionGroups } from './hooks/useCollisionGroups';
4
+ export { useRigidBody } from './hooks/useRigidBody';
5
+ // components
6
+ export { default as World } from './components/World/World.svelte';
7
+ export { default as RigidBody } from './components/RigidBody/RigidBody.svelte';
8
+ export { default as Debug } from './components/Debug/Debug.svelte';
9
+ export { default as Collider } from './components/Colliders/Collider.svelte';
10
+ export { default as AutoColliders } from './components/Colliders/AutoColliders.svelte';
11
+ export { default as CollisionGroups } from './components/CollisionGroups/CollisionGroups.svelte';
12
+ // recipes
13
+ export { default as BasicPlayerController } from './recipes/BasicPlayerController.svelte';
@@ -0,0 +1,3 @@
1
+ import type { Position, Rotation, Scale, LookAt } from '@threlte/core';
2
+ import { Object3D } from 'three';
3
+ export declare const applyTransforms: (object: Object3D, position?: Position, rotation?: Rotation, scale?: Scale, lookAt?: LookAt) => void;
@@ -0,0 +1,17 @@
1
+ import { Object3D, Vector3 } from 'three';
2
+ import { positionToVector3 } from './positionToVector3';
3
+ import { rotationToEuler } from './rotationToEuler';
4
+ import { scaleToVector3 } from './scaleToVector3';
5
+ export const applyTransforms = (object, position, rotation, scale, lookAt) => {
6
+ object.position.copy(positionToVector3(position));
7
+ if (lookAt instanceof Object3D) {
8
+ object.lookAt(lookAt.getWorldPosition(new Vector3()));
9
+ }
10
+ else if (lookAt) {
11
+ object.lookAt(positionToVector3(lookAt));
12
+ }
13
+ else {
14
+ object.rotation.copy(rotationToEuler(rotation));
15
+ }
16
+ object.scale.copy(scaleToVector3(scale));
17
+ };
@@ -0,0 +1,16 @@
1
+ import { Collider, World, RigidBody } from '@dimforge/rapier3d-compat';
2
+ import { type Object3D } from 'three';
3
+ import type { AutoCollidersShapes } from '../types/types';
4
+ /**
5
+ *
6
+ * Creates collider descriptions including default translations
7
+ *
8
+ * @param object
9
+ * @param world
10
+ * @param friction
11
+ * @param restitution
12
+ * @param collidersType
13
+ * @param rigidBody
14
+ * @returns
15
+ */
16
+ export declare const createCollidersFromChildren: (object: Object3D, collidersType: AutoCollidersShapes, world: World, rigidBody?: RigidBody) => Collider[];