/** * Framework-agnostic planet ring builder. * * Creates a carrier `Group` + ring `Mesh` pair. The carrier is what the caller * attaches to the planet's group; attaching the carrier (not the mesh) lets the * ring inherit the planet's tilt, spin and user drag while the ring's own spin * is applied at the mesh level around the carrier's local +Y. See the original * `BodyRings.vue` header for the full hierarchy rationale. * * Pure Three.js — no Vue, TresJS, or `onBeforeRender` coupling. */ import * as THREE from 'three'; import type { RingVariation } from './ringVariation'; /** * Input configuration for {@link buildBodyRings}. Couples the ring * geometry (radii derived from the planet radius), the deterministic * variation (archetype + profile + colours) and the planet's world-space * position used for shadow rays. * * Time scrubbing (pause / speed multiplier) is intentionally absent — * the caller scales the `dt` it passes to `tick()` instead, which keeps * playback control where it belongs (with the time source). */ export interface BodyRingsConfig { /** Planet visual radius (world units). Ring radii are `radius × innerRatio/outerRatio`. */ radius: number; /** Ring self-rotation speed around its own normal (rad/s). */ rotationSpeed: number; /** Deterministic ring variation (archetype + profile + colors). */ variation: RingVariation; /** * Mutable world-space position of the planet — read by the shadow * shader on every render. The caller owns the vector and mutates it * each frame (e.g. `props.group.getWorldPosition(planetWorldPos)`); the * lib never reassigns it. Wired directly into the shader uniform so no * per-frame copy is needed. */ planetWorldPos: THREE.Vector3; /** * Light source illuminating the rings. Each `tick()`, the lib reads * `sunLight.getWorldPosition()` and pushes it into the ring shader * (drives backlight halo + shadow ray). * * When omitted (or `null`), `tick()` auto-discovers the dominant * `PointLight` / `DirectionalLight` under the mesh's scene root via * {@link findDominantLightWorldPos} — handy for simple scenes with a * single light. Multi-star scenes pass the resolved light explicitly. */ sunLight?: THREE.PointLight | THREE.DirectionalLight | null; } /** * Runtime handle returned by {@link buildBodyRings}. Owns a `carrier` * group (attached to the planet) and exposes live setters to tweak the * ring variation without rebuilding. */ export interface BodyRingsHandle { /** The group to attach to the planet's group (NOT the mesh directly). */ carrier: THREE.Group; mesh: THREE.Mesh; /** * Advances the ring's internal spin angle by `dt` and refreshes the * world-space uniforms. Pass `0` (or skip the call) to freeze the * rotation — pause is just absence of ticks. */ tick(dt: number): void; /** Mutate live uniforms + rebuild the geometry when inner/outer ratios change. */ updateVariation(v: RingVariation): void; dispose(): void; } /** * Builds the ring carrier + mesh pair. The caller attaches `carrier` to the * planet group; `tick(dt)` advances spin and refreshes world-space uniforms. */ export declare function buildBodyRings(config: BodyRingsConfig): BodyRingsHandle; //# sourceMappingURL=buildBodyRings.d.ts.map