Skip to content

NeuroanatomyAndConnectivity/directionality-indicator-webgl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Directionality Indicator (Web)

πŸ”— Live demo: https://neuroanatomyandconnectivity.github.io/directionality-indicator-webgl/

Browser-based visualization of directional information on anatomical surfaces. A WebGL2 / TypeScript port of the C++/Qt/OpenGL 3.3 DirectionalityIndicator by Sebastian Eichelbaum and the Max Planck Research Group "Neuroanatomy and Connectivity". See NOTICE.md for credits and license.

The visualization pipeline is the original's Tier-1 behaviour: a Line Integral Convolution (LIC) flow rendered on the cortical surface, with directionality arrows overlaid following the parcellation-derived vector field.


Quick start

cd web
npm install
npm run dev

Open http://localhost:5173. The bundled demo dataset (label34.ply, label34.labels, label34.labelorder) loads automatically.

Browser requirements

  • WebGL2 with the EXT_color_buffer_float extension. The app detects the extension at boot and shows a banner if it's missing. Chromium-based browsers, Firefox, and Safari 16+ all support this.
  • A modern JS engine (ES2022 features used).

Panel overview

The right-side panel is fully collapsible (click the chevron at its left edge or the corner button when closed). Sections collapse individually by clicking their headings; collapse state persists.

Data

Pick a dataset triple β€” one .ply mesh, one .labels file, one .labelorder file β€” via the file picker. The triple is parsed, processed, and rendered. The dataset is cached in IndexedDB and auto-restored on the next page load. Cache is cleared by the Reset to defaults button at the bottom of the panel.

View

Six canonical anatomical view buttons: Lateral L/R, Anterior / Posterior, Dorsal / Ventral. Click to snap. Free rotation/pan/zoom with the mouse is also available; the camera position auto-saves 350 ms after each change and restores on next load.

Visibility

Independent toggles for the three layers:

  • LIC streamlines β€” the smeared noise pattern showing the directional field on the surface.
  • Parcellation colors β€” the per-region colored shading. When off, the surface goes black so the LIC streaks read more clearly.
  • Arrows β€” the overlay glyphs.

LIC

  • Streamline length (iterations) β€” how far each LIC noise sample is advected along the field. Longer = more visible streaks.
  • High contrast β€” boosts the LIC contribution to the composite.
  • Emphasize singularities β€” paints weak-magnitude regions (saddles, vortex centres) with white/black bands so field topology reads at a glance. Mirrors the original C++ m_emphasizeSingularPointsEnable.

Scene

  • Background β€” canvas clear color (used for both the page background and PNG screenshot transparency reference).

Surface shading

Phong parameters for the underlying parcellation surface:

  • Ambient / Diffuse / Specular β€” standard material weights.
  • Shininess β€” specular sharpness. Higher = smaller, sharper highlights. Defaults are softened from the original C++ to reduce glare.

Arrows

  • Borders only (M2 mode) β€” restrict arrow placement to parcellation-border vertices instead of the whole surface.
  • Density (smaller = denser) β€” Poisson minimum spacing as a fraction of mesh radius. Coupled to arrow length so arrows can't visually overlap regardless of size.
  • Size / Length / Head width / Body width β€” arrow geometry. Length and Size trigger a re-sample on release (debounced).
  • Distance from surface β€” how far above the surface the arrow bodies float (in mesh units relative to arrow scale).
  • Opacity β€” alpha-blend strength of the arrow over the LIC.
  • Flip direction β€” instant uniform-side flip of all arrows.
  • Color β€” picker; default black.

Screenshot

  • Resolution (DPI) β€” output pixel scale. 72 β†’ 1 Γ— current canvas; 150 β†’ ~1.5 Γ—; 1200 β†’ ~12.5 Γ—. Hard-capped at 50 megapixels (a console warning fires if the requested resolution would exceed this).
  • Current view β€” saves the current camera angle as a transparent- background PNG, auto-cropped to the brain extent.
  • All canonical views β€” saves six PNGs (one per anatomical direction), each auto-cropped.

Reset to defaults

At the bottom of the panel. Clears all panel parameters, the camera state, the section-collapse state, and the IndexedDB dataset cache, then reloads.


Mouse / keyboard

Gesture Action
Drag Rotate (trackball, around target)
Shift + drag Pan (translate target on screen)
Wheel Zoom (exponential, distance-clamped)

Camera state (rotation, target, distance) persists 350 ms after each change.


Data format

The app expects three files per dataset, all referring to the same mesh by vertex order.

.ply β€” ASCII PLY 1.0. The current parser supports:

ply
format ascii 1.0
element vertex N
property float x
property float y
property float z
[property uchar red]      (optional; alternative source of color)
[property uchar green]
[property uchar blue]
element face M
property list uchar int vertex_indices
end_header
...vertex data, one line per vertex...
...face data, one line per triangle...

Triangle faces only. Per-vertex colors in the PLY (the optional red / green / blue columns) are used directly as the surface palette when present. When the PLY has no color columns, the surface falls back to a label-derived HSV-wheel palette keyed by labelorder index. The labels file is always used to compute the directionality field that the arrows follow, regardless of where the surface colors come from.

TODO: decouple surface colors entirely from the PLY by reading a separate colormap file, so the PLY can be pure geometry.

.labels β€” one integer per line, one line per mesh vertex. The integer is the region ID for that vertex.

.labelorder β€” one integer per line listing the region IDs in display order. The number of entries determines how many regions there are. Region IDs in .labels that are not in .labelorder are treated as "ignored" / non-mesh (excluded from the directionality field).

The bundled demo label34.* is the FreeSurfer 34-region cortical parcellation on a single cortical hemisphere mesh (32,492 vertices, 64,980 triangles).


How it works (short version)

  1. Parse the three input files.
  2. extractRegions β€” port of the original ExtractRegions Case 2 algorithm. Computes a per-vertex unit direction vector from the parcellation: at parcel borders, the direction follows the labelorder (from later-in-order to earlier-in-order); the field is then iteratively spread inward across each parcel by Laplacian- style propagation projected onto the surface tangent plane.
  3. SurfaceLIC β€” four-pass FBO pipeline:
    • Transform β€” render the mesh into G-buffers (color, view-space vec, noise sampled from a 3D noise volume by world position, normal, position).
    • Edge β€” Laplacian on the depth buffer.
    • Advect β€” iterated noise advection along the screen-space vec field (50 forward + 50 backward Euler steps), accumulating and averaging.
    • Compose β€” combine color + LIC + edge mask + multi-LOD depth halo into the canvas.
  4. Arrows β€” streamline-based seeding (or border-restricted Poisson-disk in M2 mode), then instanced quad rendering with the parametric arrow shape from the original C++ Arrows-fragment shader. Occlusion uses the LIC G-buffer position texture.

For deeper architectural notes see docs/superpowers/specs/ and docs/superpowers/plans/.


Layout

web/
β”œβ”€β”€ README.md                        β€” this file
β”œβ”€β”€ NOTICE.md                        β€” credits and license info
β”œβ”€β”€ index.html                       β€” entry HTML + panel CSS
β”œβ”€β”€ package.json
β”œβ”€β”€ vite.config.ts
β”œβ”€β”€ tsconfig.json
β”œβ”€β”€ public/data/                     β€” bundled demo dataset
└── src/
    β”œβ”€β”€ main.ts                      β€” boot
    β”œβ”€β”€ app.ts                       β€” top-level pipeline orchestrator
    β”œβ”€β”€ io/                          β€” PLY / labels / labelorder parsers + IndexedDB cache
    β”œβ”€β”€ algorithms/                  β€” extractRegions, sampling, surfaceLIC, etc.
    β”œβ”€β”€ gfx/                         β€” view, camera, framebuffer, screen quad, program, buffer
    β”œβ”€β”€ ui/                          β€” panel
    └── shaders/                     β€” all GLSL

Development

npm test            # vitest run
npm run build       # tsc + vite build
npm run dev         # vite dev server with HMR

Tests cover the IO parsers (plyReader, labelReader, labelOrderReader), the regionColors palette, meshAdjacency, computeNormals, extractRegions, seedArrows, and the Camera view math. GPU code paths (the LIC pipeline, arrow rendering) are exercised by the dev server's interactive UAT.

About

WebGL2/TypeScript port of the C++/Qt DirectionalityIndicator (SurfaceLIC + illustrative arrows on cortical surfaces)

Resources

License

GPL-3.0, LGPL-3.0 licenses found

Licenses found

GPL-3.0
LICENSE
LGPL-3.0
LICENSE.LESSER

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors