███╗ ███╗███████╗███████╗██╗ ██╗ ████╗ ████║██╔════╝██╔════╝██║ ██║ ██╔████╔██║█████╗ ███████╗███████║ ██║╚██╔╝██║██╔══╝ ╚════██║██╔══██║ ██║ ╚═╝ ██║███████╗███████║██║ ██║ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ O P T I M I S E R · v 0 . 8 . 0
Drop a STEP file in. Get a Meshopt-compressed GLB and an interactive viewer out. A self-hosted take on the Pixyz preprocessor. Python + your browser, no licence server.
CAD assemblies are big. A real-world STEP file might contain 400 identical bolts, 80 duplicate brackets, and half a million degenerate triangles, and still expect your GPU to render it.
The pipeline collapses what it can:
400 bolts × 50 KB → 1 mesh × 50 KB + 400 transforms
80 brackets × 12 KB → 1 mesh × 12 KB + 80 transforms
500K bad triangles → adaptive retess, size-culled
───────────────────────────────────────────────────────────
320 MB STEP → 11 MB Meshopt-compressed GLB
A CAD preprocessor, viewer, hierarchy editor, and exporter, in one local app.
- Pose-normalized instancing — PCA-based hashing detects duplicate geometry regardless of position or rotation. One GPU mesh, N transforms.
- Editable assembly tree — search, isolate, recolour, batch-rename, flatten, dissolve, ungroup. All undoable.
- Two renderers — WebGPU (default, with TSL nodes and
discardNodeclipping) and WebGL2. Hot-swap from the toolbar, no reload. - GPU section planes — real
discardNode-based clipping, not a placeholder mesh. - Resumable sessions — FS Access API + IndexedDB persist file handles across reloads. Saved scenes for view/selection/recolour state.
- Keyboard-first UX — command palette (⌘K), shortcuts overlay, batch rename (F2), context menus, undo/redo.
- No build step — vanilla JS, native ES modules, CSS design tokens. Edit a file, refresh, done.
- Non-destructive — original geometry is never mutated until you export.
| 🌳 XCAF reader | Per-solid colours, names, and the full assembly tree pulled straight out of OCCT |
| 🧬 PCA pose-normalized hash | Same shape at any rotation/translation → one GPU mesh + N transforms |
| 🔷 Adaptive tessellation | Absolute or relative to bbox diagonal · size culling for the tiny stuff |
| 📦 Meshopt + Draco | Optional EXT_meshopt_compression via gltfpack — ~10× smaller GLBs |
| ⚡ One-click launch | start.bat / start.command bootstraps the venv and opens the browser |
| 🔁 Background jobs | Long conversions run as server jobs with live progress streamed to the UI |
| 🌐 Dual renderer | WebGPU (default) with hot-swap to WebGL2 — pick from the toolbar |
| 🔪 Section / Clip planes | Live cross-section via TSL discardNode — true GPU clipping, not fake plane meshes |
| 💡 PBR + AO + envmap | Studio lighting, ambient occlusion, screen-space reflections, fog |
| 🎯 Pixel-perfect picking | Hover, click, marquee-select; works on instanced meshes |
| 👁 Hide / Isolate / Solo | One key per mode — flatten the noise, focus on what matters |
| 🎨 Recolor by group | Per-instance and per-material recolouring with reset baked-in |
| 📐 Wireframe / Shaded / Matcap | Three viewport modes, switchable mid-flight |
| 📊 FPS pill | Tabular-numeric FPS readout, colour-coded for stutter detection |
| 🌳 Live tree | 10 K+ nodes, virtualized, sticky right column, content-visibility tuned |
| 🔎 Search + filters | Fuzzy name search, "highlight small parts" tinting |
| ✂️ Flatten / Dissolve | Collapse single-child chains, dissolve groups, ungroup scopes — all undoable |
| ✏️ Batch rename (F2) | Token templates ({name}, {idx}, {depth}) + regex find/replace + presets |
| 🔄 Undo / Redo | Tree edits, recolours, renames, flattens — all on a single timeline |
| 📌 Right-click menu | Hide / isolate / recolour / rename / focus camera, all in one click |
| 📦 GLB / GLTF | Draco + Meshopt compression toggles, optional embedded textures |
| 🎬 FBX / USDZ / OBJ / STL | Common DCC + AR formats, scale presets (mm/cm/m/in) or custom |
| 🧷 Save Scene | Snapshot view + selection + recolours into a sidecar .scene.json |
| 👋 Welcome modal | Drag-drop, browse, recent files (IndexedDB-persisted handles) |
| ⌘ Command palette (⌘K) | Searchable action registry — every menu item, one keystroke away |
| ⌨️ Shortcuts overlay | Discoverable cheatsheet with live key bindings |
| ⚙️ Settings modal | Persistent prefs (renderer, perf mode, background, toggles) |
| 🎨 Design-token system | Centralised CSS variables — surfaces, radii, type scale, easings |
| 📋 Copy log / Cancel load | Every long operation is observable and abortable |
┌──────────────┐ ┌────────────────────┐ ┌────────────────┐
│ .step / .stp│ ─▶ │ step2glb.py (OCCT) │ ─▶ │ .glb (Draco) │
└──────────────┘ │ • XCAF tree │ └────────┬───────┘
│ • PCA instancing │ │
│ • Tessellation │ ▼
│ • gltfpack/Meshopt │ ┌────────────────┐
└────────────────────┘ │ WebGPU viewer │
│ index.html │
└────────────────┘
cadquery-ocp · trimesh · numpy · Draco · Assimp (WASM) · WebGPU · vanilla JS
No framework. No bundler. No npm install. Just open and run.
# Windows
start.bat
# macOS
./start.commandFirst run bootstraps
.venv, pulls deps, opens the viewer. Subsequent runs are ~1 second.
python step2glb.py input.step
python step2glb.py input.step --quality 0.2 --min-size 0.5
python step2glb.py input.step --no-instance # disable instancing
python step2glb.py input.step --meshopt # shell out to gltfpack
python step2glb.py input.step --relative # quality as fraction of diag- 🐍 Python 3.10 / 3.11 / 3.12 (3.13 blocked on cadquery-ocp)
- 🌐 A WebGPU-capable browser (recent Chrome, Edge, Firefox, Safari)
- 💾 ~2 GB free for the venv on first install
step2glb.py STEP → GLB converter (OCCT + instancing)
serve.py local HTTP server + /api/convert endpoint
index.html WebGPU viewer shell
app-v2.js viewer logic (scene graph, picking, colour groups)
vendor/
├── draco/ Draco encoder + decoder (WASM)
└── assimp/ Assimp.js (WASM)
fbx_*.py FBX inspection / diff utilities
start.{bat,command} one-click launchers
step2glb.{bat,command} headless converters
🪟 "python is not on PATH" on Windows
Re-run the Python installer and tick
Add Python to PATH, or close + reopen your terminal so the new PATH is picked up.
🍎 "Operation not permitted" on macOS
Right-click
start.command → Open. Gatekeeper blocks double-clicking freshly-unzipped scripts the first time.
📦 "ModuleNotFoundError: cadquery"
Delete
.venv/ and re-run start.bat / start.command to rebuild from scratch.
v0.8.0 — the plumbing feels modern: an industry-standard ray-marched floor grid (no plane mesh, no Z-fight), a unified keycap chip across every shortcut surface, the undo system rebuilt as a flat command registry, and all runtime-injected CSS lifted into the stylesheet.
Ray-marched ground grid — fullscreen NDC quad, eye-ray + plane intersect, analytic depth write. No vertex precision loss at distance, no sub-pixel jitter under orbit, no coplanar Z-fight.
Redesigned Shortcuts modal — sticky search input, category headers with lucide icons, 2-column grid, multi-key combos rendered as separate keycap chips joined by
+. Opens via?..kbd-chipshared primitive — single class on the hint strip, tooltips, command palette, brand menu, Shortcuts modal — consistent combo splitting everywhere.Smart fit + caret merged + Smart-fit popover sliders now use the same
.scrub-rangestyle as the sidebar's Threshold scrubber.Big internal cleanups — 8 runtime
<style>injections (~490 lines) lifted intoindex.html; undo monkey-patches (11 of them) collapsed into a single_UndoOpsregistry covering 21 op types; renderer + popover dismissal helpers extracted.Tree summary stuck at "1 parts in hierarchy" after delete · stranded group origin dot after deleting all members · group-selection button popping a name dialog · path tracer error spam on empty scene · materials panel duplicate / add / merge each had their own confusing toast or selection requirement.
Pre-1.0 — breaking changes expected. The CLI flags, in-app APIs, and on-disk formats may shift between minor versions.
v1.0.0will mark the first commitment to backward compatibility.
Earlier
- v0.7.0 — GPU path tracer aperture button + sample-accumulating modal, contextual hint strip, long-hold add-primitive picker, standalone Cloner you can drag parts into, Revert-to-source escape hatch.
- v0.6.0 — C4D-style live Cloner, Ctrl-click measure tool, per-group origin markers, Spline-style two-panel Export modal,
--simplify+ meshopt-by-default pipeline, CAD-correct mouse mapping. - v0.5.0 — scene management (New scene, Import-merge, Scene settings modal), parametric-primitive polish with editable mm-snapped inputs, unit-aware transforms, banding-free dithered backgrounds,
/api/quitclean shutdown. - v0.4.0 — HDRI environment lighting, infinite floor grid + fog, parametric primitive insertion, top-center camera-view pill with
Ctrl/⌘+1..4, borderless popup language, IBM-blue accent refresh. - v0.3.0 — full material editor with shader-ball previews, scale gizmo + Shift-snap + live HUD, screenshot capture with custom resolutions, ortho Top/Front/Side viewport toggles, FBX legacy rescue.
MIT. Do whatever — just don't blame me when your assembly tessellates into a black hole.
✦ ✦ ✦
Built for engineers who want their CAD to load before their coffee. ☕