import type { Matrix4, Object3D, Vector3 } from 'three/webgpu'; export type FloatingBodyMode = 'kinematic' | 'forces'; export interface FloatingBodySurfaceField { requestProbe(x: number, z: number, options: { persistent: boolean; unique: boolean; }): number; getProbeSample(slot: number, target: Float32Array): Float32Array; setProbePosition(slot: number, x: number, z: number): void; releaseProbe(slot: number): void; } export interface FloatingBodyWaveField { getSurfaceHeightAt(x: number, z: number, time: number): number; } export interface FloatingBodyWater { surface: FloatingBodySurfaceField | null; volumeToWorldMatrix: Matrix4; worldToVolumeMatrix: Matrix4; domainSize: Vector3; time: number; gravityWorld: number; waves?: FloatingBodyWaveField | null | undefined; getStillWaterLevel(): number; } export interface FloatingBodyOptions { samplePoints?: 'auto' | Vector3[] | undefined; mode?: FloatingBodyMode | undefined; heaveSmoothTime?: number | undefined; tiltSmoothTime?: number | undefined; maxTilt?: number | undefined; buoyancyOffset?: number | undefined; mass?: number | undefined; fluidDensity?: number | undefined; draft?: 'auto' | number | undefined; } export interface FloatingBodySmoothDampState { velocity: number; } export interface FloatingBodyForces { force: Vector3; torque: Vector3; } /** * Buoyant body floating on a {@link WaterVolume} through the batched * SurfaceField probe buffer — the water-pro contract: up to five hull sample * points ride the block's single per-frame probe readback, pitch/roll come * from height differences, and SmoothDamp masks the one-frame latency. * * This implementation-level API is intentionally internal and has no public package import. * * Two modes: * - `kinematic` (default): drives the object's `position.y` and pitch/roll * directly; yaw and XZ remain caller-owned (steer the boat, the water does * the rest). * - `forces`: `update()` returns `{ force, torque }` (world units) from * per-probe Archimedes terms, for an external physics engine. * * For two-way coupling (wakes, hull push), register the same object as a * kinematic collider in the shared interaction world * (`KinematicInteractionSource` with `affects: ['fluid']`) and pass that * world to the `WaterVolume` — the water-side response uses the hull's * surface velocity, so bow waves and stern wakes emerge in the SurfaceField. * * @short Probe-batched buoyancy: 5-point hull sampling, SmoothDamp follow or Archimedes forces. * @category Simulation * @tags WebGPU, Water, Buoyancy */ export declare class FloatingBody { water: FloatingBodyWater; object: Object3D; mode: FloatingBodyMode; heaveSmoothTime: number; tiltSmoothTime: number; maxTilt: number; buoyancyOffset: number; mass: number; fluidDensity: number; samplePoints: Vector3[]; draft: number; _autoSpanX: number | undefined; _autoSpanZ: number | undefined; _slots: number[]; _heights: Float32Array; _sample: Float32Array; _heaveState: FloatingBodySmoothDampState; _pitchState: FloatingBodySmoothDampState; _rollState: FloatingBodySmoothDampState; _force: Vector3; _torque: Vector3; _disposed: boolean; /** * @param {WaterVolume} water Water block (requires its SurfaceField). * @param {THREE.Object3D} object Body to float. * @param {Object} [options] * @param {'auto'|Array} [options.samplePoints='auto'] Local-space hull sample * points. `'auto'` derives center/bow/stern/port/starboard from the object's bounding box. * @param {'kinematic'|'forces'} [options.mode='kinematic'] Integration mode. * @param {number} [options.heaveSmoothTime=0.15] SmoothDamp time for vertical follow (s). * @param {number} [options.tiltSmoothTime=0.2] SmoothDamp time for pitch/roll (s). * @param {number} [options.maxTilt=1.22] Tilt clamp in radians (~70°). * @param {number} [options.buoyancyOffset=0] Rest height of the object origin above the surface. * @param {number} [options.mass=700] Body mass (kg) for force mode. * @param {number} [options.fluidDensity=1000] Fluid density (kg/m³) for force mode. * @param {'auto'|number} [options.draft='auto'] Hull draft (world units) for submersion in force mode. */ constructor(water: FloatingBodyWater, object: Object3D, { samplePoints, mode, heaveSmoothTime, tiltSmoothTime, maxTilt, buoyancyOffset, mass, fluidDensity, draft, }?: FloatingBodyOptions); _resolveLayout(samplePoints: 'auto' | Vector3[], draft: 'auto' | number): void; _ensureSlots(): void; _surfaceHeightAt(slotIndex: number, localX: number, localZ: number): number; /** * Advance the body one frame. Call after `water.step()`. * * @param {number} dt Frame delta time (s). * @returns {this|{force: THREE.Vector3, torque: THREE.Vector3}} `this` in kinematic * mode; the accumulated world-space buoyancy force/torque in force mode. */ update(dt: number): this | FloatingBodyForces; _computeForces(): FloatingBodyForces; /** Latest per-probe surface heights (world Y), ordered like samplePoints. */ getHeights(): Float32Array; dispose(): void; }