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

@plasius/gpu-model-fbx

v0.5.0

Published

Bounded browser-worker FBX scene, skin and morph import through verified canonical GPU model contracts.

Readme

@plasius/gpu-model-fbx

Bounded, worker-backed FBX import through the canonical GPU model boundary.

This repository is the dedicated package boundary defined by ADR 0094.

Supported import profile

createFbxImporter imports the plasius.fbx-morph/4 profile: FBX 7400 ASCII or binary (including compressed arrays), static mesh instances and source hierarchies, bones, linear skin clusters and sparse morph channels/targets. Polygons of 3–64 corners are triangulated by pinned ufbx, with per-corner normals/UV0 and per-face material groups preserved. The profile allows 64 source nodes, 32 materials, 128 material groups and 10,000 triangles across all instances. Positions use Float32 resources; matrices retain double precision.

The importer converts axes and units to canonical right-handed Y-up metres once. Geometric transforms affect mesh attributes only. Effective local matrices preserve evaluated static FBX pivots and all three inherit modes, including nonuniform/negative scale. Reflected winding and inverse-transpose normals remain consistent. Only root translations receive the single world floor-centre offset. Source units/axes/version, node/mesh/material names, numeric transform properties, rotation/inherit modes and the 20 common FBX material maps remain in metadata. Names with control characters and singular transforms fail explicitly.

Lambert diffuse/emission/opacity factors map to a named custom Lambert workflow; consumers must support that workflow. Phong/other shader lobes, unsupported material channels and out-of-range colour preview clamping produce canonical loss records. Import rejects these by default with unsupported-profile and error.diagnosticReport. A caller may explicitly use { allowMaterialLoss: true } for the diffuse preview approximation; inspect document.diagnostics and document.metadata.materialDiagnosticReport. Common numeric source maps and the shading-model name are retained; arbitrary custom shader graphs are not preserved. Consent never admits unsupported scene elements or resource acquisition.

Textures, additional UV sets, vertex colours/tangents, user properties, animation, cameras, lights and other element kinds still fail with unsupported-profile. Unattached meshes and unsupported scenes never become empty models. Texture/animation/export/repair work remains in tasks27–30; this package does not yet implement general DCC interchange or an exporter. The legacy packageName/packageBootstrap metadata remains compatible.

Linear skins retain deterministic source-scoped bone identity, hierarchy, per-instance palettes, and independent inverse bind matrices when meshes share bones. Cluster mesh-node-to-bone, geometry-to-bone and link-to-world matrices, plus explicit bind poses, remain in metadata. Geometry transforms are baked into attributes once, so canonical skin matrices use the mesh-node-to-bone convention. The published renderer bridge exposes the palette and verified JOINTS/WEIGHTS accessors; hosts own pose evaluation (jointWorld * inverseBind * position). It does not evaluate FBX animation takes, which remain task27.

The profile admits at most64 joints,64 mesh-instance skins,128 cluster bindings, 8 bind poses/512 pose entries and8 influences per control point. Corner expansion preserves weights through triangulation/material seams. Weights must be finite, non-negative, in[0,1] and sum to1 within1e-6; zero entries are permitted but zero-total vertices fail with invalid-skin-weights. No truncation, normalization repair or invented fallback joint occurs. JOINTS/WEIGHTS use4 or8 padded slots. unsupported-skinning explicitly denies rigid/dual-quaternion/blended methods, additive/TotalOne cluster modes, stacked deformers, duplicate-bone palettes and joint-local shear that cannot be preserved as canonical rest TRS. Capacity violations return limit-exceeded. No loss consent overrides these denials.

See ADR0009 and the skin qualification for conventions, limits and test evidence. Static profile2 inputs remain supported; the exported profile literal and private worker protocol advance to4, requiring matching package worker assets and recompilation of literal-typed profile consumers.

Morphs retain sparse source control-point membership in verified u32 accessors, expanded position/normal deltas, target/channel names and source identities. blendShapes exposes independent targets; node morphWeights and shape defaultWeight expose effective coefficients at the authored channel default. Source metadata retains channelWeight, targetWeight, keyIndex, affectedControlPointCount and affectedControlPointsAccessorId when nonempty. Positive increasing in-between thresholds preserve every target, including targets with zero default contribution. Apply morphs in mesh space before skinning or the scene transform; normalize the blended normal. Deltas receive geometric linear transforms once and never receive translation. Node matrices carry any remaining unit/basis conversion. Bounds describe the undeformed base; hosts own posed bounds.

At most4 targets per instance,128 instance-targets,120000 expanded target corners and120000 source membership references are admitted. Stacked/layered deformers, weighted-offset extensions, orphan elements and nonpositive/duplicate thresholds fail with unsupported-morph; invalid sparse data fails with invalid-morph or invalid-fbx. Normal offsets require base normals. No consent bakes or drops unsupported targets. See ADR0010 and the morph qualification. FBX take/layer animation remains task27; this profile preserves authored morph defaults.

import { createFbxImporter } from "@plasius/gpu-model-fbx";

const importer = createFbxImporter({
  // Use your authoritative stored remote decision on every evaluation.
  resolveFeatureFlag: key => featureFlags.evaluate(key),
  // Copy the package's dist directory to this admitted same-origin location,
  // or use your bundler's module-worker asset support.
  createWorker: () => new Worker("/vendor/fbx/fbx-worker.js", { type: "module" }),
});
try {
  const document = await importer.load({ kind: "blob", blob: selectedFile });
  consumeCanonicalDocument(document);
} finally {
  importer.dispose();
}

The host supplies the trusted worker factory and runtime acquisition ports. Keep the worker's shared chunk and ufbx.mjs alongside it. ESM and CJS consumers share the same public API; @plasius/gpu-model-fbx/worker resolves the module-worker asset and /provenance resolves its build manifest. Use a bundler with dynamic import splitting to retain lazy core/runtime acquisition. No parser or worker is allocated at import/constructor time or while the remote gate denies access.

The API accepts canonical ModelSource descriptors and optional caller signal and integrity evidence. Runtime acquisition is reused from the published @plasius/[email protected]; canonical validation is owned by @plasius/[email protected]. There are no workspace/local package references. File-provider injections must enforce the supplied byte ceiling while reading.

FBX_IMPORT_LIMITS fixes 8 MiB input, 24 MiB aggregate parser allocations, 50,000 allocation attempts and a 10-second whole-operation deadline. Optional limits can only tighten these values. The parser has a fixed 64 MiB Wasm memory, 1 MiB stack and 64-node depth ceiling. Each attribute buffer is at most 480,000 bytes; all verified attribute buffers total at most 5,520,000 bytes. Native node/material/primitive/name skeletal and morph tables have fixed capacities. Each importer admits one operation at a time, creates one fresh worker, and terminates it on success, failure, abort, timeout or disposal. It retains no model cache. Returned model payloads belong to the caller; no engine GC timing claim is implied by disposal. A shared abort word is used when isolation permits it; hard termination works without cross-origin isolation. If the host uses COOP/COEP, serve its worker scripts with the matching embedding policy too.

The worker accepts only bounded message bytes, disables ambient transports and implicit external files, and embeds Wasm in its fixed JavaScript asset. It has no Node/native SDK dependency. No network upload, persistence or telemetry is added. Errors use finite FbxImportError.code values. For an unsupported profile, retain the source for a future qualified adapter rather than weakening validation.

Dependency decision and implementation plan

ADR 0006 selects ufbx under its MIT option for the import implementation. The separate ufbx-write project is the first export candidate, subject to its own qualification; its work-in-progress status does not establish export fidelity or determinism. Autodesk FBX SDK is excluded from the default browser/npm distribution. Assimp remains an alternative if the export candidate cannot meet the declared profile. The importer pins ufbx v0.23.1 / 26a482ae66871d7de36eb722aa060bce95bce274 under MIT. ADR 0007 records the compiled worker boundary and toolchain. ADR 0008 and the geometry qualification define static mapping, losses, tolerances and qualification evidence.

TDR 0001 maps the dependency review to tracked import, geometry/metadata, skinning, blend-shape, animation, resource, export, and diagnostic work. It defines the license-notice, browser worker, resource-budget, fidelity, and release evidence required before those implementations ship. Runtime acquisition and canonical contracts belong to the existing @plasius/gpu-model-runtime and @plasius/gpu-model-core packages.

Rollout

  • Feature flag: gpu.model.conversion.enabled
  • Capability: none for this package-only layer
  • Rollback: disable the feature flag and keep the published package version pinned to the last validated release

Development

Requires the pinned Node.js version in .nvmrc, npm, and Emscripten 5.0.7. Install the official SDK at immutable installer revision d7b4130688bfa348392b921ab04015aa15c4f154, then run emsdk install 5.0.7 and emsdk activate 5.0.7. Set EMCC to its absolute upstream/emscripten/emcc path. No global installation or SDK EULA is required. Builds fetch only hash-verified immutable upstream files into .fbx-build-cache/; set FBX_BUILD_CACHE to choose another local cache.

npm ci
npm run typecheck
npm test
npm run lint
npm run build
npm run test:coverage
npm run artifacts:fbx
node node_modules/playwright-core/cli.js install chromium --only-shell
npm run test:browser
npm pack --dry-run

License

Apache-2.0 for package-owned code. ufbx and Emscripten use their selected MIT options; musl and compiler-rt retain their component notices. See legal/third-party/; identical notices, the bridge and a source/compiler/glue/Wasm hash manifest ship in npm. The reviewed baseline is native/artifact-baseline.json. artifacts:fbx rejects a changed baseline, non-fixed memory, missing notices or unexpected module artifacts. Synthetic fixture rights are recorded separately in the qualification design.

Release integrity

CI keeps the administrative contributor registry outside Git and npm package artifacts using exact, case-normalised path checks. CI runs on explicit GitHub-hosted runners. Publication uses the GitHub-hosted production job with Node 24 and a pinned npm 11.6.2 client. It is token-free and proceeds only while the prepared SHA is the exact main head after successful push-triggered CI. The completed 0.1.0 bootstrap path has been removed; subsequent releases must use npm trusted publishing.