forked from phenom/healer-man
92 lines
5.0 KiB
JavaScript
92 lines
5.0 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { spawnSync } from "node:child_process";
|
|
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
import { Document, NodeIO } from "@gltf-transform/core";
|
|
import { ALL_EXTENSIONS, KHRMaterialsVariants } from "@gltf-transform/extensions";
|
|
import sharp from "sharp";
|
|
import { MeshoptDecoder } from "meshoptimizer";
|
|
|
|
import { environmentOptimizationArguments } from "../lib/environment-optimization.mjs";
|
|
|
|
const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../..");
|
|
const gltfTransformCli = path.join(projectRoot, "node_modules/@gltf-transform/cli/bin/cli.js");
|
|
const io = new NodeIO()
|
|
.registerExtensions(ALL_EXTENSIONS)
|
|
.registerDependencies({ "meshopt.decoder": MeshoptDecoder });
|
|
|
|
test("real glTF Transform optimize preserves opted-in material variant carriers and UVs", async (context) => {
|
|
await MeshoptDecoder.ready;
|
|
const workingDirectory = await mkdtemp(path.join(os.tmpdir(), "runewaker-water-variant-opt-"));
|
|
context.after(async () => rm(workingDirectory, { recursive: true, force: true }));
|
|
const sourceFile = path.join(workingDirectory, "water-variant-source.glb");
|
|
const outputFile = path.join(workingDirectory, "water-variant-optimized.glb");
|
|
|
|
const document = new Document();
|
|
const buffer = document.createBuffer("fixture");
|
|
const variants = document.createExtension(KHRMaterialsVariants).setRequired(false);
|
|
const normalPng = await sharp({
|
|
create: { width: 4, height: 4, channels: 4, background: { r: 128, g: 128, b: 255, alpha: 1 } },
|
|
}).png().toBuffer();
|
|
const normalTexture = document.createTexture("native-normal-frame")
|
|
.setImage(normalPng)
|
|
.setMimeType("image/png");
|
|
const regularMaterial = document.createMaterial("source-water").setAlphaMode("BLEND");
|
|
const frameMaterial = document.createMaterial("normal-frame-00")
|
|
.setNormalTexture(normalTexture)
|
|
.setAlphaMode("OPAQUE");
|
|
frameMaterial.getNormalTextureInfo().setWrapS(10497).setWrapT(10497);
|
|
const variant = variants.createVariant("native-frame-00");
|
|
const mapping = variants.createMappingList().addMapping(
|
|
variants.createMapping().setMaterial(frameMaterial).addVariant(variant),
|
|
);
|
|
const primitive = document.createPrimitive()
|
|
.setAttribute("POSITION", document.createAccessor("positions", buffer)
|
|
.setType("VEC3")
|
|
.setArray(new Float32Array([0, 0, 0, 1, 0, 0, 0, 0, 1])))
|
|
.setAttribute("NORMAL", document.createAccessor("normals", buffer)
|
|
.setType("VEC3")
|
|
.setArray(new Float32Array([0, 1, 0, 0, 1, 0, 0, 1, 0])))
|
|
.setAttribute("TEXCOORD_0", document.createAccessor("source-world-xz", buffer)
|
|
.setType("VEC2")
|
|
.setArray(new Float32Array([100, 200, 110, 200, 100, 210])))
|
|
.setIndices(document.createAccessor("indices", buffer).setArray(new Uint16Array([0, 1, 2])))
|
|
.setMaterial(regularMaterial)
|
|
.setExtension(KHRMaterialsVariants.EXTENSION_NAME, mapping);
|
|
const mesh = document.createMesh("native-water").addPrimitive(primitive);
|
|
const scene = document.createScene("scene").addChild(document.createNode("water-layer").setMesh(mesh));
|
|
document.getRoot().setDefaultScene(scene);
|
|
await io.write(sourceFile, document);
|
|
|
|
const args = environmentOptimizationArguments(sourceFile, outputFile, { preserveMaterialVariantCarriers: true });
|
|
assert.equal(args[args.indexOf("--join") + 1], "false");
|
|
assert.equal(args[args.indexOf("--prune") + 1], "false");
|
|
assert.equal(args[args.indexOf("--prune-attributes") + 1], "false");
|
|
const waterArgs = environmentOptimizationArguments(sourceFile, outputFile, { preserveNativeWaterLayers: true });
|
|
assert.equal(waterArgs[waterArgs.indexOf("--join") + 1], "false", "native water keeps its existing carrier-preservation behavior");
|
|
const optimized = spawnSync(process.execPath, [gltfTransformCli, ...args], {
|
|
cwd: projectRoot,
|
|
encoding: "utf8",
|
|
windowsHide: true,
|
|
});
|
|
assert.equal(optimized.status, 0, `${optimized.stdout}\n${optimized.stderr}`);
|
|
|
|
const output = await io.read(outputFile);
|
|
const outputMesh = output.getRoot().listMeshes().find((candidate) => candidate.getName() === "native-water");
|
|
const outputPrimitive = outputMesh?.listPrimitives()[0];
|
|
assert.ok(outputPrimitive, "optimized water primitive must remain present");
|
|
const texcoords = outputPrimitive.getAttribute("TEXCOORD_0");
|
|
assert.ok(texcoords, "normal-texture variant must retain its required UV0 attribute");
|
|
assert.equal(texcoords.getType(), "VEC2");
|
|
assert.deepEqual(Array.from(texcoords.getArray()), [100, 200, 110, 200, 100, 210]);
|
|
const outputMapping = outputPrimitive.getExtension(KHRMaterialsVariants.EXTENSION_NAME)?.listMappings()[0];
|
|
assert.ok(outputMapping, "KHR_materials_variants mapping must survive optimize");
|
|
assert.equal(outputMapping.getMaterial()?.getNormalTexture()?.getName(), "native-normal-frame");
|
|
assert.deepEqual(outputMapping.listVariants().map((item) => item.getName()), ["native-frame-00"]);
|
|
assert.ok((await readFile(outputFile)).length > 0);
|
|
});
|