- Geometry
- Render
Relation
Purpose
Section titled “Purpose”A Relation couples members of a Populate to each other or to the world. A spring, an attraction, a steering rule or a contact solver is a relation. It reads what the participants publish and writes what they should apply.
A Relation also groups its participants. They run, hold and reset together, so Reset Population restarts a member and the relation correcting it at the same moment. A plain data wire between two operators never creates that grouping.
- Build the module that computes the relation, for example a Warp FX that reads member poses and writes corrections.
- Place Relation from the Geometry view of the Voro menu, under Render. Its Status reads “Select a relation implementation”.
- Set Relation Implementation to that module.
- Add one Participant row per coupling. Pick the publication the relation reads in Source Publication and the input it writes in Destination Input. One end of every row must be the implementation itself.
- When a correction goes back into the member that produced the data, turn on Previous Generation for that return row.
Status reads “Resolved; coupled execution scope” once the relation is part of the network’s plan.
Inputs and outputs
Section titled “Inputs and outputs”Relation has no wires of its own. Participant rows name each connection as an operator and a port. A destination on a Populate must be an input that the population exposes, and the source and destination types must match. Otherwise Status names the row that failed.
Controls
Section titled “Controls”Relation Implementation is the module that does the work.
Participants are the couplings. Previous Generation delivers the previous step’s value instead of this one. That is what lets a loop close: a member publishes a pose, the relation reads it, and the correction comes back to the member one step later. Turn it on for the return leg only.
Lifecycle Scope is coupled by default. The relation runs, holds and resets with its participants.
Refresh Relation re-reads the implementation and its ports after you edit it in place. Expose Relations brings every relation that shares these participants onto the network so you can see and edit them.
Output from a relation reaches the members a step late. Bodies that stack, rest on each other or push both ways need a relation that owns the bodies. It reads each member’s shape and intent, solves every body together in one step, and publishes poses that each member reads back to draw. Measured on 1,000 falling cubes, impulses sent back to the members threw cubes to 205 m/s. One relation owning all the pieces as bodies kept every cube at its own free-fall speed.
A reset returns a Previous Generation input to its cold default, so a restarted member never reads a value from before the reset. Reset One Member on a Populate does not clear a shared Previous Generation input, because that belongs to the producer. The reset member picks up the producer’s current output. Reset Population restarts both.
A population and a relation joined only by their own feedback loop cannot start. Give the member one other input that publishes from the first pass.
The relation packet contract, and how a member should match packets to its handle and reset epoch, are in the Lab’s Populations guide, lab/AUTHORING_GUIDE/POPULATIONS.md in the Voro package.
Parameters
Section titled “Parameters”Relation
op('relation').par.Implementation The module that computes this relation -- a contact solver, a spring, an attraction. It reads the participants' publications and publishes what they should apply.
- Default:
None
op('relation').par.Feedbackscope coupled: this relation runs, holds and resets together with its participants, in one interaction scope. That grouping is what makes Reset Population restart a member and the relation correcting it at the same moment, so neither is reading the other from before the reset. A data wire alone never creates it.
- Default:
coupled
op('relation').par.Refreshrelation Re-read the relation implementation and its participant ports after editing it in place.
- Default:
None
op('relation').par.Exposerelations Bring every relation sharing these participants onto the network as operators you can see and edit.
- Default:
None
Participants
op('relation').par.ParticipantTemporal On: deliver the previous generation (z-1) instead of this one. This is what makes a feedback loop legal -- a member publishing a pose that a relation reads, whose correction comes back to that member. Turn it on for the return leg only. A reset returns a z-1 input to its declared cold default, so a restarted producer is never rejected as older than the packet that preceded the reset.
- Default:
Off- Options:
- Off, On