Files
workinf_Blender_Wasm/tools/web/probe-collapse-ratio.mjs
2026-08-12 04:47:48 -04:00

56 lines
2.7 KiB
JavaScript

import fs from "node:fs";
import factory from "../../web/app/src/vendor/blender/web_engine.js";
const ratio = Number(process.argv[2]);
if (!Number.isFinite(ratio) || ratio <= 0 || ratio > 1) throw new Error("usage: probe-collapse-ratio.mjs RATIO");
const wasmBinary = fs.readFileSync(new URL("../../web/app/src/vendor/blender/web_engine.wasm", import.meta.url));
const blend = fs.readFileSync(new URL("../../tests/files/web/basic_scene.blend", import.meta.url));
const engine = await factory({ wasmBinary });
const handle = engine._web_engine_create();
const text = new TextEncoder();
function open() {
const pointer = engine._malloc(blend.byteLength);
engine.HEAPU8.set(blend, pointer);
const result = engine._web_engine_open_blend(handle, pointer, blend.byteLength);
engine._free(pointer);
return result;
}
function snapshot() {
const dataOut = engine._malloc(4);
const lengthOut = engine._malloc(4);
try {
const result = engine._web_engine_get_scene_snapshot(handle, dataOut, lengthOut);
if (result !== 0) throw new Error("snapshot failed");
const pointer = engine.HEAPU32[dataOut >>> 2];
const length = engine.HEAPU32[lengthOut >>> 2];
return JSON.parse(new TextDecoder().decode(engine.HEAPU8.slice(pointer, pointer + length)));
}
finally {
engine._free(dataOut);
engine._free(lengthOut);
}
}
function apply(meshId, revision) {
const command = text.encode(JSON.stringify({
type: "decimateMesh",
meshId,
profile: { schemaVersion: 1, sourceMeshRevision: revision, attributePolicy: "PRESERVE", mode: "COLLAPSE", ratio, triangulate: false, useSymmetry: false },
}));
const pointer = engine._malloc(command.byteLength);
engine.HEAPU8.set(command, pointer);
const result = engine._web_engine_apply_command(handle, pointer, command.byteLength);
engine._free(pointer);
return result;
}
const opened = open();
if (opened !== 0) throw new Error(`open failed code=${opened} message=${engine.UTF8ToString(engine._web_engine_last_error_message())}`);
const source = snapshot();
const mesh = source.meshes.find((candidate) => candidate.id === "mesh:Cube.001") ?? source.meshes.find((candidate) => candidate.geometryStatus === "available");
if (!mesh) throw new Error("cube mesh not found");
const result = apply(mesh.id, source.revision);
const message = engine.UTF8ToString(engine._web_engine_last_error_message());
let output = null;
if (result === 0) output = snapshot().meshes.find((candidate) => candidate.id === mesh.id);
console.log(JSON.stringify({ ratio, result, message, allocatedBytes: engine._web_engine_get_allocated_bytes(), output: output && { vertexCount: output.vertexCount, triangleCount: output.triangleCount, faceCount: output.faceCount } }));
engine._web_engine_destroy(handle);