# 3D worlds, coordinates, and cameras [Programming guides](README.md) **3D** means three dimensions: width, height, and depth. A position `(x, y, z)` is measured along three imaginary rulers, called **axes**. Their meeting point `(0, 0, 0)` is the **origin**. Pliro measures distances in **world units**: units you choose for your imaginary world, not screen pixels. Here +Y points up. At the camera's starting angle, +X is right and -Z is forward. The **camera** is the viewpoint from which you see the world. **Yaw** turns it left or right; **pitch** tilts it up or down. Angles use **degrees**: 90 is a quarter-turn and 360 is a full turn. Yaw 0 faces -Z, positive yaw turns right, and positive pitch looks up. Moving the camera stays horizontal even while it looks up or down; positive sideways movement goes to its right. **Wrapping** an angle brings it back around the circle: yaw 370 becomes 10. The notation `[0, 360)` includes 0 but excludes 360. **Clamping** stops a value at a limit: camera pitch 100 becomes 89. The range `[-89, 89]` includes both ends. An **absolute value** is a number's distance from zero: -5 and 5 both have absolute value 5. ## Shapes and the camera A **primitive** is a basic shape, such as a box, sphere, or cylinder. A **radius** goes from the center to the edge; the diameter goes all the way across and is twice as large. A cylinder's axis is the imaginary line through the centers of its round ends. **Geometry** means the mathematical shape and its dimensions. An **oriented box** follows its rotation; an **axis-aligned box** would keep its edges parallel to the world's axes. A **collider** is an invisible shape used to check whether movement would hit something. Pliro's camera collider is a small ball. A **solid** object can block `moveCamera3D`; turning solidity off does not hide an object or exclude it from `touching3D` and `aim3D`. A **ray** is an imaginary straight line cast forward from the camera to ask what it points at. The nearest **hit** is the first object it meets within the allowed distance. These checks use shapes, not the colors of screen pixels. **Insertion order** means the order in which objects were first created. **Field of view** is how wide an angle the camera sees. **Near and far planes** mark the distance window used when drawing; they are not walls in the world. A **texture** is a surface pattern. Its **scale** here controls how many pattern repetitions fit in one unit measured along the object. A **frame** is one complete drawn picture. A **HUD**, short for *heads-up display*, is information such as a score drawn over the world. **Rendering** means making that picture. **WebGL2** is a browser graphics interface that can use the **GPU**, the processor specialized in drawing. A **software renderer** does the drawing calculations on the main processor, the **CPU**. See [MDN's WebGL explanation](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API). ## World settings and limits Boxes use full width, height, and depth. Cylinders use radius and full height, with their axis along +Y. Objects start at `(0, 0, 0)` with yaw 0, color `"#f59e0b"`, solidity `true`, pattern `"none"`, and texture scale 1. Recreating a name resets all those properties but preserves its insertion order. | Value | Requirement | |---|---| | Object name | Case-sensitive, non-blank `Text`, at most 64 [UTF-8](../concepts/utf-8.md) bytes. | | World capacity | At most 256 objects. | | Position component | Finite `Number`, absolute value at most 10,000. | | Dimension or radius | Finite `Number`, greater than 0 and at most 1,000. | | Turn amount | Finite `Number`, absolute value at most 1,000,000,000. | | Camera move component | Finite `Number`, absolute value at most 10 per call. | | Aiming distance | Finite `Number`, greater than 0 and at most 1,000. | | Texture scale | Finite `Number`, greater than 0 and at most 32. | Object operations require an existing name, except shape creation and the no-op removal of an absent name. Invalid arguments do not partially change the world. Colors follow the [portable color table](colors.md). The initial/reset camera is at `(0, 1.5, 5)` with yaw and pitch 0, a vertical field of view of 60 degrees, and near/far planes of 0.05 and 1,000. `camera3D` places it directly, even inside objects. `lookAt3D` rejects a target equal to the camera position. `moveCamera3D` uses a radius-0.2 camera collider against solid objects, with bounded steps, X then Z movement, and wall sliding. There is no automatic gravity, jumping, velocity, or object movement. `touching3D` uses the actual primitive geometry, independently of the solid flag. `aim3D` includes nonsolid objects and returns the nearest hit; equal hits prefer insertion order, and a ray starting inside an object hits at zero distance. These queries do not depend on rendered pixels. `texture3D` accepts `"none"`, `"checker"`, and `"brick"`, ignoring surrounding whitespace and letter case. Scale means pattern repetitions per local world unit; omitting it resets scale to 1. Patterns move with the object, require no image assets, and preserve its color, geometry, and solidity. Pattern strings are data and are **not translated** with the syntax locale. World changes do not draw automatically. `draw3D()` captures a complete frame, replacing previous 2D shapes and sprites. Draw 2D text or shapes **after** it for a HUD, then use a positive `wait` in an animation loop. `clearCanvas` hides the 3D frame without deleting the world. `clear3D` resets the world and camera but needs a following `draw3D()` to display the result. Reset/disposal releases the world; normal Stop preserves the last visible frame. [IDE](../concepts/ide.md)/browser rendering uses WebGL2 with a fallback or diagnostic when unavailable. Native Windows, Linux, and Raspberry Pi use a software renderer at 640 × 360. Pixel edges may differ across renderers; world state, movement, collision, and aiming results have the same semantics. See the [3D specification](../../../docs/spec/scene3d.md). ```pliro # language: en clear3D("#16213e") box3D("crate", 1.5, 1.5, 1.5) color3D("crate", "orange") texture3D("crate", "checker", 2) turn3D("crate", 25) cylinder3D("pillar", 0.35, 2) position3D("pillar", 2, 0, 0) color3D("pillar", "blauw") texture3D("pillar", "brick") sphere3D("ball", 0.5) position3D("ball", -2, 0, 0) color3D("ball", "rood") solid3D("ball", false) camera3D(0, 2, 6) lookAt3D(0, 0, 0) say "Crate touches pillar:", touching3D("crate", "pillar") say "Aimed object:", aim3D(20) draw3D() drawText(320, 20, "My 3D world", 24, "white", "sans", "center") ``` The pattern strings and mixed English/Dutch color values stay unchanged when this program is converted to Dutch syntax. More examples are available in [rotating-box.pliro](../../../examples/en/rotating-box.pliro) and [laser-maze-3d.pliro](../../../examples/en/laser-maze-3d.pliro). ## Related entries [Syntax and values](../syntax/README.md) · [Built-ins](../builtins/README.md) · [Programming guides](README.md)