const originalFetch = globalThis.fetch; globalThis.fetch = async (input, init) => { const url = input instanceof Request ? input.url : input.toString(); self.postMessage({ type: "LOG", message: `FETCH: ${url}` }); if (url.includes("webp.wasm")) { self.postMessage({ type: "LOG", message: `INTERCEPTED → /workers/webp.wasm`, }); const res = await originalFetch("/workers/webp.wasm", init); self.postMessage({ type: "LOG", message: `WASM response status: ${res.status}`, }); return res; } return originalFetch(input, init); }; // Intercept XMLHttpRequest (Emscripten uses this in Workers) if (typeof XMLHttpRequest !== "undefined") { const originalOpen = XMLHttpRequest.prototype.open; // @ts-ignore XMLHttpRequest.prototype.open = function ( method: string, url: string | URL, ...rest: any[] ) { if (typeof url === "string" && url.includes("webp.wasm")) { url = "/workers/webp.wasm"; } return originalOpen.apply(this, [method, url, ...rest] as any); }; } self.onmessage = async (e: MessageEvent) => { const { type, filesData, mainLccName, fileName } = e.data; if (type === "START_CONVERSION") { try { self.postMessage({ type: "LOG", message: "Initialisiere..." }); // Emscripten's native locateFile hook // @ts-ignore globalThis.Module = globalThis.Module || {}; // @ts-ignore globalThis.Module.locateFile = function (path: string) { if (path.endsWith(".wasm")) { return new URL("/webp.wasm", self.location.origin).href; } return path; }; const { readFile, writeFile, MemoryReadFileSystem, MemoryFileSystem, getInputFormat, } = await import("@playcanvas/splat-transform"); const readFs = new MemoryReadFileSystem(); self.postMessage({ type: "LOG", message: "Lade Dateien in den virtuellen Speicher...", }); for (const file of filesData) { readFs.set(file.name, new Uint8Array(file.buffer)); } const readOptions = { iterations: 0, lodSelect: [0, 1, 2, 3, 4], // we have captured a total level of 5 unbundled: false, lodChunkCount: 0, lodChunkExtent: 0, }; self.postMessage({ type: "LOG", message: "Lese LCC und Binärdaten..." }); const tables = await readFile({ filename: mainLccName, fileSystem: readFs, inputFormat: getInputFormat(mainLccName), params: [], options: readOptions, }); const mainTable = tables[0]; if (!mainTable) throw new Error("Keine Splat-Daten gefunden."); const generatedFiles: { name: string; blob: Blob }[] = []; // PASS 1: Generate Single High-Quality SOG self.postMessage({ type: "LOG", message: "Kompiliere Single SOG..." }); const writeFsSingle = new MemoryFileSystem(); const singleOutputName = `${fileName}.sog`; const singleOptions = { ...readOptions, iterations: 10, unbundled: false, }; await writeFile( { filename: singleOutputName, outputFormat: "sog", dataTable: mainTable, options: singleOptions, }, writeFsSingle, ); const singleSogData = writeFsSingle.results.get(singleOutputName); if (singleSogData) { generatedFiles.push({ name: singleOutputName, blob: new Blob([new Uint8Array(singleSogData).slice().buffer], { type: "application/octet-stream", }), }); } // ========================================== // PASS 2: Generate Unbundled LOD SOGs + JSON // ========================================== self.postMessage({ type: "LOG", message: "Kompiliere LOD Chunks..." }); const writeFsLods = new MemoryFileSystem(); // MUST be exactly "meta.json" for unbundled SOG format const lodsOutputName = "meta.json"; const lodOptions = { ...readOptions, iterations: 10, unbundled: true, lodChunkCount: 512, lodChunkExtent: 16, }; await writeFile( { filename: lodsOutputName, outputFormat: "sog", dataTable: mainTable, options: lodOptions, }, writeFsLods, ); // Jetzt iterieren wir über alle generierten Dateien im System for (const [generatedName, data] of writeFsLods.results.entries()) { const mimeType = generatedName.endsWith(".json") ? "application/json" : "application/octet-stream"; generatedFiles.push({ name: generatedName, blob: new Blob([new Uint8Array(data).slice().buffer], { type: mimeType, }), }); } // Send all Data to Frontend self.postMessage({ type: "DONE", data: { files: generatedFiles, }, }); } catch (err: any) { self.postMessage({ type: "LOG", message: `Fehler: ${err.message}` }); console.error(err); } } };