Skip to documentation
CranberryClock.Ideas / Systems / Design

INDEPENDENT TOOL / v0.1.0

LoomIntegration guide

Install Loom, connect it to your project, and understand the integration boundaries.

Start with the package archive.

Download Loom v0.1.0 ↓, then follow the installation instructions below. Commands that pack source files run from the public repository checkout.

Install

Download cranberry-forge-loom-0.1.0.tgz from the showcase, then install the archive:

bash
npm install ./cranberry-forge-loom-0.1.0.tgz three@0.180.0
javascript
import { Loom, createLoomSample } from "@cranberry-forge/loom";

Loom is ESM with complete declarations. The supported peer range is three >=0.180.0 <0.181.0; testing uses 0.180.0. Installation from the archive does not require an npm registry publication. TypeScript consumers should provide matching @types/three declarations.

For a browser without a bundler, extract the package, serve it alongside Three, and add an import map before your module:

html
<script type="importmap">
  {
    "imports": {
      "three": "/vendor/three/build/three.module.js",
      "@cranberry-forge/loom": "/packages/loom/index.js"
    }
  }
</script>

Geometry, frames, and limitations

The centerline is a centripetal Catmull–Rom curve. Loom uses Three's arc-length lookup with max(512, segments × 4, pointCount × 32) divisions. Mesh rows are equally spaced by this approximate centerline distance. Accuracy depends on curve complexity and sampling resolution; this is not an analytic arc-length solution.

The first up vector is projected perpendicular to the tangent. When that projection is nearly zero, Loom chooses a deterministic least-aligned axis. Subsequent frames use minimal tangent-to-tangent rotation and projection. Closed routes distribute residual frame twist across the loop before banking. Arbitrary samples interpolate stored orientations, then reproject against the sampled tangent. This keeps frames usable on vertical sections without requiring a global Y-up tangent cross-product at every point. It does not infer railway superelevation or physically correct roll from speed.

The ribbon is a zero-thickness strip, with transverse UV from 0 to 1 and longitudinal UV from 0 to length / uvScale. Surface normals follow the sampled up frames. Borders are rectangular prisms centered on each ribbon edge and rising along up; their faces have their own normals/UVs. The package does not build a solid roadbed, rail-wheel contact, sleepers, support columns, switches, terrain cuts, or junction meshes. Those in the showcase are host geometry placed through the public API.

Width, bank, and tight curvature can produce self-intersections or overlap between borders. Loom does not solve collisions, minimum bend radius, path clearance, topology repair, lane markings, navigation, physics, or train coupling. Rejecting degenerate inputs is not a proof that a route is physically traversable. The demo train uses kinematic placement, and its open-route carriage reversal is an illustration rather than a railway dynamics simulation.

Geometry rebuilds allocate new arrays and meshes' geometry resources. Update only when route settings change, reuse samples for moving objects, and profile large route counts. Never rebuild the route just to advance a train. The package has no workers, GPU compute dependency, event loop, timers, scene-wide traversal, network requests, or other Cranberry Forge dependencies.

View versioned source on GitHub ↗