Files
healer-man/scripts/dungeon-pipeline/lib/wow-adt-terrain-material.test.mjs
T
2026-10-07 13:05:04 -04:00

78 lines
2.8 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { composeWowAdtTerrainWeights, decodeWowAdtAlphaMap, wowAdtNormalizedUv } from "./wow-adt-terrain-material.mjs";
function layer(index, alphaMapEncoding, alphaMapDataOffset, alphaMapBytes, flags = 0x100) {
return {
index,
usesAlphaMap: (flags & 0x100) !== 0,
alphaMapCompressed: (flags & 0x200) !== 0,
alphaMapAvailable: true,
alphaMapEncoding,
alphaMapDataOffset,
alphaMapBytes,
alphaOffset: alphaMapDataOffset,
flags,
};
}
test("classic 4-bit maps expand and get deterministic edge repair", () => {
const bytes = Buffer.alloc(2048, 0x21);
const chunk = { indexX: 4, indexY: 7, flags: 0, layers: [] };
const decoded = decodeWowAdtAlphaMap(bytes, chunk, layer(1, "packed-4", 0, 2048));
assert.equal(decoded[0], 17);
assert.equal(decoded[1], 34);
assert.equal(decoded[63], decoded[62]);
assert.equal(decoded[63 * 64], decoded[62 * 64]);
chunk.flags = 0x8000;
const untouched = decodeWowAdtAlphaMap(bytes, chunk, layer(1, "packed-4", 0, 2048));
assert.equal(untouched[63], 34);
assert.equal(untouched[63 * 64], 17);
});
test("classic 4-bit opacity layers become ordered residual weights", () => {
const bytes = Buffer.alloc(4096, 0x88);
const chunk = {
indexX: 0,
indexY: 0,
flags: 0x8000,
layers: [
{ index: 0, usesAlphaMap: false },
layer(1, "packed-4", 0, 2048),
layer(2, "packed-4", 2048, 2048),
],
};
const weights = composeWowAdtTerrainWeights(bytes, chunk);
assert.equal(weights.sourcePolicy, "classic-nibble-to-big-alpha");
assert.deepEqual(weights.channelLayerIndices, [1, 2]);
assert.equal(weights.rgba[0], 63); // earlier overlay receives only remaining coverage
assert.equal(weights.rgba[1], 136); // last layer remains topmost
assert.equal(weights.rgba[2], 0);
assert.equal(weights.rgba[3], 255);
assert.equal(weights.maxWeightSum, 199);
});
test("compressed 8-bit MCAL fills exactly one 64x64 map", () => {
const packed = [];
let remaining = 4096;
while (remaining) {
const count = Math.min(127, remaining);
packed.push(0x80 | count, 37);
remaining -= count;
}
const bytes = Buffer.from(packed);
const chunk = { indexX: 1, indexY: 2, flags: 0x8000, layers: [] };
const decoded = decodeWowAdtAlphaMap(bytes, chunk, layer(1, "rle-8", 0, bytes.length, 0x300));
assert.equal(decoded.length, 4096);
assert.equal(decoded[0], 37);
assert.equal(decoded[4095], 37);
assert.throws(() => decodeWowAdtAlphaMap(Buffer.from([0x81]), chunk, layer(1, "rle-8", 0, 1, 0x300)), /truncated MCAL fill/);
});
test("normalized MCVT UVs follow source-positive local rows and stagger", () => {
assert.deepEqual(wowAdtNormalizedUv(0, 0), [0, 0]);
assert.deepEqual(wowAdtNormalizedUv(1, 0), [0.0625, 0.0625]);
assert.deepEqual(wowAdtNormalizedUv(16, 8), [1, 1]);
});