Commit graph

46 commits

Author SHA1 Message Date
Kelsi
78c7aed888 feat(editor): add --gen-texture-rust-streaks vertical-drip pattern
64th procedural texture: vertical rust drips on a metal base.
Each streak is a hash-derived (x position, width 1..4 px,
top y, length H/3..H) band that fades from full rust at the
top to bg at the bottom — the "streak" effect of years of
rain washing rust down from rivets and seams.

Distinct from --gen-texture-rust (generic surface noise) —
this is the directional-drip variant for:
  • weathered metal walls (especially under high windows)
  • sewer-grate backings under standing puddles
  • ship-hull stains below scupper ports
  • abandoned-machinery panels under leaking pipes

Deterministic from seed: re-running with same args produces
the byte-identical image. Default 40 streaks at 256x256
gives a reasonable "lightly aged" intensity; bump
streakCount for heavier corrosion.
2026-05-09 12:33:25 -07:00
Kelsi
facaacd0c6 feat(editor): add --gen-blacksmith-pack + extract emitMeshPack
Two changes in one commit because they're co-designed:

  • Extract emitMeshPack(outDir, packName, items) as a shared
    helper that takes a vector of PackItem {flag, fn, leaf}
    and runs each handler with a synthetic argv. Keeps the
    "build a 2-element argv per sub-handler" wiring in one
    place instead of copy-pasted per pack.

  • Add --gen-blacksmith-pack on top: a smithy-themed
    composite emitting forge + anvil + workbench +
    water-trough + crate-stack + hitching-post into outDir.
    The classic forge-floor layout in 6 .wom files.

Refactors --gen-camp-pack to use emitMeshPack (verified
unchanged: 6 .wom files still land in the camp dir).
Pattern is now established for future packs (--gen-village-
pack, --gen-temple-pack, --gen-dock-pack…) — each is just a
list of primitives in 8 lines of code.
2026-05-09 12:31:34 -07:00
Kelsi
006beffb83 feat(editor): add --gen-mesh-forge blacksmith hearth
69th procedural mesh primitive. Built from up to 3 axis-
aligned boxes:

  • stone hearth: rectangular base spanning width × depth ×
    baseH, where the smith's fire would sit
  • hood: smaller smoke-collector box on top of the hearth,
    inset by hoodInset on each side so it reads as the
    chimney's flared base
  • optional thin chimney rising from the hood — set
    chimneyH=0 for an open-vented forge

Pairs naturally with --gen-mesh-anvil and
--gen-mesh-workbench for blacksmith/armorer/farrier scenes,
and with --gen-mesh-bench / --gen-mesh-crate-stack for
the storage corner of a smithy.

Watertight under weld (verified 54 manifold edges, 0
boundary, 0 non-manifold). Default 1.4×1.0×0.9 m hearth +
0.5 m hood + 1.2 m chimney reads as a normal village smithy.
2026-05-09 12:29:09 -07:00
Kelsi
b8cfc90fba feat(editor): add --gen-texture-blueprint drafting-paper grid
63rd procedural texture: minor + major grid lines on a base.
Minor lines at every `minorStride` pixels (default 16);
every `majorEvery` minor lines a thicker major line is drawn
(default every 4). Both axes get the same treatment so the
result is a sectioned drafting / engineer's paper look.

Distinct from --gen-texture-mesh-screen (uniform line
weight) — this is the periodic-emphasis variant. Good for:

  • drafting-table surfaces
  • technical-schematic backdrops
  • architect-shop / cartographer-shop walls
  • engineer / scholar ritual tables
  • star-chart room floors

Default 16-stride / every-4-major gives the classic blue
graph-paper aesthetic at 256x256. First procedural texture
that takes 4 numeric layout params plus W/H — exercises the
new parseOpt* helpers across more args than usual.
2026-05-09 12:27:15 -07:00
Kelsi
68db1be97a feat(editor): add --gen-mesh-outhouse small-shed primitive
68th procedural mesh primitive. Built from 3 axis-aligned
boxes:

  • solid body slab spanning width × depth × (height-roofT)
  • thin door slab on the +Z face (pushed slightly outward
    so it visually sits on the wall — gives doorframe-like
    relief without a real cutout)
  • roof slab slightly larger than the body footprint and
    sitting on top, controlled by roofOverhang

Distinct from --gen-mesh-house (multi-walled, peaked-roof
dwelling). An outhouse is the single-room privy / tool shed
variant — useful for villages, frontier outposts, small
farms, refuse-shed corners.

Watertight under weld (verified 54 manifold edges, 0
boundary, 0 non-manifold). First handler to use the new
setCenteredBoundsXZ helper from this batch.
2026-05-09 12:24:00 -07:00
Kelsi
0b1cf65854 feat(editor): add --gen-camp-pack convenience composite
Convenience composite command: emits a complete outdoor-camp
scene (tent + firepit + bedroll + canopy + woodpile +
haystack) into <outDir>/ as 6 .wom files in one invocation.

Internally builds a synthetic argv array per primitive and
calls each existing handler — so the camp pack always
matches the per-primitive defaults exactly. Users wanting
custom dimensions should call the individual --gen-mesh-*
commands.

Smoke tested:
  • Creates outDir if needed
  • All 6 .wom files validate clean (--validate-wom PASSED)
  • Vertex / triangle counts match per-primitive defaults
    (firepit 240/120, woodpile 324/288, etc.)

The first composite command in the editor — establishes the
pattern for future packs (--gen-village-pack, --gen-dock-pack,
etc.) by showing how synthetic argv arrays let one handler
delegate to many others without spawning subprocesses.
2026-05-09 12:22:37 -07:00
Kelsi
ba1f458ad3 feat(editor): add --gen-texture-bamboo jungle-stalk pattern
62nd procedural texture: vertical bamboo stalks with
cylindrical sin² brightness shading + horizontal darker
node bands at regular Y intervals. Each stalk gets a small
hash-derived hue jitter (±15) so adjacent stalks don't
read as a perfect repeat.

Per-pixel logic:
  • 10% horizontal gap between stalks (gapFrac=0.10) →
    visible bg seam between bamboo stalks
  • Inside the stalk, brightness = sin²(insetFraction * π)
    rising from 0 at the stalk edge to 1 at the centerline
  • Every nodeY pixels, a `nodeBand`-tall horizontal strip
    has its brightness knocked down to 2/3 — the segmented
    bamboo joint look

Useful for jungle huts, pandaren / asian-themed architecture,
swamp boardwalks, tropical-tribe weapon trim, brewmaster
zone trim. Default 24-pitch / 64-spacing / 4-band reads as
adult-bamboo at typical 256x256 wall-tile scale.
2026-05-09 12:20:11 -07:00
Kelsi
38d9575eb2 feat(editor): add --gen-mesh-hitching-post stable fixture
67th procedural mesh primitive. Standard town/stable
hitching post:

  • two vertical posts separated by `span`
  • horizontal cross-bar at upper-post height (length =
    span - postW so it tucks INSIDE the post inner faces,
    matching real fence joinery)
  • optional decorative caps on each post — set capH=0
    for a bare working-yard post

All axis-aligned boxes, exercises every shared helper
(stripExt, initWomDefaults, addFlatBox,
finalizeAsSingleBatch, saveWomOrError). Watertight under
weld (verified 90 manifold edges, 0 boundary, 0
non-manifold).

Useful for stables, taverns with mount parking, town
squares, frontier outposts, ranger camps, post-and-rail
fence segments.
2026-05-09 12:15:41 -07:00
Kelsi
b1fd3382a9 feat(editor): add --gen-texture-mesh-screen orthogonal grid
61st procedural texture: thin horizontal + vertical wires
forming an axis-aligned grid. Distinct from
--gen-texture-lattice (which uses ±45° diagonals to make
diamond openings) — this gives the right-angle window-
screen / chain-link / sci-fi-grille look.

Tested per-axis: a row is "on a wire" if (y % stride) <
wireW; a pixel falls on a wire if either its row OR its
column tests positive. Result is the unmistakable
orthogonal-mesh appearance.

Useful for window screens, anti-pest grates, fish nets,
sewer grilles, sci-fi vent panels, prison-cell windows,
goblin-workshop catwalks. Default 12-stride / 2-wide
gives a coarse mesh; finer versions read as bug screen.
2026-05-09 12:14:10 -07:00
Kelsi
b311916c6c feat(editor): add --gen-mesh-training-dummy sparring prop
66th procedural mesh primitive. Combat training dummy from
axis-aligned boxes:

  • vertical post from ground to baseH (the stand)
  • cubic torso block stacked on top of the post
  • horizontal cross-bar arms at upper-third torso height
    spanning armSpan along the X axis
  • optional head cube above the torso (set headSize=0
    for a headless training-block style)

Pairs with --gen-mesh-anvil / --gen-mesh-workbench /
--gen-mesh-fence for sparring grounds, militia drill
squares, training yards, weapon-master compounds. Useful
for any "things-to-hit" set dressing where animated NPCs
would target a static prop.

Watertight under weld (verified 72 manifold edges, 0
boundary, 0 non-manifold). Default 1.0 m post + 0.4 m
torso + 0.18 m head reads at adult-human height.
2026-05-09 12:09:36 -07:00
Kelsi
adb7e014ef feat(editor): add --gen-texture-snake-skin diamond-scale pattern
60th procedural texture: brick-offset grid of diamond-shaped
scales using L1 (taxicab) metric so |dx|/halfW + |dy|/halfH
< 1 inside each diamond. Even rows are aligned with the cell
grid; odd rows shift by halfW so adjacent scales touch
tangentially along their points — the classic snake/dragon
hide pattern.

A thin dark outline at d ∈ [outlineFrac, 1] gives definition;
outline color is automatically derived as scaleHex × 0.4
(2/5 brightness). Set outlineW=0 to skip the outline for a
smoother painted-scale look.

Distinct from --gen-texture-scales (overlapping circles for
fish/dragon scales) and --gen-texture-chainmail (rings for
metal mail). Useful for snake-cult robe trim, naga skin,
dragon-scale armor inserts, lizardman set dressing,
basilisk-themed dungeon decor.
2026-05-09 12:08:11 -07:00
Kelsi
4cb1c33335 feat(editor): add --gen-mesh-water-trough basin primitive
65th procedural mesh primitive. Open-top rectangular basin
built from 5 axis-aligned boxes (uses every shared helper
from cli_box_emitter):

  • bottom slab spanning full footprint at wallT thickness
  • +X / -X side walls spanning full length
  • +Z / -Z front/back walls spanning the inner length so
    they tuck inside the side walls without overlap

Inner cavity (length-2*wallT × height-wallT × width-2*wallT)
is the open water/feed volume. Useful for stables, farmsteads,
taverns, stockyards, alchemist mixing basins.

Default 1.4 × 0.5 × 0.5 m is a reasonable horse-trough size;
configurable for smaller hand-basins or larger livestock
troughs.
2026-05-09 12:02:35 -07:00
Kelsi
5b24b54d09 feat(editor): add --gen-texture-camo woodland-disruption pattern
59th procedural texture: 2-octave bilinear value noise
thresholded into hard bg/fg blobs. Sharp edges read as
real military camouflage rather than the smooth gradient
--gen-texture-noise-color produces.

Two octaves combined at 0.7/0.3 weights:
  • low frequency at cellSize lattice → large dominant blobs
  • high frequency at cellSize/4 lattice → finer mottling
    overlay so blob edges aren't perfectly smooth

Threshold parameter shifts the bg/fg balance — lower values
expose more accent color (good for leaf-pattern), higher
values keep the dominant color dominant (good for rock/sand).

Useful for guard cloaks, military uniforms, ghillie suits,
druid robes, hunter blinds, scout cloaks. First procedural
texture to use the new savePngOrError helper from
cli_png_emit.hpp.
2026-05-09 12:01:11 -07:00
Kelsi
c10b1b0fb1 feat(editor): add --gen-mesh-watchpost sentry tower primitive
64th procedural mesh primitive. A simple scout/sentry
watchpost from axis-aligned boxes:

  • tall central pole rising from ground to postH
  • square platform slab on top of the pole, wider than
    the pole so it overhangs as the lookout deck
  • 4 corner railing posts on the platform — set
    railingH=0 for a bare deck

Distinct from --gen-mesh-tower (round castle tower with
crenellated battlements). A watchpost is the rough scout/
forward-outpost variant — just wood and rope, no masonry.

Pairs naturally with --gen-mesh-tent / --gen-mesh-firepit
for camp + lookout scenes, and --gen-mesh-fence for
perimeter setups. Watertight under weld (verified
108 manifold edges, 0 boundary, 0 non-manifold).
2026-05-09 11:57:38 -07:00
Kelsi
d7941bd4ce feat(editor): add --gen-texture-pinstripe formal-fabric pattern
58th procedural texture: thin vertical lines at every
`stride` x position, with optional thicker "feature" line
every Nth stripe. The periodic doubled-thickness emphasis
is what distinguishes this from --gen-texture-stripes
(which renders wide alternating bands of each color).

Each stripe is centered within its column and has
configurable lineW; feature stripes are 2× the regular
width. Set featureEvery=0 to disable feature emphasis for
a uniform pinstripe pattern.

Useful for noble-house tabards, formal-attire fabric,
banker's counter cloth, sci-fi panel detailing, royal-
guard uniform trim, library / archive carpet runners.

Default 12-pixel stride, 1-pixel line, feature every 6th
stripe gives the classic suit-pinstripe look at 256x256.
2026-05-09 11:56:01 -07:00
Kelsi
a10efed8f5 feat(editor): add --gen-mesh-crate-stack scene primitive
63rd procedural mesh primitive. The first to explicitly
compose a *scene* of multiple objects rather than a single
structure: an N×M×K arrangement of cube crates with a small
gap between each so they read as discrete shipping boxes
rather than one merged solid.

Default 2×2×2 = 8 crates with 0.40 m sides on a 0.02 m gap
gives a tight pyramidal pile. Larger configurations (e.g.
4×3×2 = 24 crates) read as warehouse pallets.

Uses every shared helper added this batch — addFlatBox for
each crate, finalizeAsSingleBatch for the trailing batch,
stripExt for the .wom suffix, parseOptInt/Float for the
optional dimension args. Each crate emits the standard
24-vert / 12-tri box, so an N×M×K stack is a clean
N*M*K-multiple in vertices and triangles.

Useful for warehouses, cargo holds, dock loading bays,
market stalls, dwarven mining caches, pirate stash piles.
Watertight under weld — the gap keeps adjacent crates
from sharing corner positions.
2026-05-09 11:52:20 -07:00
Kelsi
68af5c10c9 feat(editor): add --gen-texture-carbon fiber-weave pattern
57th procedural texture: 2x2 cell pattern where alternating
cells hold horizontal vs vertical fiber segments. Each
segment gets a sin² brightness profile across its
perpendicular axis — 0 at the segment edge, peak at center —
giving the rounded highlight of a real woven fiber bundle.

Cell-pair parity (cx + cy) % 2 determines orientation, so
adjacent cells always alternate weave direction in both X
and Y. Reads as the unmistakable carbon-fiber checkerboard
even at small scales.

Useful for sci-fi armor, sleek tech panels, vehicle bodies,
ritual obsidian inlays, dwarven runeplate accents — any
"machined composite" surface where flat dark grey would
read as plain plastic.

Default 12-pixel cell at 256x256 reads cleanly with about
21 visible weave segments per side.
2026-05-09 11:49:20 -07:00
Kelsi
47641bf0b4 feat(editor): add --gen-mesh-workbench crafter table
62nd procedural mesh primitive. A blacksmith / crafter
workbench built from axis-aligned boxes (uses the new
cli_box_emitter helper plus the new cli_arg_parse helpers
for all 7 optional dimension args):

  • flat top slab spanning length × depth at topT thickness
  • 4 corner legs sized so their outer faces line up with
    the top edges (post-style, no overhang)
  • optional vise box at the +X end of the top — set
    viseSize=0 for a bare bench
  • optional raised tool tray along the +Z back edge —
    set trayH=0 to omit

Pairs naturally with --gen-mesh-anvil (existing) for
blacksmith forge scenes, and --gen-mesh-cauldron for
alchemist labs. Default 1.6×0.7×0.85 m bench reads at
realistic adult-human working height.

Watertight under weld (verified via --info-mesh-stats:
126 manifold edges, 0 boundary, 0 non-manifold).
2026-05-09 11:46:05 -07:00
Kelsi
7f7104623d feat(editor): add --gen-texture-woodgrain end-cut tree-rings
56th procedural texture: concentric annual growth rings
centered slightly off-image (at -W*0.2, H/2) so the texture
shows sweeping arcs across most of its area rather than the
bullseye --gen-texture-rings produces.

Per-ring jitter shifts the dark-band center within each
ring's annular cell, so adjacent rings don't read as a
perfect modulus pattern — mimics real annual-growth
variation. Brightness lerps from lightHex (early-wood)
to darkHex (late-wood / heartwood) with a smooth
triangular falloff at the dark-band peak.

First procedural texture to use the new cli_arg_parse
helpers for the optional spacing/seed/W/H args.

Useful for tabletops, log-end caps (chopped firewood
stumps), barrel lids, beam cross-sections, plank ends —
distinct from --gen-texture-wood which renders vertical
grain streaks for plank surfaces.
2026-05-09 11:44:33 -07:00
Kelsi
e23b3faa1c feat(editor): add --gen-mesh-bedroll camp sleeping prop
61st procedural mesh primitive. Builds a bedroll prop:

  • horizontal closed cylinder along the Z axis sitting at
    y = R so it rests on the ground (radius defaults to
    0.16 m, length 1.4 m — adult-human-shaped)
  • optional pillow box at the +Z end (squashed cube,
    pillowSize controls extent)
  • per-segment N-sided cylinder uses the new addVertex
    helper; pillow uses addFlatBox

Set pillowSize=0 for a bare rolled mat. Watertight under
weld (verified via --info-mesh-stats: 90 manifold edges,
0 boundary, 0 non-manifold).

Pairs naturally with --gen-mesh-tent / --gen-mesh-firepit /
--gen-mesh-canopy for outdoor camp scenes — completes the
tent-side camping kit.
2026-05-09 11:39:33 -07:00
Kelsi
65b3352b9f feat(editor): add --gen-texture-moss organic-mottling pattern
55th procedural texture: irregular spots scattered on a hash-
jittered grid. Each cell tests its 8 neighbors so spots near
cell boundaries don't get clipped at the cell wall.

Per-cell hashing controls:
  • presence — density 0-100 chance the cell hosts a spot
  • position — uniform jitter inside the cell
  • radius — 25-75 % of stride, so adjacent spots vary in size

Result reads as random patches of organic growth rather than
a visible lattice. Useful for forest floors, weathered stone
walls, dungeon flagstones, swamp ground, ruined-temple
overlay, fungal-cavern detail.

Default 16-stride / 70-density on a stone-grey base reads
cleanly at 256x256 with about half the surface mossed over.
2026-05-09 11:38:03 -07:00
Kelsi
db2db04ffe feat(editor): add --bake-zone-collision aggregator
Walks every .wom and .wob under <zoneDir>, optionally welds
each one independently (per-mesh / per-WOB-group), and
appends its triangles to a single WoweeCollision. Useful for
shipping a zone — one .woc artifact holds all object collision
so the server side has just one file to load.

Per-file weld preserves between-object boundaries: two
distinct WOMs sitting at the same world position keep
their topology separate even if their corner positions
happen to overlap.

Same flag surface as the single-file bakers: optional
[out.woc] (defaults to <zoneDir>/zone.woc), --weld <eps>,
--steep <deg> for the walkable/steep slope cutoff.

Smoke tested over /tmp/migtest: scanned 79 WOM + 1 WOB,
produced 9259-triangle WOC (1563 walkable, 1943 steep)
with correct world bounds.
2026-05-09 11:36:38 -07:00
Kelsi
836fab7f2d feat(editor): add --gen-mesh-chimney brick-stack primitive
60th procedural mesh primitive. Builds a chimney as two
axis-aligned boxes (uses the shared addFlatBox helper):

  • main shaft: rectangular brick stack of width × depth ×
    (height - capH)
  • protective cap: a slightly wider box on top (capExtra
    wider than shaft on every side) — the rain-throw crown
    that sits on real masonry chimneys

Set capH=0 for a bare unfinished stack. Default 0.45×0.45×
1.8 m shaft with a 0.10-tall cap reads at human scale for
rooftop placement.

Useful for cottage rooflines, blacksmith forges, alchemist
labs, dwarven longhouses — any structure with a fireplace
that needs visible vent. Watertight under weld (verified
via --info-mesh-stats: 36 manifold edges, 0 boundary, 0
non-manifold).
2026-05-09 11:34:24 -07:00
Kelsi
26f1947c84 feat(editor): add --audit-watertight-wob building QA tool
Sibling of --audit-watertight that walks every .wob under
<root> and runs the welded watertight check on every group.
A WOB passes only if every group is closed — interior rooms
in a real building should each be a closed solid even
though the building as a whole has intentional portal
openings between them.

Per-failure detail lists which groups failed and why
(boundary edge count + non-manifold edge count). Exit code
is the number of failed buildings (capped at 255) — same
CI-friendly contract as the WOM audit.

Smoke tested against /tmp/migtest cube.wob: PASS, 12 tris,
exit code 0.
2026-05-09 11:33:10 -07:00
Kelsi
f1528f2dd7 feat(editor): add --gen-texture-studs riveted-armor pattern
54th procedural texture: grid of round rivet caps with an
inner highlight. Each stud has:

  • outer ring (40%-100% of studR) at the studHex base color
  • inner core (0-40% of studR) at studHex × 1.4 brightness
  • bg color outside studR

The 40% bright core sells the 3D rivet appearance — a flat
solid circle (which --gen-texture-dots already produces)
reads as a polka dot, while the bright/dim concentric pair
reads as a metal stud catching light.

Useful for studded leather armor, riveted plate, banded
mail trim, dwarven hauberks, prison-cell door reinforcement,
ship hull plating. Default 24-stride grid with R=7 reads
cleanly at typical body-armor scale.
2026-05-09 11:31:27 -07:00
Kelsi
6ff5df41eb feat(editor): add --gen-mesh-pergola garden-arbor primitive
59th procedural mesh primitive. Builds an open-top pergola
from axis-aligned boxes (uses the new addFlatBox helper):

  • 4 corner posts sized so their outer faces line up with
    the footprint perimeter
  • 2 long perimeter beams resting on top of the posts
    along the long edges
  • N cross beams running between the perimeter beams
    (slightly thinner so the lattice has visible crossings)

Distinct from --gen-mesh-canopy because there's no closed
overhead panel — the open lattice top reads as a sun-trellis
or vine-arbor instead of a market-stall awning. Useful for
palace courtyards, druid groves, garden mazes, viewing
arbors, harvest-festival entrance pieces.

Set crossbeams=0 for a bare 4-post + 2-beam frame; default
5 crossbeams gives a pleasing alternating pattern.
2026-05-09 11:26:15 -07:00
Kelsi
63048c1356 feat(editor): add --gen-texture-starburst radial-rays pattern
53rd procedural texture: N rays radiating from the texture
center. Each pixel computes its angle via atan2 and finds
the angular distance to the nearest ray axis (handling the
±π wrap so rays around the seam are continuous). Pixels
inside any ray's angular band get the ray color.

Brightness tapers linearly with distance from center: 1.0
at the hub, 0.4 at the texture diagonal — gives sun-rays
that fade as they extend outward instead of reading as
infinite lines.

Useful for sun motifs, holy/divine symbols, paladin
insignias, mage-robe trim, mosaic medallion centers,
shrine floor inlays, and any "radiant glory" surface.
2026-05-09 11:20:31 -07:00
Kelsi
173ad7796e feat(editor): add --bake-wob-collision multi-group WOB→WOC
Sibling of --bake-wom-collision for buildings. Walks every
group in a WOB, optionally welds vertices PER GROUP (groups
are intentionally separate — rooms with portals between them,
so welding across groups would fuse walls that should remain
distinct collision surfaces), and appends each to a single
WoweeCollision via WoweeCollisionBuilder::addMesh.

Same flag surface as the WOM variant: optional [out.woc]
output path, --weld <eps> for per-group vertex merge,
--steep <deg> for the walkable/steep slope cutoff.

Smoke tested on a 1-group cube WOB: 8 verts → 12-triangle
WOC with proper bounds (-1,-1,-1)..(1,1,1) and walkable/
steep classification matching the cube face orientations.
2026-05-09 11:19:09 -07:00
Kelsi
dadb08baee feat(editor): add --gen-mesh-dock pier-on-stilts primitive
58th procedural mesh primitive. Builds a wooden waterside
dock from axis-aligned boxes:

  • flat plank deck slab spanning length × width at deckT
    thickness, sitting at deckHeight off the ground
  • N pairs of square pilings under the long edges, evenly
    spaced from end to end
  • pilings inset by pilingW so the deck overhangs slightly
    (the standard "boards rest ON TOP of the posts" look)

Distinct from --gen-mesh-bridge which arches OVER an
obstacle — a dock walks straight out from a shoreline on
stilts to the water. Useful for fishing villages, port
warehouses, lake settlements, ferry stations, smuggler
hideouts.

Watertight under weld (--audit-watertight passes): pilings
sit below the deck overhang and don't share corners with it.
2026-05-09 11:17:28 -07:00
Kelsi
0137ca8707 feat(editor): add --gen-texture-caustics water-shimmer pattern
52nd procedural texture: water-surface caustics via four
superimposed sine waves running along x, y, x+y, and x-y.
Each wave is taken in absolute value before multiplication
so peaks shine on either side of the wave centerline,
giving the bright-line interference network you see on a
pool floor or sunlit shallow streambed.

Two-color lerp from bgHex (depth) to hiHex (highlight).
Default 24-pixel period reads at the right scale for water-
plane underlay; pass a smaller period for tighter ripple.

Useful as the floor texture under transparent water
volumes, magic-fountain pools, fish-tank ground plates,
ritual scrying basins, and any "submerged surface seen
through clear water" effect.
2026-05-09 11:12:28 -07:00
Kelsi
89b7e2f505 feat(editor): add --audit-watertight project-level QA tool
Walk every .wom under <zoneDir|projectDir>, run the welded
watertight check from cli_weld + the same edge-analysis as
--info-mesh-stats, and report PASS/FAIL with the per-mesh
failure detail (boundary / non-manifold edge counts).

Exit code is the number of failures (capped at 255), so
CI pipelines can gate on `--audit-watertight $project` and
fail the build if any mesh isn't a closed solid.

Smoke-tested over 61 procedurally-generated WOMs:
  • 49 PASS — most stand-alone primitives are watertight
  • tent_fixed FAIL with 5 boundary edges = the intentional
    door cutout (correct surface count)
  • woodpile / bed / well variants FAIL with non-manifold
    edges = adjacent stacked cylinders/legs sharing corners
    (correct geometry callout)

Defaults to weld eps 1e-4 — a good balance for procedural
output where positions are exact rationals at typical scales.
2026-05-09 11:11:09 -07:00
Kelsi
e732894b4c feat(editor): add --gen-mesh-haystack terraced farm haystack
57th procedural mesh primitive. Builds a layered haystack:
N stacked frustums, each smaller than the one below, with
the topmost layer tapering to an apex point. The visible
shelves where each layer overhangs the smaller one above
read as bound straw shocks rather than the smooth
silhouette --gen-mesh-pyramid produces.

Per layer: vertical side wall ring (no taper within a
single layer) plus a top "shelf" annulus where it meets
the next layer up. Final layer is a cone fan to a single
apex vertex. Closed bottom disc keeps the model a solid
for collision baking — verified watertight under weld.

Useful for farms, granaries, stables, harvest-festival
clearings, druid groves with bound bundles. Default 3
layers at 12 sides reads cleanly at typical NPC scale.
2026-05-09 11:08:39 -07:00
Kelsi
9031bdb620 feat(editor): add --gen-texture-rope twisted-cordage pattern
51st procedural texture: two interleaved sinusoidal strands
running along the Y axis. Each strand's X position oscillates
as W/4·sin(2π·y/period); the second strand is phase-shifted
by π so the two snake around each other forming the classic
helical twist of a tightened rope.

Within each strand, brightness rises from 0.55 at the edge
to 1.0 at the centerline (cos² falloff) — gives the rounded
3D appearance of cylindrical fibers without a separate
shadow pass.

Useful for hanging ropes, ship rigging, tied-bundle textures,
suspension bridges, market-stall awning ties, and any
"twisted cord" surface where a flat color would read as
ribbon rather than rope.

Default 24-pixel period with 8-pixel strands renders cleanly
at 256x256 with about 10 visible twists.
2026-05-09 11:03:33 -07:00
Kelsi
069e76057e feat(editor): add --bake-wom-collision WOM→WOC pipeline
Convert any WOM mesh into a WOC collision file via
WoweeCollisionBuilder::addMesh, with optional --weld <eps>
that merges shared positions into a single canonical index
before baking. The weld pass is what makes per-face-shaded
procedural primitives produce a properly indexed collision
mesh — adjacent faces that previously authored 4 unique
verts per face now share 1 corner across all incident
faces, so raycasts can traverse edges naturally.

Also accepts --steep <deg> to control the walkable/steep
classification threshold (default 50° from horizontal,
matching the terrain pipeline).

Smoke-tested end-to-end:
  • firepit: 240 verts → WOC with 120 tris (20 walkable
    floor, 20 steep stone walls, rest neutral)
  • tent_solid: 18 verts welds to 6, produces 8-tri WOC
  • canopy: 216 → 56 weld, 108 tris, 30° steep cut

Pairs naturally with --info-mesh-stats --weld for
collision-quality QA before baking.
2026-05-09 11:01:45 -07:00
Kelsi
51d884c248 feat(editor): add --gen-mesh-canopy market-stall awning
56th procedural mesh primitive. Builds a rectangular awning
on 4 corner posts with a flat overhead panel and optional
drape lips hanging down from each edge:

  • 4 corner posts inset by postR so their outer faces line
    up flush with the panel edges above
  • flat panel slab spanning the full footprint, sitting on
    top of the posts
  • optional drape lips on all four panel edges (set drape=0
    for a clean flat-top canopy with no hanging fabric)

All axis-aligned boxes; the no-drape variant is fully
watertight (verified via --info-mesh-stats --weld). Useful
for market-square stalls, vendor stations, alchemist booths,
caravan rest stops, and tournament viewing platforms.
2026-05-09 10:59:05 -07:00
Kelsi
4112b6d257 feat(editor): --info-wob-stats + fix weld hash collision bug
Add --info-wob-stats reporting per-group + aggregate
triangle counts, surface area, edge analysis, and watertight
check for WOB buildings. Same flag surface as --info-mesh-stats
including --weld <eps> for true topological closure check
on per-face-vertex meshes.

Also fixes a correctness bug in the weld implementation
of --info-mesh-stats: the previous code used a 64-bit hash
of the quantized position as the equality key, which gave
false-positive collisions that incorrectly merged distinct
vertices. A unit cube's 8 corners collapsed to 2 positions
under the buggy hash. Replace with std::map keyed on the
actual quantized (qx, qy, qz) tuple so equality is exact.

Re-verified: cube 8→8 watertight YES; firepit 240→80
watertight YES (was wrongly reporting 56 unique with 48
non-manifold edges); tent_solid 18→6 watertight YES;
tent_fixed 21→9 with 5 boundary edges at the door perimeter
(correct — door is intentionally open).
2026-05-09 10:57:22 -07:00
Kelsi
a7989cc7ab feat(editor): add --gen-texture-corrugated metal-sheet ridges
50th procedural texture: smooth cosine ridges that lerp
between bgHex (trough) and hiHex (crest) over a configurable
period. Direction defaults to vertical ridges (wave varies
along X) — the standard corrugated-sheet-metal-roof look —
with optional horizontal mode for siding panels and pipe
texturing.

Useful for sheet-metal roofing, corrugated-iron walls,
sci-fi paneling, and any "ridged plate" surface where the
existing flat --gen-texture-metal would read as too uniform.

Default 16px period at 256x256 reads cleanly with about 16
ridges across the tile.
2026-05-09 10:50:46 -07:00
Kelsi
c206216676 feat(editor): add --gen-mesh-woodpile firewood-stack primitive
55th procedural mesh primitive. Builds the classic 3-2-1
firewood pyramid:

  • 3 cylindrical logs along the bottom row, sitting on
    the ground at radii apart
  • 2 logs nestled in the gaps of the bottom row
  • 1 log crowning the pile

Vertical step uses cos(30°) = sqrt(3)/2 so adjacent logs
touch tangentially, giving the close-packed look of a real
chopped-wood stack. Logs lie horizontally along the Z axis
with closed end caps; sides parameter controls cross-
section smoothness (default 12, range 6..64).

Pairs naturally with --gen-mesh-firepit and --gen-mesh-tent
for outdoor camp / homestead / lumberyard set dressing.
2026-05-09 10:47:21 -07:00
Kelsi
f8bd4c70c8 feat(editor): add --gen-texture-planks floor-board pattern
49th procedural texture: horizontal plank-floor pattern.
Each plank gets:

  • a hash-derived per-plank brightness offset (-24..+24)
    so adjacent boards read as separate pieces of wood
    rather than one long stripe
  • a 1px horizontal seam at its bottom edge
  • a 1px vertical end-seam at a hash-jittered x position,
    staggering plank ends across rows
  • optional darker grain streaks at evenly-spaced columns
    (jittered per plank so the pattern doesn't grid-align)

Useful for inn/tavern floors, ship deck planking, bridge
surfaces, market-stall counters, and any wood-floor surface
where the existing single-grain --gen-texture-wood would
read as one giant board.

Default 16px plank height with 5 grain streaks gives a
recognizable floor at 256x256 without aliasing.
2026-05-09 10:44:13 -07:00
Kelsi
5e404a9fe6 feat(editor): add --info-mesh-stats geometric audit
Reports total surface area, per-triangle area histogram
(min/max/mean/median), edge analysis (boundary / manifold /
non-manifold counts), watertight check, and degenerate
triangle count for a single WOM.

Watertightness here is the topological notion: every edge
must be shared by exactly 2 triangles via shared vertex
indices. This is what collision bakes and physics queries
actually need — visually-closed primitives whose adjacent
faces don't weld vertices will (correctly) report as
non-watertight.

Already caught a real defect in handleTent's door-fan
triangulation: the fan covers the door cutout area with
a stray triangle and leaves a vertex unreferenced.
Edge analysis is gated by triCount <= 2M to keep the
unordered_map bounded for huge baked terrain meshes.
2026-05-09 10:41:58 -07:00
Kelsi
17a53f192f feat(editor): add --gen-mesh-firepit camp firepit primitive
54th procedural mesh primitive. Builds a recognizable
campfire setup from axis-aligned boxes only:

  • ring of N stone cubes evenly placed at radius ringR
    around the firepit center, sitting on the ground
  • two crossed log boxes at the center (one along X,
    one along Z, slightly raised) — the unmistakable
    visual cue separating a firepit from a generic
    decorative stone ring

Pairs naturally with --gen-mesh-tent for outdoor camp
set dressing (Horde encampments, Defias hideouts, scout
overlooks). Default 0.5-radius ring with 8 stones reads
cleanly at 1:1 player scale.
2026-05-09 10:37:37 -07:00
Kelsi
033c929576 feat(editor): add --gen-texture-chainmail interlinked rings
48th procedural texture: brick-offset ring outlines. Even
and odd rows are shifted by half a cell width so each ring
interlocks visually with its neighbors above and below —
the classic chainmail-armor pattern. Each pixel is tested
against the nearest ring center; if its distance lies
inside [ringR - strokeW/2, ringR + strokeW/2] it's
painted as the ring color, otherwise background.

Useful for armor textures (mail tunics, helms, gauntlets),
metallic fabric set dressing on guard NPCs, and dungeon
gate/grate textures. Default ring radius 5 on a 14x10
brick spacing reads cleanly at 256x256 without aliasing.
2026-05-09 10:34:02 -07:00
Kelsi
e746e400dd feat(editor): add --gen-mesh-tent A-frame canvas tent
53rd procedural mesh primitive. Builds a watertight A-frame
tent:
  • two sloped roof panels meeting at a ridge that runs along
    the X axis
  • two triangular gables sealing the ends
  • optional inverted-V door notch carved out of the +X gable
    (parameterized by doorH and doorW; either set to 0 disables
    the cutout for a solid gable)
  • bottom face for collision-bake watertightness

Useful set dressing for Horde encampments, troll camps,
Defias bandit hideouts, scout/quartermaster overlooks, and
generic outdoor quest hubs.

Default footprint 1.6 x 1.0 with 0.9 ridge height and a
0.5 x 0.4 door notch — all dimensions overridable on the CLI.
2026-05-09 10:25:38 -07:00
Kelsi
a9f4e322d5 feat(editor): add --gen-texture-knit V-stitch fabric pattern
47th procedural texture: knit fabric V-stitch — each stitch
occupies a cellW x cellH cell holding the V-shape made by
two diagonal strokes meeting at the apex (cellW/2, 0) and
dropping to the cell's bottom corners. Cells tile contiguously
in both axes giving the iconic chevron-zigzag appearance of
knitted fabric stitches.

Useful for sweater fabric, woolly NPC clothing, blanket
textures, mitten/scarf set dressing, dwarven knitwork.
Defaults to 16x12 cells with 2-px stroke width.
2026-05-09 10:18:22 -07:00
Kelsi
3db5d05519 feat(editor): add --gen-mesh-archway-double twin-passage primitive
58th procedural mesh: 5-box double archway — 3 vertical posts
(left / shared center / right) plus 2 horizontal lintels each
spanning one opening. Pairs with the existing single
--gen-mesh-archway for plaza approaches, double-door tomb
fronts, formal garden entrances, paired temple entries.

Defaults to 1.40m × 2 openings with 2.40m opening height
(~3.16m total width × 2.60m height including lintels).
2026-05-09 10:11:24 -07:00
Kelsi
0e8ef746af refactor(editor): extract kArgRequired + meta handlers into cli modules
Splits the 138-line static-local kArgRequired array (the list
of flags requiring positional args) into a new
cli_arg_required.{hpp,cpp} module with extern linkage. Then
moves the three meta handlers that depended on it out of
main.cpp into cli_introspect.cpp:
- --validate-cli-help (uses the array for self-check)
- --version / -v (3-line printf)
- --help / -h (1-line passthrough)

main.cpp shrinks by 191 lines (677 to 486). Both the early
missing-argument detector in main() and --validate-cli-help
in cli_introspect.cpp now share one source of truth for the
arg-required list.
2026-05-09 10:08:14 -07:00