import loadWasm from "../../../wasm/data"; // eslint-disable-next-line @typescript-eslint/no-explicit-any let wasmModule: any; async function initWasm() { wasmModule = await loadWasm(); } class Splat { offset: number = 0; position: Float32Array = new Float32Array(3); rotation: Float32Array = new Float32Array(4); scale: Float32Array = new Float32Array(3); selected: boolean = false; vertexCount: number = 0; positions: Float32Array = new Float32Array(0); rotations: Float32Array = new Float32Array(0); scales: Float32Array = new Float32Array(0); colors: Uint8Array = new Uint8Array(0); selection: Uint8Array = new Uint8Array(0); } let allocatedVertexCount: number = 0; const updateQueue = new Array(); let running = false; let loading = false; let positionsPtr: number; let rotationsPtr: number; let scalesPtr: number; let colorsPtr: number; let selectionPtr: number; let dataPtr: number; let worldPositionsPtr: number; let worldRotationsPtr: number; let worldScalesPtr: number; const pack = async (splat: Splat) => { while (loading) { await new Promise((resolve) => setTimeout(resolve, 0)); } if (!wasmModule) { loading = true; await initWasm(); loading = false; } const targetAllocatedVertexCount = Math.pow(2, Math.ceil(Math.log2(splat.vertexCount))); if (targetAllocatedVertexCount > allocatedVertexCount) { if (allocatedVertexCount > 0) { wasmModule._free(positionsPtr); wasmModule._free(rotationsPtr); wasmModule._free(scalesPtr); wasmModule._free(colorsPtr); wasmModule._free(selectionPtr); wasmModule._free(dataPtr); wasmModule._free(worldPositionsPtr); wasmModule._free(worldRotationsPtr); wasmModule._free(worldScalesPtr); } allocatedVertexCount = targetAllocatedVertexCount; positionsPtr = wasmModule._malloc(3 * allocatedVertexCount * 4); rotationsPtr = wasmModule._malloc(4 * allocatedVertexCount * 4); scalesPtr = wasmModule._malloc(3 * allocatedVertexCount * 4); colorsPtr = wasmModule._malloc(4 * allocatedVertexCount); selectionPtr = wasmModule._malloc(allocatedVertexCount); dataPtr = wasmModule._malloc(8 * allocatedVertexCount * 4); worldPositionsPtr = wasmModule._malloc(3 * allocatedVertexCount * 4); worldRotationsPtr = wasmModule._malloc(4 * allocatedVertexCount * 4); worldScalesPtr = wasmModule._malloc(3 * allocatedVertexCount * 4); } wasmModule.HEAPF32.set(splat.positions, positionsPtr / 4); wasmModule.HEAPF32.set(splat.rotations, rotationsPtr / 4); wasmModule.HEAPF32.set(splat.scales, scalesPtr / 4); wasmModule.HEAPU8.set(splat.colors, colorsPtr); wasmModule.HEAPU8.set(splat.selection, selectionPtr); wasmModule._pack( splat.selected, splat.vertexCount, positionsPtr, rotationsPtr, scalesPtr, colorsPtr, selectionPtr, dataPtr, worldPositionsPtr, worldRotationsPtr, worldScalesPtr, ); const outData = new Uint32Array(wasmModule.HEAPU32.buffer, dataPtr, splat.vertexCount * 8); const detachedData = new Uint32Array(outData.slice().buffer); const worldPositions = new Float32Array(wasmModule.HEAPF32.buffer, worldPositionsPtr, splat.vertexCount * 3); const detachedWorldPositions = new Float32Array(worldPositions.slice().buffer); const worldRotations = new Float32Array(wasmModule.HEAPF32.buffer, worldRotationsPtr, splat.vertexCount * 4); const detachedWorldRotations = new Float32Array(worldRotations.slice().buffer); const worldScales = new Float32Array(wasmModule.HEAPF32.buffer, worldScalesPtr, splat.vertexCount * 3); const detachedWorldScales = new Float32Array(worldScales.slice().buffer); const response = { data: detachedData, worldPositions: detachedWorldPositions, worldRotations: detachedWorldRotations, worldScales: detachedWorldScales, offset: splat.offset, vertexCount: splat.vertexCount, positions: splat.positions.buffer, rotations: splat.rotations.buffer, scales: splat.scales.buffer, colors: splat.colors.buffer, selection: splat.selection.buffer, }; self.postMessage({ response: response }, [ response.data.buffer, response.worldPositions.buffer, response.worldRotations.buffer, response.worldScales.buffer, response.positions, response.rotations, response.scales, response.colors, response.selection, ]); running = false; }; const packThrottled = () => { if (updateQueue.length === 0) return; if (!running) { running = true; const splat = updateQueue.shift() as Splat; pack(splat); setTimeout(() => { running = false; packThrottled(); }, 0); } }; self.onmessage = (e) => { if (e.data.splat) { const splat = e.data.splat as Splat; for (const [index, existing] of updateQueue.entries()) { if (existing.offset === splat.offset) { updateQueue[index] = splat; return; } } updateQueue.push(splat); packThrottled(); } };