Taos Engine · Agent Tutorials

Agent Tutorials · Step 7

Links

▶ Live demo: run this tutorial — built from src/07_links.ts. Distilled from samples/agent_links.ts.

Links connect agents into a graph — AgentScript's third primitive after turtles and patches. Taos Engine stores a fixed number of link slots per agent, uploaded once as a topology, and the built-in link_springs behavior force-directs them: linked agents pull toward a rest length while everything repels, so a tangled community graph untangles itself.

TypeScript
{
  population: 1500,
  movement: 'velocity',
  neighbors: { /* … */ },                 // link_springs uses the hash for repulsion
  links: { linksPerAgent: 8 },            // 8 slots per node
  behaviors: [{
    type: 'link_springs',
    restLength: 5, stiffness: 6,          // Hooke spring toward each linked node
    repulsion: 60, repelRadius: 12, damping: 0.85,
    maxSpeed: 45, worldHalf: HALF, edgeMargin: 8, edgeForce: 90,
  }],
}

Uploading the topology#

The graph itself (who links to whom) is host data you upload with app.setLinks(Int32Array) from onReady — population × linksPerAgent i32 slots, each a linked agent index or -1 for empty:

TypeScript
onReady: (app) => {
  app.setLinks(buildGraph(POP));   // community graph
},

buildGraph builds six densely-linked communities plus a few cross-community bridges. A rebuild gives a fresh buffer, so re-upload after it: app.rebuild(() => app.setLinks(...)).

Drawing the edges#

AgentLinkFeature draws one ground-plane ribbon per undirected edge. It's an HDR overlay, so add it through extraFeatures (which splices it in after the agents but before tonemap); its source reads the live particle + link buffers off app.particles.pass:

TypeScript
extraFeatures: (app) => [
  new AgentLinkFeature({
    source: () => ({
      particleBuffer: app.particles.pass?.particleBuffer ?? null,
      linkBuffer: app.particles.pass?.linkBuffer ?? null,
      linksPerAgent: app.particles.pass?.linksPerAgent ?? 0,
      count: app.particles.pass?.maxParticles ?? 0,
    }),
    color: [0.35, 0.55, 1.0], intensity: 0.5, width: 0.25,
  }),
],

Watch the scattered nodes pull into six clusters joined by bridges — a classic force-directed layout, computed entirely on the GPU.

Constraint: linksPerAgent is fixed, the topology is host-uploaded, and there's no on-GPU add/break of links or per-link iteration in the step yet (those need a mutable adjacency structure that doesn't fit the fixed-width model). The link_springs behavior + edge rendering cover the common force-directed case.

Next#