Skip to content
ThreeDream

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.

A UE 5.5 level walked in the browser, level manifest in the sidebar

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

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

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

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

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

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

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

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.html

Physics: 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 tab

The 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

metricfloor %measured %
statements9398.7
branches8293.5
functions9398.9
lines9499.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.