forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
6114a2295f
commit
69809f7228
593 files changed
+903643
-40774
No files matched your search
@@ -0,0 +1,116 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import test from "node:test";
|
||||
import { Accessor, Document, NodeIO } from "@gltf-transform/core";
|
||||
import { EXTMeshGPUInstancing } from "@gltf-transform/extensions";
|
||||
import {
|
||||
mappingMetrics,
|
||||
nodeInstanceTransforms,
|
||||
sourceImageAliasKey,
|
||||
transformInstancedPoint,
|
||||
triangleArea,
|
||||
} from "./audit-environment-quality.mjs";
|
||||
|
||||
test("source image aliases preserve unresolved or used alpha and normalize only known-unused alpha", () => {
|
||||
const source = new Uint8Array([
|
||||
255, 64, 32, 0,
|
||||
10, 20, 30, 255,
|
||||
]);
|
||||
const aliasWithDifferentAlpha = new Uint8Array([
|
||||
255, 64, 32, 200,
|
||||
10, 20, 30, 1,
|
||||
]);
|
||||
const opaqueA = sourceImageAliasKey({ width: 2, height: 1, rgba: source, alphaMode: "OPAQUE", alphaUsed: false });
|
||||
const opaqueB = sourceImageAliasKey({ width: 2, height: 1, rgba: aliasWithDifferentAlpha, alphaMode: "OPAQUE", alphaUsed: false });
|
||||
assert.equal(opaqueA, opaqueB, "opaque texture aliases are compared using RGB and dimensions");
|
||||
assert.notEqual(sourceImageAliasKey({ width: 2, height: 1, rgba: source, alphaMode: "OPAQUE" }),
|
||||
sourceImageAliasKey({ width: 2, height: 1, rgba: aliasWithDifferentAlpha, alphaMode: "OPAQUE" }),
|
||||
"varying source alpha stays part of identity when native use is unresolved");
|
||||
const uniformTranslucent = new Uint8Array([255, 64, 32, 128, 10, 20, 30, 128]);
|
||||
const uniformOpaque = new Uint8Array([255, 64, 32, 255, 10, 20, 30, 255]);
|
||||
assert.notEqual(sourceImageAliasKey({ width: 2, height: 1, rgba: uniformTranslucent, alphaMode: "OPAQUE" }),
|
||||
sourceImageAliasKey({ width: 2, height: 1, rgba: uniformOpaque, alphaMode: "OPAQUE" }),
|
||||
"uniform non-opaque alpha also remains part of identity when native use is unresolved");
|
||||
const nativeAlphaA = sourceImageAliasKey({ width: 2, height: 1, rgba: source, alphaMode: "OPAQUE", alphaUsed: true });
|
||||
const nativeAlphaB = sourceImageAliasKey({ width: 2, height: 1, rgba: aliasWithDifferentAlpha, alphaMode: "OPAQUE", alphaUsed: true });
|
||||
assert.notEqual(nativeAlphaA, nativeAlphaB, "native translucency preserves RGBA even if the converted material says OPAQUE");
|
||||
|
||||
const blendedA = sourceImageAliasKey({ width: 2, height: 1, rgba: source, alphaMode: "BLEND" });
|
||||
const blendedB = sourceImageAliasKey({ width: 2, height: 1, rgba: aliasWithDifferentAlpha, alphaMode: "BLEND" });
|
||||
assert.notEqual(blendedA, blendedB, "materials that use alpha retain separate RGBA identities");
|
||||
assert.notEqual(opaqueA, sourceImageAliasKey({ width: 1, height: 2, rgba: source, alphaMode: "OPAQUE", alphaUsed: false }),
|
||||
"equal pixel bytes at another image shape do not alias");
|
||||
assert.notEqual(opaqueA, sourceImageAliasKey({ width: 2, height: 1, rgba: source, alphaMode: "OPAQUE", alphaUsed: false, baseColorFactor: [0.5, 1, 1, 1] }),
|
||||
"material base-color factors remain part of rendered source equivalence");
|
||||
});
|
||||
|
||||
test("instance TRS expansion preserves UV rank and accounts for transformed area and cells", async () => {
|
||||
const temporaryDirectory = await mkdtemp(path.join(os.tmpdir(), "rom-quality-instancing-test-"));
|
||||
const fixtureFile = path.join(temporaryDirectory, "instances.glb");
|
||||
try {
|
||||
const document = new Document();
|
||||
const buffer = document.createBuffer();
|
||||
const positions = document.createAccessor("POSITION")
|
||||
.setType(Accessor.Type.VEC3)
|
||||
.setArray(new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]))
|
||||
.setBuffer(buffer);
|
||||
const primitive = document.createPrimitive().setAttribute("POSITION", positions);
|
||||
const node = document.createNode("fixture-node")
|
||||
.setMesh(document.createMesh("fixture-mesh").addPrimitive(primitive))
|
||||
.setTranslation([5, 2, 0])
|
||||
.setScale([2, 1, 1]);
|
||||
const instanceExtension = document.createExtension(EXTMeshGPUInstancing);
|
||||
const instancedMesh = instanceExtension.createInstancedMesh()
|
||||
.setAttribute("TRANSLATION", document.createAccessor("TRANSLATION")
|
||||
.setType(Accessor.Type.VEC3)
|
||||
.setArray(new Float32Array([0, 0, 0, 40, 0, 0]))
|
||||
.setBuffer(buffer))
|
||||
.setAttribute("ROTATION", document.createAccessor("ROTATION")
|
||||
.setType(Accessor.Type.VEC4)
|
||||
.setArray(new Float32Array([0, 0, 0, 1, 0, 0, Math.SQRT1_2, Math.SQRT1_2]))
|
||||
.setBuffer(buffer))
|
||||
.setAttribute("SCALE", document.createAccessor("SCALE")
|
||||
.setType(Accessor.Type.VEC3)
|
||||
.setArray(new Float32Array([2, 1, 1, 1, 3, 1]))
|
||||
.setBuffer(buffer));
|
||||
node.setExtension("EXT_mesh_gpu_instancing", instancedMesh);
|
||||
document.createScene("fixture-scene").addChild(node);
|
||||
const io = new NodeIO().registerExtensions([EXTMeshGPUInstancing]);
|
||||
await io.write(fixtureFile, document);
|
||||
|
||||
const parsed = await io.read(fixtureFile);
|
||||
const parsedNode = parsed.getRoot().listNodes().find((candidate) => candidate.getName() === "fixture-node");
|
||||
const transforms = nodeInstanceTransforms(parsedNode);
|
||||
assert.equal(transforms.length, 2, "NodeIO reads both instance records");
|
||||
|
||||
const worldMatrix = parsedNode.getWorldMatrix();
|
||||
const triangle = [[0, 0, 0], [1, 0, 0], [0, 1, 0]];
|
||||
const uvTriangle = [[0, 0], [1, 0], [0, 1]];
|
||||
const collinearUvs = [[0, 0], [1, 1], [2, 2]];
|
||||
const expandedTriangles = transforms.map((transform) => triangle.map((point) =>
|
||||
transformInstancedPoint(worldMatrix, point, transform)));
|
||||
|
||||
const areas = expandedTriangles.map(triangleArea);
|
||||
assert.ok(Math.abs(areas[0] - 2) < 1e-9 && Math.abs(areas[1] - 3) < 1e-6,
|
||||
"instance and node scales transform each triangle's area");
|
||||
assert.ok(Math.abs(areas.reduce((total, area) => total + area, 0) - 5) < 1e-6,
|
||||
"both placed triangles contribute their transformed surface area");
|
||||
const cells = expandedTriangles.map((points) => {
|
||||
const centroidX = points.reduce((total, point) => total + point[0] / 3, 0);
|
||||
return Math.floor(centroidX / 20);
|
||||
});
|
||||
assert.deepEqual(cells, [0, 4], "instance TRS precedes the non-identity node world transform");
|
||||
|
||||
for (const points of expandedTriangles) {
|
||||
const valid = mappingMetrics(points, uvTriangle, 1024, 1024);
|
||||
const degenerate = mappingMetrics(points, collinearUvs, 1024, 1024);
|
||||
assert.ok(valid && valid.uvDoubleArea > 0 && valid.smallestStretchPxPerMeter > 0,
|
||||
"an invertible texture mapping retains UV rank under instance TRS");
|
||||
assert.equal(degenerate?.uvDoubleArea, 0, "collinear UVs remain degenerate under instance TRS");
|
||||
}
|
||||
} finally {
|
||||
await rm(temporaryDirectory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user