A frame says where a part is: a position, a rotation and a size. Most frames are stated relative to the parent's, so a lantern's glass is placed in the lantern's frame and moves when the lantern moves. But not every placed thing is placed that way. Rain is placed round the camera that is drawing the picture; the sun is placed by a direction, and walking never brings it nearer. So every placed part has a frame, and a frame is one of a few kinds. The kind decides which engines the part is handed to. A part with no frame at all (a material, a rule, world state) is data, not a placed part.

The kinds of frame

KindPosition fromRotation fromExamples
Placedthe parent's frame, composed down the paththe parenta lantern; the land, placed at the origin
Around the camerathe camera drawing the picturethe world, or a planetrain, snow, stars, a sky dome
By directiona direction, which may change over time; never a distance—the sun and moons, as separate parts (a light, a disc)
perhaps a generated-list entryits generatorits generatora tuft of groundcover, a bird of a flock
perhaps bonesa bone of a skeleton in its current posethe bonea held lantern, a helmet

The last two are listed as possibilities, not settled kinds.

The viewer is the camera, not the player

"Around the camera" means the camera drawing the picture, not the visitor's body. The test case is a far-seeing stone, a palantír: looking through it at another land, the rain in its picture is round the projected eye and is that land's rain. So parts placed around the camera exist once per camera, and what they show is looked up where that camera is. As an illustration: a world showing a mirror, a portal and a minimap besides the main view has four cameras drawing, and rain round each.

Following position, rotation, or both

A part placed relative to the viewer has settings for whether rotation follows and whether its content stays fixed to the world:

A field that follows the viewer needs to ask what is around the viewer. Today's rain falls through roofs. The design that would stop it is falling weather blocked like a shadow, found by the engine with the sky along the fall's direction as the light, set by blockedByRoofs: true (to be built; sky-and-weather.html).

By direction: many at once

The sun and the moons are separate parts, each placed by a direction that may change over time; walking never moves them. Several may be present at once: two suns light a scene together. The stars turn about the celestial pole with the hour, with the camera at their center, so they are placed round the camera with the world's rotation, at: around(camera, rotation: world), like the sky dome. There is no background color in the model: what lies behind everything is whatever the designer draws there.

How you write it

A placed frame is written with the at: option, in the parent's frame, meters, y up. Expressions are allowed: the frame may read fields and other parts.

part cottage, at: (-16, land.height((-16, 0, 330)), 330)   // placed, on the land
  part porch                                               // no at: at the cottage's origin, noRotation
    part wallLantern1: wallLantern, at: (-0.7, 2.4, 0)

part lanternHead
  field hangsAt: place = (0, 0, 0)
  part light: pointLight(...), at: hangsAt + (0, 0.335 m * size, 0)      // read from fields

part pathLanterns
  ... part lantern[0]: pathLantern, at: spot                                    // a walkway's spot: on the ground
part amphora, at: (amphoraSpot.x, land.height(amphoraSpot), amphoraSpot.z)        // read from the land

To put a part in the world, say where with at:. Whatever it holds comes with it: a part inside a placed part needs no at: of its own, and stands at its holder's origin, unturned and unscaled, as the balloon's skirt, drawn in the envelope's own units, does. A part with no at: that nothing placed holds is only a description, to be copied and placed elsewhere (Designs and copies). The type of a place is place (Values: the types).

A turn and a scale

A placed frame may also be turned and scaled, with the options rotation:, scale: and unscaled:, given after at: in that order: at: (x, y, z), rotation: rotation(a), scale: k. Each may be left out.

part envelope: balloonEnvelope(), material: paints.envelopePaint,
               at: (0, 5.58 m, 0), rotation: rotation(0.3 rad), scale: 9      // 9 m a unit, turned about up
  part burner: burnerRing(), material: paints.charcoalSteel, at: (0, 0, 0), unscaled: true   // back to true meters
part pin[3]: ninepin, at: (...), scale: 0.6                                 // a pin: 0.6 of the amphora
part trough: waterTrough(), material: materials.oak, at: (...), scale: (2, 1, 0.5)   // stretched: 2 along x, 0.5 along z
part sign: signBoard(), material: materials.oak, at: (...), rotation: rotation(90 deg, about: right)   // about another axis
part vane: weatherVane(), material: materials.iron, at: (...), rotation: lean * heading   // two rotations combined: illustration

The other kinds have no settled spelling. Two have been tried:

part rain: falling(kind: rain, radius: 9 m, above: 6 m, fall: 8 m/s), at: around(camera, rotation: world)
derive(rain.strength, weather.rain)                        // the options of falling: Sky and weather

particles(around: eye, radius: 9 m, above: 6 m)            // another spelling, not settled

Attachments other than a fixed place in the parent have been sketched as values of the at: option, and calls in the part's body:

at: body.bone(head)                                        // a bone in the current pose
skinnedTo(self, body)                                      // all of a skeleton: a call in the part's body
at: nearest(course, to: ear)                               // the brook's point nearest the listener
spawn(splat, under: h.thing, at: h.point, ...)             // whatever the paint hit

A part placed by direction is given its direction by the call that makes it, direction:, where a placed part is given at:. As an illustration:

part sun: sunLight(direction: sunDirection(latitude: latitude, day: date, hour: hour(now(world))), ...)
part sunFace: sunDisc(direction: sun.direction)            // the sun as seen; the sky package's spellings

What it means

The kind decides what the part registers with

When the world loads, each part is handed to the systems that run it, ECS-style ("entity, component, system": an entity is an id, its components plain data, and each system runs every entity with the components it reads; parts.html). The frame's kind is one of the things that decides which:

A path is a chain of frames

Placed frames compose down the path. An office placed 10 m aft in a spaceship stays there as the ship flies and turns. A part with no frame passes its children through: they are placed relative to the nearest ancestor that has one, the world at the top, or, under the hypothesis of scenes, the part's scene.

Each scene has its own coordinate system

A world is partitioned into scenes, and each scene is truly separate: its own coordinate system, its own rules, its own rendering (Worlds, scenes and regions). So a chain of frames ends at its scene. Nothing places one scene relative to another; a place in one scene and a place in another cannot be compared, subtracted or measured between. The only join between scenes is a portal, which carries a being from the frame of its mouth to the frame of its arrival (Portals).

Who owns a part's current place

The content places a part; that is its defined place. But the current place, and the current rotation, can belong to someone else for a while. Together they are the part's pose, p.pose, readable at any time (Values: rotations and poses):

A part's place and rotation may be set only while nothing else drives them: no animator writes them and no awake body owns them.

A part's home

Every placed part has a home, p.home, a pose: where a reset brings it back. By default it is the part's defined place, unturned or turned as its frame says. A part may state another, separate from where it first stands, with the home: option, given a place (unturned) or a pose:

part ball, at: (-9, land.height((-9, 0, 342)) + 0.5 m, 342), rotation: rotation(0.6 rad),   // drawn on the lawn until first bowled
           home: bowlingPins.laneHead                                                      // brought back to the lane's head

The ball lies on the lawn, 12 m in front of the porch, until it is first bowled; every reset after that brings it to the head of the bowling lane. The pins' homes are their places in the rack, so they state none (Physics: acting on physics).

A part's offset

Every placed part has an offset, p.offset, of type offset: how far the part now stands from its defined place, in its parent's frame, as (x, y, z) lengths. It is (0, 0, 0) while the part stands where at: put it, so the part's place relative to its parent is at: plus offset. It is a value like any other: it may be set, animated with keys, or derived. The balloon's cap dips by animating cap.offset from (0, -2 cm, 0) back to (0, 0, 0) (The balloon ride). The same rule as for a place applies: nothing else may drive it while an animator does.

A part's place in world coordinates

p.worldPlace reads any part's place in world coordinates, through every frame above it. For a part whose frames are all fixed it is known when the world is built; for any other part it is read as the world runs. Use it where a place is worked out from other places instead of typing the numbers: the looking-glass's link from its pane to the corridor's mouth is mouth.worldPlace - pane.worldPlace (Cameras and views).

Frames and the sky

Terrain and sky are parts: the land is a large flat placed part that never moves, its questions asked in its frame; the sky and its lights are parts round the camera or by direction (terrain.html, sky-and-weather.html).

How it connects

Open questions

← Designs, copies and spawning | Contents | Loading →