From 7afee4b7fdf4b1db4dcc9de9a4107f3b2cd96a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CIsaac?= Date: Mon, 6 Jun 2022 23:27:51 +1000 Subject: [PATCH] Add useBody hook that infers shape with three-to-cannon --- .../src/demos/demo-ShapeInference.tsx | 198 ++++++++++++++++++ .../src/demos/index.ts | 1 + packages/react-three-cannon/package.json | 3 +- packages/react-three-cannon/src/hooks.ts | 57 +++-- .../react-three-cannon/src/three-to-cannon.ts | 121 +++++++++++ packages/react-three-cannon/tsconfig.json | 2 +- yarn.lock | 112 ++++++++-- 7 files changed, 455 insertions(+), 39 deletions(-) create mode 100644 packages/react-three-cannon-examples/src/demos/demo-ShapeInference.tsx create mode 100644 packages/react-three-cannon/src/three-to-cannon.ts diff --git a/packages/react-three-cannon-examples/src/demos/demo-ShapeInference.tsx b/packages/react-three-cannon-examples/src/demos/demo-ShapeInference.tsx new file mode 100644 index 00000000..20eb6e18 --- /dev/null +++ b/packages/react-three-cannon-examples/src/demos/demo-ShapeInference.tsx @@ -0,0 +1,198 @@ +import type { BodyProps, PlaneProps } from '@react-three/cannon' +import { Debug, Physics, useBody, usePlane } from '@react-three/cannon' +import { OrbitControls } from '@react-three/drei' +import { Canvas } from '@react-three/fiber' +import { Suspense, useRef } from 'react' +import type { Group, Mesh } from 'three' + +function BoundingSphere(props: BodyProps) { + const [ref] = useBody( + () => ({ + mass: 1, + ...props, + }), + useRef(null), + { type: 'Sphere' }, + ) + + return ( + + + + + ) +} + +function Sphere(props: BodyProps) { + const [ref] = useBody( + () => ({ + mass: 1, + ...props, + }), + useRef(null), + ) + + return ( + + + + + ) +} + +function BoundingBox(props: BodyProps) { + const [ref] = useBody( + () => ({ + mass: 1, + ...props, + }), + useRef(null), + { type: 'Box' }, + ) + + return ( + + + + + ) +} + +function Box(props: BodyProps) { + const [ref] = useBody( + () => ({ + mass: 1, + ...props, + }), + useRef(null), + ) + + return ( + + + + + ) +} + +function BoundingCylinder(props: BodyProps) { + const [ref] = useBody( + () => ({ + mass: 1, + ...props, + }), + useRef(null), + { type: 'Cylinder' }, + ) + + return ( + + + + + ) +} + +function Cylinder(props: BodyProps) { + const [ref] = useBody( + () => ({ + mass: 1, + ...props, + }), + useRef(null), + ) + + return ( + + + + + ) +} + +function ConvexPolyhedron(props: BodyProps) { + const [ref] = useBody( + () => ({ + mass: 1, + ...props, + }), + useRef(null), + { type: 'ConvexPolyhedron' }, + ) + + return ( + + + + + + + + + + + ) +} + +function Trimesh(props: BodyProps) { + const [ref] = useBody( + () => ({ + mass: 1, + ...props, + }), + useRef(null), + { type: 'Trimesh' }, + ) + + return ( + + + + + ) +} + +function Plane(props: PlaneProps) { + usePlane(() => ({ type: 'Static', ...props })) + return null +} + +function ShapeInference() { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export default ShapeInference diff --git a/packages/react-three-cannon-examples/src/demos/index.ts b/packages/react-three-cannon-examples/src/demos/index.ts index 0d21f70a..d6ab36d0 100644 --- a/packages/react-three-cannon-examples/src/demos/index.ts +++ b/packages/react-three-cannon-examples/src/demos/index.ts @@ -12,6 +12,7 @@ const fileDemos = [ 'KinematicCube', 'Paused', 'SphereDebug', + 'ShapeInference', 'Triggers', 'Trimesh', ] as const diff --git a/packages/react-three-cannon/package.json b/packages/react-three-cannon/package.json index 89970140..a22f5a4b 100644 --- a/packages/react-three-cannon/package.json +++ b/packages/react-three-cannon/package.json @@ -32,7 +32,8 @@ "dependencies": { "@pmndrs/cannon-worker-api": "^2.1.0", "cannon-es": "^0.19.0", - "cannon-es-debugger": "^1.0.0" + "cannon-es-debugger": "^1.0.0", + "three-to-cannon": "^4.1.0" }, "devDependencies": { "@babel/core": "^7.17.8", diff --git a/packages/react-three-cannon/src/hooks.ts b/packages/react-three-cannon/src/hooks.ts index 7acaba89..ef5243b3 100644 --- a/packages/react-three-cannon/src/hooks.ts +++ b/packages/react-three-cannon/src/hooks.ts @@ -45,6 +45,8 @@ import { DynamicDrawUsage, Euler, InstancedMesh, MathUtils, Object3D, Quaternion import { useDebugContext } from './debug-context' import type { CannonEvents } from './physics-context' import { usePhysicsContext } from './physics-context' +import type { ThreeToCannonOptions } from './three-to-cannon' +import { threeToCannon } from './three-to-cannon' export type AtomicApi = { set: (value: AtomicProps[K]) => void @@ -153,12 +155,13 @@ function setupCollision( type GetByIndex = (index: number) => T type ArgFn = (args: T) => unknown[] -function useBody, O extends Object3D>( - type: BodyShapeType, +function useBodyCommon, O extends Object3D>( + type: BodyShapeType | null, fn: GetByIndex, argsFn: ArgFn, fwdRef: Ref = null, deps: DependencyList = [], + threeToCannonOptions?: ThreeToCannonOptions, ): Api { const ref = useForwardedRef(fwdRef) @@ -184,23 +187,35 @@ function useBody, O extends Object3D>( ? new Array(objectCount).fill(0).map((_, i) => `${object.uuid}/${i}`) : [object.uuid] - const props: (B & { args: unknown })[] = + let shapeType: BodyShapeType = type || 'Particle' + let inferredProps: BodyProps = {} + + if (!type) { + const result = threeToCannon(object, threeToCannonOptions) + + if (result) { + shapeType = result.shape + inferredProps = result.props + } + } + + const props = object instanceof InstancedMesh ? uuid.map((id, i) => { - const props = fn(i) + const props = { ...inferredProps, ...fn(i) } prepare(temp, props) object.setMatrixAt(i, temp.matrix) object.instanceMatrix.needsUpdate = true refs[id] = object - debugApi?.add(id, props, type) + debugApi?.add(id, props, shapeType) setupCollision(events, props, id) return { ...props, args: argsFn(props.args) } }) : uuid.map((id, i) => { - const props = fn(i) + const props = { ...inferredProps, ...fn(i) } prepare(object, props) refs[id] = object - debugApi?.add(id, props, type) + debugApi?.add(id, props, shapeType) setupCollision(events, props, id) return { ...props, args: argsFn(props.args) } }) @@ -210,7 +225,7 @@ function useBody, O extends Object3D>( props: props.map(({ onCollide, onCollideBegin, onCollideEnd, ...serializableProps }) => { return { onCollide: Boolean(onCollide), ...serializableProps } }), - type, + type: shapeType, uuid, }) return () => { @@ -366,44 +381,52 @@ function makeTriplet(v: Vector3 | Triplet): Triplet { return v instanceof Vector3 ? [v.x, v.y, v.z] : v } +export function useBody( + fn: GetByIndex, + fwdRef: Ref = null, + threeToCannonOptions?: ThreeToCannonOptions, + deps?: DependencyList, +) { + return useBodyCommon(null, fn, (args) => args || [], fwdRef, deps, threeToCannonOptions) +} export function usePlane( fn: GetByIndex, fwdRef?: Ref, deps?: DependencyList, ) { - return useBody('Plane', fn, () => [], fwdRef, deps) + return useBodyCommon('Plane', fn, () => [], fwdRef, deps) } export function useBox(fn: GetByIndex, fwdRef?: Ref, deps?: DependencyList) { const defaultBoxArgs: Triplet = [1, 1, 1] - return useBody('Box', fn, (args = defaultBoxArgs): Triplet => args, fwdRef, deps) + return useBodyCommon('Box', fn, (args = defaultBoxArgs): Triplet => args, fwdRef, deps) } export function useCylinder( fn: GetByIndex, fwdRef?: Ref, deps?: DependencyList, ) { - return useBody('Cylinder', fn, (args = [] as []) => args, fwdRef, deps) + return useBodyCommon('Cylinder', fn, (args = [] as []) => args, fwdRef, deps) } export function useHeightfield( fn: GetByIndex, fwdRef?: Ref, deps?: DependencyList, ) { - return useBody('Heightfield', fn, (args) => args, fwdRef, deps) + return useBodyCommon('Heightfield', fn, (args) => args, fwdRef, deps) } export function useParticle( fn: GetByIndex, fwdRef?: Ref, deps?: DependencyList, ) { - return useBody('Particle', fn, () => [], fwdRef, deps) + return useBodyCommon('Particle', fn, () => [], fwdRef, deps) } export function useSphere( fn: GetByIndex, fwdRef?: Ref, deps?: DependencyList, ) { - return useBody( + return useBodyCommon( 'Sphere', fn, (args: SphereArgs = [1]): SphereArgs => { @@ -419,7 +442,7 @@ export function useTrimesh( fwdRef?: Ref, deps?: DependencyList, ) { - return useBody('Trimesh', fn, (args) => args, fwdRef, deps) + return useBodyCommon('Trimesh', fn, (args) => args, fwdRef, deps) } export function useConvexPolyhedron( @@ -427,7 +450,7 @@ export function useConvexPolyhedron( fwdRef?: Ref, deps?: DependencyList, ) { - return useBody( + return useBodyCommon( 'ConvexPolyhedron', fn, ([vertices, faces, normals, axes, boundingSphereRadius] = []): ConvexPolyhedronArgs => [ @@ -446,7 +469,7 @@ export function useCompoundBody( fwdRef?: Ref, deps?: DependencyList, ) { - return useBody('Compound', fn, (args) => args as unknown[], fwdRef, deps) + return useBodyCommon('Compound', fn, (args) => args as unknown[], fwdRef, deps) } type ConstraintApi = [ diff --git a/packages/react-three-cannon/src/three-to-cannon.ts b/packages/react-three-cannon/src/three-to-cannon.ts new file mode 100644 index 00000000..e43f8998 --- /dev/null +++ b/packages/react-three-cannon/src/three-to-cannon.ts @@ -0,0 +1,121 @@ +import type { + BodyProps, + BodyShapeType, + CompoundBodyProps, + ConvexPolyhedronArgs, + CylinderArgs, + SphereArgs, + TrimeshArgs, + Triplet, +} from '@pmndrs/cannon-worker-api' +import type { Quaternion as CQuaternion } from 'cannon-es' +import type { Object3D } from 'three' +import { Euler, Quaternion } from 'three' +import type { ConvexPolyhedronParameters, ShapeOptions, ShapeParameters, ShapeType } from 'three-to-cannon' +import { getShapeParameters } from 'three-to-cannon' + +type ShapeTypeString = `${ShapeType}` + +export type ThreeToCannonOptions = Omit & { + type?: ShapeTypeString +} + +export function threeToCannon( + object: Object3D, + options: ThreeToCannonOptions = {}, +): { props: BodyProps | CompoundBodyProps; shape: BodyShapeType } | null { + const result = getShapeParameters(object as never, { + ...options, + type: options?.type as ShapeType, + }) + + if (!result) { + return null + } + + const args = shapeParametersToBodyArgs(result) + + const boundingShapeTypes: ShapeTypeString[] = ['Box', 'Cylinder', 'Sphere'] + if (options.type && boundingShapeTypes.includes(options.type)) { + return { + props: { + shapes: [ + { + args, + position: result.offset ? [result.offset.x, result.offset.y, result.offset.z] : undefined, + rotation: cannonQuaternionToEuler(result.orientation), + type: result.type, + }, + ], + }, + shape: 'Compound', + } + } + + return { + props: { + args, + }, + shape: result.type, + } +} + +function shapeParametersToBodyArgs( + parameters: ShapeParameters, +): Triplet | SphereArgs | CylinderArgs | ConvexPolyhedronArgs | TrimeshArgs { + if (parameters.type === 'Box') { + return createBoxArgs(parameters as ShapeParameters) + } else if (parameters.type === 'Sphere') { + return createSphereArgs(parameters as ShapeParameters) + } else if (parameters.type === 'Cylinder') { + return createCylinderArgs(parameters as ShapeParameters) + } else if (parameters.type === 'ConvexPolyhedron') { + return createConvexPolyhedronArgs(parameters as ShapeParameters) + } else { + return createTrimeshArgs(parameters as ShapeParameters) + } +} + +function cannonQuaternionToEuler(q?: CQuaternion): number[] | undefined { + return q ? new Euler().setFromQuaternion(new Quaternion().fromArray(q.toArray())).toArray() : undefined +} + +function createBoxArgs(parameters: ShapeParameters): Triplet { + const { + params: { x, y, z }, + } = parameters + return [x, y, z].map((v) => v * 2) as Triplet // box props take extents, not half extents +} + +function createSphereArgs(parameters: ShapeParameters): SphereArgs { + const { + params: { radius }, + } = parameters + return [radius] +} + +function createCylinderArgs(parameters: ShapeParameters): CylinderArgs { + const { + params: { radiusTop, radiusBottom, height, segments }, + } = parameters + return [radiusTop, radiusBottom, height, segments] +} + +function createConvexPolyhedronArgs(parameters: ShapeParameters): ConvexPolyhedronArgs { + const { faces, vertices: verticesArray }: ConvexPolyhedronParameters = parameters.params + + const vertices: Triplet[] = [] + for (let i = 0; i < verticesArray.length; i += 3) { + vertices.push([verticesArray[i], verticesArray[i + 1], verticesArray[i + 2]]) + } + + return [vertices, faces] +} + +function createTrimeshArgs(parameters: ShapeParameters): TrimeshArgs { + const { + params: { vertices, indices }, + } = parameters + + return [vertices, indices] +} diff --git a/packages/react-three-cannon/tsconfig.json b/packages/react-three-cannon/tsconfig.json index ab375723..b2d2e6b3 100644 --- a/packages/react-three-cannon/tsconfig.json +++ b/packages/react-three-cannon/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "baseUrl": "./src", + "baseUrl": ".", "declaration": true, "emitDeclarationOnly": true, "esModuleInterop": true, diff --git a/yarn.lock b/yarn.lock index cf89e663..a66403c8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1385,24 +1385,36 @@ "@types/react" "*" csstype "^3.0.2" +"@types/three@>=0.125.x": + version "0.141.0" + resolved "https://registry.yarnpkg.com/@types/three/-/three-0.141.0.tgz#d9d81a54b28ebc2a56931dfd4d9c54d25c20d6c8" + integrity sha512-OJdKDgTPVBUgc+s74DYoy4aLznbFFC38Xm4ElmU1YwGNgR7GGFVvFCX7lpVgOsT6S1zSJtGdajTsOYE8/xY9nA== + dependencies: + "@types/webxr" "*" + "@types/three@^0.139.0": version "0.139.0" - resolved "https://registry.npmjs.org/@types/three/-/three-0.139.0.tgz#69af1f0c52f8eea390f513e05478af1dd7f49e6f" + resolved "https://registry.yarnpkg.com/@types/three/-/three-0.139.0.tgz#69af1f0c52f8eea390f513e05478af1dd7f49e6f" integrity sha512-4V/jZhyq7Mv05coUzxL3bz8AuBOSi/1F0RY7ujisHTV0Amy/fnYJ+s7TSJ1/hXjZukSkpuFRgV+wvWUEMbsMbQ== +"@types/webxr@*": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@types/webxr/-/webxr-0.4.0.tgz#ad06c96a324293e0d5175d13dd5ded5931f90ba3" + integrity sha512-LQvrACV3Pj17GpkwHwXuTd733gfY+D7b9mKdrTmLdO7vo7P/o6209Qqtk63y/FCv/lspdmi0pWz6Qe/ull9kQg== + "@typescript-eslint/eslint-plugin@^5.17.0": - version "5.17.0" - resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.17.0.tgz#704eb4e75039000531255672bf1c85ee85cf1d67" - integrity sha512-qVstvQilEd89HJk3qcbKt/zZrfBZ+9h2ynpAGlWjWiizA7m/MtLT9RoX6gjtpE500vfIg8jogAkDzdCxbsFASQ== - dependencies: - "@typescript-eslint/scope-manager" "5.17.0" - "@typescript-eslint/type-utils" "5.17.0" - "@typescript-eslint/utils" "5.17.0" - debug "^4.3.2" + version "5.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.28.0.tgz#6204ac33bdd05ab27c7f77960f1023951115d403" + integrity sha512-DXVU6Cg29H2M6EybqSg2A+x8DgO9TCUBRp4QEXQHJceLS7ogVDP0g3Lkg/SZCqcvkAP/RruuQqK0gdlkgmhSUA== + dependencies: + "@typescript-eslint/scope-manager" "5.28.0" + "@typescript-eslint/type-utils" "5.28.0" + "@typescript-eslint/utils" "5.28.0" + debug "^4.3.4" functional-red-black-tree "^1.0.1" - ignore "^5.1.8" + ignore "^5.2.0" regexpp "^3.2.0" - semver "^7.3.5" + semver "^7.3.7" tsutils "^3.21.0" "@typescript-eslint/experimental-utils@^5.3.0": @@ -1430,13 +1442,21 @@ "@typescript-eslint/types" "5.17.0" "@typescript-eslint/visitor-keys" "5.17.0" -"@typescript-eslint/type-utils@5.17.0": - version "5.17.0" - resolved "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.17.0.tgz#1c4549d68c89877662224aabb29fbbebf5fc9672" - integrity sha512-3hU0RynUIlEuqMJA7dragb0/75gZmwNwFf/QJokWzPehTZousP/MNifVSgjxNcDCkM5HI2K22TjQWUmmHUINSg== +"@typescript-eslint/scope-manager@5.28.0": + version "5.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.28.0.tgz#ef9a5c68fecde72fd2ff8a84b9c120324826c1b9" + integrity sha512-LeBLTqF/he1Z+boRhSqnso6YrzcKMTQ8bO/YKEe+6+O/JGof9M0g3IJlIsqfrK/6K03MlFIlycbf1uQR1IjE+w== dependencies: - "@typescript-eslint/utils" "5.17.0" - debug "^4.3.2" + "@typescript-eslint/types" "5.28.0" + "@typescript-eslint/visitor-keys" "5.28.0" + +"@typescript-eslint/type-utils@5.28.0": + version "5.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.28.0.tgz#53ccc78fdcf0205ef544d843b84104c0e9c7ca8e" + integrity sha512-SyKjKh4CXPglueyC6ceAFytjYWMoPHMswPQae236zqe1YbhvCVQyIawesYywGiu98L9DwrxsBN69vGIVxJ4mQQ== + dependencies: + "@typescript-eslint/utils" "5.28.0" + debug "^4.3.4" tsutils "^3.21.0" "@typescript-eslint/types@5.17.0": @@ -1444,6 +1464,11 @@ resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.17.0.tgz#861ec9e669ffa2aa9b873dd4d28d9b1ce26d216f" integrity sha512-AgQ4rWzmCxOZLioFEjlzOI3Ch8giDWx8aUDxyNw9iOeCvD3GEYAB7dxWGQy4T/rPVe8iPmu73jPHuaSqcjKvxw== +"@typescript-eslint/types@5.28.0": + version "5.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.28.0.tgz#cffd9bcdce28db6daaa146e48a0be4387a6f4e9d" + integrity sha512-2OOm8ZTOQxqkPbf+DAo8oc16sDlVR5owgJfKheBkxBKg1vAfw2JsSofH9+16VPlN9PWtv8Wzhklkqw3k/zCVxA== + "@typescript-eslint/typescript-estree@5.17.0": version "5.17.0" resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.17.0.tgz#a7cba7dfc8f9cc2ac78c18584e684507df4f2488" @@ -1457,6 +1482,19 @@ semver "^7.3.5" tsutils "^3.21.0" +"@typescript-eslint/typescript-estree@5.28.0": + version "5.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.28.0.tgz#3487d158d091ca2772b285e67412ff6d9797d863" + integrity sha512-9GX+GfpV+F4hdTtYc6OV9ZkyYilGXPmQpm6AThInpBmKJEyRSIjORJd1G9+bknb7OTFYL+Vd4FBJAO6T78OVqA== + dependencies: + "@typescript-eslint/types" "5.28.0" + "@typescript-eslint/visitor-keys" "5.28.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + "@typescript-eslint/utils@5.17.0": version "5.17.0" resolved "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.17.0.tgz#549a9e1d491c6ccd3624bc3c1b098f5cfb45f306" @@ -1469,6 +1507,18 @@ eslint-scope "^5.1.1" eslint-utils "^3.0.0" +"@typescript-eslint/utils@5.28.0": + version "5.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.28.0.tgz#b27a136eac300a48160b36d2aad0da44a1341b99" + integrity sha512-E60N5L0fjv7iPJV3UGc4EC+A3Lcj4jle9zzR0gW7vXhflO7/J29kwiTGITA2RlrmPokKiZbBy2DgaclCaEUs6g== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.28.0" + "@typescript-eslint/types" "5.28.0" + "@typescript-eslint/typescript-estree" "5.28.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + "@typescript-eslint/visitor-keys@5.17.0": version "5.17.0" resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.17.0.tgz#52daae45c61b0211b4c81b53a71841911e479128" @@ -1477,6 +1527,14 @@ "@typescript-eslint/types" "5.17.0" eslint-visitor-keys "^3.0.0" +"@typescript-eslint/visitor-keys@5.28.0": + version "5.28.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.28.0.tgz#982bb226b763c48fc1859a60de33fbf939d40a0f" + integrity sha512-BtfP1vCor8cWacovzzPFOoeW4kBQxzmhxGoOpt0v1SFvG+nJ0cWaVdJk7cky1ArTcFHHKNIxyo2LLr3oNkSuXA== + dependencies: + "@typescript-eslint/types" "5.28.0" + eslint-visitor-keys "^3.3.0" + "@use-gesture/core@10.2.11": version "10.2.11" resolved "https://registry.npmjs.org/@use-gesture/core/-/core-10.2.11.tgz#914c36f190bcf452500d11a11fc294fe56e5dc2f" @@ -1896,7 +1954,7 @@ debounce@^1.2.1: resolved "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== -debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3: +debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -2536,7 +2594,7 @@ globals@^13.6.0, globals@^13.9.0: dependencies: type-fest "^0.20.2" -globby@^11.0.4: +globby@^11.0.4, globby@^11.1.0: version "11.1.0" resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -2633,7 +2691,7 @@ husky@^7.0.4: resolved "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535" integrity sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ== -ignore@^5.1.8, ignore@^5.2.0: +ignore@^5.2.0: version "5.2.0" resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== @@ -3569,6 +3627,13 @@ semver@^7.3.5: dependencies: lru-cache "^6.0.0" +semver@^7.3.7: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + shallowequal@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" @@ -3804,6 +3869,13 @@ three-stdlib@^2.8.12: potpack "^1.0.1" zstddec "^0.0.2" +three-to-cannon@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/three-to-cannon/-/three-to-cannon-4.1.0.tgz#acdd7fce98359ad68d82c8d5eac96dd8193789d7" + integrity sha512-bPHiuaYuJRznxarZfaAGvF5xjTMR6Xo3MNSWwjtmNfRt5p8mMMbuKwa015dBS0UOkBmTIvl6cBaA92EpMspjWw== + dependencies: + "@types/three" ">=0.125.x" + three@^0.139.1: version "0.139.2" resolved "https://registry.npmjs.org/three/-/three-0.139.2.tgz#b110799a15736df673b9293e31653a4ac73648dd"