/** * VAV (Vertex Animation Video) plane codec: the pure product quantization layer between * baked per-frame vertex data and canonical byte planes. * * The runtime consumes this plane layout from exact UTSBM blocks: * - GEOMETRY: 16-bit position hi/lo ×3 against clip-global bounds, plus the 8-bit * octahedral-normal pair when present. A changed high byte can move a vertex across the * bounding box, so exactness is checked at these post-quantization integers. * - APPEARANCE: named 8-bit scalar planes — `ao`, `red`/`green`/`blue`, * `R/G/B` triplets, or arbitrary baked per-vertex data. Names are free-form (see * {@link VAV_PLANE_NAME_PATTERN}); the runtime exposes each plane as a TSL node by name. * * Unlike correspondence-free splats, vertex order is fixed across frames, so each plane lane * has stable temporal correspondence in the persisted lanes. * * Spec: `docs/formats/vav-manifest.md`; layout constants here are the implementation * source of truth. * * @module VAVFrames */ /** The fixed position planes that start every GEOMETRY track (top to bottom). */ export declare const VAV_POSITION_PLANES: readonly ["posXHi", "posXLo", "posYHi", "posYLo", "posZHi", "posZLo"]; /** The octahedral normal pair — appended to the GEOMETRY track when the bake has normals. */ export declare const VAV_NORMAL_PLANES: readonly ["normalOctU", "normalOctV"]; /** * Valid APPEARANCE plane names: identifier-like so they can double as TSL varying names. * Conventions the runtime sugars: `ao` (aoNode), `red`/`green`/`blue` (colorNode), and * `R`/`G`/`B` triplets (a vec3 node per base). */ export declare const VAV_PLANE_NAME_PATTERN: RegExp; /** Appearance plane count cap — keeps the atlas within sane texture dimensions. */ export declare const VAV_MAX_APPEARANCE_PLANES = 32; /** Three-component clip-global position bounds. */ export type VAVVec3 = readonly [number, number, number]; /** Atlas dimensions shared by the CPU encoder and GPU decoder. */ export interface VAVAtlasLayout { width: number; rowsPerPlane: number; geometryHeight: number; appearanceHeight: number; } /** Ordered plane names for the exact geometry and appearance tracks. */ export interface VAVPlaneSets { geometry: readonly string[]; appearance: readonly string[]; } /** One baked frame before plane quantization. */ export interface VAVFrame { positions: Float32Array; normals?: Float32Array; channels?: Readonly>; } /** Clip-global dequantization ranges. */ export interface VAVRanges { bounds: { min: VAVVec3; max: VAVVec3; }; channels?: Readonly>; } /** Quantized luma plane stacks for one frame. */ export interface VAVEncodedFramePlanes { geometry: Uint8Array; appearance: Uint8Array | null; } /** Vertex attributes reconstructed from one pair of plane stacks. */ export interface VAVDecodedFrame { positions: Float32Array; normals: Float32Array | null; channels: Record | null; } /** * Atlas layout for `vertexCount` vertices: vertex i lives at texel (i % width, plane·rows + * floor(i / width)). Width and stack heights are kept even (codec requirement). * * @param {number} vertexCount - Unique vertex count (indexed geometry). * @param {number} [width=1024] - Atlas width in texels. * @param {string[]} [geometryPlanes=VAV_POSITION_PLANES] - Ordered geometry plane names (6 position planes, optionally + the oct normal pair). * @param {string[]} [appearancePlanes=[]] - Ordered appearance plane names. * @returns {{ width:number, rowsPerPlane:number, geometryHeight:number, appearanceHeight:number }} */ export declare function vavAtlasLayout(vertexCount: number, width?: number, geometryPlanes?: readonly string[], appearancePlanes?: readonly string[]): VAVAtlasLayout; /** * Encode a unit normal into two 8-bit octahedral bytes (worst-case ~0.5° at 8 bits). * * @param {number} x * @param {number} y * @param {number} z * @returns {[number, number]} `[u, v]` bytes in 0..255. */ export declare function octEncodeNormal(x: number, y: number, z: number): [number, number]; /** * Decode two octahedral bytes back into a unit normal (the CPU twin of the TSL decoder in * {@link module:VAVNodes}). * * @param {number} u - Byte 0..255. * @param {number} v - Byte 0..255. * @param {Float32Array} out - Destination array. * @param {number} [offset=0] - Write offset (xyz). */ export declare function octDecodeNormal(u: number, v: number, out: Float32Array, offset?: number): void; /** * Quantize one frame into the two mono plane stacks (geometry, appearance) as flat * `Uint8Array`s of `width × height` luma bytes. Texels beyond `vertexCount` replicate each * plane's last real value; the decoder never samples those padding texels. * * @param {Object} frame - `{ positions:Float32Array(3V), normals?:Float32Array(3V), channels?:Object. }` — one scalar array (V values, linear) per appearance plane name. * @param {Object} layout - From {@link vavAtlasLayout}. * @param {Object} ranges - `{ bounds: { min:[x,y,z], max:[x,y,z] }, channels?:Object. }` (clip-global; `channels` holds each appearance plane's fixed linear headroom, default 1 — HDR planes like a direct+indirect GI bake need it). * @param {{ geometry:string[], appearance:string[] }} planes - Ordered plane names per track. * @param {number} vertexCount - Vertices per frame. * @returns {{ geometry:Uint8Array, appearance:Uint8Array|null }} */ export declare function encodeVAVFramePlanes(frame: VAVFrame, layout: VAVAtlasLayout, ranges: VAVRanges, planes: VAVPlaneSets, vertexCount: number): VAVEncodedFramePlanes; /** * Decode one frame's vertex arrays from the two luma plane stacks (the exact inverse of * {@link encodeVAVFramePlanes} up to quantization). The CPU * twin of the GPU sampling path — used by the encoder's round-trip gate and the tests. * * @param {Uint8Array} geometry - Geometry-track luma bytes (width × geometryHeight). * @param {Uint8Array|null} appearance - Appearance-track luma bytes (or null). * @param {Object} layout - From {@link vavAtlasLayout}. * @param {Object} ranges - Same ranges the encoder used. * @param {{ geometry:string[], appearance:string[] }} planes - Ordered plane names per track. * @param {number} vertexCount - Vertices per frame. * @returns {{ positions:Float32Array, normals:Float32Array|null, channels:Object.|null }} */ export declare function decodeVAVFramePlanes(geometry: Uint8Array, appearance: Uint8Array | null, layout: VAVAtlasLayout, ranges: VAVRanges, planes: VAVPlaneSets, vertexCount: number): VAVDecodedFrame; /** * Frame timestamp in microseconds — the ONE formula both the encoder (embedded `.af` * manifests) and the runtime (chunks fed to `VideoDecoder`) must use, so decoded-frame * timestamps map back to frame indices exactly. * * @param {number} index - Frame index. * @param {number} frameRate - Clip frame rate. * @returns {number} Timestamp in µs. */ export declare function vavFrameTimestamp(index: number, frameRate: number): number;