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,208 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { mkdtemp, rm } from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { deflateSync } from "node:zlib";
|
||||
import test from "node:test";
|
||||
import { Document, NodeIO } from "@gltf-transform/core";
|
||||
import { ALL_EXTENSIONS, KHRMaterialsSpecular } from "@gltf-transform/extensions";
|
||||
import { MeshoptDecoder } from "meshoptimizer";
|
||||
import { environmentOptimizationArguments } from "./environment-optimization.mjs";
|
||||
import { applyNativeMaterialSemantics, hasVerifiedNativeMaterialIdentity } from "./native-material-semantics.mjs";
|
||||
|
||||
const scriptDirectory = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.resolve(scriptDirectory, "../../..");
|
||||
const gltfTransformCli = path.join(projectRoot, "node_modules/@gltf-transform/cli/bin/cli.js");
|
||||
|
||||
const nativeIdentity = {
|
||||
nativeSourceModel: "model\\dungeon\\the_origin\\act_precipice_01.ros",
|
||||
nativeSourceResourceSha256: "b".repeat(64),
|
||||
nativeMaterialIndex: 8,
|
||||
nativeSourceTexture: "texture\\dungeon\\the_origin\\wave_01",
|
||||
};
|
||||
|
||||
function crc32(bytes) {
|
||||
let crc = 0xffffffff;
|
||||
for (const byte of bytes) {
|
||||
crc ^= byte;
|
||||
for (let bit = 0; bit < 8; bit += 1) crc = (crc >>> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
|
||||
}
|
||||
return (crc ^ 0xffffffff) >>> 0;
|
||||
}
|
||||
|
||||
function pngChunk(type, data) {
|
||||
const typeBytes = Buffer.from(type, "ascii");
|
||||
const contents = Buffer.concat([typeBytes, data]);
|
||||
const header = Buffer.alloc(4);
|
||||
header.writeUInt32BE(data.length);
|
||||
const checksum = Buffer.alloc(4);
|
||||
checksum.writeUInt32BE(crc32(contents));
|
||||
return Buffer.concat([header, contents, checksum]);
|
||||
}
|
||||
|
||||
function patternedPng() {
|
||||
const header = Buffer.alloc(13);
|
||||
header.writeUInt32BE(2, 0);
|
||||
header.writeUInt32BE(2, 4);
|
||||
header[8] = 8;
|
||||
header[9] = 6;
|
||||
const rows = Buffer.from([
|
||||
0, 210, 170, 125, 255, 15, 80, 210, 255,
|
||||
0, 25, 240, 95, 255, 160, 20, 180, 255,
|
||||
]);
|
||||
return Buffer.concat([
|
||||
Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]),
|
||||
pngChunk("IHDR", header),
|
||||
pngChunk("IDAT", deflateSync(rows)),
|
||||
pngChunk("IEND", Buffer.alloc(0)),
|
||||
]);
|
||||
}
|
||||
|
||||
async function writeFixture(file, extras) {
|
||||
const document = new Document();
|
||||
const buffer = document.createBuffer();
|
||||
const position = document.createAccessor()
|
||||
.setType("VEC3")
|
||||
.setArray(new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]))
|
||||
.setBuffer(buffer);
|
||||
const material = document.createMaterial("native wave")
|
||||
.setAlphaMode("BLEND")
|
||||
.setExtras(extras);
|
||||
material.setExtension("KHR_materials_specular",
|
||||
document.createExtension(KHRMaterialsSpecular).createSpecular().setSpecularFactor(0));
|
||||
const primitive = document.createPrimitive()
|
||||
.setAttribute("POSITION", position)
|
||||
.setMaterial(material);
|
||||
const mesh = document.createMesh("wave mesh").addPrimitive(primitive);
|
||||
const node = document.createNode("wave node").setMesh(mesh);
|
||||
const scene = document.createScene("fixture scene").addChild(node);
|
||||
document.getRoot().setDefaultScene(scene);
|
||||
await new NodeIO().registerExtensions(ALL_EXTENSIONS).write(file, document);
|
||||
}
|
||||
|
||||
test("adds KHR_materials_unlit only to exact-proven prelit materials and retains additive extras", async () => {
|
||||
const directory = await mkdtemp(path.join(os.tmpdir(), "rom-native-material-"));
|
||||
try {
|
||||
const file = path.join(directory, "wave.glb");
|
||||
await writeFixture(file, {
|
||||
...nativeIdentity,
|
||||
nativeBlendMode: "additive",
|
||||
nativeAlphaPolicy: "native-srcalpha-one-additive",
|
||||
nativeLightingType: "prelit",
|
||||
});
|
||||
const report = await applyNativeMaterialSemantics(file);
|
||||
assert.equal(report.khrMaterialsUnlit.length, 1);
|
||||
assert.equal(report.nativeAdditiveMaterials.length, 1);
|
||||
assert.equal(report.nativeAdditiveMaterials[0].alphaMode, "BLEND");
|
||||
|
||||
const document = await new NodeIO().registerExtensions(ALL_EXTENSIONS).read(file);
|
||||
const material = document.getRoot().listMaterials()[0];
|
||||
assert.ok(material.getExtension("KHR_materials_unlit"));
|
||||
assert.equal(material.getExtension("KHR_materials_specular"), null);
|
||||
assert.equal(material.getExtras().nativeBlendMode, "additive");
|
||||
assert.equal(material.getAlphaMode(), "BLEND");
|
||||
} finally {
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("rejects prelit claims without complete native material identity", async () => {
|
||||
assert.equal(hasVerifiedNativeMaterialIdentity(nativeIdentity), true);
|
||||
assert.equal(hasVerifiedNativeMaterialIdentity({ ...nativeIdentity, nativeSourceResourceSha256: "bad" }), false);
|
||||
|
||||
const directory = await mkdtemp(path.join(os.tmpdir(), "rom-native-material-invalid-"));
|
||||
try {
|
||||
const file = path.join(directory, "bad.glb");
|
||||
await writeFixture(file, { nativeLightingType: "prelit", ...nativeIdentity, nativeMaterialIndex: -1 });
|
||||
await assert.rejects(() => applyNativeMaterialSemantics(file), /lacks verified material provenance/);
|
||||
} finally {
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
test("gltf-transform optimize keeps shared-map standard and prelit materials distinct", async (context) => {
|
||||
const directory = await mkdtemp(path.join(os.tmpdir(), "rom-native-material-optimize-"));
|
||||
context.after(async () => rm(directory, { recursive: true, force: true }));
|
||||
const sourceFile = path.join(directory, "source.glb");
|
||||
const outputFile = path.join(directory, "optimized.glb");
|
||||
|
||||
const document = new Document();
|
||||
const buffer = document.createBuffer();
|
||||
const image = document.createTexture("shared-water-image")
|
||||
.setMimeType("image/png")
|
||||
.setImage(patternedPng());
|
||||
const positions = document.createAccessor("triangle positions")
|
||||
.setType("VEC3")
|
||||
.setArray(new Float32Array([0, 0, 0, 1, 0, 0, 0, 1, 0]))
|
||||
.setBuffer(buffer);
|
||||
const texcoords = document.createAccessor("triangle UVs")
|
||||
.setType("VEC2")
|
||||
.setArray(new Float32Array([0, 0, 1, 0, 0, 1]))
|
||||
.setBuffer(buffer);
|
||||
const indices = document.createAccessor("triangle indices")
|
||||
.setType("SCALAR")
|
||||
.setArray(new Uint16Array([0, 1, 2]))
|
||||
.setBuffer(buffer);
|
||||
|
||||
const scene = document.createScene("shared scene");
|
||||
for (const [name, lightingType, nativeMaterialIndex] of [
|
||||
["standard water", "standard", 8],
|
||||
["prelit water", "prelit", 9],
|
||||
]) {
|
||||
const material = document.createMaterial(name)
|
||||
.setBaseColorTexture(image)
|
||||
.setExtras({ ...nativeIdentity, nativeMaterialIndex, nativeLightingType: lightingType });
|
||||
const primitive = document.createPrimitive()
|
||||
.setAttribute("POSITION", positions)
|
||||
.setAttribute("TEXCOORD_0", texcoords)
|
||||
.setIndices(indices)
|
||||
.setMaterial(material);
|
||||
const mesh = document.createMesh(`${name} mesh`).addPrimitive(primitive);
|
||||
scene.addChild(document.createNode(name).setMesh(mesh));
|
||||
}
|
||||
document.getRoot().setDefaultScene(scene);
|
||||
|
||||
const io = new NodeIO()
|
||||
.registerExtensions(ALL_EXTENSIONS)
|
||||
.registerDependencies({ "meshopt.decoder": MeshoptDecoder });
|
||||
await io.write(sourceFile, document);
|
||||
assert.ok((await io.read(sourceFile)).getRoot().listMaterials().every((material) => material.getBaseColorTexture()));
|
||||
const semantics = await applyNativeMaterialSemantics(sourceFile);
|
||||
assert.equal(semantics.khrMaterialsUnlit.length, 1);
|
||||
|
||||
// Keep the fixture materials identical apart from the glTF lighting extension,
|
||||
// isolating the behavior at risk from optimizer material de-duplication.
|
||||
const annotated = await io.read(sourceFile);
|
||||
for (const material of annotated.getRoot().listMaterials()) material.setExtras({});
|
||||
await io.write(sourceFile, annotated);
|
||||
assert.equal((await io.read(sourceFile)).getRoot().listMaterials().filter((material) => material.getBaseColorTexture()).length, 2);
|
||||
|
||||
const args = environmentOptimizationArguments(sourceFile, outputFile);
|
||||
const run = spawnSync(process.execPath, [gltfTransformCli, ...args], {
|
||||
cwd: projectRoot,
|
||||
encoding: "utf8",
|
||||
windowsHide: true,
|
||||
});
|
||||
assert.equal(run.status, 0, `${run.stdout}\n${run.stderr}`);
|
||||
|
||||
const optimized = await io.read(outputFile);
|
||||
const materials = optimized.getRoot().listMaterials();
|
||||
assert.equal(materials.length, 2, "optimization must not merge materials with different lighting modes");
|
||||
const unlitMaterials = materials.filter((material) => material.getExtension("KHR_materials_unlit"));
|
||||
assert.equal(unlitMaterials.length, 1);
|
||||
assert.equal(materials.filter((material) => !material.getExtension("KHR_materials_unlit")).length, 1);
|
||||
assert.ok(materials.every((material) => material.getBaseColorTexture()), JSON.stringify(materials.map((material) => ({
|
||||
name: material.getName(),
|
||||
texture: material.getBaseColorTexture()?.getName() ?? null,
|
||||
unlit: Boolean(material.getExtension("KHR_materials_unlit")),
|
||||
})).concat([{
|
||||
textureCount: optimized.getRoot().listTextures().length,
|
||||
sceneChildren: optimized.getRoot().listScenes().flatMap((entry) => entry.listChildren()).length,
|
||||
primitives: optimized.getRoot().listMeshes().flatMap((mesh) => mesh.listPrimitives()).map((primitive) => ({
|
||||
material: primitive.getMaterial()?.getName(),
|
||||
attributes: Object.keys(primitive.listAttributes()),
|
||||
})),
|
||||
}])));
|
||||
});
|
||||
Reference in new issue
Block a user