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
| Kind | Position from | Rotation from | Examples |
|---|---|---|---|
| Placed | the parent's frame, composed down the path | the parent | a lantern; the land, placed at the origin |
| Around the camera | the camera drawing the picture | the world, or a planet | rain, snow, stars, a sky dome |
| By direction | a direction, which may change over time; never a distance | — | the sun and moons, as separate parts (a light, a disc) |
| perhaps a generated-list entry | its generator | its generator | a tuft of groundcover, a bird of a flock |
| perhaps bones | a bone of a skeleton in its current pose | the bone | a 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:
- Far backdrops (the sky, stars, the sun, a skyline) follow position only.
- Local fields (rain, snow, dust, insects, near grass, the ocean's surface) follow the viewer's position. Today's rain and snow are carried with the eye as a whole, so a walk drags the drops along; fields that stay fixed to the world, so that walking passes drops, are a design still to be built.
- Hands and a held lantern follow everything; they are ordinary placed children of the body.
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
rotation:takes a rotation,noRotationby default.rotation(a)turns the part by the angleaaboutup, counterclockwise seen from above, as every positive turn is (Shape tools: how to read the tables).rotation(a, about: axis)turns it about another axis through its place, and any other value of typerotationturns it by that (Values: rotations and poses).scale: k(a number or an(x, y, z)tuple, 1 by default) scales the part and everything under it bykabout its place: one number the same along every axis, a tuple along x, y and z in turn.kis any expression of fixed values: a literal, a fixed field,1 / 9,pinScale. It is a frame scale: it shares the one built shape and rebuilds nothing (Construction: two kinds of scale).- The order: the part is scaled, then turned, then moved to its place, so the place itself is in the parent's units and never scaled.
- Units inside. Every number inside a part given
scale: k(its shapes, its areas and platforms, its children's places) is in the part's own units, before the scale: inside the envelope above,1.1 mis 9.9 m in the world. This holds for every number a shape reads, wherever its field is declared: a length is read in the units of the part that draws the shape. unscaled: true(a bool, false by default). A part givenat: p, unscaled: truehas true meters as its own units, whatever the scale of its ancestors: everything inside it (its shapes, areas, platforms, children's places) is in meters. Its own placepis still in its parent's units, and it still turns and moves with its parent. The balloon's burner and cables, measured in meters, hang under an envelope drawn 9 m to a unit this way, so no number in them is ever multiplied by 9 or by a ninth. The basket does not: it is scaled with the envelope, and its platform and area are written in the envelope's units (Construction: units in a scaled part; The balloon ride).
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:
- Physics and the network take placed frames only. Rain round each camera is never sent and never collides.
- Streaming and culling skip camera kinds. A part round the camera is always near; there is nothing to stream or cull by distance, and it never sleeps with a region (Worlds: regions).
- The renderer resolves camera kinds per camera. Each camera drawing a picture gets its own instance.
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):
- An engine may take it. A thing a part is can hand its pose to an engine: a pin with a body is moved by physics; a rider on a platform is carried. Carrying is execution state; the rider's path does not change.
- An animator may take it back. The props' glide home, a forced move over the horns. While an animator drives a body's pose, the body is out of the physics world: it is moved by the animator alone, passes through what it meets and pushes nothing. When the animator ends, the body is simulated again where the animator left it, at rest and asleep (Physics: bodies).
- A formula may place it. A placement that follows the clock is written with
deriveon the part's place, with no animator and no new rule (the one-writer rule applies: nothing else may drive it). A ferry that swings 20 m to and fro across a landing, once a day:part ferry: ferryBoat(), material: materials.oak, at: landing derive(ferry.place, landing + (0, 0, 20 m * sin(360 deg * hour(now(world)) / 24)))
- Beings place themselves. A being's place is execution state the engines own; its defined place is only where it starts.
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
- Parts: the tree the frames compose along.
- Worlds, scenes and regions: a scene's own coordinate system; Portals: the joins between them.
- Cameras and views: mirrors, portals, far-seeing, per-camera parts.
- Sky and weather: sun and moons by direction; stars and rain round the camera.
- Physics: bodies, platforms and seats, which take a part's current place.
- Animators:
alongon a place. - Overlays: a 2D layout anchored over a 3D part.
Open questions
- The spelling of frame kinds:
at: around(camera, ...),around: eye; by direction is the argumentdirection:of the call that makes the part. - A turn and a scale in a frame are proposed as the options
rotation:,scale:andunscaled:(A turn and a scale); and whether a turn may be given as a facing (facing: (x, 0, z)) instead of an angle, are open. - Whether generated-list entries and bones are kinds of frame.
- A view of blocked rain from the sky is proposed (
blockedByRoofs, to be built). - Whether there is ground everywhere is the designer's choice; a bounded land must say what happens past its edge (terrain.html).
- Weather placed in the world (to be built): a storm is a placed part moving with the wind; the near drops round the camera ask the storms with
rainAthow hard it rains at each point. Today the rain is the weather's, the same everywhere.