footprint_tiles is an authored value, never derived from normalized mesh geometry — [1,1] defaults only for plausibly-single-tile classes; ordinarily-multi-tile classes require an explicitly stated footprint at promotion. Her exact wording in furniture-props.md §3; conventions.md §4 gains the authored-not-derived sentence pointing at the full rule (and a pre-existing 'Single Sunday-tile' typo fixed in passing). The [1,1] values shipped for the four promoted items stand as ruled. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
132 lines
7.1 KiB
Markdown
132 lines
7.1 KiB
Markdown
---
|
||
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
|
||
|
||
`<category>_<descriptor>.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: `<model>_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
|