Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commite8beb5604c

README.md

instances.to_points (procNode)

Place a piece set on target points, as Copy to Points does: one copy of a piece at each target point, standing where the point's instance attributes put it, followed by the piece point's own pose. With match off every target point gets every piece; with match on a piece goes only to the target points whose attribute value it shares. The copies are a population: io.output draws them as instanced draws, one per piece and material, io.export saves them as a population asset, and instances.unpack takes them apart. Use it to dress a building's window slots with window pieces, scatter rocks of several kinds, or stamp any kit of meshes onto points.

The pieces

pieces is a piece set: points that each carry a Mesh record ({ mesh = <geometry> }), made by instances.pack (one geometry, or one piece per value of an attribute) or by geometry.merge (several geometries with pack on, or the piece sets of several instances.pack calls merged). A piece point's place in the set is its index, counted from 0. Points carrying no Mesh record are refused.

Where a copy stands

Each target point's pose is composed by points.pose from the attributes it carries: P, orient, scale, N, v, up, pscale, rot, trans and pivot (pivot, then scale as scale times pscale, then orientation (orient, else the alignment of N, else of v, with +Z along it and +Y toward up), then rot, then trans plus P). An attribute the target points do not carry at all is identity. A point set holds an attribute for every point or for none: points that lacked an instance attribute when they were merged with points that carried it hold its identity (geometry.merge: scale and pscale 1, orient and rot unrotated, up +Y), so they pose as they did alone. A point whose scale or pscale is 0 gives a copy of no size, which draws nothing.

The piece point's own P, orient and scale (identity where the piece set carries none) are placed inside the target's pose: the copy stands at the target's P plus the piece's P scaled by the target's scale and turned by the target's orientation, turned by the target's orientation followed by the piece's, at the target's scale times the piece's. A piece packed by instances.pack stands at the origin, unturned, at scale 1, so its copy stands at the target's pose.

Matching

With match on, the value of attribute on each target point is compared with the same attribute on each piece, and a pair whose values are equal makes a copy (every equal pair, so two pieces holding one value both go to its target points):

  • The attribute holds a number or a text; an attribute of vectors is refused. Numbers compare as numbers and texts as texts, a number never equals a text.
  • When the pieces carry no such attribute, a target point's number is the 0-based index of the piece it takes (instances.pack with group = "", or a piece set whose pieces were merged without one).
  • Target points that carry no such attribute are refused, naming the attribute.
  • A target point whose value no piece holds is refused, naming the value and how many points hold it, with unsupported "refuse"; with "report" it goes without a copy and is listed in report.

instances.pack writes each piece's value under group (default variant): its name, else the value it was split by, else 0 for a whole geometry. geometry.merge with pack writes the name from names, else the piece's index among the geometries. Pieces packed one by one with no name all carry 0.

With match on, the copies are allocated for every pair of target point and piece and counted on the device: count() answers the slots (target points times pieces) and the live count the matched copies.

What a copy carries

Each copy carries P, orient, scale and id (every copy a point of its own), piece (its piece's place in the set), its Mesh (the piece's record when the set holds one piece; with several, the piece's place, which indexes the records the detail lists in labels.Mesh), and the target point attributes carry selects. Each record labels.Mesh lists states the material its piece wears as material and the most copies of the piece there can be as capacity; each piece's draw reserves that many slots. With match on and the target points' attribute read where the node cooks, capacity is the number of target points holding the piece's value, so the draws of the pieces reserve one slot per matched copy between them, and a piece no target point holds has no draw. Target points whose attribute the device rewrites as time moves (a solver's points, or a column that reads the clock) can hold any piece's value at a later time: each piece then states one per target point. With match off every piece states one per target point. The piece set rides in the detail as pieces, and the detail's population names the attributes a reader takes the piece, the pose and the material from.

A copy wears material when it is wired; else its target point's Material when the target points carry one; else its piece's, the material the piece was packed with. Merged with other populations (geometry.merge), the copies stay one population, drawn as one instanced draw per distinct piece and material.

Inputs

  • points (Points). The target points. A copy is made at each, at the pose its attributes state.
  • pieces (Points). The piece set: one point per piece, each carrying its Mesh record.
  • match (Bool, default false). On, a piece is copied to a target point when their attribute values match (every match). Off, every target point gets every piece.
  • attribute (String, default "variant"). The attribute, on both the pieces and the target points, that match compares: a number or a text. An integer on the target points with no such attribute on the pieces is the 0-based index into the piece set.
  • oriented (Bool, default true). On, copies take the target points' orientation. Off, copies stand unturned at the target's position (scale and pscale are still read).
  • carry (String, default "*"). The target point attributes carried onto each copy: a space-separated pattern of names, * matching any run of characters. P, orient, scale and id always stand on a copy.
  • material (Points or AssetRef<material>, optional). A material every copy wears, in place of its piece's: what a material node answers, or a reference to a material asset.
  • castsShadows (String, default "", one of "", "true", "false"). Whether the copies cast shadows when drawn: "false" for smoke, sparks and glow cards, "true" for debris and props. Empty keeps what each piece states (instances.pack states it).
  • receivesShadows (String, default "", one of "", "true", "false"). Whether the copies receive shadows when drawn. Empty keeps what each piece states.
  • unsupported (String, default "refuse", one of "refuse", "report"). What happens to a target point that holds a value no piece holds, when match is on. Over points a solver moves the match is made on the device and the check is answered from a read the device delivers a frame after the frame it is about: the refusal fails the play then, and the report row stands in the play's report (reported) rather than in report.

Outputs

  • instances (Geometry). The copies, a population.
  • report (List). With match on and unsupported "report", one row { attribute, count, value } when some target points matched no piece (value is the first such value); empty otherwise.
local kit = g.geometry.merge({ a = g.mesh.box({}), b = g.mesh.sphere({}), pack = true }).value
local slots = g.points.grid({ countX = 3, countZ = 1, spacing = 2 })
slots.point.variant = g.where(g.compare(g.element.id, "eq", 1), 1, 0)
local placed = g.instances.to_points({ points = slots, pieces = kit, match = true }).instances