Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View File

@@ -0,0 +1,101 @@
import assert from "node:assert/strict";
import fs from "node:fs";
import factory from "../../web/app/src/vendor/blender/web_engine.js";
const root = new URL("../../", import.meta.url);
const wasmBinary = fs.readFileSync(new URL("web/app/src/vendor/blender/web_engine.wasm", root));
const golden = JSON.parse(fs.readFileSync(new URL("tests/golden/N-015/nonmesh-desktop-geometry.json", root), "utf8"));
const fixture = fs.readFileSync(new URL(`tests/files/web/${golden.fixture}`, root));
function readOutput(engine, handle, callback) {
const dataOut = engine._malloc(4);
const lengthOut = engine._malloc(4);
try {
assert.equal(callback(handle, dataOut, lengthOut), 0, engine.UTF8ToString(engine._web_engine_last_error_message()));
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 close(actual, expected, tolerance, label) {
assert.ok(Math.abs(actual - expected) <= tolerance, `${label}: expected ${expected}, got ${actual}`);
}
function metrics(geometry) {
const positions = geometry.positions ?? [];
const edgeIndices = geometry.edgeVertexIndices ?? [];
const indices = geometry.indices ?? [];
const vertexCount = positions.length / 3;
const boundsMin = [0, 1, 2].map((axis) => vertexCount ? Math.min(...Array.from({ length: vertexCount }, (_, index) => positions[index * 3 + axis])) : 0);
const boundsMax = [0, 1, 2].map((axis) => vertexCount ? Math.max(...Array.from({ length: vertexCount }, (_, index) => positions[index * 3 + axis])) : 0);
const centroid = [0, 1, 2].map((axis) => vertexCount ? Array.from({ length: vertexCount }, (_, index) => positions[index * 3 + axis]).reduce((sum, value) => sum + value, 0) / vertexCount : 0);
let surfaceArea = 0;
for (let triangle = 0; triangle < indices.length; triangle += 3) {
const a = indices[triangle] * 3;
const b = indices[triangle + 1] * 3;
const c = indices[triangle + 2] * 3;
const ab = [positions[b] - positions[a], positions[b + 1] - positions[a + 1], positions[b + 2] - positions[a + 2]];
const ac = [positions[c] - positions[a], positions[c + 1] - positions[a + 1], positions[c + 2] - positions[a + 2]];
const cross = [ab[1] * ac[2] - ab[2] * ac[1], ab[2] * ac[0] - ab[0] * ac[2], ab[0] * ac[1] - ab[1] * ac[0]];
surfaceArea += Math.hypot(...cross) * 0.5;
}
return {
vertexCount,
edgeCount: edgeIndices.length / 2,
triangleCount: indices.length / 3,
boundsMin,
boundsMax,
centroid,
surfaceArea,
positionMoment: positions.reduce((sum, value, index) => sum + (index + 1) * value, 0),
edgeIndexMoment: edgeIndices.reduce((sum, value, index) => sum + (index + 1) * (value + 1), 0),
indexMoment: indices.reduce((sum, value, index) => sum + (index + 1) * (value + 1), 0),
};
}
assert.equal(golden.schemaVersion, 1);
assert.equal(golden.blenderVersion, "5.2.0 LTS");
const engine = await factory({ wasmBinary });
const handle = engine._web_engine_create();
try {
const input = engine._malloc(fixture.byteLength);
engine.HEAPU8.set(fixture, input);
try {
assert.equal(engine._web_engine_open_blend(handle, input, fixture.byteLength), 0, engine.UTF8ToString(engine._web_engine_last_error_message()));
}
finally {
engine._free(input);
}
const evaluation = readOutput(engine, handle, engine._web_engine_evaluate_depsgraph);
const byObject = new Map(evaluation.nonMeshGeometries.map((geometry) => [geometry.objectId.replace(/^object:/, ""), geometry]));
for (const expected of golden.geometries) {
const geometry = byObject.get(expected.object);
assert.ok(geometry, `desktop golden object ${expected.object} is missing from the Web evaluation`);
assert.equal(geometry.status, "EVALUATED");
assert.equal(geometry.sourceType, expected.sourceType);
const actual = metrics(geometry);
assert.equal(actual.vertexCount, expected.vertexCount, `${expected.object} vertex count`);
assert.equal(actual.edgeCount, expected.edgeCount, `${expected.object} edge count`);
assert.equal(actual.triangleCount, expected.triangleCount, `${expected.object} triangle count`);
assert.equal(actual.edgeIndexMoment, expected.edgeIndexMoment, `${expected.object} edge index moment`);
assert.equal(actual.indexMoment, expected.indexMoment, `${expected.object} index moment`);
for (let axis = 0; axis < 3; axis++) {
close(actual.boundsMin[axis], expected.boundsMin[axis], golden.tolerance.coordinate, `${expected.object} boundsMin[${axis}]`);
close(actual.boundsMax[axis], expected.boundsMax[axis], golden.tolerance.coordinate, `${expected.object} boundsMax[${axis}]`);
close(actual.centroid[axis], expected.centroid[axis], golden.tolerance.coordinate, `${expected.object} centroid[${axis}]`);
}
close(actual.surfaceArea, expected.surfaceArea, golden.tolerance.surfaceArea, `${expected.object} surface area`);
close(actual.positionMoment, expected.positionMoment, golden.tolerance.positionMoment, `${expected.object} position moment`);
}
assert.equal(byObject.size, golden.geometries.length, "unexpected evaluated non-mesh object count");
}
finally {
engine._web_engine_destroy(handle);
}
console.log(`nonmesh-desktop-golden-ok fixture=${golden.fixture} geometries=${golden.geometries.length}`);