In a web page
The readers, the mesher and — in the Web Pro build — the kernel, compiled to WebAssembly: an ES module for any browser, with typings. Files are read on the visitor's machine and never uploaded. The viewer, the forge and the notebook on this site run on the same module.
Two packages, one per license
Each release carries cadaclysm-<version>-web-reader.zip (the readers and the mesher, for a Web Reader license) and cadaclysm-<version>-web-pro.zip (those plus the kernel, for Web Pro — with the reader-only build beside it in pkg-reader/ for pages that only view). In a checkout of the SDK:
python fetch.py --license KEY # cadaclysm.lic from the store
python fetch.py --web # the package that license covers, into web/
Each package holds pkg/ (the module: cadaclysm.js, cadaclysm_bg.wasm, index.js and their typings), viewer/ (the WebGL2 viewer this site uses: typed arrays in, pixels out, no dependencies) and example/, a page and its worker. Serve the folder with any static server and open /example/.
In a Web Worker
An open, a mesh or a boolean runs on the thread that calls it, and a browser kills a page whose main thread blocks for long. Load the module in a worker and post the buffers back — they transfer without a copy.
// worker.js (new Worker("worker.js", { type: "module" }))
import { load, open } from "./pkg/index.js";
const ready = load({ license: "/cadaclysm.lic" }); // a URL, or the file's text
self.onmessage = async ({ data }) => {
await ready;
const scene = open(new Uint8Array(data.bytes), "step"); // step, iges, sat, 3dm, ifc, brep, scad
const vertices = scene.vertices(); // nine floats a vertex: position, normal, colour
const indices = scene.indices();
self.postMessage({ vertices, indices, tree: JSON.parse(scene.tree_json()) },
[vertices.buffer, indices.buffer]);
scene.free(); // wasm memory never shrinks: free a scene before reading the next
};
CadScene also hands over the feature edges(), free curves(), isocurves(), the bounds(), the part spans and each part's attributes_json(part). pkg/cadaclysm.d.ts types every export.
The kernel
The kernel's calls are the C API's cadaclysm_blacksmith_* entry points, name for name — cadaclysm_blacksmith.h in the SDK is the reference. Handles are numbers, a frame is twelve numbers (origin, then the x, y and z axes), a failure throws with the C API's own message, and hasKernel() tells the two builds apart.
const rect = cadaclysm_blacksmith_profile_rect(60, 40);
const plate = cadaclysm_blacksmith_extrude(rect, [0,0,0, 1,0,0, 0,1,0, 0,0,1], 8);
const bore = cadaclysm_blacksmith_translate(cadaclysm_blacksmith_cylinder(9, 30), 0, 0, -10);
const part = cadaclysm_blacksmith_cut(plate, bore, 0.05); // 0.05: the chord tolerance it meshes at
const mesh = cadaclysm_blacksmith_mesh(part, 0.05); // { positions, normals, indices }
const step = cadaclysm_blacksmith_step(new Uint32Array([part]), ap203, 1); // ap203: schemas/ap203.exp's text
A web license, and the websites it names
A web license covers one website — a domain and its subdomains — per site bought. Hand the module the file with load({ license }) or license(text); a page cannot read a path, so a URL is fetched and text is taken as it is. If the file cannot be fetched or does not verify, load() says so on the console and the module runs unlicensed rather than failing to start; useLicense() throws instead, for a page that wants to know. The license names the websites it was bought for (asked at checkout; to change them, write to info@blitter.studio). On any other host the module runs as if unlicensed; localhost and file: pages always pass, so development never needs the license to say where the site will live.
Without a license — or on a host it does not name — everything still works, and a notice goes to the browser console on every file opened and every STEP file written. license_info() says what the module runs under (customer=… scope=web sites=1 domains=acme.com); license_notice_count() counts the notices, for a page that would rather show its own banner. Paid licenses cover every build dated on or before the day their updates end (build_date()), as the native libraries' do.