lod export

This commit is contained in:
Andreas Wilms
2026-03-09 14:18:49 +01:00
parent 9b5f2d0814
commit d4ccff6342
2 changed files with 89 additions and 28 deletions

View File

@@ -8,8 +8,6 @@ export default function XgridsWizard() {
const workerRef = useRef<Worker | null>(null);
useEffect(() => {
// 1. Point to the NEW location in the /app folder
// Next.js recognizes the 'new URL' pattern and bundles it as a separate worker
const worker = new Worker(
new URL("./workers/converter.worker.ts", import.meta.url),
);
@@ -18,11 +16,17 @@ export default function XgridsWizard() {
worker.onmessage = (e) => {
const { type, message, data } = e.data;
if (type === "LOG") setStatus(message);
if (type === "DONE") {
setIsProcessing(false);
setStatus("Conversion Complete!");
downloadFile(data.sog, `${data.fileName}.sog`);
// Removed: downloadFile(data.ply, ...) — worker doesn't produce a PLY
setStatus(
`Conversion Complete! Downloading ${data.files.length} files...`,
);
// Loop through all generated files and trigger downloads
data.files.forEach((file: { name: string; blob: Blob }) => {
downloadFile(file.blob, file.name);
});
}
};

View File

@@ -41,13 +41,16 @@ self.onmessage = async (e: MessageEvent) => {
try {
self.postMessage({ type: "LOG", message: "Initialisiere..." });
// Fetch the WASM binary ourselves and inject it
const wasmResponse = await fetch("/workers/webp.wasm");
const wasmBinary = await wasmResponse.arrayBuffer();
// Inject before the module loads
// Emscripten's native locateFile hook
// @ts-ignore
globalThis.Module = { wasmBinary };
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,
@@ -55,7 +58,6 @@ self.onmessage = async (e: MessageEvent) => {
MemoryReadFileSystem,
MemoryFileSystem,
getInputFormat,
getOutputFormat,
} = await import("@playcanvas/splat-transform");
const readFs = new MemoryReadFileSystem();
@@ -69,9 +71,9 @@ self.onmessage = async (e: MessageEvent) => {
readFs.set(file.name, new Uint8Array(file.buffer));
}
const fullOptions = {
const readOptions = {
iterations: 0,
lodSelect: [0],
lodSelect: [0, 1, 2, 3, 4], // we have captured a total level of 5
unbundled: false,
lodChunkCount: 0,
lodChunkExtent: 0,
@@ -84,37 +86,92 @@ self.onmessage = async (e: MessageEvent) => {
fileSystem: readFs,
inputFormat: getInputFormat(mainLccName),
params: [],
options: fullOptions,
options: readOptions,
});
const mainTable = tables[0];
if (!mainTable) throw new Error("Keine Splat-Daten gefunden.");
self.postMessage({ type: "LOG", message: "Kompiliere SOG..." });
const generatedFiles: { name: string; blob: Blob }[] = [];
const writeFs = new MemoryFileSystem();
const outputName = `${fileName}.sog`;
// 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: outputName,
outputFormat: getOutputFormat(outputName, fullOptions),
filename: singleOutputName,
outputFormat: "sog",
dataTable: mainTable,
options: { ...fullOptions, iterations: 8 },
options: singleOptions,
},
writeFs,
writeFsSingle,
);
const sogData = writeFs.results.get(outputName);
if (!sogData) throw new Error("SOG-Erstellung fehlgeschlagen.");
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: {
sog: new Blob([new Uint8Array(sogData).slice().buffer], {
type: "application/octet-stream",
}),
fileName,
files: generatedFiles,
},
});
} catch (err: any) {