/** * Decode the compressed/instanced shape format. * * The instanced format wraps a standard Shapes object: * ``` * { instances: [ { vertices: {shape,dtype,buffer,codec}, ... }, ... ], * shapes: { version, parts, loc, name, id, bb, ... } } * ``` * * Each instance contains base64-encoded geometry buffers. Parts reference * instances via `"shape": { "ref": N }`. After decoding, the result is a * standard Shapes tree with TypedArrays — identical to the existing format. */ import type { Shape, Shapes } from "../core/types.js"; /** A single base64-encoded buffer entry. */ interface EncodedBuffer { shape: number[]; dtype: "float32" | "int32" | "uint32"; buffer: string; codec: "b64"; } /** An encoded geometry instance (all 9 buffer fields + optional uvs). */ interface EncodedInstance { vertices: EncodedBuffer; triangles: EncodedBuffer; normals: EncodedBuffer; edges: EncodedBuffer; obj_vertices: EncodedBuffer; face_types: EncodedBuffer; edge_types: EncodedBuffer; triangles_per_face: EncodedBuffer; segments_per_edge: EncodedBuffer; uvs?: EncodedBuffer; } /** Top-level structure of the instanced format. */ interface InstancedData { instances: EncodedInstance[]; shapes: Shapes; } /** * Walk the shapes tree and decode any inline encoded buffers found in * part.shape objects. This handles edge/vertex-only objects that embed * encoded buffers directly (not via instance refs). */ declare function decodeInlineBuffers(shapes: Shapes): void; /** * Type guard: check if data is in the instanced format. * Detected by the presence of an `instances` array and a `shapes` object. */ declare function isInstancedFormat(data: unknown): data is InstancedData; /** * Decode every instance's buffers from base64 into TypedArrays. * * This is the leaf half of the instanced format: it knows the encoding and * nothing about the shapes tree. A host that receives its geometry as raw * binary rather than base64 skips this step and builds the `Shape[]` itself. */ declare function decodeBuffers(instances: EncodedInstance[]): Shape[]; /** * Resolve `{ ref: N }` entries in the shapes tree against decoded instances, * and return the tree. * * This is the structural half: the same geometry referenced N times - twenty * identical bolts - which every host needs whatever encoding it received the * buffers in. Held separate from `decodeBuffers` so that a host holding * TypedArrays already does not have to reimplement the walk. */ declare function resolveInstances(shapes: Shapes, decoded: Shape[]): Shapes; /** * Decode the instanced format into a standard Shapes object. * * 1. Decode all instance buffers from base64 → TypedArrays * 2. Walk the shapes tree and replace { ref: N } with decoded instances * 3. Return the unwrapped Shapes object * * Kept as the composition of the two halves above, so existing callers see * no change. */ declare function decodeInstancedFormat(data: InstancedData): Shapes; export { isInstancedFormat, decodeBuffers, resolveInstances, decodeInstancedFormat, decodeInlineBuffers, }; export type { InstancedData, EncodedBuffer, EncodedInstance };