API Reference
Auto-generated from source metadata. Functions marked Provisional may have API changes in future releases.
eido.core
Rendering and export — the main entry point for Eido. Use `render` for one-stop rendering of scenes and animations to images, SVG, GIF, or polyline data. Specialized functions (`render-to-file`, `render-to-svg`, etc.) are also available for direct use.
*validate*Defaults to true. Bind to false in REPL/watch workflows for faster
re-renders. The
show and watch-* dev helpers automatically skipvalidation after the first successful render.
(explain scene)Returns the error vector, or nil if valid.
(format-errors errors)Takes a vector of error maps as returned by validate.
(read-scene path)(render input)(render input opts)Single scene:
(render scene) → BufferedImage
(render scene {
:output "out.png"}) → writes file, returns path(render scene {
:format :svg}) → SVG string(render scene {
:format :dxf}) → DXF R12 string(render scene {
:format :gcode}) → GRBL G-code string(render scene {
:format :hpgl}) → HPGL plotter string(render scene {
:format :polylines}) → {:polylines [...] :bounds [w h]}Animation (sequence of scenes):
(render frames {
:output "a.gif" :fps 30}) → animated GIF(render frames {
:output "a.svg" :fps 30}) → animated SVG file(render frames {
:output "dir/" :fps 30}) → PNG sequence(render frames {
:format :svg :fps 30}) → animated SVG stringCommon opts:
:scale, :transparent-background, :quality (JPEG), :dpi (PNG/TIFF),:tiff/compression (:lzw :deflate :none),:loop (GIF, default true), :prefix (frame sequence).Validation: scenes are validated before compilation by default. Bind
*validate* to false for faster REPL iteration, or set
:eido/validatefalse on the scene map.
(render-animation scenes dir)(render-animation scenes dir opts)Returns a vector of written file paths.
Opts:
:scale, :transparent-background, :prefix (default "frame-").(render-batch jobs)(render-batch generate-fn n):scene, :path, and optional :opts. Returns a vector of written paths.With a generator fn and count, calls (f i) for each index.
(render-file path)(render-from-manifest path)(render-from-manifest path override-opts)Override keys in opts to change output path, format, etc.
(render-to-animated-svg scenes path opts)Opts:
:fps (required), :scale, :transparent-background.(render-to-animated-svg-str scenes opts)Opts:
:fps (required), :scale, :transparent-background.(render-to-file scene path)(render-to-file scene path opts)Supported formats: PNG, JPEG, GIF, BMP, TIFF, SVG, DXF, G-code, HPGL.
Opts:
:format, :quality (JPEG), :scale, :transparent-background,:dpi (PNG/TIFF), :tiff/compression (:lzw :deflate :none),:emit-manifest? (write EDN sidecar for reproducibility).DXF/G-code/HPGL also accept
:flatness, :segments, :optimize-travel,and any writer-specific keys (see eido.io.dxf, eido.io.gcode,
eido.io.hpgl).
(render-to-gif scenes path opts)Opts:
:fps (required), :scale, :transparent-background, :loop (default true).(render-to-svg scene)(render-to-svg scene opts)Opts:
:scale, :transparent-background, :stroke-only, :group-by-stroke,:deduplicate, :optimize-travel.(validate scene)Returns nil if valid, or a vector of error maps with
:path, :pred, :message, and :value.eido.path
Path operations: boolean ops (union, intersection, difference, xor) plus re-exports from sub-namespaces: eido.path.stroke — stroke profiles & expansion eido.path.distort — noise/wave distortion eido.path.warp — twist/fisheye/bend/bulge eido.path.morph — path interpolation eido.path.decorate — path decoration
(chaikin-commands commands opts)Produces rounder, more uniform curves than Catmull-Rom.
opts:
:iterations (3), :retain-ends (true).(contains-point? polygon [px py])Uses the ray-casting algorithm (count horizontal ray crossings).
(dash-commands commands opts)opts:
:dash [on-length off-length] — required:offset (0.0) — shift the pattern startReturns a vector of path-command vectors, one per dash.
(decorate-path path-cmds shape opts)opts:
:spacing (required), :rotate? (default false).Returns a vector of group nodes with transforms.
(difference cmds-a cmds-b)(distort-commands commands opts)opts keys:
:type (:noise, :wave, :roughen, :jitter)For
:noise — :amplitude, :frequency, :seedFor
:wave — :axis (:x or :y), :amplitude, :wavelengthFor
:roughen/:jitter — :amount, :seed(ink-preset seed)Moderate Chaikin smoothing with organic jitter.
(inset polygon d)Returns a vector of [[x y] ...] points.
Works correctly for convex polygons; concave polygons may produce
self-intersecting results.
(interpolate commands-a commands-b t)Both paths must have the same number and type of commands.
Returns blended path commands.
(intersection cmds-a cmds-b)(jittered-commands commands opts)Resamples for uniform point density, then applies jitter distortion.
opts:
:amount (3.0), :density (1.0) — approximate spacing between points,:seed (0)(morph commands-a commands-b t)Both must have the same number of commands and matching types.
(morph-auto commands-a commands-b t)Works with any two closed or open paths.
(outline-commands path-cmds profile max-width)path-cmds: scene-format path commands ([
:move-to [x y]] ...)profile: keyword or [[t width-factor] ...] pairs
max-width: the maximum stroke width (profile scales this)
(pencil-preset seed)Light smoothing, fine jitter, short dashes for sketch feel.
(resample commands n)Flattens curves to line segments first.
(resolve-profile profile)or passes through a vector.
(shape->path-commands node)(simplify points epsilon)Removes points that contribute less than epsilon to the shape.
(simplify-commands commands epsilon)Wraps simplify on the extracted points and rebuilds commands.
(smooth-commands commands opts)opts:
:samples (32) — resample count before fitting.(split-at-length commands segment-length)Returns a vector of path-command vectors, one per segment.
(stylize commands steps)Wraps smooth-commands, jittered-commands, dash-commands, chaikin-commands.
steps: vector of {
:op :smooth/:jitter/:dash/:chaikin, ...opts}.Example: (stylize cmds [{
:op :chaikin :iterations 3} {:op :dash :dash [10 5]}])(trim-to-bounds commands bounds)bounds: [x y w h] clipping region.
Returns a vector of path-command vectors (one per visible segment).
Flattens curves to line segments before clipping.
(union cmds-a cmds-b)(warp-commands commands spec)(warp-node node spec)(watercolor-preset seed)Heavy Chaikin smoothing with pronounced jitter for bleeding edges.
(width-at profile t)Profile is a vector of [t width] pairs, sorted by t.
(xor cmds-a cmds-b)eido.scene
Declarative scene construction helpers. Functions for building scene nodes: text, shapes, grids, radial layouts, and paper presets. Returns plain maps that compose with the scene data format — no special types or wrappers.
(circle-node center radius)(circle-node center radius fill):node/type :shape/circle ...} map.Example: (circle-node [200 200] 50 [
:color/name "red"])(distribute n [x1 y1] [x2 y2] f)f receives (x y t) where t is the normalized parameter [0.0, 1.0].
For n=1, places at the midpoint. For n>1, includes both endpoints.
(grid cols rows f)f receives (col row) and must return a node map (or nil to skip).
Cells are visited row-major: (0,0) (1,0) (2,0) ... (0,1) (1,1) ...
(line-node from to)(line-node from to stroke):node/type :shape/line ...} map.stroke is a map with
:color and :width keys.Example: (line-node [0 0] [100 100] {
:color [:color/name "black"] :width 2})(paper size & {:keys [landscape dpi], :or {landscape false, dpi 300}})Keyword args:
:landscape (false), :dpi (300).The returned map includes
:image/size, :image/units, and :image/dpi —pass through with-units before rendering.
Example:
(paper
:a4) ;=> {:image/size [21.0 29.7] :image/units :cm :image/dpi 300}(paper
:letter :landscape true) ;=> {:image/size [11.0 8.5] :image/units :in :image/dpi 300}paper-sizesWidth and height are in the specified unit.
(points->path points)(points->path points closed?)Convenience for (into [[
:move-to p0]] (mapv (fn [p] [:line-to p]) rest)).(polar->xy [cx cy] radius angle)Wraps the trig: (+ cx (* r (cos a))), (+ cy (* r (sin a))).
(polygon points)(radial n [cx cy] radius f)f receives (x y angle) where angle is in radians [0, 2*pi).
Angles start from the top (12 o'clock) and proceed clockwise.
(rect-node xy size)(rect-node xy size fill):node/type :shape/rect ...} map.Example: (rect-node [10 10] [100 50] [
:color/name "blue"])(regular-polygon [cx cy] radius n)with the given radius. First vertex is at the top (12 o'clock).
(ring n [cx cy] radius shape)Convenience for (radial n [cx cy] radius (fn [x y _] shape-with-translate)).
(smooth-path points)Catmull-Rom to cubic bezier conversion. Returns a path node.
(star [cx cy] outer-radius inner-radius n)outer-radius is the distance to the tips, inner-radius to the inner vertices.
(text content origin font-spec)(text-clip content [ox oy] font-spec children)text shape — anything inside the letters shows through.
(text-glyphs content origin font-spec glyph-overrides)each with
:glyph/index and optional :style/fill, :style/stroke,:node/transform, :node/opacity.(text-on-path content path-commands font-spec)as
:shape/path — [[:move-to [x y]] [:curve-to ...] ...].(text-outline content [ox oy] font-spec)Useful as a clip mask, for boolean ops, or as a standalone shape.
(text-stack content origin font-spec layers)layers is a vector of style maps applied to copies of the same text.
Earlier layers render behind later ones.
(triangle p1 p2 p3)(with-margin scene margin)Margin is the distance in pixels from each edge.
Uses existing
:group/clip infrastructure — no new rendering machinery.(with-units scene)Reads
:image/units (:cm, :mm, or :in) and :image/dpi from the scene,walks the scene tree scaling all spatial values by the conversion factor.
Strips
:image/units from the result; retains :image/dpi for metadata embedding.The core rendering pipeline remains pixel-based — this is a preprocessing step.
Example:
(-> (paper
:a4)(assoc
:image/background :white:image/nodes [...])with-units)
eido.text
Text-to-path conversion for artistic typography. Converts text nodes into standard Eido path nodes via Java 2D font APIs. No external dependencies — uses JDK built-in Font, GlyphVector, PathIterator.
(flatten-commands commands)(flatten-commands commands flatness)(glyph-contours commands)Returns [[cmd ...] [cmd ...] ...], one vector per contour.
(path-length commands)(point-at commands distance):point [x y] :angle rad} at a given distance along path commands.resolve-font(text->glyph-paths content font-spec)Returns [{
:commands [...] :position [x y]} ...], one entry per glyph.Commands are relative to each glyph's own origin (not layout position).
:position gives the glyph's layout position within the string.(text->path-commands content font-spec)Returns at the origin [0 0]; caller positions via
:text/origin.(text-advance content font-spec)(text-glyphs-node->group node):shape/text-glyphs node into a :group with one :shape/path per glyph.(text-node->group node):shape/text node into a :group with a single :shape/path child.(text-on-path-node->group node):shape/text-on-path node into a :group with glyphs along a path.eido.path.stroke
Stroke profiles and variable-width path expansion. Apply named or custom width profiles to convert open paths into filled outlines.
(outline-commands path-cmds profile max-width)path-cmds: scene-format path commands ([
:move-to [x y]] ...)profile: keyword or [[t width-factor] ...] pairs
max-width: the maximum stroke width (profile scales this)
(resolve-profile profile)or passes through a vector.
(width-at profile t)Profile is a vector of [t width] pairs, sorted by t.
eido.path.distort
Point-level path distortion using noise, waves, roughening, and jitter. Each distortion displaces individual points without changing path topology.
(distort-commands commands opts)opts keys:
:type (:noise, :wave, :roughen, :jitter)For
:noise — :amplitude, :frequency, :seedFor
:wave — :axis (:x or :y), :amplitude, :wavelengthFor
:roughen/:jitter — :amount, :seedeido.path.warp
Geometric coordinate warps: twist, fisheye, bulge, bend, and wave. Each warp remaps point positions through a spatial transformation.
(shape->path-commands node)(warp-commands commands spec)(warp-node node spec)eido.path.morph
Path interpolation and shape morphing. Blends between two paths by resampling them to equal point counts and interpolating positions.
(morph commands-a commands-b t)Both must have the same number of commands and matching types.
(morph-auto commands-a commands-b t)Works with any two closed or open paths.
(resample commands n)Flattens curves to line segments first.
eido.path.decorate
Place copies of a shape at regular intervals along a path, optionally rotating each copy to follow the path tangent.
(decorate-path path-cmds shape opts)opts:
:spacing (required), :rotate? (default false).Returns a vector of group nodes with transforms.
eido.path.aesthetic
High-level path aesthetic helpers: smoothing, jitter, and dashing. Operates on path commands and returns path commands.
(chaikin-commands commands opts)Produces rounder, more uniform curves than Catmull-Rom.
opts:
:iterations (3), :retain-ends (true).(dash-commands commands opts)opts:
:dash [on-length off-length] — required:offset (0.0) — shift the pattern startReturns a vector of path-command vectors, one per dash.
(ink-preset seed)Moderate Chaikin smoothing with organic jitter.
(jittered-commands commands opts)Resamples for uniform point density, then applies jitter distortion.
opts:
:amount (3.0), :density (1.0) — approximate spacing between points,:seed (0)(pencil-preset seed)Light smoothing, fine jitter, short dashes for sketch feel.
(smooth-commands commands opts)opts:
:samples (32) — resample count before fitting.(stylize commands steps)Wraps smooth-commands, jittered-commands, dash-commands, chaikin-commands.
steps: vector of {
:op :smooth/:jitter/:dash/:chaikin, ...opts}.Example: (stylize cmds [{
:op :chaikin :iterations 3} {:op :dash :dash [10 5]}])(watercolor-preset seed)Heavy Chaikin smoothing with pronounced jitter for bleeding edges.
eido.color
Color parsing, conversion, and manipulation. See also eido.color.palette for color harmonies & gradients.
(contrast color-a color-b)Returns a double >= 1.0 (1 = identical, 21 = black/white).
Accepts any color form (vectors, keywords, maps).
(darken color amount)(desaturate color amount)(hsl h s l):color/hsl h s l]. Wraps hue with mod 360.(lerp color-a color-b t)(lerp color-a color-b t opts)Accepts color vectors or maps; returns a color vector.
Optional opts map: {
:space :oklab} for perceptually uniform interpolation.(lerp-oklab color-a color-b t)Wraps (lerp color-a color-b t {
:space :oklab}).(lighten color amount)(mix-subtractive color-a color-b t)Blue + yellow = green, red + blue = purple, etc.
color-a, color-b: [r g b] in linear RGB [0..1] float space.
t: mix ratio (0.0 = all color-a, 1.0 = all color-b).
Uses a reflectance multiplication model: pigments absorb light,
so mixing pigments multiplies their reflectance spectra. Approximated
by geometric mean: result_ch = a_ch^(1-t) * b_ch^t.
named-colors(oklab L a b):color/oklab L a b].(oklch L C h):color/oklch L C h].(perceptual-distance color-a color-b)Returns a double >= 0.0 (0 = identical colors).
More perceptually meaningful than RGB distance.
Accepts any color form (vectors, keywords, maps).
(resolve-color color):r :g :b :a keys.Accepts tagged vectors ([
:color/rgb 255 0 0], [:color/name "red"])or bare keywords (
:red, :cornflowerblue) as shorthand for named colors.(rgb r g b):color/rgb r g b].(rgb->hsl r g b)(rgb->oklab r g b)L: 0-1 (lightness), a: ~-0.4 to 0.4, b: ~-0.4 to 0.4.
(rgb->oklch r g b)L: 0-1, C: 0-0.4+, h: 0-360 degrees.
(rotate-hue color degrees)(saturate color amount)eido.color.palette
Color harmony algorithms and palette generation. Provides complementary, analogous, triadic, and other schemes plus palette manipulation utilities.
(adjust palette opts)Wraps warmer/cooler/muted/vivid/darker/lighter.
opts keys:
:warmer, :cooler, :muted, :vivid, :darker, :lighter.(analogous c n)(complementary c)(cooler palette amount)(darker palette amount)(from-image img k)(from-image img k opts)clustering in OKLAB perceptual color space. Returns a palette vector
sorted from dark to light.
img: BufferedImage or file path string.
opts:
:samples (1000), :seed (0), :max-iter (20).(gradient-map stops t)(gradient-map stops t opts)stops: [[pos color] ...] sorted ascending by pos.
Optional opts: {
:easing fn} applies an easing function to t before lookup.Returns a color vector.
(gradient-palette start end n)(lighter palette amount)(min-contrast palette)Wraps (color/contrast) over all pairs. Useful for checking readability.
(monochromatic c n)(muted palette amount)palettes(shuffle-palette palette seed)(sort-by-lightness palette)Wraps (sort-by (fn [c] (first (color/rgb->oklab ...))) palette).
(split-complementary c)(swatch palette)(swatch palette opts)Useful with
show at the REPL for quick visual feedback.opts:
:width (400), :height (60).(tetradic c)(triadic c)(vivid palette amount)(warmer palette amount)(weighted-gradient palette weights)Returns stops [[pos color] ...] suitable for gradient-map.
palette and weights must have the same length.
(weighted-pick palette weights seed)palette: vector of color vectors.
weights: vector of positive numbers (same length as palette).
seed: long for deterministic selection.
(weighted-sample palette weights n seed)(with-roles roles palette)Wraps (zipmap roles palette).
Example: (with-roles [
:bg :primary :accent] pal) => {:bg c1 :primary c2 :accent c3}eido.gen.noise
Noise generators: Perlin, simplex, value noise, FBM, turbulence, and ridge. Building blocks for organic textures, flow fields, and terrain-like forms.
(fbm noise-fn x y)(fbm noise-fn x y opts)noise-fn must accept (x y) or (x y opts) and return a double.
Options:
:octaves (4), :lacunarity (2.0), :gain (0.5), :seed.(perlin2d x y)(perlin2d x y opts)Optionally accepts {
:seed n} for a seeded permutation table.(perlin3d x y z)(perlin3d x y z opts)Useful for animating noise (use time as z).
Optionally accepts {
:seed n}.(perlin4d x y z w)(perlin4d x y z w opts)Essential for seamlessly looping animated noise.
Looping trick: (perlin4d x y (* r (cos t)) (* r (sin t))).
Optionally accepts {
:seed n}.(preview noise-fn)(preview noise-fn opts)noise-fn: (fn [x y] -> double), expected range [-1, 1].
Useful with
show at the REPL for tuning noise parameters.opts:
:width (256), :height (256), :scale (0.02).(ridge noise-fn x y)(ridge noise-fn x y opts)Same options as fbm, plus
:offset (1.0).(simplex2d x y)(simplex2d x y opts)Fewer directional artifacts than Perlin noise.
Optionally accepts {
:seed n}.(simplex3d x y z)(simplex3d x y z opts)Optionally accepts {
:seed n}.(simplex4d x y z w)(simplex4d x y z w opts)Essential for seamlessly looping animated noise.
Looping trick: (simplex4d x y (* r (cos t)) (* r (sin t))).
Optionally accepts {
:seed n}.(turbulence noise-fn x y)(turbulence noise-fn x y opts)Returns non-negative values. Same options as fbm.
eido.gen.flow
Flow field path generation from noise-based vector fields. Traces streamlines with optional collision avoidance for even spacing.
(flow-field bounds opts)bounds: [x y w h] region.
Returns a vector of
:shape/path nodes (streamlines).opts:
:density (20), :step-length (2.0), :steps (50),:noise-scale (0.005), :seed (0), :min-length (3),:collision-distance (nil — set to enforce minimum spacing between streamlines).eido.gen.contour
Marching squares contour extraction from scalar fields. Produces connected iso-lines at specified thresholds for topographic effects.
(contour-lines noise-fn bounds opts)noise-fn: (fn [x y opts] -> double). bounds: [x y w h].
Returns a vector of
:shape/path nodes.opts:
:thresholds ([0.0]), :resolution (5), :noise-scale (0.01), :seed (0).eido.gen.scatter
Point distribution algorithms: regular grids, Poisson disk sampling, and noise-biased placement. Includes jitter and node expansion.
(grid bounds cols rows)bounds: [x y w h].
(jitter points opts)Returns [[x' y'] ...]. opts:
:amount (required), :seed (default 0).Amount controls displacement magnitude: 0 = no change, higher = more
disorder. Uses Gaussian for natural feel.
(noise-field bounds opts)bounds: [x y w h]. opts:
:n (required), :seed (default 0).Points are placed where noise value exceeds a threshold.
(poisson-disk bounds opts)bounds: [x y w h]. opts:
:min-dist (required), :seed (default 0).Delegates to eido.gen.stipple/poisson-disk.
(scatter->nodes shape positions jitter)jitter: nil or {
:x dx :y dy :seed s} for random displacement.eido.gen.voronoi
Voronoi diagram and Delaunay triangulation from seed points. Produces cell polygons and dual-graph edges for territorial partitions.
(delaunay-edges points bounds)bounds: [x y w h] clipping region.
Derived from Voronoi: two seeds are neighbors if their cells share an edge.
(voronoi-cells points bounds)bounds: [x y w h] clipping region.
Returns a vector of
:shape/path nodes (closed polygons), one per point.Uses half-plane intersection: O(n^2) per cell.
eido.gen.lsystem
Lindenmayer systems: string rewriting and turtle-graphics interpretation. Generates branching, fractal, and botanical structures from simple rules. Rules can be plain strings (classic L-system) or vectors of alternatives (constrained L-system). When alternatives are provided with :bounds, the system searches for rule choices that keep growth within the canvas. Symbols: F=draw, G=move, +=turn right, -=turn left, [=push, ]=pop, |=reverse.
bushcoral(expand-string axiom rules iterations)Characters not in rules pass through unchanged.
Rules can be strings (classic) or vectors of strings (uses first alternative).
fern(interpret expanded opts)Returns scene-format path commands.
opts:
:angle (degrees), :length, :origin [x y], :heading (degrees).lightning(lsystem->path-cmds axiom rules opts)Returns path commands.
opts:
:iterations — number of expansion steps (default 3):angle — turn angle in degrees:length — step length:origin — [x y] start position (default [0 0]):heading — initial direction in degrees (default 0)When rules contain vector alternatives (e.g. {"F" ["FF+F" "F" ""]}):
:bounds [x y w h] — canvas constraint; growth stays within.Result is scaled to fill the bounds.
:seed (42) — controls which rule choices are made whenthe full expansion overflows bounds.
seaweedtreeeido.gen.particle
Particle systems with emitters, forces, and over-lifetime curves. Supports 2D and 3D simulation with built-in presets for fire, snow, and more.
confettiNote: uses per-particle random colors from
:particle/colors palette.firefountain(render-frame state config)(render-frame state config opts)Optionally override the projection for this frame (useful for orbiting cameras).
state: a simulation state from
statesconfig: the particle system configuration map
opts: optional {
:projection proj} to override :particle/projection for this frame(simulate config n opts)Each element is a vector of Eido node maps ready for
:image/nodes.config: particle system configuration map
n: number of frames to produce
opts: {
:fps 30} — frames per second (determines time step)Returns a lazy seq of n vectors. Use vec to realize for indexed access.
smokesnowsparks(states config n opts)Each state contains
:particles (internal particle maps with :pos, :vel, :age, etc.).Use this when you need per-frame control over rendering, e.g. orbiting cameras
for 3D particles. Pair with render-frame to convert states to nodes.
config: particle system configuration map
n: number of frames to produce
opts: {
:fps 30} — frames per second (determines time step)Returns a lazy seq of n state maps.
(with-position config pos)(with-seed config seed)eido.gen.stipple
Poisson disk sampling and stipple fills. Generates well-distributed dot patterns for shading and texture.
(poisson-disk bounds opts)bounds: [x y w h] region. opts:
:min-dist (required), :seed (default 0).Returns a vector of [x y] within the bounds.
(stipple-fill->nodes bounds spec)bounds: [x y w h] region.
spec:
:stipple/density (0-1), :stipple/radius, :stipple/seed,:stipple/color.eido.gen.hatch
Cross-hatch line patterns for pen-plotter-style fills. Generates parallel lines at arbitrary angles with multi-layer support.
(hatch-fill->nodes bounds spec)bounds: [x y w h]. Each line becomes a path node with the specified stroke.
Spec keys:
:hatch/angle, :hatch/spacing, :hatch/stroke-width,:hatch/color, :hatch/layers [{:angle :spacing} ...].(hatch-lines bounds {:keys [angle spacing], :or {angle 45, spacing 5}})bounds: [x y w h]. opts:
:angle (45), :spacing (5).eido.gen.vary
Per-item style variation: color, opacity, and transform overrides driven by index, position, noise, or gradient interpolation.
(apply-overrides children overrides)Each override map is merged onto the first child of the group at index i.
Wraps via mod when overrides is shorter than children.
(by-gradient n stops)stops: [[pos color] ...] for palette/gradient-map.
(by-index n f)f should return a map of node attribute overrides.
(by-noise positions f opts)Calls (f noise-value) where noise-value is in [-1, 1].
opts:
:noise-scale (required), :seed (default 0).(by-noise-palette positions palette opts)opts:
:noise-scale (required), :seed (default 0).Wraps (by-noise positions f opts).
(by-palette n palette)(by-palette n palette opts)opts:
:seed (default 0), :weights (optional weight vector).Wraps (by-index n (fn [i] {
:style/fill ...})).(by-position positions f)f should return a map of node attribute overrides.
eido.gen.prob
Seeded probability distributions and sampling utilities. All functions take an explicit seed (long) for deterministic, reproducible results. No global RNG state is used.
(coin p seed)(gaussian n mean sd seed)(in-circle radius seed)(in-circle radius [cx cy] seed)Uses the sqrt trick for uniform area distribution.
(in-sphere radius seed)(in-sphere radius [cx cy cz] seed)Uses the Gaussian method + cbrt trick for uniform volume distribution.
(make-rng seed)(mixture sources mix-weights n seed)Wraps weighted-choice to select which source to draw from.
Example: (mixture [(uniform 100 1 5 s1) (gaussian 100 20 3 s2)] [3 1] 50 seed)
(on-circle radius seed)(on-circle radius [cx cy] seed)Uniformly distributed angle.
(on-sphere radius seed)(on-sphere radius [cx cy cz] seed)Uses the Gaussian method to avoid polar clustering.
(pareto n alpha min-val seed)Wraps (sample-n {
:type :pareto ...}).(pick coll seed)Returns nil if coll is empty.
(pick-weighted items weights seed)Returns nil if items is empty.
(sample spec seed)Spec is a plain map with
:type and type-specific keys:{
:type :uniform :lo 0.0 :hi 1.0}{
:type :gaussian :mean 0.0 :sd 1.0}{
:type :choice :options [:a :b :c]}{
:type :weighted-choice :options [:a :b] :weights [3 1]}{
:type :boolean :probability 0.5}{
:type :pareto :alpha 2.0 :min 1.0} ;; optional :max{
:type :triangular :min 0 :max 1 :mode 0.5}{
:type :eased :easing fn :lo 0 :hi 1}Same spec format used by eido.gen.series/series-params.
(sample-n spec n seed)Each value gets a deterministic sub-seed derived from the base seed
and its index, ensuring independent samples.
(scatter-in-circle n radius center seed)Wraps repeated in-circle calls with independent sub-seeds.
(scatter-on-circle n radius center seed)Wraps repeated on-circle calls with independent sub-seeds.
(shuffle-seeded coll seed)(triangular n min-val max-val mode seed)Wraps (sample-n {
:type :triangular ...}).(uniform n lo hi seed)(weighted-choice weights seed)(weighted-sample n weights seed)eido.gen.circle
Circle packing: variable-radius non-overlapping circle placement. Uses greedy rejection sampling with spatial grid acceleration.
(circle-pack bounds opts)Returns a vector of {
:center [x y] :radius r} maps.opts:
:min-radius (2.0) — smallest circle:max-radius (40.0) — largest circle:padding (1.0) — gap between circles:attempts (500) — max failed attempts before stopping:max-circles (1000) — cap on total circles:seed (42):bounds-fn — optional (fn [x y] -> boolean) for non-rectangular containment(circle-pack-in-path path-commands opts)Uses java.awt.geom.Area for containment testing.
(pack->colored-nodes circles palette)(pack->colored-nodes circles palette opts)opts:
:seed (default 0), :weights (optional), :style (optional base style map).Wraps (pack->nodes circles) + (palette/weighted-sample palette).
(pack->nodes circles opts)opts:
:style (base style map applied to each circle)eido.gen.subdivide
Recursive rectangular subdivision for compositional layouts. Produces Mondrian-style grids and binary space partitions.
(subdivide bounds opts)Returns a vector of {
:rect [x y w h] :depth n} maps.opts:
:depth (4) — max recursion depth:min-size (20.0) — stop splitting below this dimension:split-range [0.3 0.7] — random split ratio range:h-bias (0.5) — probability of horizontal split (vs vertical):padding (0.0) — gap between sub-rects:seed (42)(subdivide->nodes rects color-fn)color-fn: (fn [{
:rect [x y w h] :depth n}] -> color).(subdivide->palette-nodes rects palette)(subdivide->palette-nodes rects palette opts)opts:
:seed (default 0), :style (optional base style map).Wraps (subdivide->nodes rects (fn [...] (prob/pick palette seed))).
eido.gen.series
Long-form generative series utilities. Deterministic seed derivation and parameter sampling for numbered editions (Art Blocks / fxhash style workflows).
(derive-traits params buckets)Wraps a simple threshold lookup over a params map.
buckets: {
:param [[threshold label] ...]}Example: (derive-traits {
:density 42} {:density [[20 "sparse"] [40 "medium"] [100 "dense"]]})(edition-seed master-seed edition-number)from a master seed. Uses murmur3-style mixing so nearby editions
produce independent seeds.
(export-edition-package {:keys [spec master-seed start end scene-fn output-dir format render-opts traits contact-sheet? contact-cols thumb-size], :or {contact-sheet? true, contact-cols 5, thumb-size [160 160]}})opts: same as render-editions, plus:
:contact-sheet? — generate a grid thumbnail image (default true):contact-cols — columns in contact sheet (default 5):thumb-size — per-thumbnail size (default [160 160])Returns {
:editions [...] :contact-sheet path-or-nil}.(load-seeds path)Returns a vector of maps in append order, or [] if the file does not exist.
(param-grid {:keys [base-params row-param col-param seed scene-fn thumb-size]})Varies one param across rows, optionally another across columns.
Pass the result to show at the REPL.
opts:
:base-params — base parameter map:row-param — {:key :param-name :values [v1 v2 ...]}:col-param — {:key :param-name :values [v1 v2 ...]} (optional, default 1 col):seed — seed for scene generation:scene-fn — (fn [params] scene-map) — takes merged params, returns scene:thumb-size — [width height] per thumbnail (default [160 160])(render-editions {:keys [spec master-seed start end scene-fn output-dir format render-opts traits emit-manifest?]})opts:
:spec — parameter spec map (as for series-params):master-seed — master seed for the series:start — first edition number (inclusive):end — last edition number (exclusive):scene-fn — (fn [params edition-number] scene-map):output-dir — directory to write files into:format — :png (default) or :svg:render-opts — optional map passed to eido.core/render (e.g. {:scale 2}):traits — optional trait buckets for derive-traits:emit-manifest? — write per-edition .edn sidecar manifests (default false)Returns a vector of {
:edition n :params params :traits traits :file path}.(save-seed! path entry)entry should contain at least
:seed; :params and :note are optional.Adds
:timestamp automatically. Accumulates one EDN form per line.(seed-grid {:keys [spec master-seed start end seeds scene-fn cols thumb-size]})Each cell shows a different seed; pass the result to show at the REPL.
opts:
:spec — parameter spec map:master-seed — master seed for the series:start — first edition number (inclusive, default 0):end — last edition number (exclusive):seeds — explicit list of edition numbers (overrides start/end):scene-fn — (fn [params edition-number] scene-map):cols — number of columns (default 5):thumb-size — [width height] per thumbnail (default [160 160])(series-params spec master-seed edition-number)spec: map of {
:param-name {:type :uniform/:gaussian/:choice/:weighted-choice/:boolean, ...}}Each parameter gets a deterministic sub-seed derived from the edition seed
and a hash of the parameter name.
(series-range spec master-seed start end)(trait-summary spec master-seed n-editions trait-buckets)Returns {
:trait-name {"label" count ...} ...} — pure data for REPL inspection.Useful for verifying that rare traits are actually rare before releasing.
eido.gen.ca
Cellular automata and Gray-Scott reaction-diffusion simulation. Grid-based evolution systems for organic pattern generation.
(ca->nodes {:keys [grid w h]} cell-size alive-style)alive-style: style map for alive cells (e.g., {
:style/fill color}).cell-size: pixel size per cell.
(ca-grid w h init seed)init:
:random (seeded), :empty, or :center (single live cell).Returns {
:grid boolean-array :w w :h h}.(ca-run grid-map rule n)(ca-step {:keys [grid w h]} rule)rule:
:life, :highlife, or {:birth #{...} :survive #{...}}.(rd->nodes {:keys [a b w h]} cell-size color-fn)color-fn: (fn [a-val b-val] -> color-vector).
(rd-grid w h init seed)init:
:center (circle of B in center), :random (scattered seeds).Returns {
:a double-array :b double-array :w w :h h}.rd-presetsAll produce visible patterns within 500-2000 steps on 100x100+ grids.
(rd-run rd-map params n)(rd-step {:keys [a b w h]} params)params: {
:feed f :kill k :da da :db db :dt dt}.eido.gen.boids
Boids flocking simulation with steering behaviors. Separation, alignment, cohesion, plus optional seek/flee/wander. Uses spatial grid for efficient neighbor lookup.
(alignment boid neighbors radius strength)classic(cohesion boid neighbors radius strength)(flee boid target flee-radius strength)(flock->nodes {:keys [boids]} opts)opts:
:shape (:triangle or :circle), :size (6), :style (style map).(init-flock opts)opts:
:count (50), :bounds [bx by bw bh], :max-speed (2.0), :seed (42).Returns {
:boids [...] :tick 0}.murmuration(seek boid target max-speed strength)(separation boid neighbors radius strength)(simulate-flock config n opts)(step-flock {:keys [boids tick]} config)eido.gen.coloring
Graph coloring via constraint satisfaction. Assigns colors to regions (Voronoi cells, subdivision rects, or any indexed set with adjacency) such that no two adjacent regions share a color. Uses core.logic CLP(FD) for the constraint solver. Primary function: `color-regions` — takes scene nodes, adjacency, and a palette, returns nodes with :style/fill applied. The solver guarantees no two adjacent regions share a color. Creative control: :seed — different seeds produce different valid colorings :pin — fix specific regions to specific colors; the solver completes the rest consistently
(cells-adjacency cells)Two regions are adjacent if they share 2+ vertices (within epsilon).
Returns a set of [i j] pairs (i < j).
(color-regions nodes adjacency palette)(color-regions nodes adjacency palette opts)nodes: vector of scene nodes
adjacency: collection of [i j] pairs
palette: vector of colors
opts:
:seed (0) — shuffles palette assignment for variety:pin {idx color} — fix specific regions to specific colors;the solver completes the rest consistently
Returns nodes with
:style/fill applied, or nil if no valid coloring exists.(rects-adjacency rects)Two rects are adjacent if they share an edge.
rects: vector of {
:rect [x y w h]} maps.Returns a set of [i j] pairs (i < j).
eido.texture
Texture and material helpers for organic rendering effects. These helpers produce scene nodes (groups with deformed, layered copies) for simulating translucent media like watercolor, ink wash, and gouache.
(layered shape-node opts)Simulates watercolor, ink wash, and other translucent media.
opts:
:layers (required), :opacity (required), :deform-fn (required),:seed (default 0).deform-fn: (fn [shape-node layer-index seed] -> shape-node).
Each layer gets a unique sub-seed derived from the base seed.
(watercolor path-node opts)Returns a group node simulating watercolor wash.
opts:
:layers (30), :opacity (0.04), :amount (3.0), :seed (0).eido.paint
Procedural paint engine for Eido. Provides declarative brush specifications, stroke constructors, and paint surface configuration. Integrates with the standard Eido rendering pipeline — paint surfaces appear as scene nodes alongside shapes, groups, and generators. Three entry points: 1. Standalone paint surface — {:node/type :paint/surface ...} 2. Paint parameters on paths — {:paint/brush :chalk ...} on any path 3. Group modifier — {:paint/surface {...}} on a group for shared surfaces
(auto-pressure points)(auto-pressure points opts)points: [[x y] ...] — point sequence.
opts: {
:mode :taper (default), :start 0.3, :end 0.2}Returns [[t pressure] ...] suitable for
:paint/pressure.(brush spec)(brush preset overrides)(brush
:chalk)(brush
:chalk {:brush/paint {:paint/opacity 0.2}})(brush {
:brush/type :brush/dab ...})(circle-points center)(circle-points center opts)center: [cx cy].
opts: {
:radius 50, :n 20, :start 0.0, :end (* 2 PI), :pressure 0.8}Returns [[x y pressure 0 0 0] ...] suitable for
:paint/points.(compose surface)(fill-ellipse center)(fill-ellipse center opts)center: [cx cy].
opts: {
:rx 50, :ry 30, :brush :oil, :color [...], :radius 8.0,:density 12, :seed 0}Returns a vector of stroke descriptors for
:paint/strokes.(fill-rect bounds)(fill-rect bounds opts)bounds: [x y w h].
opts: {
:brush :chalk, :color [...], :radius 8.0, :density 15, :seed 0}Returns a vector of stroke descriptors for
:paint/strokes.(line-points from)(line-points from opts)from: [x0 y0].
opts: {
:to [x1 y1], :n 15, :pressure 0.8}Returns [[x y pressure 0 0 0] ...].
(make-surface config)Accepts [w h], {
:paint/size [w h]}, or {:size [w h]}.(paint-group children)(paint-group children opts)children: painted path nodes or generators with paint params.
opts: {
:substrate {:substrate/tooth 0.4}}(paint-surface strokes)(paint-surface strokes opts)strokes: vector of stroke descriptors.
opts: {
:size [w h], :substrate {:substrate/tooth 0.4}, :children [nodes]}(painted-path points opts)points: [[x y] ...] — auto-smoothed via Catmull-Rom, or path commands.
opts: {
:brush :ink, :color [...], :radius 8.0, :pressure [[t p] ...], :opacity 0.5}presets(render-stroke! surface stroke-desc)(render-stroke! surface stroke-desc substrate-spec)stroke-desc: {
:stroke/brush :stroke/color :stroke/points :stroke/seed}or path-based: {
:paint/brush :paint/color :path/commands :paint/pressure}Returns nil (mutates surface).
substrate-spec: optional substrate from the surface config.
(render-strokes! surface strokes)(render-strokes! surface strokes substrate-spec)(resolve-brush brush)Accepts a keyword (preset name), a spec map, or nil (returns default).
(stroke points opts):paint/strokes.points: [[x y pressure speed tilt-x tilt-y] ...]
opts: {
:brush :chalk, :color [...], :radius 12.0, :seed 42}(stroke-from-path path-commands opts)pressure. Convenience for composing paths with paint.
path-commands: [[
:move-to [x y]] [:line-to [x y]] ...]opts: {
:brush :chalk, :color [...], :radius 12.0,:pressure :taper (or :curvature, or explicit curve), :seed 42}(wave-points from)(wave-points from opts)from: [x0 y0].
opts: {
:to [x1 y1], :amplitude 15, :frequency 0.15, :n 20, :pressure 0.7}Returns [[x y pressure 0 0 0] ...].
eido.animate
Easing, interpolation, and timing functions for animation. Easing functions take a normalized t in [0,1] and return a shaped t. Compose with `lerp` for value interpolation, or use `frames`, `stagger`, and `cycle-n` for sequencing multi-frame animations.
(cycle-n n t)E.g., (cycle-n 2 0.5) completes one full cycle by midpoint.
(ease-in t)(ease-in-back t)(ease-in-bounce t)(ease-in-circ t)(ease-in-cubic t)(ease-in-elastic t)(ease-in-expo t)(ease-in-out t)(ease-in-out-back t)(ease-in-out-bounce t)(ease-in-out-circ t)(ease-in-out-cubic t)(ease-in-out-elastic t)(ease-in-out-expo t)(ease-in-out-quart t)(ease-in-quart t)(ease-out t)(ease-out-back t)(ease-out-bounce t)(ease-out-circ t)(ease-out-cubic t)(ease-out-elastic t)(ease-out-expo t)(ease-out-quart t)(fade-in t)(fade-linear t)(fade-out t)(frames n f)where t is normalized progress [0.0, 1.0].
(lerp a b t)(ping-pong t)t in [0, 1], returns [0, 1].
(progress frame total)Frame 0 returns 0.0, last frame returns 1.0.
(pulse t)(pulse t frequency)Wraps (/ (+ 1 (sin (* t 2 PI frequency))) 2).
(stagger i n t overlap)i: element index (0-based), n: total elements, t: global progress [0, 1],
overlap: how much elements overlap (0 = sequential, 1 = all simultaneous).
Returns local progress for element i, clamped to [0, 1].
eido.scene3d
3D scene construction: mesh generation, transforms, and projection to 2D. This namespace re-exports all public vars from: eido.scene3d.camera — projections & camera positioning eido.scene3d.mesh — mesh constructors (primitives, platonics, parametric) eido.scene3d.transform — translate, rotate, scale, deform, mirror eido.scene3d.topology — subdivision, auto-smooth, adjacency, normals eido.scene3d.surface — UV projection, coloring, painting, material maps eido.scene3d.modeling — extrude/inset/bevel faces, L-system, instancing eido.scene3d.render — shading, render-mesh, depth-sort, convenience, text eido.scene3d.util — make-face, mesh-bounds, mesh-center, merge-meshes, palette-color, lerp-color Users can require this namespace for the full API, or require sub-namespaces directly for finer-grained imports.
(auto-smooth-edges mesh opts)the given angle. Use with subdivide's
:hard-edges option.opts:
:angle - threshold angle in radians (edges sharper than this are hard)(axis-component axis [x y z]):x, :y, or :z).(axis-range axis mesh)(bevel-faces mesh opts)Composes inset-faces and extrude-faces in one step.
opts:
:select/* - face selector (defaults to :all):bevel/inset - how far to shrink inward (0-1):bevel/depth - extrusion distance (positive = outward, negative = inward)(build-face-adjacency mesh)Returns {
:edge-faces {edge-key → [face-index ...]}:vert-faces {vertex → [face-index ...]}:face-data [{:vertices [...] :style ... :normal ... :point ...} ...]}(color-mesh mesh opts)When
:select/type is present, only selected faces are colored; others pass through.opts:
:color/type - :field, :axis-gradient, or :normal-map:color/palette - vector of [:color/rgb r g b] colors:color/field - field descriptor (for :field type):color/axis - :x, :y, or :z (for :axis-gradient type):select/* - optional face selector (defaults to all faces)(compute-vertex-normals face-data vert-faces)Returns {vertex → normalized-average-normal}.
(cone projection position opts)opts:
:radius, :height, :segments, :style, :light, :cull-back.(cone-mesh radius height)(cone-mesh radius height opts)Base circle in the XZ plane at y=0, apex at [0 height 0].
Opts:
:segments (default 16) — number of sides.(cube projection position opts):group node.opts:
:size (1), :style, :light, :cull-back.(cube-mesh)(cube-mesh position size)or a cube at position [x y z] with given size.
(cylinder projection position opts)opts:
:radius, :height, :segments, :style, :light, :cull-back.(cylinder-mesh radius height)(cylinder-mesh radius height opts)Opts:
:segments (default 16) — number of sides for the circular cross-section.(deform-mesh mesh descriptor)descriptor: map with
:deform/type and type-specific options.Types:
:twist, :taper, :bend, :inflate, :crumple, :displace.(depth-sort & node-colls):node/depth for correct 3D occlusion.Accepts any number of node collections — vectors of nodes, individual group
nodes (from render-mesh), or single nodes.
Groups are flattened into their children before sorting. All nodes are
sorted smallest-depth-first (farthest from camera drawn first — painter's
algorithm). Nodes without
:node/depth are placed at the back.Returns a vector of sorted nodes ready for
:image/nodes.(detail-faces mesh opts)Creates mechanical/sci-fi panel detail. Composes inset + field-driven extrude.
opts:
:select/* - face selector (defaults to :all):detail/field - noise field for per-face extrusion depth:detail/inset - inset amount (default 0.1):detail/depth-range - [min-depth max-depth] range for extrusion(edge-key a b)Sorts the endpoints so edge [a b] and [b a] produce the same key.
(extrude-faces mesh opts)opts:
:select/* - face selector (see make-face-selector):extrude/amount - distance to push faces:extrude/scale - optional scale factor toward centroid (default 1.0)(extrude-mesh path-points direction)path-points: seq of [x y] (treated as [x, 0, y] in 3D space).
direction: [dx dy dz] extrusion vector.
(fov->distance fov half-width):distance value. half-width is half the viewport width in world-spaceunits (typically screen-half-width / scale).
(heightfield-mesh {:keys [field bounds grid height]})opts:
:field - field descriptor (noise, constant, distance):bounds - [x z width depth] defining the sampling area:grid - [cols rows] number of sample points:height - maximum Y displacement(inset-faces mesh opts)opts:
:select/* - face selector:inset/amount - how far to shrink inward (0-1 fraction of distance to centroid)(instance-mesh mesh opts)Bridges 2D scatter distributions to 3D mesh placement.
opts:
:positions - vector of [x y z] positions:jitter - {:amount n :seed s} random positional jitter:rotate-y - {:range [min max] :seed s} random Y-axis rotation per instance(isometric opts)opts:
:scale (default 1.0), :origin [x y] (default [0 0]).(lerp-color [_t1 r1 g1 b1] [_t2 r2 g2 b2] t)(look-at base-projection eye target)(look-at base-projection eye target up)Derives
:yaw, :pitch, and :roll from the geometry. Preserves :type, :scale,:origin, and :distance from base-projection.up: world up vector (default [0 1 0]).
(lsystem-mesh {:keys [axiom rules iterations angle length profile segments taper]})Composes L-system string expansion + 3D turtle interpretation + sweep-mesh.
opts:
:axiom - starting string:rules - rewrite rules {"F" "FF[+F][-F]"}:iterations - number of rewriting iterations:angle - turn angle in degrees:length - distance per F step:profile - 2D cross-section [[x y] ...] for sweep:segments - sweep segments per branch (default 4):taper - profile scale factor per branch depth (default 1.0, < 1 = thinner)(make-face vertices)(make-face vertices style)Computes the normal automatically from the first three vertices.
(make-face-selector opts)Returns (fn [face centroid normal] -> boolean).
(merge-meshes & meshes)Each argument is either a bare mesh (vector of faces) or a
[mesh style] pair, where style is applied to every face in that mesh.
(mesh-bounds mesh):min [x y z] :max [x y z]}.(mesh-center mesh)(mirror-mesh mesh opts)opts:
:mirror/axis - :x, :y, or :z (which axis plane to reflect across):mirror/merge - if true, return original + reflection combined (default false)(normal-map-mesh mesh opts)Creates visible surface detail under lighting without adding geometry.
Requires
:face/texture-coords on faces (from uv-project or OBJ import).opts:
:normal-map/field - field descriptor:normal-map/strength - perturbation strength (default 1.0):select/* - optional face selector(orbit base-projection target opts)opts:
:radius, :yaw (radians), :pitch (radians).At yaw=0 pitch=0, camera is at +Z relative to target (consistent with
the default camera convention).
(orthographic opts)opts:
:scale, :origin, :yaw (radians), :pitch (radians).(paint-mesh mesh opts)When
:color/source is :uv, samples at vertex UV coordinates instead of3D positions — this is the bridge from Eido's 2D procedural system to 3D.
opts:
:color/type - :field, :axis-gradient, or :normal-map:color/source - :position (default) or :uv (requires :face/texture-coords):color/palette - vector of [:color/rgb r g b] colors:color/field - field descriptor (for :field type):color/axis - :x, :y, or :z (for :axis-gradient type):select/* - optional face selector(palette-color palette t)(perspective opts)opts:
:scale, :origin, :yaw, :pitch, :distance.(platonic-mesh type radius)type:
:tetrahedron, :octahedron, :dodecahedron, or :icosahedron.(prism projection position opts)opts:
:base-points, :height, :style, :light, :cull-back.(prism-mesh base-points height)base-points: seq of [x y] for the base (in the XZ plane).
height: extrusion distance along the Y axis.
(render-mesh projection mesh opts):group node with faces sorted back-to-front.Each face becomes a
:shape/path node.opts:
:style - default style {:style/fill [...] :style/stroke {...}}:light - single light map (backward compatible):lights - vector of light maps (multi-light):cull-back - if true, omit back-facing polygons (default true):wireframe - if true, render edges only (no fill, no shading):shading - :flat (default) or :smooth (vertex normal averaging)(revolve-mesh {:keys [profile segments]})opts:
:profile - vector of [radius height] pairs defining the cross-section:segments - number of rotation steps around the axis(rotate-mesh mesh axis angle)axis:
:x, :y, or :z. angle: radians.(scale-mesh mesh factor)(specular-map-mesh mesh opts)Requires
:face/texture-coords on faces. The material's specular value isoverridden per sub-triangle during rendering.
opts:
:specular-map/field - field descriptor:specular-map/range - [min-spec max-spec] (default [0.0 1.0]):select/* - optional face selector(sphere projection position opts)opts:
:radius, :segments, :rings, :style, :light, :cull-back.(sphere-mesh radius)(sphere-mesh radius opts)Opts:
:segments (default 16) — longitude slices,:rings (default 12) — latitude bands.(subdivide mesh opts)opts:
:iterations - number of subdivision passes (each 4× face count):hard-edges - optional set of edge keys to preserve as creasesReturns a new mesh of quad faces.
(sweep-mesh {:keys [profile path segments closed]})opts:
:profile - vector of [x y] pairs defining the cross-section:path - vector of [x y z] waypoints defining the sweep path:segments - number of steps along the path:closed - if true, connect last ring back to first (default false)(text-3d projection content font-spec opts):group node.projection: projection map. content: string. font-spec: font map.
opts:
:depth (extrusion depth), :flatness, :style, :light, :cull-back.The mesh is centered at the origin for natural rotation.
Front/back caps use even-odd fill to correctly render letter holes.
(text-mesh content font-spec depth opts)content: string. font-spec: font map. depth: extrusion depth along Y axis.
opts:
:flatness (curve approximation, default 1.0).(torus projection position opts)opts:
:major-radius, :minor-radius, :ring-segments, :tube-segments,:style, :light, :cull-back.(torus-mesh R r)(torus-mesh R r opts)R: major radius (center of tube to center of torus).
r: minor radius (tube cross-section).
Opts:
:ring-segments (default 24) — divisions around the ring,:tube-segments (default 12) — divisions around the tube.(translate-mesh mesh offset)(uv-project mesh opts)opts:
:uv/type - :box, :spherical, :cylindrical, or :planar:uv/axis - axis for :cylindrical/:planar (default :y):uv/scale - UV scale factor (default 1.0):uv/offset - [u-offset v-offset] (default [0 0]):select/* - optional face selectoreido.scene3d.camera
Projection constructors and camera utilities.
(fov->distance fov half-width):distance value. half-width is half the viewport width in world-spaceunits (typically screen-half-width / scale).
(isometric opts)opts:
:scale (default 1.0), :origin [x y] (default [0 0]).(look-at base-projection eye target)(look-at base-projection eye target up)Derives
:yaw, :pitch, and :roll from the geometry. Preserves :type, :scale,:origin, and :distance from base-projection.up: world up vector (default [0 1 0]).
(orbit base-projection target opts)opts:
:radius, :yaw (radians), :pitch (radians).At yaw=0 pitch=0, camera is at +Z relative to target (consistent with
the default camera convention).
(orthographic opts)opts:
:scale, :origin, :yaw (radians), :pitch (radians).(perspective opts)opts:
:scale, :origin, :yaw, :pitch, :distance.eido.scene3d.mesh
Mesh constructors: primitives, platonic solids, and parametric generators.
(cone-mesh radius height)(cone-mesh radius height opts)Base circle in the XZ plane at y=0, apex at [0 height 0].
Opts:
:segments (default 16) — number of sides.(cube-mesh)(cube-mesh position size)or a cube at position [x y z] with given size.
(cylinder-mesh radius height)(cylinder-mesh radius height opts)Opts:
:segments (default 16) — number of sides for the circular cross-section.(extrude-mesh path-points direction)path-points: seq of [x y] (treated as [x, 0, y] in 3D space).
direction: [dx dy dz] extrusion vector.
(heightfield-mesh {:keys [field bounds grid height]})opts:
:field - field descriptor (noise, constant, distance):bounds - [x z width depth] defining the sampling area:grid - [cols rows] number of sample points:height - maximum Y displacement(platonic-mesh type radius)type:
:tetrahedron, :octahedron, :dodecahedron, or :icosahedron.(prism-mesh base-points height)base-points: seq of [x y] for the base (in the XZ plane).
height: extrusion distance along the Y axis.
(revolve-mesh {:keys [profile segments]})opts:
:profile - vector of [radius height] pairs defining the cross-section:segments - number of rotation steps around the axis(sphere-mesh radius)(sphere-mesh radius opts)Opts:
:segments (default 16) — longitude slices,:rings (default 12) — latitude bands.(sweep-mesh {:keys [profile path segments closed]})opts:
:profile - vector of [x y] pairs defining the cross-section:path - vector of [x y z] waypoints defining the sweep path:segments - number of steps along the path:closed - if true, connect last ring back to first (default false)(torus-mesh R r)(torus-mesh R r opts)R: major radius (center of tube to center of torus).
r: minor radius (tube cross-section).
Opts:
:ring-segments (default 24) — divisions around the ring,:tube-segments (default 12) — divisions around the tube.eido.scene3d.transform
Mesh transforms, deformations, and mirror operations.
(deform-mesh mesh descriptor)descriptor: map with
:deform/type and type-specific options.Types:
:twist, :taper, :bend, :inflate, :crumple, :displace.(mirror-mesh mesh opts)opts:
:mirror/axis - :x, :y, or :z (which axis plane to reflect across):mirror/merge - if true, return original + reflection combined (default false)(rotate-mesh mesh axis angle)axis:
:x, :y, or :z. angle: radians.(scale-mesh mesh factor)(translate-mesh mesh offset)eido.scene3d.topology
Mesh topology: adjacency, subdivision, and auto-smoothing.
(auto-smooth-edges mesh opts)the given angle. Use with subdivide's
:hard-edges option.opts:
:angle - threshold angle in radians (edges sharper than this are hard)(build-face-adjacency mesh)Returns {
:edge-faces {edge-key → [face-index ...]}:vert-faces {vertex → [face-index ...]}:face-data [{:vertices [...] :style ... :normal ... :point ...} ...]}(compute-vertex-normals face-data vert-faces)Returns {vertex → normalized-average-normal}.
(subdivide mesh opts)opts:
:iterations - number of subdivision passes (each 4× face count):hard-edges - optional set of edge keys to preserve as creasesReturns a new mesh of quad faces.
eido.scene3d.surface
UV projection, face coloring, vertex painting, and material maps.
(color-mesh mesh opts)When
:select/type is present, only selected faces are colored; others pass through.opts:
:color/type - :field, :axis-gradient, or :normal-map:color/palette - vector of [:color/rgb r g b] colors:color/field - field descriptor (for :field type):color/axis - :x, :y, or :z (for :axis-gradient type):select/* - optional face selector (defaults to all faces)(normal-map-mesh mesh opts)Creates visible surface detail under lighting without adding geometry.
Requires
:face/texture-coords on faces (from uv-project or OBJ import).opts:
:normal-map/field - field descriptor:normal-map/strength - perturbation strength (default 1.0):select/* - optional face selector(paint-mesh mesh opts)When
:color/source is :uv, samples at vertex UV coordinates instead of3D positions — this is the bridge from Eido's 2D procedural system to 3D.
opts:
:color/type - :field, :axis-gradient, or :normal-map:color/source - :position (default) or :uv (requires :face/texture-coords):color/palette - vector of [:color/rgb r g b] colors:color/field - field descriptor (for :field type):color/axis - :x, :y, or :z (for :axis-gradient type):select/* - optional face selector(specular-map-mesh mesh opts)Requires
:face/texture-coords on faces. The material's specular value isoverridden per sub-triangle during rendering.
opts:
:specular-map/field - field descriptor:specular-map/range - [min-spec max-spec] (default [0.0 1.0]):select/* - optional face selector(uv-project mesh opts)opts:
:uv/type - :box, :spherical, :cylindrical, or :planar:uv/axis - axis for :cylindrical/:planar (default :y):uv/scale - UV scale factor (default 1.0):uv/offset - [u-offset v-offset] (default [0 0]):select/* - optional face selectoreido.scene3d.modeling
Polygonal modeling operations: extrude, inset, bevel, detail, L-system, instancing.
(bevel-faces mesh opts)Composes inset-faces and extrude-faces in one step.
opts:
:select/* - face selector (defaults to :all):bevel/inset - how far to shrink inward (0-1):bevel/depth - extrusion distance (positive = outward, negative = inward)(detail-faces mesh opts)Creates mechanical/sci-fi panel detail. Composes inset + field-driven extrude.
opts:
:select/* - face selector (defaults to :all):detail/field - noise field for per-face extrusion depth:detail/inset - inset amount (default 0.1):detail/depth-range - [min-depth max-depth] range for extrusion(extrude-faces mesh opts)opts:
:select/* - face selector (see make-face-selector):extrude/amount - distance to push faces:extrude/scale - optional scale factor toward centroid (default 1.0)(inset-faces mesh opts)opts:
:select/* - face selector:inset/amount - how far to shrink inward (0-1 fraction of distance to centroid)(instance-mesh mesh opts)Bridges 2D scatter distributions to 3D mesh placement.
opts:
:positions - vector of [x y z] positions:jitter - {:amount n :seed s} random positional jitter:rotate-y - {:range [min max] :seed s} random Y-axis rotation per instance(lsystem-mesh {:keys [axiom rules iterations angle length profile segments taper]})Composes L-system string expansion + 3D turtle interpretation + sweep-mesh.
opts:
:axiom - starting string:rules - rewrite rules {"F" "FF[+F][-F]"}:iterations - number of rewriting iterations:angle - turn angle in degrees:length - distance per F step:profile - 2D cross-section [[x y] ...] for sweep:segments - sweep segments per branch (default 4):taper - profile scale factor per branch depth (default 1.0, < 1 = thinner)eido.scene3d.render
3D rendering: shading, NPR, mesh projection, depth sorting, convenience wrappers, and text mesh.
(cone projection position opts)opts:
:radius, :height, :segments, :style, :light, :cull-back.(cube projection position opts):group node.opts:
:size (1), :style, :light, :cull-back.(cylinder projection position opts)opts:
:radius, :height, :segments, :style, :light, :cull-back.(depth-sort & node-colls):node/depth for correct 3D occlusion.Accepts any number of node collections — vectors of nodes, individual group
nodes (from render-mesh), or single nodes.
Groups are flattened into their children before sorting. All nodes are
sorted smallest-depth-first (farthest from camera drawn first — painter's
algorithm). Nodes without
:node/depth are placed at the back.Returns a vector of sorted nodes ready for
:image/nodes.(prism projection position opts)opts:
:base-points, :height, :style, :light, :cull-back.(render-mesh projection mesh opts):group node with faces sorted back-to-front.Each face becomes a
:shape/path node.opts:
:style - default style {:style/fill [...] :style/stroke {...}}:light - single light map (backward compatible):lights - vector of light maps (multi-light):cull-back - if true, omit back-facing polygons (default true):wireframe - if true, render edges only (no fill, no shading):shading - :flat (default) or :smooth (vertex normal averaging)(sphere projection position opts)opts:
:radius, :segments, :rings, :style, :light, :cull-back.(text-3d projection content font-spec opts):group node.projection: projection map. content: string. font-spec: font map.
opts:
:depth (extrusion depth), :flatness, :style, :light, :cull-back.The mesh is centered at the origin for natural rotation.
Front/back caps use even-odd fill to correctly render letter holes.
(text-mesh content font-spec depth opts)content: string. font-spec: font map. depth: extrusion depth along Y axis.
opts:
:flatness (curve approximation, default 1.0).(torus projection position opts)opts:
:major-radius, :minor-radius, :ring-segments, :tube-segments,:style, :light, :cull-back.eido.io.obj
Wavefront OBJ and MTL parser. Pure functions: string in, mesh data out.
(parse-mtl text)Returns e.g. {"wood" {
:style/fill [:color/rgb 139 90 43] :node/opacity 1.0}}Supported directives: newmtl, Kd, d. All others are ignored.
(parse-obj text opts)opts:
:materials - map from material name to style (from parse-mtl):default-style - style for faces with no material assignmentSupported directives: v, vn, vt, f, usemtl,
g (group name →
:face/group), s (smooth group → :face/smooth-group),o (object name, ignored). All others are silently skipped.
Texture coordinates (vt) are stored as
:face/texture-coords when present.(write-mtl materials)Inverse of parse-mtl.
(write-obj mesh)(write-obj mesh opts)Exports texture coordinates when
:face/texture-coords is present.opts:
:name - object name (default "mesh"):mtl - if true, includes material references; returns {:obj str :mtl str}if false (default), returns the OBJ string directly
eido.io.polyline
Extracts polyline data from compiled IR for CNC/plotter/laser export. Converts all geometry to sequences of [x y] points.
(extract-grouped-polylines ir)(extract-grouped-polylines ir opts)Returns {
:groups [{:stroke :polylines [[[x y] ...] ...]} ...]:bounds [w h]}.Stroke colors are resolved maps like {
:r R :g G :b B :a A}, or nilfor ops without a stroke. Groups appear in the order their stroke
color was first seen. Leaf ops inside
:buffer containers areflattened before grouping.
Options:
:flatness — curve subdivision tolerance (default 0.5):segments — number of segments for circle/ellipse/arc (default 64)(extract-polylines ir)(extract-polylines ir opts)Returns {
:polylines [[[x1 y1] [x2 y2] ...] ...] :bounds [w h]:dropped {:fills N ...} (only when non-empty)}.The optional
:dropped map summarizes visual features (fills,gradients, patterns, hatch, stipple, effects) that the polyline
pipeline cannot represent — a scene that looks filled on screen
exports as outlines only, and
:dropped flags how much got lost.Options:
:flatness — curve subdivision tolerance (default 0.5):segments — number of segments for circle/ellipse/arc approximation (default 64)(optimize-travel-polylines polylines)Greedy nearest-neighbor starting from [0 0], picking the polyline
whose first point is closest to the current position each step.
Polylines with no first point (empty/nil) are dropped, since they
produce no motion and can't anchor the nearest-neighbor search.
Input and output are both vectors of polylines:
[[[x y] ...] ...].
(polylines->edn data)(summarize-drops ir)Counts what the polyline pipeline can't represent — fills (solid,
gradient, pattern, hatch, stipple) — so callers can warn or log
when an export would lose visible information.
Returns
{} when nothing is dropped.eido.math
Shared math utilities: 3D vector operations, interpolation, smoothstep, rotations, and other numeric helpers used across Eido.
(camera-direction projection)Used for back-face culling and depth sorting.
Convention: yaw=0 pitch=0 means camera looks along -Z (camera at +Z).
(cross [x1 y1 z1] [x2 y2 z2])(dot [x1 y1 z1] [x2 y2 z2])(face-centroid vertices)(face-normal [v0 v1 v2 & _])The direction follows the right-hand rule (counter-clockwise winding).
(face-tangent-bitangent [v0 v1 v2] [uv0 uv1 uv2])vertices and their UV coordinates. Returns [tangent bitangent] as
normalized 3D vectors, or nil if the UV triangle is degenerate.
(lerp [ax ay az] [bx by bz] t)t=0 returns a, t=1 returns b.
(magnitude [x y z])(make-projector projection)Precomputes trig values and projection parameters once, avoiding
per-vertex map lookups, trig calls, and intermediate vector allocations.
(normalize v)(project projection point)(rotate [x y z] axis angle):x, :y, or :z) by angle (radians).(smoothstep edge0 edge1 x)Returns 0 when x <= edge0, 1 when x >= edge1, smooth curve between.
(v* [x y z] s)(v+ [x1 y1 z1] [x2 y2 z2])(v- [x1 y1 z1] [x2 y2 z2])(view-transform projection point)Used for perspective projection depth calculation.
eido.ir
Eido's intermediate representation. Two levels: 1. Semantic IR — containers, draw items, fill/effect descriptors. Preserves artist intent (hatch fills, effects, fields) as data. 2. Concrete ops — leaf records consumed by render.clj and svg.clj. Low-level drawing instructions (RectOp, PathOp, BufferOp). The pipeline flows: scene map → semantic IR → lower → concrete ops → render. See eido.ir.lower for the lowering step.
(->ArcOp op cx cy rx ry start extent mode fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)(->BufferOp op composite filter opacity transforms clip ops)(->CircleOp op cx cy r fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)(->EllipseOp op cx cy rx ry fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)(->LineOp op x1 y1 x2 y2 fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)(->PathOp op commands fill-rule fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)(->RectOp op x y w h corner-radius fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)(arc-geometry center rx ry start extent & {:keys [mode]})(circle-geometry center radius)(compile-command command)[
:move-to [x y]] → [:move-to x y](container size background items)(container size background items extra-resources)Optionally accepts additional resources to merge with the default framebuffer.
(draw-item geometry & {:keys [fill stroke opacity transforms clip effects pre-transforms]})(effect-pass id effect & {:keys [input target], :or {input :framebuffer, target :framebuffer}})(ellipse-geometry center rx ry)(generator-item generator-map)The generator-map should have
:item/generator with :generator/type.(geometry-bounds geom)(line-geometry from to)(path-geometry commands & {:keys [fill-rule]})(pipeline size background passes)(pipeline size background passes {:keys [resources outputs]})passes: vector of pass maps (draw-geometry, effect-pass, program-pass).
Optionally accepts additional resources and outputs.
(program-pass id program & {:keys [input target], :or {input :framebuffer, target :framebuffer}})(rect-geometry xy size & {:keys [corner-radius]})eido.ir.domain
Domain descriptors — the space over which something is evaluated. A domain describes what coordinate system and bindings are available when evaluating a program, field, or generator. Domain kinds: :image-grid — pixel grid with :uv [0..1, 0..1], :px, :py, :size :shape-local — shape-local UV space with :uv [0..1, 0..1] :world-2d — world coordinates with :pos [x y] :path-param — path parameter with :t [0..1], :pos [x y] :mesh-faces — per-face with :normal, :centroid :mesh-vertices — per-vertex with :pos [x y z] :points — point set with :pos [x y], :index :particles — particle collection with :pos, :vel, :age, :life :timeline — animation time with :t [0..1], :frame, :fps
(bindings-for domain-kind)Useful for documentation and validation.
(image-grid size)(mesh-faces mesh)(particles source)(path-param path-commands)(points point-set)(shape-local)(timeline & {:keys [fps frames]})(world-2d bounds)eido.ir.resource
Named resources for multi-pass rendering. A resource is an explicit input/output object used by passes. Resources are declared in the IR container and referenced by name. Resource kinds: :image — raster image buffer (the main framebuffer) :mask — single-channel mask :geometry — vector geometry (paths, shapes) :points — point set :field — evaluated scalar/vector field :particle-state — particle simulation state :parameter-block — named parameter values
(field-resource name field-desc)(geometry name)(image name size & {:keys [color-space], :or {color-space :srgb}})(mask name size)(merge-resources & resource-maps)(parameter-block name params)(particle-state name schema)(point-set name points)(validate-pass-resources pass resources)resource map. Returns nil if valid, or a vector of error strings.
(validate-pipeline-resources ir-container)Returns nil if valid, or a vector of error strings.
eido.ir.fill
Semantic fill descriptors and lowering to concrete ops. Fill types: :fill/solid — solid color :fill/gradient — linear or radial gradient :fill/pattern — tiled pattern :fill/hatch — hatched line pattern :fill/stipple — dot distribution pattern Hatch and stipple fills preserve their semantic identity in the IR and are expanded to concrete geometry during lowering.
(evaluate-procedural-fill fill-spec w h)The program receives
:uv as normalized [0..1, 0..1] coordinates.(gradient type stops & {:keys [from to center radius]})(hatch opts)(lower-hatch item)Calls hatch/hatch-fill->nodes directly and converts to concrete ops.
(lower-procedural item)Evaluates the program over the item's bounds and creates an image fill.
(lower-stipple item)Calls stipple/stipple-fill->nodes directly and converts to concrete ops.
(procedural program)program is a program map with
:program/body and optional :program/inputs.The program is evaluated per-pixel with
:uv bound to normalized [0-1] coords.(semantic-fill? fill)(as opposed to direct resolution to a color/gradient).
(solid color)(stipple opts)eido.ir.effect
Semantic effect descriptors and lowering to concrete ops. Effect types: :effect/shadow — drop shadow with offset, blur, color :effect/glow — glow (shadow with no offset) :effect/blur — gaussian blur :effect/grain — film grain :effect/posterize — color quantization :effect/duotone — two-color mapping :effect/halftone — dot-screen halftone Effects are stored as descriptors in draw items and expanded to BufferOp wrappers during lowering.
(blur & {:keys [radius], :or {radius 5}})(duotone & {:keys [color-a color-b]})(glow & {:keys [blur color opacity], :or {blur 8, opacity 0.7}})(grain & {:keys [amount seed], :or {amount 30}})(halftone & {:keys [dot-size angle], :or {dot-size 6, angle 45}})(lower-effects item)Builds BufferOp wrappers directly for shadow/glow and filter effects.
(posterize & {:keys [levels], :or {levels 4}})(shadow & {:keys [dx dy blur color opacity], :or {dx 3, dy 3, blur 5, opacity 0.5}})eido.ir.field
Field descriptors and evaluation. A field is a function over a 2D domain that yields a scalar or vector value. Fields are reusable descriptors that can be consumed by fills, generators, transforms, and programs. Field types: :field/noise — Perlin noise (raw, fbm, turbulence, ridge) :field/constant — uniform value everywhere :field/distance — distance from a point
(constant-field value)(distance-field center)(evaluate field x y)Returns a double.
(evaluate-3d field x y z)Noise fields use 3D Perlin noise. Distance fields use x and y only.
Returns a double.
(noise-field & {:keys [scale variant octaves lacunarity gain seed offset], :or {scale 1.0, variant :fbm}})Options:
:noise-type (:perlin), :variant (:raw | :fbm | :turbulence | :ridge),:scale (1.0), :octaves (4), :lacunarity (2.0), :gain (0.5),:seed (nil), :offset (1.0, ridge only).eido.ir.program
Minimal expression evaluator for vector-form programs. Programs are pure data: nested vectors describing computations. They are evaluated over a domain (e.g. image grid) with named bindings. Expression forms: Literals: 42, 0.5, [1 2 3] References: :uv, :time, :seed (keywords resolve in env) Arithmetic: [:+ a b], [:- a b], [:* a b], [:/ a b] Math: [:abs x], [:sqrt x], [:pow x n], [:mod x n] [:sin x], [:cos x], [:floor x], [:ceil x] Vector: [:vec2 x y], [:vec3 x y z], [:vec4 x y z w] Access: [:x v], [:y v] (first/second of a vector) Interpolate: [:mix a b t], [:clamp x lo hi] Conditional: [:select pred a b] Fields: [:field/noise {field-desc} pos-expr] Color: [:color/rgb r g b]
(evaluate env expr)env is a map of keyword → value (e.g. {
:uv [0.5 0.5] :time 0.0}).(run program env)program: {
:program/inputs {:uv :vec2 ...}:program/domain {:domain/kind :image-grid ...} ;; optional:program/body env: {
:uv [0.5 0.5] :time 0.0 ...}If the program has a
:program/domain, validates that the env containsthe expected bindings for that domain kind.
eido.ir.transform
Semantic transform descriptors and lowering. Transform types: :transform/distort — noise/wave/roughen/jitter displacement on paths :transform/warp — wave/twist/fisheye/bulge/bend coordinate warp :transform/morph — interpolation between two path command sets Transforms are stored on draw items as :item/pre-transforms and applied to geometry before coordinate transforms during lowering.
(apply-pre-transform commands transform)(apply-pre-transforms geom pre-transforms)Returns a modified geometry map (always
:path type after transforms).(distortion method opts)method:
:noise | :wave | :roughen | :jitteropts: method-specific params (see eido.path.distort).
(morph-transform target t)target: path commands to morph toward.
t: interpolation parameter (0.0 = source, 1.0 = target).
(warp-transform method params)method:
:wave | :twist | :fisheye | :bulge | :bendparams: method-specific params (see eido.path.warp).
eido.ir.generator
Generator descriptors and lowering. A generator is a draw item that produces multiple concrete ops by calling existing feature module functions. Generators use :item/generator instead of :item/geometry. Generator types: :generator/flow-field — streamlines from noise field :generator/contour — iso-contour lines from scalar field :generator/scatter — distributed copies of a shape :generator/voronoi — Voronoi tessellation from seed points :generator/delaunay — Delaunay triangulation edges :generator/decorator — shapes placed along a path
(contour bounds & {:keys [field opts style]})field: a field descriptor (or nil for default Perlin noise).
(decorator-gen path-commands shape & {:keys [spacing rotate? overrides], :or {spacing 20, rotate? true}})(delaunay-gen points bounds & {:keys [style]})(expand-generator gen-desc)existing feature module functions and compiling the results.
(flow-field bounds & {:keys [opts style overrides]})(particle-gen config frame n)config: particle system config map (emitter, forces, lifetime, etc.)
frame: which frame to render (0-indexed)
n: total frames to simulate.
(scatter-gen shape positions & {:keys [jitter overrides]})(voronoi-gen points bounds & {:keys [style overrides]})eido.ir.vary
Vary descriptors for per-item style variation. Vary descriptors generate override vectors that modify generated items (fill, stroke, opacity, transforms). Vary types: :vary/by-index — override function called with index :vary/by-position — override function called with position :vary/by-noise — noise-sampled at each position :vary/by-gradient — interpolated color gradient
(by-gradient n stops)(by-index n f)(by-noise positions f opts)opts:
:noise-scale (required), :seed (default 0).(by-position positions f)(resolve-overrides vary-desc)If the input is already a vector, returns it as-is.
eido.ir.material
Material descriptors and multi-light shading for 3D rendering. Materials describe how surfaces respond to light using Blinn-Phong. Light types: :directional — parallel rays from a direction (default, existing) :omni — radiates in all directions from a position :spot — cone of light from a position with hotspot/falloff :hemisphere — sky/ground ambient blend by normal direction Standard light types for 3D scene illumination.
(directional direction & {:keys [color multiplier ambient], :or {multiplier 1.0, ambient 0.0}})(hemisphere sky-color ground-color & {:keys [up multiplier], :or {up [0 1 0], multiplier 0.3}})(omni position & {:keys [color multiplier decay decay-start], :or {multiplier 1.0, decay :none, decay-start 0.0}})(phong & {:keys [ambient diffuse specular shininess color], :or {ambient 0.3, diffuse 0.7, specular 0.0, shininess 32.0}})(shade-face style normal light-dir cam-dir light material)(shade-face style normal light-dir cam-dir light material lights face-centroid)Supports single light or lights vector.
(shade-multi-light normal cam-dir face-centroid material lights)Returns [
:color/rgb r g b].(shade-phong normal light-dir cam-dir light material)(spot position direction & {:keys [color multiplier hotspot falloff decay decay-start], :or {multiplier 1.0, hotspot 43.0, falloff 45.0, decay :none, decay-start 0.0}})eido.ir.lower
Lowers semantic IR containers to concrete ops. Input: {:ir/version 1 :ir/size [w h] :ir/background bg :ir/passes [{:pass/items [...]}]} Output: {:ir/size [w h] :ir/background bg :ir/ops [RectOp ...]}
(lower ir-container)consumed by eido.engine.render and eido.engine.svg.
(lower-scene-node node)Handles scene-level fill/stroke resolution. For use by IR modules that
receive scene nodes from feature modules (hatch, stipple, flow, etc.).
(lower-scene-nodes nodes)(resolve-fill f)