Hi all — we build Like Art, a marketplace where independent artists sell handmade art dolls. Over the last months we turned that catalogue into a browser 3D world: every physical doll gets reconstructed as a rigged GLB avatar you can walk around with, in a shared, streamed scene.
What it looks like: you pick a doll, it becomes your character, and you wander a cozy village/garden world with other dolls. Built with three.js + a small Node service.
Pipeline notes that may be useful to others here:
- Rigging is the bottleneck, not modelling. Our rig target is a 26-bone skeleton with 6 clips (idle / walk / run / sit / wave / dance). Automated rigging services only handled bipeds properly, so quadruped dolls are parked rather than shipped half-rigged.
- Reconstruction must be checked against the source photo, not just “does it look nice”: silhouette overlap, dominant-color distance (we gate on ΔE ≤ 5), and “is it recognisably the same doll”. Anything that drifted got rejected and rebuilt.
- Scale/grounding is a per-frame invariant. Height 1.500 m ±3 mm, root scale exactly 1.0, minY = 0 — checked on every animation frame, not only in the rest pose. Skinned meshes drift out of tolerance surprisingly often mid-clip.
- Textures: resize to 2048 before WebP conversion. A single doll went from 47 MB to a few MB with no visible loss at our viewing distance, and it fixed the “preview never loads” class of bugs.
- Streaming: world is split into chunks; we prefetch neighbouring areas during idle so players don’t watch objects pop in. On mobile we ship a pre-bundled asset pack inside the app shell and intercept those requests in the WebView instead of hitting the network.
Happy to go deeper on any of it (rigging QA, chunk streaming, or the asset budget work). If you want to poke at it, the world entry is here — it’s free and runs in the browser:
Feedback very welcome, especially on load time / frame-rate on mid-range Android.