The cage is authored and committed, not derived from a field; the cage primitive's distance serves measurement only (no cheap bound); detail is cut and split booleans on the evaluated mesh with the operator's weld rule; panel lines are splits; SDF composition and cage generators are research scored against the hand cage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
16 KiB
Brush tree: target (r3)
Campaign brush-tree, owned by the Aetheria/Ghostlight Self. Drafted by Imagination
(imagination-brush-tree-target-r3, session self-2026-10-11-ag2) on 2026-10-12.
It supersedes r2 (a7879dad). This page holds the ends, not the means: no cut plan. The typed
brush-tree:target:r3 holds the invariants, the not-in-scope list and the canonical implementations;
this page holds why, the authority map, and what is still unknown.
- Repos:
GameCult/GameCult.Geometry.Csg(the tree, the cage evaluator, the kernel, booleans and the weld, the scorer),GameCult/Brokkr(the agent's hands in Blender),GameCult/Aetheria(the first consumer). - Working branch:
eureka/brush-tree.
The rulings this target rests on
Read them in the mind by id; their operator quotes are the authority, not this page.
brush-tree:ruling:hand-cages-enter-the-tree(Operator, 2026-10-12): a continuous hull's primary form is an artist's cage, entered as a tree primitive with its distance defined once in Geometry.Csg; detail is cut into its evaluated surface. Automatic cage generation is research and gates nothing.brush-tree:ruling:boolean-cleanup-tighter-curve-wins(Operator): detail is boolean cuts into the evaluated hull, and the weld cleanup is automated by her rule. Her words: "the surface with the tighter curve defines the silhouette of the cut, and the spare vertices that come from the flatter surface all get merged away."brush-tree:ruling:panel-lines-by-split-boolean-r2(Operator): a panel line is a through-cut that keeps both sides; the stack's one-segment Bevel and Weighted Normal turn the split into a seam. The weld rule applies to its seams too. It is the only panel-line method: the operator chose geometry over parallax decals (aetheria-release:ruling:panel-lines-are-geometry), so hull panel lines are in this campaign's scope.brush-tree:ruling:primary-form-is-the-hand-cage(Defaulted): research generators are scored against the hand cage's limit surface, not against a masked or smoothed scan.brush-tree:ruling:representation-per-hull: cages for continuous bodies like Dexter Quiet, primitives for mechanical hulls like the squatter mech ship.brush-tree:ruling:shippable-part-bar,:no-unownable-tools-in-loop,:openscad-target,:brokkr-beats-blender-mcp,:cli-not-mcp, and the defaulted rulings on the Blender sink,run, docs lookup, look files, the per-ship tree.cc, persistence through cultcache-rs, the Package path, Studio and impostors: unchanged from r2.brush-tree:ruling:pursue-sdf-composition-remeshingand:spike-sdf-smin-to-cage: still in force, but narrowed byhand-cages-enter-the-tree. SDF composition with automated remeshing is one research generator among the cage-connectivity candidates, not the production path.
What changed from r2, in one paragraph
r2 made the SDF composition the authority for a continuous hull's shape and derived a fitted cage from
it, with the operator's hand cage as the measuring stick. Two findings ended that. The
cage-connectivity pass (cage-connectivity-prior-art.md @ 492f83a) found no open method that reaches
a coarse quad cage at the hand cage's quality. Every method starts from a dense mesh, and only
Lavoue 2009 reports output at about 200 faces, with n-gons and high valence accepted. The operator then
ruled her own cages into the tree, and named her detail practice: boolean cuts into the subdivided form,
then a weld she does by a rule simple enough to automate. So in r3 the cage is authored, not derived.
The field leaves the production path for continuous hulls. The open engineering problem moves from
generating connectivity to cleaning booleans on a curved evaluated surface.
What the pipeline turns a brush tree into
The tree is one typed document per ship (tree-store-per-ship-cc). Every part, meaning a top-level
branch, declares its representation, cage or kernel. The declaration is authored, never inferred.
Each part carries a detail list of cutters, each tagged cut (remove) or split (keep both sides).
A cage part (continuous body, Dexter Quiet):
- Primary form: the cage primitive. The tree holds control points, faces (quads and triangles),
edge crease weights and the mirror plane. She authors it in Blender. A
brokkr-ctlcommit reads the cage object and commits it as a new revision of the part against its base revision. After that the Blender cage object is a projection, and an edit to it is a proposed commit, as for any brush proxy. A commit is refused when a crease chain is open and does not end on the mirror plane (her finding: open crease paths give "horrible geometry" in Blender's Catmull-Clark). - Evaluated mesh, derived. Mirror, then Catmull-Clark to the limit surface at a declared level,
with Blender's crease rules (
one-subdivision-rule). Who runs this evaluation is questioncage-evaluator. - Detail, derived from cutters. Each cutter is a kernel brush, lowered alone to a closed mesh.
cut: the evaluated mesh minus the cutter (gun ports, vents, intakes).split: the evaluated mesh minus the cutter, plus the evaluated mesh intersected with the cutter, kept as two pieces that share one seam loop. This is how every panel line is made; there is no decal path. Every intersection loop is then welded by the rule below, and its edges get the bevel weight. Detail never moves the cage. Outside a band around each loop, the output's vertices are the evaluated mesh's vertices, unchanged.
- Shipped stack on the output object: Bevel (one segment, limited by weight: the crease loops plus every cut and split loop), then Weighted Normal. Seams for UVs lie on closed crease loops, part boundaries and split loops, so every panel is its own island.
The weld rule, as specified for the spike (boolean-cleanup-prior-art.md @ 34cccf3 found it
nowhere under any name):
- Along each intersection loop, compare the two surfaces' normal curvature across the loop. The across direction is the surface tangent perpendicular to the loop tangent.
- The surface with the larger magnitude owns the loop. The loop's vertices are sampled at the owner's resolution and lie on the owner's surface.
- The yielding surface's vertices within one ring of the loop, plus any of its loop vertices that are not owner vertices, collapse onto the nearest owner loop vertex.
- A collapse is refused if it flips a triangle or drops the worst angle below a floor. This is the
Manifold
CollapseEdgeguard (same file, s.1). - In a
split, the two pieces weld their shared loop identically, so the seam stays closed vertex for vertex.
Undefined so far, and named as the spike's failure cases: equal curvature, saddles where the across direction changes sign, a loop crossing a crease, and an ownership switch partway along one loop.
A kernel part (mechanical, the squatter mech ship): unchanged from r2. The polygon kernel builds
exact planar faces with scoped booleans, a one-segment bevel on hard edges, face-weighted normals and
UVs from each brush's declared charts. Its cutters use the same boolean and weld as a cage part's
detail.
Both reach Aetheria the same way (lowered-hull-through-package): an object in the ship file,
exported by the existing Package. Nothing reads an evaluated mesh, cut mesh or render back as truth.
Distance for a cage primitive, stated honestly
one-distance-per-primitive holds for the cage. Its distance is defined once in Geometry.Csg as the
unsigned distance to the limit surface, signed by winding number. The cost is the honest part.
- The limit surface has exact evaluation: Stam 1998, OpenSubdiv
LimitStencilTable, and run 3'sX = S c, linear in the cage. A closest point on it comes from a Newton search (Marinov and Kobbelt 2005). So the distance is computable (subd-cages-mixed-hulls-and-open-kernels.md@390db63, s.1). - No source gives a cheap distance bound away from the surface, that is, a Lipschitz-safe lower bound usable for sphere tracing, Newton projection from afar, or smooth-min composition with other primitives. The r1 field assumed one for every primitive.
- So the cage primitive is refused inside any field composition (smooth union, hard
maxcrease) and in sphere tracing (no-silent-skips). Its distance serves measurement only: heatmaps, scores and fit residuals, evaluated near the surface from a dense limit sample. Nothing in the production path needs more. A bound, if one is ever needed, is research.
Where SDF composition still has a role
- As a research generator. An SDF program with smooth-min, remeshed and refit to a cage (runs 4-7), is one candidate source of cage connectivity. It is scored like any other candidate.
- As the kernel brushes' distance.
field.rsstays the one distance for kernel primitives, for heatmaps and scores. - Not as a part representation. No production part is a
fieldpart, and smooth union leaves the production vocabulary. A generator's output, if it ever meets the bar, enters as a cage, and so does every continuous hull.
Authority map (r2 to r3)
- Owner of a continuous hull's primary form: the cage primitive in the tree. The field is no longer an owner. The cage is no longer derived from the field; it is authored and committed.
- Inputs: the operator's cage object in Blender (through the commit primitive only), the part's cutter brushes.
- Outputs: the lowered part object (evaluated, cut, split and welded mesh, with bevel weights), and scores.
- Derived state: the evaluated mesh, the cutter meshes, the cut mesh, UV islands, heatmaps, renders. These are cache only, regenerated per revision.
- Forbidden writers: the SDF program, the cage fitter and any remesher writing a production cage. They write research artifacts only, and a research cage enters only by a commit like any other. Also forbidden: Blender's Boolean modifier, or hand edits to the lowered object, deciding the shipped detail.
- Shared paths: the operator's cage edit, a model's script edit and a research generator's candidate all enter through the one commit primitive. Cut-in and split use one boolean and one weld. Kernel parts' cutters use the same boolean.
- Deletion line: r2's "cage connectivity generator" and "cage fitter" leave the production owner
table and become research ports.
fieldleaves the per-part representation enum. Smooth union is not added to the tree vocabulary.
Owners, inputs, outputs, mock points
| Owner | Inputs | Outputs | Mock point |
|---|---|---|---|
| Tree (Geometry.Csg) | text or a cage object, through the one commit primitive | typed tree revision | in-memory store |
| Cage evaluator | cage primitive, level | evaluated mesh (mirror applied) | trait; Blender's output as the oracle (cage-evaluator) |
| Cutter lowering | cutter brush | closed cutter mesh | the kernel, per brush |
| Boolean | evaluated mesh, cutter mesh, cut or split |
pieces, intersection loops with both sides' faces | trait; kernel chosen by the spike |
| Weld | pieces, loops, the two surfaces' curvature | welded pieces, loop edges with bevel weight | pure mesh math |
| Kernel | kernel part | mesh with per-face brush and surface ids | trait |
| Scorer | two meshes | the bar's numbers | pure mesh math, no Blender |
| Research generators | a reference (scan or SDF program) | candidate cage | port; never a production writer |
| Brokkr bridge | intents from brokkr-ctl |
receipts, cage reads, objects in the ship file | directory store or loopback, per blender-transport |
The hand cage
What it is (docs/research/dexter-quiet-cage/ @ d426f86, note @ 4b55c58): half hull of 29 vertices
and 25 faces (19 quads, 6 triangles); about 50 faces mirrored. Nine creases form one chain that the
mirror closes into a loop round the wing rim. At level 3 it evaluates to 3,154 vertices and 3,152 quads,
with 31 irregular vertices and no UVs. Against the scan (vertex to nearest vertex, % of the 1.492
diagonal): cage to scan mean 0.88, p95 2.04, max 3.11; scan to cage mean 1.29, p95 4.12, max 6.03.
Those numbers mix her declared liberty with detail the cage omits by design. They describe the
reference; they are not a bar any production output is held to.
It is the production primary form, not only the yardstick. Production fidelity is by construction: away from detail loops, the shipped part is the cage's limit surface.
Research generators are scored against it (primary-form-is-the-hand-cage). A candidate's
evaluated limit surface is compared with the hand cage's (Mirror, limit, no Bevel) vertex to nearest
vertex both ways, at half to double 3,154 vertices, and by three-axis silhouette IoU. Every measurement
reports the candidate's source against its reference and the candidate cage against its own source
separately, besides the end-to-end number; run 7 lost a spike to an unattributed number. The scan is the
reference only for the hand cage's own recorded liberty. A candidate is interesting when it is no worse
than the hand cage's own spread and meets the cage bar: at most about 200 faces (4x), quads and
triangles only with at most 24 % triangles, closed creases, and a watertight level-3 limit mesh with at
most 62 irregular vertices. Meeting the bar makes a candidate committable as a cage. It gates nothing
else.
Not yet known (owed before or during the next cuts)
- The weld rule's behaviour on real geometry. It has never been run. The spike brief is
spike-boolean-weld.md(Self's scratch); its measures and failure cases decide whether the rule ships as stated, needs a tiebreak, or needs the cutter tessellated to the hull's density. - Which boolean kernel: Manifold through
manifold-csg(Apache-2.0, C++ underneath, with provenance and its own degenerate cleanup), boolmesh (pure Rust, MPL-2.0, released 2026-10-11, 0 % doc coverage), or an extension of the crate's own kernel. The spike measures the first two; the crate's kernel is planar-convex today. - Who evaluates the cage for the lowering: question
cage-evaluator. - Split pieces' interior caps: a through-cut of a closed hull leaves cross-section caps inside both pieces. Whether they are kept (closed pieces, hidden triangles) or dropped (open pieces) depends on how Bevel and Weighted Normal treat the open boundary. The spike probes it.
- How a
cagepart and akernelpart meet on one hull. Under r3 a union with the same boolean and weld is the natural candidate, but nothing has measured it. - Text for a cage part. It prints as a polyhedron-like
subdivision_cage(points, faces, creases, mirror). OpenSCAD would render the cage's control polyhedron, not its limit surface, so cage parts sit outside the "OpenSCAD renders it the same" half oftext-round-trips, as smooth-min parts did in r2.
Research it rests on
All in GameCult.Geometry.Csg docs/research/ on eureka/brush-tree:
dexter-quiet-cage/@4b55c58: the reference cage, the primary-form note, her screenshots (cage files @d426f86).cage-connectivity-prior-art.md@492f83a: no open method reaches a coarse quad cage at this quality.boolean-cleanup-prior-art.md@34cccf3: no named precedent for the weld rule; Manifold's collapse guard; Adaptive Mesh Booleans' failure modes; ownable kernels.detail-on-subd-prior-art.md@c513992: cut into the evaluated mesh is the only option that keeps the cage independent and regenerable; support loops grow the cage.sdf-authoring-text-prior-art.md@6a575d2: no SDF tool round-trips a typed tree through text.subd-cages-mixed-hulls-and-open-kernels.md@390db63: limit evaluation, closest point, no cheap bound.shippable-bar/,mesh-probe-run1/tomesh-probe-run7-im-field/,openscad-evaluators-and-csg-export.md,primitive-seams-and-sdf-bevel-meshing-prior-art.md,brush-surfaces-and-sdf-bricks-prior-art.md,octahedral-impostors-prior-art.md: as in r2.