Skip to content

Commit 239e754

Browse files
montfortclaude
andauthored
feat(loom): loom-0.6.0 — A3: axonometric/BIM exploded view (Three.js 3D) (#268)
The Spec 002 north star — a second projection of the same architecture model in real 3D. A 2D|3D toggle in the Architecture tab swaps the maxGraph plan for a Three.js axonometric scene: each layer a stacked translucent floor, each component a box colored by the shared "you are here" status, dependency edges as lines. Explode slider peels the floors apart (BIM exploded view); CSS2DRenderer labels (layer + component); raycast click reuses the A2.4 detail panel; hover highlight. One model, many views — CLI authors structure, Loom renders 2D + 3D, status is always the one core::architecture::project projection. Closes A3 / Spec 002 fully realized. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 6ad22fb commit 239e754

9 files changed

Lines changed: 172 additions & 81 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

experimento/CHANGELOG.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,34 @@ project adheres to [Semantic Versioning](https://semver.org/).
1212
1313
## [Unreleased]
1414

15-
### Planned — Architecture Plan view (Spec 002)
16-
- A3 (north star): axonometric/BIM exploded-layers view.
15+
## [0.6.0] — 2026-06-16 (Axonometric / BIM exploded view — A3)
16+
17+
The Spec 002 **north star**: a second projection of the same architecture model in real 3D. A
18+
`2D | 3D` toggle inside the Architecture tab swaps the maxGraph plan for a **Three.js**
19+
axonometric scene — each layer a stacked, translucent "floor", each component a box colored by
20+
the same §4 "you are here" status palette, dependency edges drawn as lines between boxes. This
21+
fully realizes Spec 002 (BIM "one model, many views"): the CLI authors structure
22+
(`architecture generate|sync|validate`), Loom renders it as both a 2D plan and a 3D exploded
23+
model, and the status overlay is always the one shared `core::architecture::project` projection.
24+
25+
### Added (A3)
26+
- **Axonometric 3D view** (`web/src/axon.ts`): orthographic camera (true axonometric) +
27+
`OrbitControls` (rotate/zoom/pan). Layers auto-laid-out per floor — the 3D view doesn't need
28+
the human DrawIO geometry; it reads `/api/architecture`. `active` components glow (emissive);
29+
every box gets crisp edge outlines. Leaving the view / switching mode `dispose()`s the GL
30+
context (geometries, materials, renderers, listeners).
31+
- **Explode slider** (`#axon-explode`, localized): peels the floors apart on `y`
32+
(`MIN_FLOOR_GAP..MAX_FLOOR_GAP`); dependency lines re-route to the boxes' new world positions
33+
on every change — the BIM exploded view.
34+
- **Labels** via `CSS2DRenderer` (crisp HTML over the WebGL canvas): layer name per floor +
35+
component name per box.
36+
- **Interaction**: raycast a no-drag click → the **shared** A2.4 component detail panel
37+
(`showDetail` reused across the 2D plan and 3D view); hover highlights the box under the
38+
pointer. The "where are we" + legend panels are shared with the 2D plan untouched.
39+
40+
### Notes
41+
- Bundle grows ~600 KB (Three.js) — accepted for the experimental visual; the KG and 2D plan
42+
paths are unaffected.
1743

1844
## [0.5.0] — 2026-06-16 (Architecture Plan view — A2)
1945

experimento/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "straymark-loom"
3-
version = "0.5.0"
3+
version = "0.6.0"
44
edition = "2021"
55
description = "Loom — StrayMark's experimental knowledge-graph visualization server (localhost development dashboard)"
66
license = "MIT"

experimento/specs/002-architecture-plan/tasks.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,15 @@
354354
explode change the lines are re-routed to the boxes' new world positions
355355
(`getWorldPosition` after `updateMatrixWorld`). Verified on Sentinel (7 floors separate, the
356356
dependency lines stretch across the gaps). `tsc` + `vite build` clean.
357-
- [ ] **A3.2 — Interaction & labels.** Floor labels (layer names) + component labels (sprites),
358-
click a box → the A2.4 component detail panel, hover highlight. Reuse the where/legend panels.
359-
- [ ] **A3.3 — Acceptance + release.** Dogfood; `experimento/CHANGELOG.md` + bump
360-
`experimento/Cargo.toml` + `web/package.json`; PR → merge → tag **`loom-0.6.0`**. Update the
361-
Loom memory note (A3 shipped — Spec 002 fully realized).
357+
- [x] **A3.2 — Interaction & labels.** Floor labels (layer names) + component labels via
358+
**`CSS2DRenderer`** (crisp HTML overlaid on the WebGL canvas, `pointer-events:none` so orbit/pick
359+
fall through) — `.axon-floor-label` off each slab's left edge, `.axon-label` above each box.
360+
**Raycasting** (`THREE.Raycaster` against the box meshes): a no-drag pointerup → `pick()`
361+
the **shared** A2.4 `showDetail()` (now `export`ed from `plan.ts`, reused by both projections);
362+
pointermove → `setHover()` bumps the hovered box's `emissiveIntensity` (restored from a
363+
per-box `baseEmissive`) + `cursor:pointer`. Reuses the where/legend panels untouched. Verified
364+
on Sentinel (7 floor labels + 13 component labels; click `db` → Database detail with 16 charters
365+
+ 41 owned files). `tsc` + `vite build` clean.
366+
- [x] **A3.3 — Acceptance + release.** Dogfooded on Sentinel; `experimento/CHANGELOG.md` `[0.6.0]`
367+
+ bump `experimento/Cargo.toml` + `web/package.json` to 0.6.0; PR → merge → tag **`loom-0.6.0`**.
368+
Loom memory note updated (A3 shipped — Spec 002 fully realized).

experimento/web/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@
9898
/* A3 — axonometric (3D) view, a second projection of the same model */
9999
#axon { position:absolute; inset:0; z-index:0; display:none; background:var(--bg); cursor:grab; }
100100
#axon .plan-empty { position:absolute; inset:0; display:flex; align-items:center; justify-content:center; color:var(--muted); font-size:13px; text-align:center; padding:0 40px; }
101+
/* CSS2D labels drawn over the WebGL canvas (A3.2) */
102+
.axon-label { color:#cdd2dc; font:11px var(--font, system-ui), sans-serif; pointer-events:none; white-space:nowrap; text-shadow:0 1px 3px #000, 0 0 2px #000; }
103+
.axon-floor-label { color:#8b91a0; font:600 11px var(--font, system-ui), sans-serif; pointer-events:none; white-space:nowrap; text-transform:uppercase; letter-spacing:.06em; text-shadow:0 1px 3px #000; }
101104
body.view-plan.plan-3d #axon { display:block; }
102105
body.view-plan.plan-3d #plan, body.view-plan.plan-3d #plan-zoom { display:none !important; }
103106
#plan-mode { display:none; gap:2px; margin-left:6px; }

experimento/web/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

experimento/web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "straymark-loom-web",
33
"private": true,
4-
"version": "0.5.0",
4+
"version": "0.6.0",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

0 commit comments

Comments
 (0)