Skip to content

feat(constellarium): rebuild on pixi + d3-force — Obsidian's actual mechanics - #147

Merged
vicquick merged 1 commit into
mainfrom
feat/constellarium-obsidian
Aug 21, 2026
Merged

feat(constellarium): rebuild on pixi + d3-force — Obsidian's actual mechanics#147
vicquick merged 1 commit into
mainfrom
feat/constellarium-obsidian

Conversation

@vicquick

Copy link
Copy Markdown
Owner

Why cosmos.gl could never feel like Obsidian

The feel isn't a parameter. It's d3-force's velocity-Verlet settle plus a handful of very specific interaction behaviours, and cosmos.gl runs its own shader integrator. Tuning was never going to converge.

Research (stored in nobrainr, tags: research/obsidian-graph)

Obsidian core is closed, but the canonical open replica — Quartz v4 graph.inline.ts — uses pixi.js + d3-force and its mechanics are readable. Cross-checked against Obsidian's official Help (sliders, filters, groups) and the plugin ecosystem (Pixi.js WebGL mirrors the core's stack).

The mechanics, implemented verbatim

behaviour implementation
charge forceManyBody().strength(-100 * repelForce), repel 0.5
center forceCenter().strength(0.3)
link forceLink().distance(30) + strength slider
collide forceCollide(nodeRadius)
node radius 2 + √degree
hover non-neighbour nodes AND links tween → α0.2 over 200ms; hovered label pops α1 at 1.1× over 100ms
label fade α = max((k·opacityScale − 1)/3.75, 0) — the exact zoom law
drag alphaTarget(1) reheat on grab; fx = init + Δ/k; release un-pins, node re-floats

Plus Obsidian's four force sliders live on the running sim + text-fade slider — "behaves like Obsidian" made literal.

Deliberate deviations (documented inline)

  • radius capped at 14 — our hubs reach degree 500+, no vault sees that
  • labels: top-400 by degree + materialised on hover, not 5k pixi Texts — faint labels are zoom-faded to zero anyway
  • deep tier 12k → 5k — d3-force is CPU, Obsidian itself slows there, and the feel is the point. The GPU full sky remains at /galaxy.

Kept

Manuscript chrome, tier picker, seek, folio, the curated 12-hue warm palette, community-bearing seeding.

Bundle 570kB → 360kB. Build passes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GobDsDKP6FE5hr747DPtcC

…echanics

The old Constellarium ran cosmos.gl, a GPU particle simulator with its own
shader integrator. It could show 12k points, but no parameter tuning could
make it feel like Obsidian, because the feel is not a parameter: it is
d3-force's velocity-Verlet settle plus a handful of very specific
interaction behaviours. Researched against the canonical open replica
(Quartz v4 graph.inline.ts — pixi.js + d3-force, the same stack Obsidian
itself credits) and implemented its mechanics verbatim:

  charge  = forceManyBody().strength(-100 * repelForce)   [repel 0.5]
  center  = forceCenter().strength(centerForce)           [0.3]
  link    = forceLink().distance(linkDistance)            [30]
  collide = forceCollide(nodeRadius)
  radius  = 2 + sqrt(degree)
  hover   → non-neighbour nodes AND links tween to α0.2 over 200ms;
            hovered label pops to α1 at 1.1x over 100ms
  label   → α = max((k · opacityScale − 1) / 3.75, 0)  — the zoom fade law
  drag    → alphaTarget(1) reheat on grab; fx delta divided by zoom k;
            release un-pins so the node re-floats

Plus the four Obsidian force sliders (center / repel / link force / link
distance) live on the running simulation, and a text-fade slider — the
"behaves like Obsidian" ask made literal.

Deviations, each deliberate and documented inline:
- node radius capped at 14: our hub entities reach degree 500+, which no
  vault sees — uncapped they render as plates
- labels materialised for the top 400 by degree + on hover, not all 5k:
  Obsidian-scale vaults are hundreds of notes; faint stars' labels are
  zoom-faded to zero anyway, so this is visually indistinguishable
- deep tier 12k -> 5k: d3-force is CPU; Obsidian itself slows at that
  scale, and the feel matters more here than raw count. The GPU full sky
  still exists at /galaxy.

Kept: manuscript chrome, tier picker, seek, folio panel, the curated
12-hue warm community palette, community-bearing seeding.

Bundle 570kB -> 360kB (cosmos + webgl-device out, pixi + d3 in).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GobDsDKP6FE5hr747DPtcC
@vicquick
vicquick enabled auto-merge (squash) August 21, 2026 21:28
@vicquick
vicquick merged commit 4041b00 into main Aug 21, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant