Game guide · source of truth
Ledger

M0-02

Blender headless smoke: cube → GLB → PNG

← Ledger

donestatus · M0
10✓ 1✗tests passed / failed
5.62Mtokens · 9 min
4evidence files · 245 kB

Evidence

From logs/evidence/M0-02/. Click a thumbnail for the full image.

Images (1)

smoke_render.png
smoke_render.png · 240 kB

Logs and data (3)

smoke_blender_log.txt · 1 kB · open
$ /Users/king/Applications/Blender.app/Contents/MacOS/Blender -b --factory-startup --python-exit-code 1 -P /Users/king/Desktop/Workspace/SRO/zoen/tools/blender/smoke.py --
exit 0
…last 40 lines…
INFO Draco mesh compression is available, use library at /Users/king/Applications/Blender.app/Contents/Resources/4.5/scripts/addons_core/io_scene_gltf2/libextern_draco.dylib
08:40:37 | INFO: Starting glTF 2.0 export
08:40:37 | INFO: Extracting primitive: SmokeCube
08:40:37 | INFO: Primitives created: 1
08:40:37 | INFO: Finished glTF 2.0 export in 0.011265993118286133 s
Blender 4.5.9 LTS (hash 8bf95cbd38d1 built 2026-04-21 01:30:46)
Fra:1 Mem:46.91M (Peak 46.91M) | Time:00:00.08 | Rendering 1 / 32 samples
Fra:1 Mem:47.00M (Peak 47.00M) | Time:00:00.17 | Rendering 25 / 32 samples
Fra:1 Mem:47.00M (Peak 47.00M) | Time:00:00.20 | Rendering 32 / 32 samples
Saved: '/Users/king/Desktop/Workspace/SRO/zoen/logs/evidence/M0-02/smoke_render.png'
Time: 00:00.22 (Saving: 00:00.01)


ZOEN_SMOKE_OK {"glb": "art/build/smoke/smoke_cube.glb", "png": "logs/evidence/M0-02/smoke_render.png", "engine": "BLENDER_EEVEE_NEXT", "tris": 12}

Blender quit
smoke_validate.txt · 1 kB · open
M0-02 Blender smoke · 2026-10-08T00:40:37.861Z
Blender 4.5.9 LTS (glTF exporter 4.5.51) · render BLENDER_EEVEE_NEXT 0.2204 s · export 0.0716 s · total 0.3424 s
GLB art/build/smoke/smoke_cube.glb (19,904 bytes)
  PASS  glTF 2.0: Khronos glTF Blender I/O v4.5.51
  PASS  triangles: 12 (expected 12)
  PASS  one mesh, node and primitive: 1 meshes, 1 instances, 1 primitives
  PASS  bounds 1 m: size [1, 1, 1] m
  PASS  +Y up, base at y = 0: min [-0.5, 0, -0.5] max [0.5, 1, 0.5]
  PASS  transforms applied: SmokeCube: no rotation, no scale
  PASS  normals: POSITION, NORMAL, TEXCOORD_0
  PASS  UVs (TEXCOORD_0): 0 primitives without UVs
  PASS  one PBR material: M_SmokeCube: metallic 0, roughness 0.5
  PASS  single-sided: doubleSided false
  PASS  embedded base-colour texture: 1 image(s), 0 external, largest 256 px
  PASS  no skin: 0 skins, 0 skinned nodes, 0 parts with JOINTS/WEIGHTS
  PASS  no animation or morph targets: 0 animations, 0 morph parts
  PASS  no Draco/meshopt: none required
  PASS  no cameras or lights: 0 cameras
PNG logs/evidence/M0-02/smoke_render.png
  PASS  size 512 × 512: 512 × 512
  PASS  not black or white: luma mean 0.388 (allowed 0.03–0.97)
  PASS  not blank: luma std 0.096 (min 0.03)
Metrics logs/evidence/M0-02/smoke_metrics.json
  PASS  Blender and GLB triangles agree: Blender 12, GLB 12
  PASS  render settings: BLENDER_EEVEE_NEXT 512 × 512
RESULT PASS: 20/20 checks
smoke_metrics.json · 2 kB · open
{
  "task": "M0-02",
  "blender": "4.5.9 LTS",
  "blenderBuild": {
    "hash": "8bf95cbd38d1",
    "date": "2026-04-21"
  },
  "gltfExporter": "4.5.51",
  "mesh": {
    "name": "SmokeCube",
    "tris": 12,
    "verts": 8,
    "faces": 6,
    "uvLayers": [
      "UVMap"
    ],
    "materials": [
      "M_SmokeCube"
    ],
    "baseColorTexture": {
      "name": "T_SmokeGrid",
      "size": [
        256,
        256
      ]
    },
    "boundsBlenderZUp": {
      "min": [
        -0.5,
        -0.5,
        0.0
      ],
      "max": [
        0.5,
        0.5,
        1.0
      ],
      "size": [
        1.0,
        1.0,
…

Tests

pass blender smoke.py (raw run) · 6.0 s · raw log$ /Users/king/Applications/Blender.app/Contents/MacOS/Blender -b --python-exit-code 1 -P tools/blender/smoke.py
pass smoke validator self-test · 0.1 s · raw log$ node --test tools/blender/smoke.test.mjs
pass blender smoke: cube to GLB to PNG + validate · 0.9 s · raw log$ pnpm blender:smoke
fail data tests · 6.5 s · raw log$ pnpm data:test
pass data tests · 6.5 s · raw log$ pnpm data:test
pass zoen-sim cargo tests + clippy · 1.8 s · raw log$ pnpm sim:test
pass Zoen.Core dotnet build + xunit · 1.4 s · raw log$ pnpm core:test
pass docs lint + index · 0.2 s · raw log$ pnpm docs:lint
pass wiki typecheck · 5.0 s · raw log$ pnpm --filter @zoen/wiki typecheck
pass wiki production build · 9.8 s · raw log$ pnpm wiki:build
pass wiki e2e (changed specs) · 0.7 s · raw log$ pnpm --filter @zoen/wiki exec playwright test --only-changed

Notes

2026-10-08 00:42 UTC · Evidence logs/evidence/M0-02/: smoke_render.png (512x512 Eevee Next), smoke_metrics.json (Blender 4.5.9 LTS, glTF exporter 4.5.51, 12 tris, bounds, export 0.07 s, render 0.22 s), smoke_validate.txt (20/20 PASS), smoke_blender_log.txt (log tail). GLB art/build/smoke/smoke_cube.glb (art/build/ now git-ignored). Decisions: tools/blender/smoke.py replaced the old training-dummy smoke (same CLI: -- [out_dir] [glb_dir], SETUP command still valid); cube origin at base centre so GLB y 0..1 proves +Y up; glTF settings for the Unity import (glTFast, not installed): GLB, embedded PNG, +Y up, metres, export_apply, no tangents, no Draco/meshopt, no skins/anims/morphs/cameras/lights, backface culling on -> doubleSided false; Eevee works headless (Workbench fallback kept, unused). Validator tools/blender/smoke.mjs reuses model-inbox parseGlb/inspectGlb + own 8-bit PNG decoder; self-test smoke.test.mjs 4/4. Finding: installed Blender is 4.5.9 LTS not 4.2.3 (SETUP.md, stack.json check, CONTINUE_HERE corrected). pnpm blender:smoke added; UNITY_TOOLKIT one line. No proposed values.