--- title: "Asset Brief — Furniture / Props" description: "Interior furniture and small props — manifest categories furniture|props, spike prior art exists unpromoted" type: design status: active ticket: "" decision_refs: [D-241, D-244, D-257] author: "Araminta" created: 2026-07-25 updated: 2026-07-25 --- # Asset Brief — Furniture / Props One page. Gates its child story — the story does not enter `in_progress` without this brief attached. --- ## 1. Scope Freestanding interior objects — the manifest's two categories, `furniture` (tables, chairs, storage — occupies a footprint, usually multi-tile) and `props` (smaller/decorative objects — usually single-tile). No D-235 ObjectTag axis applies (that vocabulary is building-exterior only); this class is closest in spirit to D-235's incremental-content *mechanism* (specific-to-generic fallback) without the ratified vocabulary itself — an open question this brief does not resolve (see §5, T-995's ObjectTag extension). **Real prior art exists and is unpromoted**: the spike's `models/` tree holds **five** GLBs total — 3 at `spikes/3dpipeline/models/ furniture/` (`furniture`-category) and 2 at `spikes/3dpipeline/models/ props/` (`props`-category: `lion_statue.glb`, mode "fixed", non-tintable; and `vw_beetle.glb`, a car). Of these five, **four are in this brief's scope** (3 furniture + `lion_statue`) — this brief's first job is promoting that spike output through the now-real production path (`client/assets/ models/`, `manifest.json`), not generating from zero. `vw_beetle.glb` is explicitly **excluded**: it is a vehicle, covered by the Q-067 car deferral in `deferred.md`, not this brief, regardless of sitting in the same spike `props/` directory as `lion_statue.glb`. Out of scope: walls, doors, floors (separate briefs); vehicles (Q-067, deferred — `vw_beetle.glb` per above); the four `deferred.md` classes (lamp posts, TVs, billboards, barns — those are furniture-*tier* objects but are formally deferred by name, not folded into this brief). ## 2. Visual Reference `palette.md` §2 — furniture and props are explicitly named as sharing the character toon treatment (`toon.gdshader`/`toon_masked.gdshader`, `roughness=1.0`/`specular=0.0` default from `postprocess_glb.py:: setup_materials()`), **with the standing glazing/polished-metal carve-out** (§2.1) applying to any prop that is deliberately glass or mirror-finish (a display case, a chrome fixture) — minimal-PBR (`roughness` 0.05–0.2, controlled specular), same rule as building glazing, not a new one. §4's "functional warmth" mood target and the object-tier saturation ceiling (entity > object > structure, §4 table) both apply directly: furniture/prop colors stay moderate saturation, below entity color but the class is allowed more personality than the structural material register (the `shuttered_facade` accent-color precedent is the closest analogue — object- tier is where a saturation bump is permitted, unlike wall/roof/street). ## 3. Naming `_.glb` per `conventions.md` §1 — the spike's existing furniture files (`baroque_table.glb`, `modernist_chair.glb`) are **descriptor-first** and must be **renamed to category-first** (`table_baroque.glb`, `chair_modernist.glb`) at promotion time; `conventions.md` §1 explicitly rules the spike naming "pre-convention scratch work, not a precedent to preserve." `lion_statue.glb` is already category-first as named and needs no rename. Mask sidecar: `_mask .png`, single-channel, per §2 — the existing Trellis convention, just reordered for the renamed furniture items; `lion_statue.glb` is non-tintable ("fixed" mode in the spike) and ships with **no mask sidecar** at all, not an empty one — `conventions.md` §2's `hint_default_black` default already covers "no mask loaded = no tinting" for this case. `footprint_tiles` in the manifest for any furniture with a real multi-tile footprint (a table spanning `[2, 1]`); most `props`-category items, including `lion_statue`, omit the field or set `[1, 1]`. **Footprint for normalized assets** (araminta ruling, PR #214). Blender-normalized GLBs (`target-width=1.0` postprocess, the spike default) lose real-world scale — footprint cannot be derived from geometry after normalization. `footprint_tiles` is therefore an **authored** value, not a measured one: default `[1, 1]` only holds when the object's real-world class is plausibly single-tile (chairs, stools, small props, compact desks). Any item whose class is ordinarily multi-tile (dining tables seating 4+, couches, beds, wardrobes) needs the promoting author to state an intended real-world footprint explicitly (in the promotion commit/PR, or a per-item scale note in the brief) — never left to infer from the normalized mesh. ## 4. Generation Path Two paths, depending on whether the spike asset is being promoted or a new one generated: (a) **Promotion path** for the 4 in-scope existing spike GLBs (3 furniture + `props/lion_statue.glb`) — rename per §3 (furniture items only; `lion_statue` keeps its name), run through Blender postprocess if not already toon-compatible, place in `client/assets/models/furniture/` or `client/assets/models/props/` per actual category, register in `manifest.json`. This IS the promotion act (D-241) — nothing stays "promoted" in `spikes/`. `props/vw_beetle.glb` does **not** take this path; it stays out of scope per §1 (Q-067 car deferral). (b) **New-asset path**, standard: `/image-gen` concept → `/glb-gen` (Trellis) → Blender postprocess → `client/assets/models/{furniture,props}/` + `manifest.json`. Both paths converge on the same manifest registration step. ## 5. Acceptance **4 promotable GLBs** enter `models.md` + `manifest.json` at `planned`: the 3 existing spike furniture GLBs (`spikes/3dpipeline/models/furniture/`), promoted and renamed per §3, plus `spikes/3dpipeline/models/props/ lion_statue.glb`, promoted as-is (no rename, no mask). This satisfies acceptance without generating anything new, since the prior art already exists and simply hasn't crossed the promotion boundary. **Excluded from this count:** `spikes/3dpipeline/models/props/vw_beetle.glb` — a car, held under the Q-067 deferral in `deferred.md`, not promoted by this brief's story. Note for the story: whether a `generic_furniture`/`generic_prop` placeholder parent becomes a formal fallback-chain member (mirroring D-235's wall/roof/facade/street pattern) is exactly Q-119's open question ("generic door/floor/furniture parents") — **milestone-0 IF Q-119 resolves yes**, not resolved by this brief. --- ## Cross-References - `docs/assets/visual/conventions.md` §1, §2, §4 — category-first naming ruling, mask sidecar, footprint metadata - `docs/assets/visual/palette.md` §2, §4 — toon/PBR treatment, saturation-ceiling hierarchy - `docs/assets/visual/models.md` — target catalog - `client/assets/models/manifest.json` - `spikes/3dpipeline/models/furniture/` — existing unpromoted prior art (3 GLBs) - `spikes/3dpipeline/models/props/` — existing unpromoted prior art; `lion_statue.glb` in scope (this brief), `vw_beetle.glb` excluded (Q-067 car deferral, see `deferred.md`) - D-241 — spike binaries local-only; promotion = repo-canonical