This appendix lists every tool a shape may call, with its exact spelling, its parameters (their types, units and defaults), what it returns, and what it does, in one line. Sculpting explains the tools in plain words, in the same four groups, with an example for each; this page is where to look up a call. A name used in a shape that is not on this page, and is not the world's own, is not vocabulary.
How to read the tables
- Coordinates. Meters, right-handed: x to the right, y up, z toward the viewer (so north, away from the viewer, is
-z). A point is(x, y, z); a point of a flat outline is(x, y). - Named directions.
up(0, 1, 0),down(0, -1, 0),right(1, 0, 0),left(-1, 0, 0),front(0, 0, 1), toward the viewer, andback(0, 0, -1). Any three numbers may stand for a direction; they need not be of length 1. - Angles carry their unit:
90 deg,1.2 rad. A positive turn is counterclockwise seen from the tip of its axis, looking back toward the origin. - Lengths are meters. A plain number where a length is wanted is meters; another unit may be written (
6 mm,2 cm), and a point or a range may mix the two (Values: plain numbers in shapes). Inside a part placed withscale: k, meters are the part's own units, before the scale; a part placed withunscaled: trueis in true meters again (Frames: a turn and a scale). - Shapes calling shapes. A shape is a function,
fn name(...) shape { ... }. A world's own shape may call another of its shapes as it calls a tool, and may read the fixed values in scope (Construction: a shape is a function). - Types in the tables:
meters,angle,count(a whole number, 0 or more: Values: counts),number,fraction(0 to 1),bool,text,point(x, y, z),flat point(x, y),direction,range(a ..= b),shape,outline(a flat outline),spine(a line in space, called a spine so that it is never confused with a part's path),Frame,selection, lists, writtenList[T](List[point],List[shape]), and functions, writtenfn(p: point) meters. - Numbers. The maths functions (
sin,sqrt,lerp,fractand the rest) are listed once, with what each does with units, on Expressions: maths functions. - Arguments. A parameter without a default (in the tables, one written without
= value) may be given by position, in the table's order, or by name. A parameter with a default must be named, and may be left out. Positional arguments come first; after the first named argument every argument is named:subdivide(s, levels: 2),panes(size),tube(from: a, to: b, radius: 3 cm)(Expressions: calls). In every row the parameters without defaults come first. - Ranges. Wherever a tool takes an extent, a range
a ..= bmay be given. Either end may come first:-1 * (0.052 ..= 0.062)is the extent from -0.062 to -0.052. - A list of flat points may be given wherever an
outlineis wanted; it meansoutline.points(points: the list, closed: false). - Every tool returns a new value. Nothing is changed in place:
subdivide(s, levels: 2)leavessas it was. - A refused input is a load-time error. A tool that cannot do what it is asked (a boolean of a solid that is not closed, a bevel wider than its faces allow) stops the world loading, with an error naming the shape and the line. There is no list of problems to read in content.
- Joining. A shape's body is an ordinary block, whose value is its last line. Several pieces are joined by
join([...]), one list of shapes. A list built by a loop uses Cone's own collection form,List[shape]() <- box(...), each f in 0 ..< 4 yield turn(side, by: f * 90 deg, about: up);, and thenjoin(pieces)(Blocks: joining shapes). - (to be built) marks a tool that is specified here but not yet in the browser's library. Every other tool exists; its ConeScript spelling is a binding over the library's own. A tool marked (to be built) is written exactly as its row says, as the examples write it: the row is its design, and a world that names one loads in any browser that has it.
Group 1. Outlines and spines
Outlines: flat shapes in (x, y)
An outline is a list of flat points, open or closed. A closed outline that runs counterclockwise (seen with x to the right and y up) makes solids whose faces face outward.
| Call | Result | What it makes |
|---|---|---|
outline.points(points: List[flat point], closed: bool = true) | outline | the points as given, in order |
outline.polygon(sides: count, radius: meters) | outline | a regular polygon centered on (0, 0), its first corner at (radius, 0), counterclockwise |
outline.circle(radius: meters, segments: count = 32) | outline | a circle centered on (0, 0) as segments straight pieces |
outline.rectangle(width: meters, height: meters) | outline | a rectangle centered on (0, 0), width along x and height along y |
outline.roundedRectangle(width: meters, height: meters, radius: meters, segments: count = 4) | outline | the same with quarter-circle corners of radius, each segments pieces |
outline.ellipse(width: meters, height: meters, segments: count = 32) (to be built) | outline | an ellipse centered on (0, 0), width across and height high. Like the polygon, its first corner is at (width / 2, 0), on the +x side, and the corners follow counterclockwise, evenly spaced in angle; segments: 6 puts corners at 0, 60, 120 ... degrees from +x |
outline.arc(radius: meters, from: angle, to: angle, segments: count = 16) (to be built) | outline | an open arc of a circle centered on (0, 0), from angle from to to, 0 deg along +x |
outline.star(tips: count, outer: meters, inner: meters) (to be built) | outline | a star of tips points: corners alternately outer and inner from (0, 0), the first tip at (outer, 0) |
outline.bezier(controls: List[flat point], segments: count = 16) | outline | an open curve: a quadratic Bezier for three control points, a cubic for four, sampled evenly in segments pieces |
outline.hull(points: List[flat point]) | outline | the smallest convex outline holding every point, counterclockwise |
outline.offset(outline: outline, by: meters) (to be built) | outline | the outline grown outward by by (shrunk inward when negative), its corners rounded |
outline.roughen(outline: outline, amplitude: meters, seed: count, levels: count = 4, roughness: fraction = 0.5) | outline | the outline made rough, as a coastline is: each edge split levels times, each new point pushed sideways by a random amount from the seed, smaller at each level by roughness |
An outline answers what a spine answers. For an outline o, o.length(), o.spotAt(distance), o.frameAt(distance) and o.fromEnd(distance) mean what they mean for a spine (below), with flat points: distance is measured along the outline from its first point, and the frame lies in the outline's plane. A search such as "the first point of the outline at a height" is a loop written with these, a while that steps distance along and tests o.spotAt(distance).y; there is no separate call for it. (To be built, with the spine's queries.)
An outline is also a flat area. A closed outline answers o.contains(p): true when the place p lies inside it. An outline laid on the land's plan names its points as (x, z), and contains reads the x and z of the place it is given, whatever its height. This is how a world states a flat area of the land, such as the dressed area where vegetation is laid out (The land); there is no separate polygon type. (To be built, with the spine's queries.)
Spines: lines in space
A spine is a line of points in space, open or closed: the line an outline is swept along. It carries a frame at every point: the way it runs, and two directions across it that turn as little as the spine allows. (It is called a spine so that it is never confused with the path of a part, a.b.)
| Call | Result | What it makes |
|---|---|---|
spine.points(points: List[point], closed: bool = false) | spine | straight pieces through the points, in order |
spine.line(from: point, to: point, segments: count = 1) | spine | a straight line in segments equal pieces |
spine.circle(radius: meters, segments: count = 32) | spine | a closed circle about the origin, flat in y = 0, starting at (radius, 0, 0) and running counterclockwise seen from above |
spine.arc(radius: meters, from: angle, to: angle, segments: count = 16) (to be built) | spine | part of that circle, from angle from to to, 0 deg at (radius, 0, 0) |
spine.helix(radius: meters, rise: meters, turns: number, segments: count = 32) (to be built) | spine | a spiral about the y axis from (radius, 0, 0), climbing rise each turn, counterclockwise seen from above; segments pieces a turn. To wind the other way, mirror what is swept along it: scale(s, by: (1, 1, -1)) |
spine.through(points: List[point], segments: count or fn(chord: meters) count = 8, kind: centripetal or uniform = centripetal, ends: doubled or extrapolated = extrapolated, closed: bool = false, pointNames: List[(name, count)] = []) (to be built) | spine | a smooth curve through every point (not a polyline), segments pieces between each two (or, given a function of the distance between the two points, the count it answers for that pair). Its length is measured from 64 samples in each segment between two points, a fixed number, whatever segments says. pointNames gives names to points, each as a name and the point's number counting from 0 (the balloon's course names its highest point summit, pointNames: [(summit, 5)]). centripetal, the default, is a Catmull-Rom spline that never loops between unevenly spaced points. uniform is the plain Catmull-Rom spline, which swings out where points are unevenly spaced; the island's pins, amphora handles, walkway and brook use it. ends says how an open spine's first and last pieces are carried on: extrapolated, the default, by a point mirrored past the first and last (the pins and handles); doubled, by the first and last points themselves repeated (the walkway and the brook). A closed spine wraps and has no ends |
spine.bezier(controls: List[point], segments: count = 16) | spine | a quadratic (three controls) or cubic (four) Bezier curve, its directions from the curve |
spine.beziers(curves: List[List[point]], segments: count = 16, closed: bool = false) | spine | cubic Bezier curves end to end, each of four controls, each beginning where the last ends |
What a spine answers
In the table, s is a spine.
| Call | Result | What it answers |
|---|---|---|
s.length() | meters | the spine's length, the closing piece included when it is closed |
s.frameAt(distance: meters) (to be built) | Frame | the frame distance along the spine from its start; past an open spine's ends it carries on straight, and round a closed one it wraps |
s.headingAt(along: meters) (to be built) | direction | the way the spine runs at that distance, a direction of length 1 (the frame's along); like frameAt and spotAt it accepts a distance below 0 or past the end, and carries the end straight on |
s.pointNamed(name) (to be built) | meters | the distance along the spine at the point given that name in pointNames |
s.spotAt(distance: meters, across: meters = 0) (to be built) | point | the point (x, y, z) distance along the spine, moved across sideways in the frame there (opposite frame.x): to the right as you look along the spine, to the left when negative. On a spine the land lays on its surface (the walkway, Terrain), the point is on the ground. |
s.fromEnd(distance: meters) (to be built) | meters | the distance along the spine of the place distance back from its end: its length minus distance |
s.points() (to be built) | List[point] | the spine's points as it was built: for through, the points given and the points that cut each pair into segments pieces. There is a point for each piece, not one for each meter of the spine's length (the island's walkway and brook cut each pair into one piece for each whole meter between the two points, and one more, so their points fall about a meter apart). A world that works on a spine point by point (pressing a walkway into the ground, reading a brook's levels) works on exactly these |
s.nearest(p, within: d) (to be built) | ?(meters, meters) | the point of the spine nearest the place p, read on its x and z for a spine laid on the land: the distance to it and the distance along the spine at it, as a pair (distance, along); None if the spine is not within d of p. How the answer is found (the land keeps a grid of distances) is the engine's business |
s.indexAt(along: meters), s.alongAt(index: number) (to be built) | number; meters | the number of the control point at a distance along the spine, with a fraction for the way on to the next (11.5 is half way from the twelfth point given to the thirteenth, counting the first as 0); and back, the distance along at a control number. A table with a value for each control point is a curve read at this number |
frame.place(at: flat point) | point | a flat point placed in the frame, as an outline's points are placed across a spine |
A Frame has four parts: frame.origin (a point), frame.along (the way the spine runs), and frame.x and frame.y, the directions an outline's x and y are laid along when it is placed across the spine. On a spine that does not run straight up or down, frame.y starts as near to up as it can be, and frame.x then points to the left as you look along the spine. On a spine that starts straight up, frame.y starts toward front and frame.x toward left. After the start, each frame is turned as little as possible from the one before.
Group 2. Making solids
Primitives
Every primitive gets its natural texture coordinates, the ones that suit its form (Sculpting: what a drawn shape gets):
box: per face. Each of the six faces runs 0 to 1 in u and in v, from its lower left to its upper right seen from outside.sphere: spherical. u runs once round the y axis, 0 to 1; v runs from the bottom pole (0) to the top pole (1).cylinder,coneandtorus: cylindrical. u runs once round the axis, 0 to 1; v runs along the axis (or round the tube, for a torus), 0 to 1. A cylinder's or cone's caps are flat discs, read across the disc.planeanddisc: flat, 0 to 1 across the sheet.faceandbar: box-projected, each face taking the two axes it faces least along, one unit to a meter.
Any of them is changed by a tool in "Texture coordinates" below.
| Call | Result | What it makes |
|---|---|---|
box(size: (meters, meters, meters), at: point = (0, 0, 0))box(x: range, y: range, z: range, at: point = (0, 0, 0)) (to be built) | shape | a box of six four-cornered faces: size across in x, y and z, centered on at; or reaching from end to end of each range, moved by at |
cylinder(radius: meters, height: meters, segments: count = 32, caps: bool = true, at: point = (0, 0, 0)) (to be built) | shape | a round column about a vertical axis, standing with the middle of its foot at at, closed at each end when caps |
cone(bottom: meters, height: meters, top: meters = 0, segments: count = 32, caps: bool = true) (to be built) | shape | a cone about the y axis standing on y = 0, radius bottom at its foot and top at its head (a cut-off cone when top is above 0). Its first corner is on +x and the rest follow counterclockwise seen from above, so segments: 4 is a pyramid whose corners point along the axes; turn it 45 deg for one whose sides face them |
sphere(radius: meters, segments: count = 32, at: point = (0, 0, 0)) (to be built) | shape | a ball centered on at, segments slices round and half as many from pole to pole |
torus(major: meters, minor: meters, segments: count = 32, sides: count = 16) (to be built) | shape | a ring about the y axis, flat in y = 0: its tube's center major from the axis, the tube minor in radius |
plane(size: (meters, meters), segments: (count, count) = (1, 1)) (to be built) | shape | a flat sheet in y = 0 facing up, centered on the origin, size across in x and z, cut into a grid |
disc(radius: meters, segments: count = 32) (to be built) | shape | a flat round face in y = 0 facing up, centered on the origin |
face(points: List[point]) (to be built) | shape | one flat polygon through three or more points (three make a triangle), one-sided: it faces the side from which the points are seen to run counterclockwise (the right-hand rule: curl the fingers of the right hand along the points, and the thumb points the way it faces). The ceiling of a lantern, seen from below, runs counterclockwise from below and faces down. A sheet meant to be seen from both sides (a wing) is drawn with a material that is twoSided: true (Materials). Its texture coordinates are box-projected (above) |
bar(from: point, to: point, width: meters, thickness: meters, facing: direction = front) (to be built) | shape | a straight bar of rectangular section centered on the line from from to to: thickness along facing, width across the line and facing; closed at both ends |
Primitives as volumes
sphere, box and cylinder also describe a space: the inside of the surface they would make. Written exactly as above, in the frame of the part they belong to, they give an area its volume: area(self, sphere(radius: 4 m, at: (0, 0.2, 0))) is the ball of 4 m round a point 0.2 m up a lantern's post. As a volume, segments and caps mean nothing and are left out: the sphere is exactly round. A cylinder used as a volume may be unbounded upward or downward: cylinder(radius: 15 m, above: y) is the whole column from height y up, and cylinder(radius: 30 m, below: y) the whole column from y down, with height: left out. A region that has no top or bottom (everything under the island) is below: alone.
Generators: an outline turned into a solid
Each generator leaves three channels on its shape (Sculpting: channels): uv, texture coordinates on the face corners, each 0 to 1 by length; and on the points along, how far the outline had traveled (0 to 1), and around, where on the outline the point came from (0 to 1 by the outline's length, from its first point to its last).
A lathe is a sweep round a circle. It carries the outline round the axis as a sweep carries it along a spine, so its channels mean the same: along runs round the turn, 0 where the outline starts and 1 when it has come all the way round, and around runs along the outline, from its first point to its last. The turn starts at +x (for the default axis, up) and runs toward -z, counterclockwise seen from above: a quarter of the way round is at -z. The channel along the outline is 0 at the outline's first point and 1 at its last, in proportion to the outline's length. The texture coordinates read the same way: u is the turn's fraction, v the fraction along the outline. On a lathed post, along goes round the post and around goes up it; on the balloon's envelope, along * 24 is a whole number on each gore's edge, and around is 1 at the crown.
| Call | Result | What it makes |
|---|---|---|
lathe(profile: outline, axis: direction = up, angle: angle = 360 deg, steps: count = 32) | shape | the outline turned about an axis through the origin, in steps equal steps. An outline point (x, y) is x out from the axis and y along it. A whole turn closes the solid; points on the axis become one point. Faces face outward when a closed outline runs counterclockwise, or an open one runs up the axis on the +x side: from a lower point to a higher one, however far out it goes on the way (a can's outline from the axis out, up and back in to the axis faces outward). |
extrude(profile: outline, direction: (meters, meters, meters), segments: count = 1, caps: bool = true) | shape | the outline, lying flat in z = 0, moved along direction (its length is the depth) in segments equal steps; a closed outline's ends are closed when caps |
sweep(profile: outline, spine: spine, twist: angle = 0 deg, startScale: number = 1, endScale: number = 1, caps: bool = true) | shape | the outline placed across the spine at each of its points (its x along frame.x, its y along frame.y), turned by twist over the whole length and scaled from startScale to endScale, both in proportion to length; no widening at sharp corners. caps closes the two ends of a closed outline swept along an open spine; a closed spine has no ends, so there it closes nothing |
sweepScaled(profile: outline, spine: spine, scale: fn(u: fraction) number, twist: angle = 0 deg, caps: bool = true) | shape | the same, the outline scaled by scale(u), u its fraction of the way along (0 at the start, 1 at the end) |
loft(profiles: List[outline], frames: List[Frame], count: count = 0, between: count = 0, smooth: bool = false, caps: bool = true) | shape | a skin through several outlines, outline k placed in frame k: outlines of different counts and shapes are matched point to point so the skin does not twist. count 0 keeps every outline's own points; above 0, every outline is resampled to that many. between adds rings between each two; smooth curves them through the outlines rather than running straight. |
loftAlong(profiles: List[outline], spine: spine, stations: List[fraction] = [], count: count = 0, between: count = 0, smooth: bool = false, caps: bool = true) | shape | the same skin with outline k placed across the spine at station k: the fraction stations[k] of the spine's length (0 its start, 1 its end), rising. With no stations given, the outlines are spread evenly. Outlines are placed as a sweep places them. Its faces face outward, away from the spine: a closed outline is first turned counterclockwise, so every station runs the same way. With caps: true (the default) each end is closed by one flat face, making a closed solid; caps: false leaves both ends open, a skin only (the lantern's roof, which sits on its fascia). A worked example is on Sculpting. A spine that does not start upward (a leg or an arm hanging down): the profile's y is the first frame's y, s.frameAt(0).y, so draw each outline with that direction in mind. A ring whose middle is off the spine is written as an outline of points (outline.points); outline.ellipse is centered. |
Group 3. Combining and placing
Placing a shape
| Call | Result | What it does |
|---|---|---|
move(s: shape, by: (meters, meters, meters)) (to be built) | shape | the shape moved by the offset |
turn(s: shape, by: angle, about: direction = up, origin: point = (0, 0, 0)) (to be built) | shape | the shape turned by the angle about the line through origin along about, counterclockwise seen from the axis's tip |
scale(s: shape, by: number or (number, number, number), origin: point = (0, 0, 0)) (to be built) | shape | the shape scaled about origin: uniformly by one number, or along x, y and z by three; a negative factor reflects it, and its faces are turned to face outward again |
onBone(s: shape, bone: bone) (to be built) | shape | the shape tied wholly to one bone of a body's skeleton, so it moves with that bone. Its points are written in the body's rest-pose coordinates: where the point is when the body stands in its rest pose, in the body's own frame (Fitted bodies: attachment at run time). Used inside join([...]), the pieces tied to different bones make one skinned mesh, for one part in one material |
skinChain(s: shape, bones: List[bone], joints: List[point], blend: List[meters]) (to be built) | shape | the shape skinned along a chain of bones, its weights blended across each joint. joints are the points where one bone ends and the next begins, one fewer than bones; blend[j] is the half-width either side of joint j over which the weights pass from one bone to the next by a smooth step, and outside every blend a point is wholly its segment's bone. A point's place along the chain is its nearest point on the chain's segments, the end segments carried on straight. The knee, the elbow and the waist are so skinned, where onBone would crease them |
inFrame(s: shape, frame: Frame) (to be built) | shape | the shape, written upright about the origin with its y axis along its own length, placed in a frame got from a spine (s.frameAt(distance)): the origin to frame.origin, its x axis to frame.x, its y axis to frame.along and its z axis to the cross of the two. The horn-flower's petals, heart and leaves are carried into the stalk's frames so. The stalk's own path, its cut and its radius (hornPath, hornCut, hornRadius) are the stage horn's, another piece: the flower names them as that piece's own, with its own length, cut and rings |
cut(s: shape, plane: (direction, point), keep: front or back) (to be built) | shape | the shape cut by a plane, given as the direction it faces and a point on it, keeping the side the direction points to (front) or the other (back). Faces the plane crosses are cut, and the cut is left open (no cap), so a dome cut at its equator is a skin open underneath. The shape need not be closed |
Joining and copying
| Call | Result | What it does |
|---|---|---|
join(shapes: List[shape]) | shape | the shapes in the list as one shape, nothing welded; channels of the same name become one. A list that a loop makes is built with List[shape]() <- ..., each ... yield ... (Blocks: joining shapes). |
mirror(s: shape, normal: direction = right, origin: point = (0, 0, 0), merge: meters = 0.0001, flipU: bool = false, flipV: bool = false) | shape | the shape and its reflection in the plane through origin facing normal; points within merge of their reflections are welded into one, stitching the seam (see "Stitching", below). flipU and flipV mirror the copy's texture coordinates. |
symmetrize(s: shape, normal: direction = right, origin: point = (0, 0, 0), merge: meters = 0.0001) | shape | the half on the side normal points to kept, the other half replaced by its reflection, and the two stitched along the plane; faces the plane crosses are cut |
arrayLinear(s: shape, count: count, offset: (meters, meters, meters), merge: meters = 0.0001) | shape | count copies in a row, copy k moved by offset times k; touching copies are stitched within merge |
arrayRadial(s: shape, count: count, axis: direction = up, angle: angle = 360 deg, origin: point = (0, 0, 0), merge: meters = 0.0001) | shape | count copies turned about an axis: spread evenly round a whole turn, or from 0 to angle, the last at angle, for any other |
arrayAlongSpine(s: shape, spine: spine, count: count, merge: meters = 0.0001) | shape | count copies spaced evenly along the spine, each placed rigidly in the spine's frame there: the shape's x along frame.x, its y along frame.y and its z along the spine, so a shape built along +z follows the spine |
weld(s: shape, within: meters) | shape | points closer than within merged into one |
bridge(a: shape, b: shape, cuts: count = 0, smoothness: number = 0) | shape | two shapes, each with one open edge loop, joined into one by a band of faces from the one loop to the other; cuts rings across the band, curved by smoothness |
Stitching, in mirror, symmetrize and the arrays. Points closer than merge are welded into one: the copies' neighboring points, or a point and its reflection. Each welded point's shading direction follows creaseAngle like any other point's (so a weld across a sharp edge still shows the edge). Texture coordinates stay per piece: they belong to the face corners, not the points, so a seam keeps both pieces' coordinates and the image is not smeared across it. A negative merge turns stitching off, so the pieces are only joined. merge: 0 m still welds points that coincide exactly, as the library does (a lone 0 m is not "off"). Only points of neighboring copies are welded, never two points of one copy.
Booleans
Both shapes must be closed solids whose faces face outward; otherwise the world does not load. The result is exact, the same on every machine.
| Call | Result | What it does |
|---|---|---|
union(a: shape, b: shape, crease: number = 0) | shape | everything inside either. With crease above 0, the line where the two surfaces meet is creased that sharply, so smoothing keeps it. |
difference(a: shape, b: shape, crease: number = 0) | shape | what is inside a and not inside b: b cut out of a |
intersection(a: shape, b: shape, crease: number = 0) | shape | what is inside both |
notch(at: part, wide: meters, deep: meters) (to be built) | shape | a slot to cut out of a wall's block with difference: wide across, centered on the part (a pane), cut deep into the block from the side the pane is on, and the full height of the block it cuts. The block is the shape the difference takes it from, so the slot never stops short of its top or its foot. Physics: gates uses it for the looking-glass. |
Group 4. Changing a solid
Selections: saying which faces, edges or points
A selection names part of a shape without numbering its points. The same selection serves wherever a tool asks for faces, edges or points: an edge is chosen when both its ends are, a face when all its corners are, unless the row says otherwise.
| Call | Result | What it chooses |
|---|---|---|
all | selection | everything |
facing(direction: direction, within: angle = 30 deg) (to be built) | selection | the faces whose outward direction is within within of direction; as edges or points, those of these faces |
inBox(x: range, y: range, z: range) (to be built) | selection | the points inside the box; any of the three may be left out, and that axis is then unbounded |
sharperThan(angle: angle) | selection | the edges where the two faces meeting differ in direction by more than angle; as points, the points on them |
byChannel(name: text) | selection | whatever has a value above 0 in the channel name: points, or edges and faces when the channel is on edges or faces |
boundary (to be built) | selection | the open edges, those with a face on one side only, and the points on them |
where(test: fn(p: surfacePoint) bool) (to be built) | selection | the points for which the test is true (see "A point's values", below) |
Editing faces
| Call | Result | What it does |
|---|---|---|
extrudeFaces(s: shape, faces: selection, distance: meters, individual: bool = false)extrudeFaces(s: shape, faces: selection, offset: (meters, meters, meters)) | shape | the chosen faces pushed out distance along their region's outward direction (or each along its own, when individual), or all moved by one offset, joined to where they were by walls of faces |
inset(s: shape, faces: selection, thickness: meters, depth: meters = 0, individual: bool = false) | shape | each region of chosen faces shrunk inside a border thickness wide, then moved depth out (in when negative) |
solidify(s: shape, thickness: meters, offset: number = -1, even: bool = true, rim: bool = true) | shape | a sheet given thickness: a second skin thickness away, behind the sheet at offset -1, centered at 0, in front at 1 (offset runs from -1 to 1); rim closes the open edges between the skins; even keeps the thickness even at folds |
bevel(s: shape, edges: selection, width: meters, segments: count = 1, roundness: fraction = 0.5, clamp: bool = true) | shape | the chosen edges cut back width into segments faces: a flat chamfer at 1 segment, rounder with more; roundness 0.5 is a circular profile, lower hollows it, higher squares it; clamp keeps neighboring bevels from overlapping. Open edges cannot be beveled. |
bevelCorners(s: shape, points: selection, width: meters, segments: count = 1) | shape | the chosen corners cut off width along each edge |
Refining and reducing
| Call | Result | What it does |
|---|---|---|
subdivide(s: shape, levels: count = 1) | shape | Catmull-Clark smoothing levels times: every four-cornered face split in four and every point moved toward its neighbors, so a coarse cage becomes a smooth surface; creased edges stay sharp; every channel is carried |
decimate(s: shape, ratio: fraction) | shape | the shape cut to ratio of its triangles by collapsing the edges whose loss changes it least; the result is triangles |
dissolvePlanar(s: shape, within: angle = 5 deg) | shape | neighboring faces that differ in direction by at most within merged into one, and points in straight runs dropped |
voxelRemesh(s: shape, voxel: meters, keepVolume: bool = false) | shape | a closed shape rebuilt as an even skin of four-cornered faces about voxel across, its channels carried from the nearest point; keepVolume moves each new point onto the old surface |
multires(base: shape, levels: count, detail: data) | shape | the base subdivided levels times with stored detail added at each level: the surface an authoring tool sculpted, carried as a coarse base and a file of its detail |
Deforming: moving points, keeping faces and channels
| Call | Result | What it does |
|---|---|---|
bend(s: shape, angle: angle, axis: direction = front, along: direction = up, origin: point = (0, 0, 0)) | shape | the shape's length along along curled through angle about axis, keeping its length; with the defaults, a shape standing up bends toward -x |
twist(s: shape, angle: angle, along: direction = up, origin: point = (0, 0, 0))twist(s: shape, angleAt: fn(u: fraction) angle, along: direction = up, origin: point = (0, 0, 0)) | shape | each point turned about the line through origin along along, from none at one end of the shape to angle at the other; or by angleAt(u), u the point's fraction of the way along |
taper(s: shape, factor: number, along: direction = up, origin: point = (0, 0, 0))taper(s: shape, scaleAt: fn(u: fraction) number, along: direction = up, origin: point = (0, 0, 0)) | shape | each point's distance from that line scaled by 1 at one end of the shape to 1 + factor at the other; or by scaleAt(u) |
deform(s: shape, to: fn(p: point) point) | shape | every point moved to to(p) |
deformAlong(s: shape, offset: fn(u: fraction) (meters, meters, meters), along: direction = up) | shape | every point moved by offset(u), u its fraction of the way along: a sway, a shear, a swell to one side |
curveDeform(s: shape, spine: spine, along: direction = front, up: direction = up, origin: point = (0, 0, 0)) | shape | the shape laid along the spine, its along direction following the spine and its up the spine's frame.y; not stretched to the spine's length. Put origin at the end that should sit at the spine's start. |
lattice(s: shape, x: range, y: range, z: range, moves: List[((count, count, count), (meters, meters, meters))], points: (count, count, count) = (2, 2, 2), smoothness: linear or bernstein or bspline = bspline) | shape | a cage of control points over the box, points along each axis; each move shifts control point (i, j, k) by an offset, and the shape inside follows smoothly |
smooth(s: shape, factor: fraction = 0.5, iterations: count = 1, keepVolume: bool = false) | shape | each point moved factor of the way toward its neighbors' middle, iterations times; keepVolume smooths without shrinking |
shrinkwrap(s: shape, onto: shape, mode: nearestSurface or project(along: direction) or nearestPoint or targetNormal = nearestSurface, offset: meters = 0) | shape | every point moved onto the other shape's surface (to its nearest point, along a direction, to its nearest point of the mesh, or along that surface's direction), then offset out from it |
Detailing
| Call | Result | What it does |
|---|---|---|
displace(s: shape, channel: text, amount: meters) | shape | every point moved out along its surface's direction by amount times its value in the channel |
displace(s: shape, by: fn(p: surfacePoint) meters) (to be built) | shape | every point moved out along its surface's direction by by(p) (in when negative); the function reads the point's position and channels |
ribs(s: shape, into: text, frequency: number, seed: count, sharpness: number = 3) | shape | a channel named into of rib heights, 0 to 1: frequency ribs from end to end, read from the generator's along and around; displace turns it into shape |
marginRing(s: shape, into: text, frequency: number, seed: count) | shape | a channel of ribs grown as a shell grows them, pulse by pulse at its rim: less regular than ribs |
roughen(s: shape, amount: meters, size: meters, seed: count, octaves: count = 4) (to be built) | shape | every point moved in or out along its surface's direction by seeded noise: bumps about size across and up to amount high, with octaves finer layers each half the size |
Edges and normals
| Call | Result | What it does |
|---|---|---|
crease(s: shape, edges: selection, sharpness: number = 1) (to be built) | shape | the chosen edges marked sharp for subdivision: they stay sharp for sharpness levels, and for ever at 10 or more |
creaseAngle(s: shape, angle: angle = 30 deg) (to be built) | shape | how sharp an edge must be to show as an edge when the shape is drawn: across edges sharper than angle the shading breaks; elsewhere it is smooth. angle: 0 deg is flat shading: every face is shaded flat, its own direction across the whole face (the launch button's cap) |
Texture coordinates
Each replaces the shape's uv channel. size is the meters one repeat of a texture covers.
| Call | Result | What it does |
|---|---|---|
uvPlanar(s: shape, facing: direction = up, size: meters = 1) (to be built) | shape | the texture laid flat across the shape from the direction facing, as a slide projector would |
uvAt(s: shape, f: fn(p: point) (number, number)) (to be built) | shape | each point's texture coordinates worked out from its place: f maps the point (in the shape's own coordinates) to (u, v). A constant is a function that ignores its point: uvAt(handle, p => (0.5, 0.02)) puts every point of the handle on one spot of the image, so a handle joined to a jar is painted the color found there |
uvBox(s: shape, size: meters = 1) (to be built) | shape | each face given the projection along the axis it faces most, size meters a repeat: what face and bar have |
uvCylindrical(s: shape, axis: direction = up, origin: point = (0, 0, 0), size: meters = 1) (to be built) | shape | u once round the axis, v along it, size meters a repeat |
uvSpherical(s: shape, center: point = (0, 0, 0)) (to be built) | shape | u once round the y axis through center, v from the bottom pole to the top |
A point's values
A function a tool runs for each point of a shape (where, displace(by: ...)) receives a surfacePoint. Its values:
| Value | Type | What it is |
|---|---|---|
p.position | point | where the point is |
p.normal | direction | the direction the surface faces there, of length 1 |
p.along, p.around | fraction | the generator's channels (Group 2), carried through every later tool |
p.uv | flat point | the point's texture coordinates; on a seam, those of its first face |
p.name | number | any other point channel by its name, such as p.ribs after ribs(s, into: "ribs", ...); 0 where the shape has no such channel |
Numbers in shapes
A shape uses the same maths as every other part of a world: min, max, clamp, abs, sign, floor, ceil, round, fract, sqrt, pow, exp, ln, log2, sin, cos, tan, asin, acos, atan2, pi, lerp, smoothstep, remap, length, distance, dot, cross, normalize, mix, noise and hash, and arithmetic on points and directions (Values). There is one list, with each function's arguments and what it does with units, on Expressions: maths functions. Units follow algebra: sqrt(x * x + z * z) of two lengths is a length, and floor and fract keep their argument's unit; angles go in with their unit (sin(22.5 deg)), and only exp, ln, log2 and pow with a fractional exponent need a length divided by its unit first.
Images for materials
Not shape tools, but listed here so every name an example uses can be looked up. Each makes an image that paintedBy(...) lays on a material of any kind (Textures).
| Call | Result | What it makes |
|---|---|---|
surfacepatterns(tile: (meters, meters), texel: fn(u: meters, v: meters) texel), and the presets surfacepatterns.PlankParams.siding(size, seed:) and the rest | image | a seamless tile and its maps, from a world's own texel function or a preset (Textures: the pattern recipes) |
texel(color: color, height: fraction = 0, roughness: fraction = 1, cavity: fraction = 1) | texel | one point of a tile: its color, and the values its other maps are worked out from |
painted(size: (texels, texels), colorAt: fn(uv: (number, number)) color, samples: count = 1, wraps: bool = false) or painted(size: (texels, texels), valueAt: fn(uv: (number, number)) number, samples: count = 1, wraps: bool = false) (to be built) | image | an image painted over a shape's texture coordinates (with valueAt, a one-channel image of numbers, such as a roughness map: Textures): colorAt called at samples by samples evenly spaced points in each texel, their mean on the sRGB numbers the texel's color; with wraps: true a tile that repeats every 1 in u and v (Textures: painting an image) |