Skip to content

Replace the greybox with a generated art set - #5

Merged
ralyodio merged 1 commit into
mainfrom
feat/generated-art-set
Jul 26, 2026
Merged

Replace the greybox with a generated art set#5
ralyodio merged 1 commit into
mainfrom
feat/generated-art-set

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Closes #1.

The game was a greybox — every visible solid was a MeshBuilder box built from the collision map and skinned with runtime canvas noise, there were no 3D models, and the player's hands were empty.

Pipeline (tools/art)

Everything is generated, nothing downloaded, so the whole set satisfies CLAUDE.md's provenance rule:

pnpm assets:build              # models + textures
pnpm assets:build --previews   # + a hero render per model

Seeded and byte-reproducible — verified across two full builds, all 32 artefacts identical.

What ships

10 models (container, tank, deck, pipe_rack, wall, hardpoint, stair, lamp_mast, character, carbine) and 7 PBR materials at 1024² plus an IBL environment. 3.0 MB total against a 15 MB shell budget.

Props are tiled and scaled to fill the same collision volumes, so "what you see is what you collide with" still holds.

Three fixes that weren't cosmetic

  • IBL is mandatory. A PBR metal is lit almost entirely by what it reflects; with no scene.environmentTexture every steel, rust and grating surface rendered pure black.
  • Light cap. Babylon's default 4-lights-per-mesh silently dropped lamps depending on where you stood.
  • Weapon pointed backwards. The glTF loader's __root__ is scaled (1,1,-1) to convert right-handed glTF into Babylon's left-handed space, aiming the barrel at the player.

Also fixed: the PWA runtime cache matched .glb but not .webp, so an offline launch would have loaded untextured models.

Notes

  • Weapon viewmodel is excluded from photo mode; the vantages are environment showcases and a rifle across the lower third hides the yard. Marketing captures regenerated.
  • apps/game/src/assets.test.ts guards the Blender↔engine boundary — a renamed material slot un-skins a mesh silently and nothing else would catch it.
  • Requires Blender 4.5+ to rebuild; the built assets are committed, so normal builds and CI need nothing new.

188 tests pass (was 179). Format, lint and typecheck clean.

🤖 Generated with Claude Code

The game was a greybox: every visible solid was a MeshBuilder box built from
the collision map and skinned with canvas-generated noise, there were no 3D
models at all, and the player's hands were empty. This adds a reproducible
asset pipeline and wires its output into the yard.

Pipeline (tools/art):
  - Blender 4.5 Python generators for every model, run headless. Seeded, so
    a rebuild is byte-identical — verified across two full builds.
  - numpy PBR texture generator: 7 materials x albedo/normal/ORM at 1024,
    tileable, plus an equirectangular IBL environment.
  - build-assets.mjs orchestrates both and writes a provenance manifest.
  - preview.py renders a hero shot per model, so assets can be reviewed
    (CLAUDE.md requires previewing and validating every asset).

Models: container, tank, deck, pipe_rack, wall, hardpoint, stair, lamp_mast,
character, carbine. 10 models (1.08 MB) + 22 textures (1.91 MB) = 3.0 MB,
against a 15 MB shell budget.

Integration keeps the existing invariant that what you see is what you
collide with: props are tiled and scaled to fill the same collision volumes,
never the reverse.

Three fixes that were not cosmetic:

  - IBL is mandatory, not polish. A physically-based metal is lit almost
    entirely by what it reflects, so with no scene.environmentTexture every
    steel, rust and grating surface rendered pure black.
  - Babylon's default 4-lights-per-mesh cap silently dropped lamps depending
    on where you stood; raised to 6 now that all eleven masts are lit.
  - The glTF loader's __root__ node is scaled (1,1,-1) to convert
    right-handed glTF into Babylon's left-handed space, which pointed the
    carbine's barrel back at the player. The viewmodel corrects for it.

Also: the PWA runtime cache matched .glb but not .webp, so an offline launch
would have loaded untextured models.

Weapon viewmodel is excluded from photo mode — the vantages are environment
showcases for the marketing site, and a rifle across the lower third hides
the yard they exist to show. Marketing captures regenerated from the new
scene.

apps/game/src/assets.test.ts guards the boundary between Blender and the
engine: a renamed material slot un-skins a mesh silently, and nothing else
would catch it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedplaywright@​1.62.01001001009980

View full report

@socket-security

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
License policy violation: npm playwright-core under ms-azure-data-studio

License: ms-azure-data-studio - The applicable license policy does not permit this license (5) (package/ThirdPartyNotices.txt)

From: pnpm-lock.yamlnpm/playwright@1.62.0npm/playwright-core@1.62.0

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/playwright-core@1.62.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
License policy violation: npm playwright under ms-azure-data-studio

License: ms-azure-data-studio - The applicable license policy does not permit this license (5) (package/ThirdPartyNotices.txt)

From: package.jsonnpm/playwright@1.62.0

ℹ Read more on: This package | This alert | What is a license policy violation?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Find a package that does not violate your license policy or adjust your policy to allow this package's license.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/playwright@1.62.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@ralyodio
ralyodio merged commit 8e645e6 into main Jul 26, 2026
6 checks passed
@ralyodio
ralyodio deleted the feat/generated-art-set branch July 26, 2026 09:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

need assets

1 participant