Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

nodehammer

CI MIT license C++23 WebAssembly

Turn High-Energy Physics detector geometry into a scene you can actually fly through.


Detector geometries (ROOT/TGeo, DD4hep, GDML, GeoModel, …) are huge, deeply nested, and built for simulation — not for looking at. nodehammer converts them into a clean, semantically-tagged scene graph and renders it in real time with a physically-based pipeline, natively or straight in the browser.

   TGeo / DD4hep ── (GDML/Geant4, GeoModel: planned)
              │
              ▼
    Semantic scene graph (.nhb / .nhb.zst)
    nodes · shapes · materials · deduplicated transforms
              │
       ┌──────┴──────┐
       ▼             ▼
  glTF / OBJ    Render IR (NHR8, FlatBuffers)
                       │
                       ▼
              Interactive viewer
        native (Metal / GLCORE / D3D11) · web (WebGPU / GLES3, wasm)

Every stage is driven by declarative TOML config — keep_if/drop_if selection rules with a small predicate-expression language (tag.sensitive == "true" && any(path ~= "**/Pixels/**")), material remapping, and analytical boolean cuts — so you can go from "the whole detector" to "just the Pixel barrel" without touching code.

Status

nodehammer is under active, pre-1.0 development. Here's what's real today versus what's on the roadmap.

✅ Implemented

  • Importers: ROOT/TGeo and DD4hep, each independently switchable at build time (NODEHAMMER_WITH_TGEO, NODEHAMMER_WITH_DD4HEP).
  • Exporters: glTF/GLB and OBJ (render IR), plus the native .nhb/.nhb.zst FlatBuffers semantic-scene container — a documented, zstd-compressible on-disk format.
  • Analytical geometry surgery: semantic-level azimuthal wedge cuts and boolean operations via manifold, correct on non-manifold swept primitives, cooperative with UI progress.
  • CLI: convert, inspect, validate-config, config-flatten, dump-semantic, dump-render, viewer.
  • Viewer rendering pipeline, live today:
    • Full offscreen HDR pipeline with ACES / Reinhard / AgX tonemapping and exposure control
    • GTAO screen-space ambient occlusion, with selectable quality presets
    • Nishita single-scattering atmospheric sky (real Rayleigh + Mie, a real sun disc) baked into the IBL pipeline, plus a visible background dome
    • FXAA 3.11 console-quality antialiasing
    • Dynamic, GPU-load-adaptive render scale with a power-saving idle profile — renders on demand and caps the idle frame rate
    • Live ImPlot performance graphs in the debug panel
    • High-resolution, supersampled PNG screenshot export (nodehammer viewer --screenshot out.png ...) — verified on Metal; the WebGL2/GLES3 and WebGPU readback paths compile and link but are not yet verified in-browser
  • Builds on macOS, Linux, and Windows natively (Metal, GLCORE, and D3D11 respectively), plus a wasm build targeting both GLES3 and WebGPU from one configure, with the browser shell auto-picking the right bundle via navigator.gpu. All five configurations build and pass the (headless) test suite in CI. A headless compute-worker wasm module (nodehammer-compute) runs tessellation and boolean cuts off the main thread. macOS is the primary hand-verified target for the interactive viewer itself — see below for what's untested elsewhere.
  • Modern C++: C++23 throughout (<print>, the works); requires GCC ≥ 14, Clang ≥ 18/libc++, or MSVC ≥ 19.37.

🚧 Planned / in progress

  • GDML/Geant4 importer — CMake option and library wiring exist (NODEHAMMER_WITH_GEANT4); the actual importer isn't written yet.
  • GeoModel importer — CMake option declared only; no implementation.
  • Windows viewer verification — the D3D11 backend builds and passes CI's headless tests, but the maintainer has no Windows machine to manually verify interactive rendering; the PNG-export readback for D3D11 is a build-time #error stub for now.
  • Bloom and IBL-quality levels — UI controls exist and are wired through RenderQualitySettings, but both are no-ops for now.
  • Project save/export system — the archive-as-project model below is landing now (working set, IndexedDB persistence, sidecar viewer mode, layered steer, Publish package); in-viewer editor windows and a named multi-document switcher are still to come. See docs/viewer-project-strategy.md.
  • Single-instance enforcement + a real macOS .app bundle — designed, not implemented; see docs/viewer-single-instance.md.

Project model: the archive is the project

One ZipWorkingSet is both the thing you author (edit / curate / drop files into) and the thing you publish (serialize → host → share). Authoring and publishing are the same object flowing in two directions.

A nodehammer project is a .nhproj archive: a ZIP container holding the config, geometry, and materials for a scene, plus an optional root nodehammer.toml that makes it self-describing. The same archive opens natively, in the browser, and behind a published link.

Term Meaning
Working set the live, editable in-memory project (ZipWorkingSet) — what the viewer edits
Archive a serialized .nhproj of a working set — the portable, publishable unit
Project manifest root nodehammer.toml inside the archive: [project] entry keys + [view] initial steer
Sidecar nh_manifest.json next to index.html — points at archive(s), carries deployment presentation (lock, steer overrides)
Steer view-state (camera, angle cut, rotation, toggles) — the ephemeral per-link layer, committed to the URL query
Provenance Empty | Local(name) | Remote(url) — where the working set came from; drives persistence and posture
Package the self-contained static folder emitted by Publish — drop it on any static host, zero server code

The web build has two postures from one wasm binary, branched on whether a sidecar is present:

  • Application mode (no sidecar) — empty start, editable, native-like; the working set auto-persists to IndexedDB and restores on reload. Your document.
  • Viewer mode (sidecar present) — fetches the archive, content locked, re-fetched from source on reload. A publication.

Content-lock is a deployment property of the sidecar; steer is never frozen, so a shared link keeps camera and cuts live. The only viewer→app bridge is explicit: save the .nhproj and open it in application mode.

Full design of record, including backend mapping and mode transitions: docs/viewer-project-strategy.md.

CLI

nodehammer convert         # geometry → glTF / OBJ / render IR
nodehammer inspect         # explore a semantic scene
nodehammer validate-config # lint a TOML config before running it
nodehammer config-flatten  # resolve config includes/overrides
nodehammer dump-semantic   # dump the semantic scene as JSON
nodehammer dump-render     # dump the render IR as JSON
nodehammer viewer          # launch the interactive viewer

Running the executable with no arguments at all (e.g. double-clicking nodehammer.exe in a file manager) also launches the viewer, in builds with NODEHAMMER_WITH_VIEWER enabled.

Building

Dependencies are managed with Conan; builds with CMake + Ninja.

just recipes    # export vendored recipes (sokol-shdc)
just deps       # conan install (viewer=True)
just configure  # cmake --preset conan-relwithdebinfo
just build
just test

Or drive conan/cmake directly — see the Justfile for the exact flags, including the Emscripten/wasm targets (just wasm-deps, requires emsdk) and the spack-based dev configuration (configure-full) that turns on the TGeo and DD4hep importers together.

Key CMake options:

Option Purpose Status
NODEHAMMER_WITH_VIEWER Build the sokol/Dear ImGui interactive viewer
NODEHAMMER_WITH_TGEO ROOT/TGeo importer
NODEHAMMER_WITH_DD4HEP DD4hep importer
NODEHAMMER_WITH_GEANT4 GDML/Geant4 importer 🚧 links Geant4 only, no importer yet
NODEHAMMER_WITH_GEOMODEL GeoModel importer 🚧 declared only
NODEHAMMER_BUILD_TESTS Build the Catch2 unit-test binary
NODEHAMMER_BUILD_SHARED Also build and install libnodehammer + the public headers + a CMake package config 🚧 packaging works; the API it exposes is still being written

With NODEHAMMER_BUILD_SHARED=ON, cmake --install adds the shared library, include/nodehammer/, and a package config, so a consumer needs only:

find_package(nodehammer REQUIRED)
target_link_libraries(app PRIVATE nodehammer::nodehammer)

No find_dependency for zstd, flatbuffers, manifold or the rest — the shared library absorbs them. ci/shared-build.sh runs the whole thing end to end and, on ELF, checks that nothing third-party or internal escaped into the export table. CI runs it on every native platform.

A consumer needs only C++20. nodehammer itself is built as C++23, but the installed headers do not require it, and the exported target asks for no more than cxx_std_20. ci/shared_consumer compiles at exactly that floor, so a public header reaching past it fails there rather than in your build.

On Windows the library and its consumer must agree on the C runtime (/MD vs /MT) and on _ITERATOR_DEBUG_LEVEL — so a Debug consumer needs a Debug nodehammer. This is not specific to nodehammer; it is what passing std:: types across a DLL boundary requires, and mismatches usually surface as heap corruption rather than as a link error.

Try it

The repo ships a real detector fixture — the Open Data Detector — ready to convert:

just odd    # full ODD → glb (see the Justfile for single-stave recipes too)
build/RelWithDebInfo/nodehammer viewer

…in a browser

Every push to main publishes the wasm viewer to https://paulgessinger.github.io/nodehammer/, in both of the postures the web build supports:

/app/ the open application — empty start; drop a .nhproj or loose config/geometry files onto it
/odd/ the full Open Data Detector, preconfigured and content-locked
/odd-simple/ the simplified ODD — same, lighter to build

Each directory is a self-contained static package of the kind the viewer's Publish command emits. Reproduce the whole site locally with just pages-site after just wasm-release.

Project layout

src/           core pipeline: cli, config, ir (intermediate representation),
               scene building, tessellation, selection, the viewer, web glue
shaders/       sokol-shdc GLSL sources for the full render pipeline
schemas/       FlatBuffers schemas (render.fbs, semantic.fbs)
profiles/      Conan profiles (Emscripten cross-compilation)
recipes/       vendored/patched Conan recipes (sokol, sokol-shdc, imgui, implot, nfd)
fixtures/      sample detector geometries and configs
docs/          format specs and design docs (nhb format, predicate expressions,
               orbit navigation, rendering-fidelity strategy, PNG export)
web/           browser viewer entry point

License

MIT © Paul Gessinger — see LICENSE. Third-party license texts for vendored/bundled assets live under LICENSES/.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nodehammer-0.2.0rc3.tar.gz (1.1 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

nodehammer-0.2.0rc3-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (3.0 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

nodehammer-0.2.0rc3-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl (2.7 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.27+ ARM64manylinux: glibc 2.28+ ARM64

nodehammer-0.2.0rc3-cp312-abi3-macosx_13_0_arm64.whl (1.9 MB view details)

Uploaded CPython 3.12+macOS 13.0+ ARM64

File details

Details for the file nodehammer-0.2.0rc3.tar.gz.

File metadata

  • Download URL: nodehammer-0.2.0rc3.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for nodehammer-0.2.0rc3.tar.gz
Algorithm Hash digest
SHA256 985756d66dc33482aceefca75e8cae83202b74e9a4b6a88a7676f80ece6b8a0d
MD5 2c2fc00a5ab9d31745adf4452454387c
BLAKE2b-256 3027c27c2eaa86100e5df7295eb5a1e8f8a28a5a3390319d91104136567e3015

See more details on using hashes here.

Provenance

The following attestation bundles were made for nodehammer-0.2.0rc3.tar.gz:

Publisher: ci.yml on paulgessinger/nodehammer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nodehammer-0.2.0rc3-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for nodehammer-0.2.0rc3-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 4e18b3e15b036c5f86c446aecfe6a96032f7f07664b7c697eb006ca07733626c
MD5 09cd8a0590616f34653e94adc51ff952
BLAKE2b-256 2102cbc0223582f97ad0d353d913c176404a08b0a98f2e8fa5725f03b316feb1

See more details on using hashes here.

Provenance

The following attestation bundles were made for nodehammer-0.2.0rc3-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: ci.yml on paulgessinger/nodehammer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nodehammer-0.2.0rc3-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for nodehammer-0.2.0rc3-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9eb40d1aa777d2ee5b7749ae9f065b9e1c1de76fe7d13418c338ee8cb506088a
MD5 f07f42c248452b4283c033eda2bd3e7e
BLAKE2b-256 fd24ffa1b8a6a961ed70bd4e6a7978d13e5fd6783c3acfb80e8ee85880fac461

See more details on using hashes here.

Provenance

The following attestation bundles were made for nodehammer-0.2.0rc3-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl:

Publisher: ci.yml on paulgessinger/nodehammer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nodehammer-0.2.0rc3-cp312-abi3-macosx_13_0_arm64.whl.

File metadata

File hashes

Hashes for nodehammer-0.2.0rc3-cp312-abi3-macosx_13_0_arm64.whl
Algorithm Hash digest
SHA256 34c8ee29c72694e2d73573203cca90311c184a68bff43094ed85050878852218
MD5 df5f442aecf9c3d949aea98c01e8b4aa
BLAKE2b-256 dee11968711bb14090420288a18adad8cd95c49168836f5481d7a4a4bc6c7d03

See more details on using hashes here.

Provenance

The following attestation bundles were made for nodehammer-0.2.0rc3-cp312-abi3-macosx_13_0_arm64.whl:

Publisher: ci.yml on paulgessinger/nodehammer

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.2.0rc2

4 files

1.2.0rc1

4 files

This release

0.2.0rc3 This release

4 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page