bilca's picture
Upload 56 files
352fb85 verified
raw
history blame
5.42 kB
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<Splat>();
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();
}
};