Skip to content

Commit c7e6727

Browse files
TMHSDigitalclaude
andcommitted
feat(showcase): add terrain category; move terrain-scatter and sea-stack-arch into it
One category for maps and terrain: ground at map scale (heightfield landscapes, map and diorama tiles, islands, level blocks). Seeded with the two existing tile pieces; ROADMAP gains Terrain candidates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 5f398ec commit c7e6727

8 files changed

Lines changed: 18 additions & 12 deletions

File tree

‎ROADMAP.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ Not committed; open subjects only. Remove a subject when it ships (CLAUDE.md §
152152
- **Nature:** (all candidates shipped)
153153
- **Household:** laundry basket
154154
- **Vehicles:** sci-fi supply crate
155+
- **Terrain:** hex island map tile (heightfield island, river draining spring to delta, terraced fields, sea to the hex rim; tile edges on one canonical profile); river delta tile; canyon mesa tile; terraced paddy hillside; volcanic caldera island
155156
- `persistent` app-handler witness — handlers registered without `@bpy.app.handlers.persistent` are dropped by `wm.read_homefile`/file load while persistent ones survive; assert the registered-handler set before and after a reload (silent loss AI code hits)
156157
- Link vs append witness — `bpy.data.libraries.load(link=True)` yields a linked, non-editable datablock (`library` set, `is_editable` False) while append yields a local copy; write a temp .blend with `bpy.data.libraries.write`, then assert both paths
157158
- Orphan purge witness — `bpy.data.orphans_purge(do_recursive=...)` removes exactly the zero-user datablocks computed independently beforehand, and `bpy.data.batch_remove` removes a given set in one call (counts closed-form)

‎docs/gallery/index.html‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,12 @@ <h1>Examples and Showcase</h1>
117117
<span class="cats-label" id="catsLabel">Showcase category</span>
118118
<div class="density" role="group" aria-labelledby="catsLabel">
119119
<button class="cat-btn" data-cat-filter="" type="button" aria-pressed="true">All</button>
120-
<button class="cat-btn" data-cat-filter="village" type="button" aria-pressed="false">Village <span aria-hidden="true">41</span></button>
120+
<button class="cat-btn" data-cat-filter="village" type="button" aria-pressed="false">Village <span aria-hidden="true">40</span></button>
121121
<button class="cat-btn" data-cat-filter="sports" type="button" aria-pressed="false">Sports <span aria-hidden="true">7</span></button>
122-
<button class="cat-btn" data-cat-filter="nature" type="button" aria-pressed="false">Nature <span aria-hidden="true">11</span></button>
122+
<button class="cat-btn" data-cat-filter="nature" type="button" aria-pressed="false">Nature <span aria-hidden="true">10</span></button>
123123
<button class="cat-btn" data-cat-filter="household" type="button" aria-pressed="false">Household <span aria-hidden="true">7</span></button>
124124
<button class="cat-btn" data-cat-filter="vehicles" type="button" aria-pressed="false">Vehicles <span aria-hidden="true">10</span></button>
125+
<button class="cat-btn" data-cat-filter="terrain" type="button" aria-pressed="false">Terrain <span aria-hidden="true">2</span></button>
125126
</div>
126127
</div>
127128
<div class="chips" id="chips" role="toolbar" aria-label="Filter by topic (combine several)">
@@ -925,7 +926,7 @@ <h2><a class="stretch" href="treasure-chest/">Treasure Chest</a></h2>
925926
<span class="card-link" aria-hidden="true">View showcase piece &rarr;</span>
926927
</div>
927928
</article>
928-
<article class="card" data-tags="mesh export showcase" data-kind="showcase" data-category="village" data-name="terrain-scatter" data-search="terrain scatter terrain-scatter a geometry nodes hill tile with embedded, varied stone scatter through uvs, bake, lod, collider, and unity gltf, asserting recomputed budgets rather than an api contract. mesh export showcase village">
929+
<article class="card" data-tags="mesh export showcase" data-kind="showcase" data-category="terrain" data-name="terrain-scatter" data-search="terrain scatter terrain-scatter a geometry nodes hill tile with embedded, varied stone scatter through uvs, bake, lod, collider, and unity gltf, asserting recomputed budgets rather than an api contract. mesh export showcase terrain">
929930
<div class="card-media">
930931
<img src="assets/terrain-scatter-hero-640.webp" srcset="assets/terrain-scatter-hero-640.webp 640w, assets/terrain-scatter-hero.webp 1280w" sizes="(min-width: 900px) 340px, (min-width: 560px) 50vw, 100vw" alt="A square hill tile of patchy grass over dark earth with a rounded soil edge, nine faceted grey stones sunk across it among grass tufts and pebbles." width="1280" height="720" loading="lazy" decoding="async" />
931932
</div>
@@ -1633,7 +1634,7 @@ <h2><a class="stretch" href="fern-mossy-rock/">Fern Mossy Rock</a></h2>
16331634
<span class="card-link" aria-hidden="true">View showcase piece &rarr;</span>
16341635
</div>
16351636
</article>
1636-
<article class="card" data-tags="mesh export showcase" data-kind="showcase" data-category="nature" data-name="sea-stack-arch" data-search="sea stack arch sea-stack-arch a procedural coastal diorama tile — a fragment of a bedded sandstone headland at the sea&#x27;s edge as one eroded mass: eighteen level hard and soft beds running on from the legs into the roof and the stack, jointed faces leaning back and battered and flared at the foot, one weathering field read on the face through every bed, fallen-out blocks and open joints, soft beds undercut to a wave-cut notch; two legs curving in on an ellipse to meet at the crown under a roof that steps down seaward; a tapering stack standing in the sea; the sea filling the tile to its rim with foam at the shore and round the feet, a wave-cut platform, tide pools and a shingle cove, fallen blocks, boulders and pebbles, and a draped turf mat with sea grass and thrift cushions — through uvs, bake, lod, collider, and unity gltf, asserting recomputed budgets rather than an api contract. mesh export showcase nature">
1637+
<article class="card" data-tags="mesh export showcase" data-kind="showcase" data-category="terrain" data-name="sea-stack-arch" data-search="sea stack arch sea-stack-arch a procedural coastal diorama tile — a fragment of a bedded sandstone headland at the sea&#x27;s edge as one eroded mass: eighteen level hard and soft beds running on from the legs into the roof and the stack, jointed faces leaning back and battered and flared at the foot, one weathering field read on the face through every bed, fallen-out blocks and open joints, soft beds undercut to a wave-cut notch; two legs curving in on an ellipse to meet at the crown under a roof that steps down seaward; a tapering stack standing in the sea; the sea filling the tile to its rim with foam at the shore and round the feet, a wave-cut platform, tide pools and a shingle cove, fallen blocks, boulders and pebbles, and a draped turf mat with sea grass and thrift cushions — through uvs, bake, lod, collider, and unity gltf, asserting recomputed budgets rather than an api contract. mesh export showcase terrain">
16371638
<div class="card-media">
16381639
<img src="assets/sea-stack-arch-hero-640.webp" srcset="assets/sea-stack-arch-hero-640.webp 640w, assets/sea-stack-arch-hero.webp 1280w" sizes="(min-width: 900px) 340px, (min-width: 560px) 50vw, 100vw" alt="A ragged bedded sandstone sea arch and a tapering sea stack standing in a sea that fills the tile to its rim, beside a wave-cut platform and a shingle cove, with thrift on the turfed tops." width="1280" height="720" loading="lazy" decoding="async" />
16391640
</div>

‎docs/gallery/sea-stack-arch/index.html‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ <h1>Sea Stack Arch</h1>
5454
</button>
5555
<p class="zoom-hint">Rendered headless by the showcase piece itself. Select it to enlarge.</p>
5656
<div class="callout"><span class="tag">witnesses</span> Recomputed: 90422 tris, eight materials with 46448 sandstone, 13438 shelf, 5546 water, 1966 foam, 2856 cobble, 5540 turf, 5331 grass and 3552 thrift faces, UVs in 0..1 with zero AABB overlap, outer AABB 2.840×1.960×1.465 m, zmin 0, hygiene 0 including zero coplanar cross-shell pairs across 43 bed shells, every soft bed&#x27;s end rings inside the hard beds either side (41 joints, 0.0019–0.0163 m) with the roof&#x27;s lowest bed biting both legs 0.015 m, the stack&#x27;s mass centre 0.128 m inside its foot notch&#x27;s footprint (min 0.100), both legs and the stack sealed in the ground in 8 of 8 sectors (worst 0.031 m, min 0.020), a clear aperture 0.264 m wide and 0.757 m high (min 0.22 × 0.68), all 21 hard bed tops level (0.00°) and continuous across the columns, the 22 soft beds undercut 0.013–0.079 m (band 0.008–0.085), the sea at 0.1050 m with a 0.0024 m ripple and both pools flat, every water rim 0.010 m under the shore or the tile&#x27;s rim (min 0.008), the foam within 0.0043 m of the waterline with its land edge 0.005 m under the ground or in the rock, all 57 blocks, boulders and pebbles sealed in every sector and none overlapping, all 324 roots of grass and thrift 0.008–0.040 m in the turf or stone and none loose, 0.176 of the rock&#x27;s walls squared to their column&#x27;s axes (max 0.25), LOD ratios in band, five-hull collider 244 tris, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z 16; --gap-lintel 17; --lean-stack 19; --cut-pillar 20; --close-arch 21; --tilt-beds 22; --flush-beds 23; --flat-sea 24; --short-sea 25; --lift-foam 26; --perch-talus 27; --pile-talus 28; --float-cover 29; --tidy-rock 31.</div>
57-
<p class="taglist"><span class="tag">category</span> <a href="../#k=showcase&amp;c=nature">Nature</a></p>
57+
<p class="taglist"><span class="tag">category</span> <a href="../#k=showcase&amp;c=terrain">Terrain</a></p>
5858
<p class="taglist"><span class="tag">tags</span> <a href="../#tag=mesh">mesh</a> <a href="../#tag=export">export</a> <a href="../#tag=showcase">showcase</a></p>
5959
<div class="runline">
6060
<pre id="runCmd" tabindex="0">blender --background --python showcase/sea-stack-arch/sea_stack_arch.py --</pre>
6161
<button class="copy-btn" id="copyRun" type="button">Copy</button>
6262
</div>
6363
<nav class="jumpnav" aria-label="On this page"><span class="tag">jump to</span> <a href="#run">Run</a> <a href="#exit-codes">Exit codes</a> <a href="#source">Source</a> <a href="#related">Related</a></nav>
6464
<section class="detail-section md">
65-
<p>A showcase piece, not an example, and the tenth in the <code>nature</code> category. It builds a procedural game-ready coastal diorama tile, 2.84 × 1.96 m across and 1.46 m high: a fragment of a bedded sandstone headland at the sea&#x27;s edge, with a natural arch through it and a sea stack standing in the water beside it.</p>
65+
<p>A showcase piece, not an example, in the <code>terrain</code> category. It builds a procedural game-ready coastal diorama tile, 2.84 × 1.96 m across and 1.46 m high: a fragment of a bedded sandstone headland at the sea&#x27;s edge, with a natural arch through it and a sea stack standing in the water beside it.</p>
6666
<ul><li><strong>The tile.</strong> A rounded square. The sea fills the right of it out to the edge, where the tile&#x27;s rim stands 16 mm over the water and holds it, and runs through the arch to the back edge. The left is a wave-cut rock platform, crossed by wandering joint cracks, with two tide pools, and a shingle cove in front: grey and buff pebbles in dark sand, wet at the water&#x27;s edge. The seabed falls away from the shore, so the water darkens with depth. The tile&#x27;s skirt drops straight to a flat base, the beds in section.</li><li><strong>One eroded mass.</strong> Eighteen level beds, hard sandstone beds of uneven thickness (65–132 mm) over thin soft ones (18–35 mm), at one set of heights in every column, so the strata run on from the legs into the roof and the stack. Every bed&#x27;s outline is the headland&#x27;s jointed faces (fourteen planes turning the corners round the fin), each leaning back with height, battered out below 0.64 m and flared at the foot, then set back by the bed&#x27;s own retreat. On that, one weathering field in space, read on the weathered face itself, so the swells and hollows of a face run on through the beds and from the legs into the roof whichever column a face belongs to. Each hard bed stands proud or sits back by its own amount, has blocks fallen out of it and, here and there, an open joint; its top arris is worn round and its foot chamfered. The soft beds are undercut behind the hard beds either side, deeply in places and all but flush in others, and deepest at the foot of each leg and the stack, the wave-cut notch.</li><li><strong>The arch.</strong> Two legs, the seaward one standing in the water, whose inner faces curve in on a flattened ellipse from 0.55 m apart at the springing and meet at the crown under the roof, their arrises cut back where the sea has rounded them. The roof&#x27;s lowest bed runs on from the legs&#x27; top bed face for face and bears on both; its upper beds step down toward the sea, so the skyline falls away seaward.</li><li><strong>The stack.</strong> A rugged, tapering pillar of the same beds (fourteen layers, 1.10 m) standing in the sea on a flared foot, its upper beds broken back on different sides so its top is ragged.</li><li><strong>The sea.</strong> A rippled sheet at a declared level of 0.105 m, its rim run under the shore and under the tile&#x27;s rim, calm at the shore, the rim and round the feet. A foam line lies at the waterline along the shore, rim to rim, and round each foot in the water, its land edge tucked under the shore or into the rock.</li><li><strong>Loose rock.</strong> Five fallen blocks (bed fragments cut by fracture planes), six rounded boulders and 46 pebbles on the shingle, sealed all round and held apart, and clear of the feet and the pools.</li><li><strong>The tops.</strong> A turf mat over the roof&#x27;s top bed and the stack&#x27;s, draped over the edge as an overhanging lip (stopping short where it has eroded back) and tucked into the stone, with tufts of sea grass and cushions of sea thrift (a mound of leaves, pink heads on short stalks).</li></ul>
6767
<p>The littoral bands are in the materials: dark wet stone and green-black weed at the waterline, a barnacle crust over it, a black lichen band above, then orange and grey lichen high up, bird lime splashed on the high ledges and streaked down the seaward faces; each bed its own cast, so the strata band across the rock; overhangs stay dark and damp.</p>
6868
<p>Every seeded draw comes from <code>random.Random(SEED)</code> in <code>plan_scene()</code>, before anything is built: each face&#x27;s drift and set-backs, the weathering fields, each bed&#x27;s relief, fallen-out blocks, joints and undercut, the loose rock and the cover. Per-point variety comes from closed-form functions of position. No flag draws from the stream, so a falsifier changes only what it names.</p>

‎docs/gallery/terrain-scatter/index.html‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ <h1>Terrain Scatter</h1>
5454
</button>
5555
<p class="zoom-hint">Rendered headless by the showcase piece itself. Select it to enlarge.</p>
5656
<div class="callout"><span class="tag">witnesses</span> Recomputed: 2398 tris, two materials with 720 stone faces, UVs in 0..1 with zero AABB overlap, outer AABB 1.800x1.800x0.570 m, grounded zmin, 9 stones of &gt;=80 faces each sealed into the ground in 8/8 sectors, footprint ratio 9.8, rim tilt step 33.5 deg, no stone pairs overlapping, LOD ratios in band, convex collider 36 tris, hygiene zero, non-empty glTF. --skip-decimate exits 9; --stray-vert 15; --lift-z 16; --poke-rock 17; --float-rocks 18; --box-rocks 19; --pile-rocks 20; --perch-rocks 21; --uniform-rocks 22; --sharp-rim 23.</div>
57-
<p class="taglist"><span class="tag">category</span> <a href="../#k=showcase&amp;c=village">Village</a></p>
57+
<p class="taglist"><span class="tag">category</span> <a href="../#k=showcase&amp;c=terrain">Terrain</a></p>
5858
<p class="taglist"><span class="tag">tags</span> <a href="../#tag=mesh">mesh</a> <a href="../#tag=export">export</a> <a href="../#tag=showcase">showcase</a></p>
5959
<div class="runline">
6060
<pre id="runCmd" tabindex="0">blender --background --python showcase/terrain-scatter/terrain_scatter.py --</pre>

‎scripts/build_gallery.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def thumb_path(hero: str) -> str:
9494
"nature": "Nature",
9595
"household": "Household",
9696
"vehicles": "Vehicles",
97+
"terrain": "Terrain",
9798
}
9899

99100

‎showcase/README.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -792,16 +792,19 @@ The keys live in `CATEGORIES` in `scripts/build_gallery.py`, which the
792792
| --- | --- |
793793
| `village` | Pre-industrial settlement props: timber, stone, forged iron, rope, cloth. |
794794
| `sports` | Equipment and field furniture for a game or training: goals, hoops, nets, racks. |
795-
| `nature` | Organic forms with no maker: trees, rocks, logs, fungi, plants. |
795+
| `nature` | Single organic subjects with no maker: trees, rocks, logs, fungi, plants. |
796796
| `household` | Modern domestic and office objects: furniture, lamps, appliances, kitchenware. |
797797
| `vehicles` | Things that move or direct movement, present-day or sci-fi: drones, bikes, cones, loaders. |
798+
| `terrain` | Ground at map scale: heightfield landscapes, map and diorama tiles, islands, level blocks. |
798799

799800
A category changes the subject, not the bar. Every piece still asserts
800801
recomputed budgets, proves each falsifier fails once, clears the framing
801802
helper and the asset-sheet gate. Nature pieces have no joinery to test, so
802803
their piece-specific falsifier targets a measured organic invariant instead
803804
(branch tiers seated on the trunk, rocks resting on each other, a log's
804-
contact patch on the ground).
805+
contact patch on the ground). Terrain pieces test measured ground
806+
invariants the same way: water draining downhill, tile edges matching a
807+
canonical profile, a sea level held to the rim.
805808

806809
## Smoke
807810

0 commit comments

Comments
 (0)