import type { Mat4 } from './types.js'; import type { DecodedInstancedShard } from '@ifc-lite/geometry'; /** * Constant IFC Z-up → WebGL Y-up swap `(x, y, z) → (x, z, -y)`, column-major * (MathUtils / WGSL convention). Identical to the swap `MeshDataJs::new` applies * to the flat path, so instanced geometry shares the flat frame exactly. */ export declare const SWAP_ZUP_TO_YUP: Mat4; /** * Bytes per instance in the GPU instance buffer: * [0..63] mat4 (16 f32, column-major) * [64..67] entityId (u32) * [68..83] rgba (4 f32) * [84..87] flags (u32 — bit 0 = selected; bit 1 = hidden) */ export declare const INSTANCE_STRIDE_BYTES = 88; /** Byte offset of the rgba colour within an instance record (patched by lens/IDS overlays). */ export declare const INSTANCE_COLOR_OFFSET = 68; /** Byte offset of the flags u32 within an instance record (patched by selection/visibility). */ export declare const INSTANCE_FLAGS_OFFSET = 84; /** flags bit 0 — this occurrence is selected (blue highlight in the shader). */ export declare const INSTANCE_FLAG_SELECTED = 1; /** flags bit 1 — this occurrence is hidden (hide/isolate); the shader discards it * in both the render and pick passes so it neither draws nor is pickable. */ export declare const INSTANCE_FLAG_HIDDEN = 2; /** * Compose the per-occurrence render matrix `SWAP · rel_k · T(origin)` that maps a * template's LOCAL vertex (relative to `origin`, native IFC frame) into WebGL * Y-up world space. Returns a column-major 16-float array; the renderer feeds its * four columns as vec4 vertex attributes (@location 3..6) and the shader computes * `worldPos = instMat * vec4(position, 1.0)`. */ export declare function composeInstanceMatrix(transformRowMajor: Float32Array, origin: readonly [number, number, number]): Float32Array; /** A unique template + the interleaved per-instance buffer for its occurrences. */ export interface InstancedRenderTemplate { /** Index of this template within its source shard (diagnostic only). */ templateIndex: number; /** Template geometry, LOCAL to `origin`, native IFC frame (uploaded once). */ positions: Float32Array; normals: Float32Array; indices: Uint32Array; /** Template local origin (f64), folded into each instance matrix. */ origin: [number, number, number]; /** Interleaved instance data: per occurrence mat4(64B) + entityId(4B) + rgba(16B) + flags(4B). */ instanceBuffer: ArrayBuffer; /** Number of occurrences (the `instanceCount` for drawIndexed). */ instanceCount: number; /** Per-occurrence express ids, in buffer order (occurrence i is at byte i*stride). * Lets the Scene build an express_id → occurrence map for per-instance * selection-flag + colour-override patching. */ entityIds: Uint32Array; } /** * Write one occurrence's interleaved record (mat4 column-major + entityId + rgba) * into `dv` at `byteOffset`. Little-endian to match the GPU buffer + the IFNS * decoder. Exposed for the unit test. */ export declare function writeInstanceRecord(dv: DataView, byteOffset: number, instanceMatrix: Float32Array, entityId: number, color: readonly [number, number, number, number], flags?: number): void; /** * Turn a decoded IFNS shard into render-ready templates. Each template's * occurrences are grouped and their `SWAP · rel_k · T(origin)` matrices + * entityId + colour packed into one interleaved instance buffer. Templates with * zero occurrences are skipped (encode always emits ≥1, but be defensive). * * TRANSPARENT instances (colour alpha < OPAQUE_ALPHA_CUTOFF — glass, IfcSpace, * openings) are EXCLUDED: the instanced pipeline is the opaque clone (no alpha * blend, depth-write on), so drawing glass here renders it opaque (and fs_main's * glass-fresnel tints it near-white). They render correctly via the flat * transparent pipeline instead — which the emit-both path still produces. Uses * the SAME 0.99 cutoff as the flat opaque/transparent split (overlay-routing.ts). */ export declare function prepareInstancedRender(shard: DecodedInstancedShard): InstancedRenderTemplate[]; /** Per-template cull metadata (structurally satisfied by InstancedTemplateGPU). */ export interface InstancedCullMeta { /** Union of the occurrences' world AABBs; null = uncullable. */ bounds: { min: [number, number, number]; max: [number, number, number]; } | null; /** Largest single-occurrence bounding-sphere radius. Infinity marks a * POISONED template (a non-finite occurrence box was seen): it is never * culled and later finite occurrences must not resurrect its bounds. */ maxOccRadius: number; } /** One occurrence's world AABB, as produced by the shard-upload transform. */ export interface OccurrenceWorldBox { minX: number; minY: number; minZ: number; maxX: number; maxY: number; maxZ: number; } /** * Fold one occurrence's world AABB into a template's cull metadata: grow the * union bounds and the max occurrence bounding-sphere radius. * * A non-finite box (NaN/Infinity occurrence matrix) POISONS the template — * bounds are wiped and maxOccRadius pinned to Infinity so the render loop * fails OPEN (culling on poisoned metadata would hide real geometry), and the * poison is sticky against later finite occurrences. */ export declare function foldOccurrenceWorldBox(meta: InstancedCullMeta, w: OccurrenceWorldBox): void; //# sourceMappingURL=instanced-render.d.ts.map