@pmndrs/cannon-worker-api
Version:
An API to use cannon-es in a web worker
61 lines (48 loc) • 1.74 kB
text/typescript
import type { Body, RayOptions } from 'cannon-es'
import { Ray, RAY_MODES, RaycastResult } from 'cannon-es'
import type { CannonMessageMap } from '../../types'
import type { State } from '../state'
import { tripletToVec3 } from '../triplet-to-vec3'
import type { CannonWorkerGlobalScope, WithUUID } from '../types'
declare const self: CannonWorkerGlobalScope
function toUppercase<T extends string>(str: T): Uppercase<T> {
return str.toUpperCase() as Uppercase<T>
}
export const addRay = (
state: State,
{ props: { from, mode, to, ...rayOptions }, uuid }: CannonMessageMap['addRay'],
) => {
const ray = new Ray(tripletToVec3(from), tripletToVec3(to))
const options: RayOptions = {
mode: RAY_MODES[toUppercase(mode)],
result: new RaycastResult(),
...rayOptions,
}
state.rays[uuid] = () => {
ray.intersectWorld(state.world, options)
if (!options.result || !options.result.body) return
const { body, shape, rayFromWorld, rayToWorld, hitNormalWorld, hitPointWorld, ...rest } = options.result
const bodyUUID = (body as WithUUID<Body>).uuid
if (!bodyUUID) return
self.postMessage({
body: bodyUUID,
hitNormalWorld: hitNormalWorld.toArray(),
hitPointWorld: hitPointWorld.toArray(),
op: 'event',
ray: {
collisionFilterGroup: ray.collisionFilterGroup,
collisionFilterMask: ray.collisionFilterMask,
direction: ray.direction.toArray(),
from,
to,
uuid,
},
rayFromWorld: rayFromWorld.toArray(),
rayToWorld: rayToWorld.toArray(),
shape: shape ? { ...shape, body: bodyUUID } : null,
type: 'rayhit',
...rest,
})
}
state.world.addEventListener('preStep', state.rays[uuid])
}