@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,94 @@
1
+ import { ActiveEvents, Collider, ColliderDesc, World, RigidBody } from '@dimforge/rapier3d-compat';
2
+ import { Mesh, Quaternion, Vector3 } from 'three';
3
+ /**
4
+ *
5
+ * Creates collider descriptions including default translations
6
+ *
7
+ * @param object
8
+ * @param world
9
+ * @param friction
10
+ * @param restitution
11
+ * @param collidersType
12
+ * @param rigidBody
13
+ * @returns
14
+ */
15
+ export const createCollidersFromChildren = (object, collidersType, world, rigidBody) => {
16
+ const colliders = [];
17
+ let description;
18
+ const offset = new Vector3();
19
+ /**
20
+ * Trying to find the parent RigidBody.
21
+ * If we find something, good. If not,
22
+ * the Colliders are created on the world positions
23
+ * of the meshes they resemble.
24
+ */
25
+ const rigidBodyWorldPos = new Vector3();
26
+ const rigidBodyWorldQuatInversed = new Quaternion();
27
+ object.traverseAncestors((child) => {
28
+ if (child.userData.isRigidBody) {
29
+ child.getWorldPosition(rigidBodyWorldPos);
30
+ child.getWorldQuaternion(rigidBodyWorldQuatInversed);
31
+ rigidBodyWorldQuatInversed.invert();
32
+ }
33
+ });
34
+ object.traverse((child) => {
35
+ if ('isMesh' in child) {
36
+ const { geometry } = child;
37
+ const worldPos = child.getWorldPosition(new Vector3());
38
+ const { x, y, z } = worldPos.sub(rigidBodyWorldPos);
39
+ const worldQuat = child.getWorldQuaternion(new Quaternion());
40
+ const { x: rx, y: ry, z: rz, w: rw } = worldQuat.clone().premultiply(rigidBodyWorldQuatInversed);
41
+ const scale = child.getWorldScale(new Vector3());
42
+ switch (collidersType) {
43
+ case 'cuboid':
44
+ {
45
+ geometry.computeBoundingBox();
46
+ const { boundingBox } = geometry;
47
+ const size = boundingBox.getSize(new Vector3());
48
+ boundingBox.getCenter(offset);
49
+ description = ColliderDesc.cuboid((size.x / 2) * scale.x, (size.y / 2) * scale.y, (size.z / 2) * scale.z);
50
+ }
51
+ break;
52
+ case 'ball':
53
+ {
54
+ geometry.computeBoundingSphere();
55
+ const { boundingSphere } = geometry;
56
+ const radius = boundingSphere.radius * scale.x;
57
+ offset.copy(boundingSphere.center);
58
+ description = ColliderDesc.ball(radius);
59
+ }
60
+ break;
61
+ case 'trimesh':
62
+ {
63
+ const g = geometry.clone().scale(scale.x, scale.y, scale.z);
64
+ description = ColliderDesc.trimesh(g.attributes.position.array, g.index?.array);
65
+ }
66
+ break;
67
+ case 'capsule':
68
+ {
69
+ geometry.computeBoundingBox();
70
+ const { boundingBox } = geometry;
71
+ const size = boundingBox.getSize(new Vector3());
72
+ boundingBox.getCenter(offset);
73
+ const radius = Math.max((size.x / 2) * scale.x, (size.z / 2) * scale.z);
74
+ description = ColliderDesc.capsule((size.y / 2) * scale.y - radius, radius);
75
+ }
76
+ break;
77
+ case 'convexHull':
78
+ // eslint-disable-next-line no-case-declarations
79
+ const g = geometry.clone().scale(scale.x, scale.y, scale.z);
80
+ {
81
+ description = ColliderDesc.convexHull(g.attributes.position.array);
82
+ }
83
+ break;
84
+ }
85
+ description
86
+ .setTranslation(x + offset.x, y + offset.y, z + offset.z)
87
+ .setRotation({ x: rx, y: ry, z: rz, w: rw })
88
+ .setActiveEvents(ActiveEvents.COLLISION_EVENTS);
89
+ const collider = world.createCollider(description, rigidBody);
90
+ colliders.push(collider);
91
+ }
92
+ });
93
+ return colliders;
94
+ };
@@ -0,0 +1,16 @@
1
+ import type { Collider, RigidBody } from '@dimforge/rapier3d-compat';
2
+ import RAPIER from '@dimforge/rapier3d-compat';
3
+ import type { Object3D } from 'three';
4
+ import type { ColliderEventDispatcher, ColliderEventDispatchers, RigidBodyEventDispatcher, RigidBodyEventDispatchers } from '../types/types';
5
+ 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) => {
6
+ rapier: typeof RAPIER;
7
+ world: RAPIER.World;
8
+ colliderObjects: Map<number, Object3D<import("three").Event>>;
9
+ rigidBodyObjects: Map<number, Object3D<import("three").Event>>;
10
+ rigidBodyEventDispatchers: RigidBodyEventDispatchers;
11
+ colliderEventDispatchers: ColliderEventDispatchers;
12
+ addColliderToContext: (collider: Collider, object: Object3D, eventDispatcher: ColliderEventDispatcher) => void;
13
+ removeColliderFromContext: (collider: Collider) => void;
14
+ addRigidBodyToContext: (rigidBody: RigidBody, object: Object3D, eventDispatcher: RigidBodyEventDispatcher) => void;
15
+ removeRigidBodyFromContext: (rigidBody: RigidBody) => void;
16
+ };
@@ -0,0 +1,56 @@
1
+ import RAPIER from '@dimforge/rapier3d-compat';
2
+ export const createRapierContext = (...args) => {
3
+ const world = new RAPIER.World(...args);
4
+ const colliderObjects = new Map();
5
+ const rigidBodyObjects = new Map();
6
+ const rigidBodyEventDispatchers = new Map();
7
+ const colliderEventDispatchers = new Map();
8
+ /**
9
+ * Adds a collider to the context
10
+ * @param collider
11
+ * @param object
12
+ * @param eventDispatcher
13
+ */
14
+ const addColliderToContext = (collider, object, eventDispatcher) => {
15
+ colliderObjects.set(collider.handle, object);
16
+ colliderEventDispatchers.set(collider.handle, eventDispatcher);
17
+ };
18
+ /**
19
+ * Removes the collider from the context
20
+ * @param collider
21
+ */
22
+ const removeColliderFromContext = (collider) => {
23
+ colliderObjects.delete(collider.handle);
24
+ colliderEventDispatchers.delete(collider.handle);
25
+ };
26
+ /**
27
+ * Adds a RigidBody to the context
28
+ * @param rigidBody
29
+ * @param object
30
+ * @param eventDispatcher
31
+ */
32
+ const addRigidBodyToContext = (rigidBody, object, eventDispatcher) => {
33
+ rigidBodyObjects.set(rigidBody.handle, object);
34
+ rigidBodyEventDispatchers.set(rigidBody.handle, eventDispatcher);
35
+ };
36
+ /**
37
+ * Removes the RigidBody from the context
38
+ * @param rigidBody
39
+ */
40
+ const removeRigidBodyFromContext = (rigidBody) => {
41
+ rigidBodyObjects.delete(rigidBody.handle);
42
+ rigidBodyEventDispatchers.delete(rigidBody.handle);
43
+ };
44
+ return {
45
+ rapier: RAPIER,
46
+ world,
47
+ colliderObjects,
48
+ rigidBodyObjects,
49
+ rigidBodyEventDispatchers,
50
+ colliderEventDispatchers,
51
+ addColliderToContext,
52
+ removeColliderFromContext,
53
+ addRigidBodyToContext,
54
+ removeRigidBodyFromContext
55
+ };
56
+ };
@@ -0,0 +1,41 @@
1
+ import { Euler, Object3D, Quaternion, Vector3 } from 'three';
2
+ /**
3
+ * Get the world position of an object.
4
+ * If no target is provided, a globally used
5
+ * temporary Vector3 is used.
6
+ *
7
+ * @param object
8
+ * @param target
9
+ * @returns
10
+ */
11
+ export declare const getWorldPosition: (object: Object3D, target?: Vector3) => Vector3;
12
+ /**
13
+ * Get the world quaternion of an object.
14
+ * If no target is provided, a globally used
15
+ * temporary Quaternion is used.
16
+ *
17
+ * @param object
18
+ * @param target
19
+ * @returns
20
+ */
21
+ export declare const getWorldQuaternion: (object: Object3D, target?: Quaternion) => Quaternion;
22
+ /**
23
+ * Get the world rotation of an object.
24
+ * If no target is provided, a globally used
25
+ * temporary Euler is used.
26
+ *
27
+ * @param object
28
+ * @param target
29
+ * @returns
30
+ */
31
+ export declare const getWorldRotation: (object: Object3D, target?: Euler) => Euler;
32
+ /**
33
+ * Get the world scale of an object.
34
+ * If no target is provided, a globally used
35
+ * temporary Vector3 is used.
36
+ *
37
+ * @param object
38
+ * @param target
39
+ * @returns
40
+ */
41
+ export declare const getWorldScale: (object: Object3D, target?: Vector3) => Vector3;
@@ -0,0 +1,55 @@
1
+ import { Euler, Object3D, Quaternion, Vector3 } from 'three';
2
+ const tempVector3 = new Vector3();
3
+ const tempQuaternion = new Quaternion();
4
+ const tempEuler = new Euler();
5
+ /**
6
+ * Get the world position of an object.
7
+ * If no target is provided, a globally used
8
+ * temporary Vector3 is used.
9
+ *
10
+ * @param object
11
+ * @param target
12
+ * @returns
13
+ */
14
+ export const getWorldPosition = (object, target) => {
15
+ return object.getWorldPosition(target ?? tempVector3);
16
+ };
17
+ /**
18
+ * Get the world quaternion of an object.
19
+ * If no target is provided, a globally used
20
+ * temporary Quaternion is used.
21
+ *
22
+ * @param object
23
+ * @param target
24
+ * @returns
25
+ */
26
+ export const getWorldQuaternion = (object, target) => {
27
+ return object.getWorldQuaternion(target ?? tempQuaternion);
28
+ };
29
+ /**
30
+ * Get the world rotation of an object.
31
+ * If no target is provided, a globally used
32
+ * temporary Euler is used.
33
+ *
34
+ * @param object
35
+ * @param target
36
+ * @returns
37
+ */
38
+ export const getWorldRotation = (object, target) => {
39
+ object.getWorldQuaternion(tempQuaternion);
40
+ return target
41
+ ? target.setFromQuaternion(tempQuaternion)
42
+ : tempEuler.setFromQuaternion(tempQuaternion);
43
+ };
44
+ /**
45
+ * Get the world scale of an object.
46
+ * If no target is provided, a globally used
47
+ * temporary Vector3 is used.
48
+ *
49
+ * @param object
50
+ * @param target
51
+ * @returns
52
+ */
53
+ export const getWorldScale = (object, target) => {
54
+ return object.getWorldScale(target ?? tempVector3);
55
+ };
@@ -0,0 +1,3 @@
1
+ import { RigidBodyType } from '@dimforge/rapier3d-compat';
2
+ export declare type RigidBodyTypeString = 'fixed' | 'dynamic' | 'kinematicPosition' | 'kinematicVelocity';
3
+ export declare const parseRigidBodyType: (type: RigidBodyTypeString) => RigidBodyType;
@@ -0,0 +1,10 @@
1
+ import { RigidBodyType } from '@dimforge/rapier3d-compat';
2
+ const rigidBodyTypeMap = {
3
+ dynamic: RigidBodyType.Dynamic,
4
+ fixed: RigidBodyType.Fixed,
5
+ kinematicPosition: RigidBodyType.KinematicPositionBased,
6
+ kinematicVelocity: RigidBodyType.KinematicVelocityBased
7
+ };
8
+ export const parseRigidBodyType = (type) => {
9
+ return rigidBodyTypeMap[type];
10
+ };
@@ -0,0 +1,3 @@
1
+ import type { Position } from '@threlte/core';
2
+ import { Vector3 } from 'three';
3
+ export declare const positionToVector3: (position?: Position, v3?: Vector3) => Vector3;
@@ -0,0 +1,8 @@
1
+ import { Vector3 } from 'three';
2
+ export const positionToVector3 = (position, v3) => {
3
+ if (v3) {
4
+ v3.set(position?.x ?? 0, position?.y ?? 0, position?.z ?? 0);
5
+ return v3;
6
+ }
7
+ return new Vector3(position?.x ?? 0, position?.y ?? 0, position?.z ?? 0);
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { Rotation } from '@threlte/core';
2
+ import { Euler } from 'three';
3
+ export declare const rotationToEuler: (rotation?: Rotation, euler?: Euler) => Euler;
@@ -0,0 +1,8 @@
1
+ import { Euler } from 'three';
2
+ export const rotationToEuler = (rotation, euler) => {
3
+ if (euler) {
4
+ euler.set(rotation?.x ?? 0, rotation?.y ?? 0, rotation?.z ?? 0);
5
+ return euler;
6
+ }
7
+ return new Euler(rotation?.x ?? 0, rotation?.y ?? 0, rotation?.z ?? 0);
8
+ };
@@ -0,0 +1,3 @@
1
+ import type { Rotation } from '@threlte/core';
2
+ import { Quaternion } from 'three';
3
+ export declare const rotationToQuaternion: (rotation?: Rotation, quaternion?: Quaternion) => Quaternion;
@@ -0,0 +1,10 @@
1
+ import { Quaternion } from 'three';
2
+ import { rotationToEuler } from './rotationToEuler';
3
+ export const rotationToQuaternion = (rotation, quaternion) => {
4
+ const euler = rotationToEuler(rotation);
5
+ if (quaternion) {
6
+ quaternion.setFromEuler(euler);
7
+ return quaternion;
8
+ }
9
+ return new Quaternion().setFromEuler(euler);
10
+ };
@@ -0,0 +1,5 @@
1
+ import type { ColliderDesc } from '@dimforge/rapier3d-compat';
2
+ import type { Vector3 } from 'three';
3
+ import type { ColliderShapes } from '../types/types';
4
+ export declare const scaleVertices: (vertices: ArrayLike<number>, scale: Vector3) => number[];
5
+ export declare const scaleColliderArgs: <Shape extends ColliderShapes>(shape: Shape, args: Parameters<(typeof ColliderDesc)[Shape]>, scale: Vector3) => Parameters<(typeof ColliderDesc)[Shape]>;
@@ -0,0 +1,25 @@
1
+ export const scaleVertices = (vertices, scale) => {
2
+ const scaledVerts = Array.from(vertices);
3
+ for (let i = 0; i < vertices.length / 3; i++) {
4
+ scaledVerts[i * 3] *= scale.x;
5
+ scaledVerts[i * 3 + 1] *= scale.y;
6
+ scaledVerts[i * 3 + 2] *= scale.z;
7
+ }
8
+ return scaledVerts;
9
+ };
10
+ export const scaleColliderArgs = (shape, args, scale) => {
11
+ // Heightfield only scales the last arg
12
+ const newArgs = args.slice();
13
+ if (shape === 'heightfield') {
14
+ ;
15
+ newArgs[3] *= scale.x;
16
+ return newArgs;
17
+ }
18
+ // Trimesh and convex scale the vertices
19
+ if (shape === 'trimesh' || shape === 'convexHull') {
20
+ newArgs[0] = new Float32Array(scaleVertices(newArgs[0], scale));
21
+ return newArgs;
22
+ }
23
+ const scaleArray = [scale.x, scale.y, scale.z];
24
+ return newArgs.map((arg, index) => scaleArray[index] * arg);
25
+ };
@@ -0,0 +1,3 @@
1
+ import type { Scale } from '@threlte/core';
2
+ import { Vector3 } from 'three';
3
+ export declare const scaleToVector3: (scale?: Scale, v3?: Vector3) => Vector3;
@@ -0,0 +1,16 @@
1
+ import { Vector3 } from 'three';
2
+ export const scaleToVector3 = (scale, v3) => {
3
+ if (v3) {
4
+ if (typeof scale === 'number') {
5
+ v3.set(scale, scale, scale);
6
+ }
7
+ else {
8
+ v3.set(scale?.x ?? 1, scale?.y ?? 1, scale?.z ?? 1);
9
+ }
10
+ return v3;
11
+ }
12
+ if (typeof scale === 'number') {
13
+ return new Vector3(scale, scale, scale);
14
+ }
15
+ return new Vector3(scale?.x ?? 1, scale?.y ?? 1, scale?.z ?? 1);
16
+ };
@@ -0,0 +1,129 @@
1
+ <script>import { Group, useFrame, useThrelte } from '@threlte/core';
2
+ import { createEventDispatcher } from 'svelte';
3
+ import { Vector2, Vector3 } from 'three';
4
+ import Collider from '../components/Colliders/Collider.svelte';
5
+ import CollisionGroups from '../components/CollisionGroups/CollisionGroups.svelte';
6
+ import RigidBody from '../components/RigidBody/RigidBody.svelte';
7
+ export let position = undefined;
8
+ export let height = 1.7;
9
+ export let radius = 0.3;
10
+ export let speed = 1;
11
+ export let jumpStrength = 3;
12
+ export let playerCollisionGroups = [0];
13
+ export let groundCollisionGroups = [15];
14
+ let rigidBody;
15
+ const { renderer } = useThrelte();
16
+ if (!renderer)
17
+ throw new Error();
18
+ const keys = {
19
+ up: false,
20
+ down: false,
21
+ left: false,
22
+ right: false
23
+ };
24
+ const t = new Vector3();
25
+ const t2 = new Vector2();
26
+ const dispatch = createEventDispatcher();
27
+ let grounded = false;
28
+ let groundsSensored = 0;
29
+ $: {
30
+ if (groundsSensored === 0)
31
+ grounded = false;
32
+ else
33
+ grounded = true;
34
+ }
35
+ $: grounded ? dispatch('groundenter') : dispatch('groundexit');
36
+ useFrame(() => {
37
+ if (!rigidBody)
38
+ return;
39
+ t.fromArray([0, 0, 0]);
40
+ if (keys.down)
41
+ t.x += 1;
42
+ if (keys.up)
43
+ t.x -= 1;
44
+ if (keys.left)
45
+ t.z += 1;
46
+ if (keys.right)
47
+ t.z -= 1;
48
+ const l = t.length();
49
+ const xzLength = t2.set(t.x, t.z).length();
50
+ if (l > 0)
51
+ t.divideScalar(l).multiplyScalar(speed);
52
+ if (xzLength > 0) {
53
+ rigidBody.resetForces(true);
54
+ rigidBody.resetTorques(true);
55
+ }
56
+ const linVel = rigidBody.linvel();
57
+ t.y = linVel.y;
58
+ rigidBody.setLinvel(t, true);
59
+ });
60
+ const onKeyDown = (e) => {
61
+ switch (e.key) {
62
+ case 'ArrowDown':
63
+ keys.down = true;
64
+ break;
65
+ case 'ArrowUp':
66
+ keys.up = true;
67
+ break;
68
+ case 'ArrowLeft':
69
+ keys.left = true;
70
+ break;
71
+ case 'ArrowRight':
72
+ keys.right = true;
73
+ break;
74
+ case ' ':
75
+ if (!rigidBody || !grounded)
76
+ break;
77
+ rigidBody.applyImpulse({ x: 0, y: jumpStrength, z: 0 }, true);
78
+ default:
79
+ break;
80
+ }
81
+ };
82
+ const onKeyUp = (e) => {
83
+ switch (e.key) {
84
+ case 'ArrowDown':
85
+ keys.down = false;
86
+ break;
87
+ case 'ArrowUp':
88
+ keys.up = false;
89
+ break;
90
+ case 'ArrowLeft':
91
+ keys.left = false;
92
+ break;
93
+ case 'ArrowRight':
94
+ keys.right = false;
95
+ break;
96
+ default:
97
+ break;
98
+ }
99
+ };
100
+ </script>
101
+
102
+ <svelte:window on:keydown|preventDefault={onKeyDown} on:keyup|preventDefault={onKeyUp} />
103
+
104
+ <RigidBody
105
+ dominance={127}
106
+ enabledRotations={[false, false, false]}
107
+ bind:rigidBody
108
+ {position}
109
+ type={'dynamic'}
110
+ >
111
+ <CollisionGroups groups={playerCollisionGroups}>
112
+ <Collider shape={'capsule'} args={[height / 2 - radius, radius]} />
113
+ </CollisionGroups>
114
+
115
+ <CollisionGroups groups={groundCollisionGroups}>
116
+ <Collider
117
+ sensor
118
+ on:sensorenter={() => (groundsSensored += 1)}
119
+ on:sensorexit={() => (groundsSensored -= 1)}
120
+ shape={'ball'}
121
+ args={[radius * 1.2]}
122
+ position={{ y: -height / 2 + radius }}
123
+ />
124
+ </CollisionGroups>
125
+
126
+ <Group position={{ y: -height / 2 }}>
127
+ <slot />
128
+ </Group>
129
+ </RigidBody>
@@ -0,0 +1,29 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ import { type Position } from '@threlte/core';
3
+ import type { CollisionGroupsBitMask } from '../types/types';
4
+ declare const __propDef: {
5
+ props: {
6
+ position?: Position | undefined;
7
+ height?: number | undefined;
8
+ radius?: number | undefined;
9
+ speed?: number | undefined;
10
+ jumpStrength?: number | undefined;
11
+ playerCollisionGroups?: CollisionGroupsBitMask | undefined;
12
+ groundCollisionGroups?: CollisionGroupsBitMask | undefined;
13
+ };
14
+ events: {
15
+ groundenter: CustomEvent<void>;
16
+ groundexit: CustomEvent<void>;
17
+ } & {
18
+ [evt: string]: CustomEvent<any>;
19
+ };
20
+ slots: {
21
+ default: {};
22
+ };
23
+ };
24
+ export declare type BasicPlayerControllerProps = typeof __propDef.props;
25
+ export declare type BasicPlayerControllerEvents = typeof __propDef.events;
26
+ export declare type BasicPlayerControllerSlots = typeof __propDef.slots;
27
+ export default class BasicPlayerController extends SvelteComponentTyped<BasicPlayerControllerProps, BasicPlayerControllerEvents, BasicPlayerControllerSlots> {
28
+ }
29
+ export {};
@@ -0,0 +1,131 @@
1
+ import type { CoefficientCombineRule, ColliderDesc } from '@dimforge/rapier3d-compat';
2
+ import type { RawBroadPhase, RawCCDSolver, RawColliderSet, RawDebugRenderPipeline, RawImpulseJointSet, RawIntegrationParameters, RawIslandManager, RawMultibodyJointSet, RawNarrowPhase, RawPhysicsPipeline, RawQueryPipeline, RawRigidBodySet, RawSerializationPipeline } from '@dimforge/rapier3d-compat/raw';
3
+ import type { Position, Rotation, TransformableObjectProperties } from '@threlte/core';
4
+ import type { RigidBodyTypeString } from '../lib/parseRigidBodyType';
5
+ import type { AutoCollidersShapes, ColliderShapes, CollisionGroupsBitMask } from './types';
6
+ export declare type Boolean3Array = [x: boolean, y: boolean, z: boolean];
7
+ export declare type Vector3Array = [x: number, y: number, z: number];
8
+ export declare type RigidBodyProperties = Omit<TransformableObjectProperties, 'object'> & {
9
+ /**
10
+ * Specify the type of this rigid body
11
+ */
12
+ type?: RigidBodyTypeString;
13
+ /** Whether or not this body can sleep.
14
+ * default: true
15
+ */
16
+ canSleep?: boolean;
17
+ /** The linear velocity of this body.
18
+ * default: zero velocity
19
+ */
20
+ linearVelocity?: Position;
21
+ /** The angular velocity of this body.
22
+ * Default: zero velocity.
23
+ */
24
+ angularVelocity?: Rotation;
25
+ /**
26
+ * The scaling factor applied to the gravity affecting the rigid-body.
27
+ * Default: 1.0
28
+ */
29
+ gravityScale?: number;
30
+ /**
31
+ * Whether or not Continous Collision Detection is enabled for this rigid-body.
32
+ * https://rapier.rs/docs/user_guides/javascript/rigid_bodies#continuous-collision-detection
33
+ * @default false
34
+ */
35
+ ccd?: boolean;
36
+ /**
37
+ * Locks all rotations that would have resulted from forces on the created rigid-body.
38
+ */
39
+ lockRotations?: boolean;
40
+ /**
41
+ * Locks all translations that would have resulted from forces on the created rigid-body.
42
+ */
43
+ lockTranslations?: boolean;
44
+ /**
45
+ * Allow rotation of this rigid-body only along specific axes.
46
+ */
47
+ enabledRotations?: Boolean3Array;
48
+ /**
49
+ * Allow rotation of this rigid-body only along specific axes.
50
+ */
51
+ enabledTranslations?: Boolean3Array;
52
+ /**
53
+ * Dominance is a non-realistic, but sometimes useful, feature.
54
+ * It can be used to make one rigid-body immune to forces
55
+ * originating from contacts with some other bodies.
56
+ *
57
+ * Number in the range -127 to 127, default is 0
58
+ */
59
+ dominance?: number;
60
+ };
61
+ export declare type ColliderProperties<Shape extends ColliderShapes> = Omit<TransformableObjectProperties, 'object'> & {
62
+ shape: Shape;
63
+ /**
64
+ * Arguments to pass to the collider specific to shape
65
+ */
66
+ args: Parameters<typeof ColliderDesc[Shape]>;
67
+ /**
68
+ * The mass of this rigid body.
69
+ * The mass and density is automatically calculated based on the shape of the collider.
70
+ * Generally, it's not recommended to adjust the mass properties as it could lead to
71
+ * unexpected behaviors.
72
+ * More info https://rapier.rs/docs/user_guides/javascript/colliders#mass-properties
73
+ */
74
+ mass?: number;
75
+ /**
76
+ * The center of mass of this rigid body
77
+ */
78
+ centerOfMass?: Position;
79
+ /**
80
+ * Principal angular inertia of this rigid body
81
+ */
82
+ principalAngularInertia?: Position;
83
+ /**
84
+ * Restitution controls how elastic (aka. bouncy) a contact is. Le elasticity of a contact is controlled by the restitution coefficient
85
+ */
86
+ restitution?: number;
87
+ /**
88
+ * What happens when two bodies meet. See https://rapier.rs/docs/user_guides/javascript/colliders#friction.
89
+ */
90
+ restitutionCombineRule?: CoefficientCombineRule;
91
+ /**
92
+ * Friction is a force that opposes the relative tangential motion between two rigid-bodies with colliders in contact.
93
+ * A friction coefficient of 0 implies no friction at all (completely sliding contact) and a coefficient
94
+ * greater or equal to 1 implies a very strong friction. Values greater than 1 are allowed.
95
+ */
96
+ friction?: number;
97
+ /**
98
+ * What happens when two bodies meet. See https://rapier.rs/docs/user_guides/javascript/colliders#friction.
99
+ */
100
+ frictionCombineRule?: CoefficientCombineRule;
101
+ /**
102
+ * A sensor does not participate in physics simulation and is
103
+ * used as a trigger e.g. to check whether another RigidBody
104
+ * entered an area.
105
+ */
106
+ sensor?: boolean;
107
+ };
108
+ export declare type AutoCollidersProperties = Omit<ColliderProperties<AutoCollidersShapes>, 'args'>;
109
+ export declare type InnerWorldProperties = {
110
+ gravity?: Position;
111
+ rawIntegrationParameters?: RawIntegrationParameters;
112
+ rawIslands?: RawIslandManager;
113
+ rawBroadPhase?: RawBroadPhase;
114
+ rawNarrowPhase?: RawNarrowPhase;
115
+ rawBodies?: RawRigidBodySet;
116
+ rawColliders?: RawColliderSet;
117
+ rawImpulseJoints?: RawImpulseJointSet;
118
+ rawMultibodyJoints?: RawMultibodyJointSet;
119
+ rawCCDSolver?: RawCCDSolver;
120
+ rawQueryPipeline?: RawQueryPipeline;
121
+ rawPhysicsPipeline?: RawPhysicsPipeline;
122
+ rawSerializationPipeline?: RawSerializationPipeline;
123
+ rawDebugRenderPipeline?: RawDebugRenderPipeline;
124
+ };
125
+ export declare type WorldProperties = InnerWorldProperties;
126
+ export declare type CollisionGroupsProperties = {
127
+ groups: CollisionGroupsBitMask;
128
+ } | {
129
+ filter: CollisionGroupsBitMask;
130
+ memberships: CollisionGroupsBitMask;
131
+ };