Math Functions

These reusable DSL functions are provided by the installed nodeforge.math package and are imported from functions.

The functions catalog of the Math library contains reusable functions written in the DSL. Import a function before calling it. See Imports for import syntax and name-resolution rules.

Math Helpers

inverse_lerp(a=0.0, b=1.0, x=0.0)

Computes the unbounded interpolation factor of x between a and b.

Parameter Type Default Description
a Float 0.0 Range start.
b Float 1.0 Range end.
x Float 0.0 Value to measure inside the range.

Returns: Float.

from functions import inverse_lerp
value_1 = input_float('Value', default=4.0)
t = inverse_lerp(2.0, 6.0, value_1)
output('Factor', t)

remap(x=0.0, in_min=0.0, in_max=1.0, out_min=0.0, out_max=1.0)

Maps x from one numeric range to another. The result is not clamped.

Parameter Type Default Description
x Float 0.0 Input value.
in_min Float 0.0 Source range lower bound.
in_max Float 1.0 Source range upper bound.
out_min Float 0.0 Target range lower bound.
out_max Float 1.0 Target range upper bound.

Returns: Float.

from functions import remap
count = input_int('Count', default=32)
pts = points(count)
value_1 = index()
z = remap(value_1, in_min=0.0, in_max=count - 1.0, out_min=-1.0, out_max=1.0)
value_2 = index()
vec_3 = vector(value_2 * 0.1, 0, z)
pts = set_position(pts, vec_3)
output('Geometry', pts)

saturate(x=0.0)

Clamps x to the 0..1 range.

Parameter Type Default Description
x Float 0.0 Input value.

Returns: Float.

from functions import saturate
value = input_float('Value', default=1.25)
value_1 = saturate(value)
output('Clamped', value_1)

step(edge=0.0, x=0.0)

Returns 1.0 when x >= edge; otherwise returns 0.0.

Parameter Type Default Description
edge Float 0.0 Threshold.
x Float 0.0 Value to test.

Returns: Float.

from functions import step
value_1 = position()
value_2 = noise(value_1, scale=3.0)
mask_value = step(0.5, value_2)
output('Mask', mask_value)

smoothstep(edge0=0.0, edge1=1.0, x=0.0)

Returns a clamped Hermite interpolation from 0 to 1 between edge0 and edge1.

Parameter Type Default Description
edge0 Float 0.0 Lower transition edge.
edge1 Float 1.0 Upper transition edge.
x Float 0.0 Input value.

Returns: Float.

from functions import smoothstep
pts = points(64)
value_1 = index()
t = smoothstep(0.0, 63.0, value_1)
value_2 = index()
vec_3 = vector(value_2 * 0.05, 0, t)
pts = set_position(pts, vec_3)
output('Geometry', pts)

smootherstep(edge0=0.0, edge1=1.0, x=0.0)

Returns a clamped smoother interpolation from 0 to 1 between edge0 and edge1.

Parameter Type Default Description
edge0 Float 0.0 Lower transition edge.
edge1 Float 1.0 Upper transition edge.
x Float 0.0 Input value.

Returns: Float.

from functions import smootherstep
x = input_float('X', default=0.35)
value_1 = smootherstep(0.0, 1.0, x)
output('Value', value_1)

pingpong(x=0.0, length=1.0)

Wraps x into a repeating triangular wave between 0 and length.

Parameter Type Default Description
x Float 0.0 Input value.
length Float 1.0 Peak value of the wave.

Returns: Float.

from functions import pingpong
pts = points(80)
value_1 = index()
z = pingpong(value_1 * 0.1, 1.0)
value_2 = index()
vec_3 = vector(value_2 * 0.05, 0, z)
pts = set_position(pts, vec_3)
output('Geometry', pts)

wrap(x=0.0, min=0.0, max=1.0)

Wraps x into the half-open range [min, max) using modulo arithmetic.

Parameter Type Default Description
x Float 0.0 Input value.
min Float 0.0 Lower bound.
max Float 1.0 Upper bound.

Returns: Float.

from functions import wrap
value_1 = input_float('Angle', default=7.0)
angle = wrap(value_1, min=0.0, max=tau)
output('Angle', angle)

sign(x=0.0)

Returns -1.0 for negative values, 0.0 for zero, and 1.0 for positive values.

Parameter Type Default Description
x Float 0.0 Input value.

Returns: Float.

from functions import sign
x = input_float('X', default=-2.0)
value_1 = sign(x)
output('Direction', value_1)

Vector Helpers

rotate2d(v=vector(1, 0, 0), angle=0.0)

Rotates the XY components of v around the Z axis. The original Z component is preserved.

Parameter Type Default Description
v Vector vector(1, 0, 0) Input vector.
angle Float 0.0 Rotation angle in radians.

Returns: Vector.

from functions import rotate2d
vec_1 = vector(1, 0, 0)
value_2 = radians(45)
v = rotate2d(vec_1, value_2)
output('Vector', v)

polar(radius=1.0, angle=0.0)

Creates an XY vector from polar coordinates. Z is 0.0.

Parameter Type Default Description
radius Float 1.0 Distance from origin.
angle Float 0.0 Angle in radians.

Returns: Vector.

from functions import polar
value_1 = radians(30)
pos = polar(radius=2.0, angle=value_1)
output('Vector', pos)

angle_between(a=vector(1, 0, 0), b=vector(0, 1, 0))

Computes the angle between two vectors. Inputs are normalized internally and the dot product is clamped to -1..1 before acos(...).

Parameter Type Default Description
a Vector vector(1, 0, 0) First vector.
b Vector vector(0, 1, 0) Second vector.

Returns: Float.

from functions import angle_between
vec_1 = vector(1, 0, 0)
value_2 = position()
vec_3 = normalize(value_2)
angle = angle_between(vec_1, vec_3)
output('Angle', angle)

rotate_around_axis(v=vector(1, 0, 0), axis=vector(0, 0, 1), angle=0.0)

Rotates v around axis using Rodrigues' rotation formula. axis is normalized internally.

Parameter Type Default Description
v Vector vector(1, 0, 0) Input vector.
axis Vector vector(0, 0, 1) Rotation axis.
angle Float 0.0 Rotation angle in radians.

Returns: Vector.

from functions import rotate_around_axis
vec_1 = vector(1, 0, 0)
vec_2 = vector(0, 1, 0)
value_3 = radians(90)
v = rotate_around_axis(vec_1, axis=vec_2, angle=value_3)
output('Vector', v)

Point Creation and Layouts

Layout functions operate on point-domain geometry. They use the current point index() field and the explicit count parameter when present; they do not inspect the input geometry's point count.

layout_grid(geometry, count=vector(1, 1, 1), spacing=vector(1, 1, 1), centered=False)

Places existing points in a 3D lattice.

Parameter Type Default Description
geometry Geometry required Point geometry to position.
count Vector vector(1, 1, 1) Lattice dimensions interpreted as (count_x, count_y, count_z). Components are clamped to at least 1.0 for index math.
spacing Vector vector(1, 1, 1) Per-axis spacing. Use vector(s, s, s) for uniform spacing.
centered Bool False When true, positions are shifted by half of the layout extent so the lattice is centered around the origin. When false, positions use raw lattice coordinates from the origin.

Returns: Geometry.

from functions import layout_grid
pts = points(12)
vec_1 = vector(4, 3, 1)
vec_2 = vector(0.5, 0.5, 0.0)
pts = layout_grid(pts, count=vec_1, spacing=vec_2, centered=False)
output('Geometry', pts)

grid_points(count=vector(1, 1, 1), spacing=vector(1, 1, 1), centered=False)

Creates points and places them with layout_grid(...). The point count is max(count.x, 0) * max(count.y, 0) * max(count.z, 0).

Parameter Type Default Description
count Vector vector(1, 1, 1) Number of generated points per axis. Zero or negative components produce zero generated points for that component.
spacing Vector vector(1, 1, 1) Per-axis spacing.
centered Bool False Passed to layout_grid(...).

Returns: Geometry.

from functions import grid_points
vec_1 = vector(5, 4, 1)
vec_2 = vector(0.5, 0.5, 0.0)
grid = grid_points(count=vec_1, spacing=vec_2, centered=False)
output('Geometry', grid)

layout_circle(geometry, count=16, radius=1.0, start_angle=0.0, end_angle=tau, include_endpoint=False)

Places existing points on an XY circle or arc.

Parameter Type Default Description
geometry Geometry required Point geometry to position.
count Int 16 Explicit count used to compute the normalized index.
radius Float 1.0 Circle or arc radius.
start_angle Float 0.0 Start angle in radians.
end_angle Float tau End angle in radians.
include_endpoint Bool False When true, the last point reaches end_angle. For full circles the default avoids duplicating the first point.

Returns: Geometry.

from functions import layout_circle
pts = points(24)
pts = layout_circle(pts, count=24, radius=2.0, start_angle=0.0, end_angle=tau)
output('Geometry', pts)

circle_points(count=16, radius=1.0, start_angle=0.0, end_angle=tau, include_endpoint=False)

Creates point geometry and places the points with the same circle/arc formula used by layout_circle(...).

Parameter Type Default Description
count Int 16 Number of generated points. Negative values are clamped to zero for point generation.
radius Float 1.0 Circle or arc radius.
start_angle Float 0.0 Start angle in radians.
end_angle Float tau End angle in radians.
include_endpoint Bool False When true, the last point reaches end_angle.

Returns: Geometry.

from functions import circle_points
arc = circle_points(count=16, radius=2.0, start_angle=0.0, end_angle=pi, include_endpoint=True)
output('Geometry', arc)

layout_spiral(geometry, count=16, radius=1.0, turns=1.0, height=0.0, start_radius=0.0, start_angle=0.0)

Places existing points along a radial spiral in the XY plane, with optional Z height.

Parameter Type Default Description
geometry Geometry required Point geometry to position.
count Int 16 Explicit count used to compute the normalized index.
radius Float 1.0 Final radius.
turns Float 1.0 Number of full revolutions.
height Float 0.0 Final Z height.
start_radius Float 0.0 Initial radius.
start_angle Float 0.0 Initial angle in radians.

Returns: Geometry.

from functions import layout_spiral
pts = points(96)
pts = layout_spiral(pts, count=96, radius=3.0, turns=4.0, height=1.5)
output('Geometry', pts)

spiral_points(count=16, radius=1.0, turns=1.0, height=0.0, start_radius=0.0, start_angle=0.0)

Creates point geometry and places the points with layout_spiral(...).

Parameter Type Default Description
count Int 16 Number of generated points. Negative values are clamped to zero for point generation.
radius Float 1.0 Final radius.
turns Float 1.0 Number of full revolutions.
height Float 0.0 Final Z height.
start_radius Float 0.0 Initial radius.
start_angle Float 0.0 Initial angle in radians.

Returns: Geometry.

from functions import spiral_points
spiral = spiral_points(count=128, radius=3.0, turns=5.0, height=2.0, start_radius=0.25)
output('Geometry', spiral)

layout_random(geometry, min=vector(-1, -1, -1), max=vector(1, 1, 1), seed=0)

Places existing points at random positions between vector bounds. The point index is used as the random ID.

Parameter Type Default Description
geometry Geometry required Point geometry to position.
min Vector vector(-1, -1, -1) Lower random bound.
max Vector vector(1, 1, 1) Upper random bound.
seed Int 0 Random seed.

Returns: Geometry.

from functions import layout_random
pts = points(50)
vec_1 = vector(-2, -2, 0)
vec_2 = vector(2, 2, 1)
pts = layout_random(pts, min=vec_1, max=vec_2, seed=7)
output('Geometry', pts)

random_points(count=16, min=vector(-1, -1, -1), max=vector(1, 1, 1), seed=0)

Creates point geometry and places the points with layout_random(...).

Parameter Type Default Description
count Int 16 Number of generated points. Negative values are clamped to zero for point generation.
min Vector vector(-1, -1, -1) Lower random bound.
max Vector vector(1, 1, 1) Upper random bound.
seed Int 0 Random seed.

Returns: Geometry.

from functions import random_points
vec_1 = vector(-3, -3, 0)
vec_2 = vector(3, 3, 2)
pts = random_points(count=100, min=vec_1, max=vec_2, seed=42)
output('Geometry', pts)

Geometry Helper

copy_by_offsets(geometry, scale=vector(1/3, 1/3, 1))

Duplicates input geometry into the eight cells around the center of a 3x3 grid. This is the offset pattern used for Sierpinski-carpet style subdivision.

Parameter Type Default Description
geometry Geometry required Source geometry.
scale Vector vector(1/3, 1/3, 1) Per-copy scale.

Returns: Geometry.

from functions import copy_by_offsets
geo = cube(size=1.0)
vec_1 = vector(1 / 3, 1 / 3, 1 / 3)
geo = copy_by_offsets(geo, scale=vec_1)
output('Geometry', geo)

Fractal Helper

sierpinski_carpet(geometry, steps=2, scale=vector(1/3, 1/3, 1))

Repeatedly applies copy_by_offsets to create a Sierpinski-carpet-style arrangement. steps is a runtime Int; non-positive values perform no repeat iterations.

from functions import sierpinski_carpet

source = cube(size=1.0)
geometry = sierpinski_carpet(source, steps=2)
output('Geometry', geometry)

Sequence Helper

fibonacci(n=8)

Computes the Fibonacci sequence with a runtime Repeat Zone. F(0)=0, F(1)=1, and F(n)=F(n-1)+F(n-2).

Parameter Type Default Description
n Int 8 Iteration count.

Returns: Int or numeric value compatible with the Repeat Zone state.

from functions import fibonacci
n = input_int('N', default=10)
value = fibonacci(n)
output('Value', value)

For complete scripts included with the package, see Math Examples.