Files
healer-man/scripts/runewaker-pipeline/lib/native-water-geometry.test.mjs
T
2026-10-06 22:25:34 -04:00

94 lines
4.0 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import { buildNativeWaterGeometry } from "./native-water-geometry.mjs";
const primaryPlacement = {
translation: [2, 3, 4],
rotation: [0, 0, 0, 1],
scale: [1, 1, 1],
};
function fixtureLayer({ flags = [0xff, 0xdf, 0x9f, 0xbf, 0x80, 0x00, 0xff, 0x9f, 0xbf] } = {}) {
const colors = [
0xff112233, 0xff445566, 0xff778899,
0xffaabbcc, 0xffddeeff, 0xff010203,
0xff102030, 0xff405060, 0xff708090,
];
return {
classGuid: "test-water",
version: 3,
waterBodyGuid: "exact-body-guid",
transform: { scale: [2, 1, 1], rotation: [0, 0, 0, 1], translation: [100, 5, 200] },
height: {
origin: [0, 0, 0], spacing: 10, overlap: 0, width: 3, height: 3,
values: Float32Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9]),
},
color: {
present: true, origin: [0, 0, 0], spacing: 10, overlap: 0, width: 3, height: 3,
values: Uint32Array.from(colors),
},
flags: {
origin: [0, 0, 0], spacing: 10, overlap: 0, width: 3, height: 3,
values: Uint8Array.from(flags),
},
descriptorJoin: {
strategy: "exact serialized body GUID bytes",
status: "matched",
descriptorKeys: ["body-row"],
descriptors: [{ key: "body-row", guid: "exact-body-guid", effectType: 4 }],
},
unbuildableReason: null,
};
}
function assertClose(actual, expected, epsilon = 1e-6) {
assert.equal(actual.length, expected.length);
for (let index = 0; index < expected.length; index += 1) {
assert.ok(Math.abs(actual[index] - expected[index]) <= epsilon, `value[${index}] ${actual[index]} != ${expected[index]}`);
}
}
test("native water geometry expands even and odd pair patterns with one reflected-Z winding reversal", () => {
const built = buildNativeWaterGeometry([fixtureLayer()], primaryPlacement, 0.1);
const [water] = built.layers;
assert.equal(water.summary.consideredTwoCellQuadPairs, 2);
assert.equal(water.summary.emittedTwoCellQuadPairs, 2);
assert.equal(water.summary.emittedTriangles, 8);
assert.deepEqual(Array.from(water.indices.slice(0, 12)), [0, 4, 3, 0, 1, 4, 1, 2, 4, 2, 5, 4]);
assert.deepEqual(Array.from(water.indices.slice(12, 24)), [3, 4, 6, 4, 7, 6, 4, 5, 8, 4, 8, 7]);
assertClose(Array.from(water.positions.slice(0, 3)), [9.8, 0.3, -19.6]);
assert.equal(water.summary.sourceSplitPlaneHeight, 6);
assertClose(Array.from(water.positions.slice(3, 6)), [11.8, 0.4, -19.6]);
assertClose(Array.from(water.sourceWorldXZ.slice(0, 6)), [100, 200, 120, 200, 140, 200]);
assertClose(Array.from(water.sourceWorldXZ.slice(6, 12)), [100, 210, 120, 210, 140, 210]);
assert.deepEqual(Array.from(water.normals.slice(0, 3)), [0, 1, 0]);
assertClose(Array.from(water.colors.slice(0, 4)), [17 / 255, 34 / 255, 51 / 255, 1]);
assertClose([water.colors[1 * 4 + 3]], [125 / 255]);
assert.equal(water.layer.descriptorJoin.descriptors[0].effectType, 4);
});
test("water visibility bit masks pair geometry while preserving per-vertex diffuse alpha", () => {
const hidden = buildNativeWaterGeometry([fixtureLayer({ flags: new Array(9).fill(0x3f) })], primaryPlacement, 0.1);
assert.equal(hidden.layers[0].indices.length, 0);
assert.equal(hidden.layers[0].colors[3], 1);
const visibleFromOneVertex = buildNativeWaterGeometry([fixtureLayer({ flags: [0x80, 0, 0, 0, 0, 0, 0, 0, 0] })], primaryPlacement, 0.1);
assert.equal(visibleFromOneVertex.layers[0].summary.emittedTriangles, 4);
assert.equal(visibleFromOneVertex.layers[0].colors[3], 0);
});
test("native water builder refuses non-exact material joins and missing source color bytes", () => {
const unmatched = fixtureLayer();
unmatched.descriptorJoin.status = "missing";
assert.throws(() => buildNativeWaterGeometry([unmatched], primaryPlacement, 0.1), /descriptor GUID join is missing/);
const v1 = fixtureLayer();
v1.color = { present: false };
v1.unbuildableReason = "native v1 color absent";
const result = buildNativeWaterGeometry([v1], primaryPlacement, 0.1);
assert.equal(result.layers.length, 0);
assert.equal(result.skipped[0].reason, "native v1 color absent");
});