Three.js LDraw Viewer
Sixteen LDraw brick models rendered by Three.js and its LDrawLoader, with an Adwaita sidebar that picks the model and walks it through its building instructions one step at a time.
This is the showcase where the scene arrives from disk rather than from code. LDrawLoader fetches a packed .mpd file, reads it through Response.body, and turns roughly 250 KB of LDraw commands into 62 meshes and 124 line objects before the first frame. If your app loads its data at runtime instead of bundling it, this is the one to read.
Ported from the upstream webgl_loader_ldraw example.
Live demo
Section titled “Live demo”Run it
Section titled “Run it”This showcase declares all four runtimes, so pick the one you already have:
gjsify showcase three-loader-ldraw --runtime gjsgjsify showcase three-loader-ldraw --runtime nodegjsify showcase three-loader-ldraw --runtime bungjsify showcase three-loader-ldraw --runtime denoA GTK 4 window opens with an Adwaita sidebar next to the canvas. Drag to orbit, scroll to zoom. Same window and same models on all four.
- Model picks one of the sixteen models, from a car to a UCS AT-ST.
- Rendering toggles Flat Colors, Merge Model and Smooth Normals.
- Display steps through Building Step, and toggles the two edge layers
LDrawLoaderbuilds alongside the geometry: Display Lines and Conditional Lines.
Under gjs this runs the --app gjs bundle against GJS’s native gi://. Under node, bun and deno it runs one shared --app node bundle, where gi:// goes through the node-gi bridge. Choose the runtime covers what the CLI does when you leave the flag off.
Run it in the browser
Section titled “Run it in the browser”import { mount } from '@gjsify/example-dom-three-loader-ldraw/browser';
const handle = mount(document.getElementById('app')!, { assetBase: '/demos/ldraw/', // where the .mpd models are served from});
handle.pause();handle.resume();The models ship with the package under ./assets/*, so point assetBase at wherever you copied them.
What it uses
Section titled “What it uses”| Package | What Three.js needs it for |
|---|---|
@gjsify/fetch | fetch over file://, Request, Headers, AbortSignal.any, and a Response.body the loader can re-wrap |
@gjsify/web-streams | ReadableStream, so the loader can report download progress |
@gjsify/dom-events | ProgressEvent, dispatched per chunk while a model downloads |
@gjsify/webgl | The full WebGL 2.0 surface, including drawElementsInstanced and sized internal formats |
@gjsify/dom-elements | HTMLCanvasElement and requestAnimationFrame |
@gjsify/adwaita-web | The sidebar in the browser build |
| Libadwaita | Adw.ComboRow, Adw.SwitchRow and Adw.SpinRow in the GTK build |
Copy the structure
Section titled “Copy the structure”showcases/dom/three-loader-ldraw/
src/three-demo.tsis the scene plus the LDraw loading, with no platform imports.src/models.tsis the model catalog, exported so both shells build the same dropdown.src/gjs/gjs.ts,ldraw-window.tsandldraw-window.blpare theAdw.Application, the window class and its Blueprint UI.src/browser/browser.tsexportsmount();browser-main.tsruns it full-page.src/assets/models/ldraw/officialLibrary/holds the packed models, from the LDraw Parts Library under CC BY 2.0.
Related
Section titled “Related”three-geometry-teapotis the simpler Three.js scene, built entirely in code.three-postprocessing-pixeladds a multi-pass post-processing chain.- Bridge widgets covers the
WebGLBridgelifecycle.