The right axis wasn't "generate or don't" — it was WHICH HALF. Geometry stays procedural because a molecule's shape is already known exactly. **Material is exactly a generation problem**, and it's the whole difference between a textbook diagram and a game object. So MODELBEAST made the materials. 5 greyscale matcaps, flux_local, 69 seconds, $0.00, 68 KB total: mol_glass (O,N) — the big win: oxygen is a red glass marble with internal glow mol_matte (C) — graphite soot; carbon reads as the scaffold it is mol_chrome (Co) — B12's cobalt is now a chrome bearing in a cage mol_molten (P) — ATP's phosphate tail is incandescent AND pulses (uTime, free) mol_pearl (H) — satin white; hydrogens stop shouting The trick is Lane D's own law applied to spheres: author the LUMINANCE, tint in-shader. derive_maps already greyscales every matcap, so one glass ball serves oxygen AND nitrogen at their own CPK hues — 5 balls dress the whole periodic table we care about. They pack into one strip atlas indexed per-vertex by aMat, so **a molecule is still exactly 1 draw call** however many materials it's made of (7 molecules = 7 draws, unchanged). ?matcap=0 falls back to the built-in fake-lit path: the assets-optional law holds. SPACE-FILLING WINS FOR PICKUPS, and the canal decided it, not me. New `repr: 'space-filling'` draws every atom at its real van der Waals radius with no sticks. A/B'd at real pickup size against the real L2 wall, same camera: ball-and-stick goes spindly and dissolves; the solid blob holds its silhouette — and it's CHEAPER (21k vs 26k tris, no bond cylinders). Recommendation to B: space-filling in flight, ball-stick for hero/UI/collect close-ups where the chemistry is worth reading. Evidence: round2_molecule_materials.png (3-way). Two defects found by rendering it, both mine, both fixed: - Tint x luminance darkens TWICE: CPK carbon is 0.4 and a matte ball averages 0.5, so soot x soot vanished — the first pass sank glucose, caffeine and the cobalt into the background. Floored the matcap at 0.22, the same floor the fallback's key light always had. - The molten matcap was my own bad prompt: I asked for an "incandescent white hot CORE" and got exactly that — a black ball with a hot spot, so phosphorus lost its orange. Re-rolled for the whole sphere to glow (attempt 2 of the <=2 PIPELINE allows). Lesson for the kit, next to the organ/tissue one: a matcap is a LUMINANCE LOOKUP, so a dark-dominant ball makes a dark-dominant object. Also corrected the doc's own framing — v1 said "I'm authorised to burn GPU and I'm not going to", which was the wrong axis, not just the wrong tone. qa GREEN; 16/16 texture provenance verified (synced the FIXED batch json up first this time, so the box couldn't clobber it on the way back). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
202 lines
13 KiB
Markdown
202 lines
13 KiB
Markdown
# MOLECULES — a proposal (Lane A, round 2)
|
||
|
||
**Status: PROTOTYPE + argument.** Nothing here is wired into boot. Pickups are Lane B's
|
||
systems, their economy is Lane C's, object art is Lane D's — this document is a pitch to all
|
||
three, plus a working renderer they can take or leave.
|
||
|
||
Fly it: `web/dev/laneA_molecules.html` · code: `web/js/world/molecule.js` ·
|
||
evidence: `docs/shots/laneA/round2_molecule_pickups.png` (the set + roles),
|
||
`round2_molecule_materials.png` (flat vs matcap vs space-filling, in the real canal),
|
||
`round2_molecules_in_canal.png`, `round2_molecules_truescale.png`
|
||
|
||
---
|
||
|
||
## The pitch in one line
|
||
|
||
**The pickups already in L2 are molecules — so draw them as molecules.**
|
||
|
||
C authored `nutrient`, `mucin`, `B12`, `antacid ammo` before any of this existed. Those aren't
|
||
game-flavoured names; they're the actual biochemistry of a digestive tract. Glucose, cobalamin
|
||
and bicarbonate are *real compounds with known shapes*. We don't have to invent a pickup
|
||
language — we have to stop hiding the one the fiction already handed us.
|
||
|
||
## Why this is free sciency-ness, and why it isn't educational
|
||
|
||
The game does not explain anything and should not start. Nobody needs to know what ATP is.
|
||
But a purine reads as *chemistry* to anyone alive, the way a circuit diagram reads as
|
||
*electronics* — because it is the real notation, not an impression of one. **The game gets to
|
||
feel sciency by not faking it**, which is cheaper than faking it and better.
|
||
|
||
Consider what's already true: an **eosinophil** is a real white blood cell. **Candida** is a
|
||
real yeast. A **bolus** is a real mass of chewed food. The **hiatus** is a real anatomical
|
||
choke point. **GUTS is already a science game** — C built it that way. It just doesn't *look*
|
||
like one yet, because everything on screen is tinted tissue.
|
||
|
||
## The one rule that makes it all work: CPK is the scanner
|
||
|
||
**Everything the ship's scanner has identified is drawn in CPK colours. Everything it hasn't
|
||
is monochrome tinted tissue.**
|
||
|
||
CPK is the standard element palette — oxygen red, nitrogen blue, phosphorus orange, sulfur
|
||
yellow, metals pink. Every chemistry textbook and protein viewer on earth uses it. Against six
|
||
biomes of tinted tissue, **a CPK molecule is the only saturated foreign colour on screen**, so
|
||
it reads as artificial, valuable and targetable at a glance — *with no HUD marker*
|
||
(`round2_molecules_in_canal.png` is the proof: a glucose in the esophagus, unmissable).
|
||
|
||
That's ART_BIBLE's synthetic-scanner fiction paying rent: the ship identifies a compound and
|
||
colours it in. → **Lane E**: this is a free HUD language. Accent a readout in an element's CPK
|
||
colour and it belongs to that compound with no legend.
|
||
|
||
## The division of labour: procedural geometry, generated materials
|
||
|
||
**MODELBEAST makes the materials. Procedural makes the shapes.** Both halves matter and they
|
||
are not in competition — the first version of this doc framed it as "don't use the GPU", which
|
||
was the wrong axis and is corrected below.
|
||
|
||
**Geometry is not a generation problem, because a molecule's shape is already known exactly.**
|
||
Glucose is a hexagonal ring because it is a hexagonal ring. FLUX + TRELLIS would give a
|
||
plausible blob, in 3–8 minutes, that a chemist clocks as wrong instantly and that can never be
|
||
re-derived. Ball-and-stick from an atom list is exact, rebuilds in milliseconds, and is **one
|
||
draw call per molecule** (measured: 7 molecules = 7 draws, 26.5k tris total; glucose alone is
|
||
3.7k tris / 1 draw).
|
||
|
||
**Material is exactly a generation problem**, and it's what separates a diagram from an object
|
||
— see the next section.
|
||
|
||
### What MODELBEAST *did* do: the materials (round 2, second pass)
|
||
|
||
Geometry is exact and free. **Material is where the GPU earns its keep** — and it's the whole
|
||
difference between a textbook diagram and a game object. GUTS has no real-time lights by law,
|
||
so a **matcap** (a lit-sphere image) is the only way to make something look *made of* anything.
|
||
|
||
Five greyscale matcaps, flux_local, **69 seconds, $0.00, 68 KB total**:
|
||
|
||
| matcap | elements | what it does |
|
||
|---|---|---|
|
||
| `mol_glass` | O, N | **the big win.** Oxygen becomes a deep red glass marble with internal glow. |
|
||
| `mol_matte` | C | graphite soot. Carbon is scaffold, and now it reads as scaffold. |
|
||
| `mol_chrome` | Co, Fe, Na | polished metal — B₁₂'s cobalt is a chrome bearing in a cage. |
|
||
| `mol_molten` | P | ATP's phosphate tail is incandescent, and **pulses** (`uTime`, free). |
|
||
| `mol_pearl` | H | soft satin white; hydrogens stop shouting. |
|
||
|
||
**The trick that makes it cheap is Lane D's own law, applied to spheres**: author the
|
||
*luminance*, tint in-shader. `derive_maps` greyscales every matcap already, so one glass ball
|
||
serves oxygen *and* nitrogen at their own CPK hues. Five balls dress the whole periodic table
|
||
we care about, and they pack into one strip atlas indexed per-vertex by `aMat` — so **a
|
||
molecule is still exactly one draw call** no matter how many materials its atoms are made of.
|
||
`?matcap=0` falls back to the built-in fake-lit path: the assets-optional law holds.
|
||
|
||
Two things that only showed up by rendering it, both fixed:
|
||
- **Tint × luminance darkens twice.** CPK carbon is already 0.4 and a matte ball averages 0.5,
|
||
so soot × soot vanished — the first pass sank glucose, caffeine and the cobalt into the
|
||
background. Floored the matcap at 0.22, the same floor the fallback's key light has always
|
||
had.
|
||
- **The molten matcap was my own bad prompt**: I asked for an "incandescent white hot *core*"
|
||
and got exactly that — a black ball with a hot spot, so the phosphorus lost its orange
|
||
entirely. Re-rolled asking for the *whole sphere* to glow. Lesson for the kit, next to the
|
||
organ/tissue one: **a matcap is a luminance lookup, so a dark-dominant ball makes a
|
||
dark-dominant object.** Ask for bright, always.
|
||
|
||
### What the canal decided: space-filling wins for pickups
|
||
|
||
`buildMolecule(id, {repr})` now does `'ball-stick'` (default) or `'space-filling'` — every atom
|
||
at its real van der Waals radius, no sticks, atoms merging into one solid lump. A/B'd at real
|
||
pickup size against the real L2 wall, same camera (`round2_molecule_materials.png`):
|
||
|
||
**Ball-and-stick goes spindly and starts dissolving. Space-filling holds its silhouette — and
|
||
it is CHEAPER** (21k vs 26k tris across the set: no bond cylinders). It's also more true, since
|
||
that *is* how a molecule occupies space.
|
||
|
||
→ **Recommendation to B**: `space-filling` for anything in flight, `ball-stick` for hero, UI,
|
||
the medal card and the collect close-up — where the chemistry is legible and worth reading.
|
||
The obvious LOD (blob far, sticks near) is untested and I'm not claiming it.
|
||
|
||
**The split, and it's a principle, not a preference:**
|
||
|
||
| kind | how | why |
|
||
|---|---|---|
|
||
| **Small molecules** — glucose, ATP, caffeine, bicarbonate, capsaicin, B12, ions | **procedural ball-and-stick** | exact geometry is known; generation can only degrade it |
|
||
| **Proteins / enzymes** — pepsin, trypsin, lipase, mucin | **MODELBEAST** (flux → sf3d → trellis) | real ones are 3000-atom blobs; nobody reads their structure. A blob is the honest render, and PIPELINE says blobby organics are TRELLIS's sweet spot |
|
||
| **Cells / creatures** — eosinophil, candida, bolus, ENDO-1 | **MODELBEAST** (Lane D's round-2 headline, gated on concept sign-off) | organic, no canonical geometry, exactly what it's for |
|
||
|
||
So MODELBEAST still does the heavy lifting — on the things where invention is the right answer.
|
||
|
||
## The library (built, rendering, in the sheet)
|
||
|
||
Every one of these is really in the human gut. That constraint does the design work: the pickup
|
||
table *is* the biochemistry of digestion, so nothing has to be invented and the fiction is
|
||
automatic.
|
||
|
||
| molecule | proposed role | why it's the right object |
|
||
|---|---|---|
|
||
| **Glucose** `C₆H₁₂O₆` | nutrient / score | Food. The reason the canal exists. Common, stacks. |
|
||
| **ATP** `C₁₀H₁₆N₅O₁₃P₃` | **boost** | Literally the cell's energy currency. The orange triphosphate tail *is* the charge — a body spends ATP by snapping one off. A boost pickup that visibly carries three charges is a diagram of its own mechanic. |
|
||
| **Bicarbonate** `HCO₃⁻` | **antacid ammo** | Already in L2. `HCO₃⁻ + HCl → salt + H₂O + CO₂` is the real reaction that neutralises stomach acid — fire it into the acid sea and it genuinely fizzes. |
|
||
| **Caffeine** `C₈H₁₀N₄O₂` | **overdrive** | Really absorbed through the gut wall. Everyone knows what it does to a body: throttle up, twitchier, wears off badly. Needs no tutorial. |
|
||
| **Capsaicin** `C₁₈H₂₇NO₃` | **burn hazard** | Chilli. Long greasy tail + aromatic ring = a silhouette that reads *wrong* across a room, and it tumbles unlike any compact pickup. Free readability. |
|
||
| **Vitamin B₁₂** `C₆₃H₈₈CoN₁₄O₁₄P` | **rare treasure** | C already authored B12 as a pickup. It's the most complex vitamin and the *only one with a metal at its heart* — a cobalt in a corrin cage. It renders as a jewel in a setting. |
|
||
| **Water** `H₂O` | trickle / chaff | Everywhere, worth a sliver. The size floor. |
|
||
|
||
**Size is a free rarity signal.** `buildMolecule(id, {unit})` keeps molecules at their TRUE
|
||
relative sizes: water is a speck, B12 is a chandelier (`round2_molecules_truescale.png`). The
|
||
player learns what's worth chasing before reading a single colour, and it costs nothing because
|
||
it's just true. (`{fit}` normalises them all to one size instead, if a pickup must occupy a
|
||
fixed box — B's call.)
|
||
|
||
## Cheap next molecules, if this lands
|
||
|
||
- **Ions as basic ammo/energy**: Na⁺, K⁺, Cl⁻, Ca²⁺ — single coloured spheres, ~30 tris, and
|
||
they're the real electrolytes. Violet, green, purple: instant colour-coded ammo types.
|
||
- **Ethanol** `C₂H₅OH` — a *powerdown*. Controls drift, aim lags. Funny, real, gut-absorbed.
|
||
- **Vitamin C** `C₆H₈O₆` — coat repair (it's the antioxidant). Pairs with B12 as a vitamin tier.
|
||
- **Mucin** — the coat itself, and it's already a pickup. It's a glycoprotein → MODELBEAST blob,
|
||
not ball-and-stick. Good first test of the split above.
|
||
- **HCl** — the acid sea's own molecule. One green Cl, one white H. The sea could *shed* them.
|
||
|
||
## Other ways to be sciency that cost ~nothing
|
||
|
||
1. **Show the real pH.** L3's identity is "ambient pH drains the coat". Stomach pH really is
|
||
~1.5–3.5. A HUD readout ticking `pH 1.8` as you descend is instantly sciency, is true, and
|
||
is one number. → Lane E / C.
|
||
2. **Name the real reaction when it fires.** Antacid hit → `HCO₃⁻ + HCl → NaCl + H₂O + CO₂↑`
|
||
flashed for half a second in the feed. Never explained. Reads as an instrument log.
|
||
3. **Let CO₂ be the fizz.** The bicarbonate reaction really produces gas. Bubbles from a
|
||
neutralised acid patch are the reaction being visible, not a particle effect.
|
||
4. **The enemies are already real** — lean in. `eosinophil_swarm` is a real immune response to
|
||
an invader. The player IS the invader. That's the whole game's joke and it's science.
|
||
|
||
## What I'd need from each lane
|
||
|
||
- **→ C**: are these the roles you want? The economy is yours. If `nutrient` should be glucose
|
||
and `antacid` bicarbonate, they're built. Tell me which molecules a level needs.
|
||
- **→ B**: `buildMolecule(id, {fit|unit, detail, material})` returns one `THREE.Mesh`, one draw,
|
||
`.userData` carries name/formula/role. Share ONE material across all of them (colour is
|
||
per-vertex, so they still batch). Use `detail: 1` for live pickups, `2` for hero/close.
|
||
- **→ D**: this doesn't touch your pack and doesn't want your GPU time. It *asks* for the split
|
||
above — proteins and cells are yours, small molecules are arithmetic. Your round-2 hero list
|
||
is unaffected.
|
||
- **→ E**: CPK as the scanner's identification language is a free HUD palette. `ELEMENTS` in
|
||
`molecule.js` exports the hexes.
|
||
- **→ F**: `world/molecule.js` sits in my dir because it's my dir, not because molecules are
|
||
"world". If this is adopted it probably wants a shared `web/js/fx/` — your call.
|
||
|
||
## Honest limitations
|
||
|
||
- **Geometry is idealised, not crystallographic**: correct connectivity, ring sizes and bond
|
||
orders, believable angles, authored mostly flat because a flat ring reads instantly and spins
|
||
well. Real molecules pucker (glucose is a chair, not a hexagon). This is a game, not PyMOL —
|
||
but nobody should mistake this table for a structure database later.
|
||
- **The B12 is a simplified corrin core** — the real thing has a nucleotide tail and far more
|
||
side chains. It reads as "jewel in a cage", which is the job.
|
||
- **Not performance-tested at pickup density.** 7 on screen is 7 draws / 26k tris (13 draws /
|
||
87k with the canal behind them). Fifty would want instancing or a merged batch, and neither
|
||
exists yet.
|
||
- **The matcap atlas is built at runtime from a canvas.** Fine, but it means a one-frame hitch
|
||
on first build and it bypasses `assets.matcap()` (it reads `assets.get('matcaps', …).url` —
|
||
the documented floor — and loads the images itself, because an atlas needs pixels and
|
||
`matcap()` hands back a `THREE.Texture` that may not have decoded yet). If this is adopted,
|
||
baking the atlas offline in `derive_maps.py` would be tidier and D may prefer it.
|
||
- **`repr: 'space-filling'` hides the bonds by definition**, so a molecule's *chemistry* stops
|
||
being readable — that's the trade for silhouette, and it's why ball-stick stays the default
|
||
for anything the player is meant to look AT rather than fly at.
|