Fail fast on missing terrain assets and recover empty renders
This commit is contained in:
79
tests/renderer-geometry.test.ts
Normal file
79
tests/renderer-geometry.test.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import sharp from "sharp";
|
||||
import { OpaqueIndex, QuadBuffer } from "../renderer/mesh-buffers.mjs";
|
||||
import { assertTerrainImage } from "../renderer/image-validation.mjs";
|
||||
|
||||
test("opaque sections preserve negative coordinates and do not alias adjacent boundaries", () => {
|
||||
const index = new OpaqueIndex(
|
||||
{ minX: -32, minZ: -32, maxX: 32, maxZ: 32 },
|
||||
-32,
|
||||
32,
|
||||
);
|
||||
const expected = new Set<string>();
|
||||
for (let x = -32; x <= 32; x++) {
|
||||
for (let y = -32; y <= 32; y++) {
|
||||
for (let z = -32; z <= 32; z++) {
|
||||
if ((x * 3 + y * 7 + z * 11) % 23 === 0) {
|
||||
index.add(x, y, z);
|
||||
expected.add(`${x},${y},${z}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let x = -33; x <= 49; x++) {
|
||||
for (let y = -33; y <= 49; y++) {
|
||||
for (let z = -33; z <= 49; z++) {
|
||||
assert.equal(index.has(x, y, z), expected.has(`${x},${y},${z}`));
|
||||
}
|
||||
}
|
||||
}
|
||||
index.clear();
|
||||
assert.equal(index.has(0, 0, 0), false);
|
||||
});
|
||||
|
||||
test("geometry batches retain every quad through growth with valid triangle indices and bounds", () => {
|
||||
const buffer = new QuadBuffer();
|
||||
const face = {
|
||||
positions: new Float64Array([0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0]),
|
||||
uvs: new Float32Array([0, 0, 1, 0, 0, 1, 1, 1]),
|
||||
normal: [0, 0, -1],
|
||||
};
|
||||
for (let i = 0; i < 4096; i++) buffer.add(face, i - 2048, 64, -1);
|
||||
assert.equal(buffer.full, true);
|
||||
assert.throws(() => buffer.add(face, 0, 0, 0), /full/);
|
||||
const data = buffer.finish();
|
||||
assert.equal(data.positions.length, 4096 * 12);
|
||||
assert.equal(data.indices.length, 4096 * 6);
|
||||
assert.equal(Math.max(...data.indices), 4096 * 4 - 1);
|
||||
assert.deepEqual(
|
||||
[...data.indices.slice(-6)],
|
||||
[16380, 16381, 16382, 16382, 16381, 16383],
|
||||
);
|
||||
assert.deepEqual(data.min, [-2048, 64, -1]);
|
||||
assert.deepEqual(data.max, [2048, 65, -1]);
|
||||
});
|
||||
|
||||
test("sky-only WebP output is rejected instead of becoming a playable draft", async () => {
|
||||
const sky = await sharp({
|
||||
create: { width: 128, height: 128, channels: 3, background: "#95c4eb" },
|
||||
})
|
||||
.webp({ quality: 85 })
|
||||
.toBuffer();
|
||||
await assert.rejects(
|
||||
assertTerrainImage(sky, "Surface map"),
|
||||
/contains only sky/,
|
||||
);
|
||||
});
|
||||
|
||||
test("flat textured terrain is accepted even when its colors are nearly uniform", async () => {
|
||||
const terrain = await sharp({
|
||||
create: { width: 128, height: 128, channels: 3, background: "#719447" },
|
||||
})
|
||||
.webp()
|
||||
.toBuffer();
|
||||
assert.equal(
|
||||
await assertTerrainImage(terrain, "Panorama p0, downward face"),
|
||||
64 * 64,
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user