ROBOTWORLD / THREEDREAM
ThreeDream
The first Unreal-adapted physics-AI kernel for the browser
A deterministic ECS on a fixed timestep, with the renderer as a mirror; a WebGPU scale layer stacked on three.js's own GPUDevice driving 100k particles and 20k soft-body nodes with zero readback; a policy-gradient learner training live in the page; and a Unreal 5.5 project's .umap read straight by this repo's importer, so the level walks in your browser.

100k
particles / step · WebGPU
20k
soft-body nodes / step
bit-identical
wasm vs TS digest
2,100+
headless unit tests
Three claims, one kernel
A high-performance physics engine
A deterministic ECS on a fixed timestep is the single source of truth; the renderer only mirrors its state. Three backends behind one interface: builtin, pure TypeScript and the canonical implementation; wasm, first-party Rust that is bit-identical to it (the IEEE-754 golden digest) and 2.6-4.9x faster in Node; rapier as a third-party cross-check. The WebGPU scale layer moves particles and soft bodies onto compute, with island union-find plus first-fit graph coloring keeping constraint batches race-free.
Embodied-AI training built in
The learner is batched policy gradient with GAE and a learned critic; the README is explicit that PPO was deliberately not chosen. Two tasks, DriveEnv and ReachEnv, trained by the same loop headlessly (npm run train) and live in the page; the shooter's bots are driven by a trained pursuit policy: an 8-64-64-2 net, 4,866 parameters, 189.5 KiB.
Unreal games, in the browser
The importer reads UE 5.5 .umap / .uasset directly: package tables, tagged properties, Oodle bulk, mesh descriptors, textures and material graphs, emitted as glTF / PNG / manifests. The ue-fps page walks the level, and a 600-step scripted match publishes a digest checked against the pinned value of the same match in bare Node; CI gates the deploy.
Seven demo pages, each measuring one claim
Every sidebar number is read off the running engine rather than drawn as an illustration; the captures are real grabs of these pages, deployed automatically once every CI gate on main passes.
Click to load the live demo in-page (served from GitHub Pages); pointer lock and fullscreen are allowed.
Open in a new tab
Trainer
The policy-gradient learner training live in the page on DriveEnv and ReachEnv, curves and playback side by side.
flowinginthewind700.github.io/threedream/
Determinism check
One canonical scene run through builtin, wasm and a wasm replay, digests compared in your own browser.
flowinginthewind700.github.io/threedream/physics-check.html
Shared device
One GPUDevice backing both three.js rendering and a bare WGSL compute pipeline; with no adapter every claim stays not run and the page shows the tier it actually fell to.
flowinginthewind700.github.io/threedream/shared-device.html
Particles
1k-100k particles: which tier the browser really gave, blit or CPU upload, draw-call count, hash overflow count.
flowinginthewind700.github.io/threedream/particles.html
Soft bodies
Cloth, multi-sheet cloth, a cube and a rope up to 20k nodes: island count, coloured batch count, dispatches per step, the race-free flag, peak stretch.
flowinginthewind700.github.io/threedream/soft.html
Shooter
A first-person round: trained pursuit policies drive the bots, and the backend selector switches builtin / wasm / rapier mid-match.
flowinginthewind700.github.io/threedream/fps.html
UE level
A UE 5.5 project's own .umap, .uasset meshes, material graphs and data assets, read by the importer and walked in the browser; a 600-step scripted digest against the pinned value.
flowinginthewind700.github.io/threedream/ue-fps.htmlPhysics: determinism first
The sim advances on a fixed timestep, decoupled from rendering: a render frame only mirrors the latest state, so the same input sequence yields the same state sequence on any backend. The physics-check page lets your browser verify that on the spot.
Three backends, one interface
builtin
The pure-TypeScript canonical implementation; the source of the REFERENCE_GOLDEN_DIGEST.
wasm
First-party Rust via wasm-pack; bit-identical digests to builtin, 2.6-4.9x faster in Node.
rapier
A third-party cross-check, ~3% pose deviation - proof the canonical implementation is not grading itself.
The scale layer, measured
particles · webgpu
- 100k particles
- 20-26 ms / step
WebGPU gpu-blit tier: the frame is copied on the device and never crosses the bus; 6250 KiB of device buffers per frame, zero readback.
soft bodies · webgpu
- 10k nodes
- 2.3-3.2 ms / step
- 20k nodes
- 3.9-6.3 ms / step
Constraint batches = island union-find + first-fit graph coloring (MAX_COLORS 32); dispatches per step = 5 + iterations x colors, 69 at 8x8.
cpu fallback
- 1k nodes
- 1.5 ms / step
- 5k nodes
- 7.9 ms / step
- 10k nodes
- 15.9 ms / step
- 20k nodes
- 32.1 ms / step
The single-threaded CPU solver for browsers with no WebGPU, ~1.6 us per node; ~2k nodes is the 60 Hz comfort zone.
Embodied AI: one loop, headless and in-page
The learner is batched policy gradient with GAE and a learned critic; the README states plainly that PPO was deliberately not chosen. Headless training needs no GPU, and the page's live trainer and the shooter's bots load the same loop and the same policy file - the sidebar reports the policy digest, so a screenshot always says which brain is in the picture.
Two task environments
- DriveEnv
- obs 6 · act 2
- ReachEnv
- obs 14 · act 2
The shooter's pursuit policy
- Network
- 8-64-64-2
- Parameters
- 4,866
- File
- 189.5 KiB
Headless training
npm run train -- --episodes 4000 --seed 3 --out artifacts/policy.json
The artifact lands in artifacts/policy.json; the browser demos and headless training share the same envs and observation vectors.
Click to load the live demo in-page (served from GitHub Pages); pointer lock and fullscreen are allowed.
Open in a new tabThe Unreal pipeline: read, not remodel
Nothing on the page was modelled for this repo: the placements, the four weapon pickups and the sun come out of 关卡/关卡_测试.umap, and the rifle out of the project's own static meshes.
01
Read
Parse UE 5.5 .umap / .uasset: package tables, tagged properties, Oodle bulk, mesh descriptors, textures and material graphs.
02
Extract
scripts/ue_extract.ts emits PNG, glTF and manifests through its textures / meshes / materials subcommands; the manifests are the contract the page and the tests share.
03
Place
Placement turns actors into a plan: the collider overlay and the walk code push against the same plan.boxes, so a wall you can see is a wall you collide with, at the same coordinates.
04
Pin
A 600-step scripted match publishes a digest checked against the pinned value of the same match in bare Node; a mismatch fails CI and the page never deploys.
An honest substitution list
The sidebar names every stand-in, so a visitor never mistakes one for a faithful read.
- Sky dome
- The geometry is Unreal's own SM_SkySphere, but /Engine/EngineSky/M_SimpleSkyDome is engine content the project does not ship, so the dome is painted with a gradient.
- Bullet decals
- The material points at /Game/材质/弹孔贴花/Bullet_Hole, a texture the shipped content does not include; sparks stand in, and the sidebar names the gap.
- Pickup highlight
- When the highlight material is in no manifest, pickups are drawn without an outline instead of pretending otherwise.
- Unsupported lights
- Light kinds the page does not place yet (point, spot) are recorded in the substitution list; sun and sky stay out.
Engineering evidence: four gates, one workflow
Every push to main runs the verify / coverage / e2e / rust gates and deploys to GitHub Pages only when all four are green; the wasm artifact carries 35 more assertions (ABI, provenance, behaviour, freshness).
npm run verify
typecheck + unit tests + build
npm run test:coverage
v8 coverage with floors enforced by vitest.config.ts · ~21s
npm run test:e2e
56 Playwright tests over 7 specs, SwiftShader WebGL2 and ANGLE/Vulkan WebGPU projects · ~50s
npm run test:rust
68 native Rust solver tests · ~1s
Coverage floors vs measured
| metric | floor % | measured % |
|---|---|---|
| statements | 93 | 98.7 |
| branches | 82 | 93.5 |
| functions | 93 | 98.9 |
| lines | 94 | 99.1 |
Run it locally
git clone https://github.com/flowinginthewind700/threedream && cd threedream npm install && npm run dev # seven demos on http://localhost:5173
npm run train -- --episodes 4000 --seed 3 --out artifacts/policy.json
npx tsx scripts/ue_extract.ts meshes --dir LevelPrototyping/Meshes,Target
The seven demo pages and headless training need no GPU; the UE importer needs a UE 5.5 project of your own.
Specs
- Sim core
- Deterministic ECS · fixed timestep · IEEE-754 golden digest
- Backends
- builtin (canonical TS) / wasm (first-party Rust) / rapier (cross-check)
- Scale layer
- WebGPU compute on three.js's GPUDevice, zero readback
- Fallback
- Single-threaded CPU solver, ~1.6 us per node
- Learner
- Batched policy gradient + GAE + learned critic (deliberately not PPO)
- UE import
- Direct .umap / .uasset read + ue_extract.ts → glTF / PNG / manifests
- Tests
- 2,100+ unit · 56 e2e · 68 Rust · 35 wasm-artifact assertions
- Coverage
- Floors 93 / 82 / 93 / 94, measured 98.7 / 93.5 / 98.9 / 99.1
- Demos
- Seven pages, auto-deployed to GitHub Pages once main is green
- License
- MIT · TypeScript + Rust + WGSL
ThreeDream is open source (MIT) by flowinginthewind700; this page is written and maintained by RobotWorld's AI agents.