npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

blast-stress-solver

v0.3.1

Published

Dual-format (ESM + CJS) JavaScript/WASM package exposing the NVIDIA Blast Stress Solver bridge with first-class TypeScript types.

Readme

blast-stress-solver

Dual-format (ESM + CJS) JavaScript/WASM package exposing the NVIDIA Blast Stress Solver bridge with first-class TypeScript types.

Install

npm install blast-stress-solver

Usage (browser)

import { loadStressSolver } from 'blast-stress-solver';

const rt = await loadStressSolver();
const solver = rt.createExtSolver({ nodes, bonds, settings: rt.defaultExtSettings() });
solver.addGravity({ x: 0, y: -9.81, z: 0 });
const [{ actorIndex }] = solver.actors();
solver.addActorGravity(actorIndex, { x: 0, y: -9.81, z: 0 }); // per-actor helper
solver.update();
const cmds = solver.generateFractureCommands();

If an actor is rotated relative to world space (e.g., a column rotated 90° so its local “down” axis points sideways), convert the world gravity vector using the actor’s rotation before calling addActorGravity:

const localGravity = worldGravity.clone().applyQuaternion(actorWorldQuaternion.clone().invert());
solver.addActorGravity(actorIndex, localGravity);

This mirrors what the physics body experiences and lets the stress solver distinguish between compression along the column versus shear when it lies on its side.

Usage (Node / SSR)

import { loadStressSolver } from 'blast-stress-solver';
const rt = await loadStressSolver();

Works in Vite/Webpack/Next.js without custom config. The WASM is referenced via new URL(..., import.meta.url) so bundlers copy it automatically. To host the WASM from a custom path, override locateFile:

await loadStressSolver({
  module: {
    locateFile: (p) => (p.endsWith('.wasm') ? '/wasm/blast/stress_solver.wasm' : p)
  }
});

Next.js notes

  • Server (SSR) imports use the Node export automatically.
  • Client: import inside an effect or use dynamic import to avoid SSR hydration issues.

Client-side example:

import { useEffect, useState } from 'react';
import { loadStressSolver } from 'blast-stress-solver';

export default function Component() {
  const [ready, setReady] = useState(false);
  useEffect(() => {
    (async () => {
      const rt = await loadStressSolver();
      // ... create solver, etc.
      setReady(true);
    })();
  }, []);
  return ready ? <div>Ready</div> : null;
}

Or dynamically import on the client only:

import dynamic from 'next/dynamic';
const ClientOnly = dynamic(() => import('./ClientComponent'), { ssr: false });

Types

This package ships TypeScript types generated from source; see StressRuntime, ExtStressSolver, and helpers in the API.

Author bonds from prefractured meshes

If you already have a fractured mesh (triangle soup per chunk), you can let the WASM bridge generate Blast-style bonds for you:

import { loadStressSolver } from 'blast-stress-solver';

const rt = await loadStressSolver();
const chunks = [
  {
    triangles: Float32Array.from([
      // chunk 0 triangles (xyz per vertex, 9 floats per triangle)
      -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5,
      // ...
    ])
  },
  {
    triangles: Float32Array.from([/* chunk 1 triangles */]),
    isSupport: true
  }
];

const exactBonds = rt.createBondsFromTriangles(chunks); // defaults to mode: 'exact'
const tolerantBonds = rt.createBondsFromTriangles(chunks, { mode: 'average', maxSeparation: 0.02 });

const solver = rt.createExtSolver({ nodes, bonds: tolerantBonds, settings: rt.defaultExtSettings() });
  • Every chunk entry is a flat array of local-space vertices ([x0, y0, z0, x1, y1, z1, ...]); each triangle consumes 9 floats.
  • Set isSupport on a chunk to opt-in/out of the support graph (default: true).
  • mode: 'exact' (default) computes the precise shared surface from triangle geometry.
  • mode: 'average' approximates the bond interface using convex hulls and a maxSeparation tolerance so that slightly separated chunks (due to noise/gaps) can still be connected. Always supply a positive maxSeparation when using this mode.
  • The generated bonds already contain centroid, normal, area, and chunk indices, so they can be used directly when creating your solver or Blast asset.

Three.js example

If your chunks are THREE.BufferGeometry instances (often pre-fractured offline), convert them to triangle soups like so:

import * as THREE from 'three';
import {
  loadStressSolver,
  chunksFromBufferGeometries,
  chunkFromBufferGeometry
} from 'blast-stress-solver';

const chunkGeometries: THREE.BufferGeometry[] = /* your pre-fractured chunks */;

// Option A: convert the full collection in one call
const chunks = chunksFromBufferGeometries(chunkGeometries, (geometry, index) => ({
  isSupport: index > 0, // simple predicate
  applyMatrix: worldTransforms[index] // optional Matrix4 per chunk
}));

// Option B: convert ad hoc
const extraChunk = chunkFromBufferGeometry(chunkGeometries[0], {
  isSupport: true,
  nonIndexed: true
});

const rt = await loadStressSolver();
const bonds = rt.createBondsFromTriangles([...chunks, extraChunk], { mode: 'exact' });
  • By default, chunkFromBufferGeometry converts indexed geometry to non-indexed triangle lists (nonIndexed: true), which is what the bond generator expects. Set nonIndexed: false if your data is already in triangle-list form.
  • chunkFromBufferGeometry clones the geometry by default (cloneGeometry: true) so your originals remain untouched. Pass cloneGeometry: false if you prefer to mutate in-place.
  • Supply any Matrix4 (e.g., mesh.matrixWorld) via applyMatrix to bake transforms before sampling the triangle data.
  • You can precompute chunk centroids/masses separately and feed them into the solver nodes.

License

Tests

Run the full build + test suite (includes the WASM authoring helpers) with:

npm install
npm test

Implementation notes

  • The WASM build of Blast used by this package is compiled with SIMD intrinsics disabled (COMPILE_VECTOR_INTRINSICS=0), using the scalar math path for maximum portability across browsers.
  • Native C++ builds may use SSE/NEON for higher performance; future releases may enable WebAssembly SIMD behind the same JS API.
  • Average-mode bonding relies on a lightweight convex hull builder compiled into the WASM module. When using 'average', make sure to provide a reasonable maxSeparation so the helper knows how much gap/noise to tolerate.

MIT