Skip to content

Spline

App: apps/spline_demo/

Demonstrates the Spline curve primitive (engine PLM-243 / ADR 0080), the keystone of Block SPL (splines / geometry / scatter). A 5-point Catmull-Rom curve is drawn as a line strip and its rotation-minimizing orientation frames are drawn as gizmos — tangent red, normal green, binormal blue — the moving basis a mesh extruder sweeps a profile along.

Terminal window
% ./plume3d spline_demo

An oblique camera looks at the curvy 3D path; the line strip traces it and 16 evenly-spaced axis gizmos ride along it. The demo captures a screenshot at frame 90 and exits.

  • Builds an empty spline and appends five control points (the default type is "catmullrom", which passes through every point), then logs its arc length:

    _spline = Spline.new()
    _spline.addPoint(-4, 0, -2)
    _spline.addPoint(-2, 2.5, 2)
    _spline.addPoint(0.5, -1.5, 3)
    _spline.addPoint(2.5, 2, -1)
    _spline.addPoint(4, -0.5, -3)
    Logger.info("spline length = %(_spline.length), points = %(_spline.pointCount)")
  • Samples the curve as a line strip at constant arc-length spacing — using positionAtDistance rather than position(t), so the vertices never bunch up on the tight turns (t is not constant-speed):

    var L = _spline.length
    var n = 80
    var cv = []
    for (i in 0...n) {
    var p = _spline.positionAtDistance(L * i / (n - 1)) // p = [x, y, z]
    cv.add([p[0], p[1], p[2], 0, 1, 0, 0.95, 0.85, 0.25, 1, 0, 0])
    }
    _curve = Graphics.newMesh(cv, "linestrip", _flat)
  • Asks for 16 evenly-spaced orientation frames and draws each frame’s three axes as gizmo lines. Each frame is a flat 13-number list [px,py,pz, tx,ty,tz, nx,ny,nz, bx,by,bz, width], so the tangent is slots 3..5, the normal 6..8, and the binormal 9..11:

    var frames = _spline.sampleFrames(16)
    for (f in frames) {
    addAxis(gz, f, 3, 6, g, [1.0, 0.35, 0.35]) // tangent (red)
    addAxis(gz, f, 6, 9, g, [0.35, 1.0, 0.4]) // normal (green)
    addAxis(gz, f, 9, 12, g, [0.4, 0.6, 1.0]) // binormal (blue)
    }
  • The frames are rotation-minimizing — they transport the normal along the curve without twist, so the gizmo basis never suddenly flips over between samples.
  • sampleFrames(count) is the direct input to mesh extrusion: place a cross-section profile at each frame’s position, oriented by its normal/binormal and scaled by its width slot.

See Spline for the full method surface — Bézier / closed-loop / roll options, addPointFull per-point width, and the t-vs-distance distinction.