Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

README.md

curve.grow (procNode)

Branches reaching toward a cloud of attractor points (space colonisation): from the starting curves, every node an attractor lies nearest grows a step toward the attractors pulling on it, and an attractor a branch reaches is spent. Trees, roots and veins.

Growth is a fold of iterations passes, each over counts that stay on the device: a pass that grows nothing (with no attractor left, nothing is pulled) leaves the nodes as they are. Each pass finds, for every living attractor, the nearest node within influence (core.neighbours, nearest mode), adds the unit vector toward the attractor onto that node (core.scatter, add), grows one step from every node with a pull (compacted in node order by compact; a pass grows no more nodes than there are attractors), and spends every attractor a node has come within kill of. Nothing is read back, so a cook over a moving count of attractors replays a recorded list.

The nodes then become curves. A grown node continues its parent's chain when the parent is a grown node with one child; otherwise it heads a chain that starts at its parent. curve.chain_ranks over those links gives each node its chain and place in it, and a second one over the chain heads gives the generation (forks between a chain and a trunk). Rows are laid out by chain and place: each chain starts where the chains before it end (geometry.offsets), a scatter names the row every slot takes and attribute.carry moves the rows there. curve.strands makes one curve per chain, each point carrying generation and u. The starting curves come first, as generation 0.

Every grown node is joined to a trunk point through its parents, no curve is shorter than two points, and every attractor within kill of the finished tree was spent, so the tree reaches the attractors it can reach.

Built from: curve.tag_trunks, core.owner, attribute.promote, core.points, core.neighbours, compact, core.select, core.scatter, core.concat, attribute.carry, geometry.offsets, curve.chain_ranks, curve.strands, g:fold.

Inputs

  • curve (Curves). The curves growth starts from. They come out unchanged as generation 0.
  • attractors (Geometry). The points the growth reaches toward: scatter them through the volume or over the surface it should fill.
  • iterations (Float). Default 80. At least 0. The most steps of growth. It stops sooner once every attractor is spent or none can reach a branch.
  • step (Float). Default 0.1. How far a branch grows each step.
  • influence (Float). Default 1. How far an attractor reaches for a branch; one further from every branch waits until a branch comes near.
  • kill (Float). Default 0.2. At least 0. How close a branch comes to an attractor to spend it.

Outputs

  • curve: the starting curves followed by the grown chains, one curve per chain. Each point carries generation and u. The counts stay on the device, so the curve is allocated for more points and curves than it holds.

Example

local trunk = g.curve.line({ start = vector.create(0, 0, 0), finish = vector.create(0, 1, 0), segments = 2 })
local cloud = g.points.grid({ countX = 4, countZ = 4, spacing = 0.5, y = 2 })
local tree = g.curve.grow({ curve = trunk, attractors = cloud, iterations = 30, step = 0.2, influence = 3, kill = 0.3 })

The trunk grows up toward the sixteen attractors at height 2 and forks among them.