lod export
This commit is contained in:
14
app/page.tsx
14
app/page.tsx
@@ -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);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user