Skip to content

feat(playset): scene3d surface + GameBlocks port + native wgpu core — rally renders#85

Draft
doodlewind wants to merge 8 commits into
mainfrom
feat/playset
Draft

feat(playset): scene3d surface + GameBlocks port + native wgpu core — rally renders#85
doodlewind wants to merge 8 commits into
mainfrom
feat/playset

Conversation

@doodlewind

@doodlewind doodlewind commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

What

Playset — Three.js mini-games (GameBlocks-class) running on Pocket, end to end: framework, native rendering on desktop wgpu AND PSP GE, and the first four games.

rally desktop

Same bundle on the PSP host under PPSSPP: RMSE 5.4% vs the desktop frame. Wave-1 ports: runner · dogfight · snake

Layers

  1. scene3d surface (playset/scene3d/) — closed write-only 3D presentation vocabulary (the 3D sibling of ui): batched writePoses, primitives/heightfield/mesh, vertex-lit fixed-function-honest materials, sun/hemisphere/fog/sky, sprite & beam pools, bindViewport per the <Video> precedent. TS client + <Viewport3D> + renderless sim host for goldens.
  2. playset/modules/ — all 74 GameBlocks modules (MIT, attributed) + 3 natives (deterministic CollisionWorld replacing Rapier, blob-shadow, color-utils). Copy-into-project source per SKILL.md (with the Three.js → playset mapping table).
  3. Native coresPROP.scene3d + DRAW_OP.sceneQuad through spec/core (all four DrawList consumers; graceful absence, zero golden drift). Desktop: pocket3d/crates/pocket-scene3d (retained store + rquickjs s3 mount + wgpu vertex-lit renderer), composited in uihost. PSP: the store goes no_std behind a feature gate (one semantics, two hosts — the pocket3d-bsp pattern) with native/src/{scene3d,ge3d}.rs: QuickJS C-API mount, GE hardware sun + hemisphere-average ambient, sceGuFog, depth-only clear, additive pools, 2D-clean exit. Always-on perf probe (avg_js_us per 300 frames) answers the 333 MHz QuickJS question on hardware: bun run hw rally -r.
  4. Gamesdemos/rally (original composition) + wave-1 ports demos/runner, demos/dogfight (17 modules as-is; FlightHud + radar in action), demos/snake (A*/flood-fill AI rival). Each: fixed-step deterministic sim, two-boot byte-identical goldens, exact 30↔60 Hz subsampling, no-s3 degradation, uihost screenshots in-repo.

Validation

  • 365 bun tests / 5,879 assertions green (bun run test builds all five game bundles); tsc --noEmit clean; 12 pocket-scene3d cargo tests; no_std build clean; clippy clean
  • PSP: all 23 ui e2e goldens byte-exact under PPSSPP, tape:check 180 frames, rally renders at RMSE 5.4%/5.3% vs desktop refs
  • Desktop hero-main screenshot: pixel-identical (2D path inert)

Follow-ups

  • Wave-2 ports (shooters/defense ×6), wave-3 (vehicles/water/marble/arm), voxel-survival last (needs a voxel-world module)
  • Playset gap backlog from wave-1: instanced-geometry verb, pooled-entity helper, edge-triggered input in GameInput, flight-pursuit behavior module, per-target hit radii on projectiles, default font slot for unclassed Text (systemic), point-light verb, frameBounds camera solver, BoardEnvironment rim option, exp fog
  • Rust hot-path blocks behind the batch seams; mid-DrawList compositing (v1: scene under all ui); ramp wedge collision; textured materials; pocket port funnel skill
  • Hardware perf spike: bun run hw rally -r on the real PSP (PSPLINK console prints the probe)

🤖 Generated with Claude Code

doodlewind and others added 6 commits July 11, 2026 07:41
…, foundation modules

- scene3d: closed write-only presentation vocabulary (ops.ts), retained
  guest mirror with batched pose flush (client.ts), renderless sim host
  with canonical serialization for goldens (sim.ts), <Viewport3D>
- playset/math: clean-room three@0.161-compatible math subset
- modules/math: WorldBasis, Vector3Utils, Scalar/Random/TimeUtils ports
  (Clock defaults to the virtual clock, never Date.now)
- modules/physics: deterministic CollisionWorld (capsule resolve,
  raycasts, walkable tops) — the injected-Rapier replacement seam
- loop.ts: fixed 1/60 game loop, hz-invariant via ticksPerFrame catch-up

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
actor-motion (18), behavior (6), camera (5), gameplay (8), math (5),
user-interface (8), world (24) — kebab-case files, PascalCase exports,
verbatim semantics with per-file deviation notes and MIT attribution.

Reengineered seams (documented in headers):
- KinematicBatchResolver + DynamicCarBatchResolver run on the
  deterministic CollisionWorld (Rapier replaced; dynamic car is a
  kinematic raycast-vehicle approximation pending the native block)
- AimResolver picks via CollisionWorld.raycast + Camera3D.rayFromNdc
- visual factories/effects build SceneNode trees; JetFlame shader ->
  additive cones; tire marks/tracers -> beam pools; shadows ->
  blob-shadow.ts decals
- DOM/Canvas2D HUD -> Solid components (radar/minimap as View trees)

243 new tests (344 total in playset/), all green; repo test script now
runs playset/test/.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- demos/rally: checkpoint-racing demo composing track environment,
  arcade car + AI rival (waypoint driver), kinematic resolver, chase
  camera, Viewport3D + HUD (lap/standings/minimap)
- playset/test/rally-sim.test.ts: host-sim goldens — byte-identical
  framebuffer + scene3d serialization across boots, 30/60 Hz exact
  subsampling relation, graceful no-s3 degradation
- summary.md (77-entry catalog), README.md, SKILL.md with the
  Three.js -> playset porting mapping table

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…kdrop

Core emits sceneQuad(xy, wh, handle) at a node's world AABB before its
background when the host has bound a scene3d scene (host-written prop,
never app code). All DrawList consumers skip it gracefully: wasm raster
and PSP GE draw nothing (graceful absence), pocket-ui-wgpu skips (the
3D-capable host composites from the same DrawList). No golden drift —
the prop is only ever set by hosts with a scene3d core.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…top host

New pocket3d/crates/pocket-scene3d: retained store implementing the
scene3d contract (sim.ts semantics: id lifecycle, silent dead-handle
ops, pool replace+clamp, heightfield tessellation with smooth normals),
rquickjs mount as globalThis.s3, and a wgpu renderer — per-scene pass
into the sceneQuad rect: gradient sky, per-vertex sun+hemisphere lit
meshes with linear fog (fixed-function honest), back-to-front
transparent/additive, camera-facing sprite pools + view-aligned beams.

pocket-ui-wgpu grows scene_quads() (DrawList walker) + UiSurface
set_prop passthrough. uihost mounts s3 before eval, bridges
bindViewport -> PROP.scene3d, composites scenes under the ui layer
(LoadOp::Load), adds --hold for scripted screenshot input. rally
verified visually at 480x272 (terrain/fog/cars/gates/HUD); hero-main
regression unchanged; 12 crate tests + full bun run test green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@doodlewind doodlewind changed the title feat(playset): scene3d surface + full GameBlocks module port + rally E2E feat(playset): scene3d surface + GameBlocks port + native wgpu core — rally renders Jul 11, 2026
doodlewind and others added 2 commits July 11, 2026 11:31
…he PSP host

pocket-scene3d store goes no_std+alloc behind a feature gate (desktop
keeps mount+wgpu under default 'std'; BTreeMap swap, fmath shim) so both
hosts share one semantics. native/ gains scene3d.rs (globalThis.s3 over
the QuickJS C API, bindViewport -> PROP.scene3d) and ge3d.rs (SCENE_QUAD
compositor: rect-scoped viewport/scissor, depth-only clear, gouraud sky
strip, GE hardware sun + hemisphere-average ambient, sceGuFog, additive
pools, 2D-clean exit state). Always-on perf probe logs avg_js_us every
300 frames for the 333MHz hardware spike (bun run hw rally -r).

PPSSPP-verified: rally f10/f240 at RMSE 5.4%/5.3% vs the desktop wgpu
references; all 23 PSP ui goldens byte-exact; tape:check 180 frames;
desktop uihost screenshot byte-identical after the store rework.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three ports following the rally pipeline (fixed-step sim, seeded PRNG,
Viewport3D + HUD, sim-host goldens, uihost screenshot verification):
- runner: 3-lane endless runner (jump/slide, coins/boost, difficulty
  ramp, snow sprite pool) — clean-room glue, numbers from the original
- dogfight: the flight+combat+UI showcase — 17 playset modules as-is,
  FlightHud + HeadingRelativeRadar in action, wave AI, missile lock,
  terrain crash referee
- snake: 16x16 grid arena vs A*/flood-fill AI rival, cadence ramp

16 new sim tests (byte-identical two-boot traces, 30/60 Hz subsampling,
no-s3 degradation, gameplay probes); all bundles in the test chain.
Module adaptations: WeaponEffectsSystem gains tracerWidth/particleSize
options; FlightHud gets font classes + 480x272 layout fixes (unclassed
Text renders nothing on native hosts — systemic gap noted for core).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant