backup: 2026-06-19 18:09
This commit is contained in:
+79
-21
@@ -5,40 +5,98 @@
|
||||
#+title: trmn/assets
|
||||
#+filetags: :project: :knowledge: :assets:
|
||||
|
||||
:PROPERTIES:
|
||||
:ID: trmn-assets
|
||||
:END:
|
||||
|
||||
#+title: trmn/assets
|
||||
#+filetags: :project: :knowledge: :assets:
|
||||
|
||||
[[id:6293baa2-c8a8-4c49-9284-1fa2eed75032][trmn]] — asset pipeline: SVG sprites + GLB objects
|
||||
[[id:6293baa2-c8a8-4c49-9284-1fa2eed75032][trmn]] — asset pipeline: SVG sprites + GLB objects + location scenes
|
||||
|
||||
** Architecture
|
||||
Two asset types, both served from ~$out/assets/~ by Caddy:
|
||||
Three asset types, all served from ~$out/assets/~ by Caddy:
|
||||
- *Sprites*: SVG files in ~assets/sprites/{eyes,nose,mouth}/~, static/committed, no build step
|
||||
- *3D objects*: GLB files in ~assets/objects/~, generated during ~nix build~ by Node.js scripts in ~scripts/~
|
||||
- *Location scenes*: ~.blend~ files in ~assets/scenes/**~ are the source of truth; Blender exports GLBs at build time, then packed into ~assets/scenes/scenes.pack~ (single binary, one browser fetch)
|
||||
|
||||
Face compositing at runtime: load SVG parts → draw onto ~OffscreenCanvas(128,128)~ → ~THREE.CanvasTexture~.
|
||||
Applied to the +z front face (index 4) of the head ~BoxGeometry~ via a material array.
|
||||
|
||||
** Location Scene Pipeline
|
||||
~.blend~ files are the source of truth (edit in Blender, commit ~.blend~, GLBs are build artifacts):
|
||||
1. ~flake.nix~ buildPhase: ~blender --background file.blend --python scripts/export-glb.py -- out.glb~ for each ~.blend~ in ~assets/scenes/**~
|
||||
2. ~scripts/pack-scenes.mjs glb_tmp assets/scenes/scenes.pack~: validates all SCENES location IDs have a GLB (warn by default, ~STRICT_LOCATIONS=1~ to error), concatenates into ~scenes.pack~
|
||||
3. Pack format: ~[4-byte LE uint32: manifest len][JSON manifest][...GLB bytes]~
|
||||
4. Runtime: ~loadPack()~ fetches once, ~loadLocationScene(id)~ slices + parses per scene, cached
|
||||
|
||||
34 unique location IDs (e.g. ~home/bedroom~, ~office~, ~school/classroom~). Directory mirrors IDs: ~assets/scenes/home/bedroom.blend~ → ID ~home/bedroom~. Full mapping in ~ASSETS.md~.
|
||||
|
||||
** Blender Naming Conventions (procedural overrides)
|
||||
- ~IF_<NAME>~ meshes: toggled visible/hidden at runtime by ~applyLocationProps()~
|
||||
Examples: ~IF_CRIB~ (age<3), ~IF_ADULT_BED~ (age≥13), ~IF_TV_LARGE~ (wealthLevel>70)
|
||||
- ~WALLS~, ~FLOOR~: material color replaced at runtime with deterministic palette color
|
||||
- All other mesh names: always visible, untouched
|
||||
Full ~IF_*~ table and authoring guide in ~ASSETS.md~.
|
||||
|
||||
** Blender Scene Setup
|
||||
- Character is ~2 units tall; typical interior: 5–8 units wide, 3 units tall
|
||||
- Camera: pos ~(0.5, 1.6, 6.5)~, looks at ~(0, 1.0, 0)~, FOV 26°, aspect 2.39:1
|
||||
- No lights in .blend files — runtime adds ambient + two directional lights
|
||||
- Materials: Diffuse BSDF (flat color); Principled BSDF works but is overkill under Lambert
|
||||
- ~export_apply=True~ in export script — modifiers applied; no armatures/animations
|
||||
- Poly budget: ~500 triangles/scene; outdoor scenes skip WALLS/FLOOR (no runtime error)
|
||||
- Run ~nix develop~ to get a shell with ~blender~ on PATH for authoring
|
||||
|
||||
** Runtime API (~index.html~ Three.js block)
|
||||
- ~loadPack()~: called once at init; gracefully no-ops if pack not built yet
|
||||
- ~loadLocationScene(locationId)~: returns ~THREE.Group~ (cloned from cache), or ~null~ if not in pack
|
||||
- ~applyLocationProps(threeScene, props)~: traverses scene, applies ~IF_*~ visibility + WALLS/FLOOR colors
|
||||
- ~generateLocationProps(locationId, masterSeed, playerState, eventLog?)~ from ~locations.js~
|
||||
- ~window.__sceneLoader.loadAndShow(locationId, props)~: removes previous loc scene, loads + applies new one
|
||||
|
||||
** Debug Panel (~▸ scene debug~ in browser)
|
||||
Collapsible ~<details>~ panel below the chat box. Controls:
|
||||
- Location dropdown (all 34 IDs, populated from ~SCENES~ at runtime)
|
||||
- Sliders: age, wealth, children, job tier, moves (home move count)
|
||||
- *sync from today*: pulls actual simulated state from ~window.__life~
|
||||
- *load scene*: calls ~window.__sceneLoader.loadAndShow()~; shows ~[not in pack]~ if .blend missing
|
||||
- Live props display: wall/floor color swatches + hex, visible ~IF_*~ mesh names
|
||||
Props update on every slider move even without a loaded scene.
|
||||
|
||||
** locations.js
|
||||
ES module, imported by Three.js block and debug module. Exports ~generateLocationProps~.
|
||||
- Home: seeded from ~makeRng(masterSeed, 200000 + moveIndex)~ where moveIndex = count of ~move_city~ events ≤ currentDay → new house each time player moves
|
||||
- Office: offset 300000; School: 301000; University/dorm: 302000; others: hash into 303000–399999
|
||||
- ~playerState~ fields: ~{ age, wealthLevel, numChildren, jobTier, inCollege, retired, currentDay }~
|
||||
|
||||
** PRNG Offset Allocation (all streams)
|
||||
| Range | Owner |
|
||||
|---|---|
|
||||
| -2 to -1 | Family layout + protagonist traits |
|
||||
| 0 – 36,500 | Life simulation daily |
|
||||
| 50,000+ | Schedule (per-day, offset 50000) |
|
||||
| 200,000 + moveIndex | Home appearance (per house) |
|
||||
| 300,000 | Workplace |
|
||||
| 301,000 | School |
|
||||
| 302,000 | University / dorm |
|
||||
| 303,000–399,999 | Other locations (hashed from ID) |
|
||||
|
||||
** Conventions
|
||||
- All sprite SVGs are 128×128; each draws its feature in the region it occupies on the face canvas
|
||||
(eyes ~y≈35–55~, nose ~y≈65–85~, mouth ~y≈90–110~) so all layers composite with ~drawImage(img, 0, 0, 128, 128)~
|
||||
- Face part selection seeded from ~window.__life.masterSeed~ via inline ~mulberry32~ in the Three.js script block
|
||||
- ~window.__life~ exports ~masterSeed~ (added alongside traits/buf/eventLog/today/currentDay)
|
||||
- GLB generators: pure Node.js stdlib only (no npm), accept output path as ~process.argv[2]~
|
||||
- Three.js importmap includes ~"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/"~ for GLTFLoader
|
||||
- All sprite SVGs are 128×128; composite with ~drawImage(img, 0, 0, 128, 128)~
|
||||
- Face part selection seeded from ~window.__life.masterSeed~ via inline ~mulberry32~ in Three.js block
|
||||
- GLB generators: pure Node.js stdlib only (no npm), accept output path as arg
|
||||
- ~pkgs.blender~ in ~nativeBuildInputs~ (build) and ~devShells.buildInputs~ (~nix develop~ shell)
|
||||
|
||||
** Gotchas
|
||||
- *Critical*: Nix flake ~src = ./.~ only includes git-tracked files (~git ls-files~).
|
||||
New ~assets/~ and ~scripts/~ dirs must be ~git add~-ed before ~nix build~ or they are silently excluded.
|
||||
- ~BoxGeometry~ material array face order: ~[+x, -x, +y, -y, +z, -z]~ → index 4 is the front face (camera-facing)
|
||||
- GLB generator runs in Nix buildPhase and writes to the build dir; installPhase ~cp -r assets $out/assets~ picks up both committed sprites and the generated ~book.glb~
|
||||
- ~src = ./.~ only includes git-tracked files. Run ~git add assets/scenes/ scripts/export-glb.py scripts/pack-scenes.mjs locations.js~ before ~nix build~ or they are silently excluded.
|
||||
- ~BoxGeometry~ material array face order: ~[+x, -x, +y, -y, +z, -z]~ → index 4 is front face
|
||||
- GLB generator runs in Nix buildPhase and writes to build dir; ~cp -r assets $out/assets~ picks up generated files
|
||||
- ~locations.js~ imports ~makeRng~ from ~./life.js~; served by Caddy alongside other JS modules
|
||||
- Blender headless needs ~--background~ flag; no X11 required in stdenvNoCC sandbox
|
||||
|
||||
** Key Files
|
||||
- ~assets/sprites/eyes/eyes_{1,2}.svg~ — wide-open vs narrow/tired eyes
|
||||
- ~assets/sprites/nose/nose_{1,2}.svg~ — dot vs nostrils nose
|
||||
- ~assets/sprites/mouth/mouth_{1,2}.svg~ — smile vs neutral mouth
|
||||
- ~assets/objects/book.glb~ — generated at build time (not committed); dark-red flat box 0.14×0.18×0.03
|
||||
- ~scripts/gen-book.mjs~ — pure Node.js GLB writer, no npm deps; ~node scripts/gen-book.mjs <outpath>~
|
||||
- ~assets/objects/book.glb~ — generated at build time; dark-red flat box 0.14×0.18×0.03
|
||||
- ~assets/scenes/~ — ~.blend~ source files, mirroring location ID hierarchy
|
||||
- ~assets/scenes/scenes.pack~ — build artifact; binary pack of all location GLBs
|
||||
- ~scripts/gen-book.mjs~ — pure Node.js GLB writer for book object
|
||||
- ~scripts/export-glb.py~ — Blender Python: exports active scene to GLB
|
||||
- ~scripts/pack-scenes.mjs~ — validates + concatenates GLBs into ~scenes.pack~
|
||||
- ~locations.js~ — ~generateLocationProps(locationId, masterSeed, playerState, eventLog?)~
|
||||
- ~ASSETS.md~ — full authoring guide: location→file map, IF_* table, Blender setup, workflow
|
||||
|
||||
Reference in New Issue
Block a user