import type { Box3, Mat4 } from 'mathcat'; import { type Quat, type Vec3 } from 'mathcat'; import type { MassProperties } from '../body/mass-properties'; import type { SubShapeId } from '../body/sub-shape'; import type { CastRayCollector, CastRaySettings } from '../collision/cast-ray-vs-shape'; import type { CastShapeCollector, CastShapeSettings } from '../collision/cast-shape-vs-shape'; import type { CollidePointCollector, CollidePointSettings } from '../collision/collide-point-vs-shape'; import type { CollideShapeCollector, CollideShapeSettings } from '../collision/collide-shape-vs-shape'; import type { SupportFunctionMode } from '../collision/support'; import type { Face } from '../utils/face'; import type { BoxShape } from './box'; import type { CapsuleShape } from './capsule'; import type { CompoundShape } from './compound'; import type { ConvexHullShape } from './convex-hull'; import type { CylinderShape } from './cylinder'; import type { EmptyShape } from './empty-shape'; import type { OffsetCenterOfMassShape } from './offset-center-of-mass'; import type { PlaneShape } from './plane'; import type { ScaledShape } from './scaled'; import type { SphereShape } from './sphere'; import type { StaticCompoundShape } from './static-compound'; import type { TransformedShape } from './transformed'; import type { TriangleMeshShape } from './triangle-mesh'; /** base shape type */ export type ShapeBase = { /** shape type discriminator */ type: ShapeType; /** shape local bounds */ aabb: Box3; /** shape center of mass */ centerOfMass: Vec3; /** shape volume */ volume: number; }; /** shape types enum */ export declare enum ShapeType { SPHERE = 0, BOX = 1, CAPSULE = 2, CONVEX_HULL = 3, TRIANGLE_MESH = 4, COMPOUND = 5, TRANSFORMED = 6, SCALED = 7, EMPTY = 8, CYLINDER = 9, OFFSET_CENTER_OF_MASS = 10, PLANE = 11, STATIC_COMPOUND = 12, USER_1 = 101, USER_2 = 102, USER_3 = 103, USER_4 = 104, USER_5 = 105, USER_6 = 106, USER_7 = 107, USER_8 = 108, USER_9 = 109, USER_10 = 110 } /** shape categories enum */ export declare enum ShapeCategory { /** Convex shapes (Sphere, Box, Capsule, ConvexHull) */ CONVEX = 0, /** Mesh shapes (TriangleMesh) */ MESH = 1, /** Decorator shapes that transform other shapes (Transformed, Scaled) */ DECORATOR = 2, /** Composite shapes that contain other shapes (Compound) */ COMPOSITE = 3, /** Shapes that don't fit into the above categories */ OTHER = 4 } /** * Shape type registry for discriminated unions (extensible). * Custom shapes can extend this via declaration merging: * @example * ```typescript * declare module 'crashcat' { * interface ShapeTypeRegistry { * [ShapeType.USER_1]: MyCustomShape; * } * } * ``` */ export interface ShapeTypeRegistry { [ShapeType.SPHERE]: SphereShape; [ShapeType.BOX]: BoxShape; [ShapeType.CAPSULE]: CapsuleShape; [ShapeType.CONVEX_HULL]: ConvexHullShape; [ShapeType.CYLINDER]: CylinderShape; [ShapeType.TRIANGLE_MESH]: TriangleMeshShape; [ShapeType.COMPOUND]: CompoundShape; [ShapeType.TRANSFORMED]: TransformedShape; [ShapeType.SCALED]: ScaledShape; [ShapeType.EMPTY]: EmptyShape; [ShapeType.OFFSET_CENTER_OF_MASS]: OffsetCenterOfMassShape; [ShapeType.PLANE]: PlaneShape; [ShapeType.STATIC_COMPOUND]: StaticCompoundShape; } /** shape type, union derived from registry interface */ export type Shape = ShapeTypeRegistry[keyof ShapeTypeRegistry]; /** shape type registry for convex shapes */ export interface ConvexShapeTypeRegistry { [ShapeType.SPHERE]: SphereShape; [ShapeType.BOX]: BoxShape; [ShapeType.CAPSULE]: CapsuleShape; [ShapeType.CONVEX_HULL]: ConvexHullShape; [ShapeType.CYLINDER]: CylinderShape; } /** shape type, constrained to convex shapes */ export type ConvexShape = ConvexShapeTypeRegistry[keyof ConvexShapeTypeRegistry]; export declare const DEFAULT_SHAPE_DENSITY = 1000; export type SurfaceNormalResult = { normal: Vec3; position: Vec3; quaternion: Quat; scale: Vec3; }; export type SupportingFaceResult = { face: Face; transform: Mat4; scale: Vec3; }; export declare function createSupportingFaceResult(): SupportingFaceResult; export type GetLeafShapeResult = { /** The leaf shape found, or null if navigation failed */ shape: Shape | null; /** Remaining SubShapeId after navigation */ remainder: SubShapeId; }; export type GetSubShapeTransformedShapeResult = { /** The transformed shape found, or null if navigation failed */ shape: Shape | null; /** Accumulated position transform */ position: Vec3; /** Accumulated rotation transform */ rotation: Quat; /** Accumulated scale transform */ scale: Vec3; /** Remaining SubShapeId after navigation */ remainder: SubShapeId; }; export type CastRayVsShapeFn = (collector: CastRayCollector, settings: CastRaySettings, originX: number, originY: number, originZ: number, directionX: number, directionY: number, directionZ: number, length: number, shape: S, subShapeId: number, subShapeIdBits: number, posX: number, posY: number, posZ: number, quatX: number, quatY: number, quatZ: number, quatW: number, scaleX: number, scaleY: number, scaleZ: number) => void; export type CollidePointVsShapeFn = (collector: CollidePointCollector, settings: CollidePointSettings, pointX: number, pointY: number, pointZ: number, shapeB: S, subShapeIdB: number, subShapeIdBitsB: number, posBX: number, posBY: number, posBZ: number, quatBX: number, quatBY: number, quatBZ: number, quatBW: number, scaleBX: number, scaleBY: number, scaleBZ: number) => void; /** Collision handler function type for colliding two shapes */ export type CollideShapeVsShapeFn = (collector: CollideShapeCollector, settings: CollideShapeSettings, shapeA: Shape, subShapeIdA: number, subShapeIdBitsA: number, posAX: number, posAY: number, posAZ: number, quatAX: number, quatAY: number, quatAZ: number, quatAW: number, scaleAX: number, scaleAY: number, scaleAZ: number, shapeB: Shape, subShapeIdB: number, subShapeIdBitsB: number, posBX: number, posBY: number, posBZ: number, quatBX: number, quatBY: number, quatBZ: number, quatBW: number, scaleBX: number, scaleBY: number, scaleBZ: number) => void; /** Cast handler function type for casting one shape against another */ export type CastShapeVsShapeFn = (collector: CastShapeCollector, settings: CastShapeSettings, shapeA: Shape, subShapeIdA: number, subShapeIdBitsA: number, posAX: number, posAY: number, posAZ: number, quatAX: number, quatAY: number, quatAZ: number, quatAW: number, scaleAX: number, scaleAY: number, scaleAZ: number, dispAX: number, dispAY: number, dispAZ: number, shapeB: Shape, subShapeIdB: number, subShapeIdBitsB: number, posBX: number, posBY: number, posBZ: number, quatBX: number, quatBY: number, quatBZ: number, quatBW: number, scaleBX: number, scaleBY: number, scaleBZ: number) => void; type OptionalShapeDef = 'computeMassProperties' | 'getInnerRadius' | 'createSupportPool' | 'getSupportFunction' | 'getLeafShape' | 'getSubShapeTransformedShape'; export type ShapeDefOptions = Omit, OptionalShapeDef> & Partial, OptionalShapeDef>>; export declare function defineShape(shapeDef: ShapeDefOptions): ShapeDef; export type ComputeMassPropertiesImpl = (out: MassProperties, shape: S) => void; export type GetSurfaceNormalImpl = (ioResult: SurfaceNormalResult, shape: S, subShapeId: number) => void; export type GetSupportingFaceImpl = (ioResult: SupportingFaceResult, direction: Vec3, shape: S, subShapeId: number) => void; export type GetInnerRadiusImpl = (shape: S) => number; export type GetLeafShapeImpl = (outResult: GetLeafShapeResult, shape: S, subShapeId: SubShapeId) => void; export type GetSubShapeTransformedShapeImpl = (outResult: GetSubShapeTransformedShapeResult, shape: S, subShapeId: SubShapeId) => void; export type GetSupportFunctionImpl = (pool: any, shape: S, mode: SupportFunctionMode, scale: Vec3) => any | undefined; export type ShapeDef = { type: ShapeType; /** Shape category used for collision dispatch registration */ category: ShapeCategory; /** get mass properties for the shape */ computeMassProperties: ComputeMassPropertiesImpl; /** get surface normal */ getSurfaceNormal: GetSurfaceNormalImpl; /** get supporting face */ getSupportingFace: GetSupportingFaceImpl; /** get inner radius - radius of the biggest sphere that fits entirely in the shape */ getInnerRadius: GetInnerRadiusImpl; /** navigate to leaf shape following sub shape id hierarchy */ getLeafShape: GetLeafShapeImpl; /** navigate to transformed shape following sub shape id hierarchy, accumulating transforms */ getSubShapeTransformedShape: GetSubShapeTransformedShapeImpl; /** cast a ray against the shape */ castRay: CastRayVsShapeFn; /** test if a point collides with the shape */ collidePoint: CollidePointVsShapeFn; /** * Create a support pool for this shape type. * return undefined for non-convex shapes. * Called once per ShapeSupportPool when pools are created or shapes are registered. */ createSupportPool(): any | undefined; /** * Get a support function for this shape. * return undefined for non-convex shapes. * @param pool the pool created by createSupportPool() for this shape type * @param shape the shape instance * @param mode support function mode (INCLUDE/EXCLUDE_CONVEX_RADIUS) * @param scale scale to apply to the shape */ getSupportFunction: GetSupportFunctionImpl; /** Register collision and cast handlers for this shape type */ register(): void; }; export declare const shapeDefs: Record>; export type CollisionDispatch = { collideFns: Map>; castFns: Map>; }; export declare const collisionDispatch: CollisionDispatch; /** * Register a collision handler for a shape type pair. * If a handler already exists for the pair, it will be overwritten. * @param typeA first shape type * @param typeB second shape type * @param fn collision handler function */ export declare function setCollideShapeFn(typeA: ShapeType, typeB: ShapeType, fn: CollideShapeVsShapeFn): void; /** * Register a cast handler for a shape type pair. * If a handler already exists for the pair, it will be overwritten. * @param typeA first shape type * @param typeB second shape type * @param fn cast handler function */ export declare function setCastShapeFn(typeA: ShapeType, typeB: ShapeType, fn: CastShapeVsShapeFn): void; export declare function getShapeSurfaceNormal(out: Vec3, shape: Shape, position: Vec3, subShapeId: number): Vec3; export declare function computeMassProperties(out: MassProperties, shape: Shape): MassProperties; /** * Computes the supporting face, takes a local-space direction and returns face vertices in world space. * @param out output face with vertices in world space * @param shape shape to query * @param subShapeId sub-shape ID * @param localDirection query direction in local space to the shape * @param transform world transform of shape (rotation + translation, no scale) * @param scale scale in local space of the shape */ export declare function getShapeSupportingFace(out: Face, shape: Shape, subShapeId: number, localDirection: Vec3, transform: Mat4, scale: Vec3): void; /** * Get the inner radius of a shape. * Returns the radius of the biggest sphere that fits entirely in the shape. * For shapes with multiple sub-shapes, returns the smallest inner radius of the parts. * This can be used as a measure of how far the shape can be moved without risking going through geometry. * * Note: This is calculated on-demand, not cached. For performance-critical paths, * consider caching the result if calling repeatedly on the same shape. * * @param shape the shape to query * @returns the inner radius in meters */ export declare function getShapeInnerRadius(shape: Shape): number; export {};