@pmndrs/cannon-worker-api
Version:
An API to use cannon-es in a web worker
353 lines (352 loc) • 13.2 kB
TypeScript
import type { ContactMaterialOptions, MaterialOptions, RayOptions as RayOptionsImpl, Shape } from 'cannon-es';
import type { Object3D } from 'three';
import type { AtomicProps, BodyShapeType } from './body';
export type { ContactMaterialOptions };
export declare type Triplet = [x: number, y: number, z: number];
export declare type Quad = [x: number, y: number, z: number, w: number];
export declare type Broadphase = 'Naive' | 'SAP';
export declare type Solver = 'GS' | 'Split';
export declare type Buffers = {
positions: Float32Array;
quaternions: Float32Array;
};
export declare type Refs = {
[uuid: string]: Object3D;
};
export declare type ConstraintTypes = 'PointToPoint' | 'ConeTwist' | 'Distance' | 'Lock';
export interface ConstraintOptns {
collideConnected?: boolean;
maxForce?: number;
maxMultiplier?: number;
wakeUpBodies?: boolean;
}
export interface PointToPointConstraintOpts extends ConstraintOptns {
pivotA: Triplet;
pivotB: Triplet;
}
export interface ConeTwistConstraintOpts extends ConstraintOptns {
angle?: number;
axisA?: Triplet;
axisB?: Triplet;
pivotA?: Triplet;
pivotB?: Triplet;
twistAngle?: number;
}
export interface DistanceConstraintOpts extends ConstraintOptns {
distance?: number;
}
export interface HingeConstraintOpts extends ConstraintOptns {
axisA?: Triplet;
axisB?: Triplet;
pivotA?: Triplet;
pivotB?: Triplet;
}
export declare type LockConstraintOpts = ConstraintOptns;
export interface SpringOptns {
damping?: number;
localAnchorA?: Triplet;
localAnchorB?: Triplet;
restLength?: number;
stiffness?: number;
worldAnchorA?: Triplet;
worldAnchorB?: Triplet;
}
export interface WheelInfoOptions {
axleLocal?: Triplet;
chassisConnectionPointLocal?: Triplet;
customSlidingRotationalSpeed?: number;
dampingCompression?: number;
dampingRelaxation?: number;
directionLocal?: Triplet;
frictionSlip?: number;
isFrontWheel?: boolean;
maxSuspensionForce?: number;
maxSuspensionTravel?: number;
radius?: number;
rollInfluence?: number;
sideAcceleration?: number;
suspensionRestLength?: number;
suspensionStiffness?: number;
useCustomSlidingRotationalSpeed?: boolean;
}
declare type WorkerContact = WorkerCollideEvent['data']['contact'];
export declare type CollideEvent = Omit<WorkerCollideEvent['data'], 'body' | 'target' | 'contact'> & {
body: Object3D;
contact: Omit<WorkerContact, 'bi' | 'bj'> & {
bi: Object3D;
bj: Object3D;
};
target: Object3D;
};
export declare type CollideBeginEvent = {
body: Object3D;
op: 'event';
target: Object3D;
type: 'collideBegin';
};
export declare type CollideEndEvent = {
body: Object3D;
op: 'event';
target: Object3D;
type: 'collideEnd';
};
export declare type RayhitEvent = Omit<WorkerRayhitEvent['data'], 'body'> & {
body: Object3D | null;
};
export declare type PropValue<T extends SubscriptionName = SubscriptionName> = T extends AtomicName ? AtomicProps[T] : T extends VectorName ? Triplet : T extends 'quaternion' ? Quad : T extends 'sliding' ? boolean : never;
export declare type Subscription = Partial<{
[K in SubscriptionName]: (value: PropValue<K>) => void;
}>;
export declare type Subscriptions = Partial<{
[id: number]: Subscription;
}>;
export declare type AtomicName = 'allowSleep' | 'angularDamping' | 'collisionFilterGroup' | 'collisionFilterMask' | 'collisionResponse' | 'fixedRotation' | 'isTrigger' | 'linearDamping' | 'mass' | 'material' | 'sleepSpeedLimit' | 'sleepTimeLimit' | 'userData';
export declare type VectorName = 'angularFactor' | 'angularVelocity' | 'linearFactor' | 'position' | 'velocity';
export declare type SubscriptionName = AtomicName | VectorName | 'quaternion' | 'sliding';
export declare type SetOpName<T extends AtomicName | VectorName | WorldPropName | 'quaternion' | 'rotation'> = `set${Capitalize<T>}`;
declare type Operation<T extends OpName, P> = {
op: T;
} & (P extends symbol ? {} : {
props: P;
});
declare type WithUUID<T extends OpName, P = symbol> = Operation<T, P> & {
uuid: string;
};
declare type WithUUIDs<T extends OpName, P = symbol> = Operation<T, P> & {
uuid: string[];
};
declare type AddConstraintProps = [
uuidA: string,
uuidB: string,
options: {
angle?: number;
axisA?: Triplet;
axisB?: Triplet;
collideConnected?: boolean;
distance?: number;
maxForce?: number;
maxMultiplier?: number;
pivotA?: Triplet;
pivotB?: Triplet;
twistAngle?: number;
wakeUpBodies?: boolean;
}
];
export declare type AddContactMaterialProps = [
materialA: MaterialOptions,
materialB: MaterialOptions,
options: ContactMaterialOptions
];
export declare type RayMode = 'Closest' | 'Any' | 'All';
declare type AddRayProps = {
from?: Triplet;
mode: RayMode;
to?: Triplet;
} & Pick<RayOptionsImpl, 'checkCollisionResponse' | 'collisionFilterGroup' | 'collisionFilterMask' | 'skipBackfaces'>;
export declare type RayOptions = Omit<AddRayProps, 'mode'>;
declare type AtomicMessage<T extends AtomicName> = WithUUID<SetOpName<T>, AtomicProps[T]>;
declare type VectorMessage = WithUUID<SetOpName<VectorName>, Triplet>;
declare type SerializableBodyProps = {
onCollide: boolean;
};
export declare type SubscriptionTarget = 'bodies' | 'vehicles';
declare type SubscribeMessageProps = {
id: number;
target: SubscriptionTarget;
type: SubscriptionName;
};
export declare type Observation = {
[K in AtomicName]: [id: number, value: PropValue<K>, type: K];
}[AtomicName];
export declare type WorkerFrameMessage = {
data: Buffers & {
active: boolean;
bodies?: string[];
observations: Observation[];
op: 'frame';
};
};
export declare type WorkerCollideEvent = {
data: {
body: string;
collisionFilters: {
bodyFilterGroup: number;
bodyFilterMask: number;
targetFilterGroup: number;
targetFilterMask: number;
};
contact: {
bi: string;
bj: string;
contactNormal: number[];
contactPoint: number[];
id: number;
impactVelocity: number;
ni: number[];
ri: number[];
rj: number[];
};
op: 'event';
target: string;
type: 'collide';
};
};
export declare type WorkerRayhitEvent = {
data: {
body: string | null;
distance: number;
hasHit: boolean;
hitFaceIndex: number;
hitNormalWorld: number[];
hitPointWorld: number[];
op: 'event';
ray: {
collisionFilterGroup: number;
collisionFilterMask: number;
direction: number[];
from?: Triplet;
to?: Triplet;
uuid: string;
};
rayFromWorld: Triplet;
rayToWorld: Triplet;
shape: (Omit<Shape, 'body' | 'updateBoundingSphereRadius' | 'volume' | 'calculateLocalInertia' | 'calculateWorldAABB'> & {
body: string;
}) | null;
shouldStop: boolean;
type: 'rayhit';
};
};
export declare type WorkerCollideBeginEvent = {
data: {
bodyA: string;
bodyB: string;
op: 'event';
type: 'collideBegin';
};
};
export declare type WorkerCollideEndEvent = {
data: {
bodyA: string;
bodyB: string;
op: 'event';
type: 'collideEnd';
};
};
export declare type WorkerEventMessage = WorkerCollideBeginEvent | WorkerCollideEndEvent | WorkerCollideEvent | WorkerRayhitEvent;
export declare type IncomingWorkerMessage = WorkerEventMessage | WorkerFrameMessage;
export declare type WorldPropName = 'axisIndex' | 'broadphase' | 'frictionGravity' | 'gravity' | 'iterations' | 'tolerance';
export declare type StepProps = {
maxSubSteps?: number;
stepSize: number;
timeSinceLastCalled?: number;
};
export declare type WorldProps = {
allowSleep: boolean;
axisIndex: 0 | 1 | 2;
broadphase: Broadphase;
defaultContactMaterial: ContactMaterialOptions;
frictionGravity: Triplet | null;
gravity: Triplet;
iterations: number;
quatNormalizeFast: boolean;
quatNormalizeSkip: number;
solver: Solver;
tolerance: number;
};
declare type WorldMessage<T extends WorldPropName> = Operation<SetOpName<T>, WorldProps[T]>;
export declare type CannonMessageMap = {
addBodies: WithUUIDs<'addBodies', SerializableBodyProps[]> & {
type: BodyShapeType;
};
addConstraint: WithUUID<'addConstraint', AddConstraintProps> & {
type: 'Hinge' | ConstraintTypes;
};
addContactMaterial: WithUUID<'addContactMaterial', AddContactMaterialProps>;
addRay: WithUUID<'addRay', AddRayProps>;
addRaycastVehicle: WithUUID<'addRaycastVehicle', [
chassisBodyUUID: string,
wheelUUIDs: string[],
wheelInfos: WheelInfoOptions[],
indexForwardAxis: number,
indexRightAxis: number,
indexUpAxis: number
]>;
addSpring: WithUUID<'addSpring', [uuidA: string, uuidB: string, options: SpringOptns]>;
applyForce: WithUUID<'applyForce', [force: Triplet, worldPoint: Triplet]>;
applyImpulse: WithUUID<'applyImpulse', [impulse: Triplet, worldPoint: Triplet]>;
applyLocalForce: WithUUID<'applyLocalForce', [force: Triplet, localPoint: Triplet]>;
applyLocalImpulse: WithUUID<'applyLocalImpulse', [impulse: Triplet, localPoint: Triplet]>;
applyRaycastVehicleEngineForce: WithUUID<'applyRaycastVehicleEngineForce', [
value: number,
wheelIndex: number
]>;
applyTorque: WithUUID<'applyTorque', [torque: Triplet]>;
disableConstraint: WithUUID<'disableConstraint'>;
disableConstraintMotor: WithUUID<'disableConstraintMotor'>;
enableConstraint: WithUUID<'enableConstraint'>;
enableConstraintMotor: WithUUID<'enableConstraintMotor'>;
init: Operation<'init', WorldProps>;
removeBodies: WithUUIDs<'removeBodies'>;
removeConstraint: WithUUID<'removeConstraint'>;
removeContactMaterial: WithUUID<'removeContactMaterial'>;
removeRay: WithUUID<'removeRay'>;
removeRaycastVehicle: WithUUID<'removeRaycastVehicle'>;
removeSpring: WithUUID<'removeSpring'>;
setAllowSleep: AtomicMessage<'allowSleep'>;
setAngularDamping: AtomicMessage<'angularDamping'>;
setAngularFactor: VectorMessage;
setAngularVelocity: VectorMessage;
setAxisIndex: WorldMessage<'axisIndex'>;
setBroadphase: WorldMessage<'broadphase'>;
setCollisionFilterGroup: AtomicMessage<'collisionFilterGroup'>;
setCollisionFilterMask: AtomicMessage<'collisionFilterMask'>;
setCollisionResponse: AtomicMessage<'collisionResponse'>;
setConstraintMotorMaxForce: WithUUID<'setConstraintMotorMaxForce', number>;
setConstraintMotorSpeed: WithUUID<'setConstraintMotorSpeed', number>;
setFixedRotation: AtomicMessage<'fixedRotation'>;
setFrictionGravity: WorldMessage<'frictionGravity'>;
setGravity: WorldMessage<'gravity'>;
setIsTrigger: AtomicMessage<'isTrigger'>;
setIterations: WorldMessage<'iterations'>;
setLinearDamping: AtomicMessage<'linearDamping'>;
setLinearFactor: VectorMessage;
setMass: AtomicMessage<'mass'>;
setMaterial: AtomicMessage<'material'>;
setPosition: VectorMessage;
setQuaternion: WithUUID<SetOpName<'quaternion'>, Quad>;
setRaycastVehicleBrake: WithUUID<'setRaycastVehicleBrake', [brake: number, wheelIndex: number]>;
setRaycastVehicleSteeringValue: WithUUID<'setRaycastVehicleSteeringValue', [
value: number,
wheelIndex: number
]>;
setRotation: WithUUID<SetOpName<'rotation'>, Triplet>;
setSleepSpeedLimit: AtomicMessage<'sleepSpeedLimit'>;
setSleepTimeLimit: AtomicMessage<'sleepTimeLimit'>;
setSpringDamping: WithUUID<'setSpringDamping', number>;
setSpringRestLength: WithUUID<'setSpringRestLength', number>;
setSpringStiffness: WithUUID<'setSpringStiffness', number>;
setTolerance: WorldMessage<'tolerance'>;
setUserData: AtomicMessage<'userData'>;
setVelocity: VectorMessage;
sleep: WithUUID<'sleep'>;
step: Operation<'step', StepProps> & {
positions: Float32Array;
quaternions: Float32Array;
};
subscribe: WithUUID<'subscribe', SubscribeMessageProps>;
unsubscribe: Operation<'unsubscribe', number>;
wakeUp: WithUUID<'wakeUp'>;
};
declare type OpName = keyof CannonMessageMap;
export declare type CannonMessageBody<T extends OpName> = Omit<CannonMessageMap[T], 'op'>;
export declare type CannonMessageProps<T extends OpName> = CannonMessageMap[T] extends {
props: unknown;
} ? CannonMessageMap[T]['props'] : never;
export declare type CannonMessage = CannonMessageMap[OpName];
export interface CannonWebWorker extends Worker {
onmessage: ((e: IncomingWorkerMessage) => void) | null;
postMessage(message: CannonMessage, transfer: Transferable[]): void;
postMessage(message: CannonMessage, options?: StructuredSerializeOptions): void;
terminate: () => void;
}