Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/flo-bit/shapecraft. flo-bit.dev/shapecraft
Something went wrong. Try again.
4.0 kB · 103 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104import { describe, it, expect } from 'vitest'import { tree, pine, palm, bush, grass, fern, flower, deadTree, leafyTree, rock, sharpRock, blockRock, mushroom } from '../src/generators'import type { Mesh } from '../src/core/mesh'import type { Asset } from '../src/core/asset'
const generators = [ { name: 'tree', gen: tree }, { name: 'pine', gen: pine }, { name: 'palm', gen: palm }, { name: 'bush', gen: bush }, { name: 'grass', gen: grass }, { name: 'fern', gen: fern }, { name: 'flower', gen: flower }, { name: 'dead', gen: deadTree }, { name: 'leafy', gen: leafyTree }, { name: 'rock', gen: rock }, { name: 'sharp', gen: sharpRock }, { name: 'block', gen: blockRock }, { name: 'mushroom', gen: mushroom },] as const
// Generators that support snow (trees, shrubs, rocks). Grass/ferns don't take snow options.const snowGenerators = generators.filter((g) => ['tree', 'pine', 'palm', 'bush', 'leafy', 'rock', 'sharp', 'block'].includes(g.name))
// Golden snapshots captured after the named-stream RNG migration. A change here means// generator output shifted — intentional changes should update these numbers deliberately.const golden: Record<string, { verts: number }> = { tree: { verts: 1830 }, pine: { verts: 840 }, palm: { verts: 3630 }, bush: { verts: 3600 }, grass: { verts: 1632 }, fern: { verts: 13932 }, flower: { verts: 1050 }, dead: { verts: 1400 }, leafy: { verts: 7020 }, rock: { verts: 1440 }, sharp: { verts: 696 }, block: { verts: 432 }, mushroom: { verts: 1584 },}
function allFinite(m: Mesh | Asset): boolean { const p = m.positions for (let i = 0; i < p.length; i++) if (!Number.isFinite(p[i])) return false return true}
describe.each(generators)('$name generator', ({ name, gen }) => { it('produces a valid, colored, finite mesh', () => { const m = gen({ seed: 1 }) expect(m.vertexCount).toBeGreaterThan(0) expect(m.colors).not.toBeNull() expect(allFinite(m)).toBe(true) })
it('matches the golden vertex count for seed 1', () => { expect(gen({ seed: 1 }).vertexCount).toBe(golden[name].verts) })
it('is deterministic: same seed → identical positions', () => { const a = gen({ seed: 7 }).positions const b = gen({ seed: 7 }).positions expect(Array.from(a)).toEqual(Array.from(b)) })
it('different seeds produce different geometry', () => { const a = gen({ seed: 1 }).positions const b = gen({ seed: 2 }).positions expect(Array.from(a)).not.toEqual(Array.from(b)) })})
describe('stream independence at the model level', () => { // The headline benefit of named streams: a feature that only affects color (snow) // must not perturb geometry, because positions come from independent streams. it.each(snowGenerators)('$name: painted snow (depth 0) leaves geometry byte-identical', ({ gen }) => { const bare = gen({ seed: 3, snowColors: [] }) const snowy = gen({ seed: 3, snowColors: ['#ffffff', '#eeeeee'] })
// Same geometry... expect(Array.from(snowy.positions)).toEqual(Array.from(bare.positions)) // ...but different coloring. expect(Array.from(snowy.colors!)).not.toEqual(Array.from(bare.colors!)) })})
describe('geometric snow (snowDepth > 0)', () => { it.each(snowGenerators)('$name: adds a snow layer of real geometry', ({ gen }) => { const bare = gen({ seed: 4, snowColors: [] }) const snowy = gen({ seed: 4, snowColors: ['#eef0f5'], snowDepth: 0.08 }) // The snow shell adds vertices on top of the model. expect(snowy.vertexCount).toBeGreaterThan(bare.vertexCount) // And reaches higher than the bare model (snow sits on top). expect(snowy.boundingBox.max.y).toBeGreaterThan(bare.boundingBox.max.y) })
it.each(snowGenerators)('$name: geometric snow is deterministic', ({ gen }) => { const a = gen({ seed: 4, snowColors: ['#eef0f5'], snowDepth: 0.08 }).positions const b = gen({ seed: 4, snowColors: ['#eef0f5'], snowDepth: 0.08 }).positions expect(Array.from(a)).toEqual(Array.from(b)) })})