Most things are not boxes. On this page the block grows into a garden lantern standing on the floor: a turned post, a flat plinth, four corner posts, amber glass and a pointed roof. Two of those pieces cannot be made from boxes at all, and they bring in the most useful idea in shaping: start from a path. Then the pieces are joined into one shape. The turning and the hop from page 2 are left behind, since a lantern stands still, but it still brightens when you come near.

The whole world, changed

part hello                                              // the world
  part materials
    part steel: physical(color: srgb(60, 62, 66), roughness: 0.4, metal: 1)     // new: blackened steel
    part amber: [plain(srgb(255, 205, 130)), translucent(covers: 0.5)]          // new: amber glass
    part stone: plain(srgb(140, 140, 135))
  part floor: box(x: -5 ..= 5, y: -0.1 ..= 0, z: -5 ..= 5), material: materials.stone, at: (0, 0, 0)
    solid(self, derived)
  part lantern, at: (0, 0, 0)                          // new: the block has become a lantern
    fn frame() shape {                                  // the post, plinth, corners and roof, as one shape
      let post   = lathe(profile: [(0, 0), (0.05, 0), (0.05, 0.03), (0.025, 0.08),
                                   (0.025, 0.9), (0, 0.9)]);
      let plinth = box(x: -0.15 ..= 0.15, y: 0.9 ..= 0.94, z: -0.15 ..= 0.15);
      let corner = box(x: 0.11 ..= 0.13, y: 0.94 ..= 1.2, z: 0.11 ..= 0.13);
      let roof   = loftAlong(profiles: [outline.rectangle(width: 0.34, height: 0.34),
                                        outline.rectangle(width: 0.06, height: 0.06)],
                             spine: spine.line(from: (0, 1.2, 0), to: (0, 1.36, 0)));
      join([post, plinth, arrayRadial(corner, count: 4), roof])
    }
    part body : frame(), material: materials.steel
    part glass: box(x: -0.11 ..= 0.11, y: 0.94 ..= 1.2, z: -0.11 ..= 0.11), material: materials.amber
    field near: bool = false, lives: client
    area(self, sphere(radius: 2 m, at: (0, 1, 0)))
    derive(near, occupied(self, by: me))
    derive(glass.tint, if near { 1.4 } else { 1 })      // now only the glass brightens
  part sun: sunLight(direction: (0.4, 1, 0.3), color: color(1, 0.96, 0.9), lux: 80000 lux,
                castsShadow: true)
  part arrivals
    part start, at: (0, 0, 3), facing: (0, 0, -1)

A shape written as a function

The lantern's metalwork is made in several steps, so it is written as a function: fn frame() shape { ... } is a named recipe whose result is a shape. Inside it, each let names one step's result so a later step can use it, and the last line is the function's result. part body: frame() draws the shape that recipe makes, just as part block: box(...) drew a box. The recipe is still only a description; the browser runs it to hydrate the mesh.

The lantern part itself has no shape of its own. It holds the body and the glass, which are drawn in two different materials: a shape is one surface in one material, so an object of two materials is two shapes.

The pieces that are boxes

The plinth is the block from page 1, flattened to 4 cm thick and 30 cm square, and raised to the top of the post at 90 cm. One corner post is a tall thin box at the front right corner. The glass is a box too, filling the space between the corners.

A turned post: spin a flat path

The post is round, flares out at its foot, and narrows to a slim shaft. No box makes that. A woodturner would make it on a lathe, and so does ConeScript. You draw half the post's side view as a flat path, a line of points on a page, and lathe spins it round the upright axis.

lathe(profile: [(0, 0), (0.05, 0), (0.05, 0.03), (0.025, 0.08), (0.025, 0.9), (0, 0.9)])

Each point is (how far out from the middle, how high). The path starts at the middle of the foot, goes out 5 cm, up the flared foot, in to a shaft 5 cm across, up to 90 cm, and back in to the middle at the top. Spun round, it is a solid post. Vases, bowls, bottles and balloons are made the same way. The path that is spun is the profile, and ConeScript calls a flat path an outline.

A pointed roof: skin through outlines

The roof is square at the bottom and comes to a small square at the top. It is made by placing two flat squares, one above the other, and stretching a skin between them. That is a loft, the way a boat's hull is built through its cross-sections.

loftAlong(profiles: [outline.rectangle(width: 0.34, height: 0.34),     // the eaves: 34 cm square
                     outline.rectangle(width: 0.06, height: 0.06)],    // the top: 6 cm square
          spine: spine.line(from: (0, 1.2, 0), to: (0, 1.36, 0)))      // 16 cm straight up

The squares are placed along a path through space, which ConeScript calls a spine: here a straight line rising 16 cm from the top of the glass. The first square sits at its start and the last at its end. Its ends are closed, so the roof is a solid. The skin runs straight from one outline to the next; with more outlines between and smooth: true, it curves through them, and the same loft makes a bell-shaped roof or a dome.

A flat path can also be pushed straight out to make a solid (a letter cut out of board, a tabletop), or swept along a path through space (a rail, a rope, a handle). Sculpting tells that story in full.

Join the pieces into one shape

arrayRadial(corner, count: 4) copies the one corner post four times round the upright axis, a quarter turn apart, so the lantern has all four corners from one box. join([...]) then makes the post, plinth, corners and roof one shape, drawn in one material. Building one piece and copying it is the usual way to make anything that repeats: the slats of a fence, the spokes of a wheel.

Glass you can see through

The amber material is a list again: a plain color, then translucent(covers: 0.5), which makes it see-through. covers is how much of what lies behind is hidden, so at 0.5 you see the post and the far corners through it, dimmed.

The nearness rule is the same as page 2's, moved onto the lantern; it now brightens only the glass, glass.tint, a part of the lantern named by its part path.

Try changing it

What you have now

Most shapes start from a path. Spin a flat path and it is a turned solid; skin through flat paths placed along a path in space and it is a lofted solid. Copy a piece to repeat it, and join pieces into one shape. A shape made in steps is written as a function. The lantern is complete, but it is dark: the next page lights it.

← Guide 2: Bring it to life | Contents | Guide 4: Light it →