# Building geometry Everything the llama walks on, bumps into or falls through is *geometry*. In the editor you build it in two ways: * **Brushes** – editor shapes such as blocks, platforms, ramps, stairs, walls, water and death planes. You draw them with the **Brush** tool, resize them with handles and turn them freely. When the level is built, every brush is cut into the engine's tiles automatically. * **Tiles** – the placed models of the base level's tile set, exactly as the original levels are made. The **Tiles** tool paints them onto grid cells. Collision is part of both: the **Collision** tool shows and changes what the llama can stand on, where it dies and where the level exit fires. ![Drawing a ramp with the Brush tool](img/geo_draw.jpg) ## How the engine stores geometry A few engine facts explain most of what follows: * The level is a grid of **cells** (1 cell = one grid square, 4096 game units). The llama is about 0.6 cells tall. * Geometry is made of **tiles**: a tile is a model placed in one cell, turned about the vertical axis. A tile cannot be scaled or mirrored and its collision must stay close to its cell. * A tile model may have at most **8000 vertices**. * Every collision polygon carries a **material** number. 0 is normal ground, **16** is the exit floor the level door needs, **30** is "no floor" (the llama falls and loses a life). * Collision is looked up per cell, so geometry outside the level grid has no effect. Brushes hide most of this: they can have any size, position and rotation, and the build splits them into 1×1-cell tiles with matching collision for you. ## Brush tool (B) Start it with the toolbar button, the key **B** or **Geometry → Brush tool**. The options bar shows one button per primitive plus **Height**, **Drag height** and **Work plane**; the Inspector shows the same primitives with names (section **Draw**) and the options of the chosen primitive below them. ### Drawing a brush 1. Choose a primitive. 2. Drag in the viewport. Most primitives start with a **footprint**: press on the ground (or on top of other geometry), drag the rectangle and release. 3. For primitives with a height, now move the mouse **up or down** – the preview grows – and **click** to confirm. **Enter** uses the value of the **Height** field instead, **Esc** cancels. The new brush is selected and shows its handles. The status bar shows the size while you draw. | Option (options bar) | Meaning | |---|---| | **Height** | height used for **Enter** and for a click without dragging | | **Drag height** | after the footprint, the mouse movement sets the height; off = the **Height** field is used directly | | **Work plane** + value | draw on a horizontal plane at this height instead of on the surface under the cursor; the grid moves to that height | Footprints snap to the move step of the snapping settings; hold **Ctrl** while dragging to toggle snapping for this drag. **Shift+click** selects an existing brush without drawing. > **Tip:** Drawing on the *surface under the cursor* is the fastest way to stack things: start a > drag on top of a block and the new brush stands on it. ### Primitives | Primitive | How to draw | Notes | |---|---|---| | **Block** | footprint, then height | solid box with top, sides and optional bottom | | **Platform** | footprint, then the height of the top | floating slab with an edge row, bottom and **Thickness** | | **Floor** | footprint only | flat floor, top only | | **Ramp** | footprint, then the height of the high end | rises in the main drag direction | | **Stairs** | footprint, then the top height | rises in the drag direction; **Steps**, **Walkable (invisible slope)** | | **Pillar** | click for the default size or drag its size, then height | square column | | **Round** | drag the diameter, then height | cylinder: round platform or column, **Segments** 3–64 | | **Wall** | drag along the wall in any direction, then height | a turned block when diagonal; snapped to the angle step; **Thickness** | | **Fence** | click the corner points, double-click or **Enter** finishes | posts and rails along a polyline | | **Tree** | click | block tree: trunk and two crown cubes | | **Water** | footprint only | water surface without collision, with a death plane just above it | | **Death plane** | footprint only | invisible no-floor plane (material 30) – falling onto it kills | | **Invisible wall** | drag along its length, then height | collision only, nothing is drawn in the game | | **Invisible block** | footprint, then height | invisible collision volume: floor, ceiling or blocker | > **Note:** Stairs need **Walkable (invisible slope)**: the engine has no step-up logic, so the > llama walks up an invisible slope that lies over the steps. Stairs start at the floor in front > of the first step (*Start height (floor in front)*). ### Primitive options The options section in the Inspector changes with the primitive. Textures are chosen with a swatch button: click it for a searchable grid of all textures of the level (names are the village texture names; `#n` is texture number *n* of the base level, see [Textures](08-textures.md)). **none** leaves that part out. | Option | Primitives | Meaning | |---|---|---| | **Top** / **Texture** | all textured ones | texture of the top (Floor and Water: the only texture) | | **Sides** | Block, Platform, Ramp, Stairs, Pillar, Round, Wall | side texture | | **Top edge** | same | texture of the top row of the sides (e.g. a grass edge), or none | | **Bottom** | same | bottom texture, or none (no bottom faces) | | **Thickness** | Platform, Wall, Invisible wall | slab or wall thickness in cells | | **Steps** | Stairs | number of steps (1–64) | | **Walkable (invisible slope)** | Stairs | adds the invisible slope (see above) | | **Segments** | Round | number of sides of the cylinder | | **Collision** | Block, Round, Wall, Floor, Ramp | off = decoration only, the llama walks through | | **Solid sides** | Block, Round, Wall | off = the sides have no collision, so the llama can walk up onto low plinths | | **Material** | Block, Platform, Round, Wall, Floor, invisible ones | collision material of the brush | ### Handles: resizing A selected brush shows small cubes on its faces – **orange** for the sides, **green** for top and bottom. Drag one to resize: the opposite face stays where it is, also for turned brushes. The status bar shows the new size. ![A selected brush with its resize handles](img/geo_handles.jpg) ### Keys while the Brush tool is active | Key | Action | |---|---| | **[** / **]** | turn the selection by 90° left / right | | **Page Up** / **Page Down** | raise / lower the selection by the snap step | | **Enter** | use the **Height** field (height step) or finish a fence | | **Esc** | cancel the current drawing | | **Ctrl** (held) | toggle snapping for this drag | | **Shift+click** | select instead of drawing | ## Brush properties in the Inspector Selecting a single brush shows two Inspector sections: **Brush shape** (below) and the brush's own parameters (all of them, as numbers and texture fields). Every parameter can be typed in; number fields accept arithmetic such as `2+0.5`. Common parameters: | Parameter | Meaning | |---|---| | **X0 / Z0 / X1 / Z1** | footprint corners in cells (x east, z = grid row, growing south) | | **Bottom / Top**, **Height** | heights in cells | | **Top texture**, **Side texture**, **Top row of the sides**, **Bottom texture** | textures (name, `#n`, a flat colour name or `rgbRRGGBB`) | | **Sides (n, e, s, w)** | which sides of a block exist | | **Collision**, **Side collision**, **Collision material** | collision of the whole brush | | **Casts shadows** | the block shadows other geometry when lighting is baked | | **Texture rotation (0-3, −1 random)** | turns the texture on every face; −1 picks a random turn per tile | | **Tile size** | size of the generated tiles (floors, ramps, water) | | **Tint (r, g, b)** | colour multiplier for the brush's vertex colours | | **Rises towards** | direction of ramps and stairs: `+x`, `-x`, `+z`, `-z` | | **Base height** | ramps and stairs: how far the closed sides reach down (empty = 0.5 below) | | **Post size**, **Post spacing**, **Post texture**, **Rail texture** | fences | | **Trunk height**, **Crown size**, **Trunk size (0 = auto)** | trees | ### Brush shape section ![The Brush shape section after turning a ramp with the blue ring](img/geo_rotate3d.jpg) * The first line shows the kind and size, e.g. **Ramp · 6.25 × 2 × 3.5 cells**. * **Rotation°** – three fields for the rotation about x (east), y (up) and z (south) in degrees, applied in the order x·y·z. The bottom centre of the brush stays in place. * **Left 90°** / **Right 90°** – quarter turns about the vertical axis (**[** / **]**). * **Mirror X** / **Mirror Z** – mirror east ↔ west or north ↔ south. * **Visible (off = invisible collision volume)** – hides the brush in the game but keeps its collision. This is how invisible walls and blocks are made. * **Faces (collision and material)** – a table with one row per face: **top**, **bottom**, **north**, **east**, **south**, **west**. **Collision** switches the face's collision on or off, **Material** gives it its own collision material (for example only the top face 16). Water and death planes are laid out per grid cell: they can be resized and moved but only turned by 90°. A collider (a free invisible polygon) is edited through its corner list. > **Note:** Brushes are baked into tiles when the level is built, so any rotation and scale works. > Tiles placed with the Tiles tool cannot do that – see [Tiles tool](#tiles-tool). ## Rotating, scaling and mirroring The general transform tools are described in [Selection and transforming](05-selection.md). On brushes they can do more than on tiles and objects: * **Rotate (E)**: the green ring turns everything about the vertical axis. The **red** and **blue** rings turn **brushes freely in 3D** (imported meshes about their origin). Tiles and objects only turn about the vertical axis in the engine; the status bar says so and leaves them alone. * **Scale (R)** on a brush changes the primitive's own sizes – width, depth, height, thickness, radius, crown … ; meshes stretch per axis. The bottom centre stays. * **Quarter turns and mirrors** of unturned brushes change their parameters instead of adding a rotation, so textures stay aligned to the grid and ramp directions, sides and per-face settings follow. **Geometry** menu commands for the selection: | Command | Key | What it does | |---|---|---| | **Turn left 90°** / **Turn right 90°** | **Ctrl+[** / **Ctrl+]** | quarter turn about the vertical axis | | **Mirror X (east ↔ west)** / **Mirror Z (north ↔ south)** | | mirror about the centre of the selection; tiles and objects are moved and turned (tile models themselves cannot be mirrored) | | **Array duplicate…** | **Ctrl+Shift+D** | see below | | **Align ▸** | | see below | ### Array duplicate **Geometry → Array duplicate…** (**Ctrl+Shift+D**) makes several copies in one step – a row of platforms, a staircase of blocks, a ring of pillars. | Field | Meaning | |---|---| | **Copies** | number of new copies | | **Offset X (cells)**, **Offset Y**, **Offset Z** | offset of each copy from the previous one | | **Turn per copy (°)** | each copy is turned once more than the previous one | | **Turn about the selection centre (circular array)** | turn around the centre of the selection instead of each item's own position: arranges copies on a circle | Objects in the selection get a copy of their waypoint chain. The whole array is one undo step. ### Align and distribute **Geometry → Align** lines up the selection with the **last selected** item (select two or more): * **Align West (min X)**, **Align Centre X**, **Align East (max X)** * **Align Bottom**, **Align Middle Y**, **Align Top** * **Align North (min Z)**, **Align Centre Z**, **Align South (max Z)** * **Distribute along X** / **Distribute along Z** – spaces three or more items evenly between the outermost two. ![The Geometry menu with the Align submenu](img/geo_menu.jpg) ### Grid and snapping The options bar holds the quick settings: **Snap** (**G**), the move step (1 … 1/16 cell) and the angle step (90° … 1°). **Geometry → Grid & snapping…** sets any value: | Field | Meaning | |---|---| | **Snapping on** | same as **G**; hold **Ctrl** while dragging to invert | | **Move step (cells)** | any step from 1/64 to 16 cells | | **Angle step (°)** | any angle step | | **Scale step** | step of the Scale tool | | **Show the grid** | grid display on or off | The engine places tiles on whole cells; brushes and objects can sit anywhere. ## Tiles tool The **Tiles** tool paints tile models of the base level onto grid cells – the way the original levels are built. Start it with **T**, from the toolbar or **Geometry → Tiles tool**. ![The Tiles tool with its palette in the village](img/geo_tiles.jpg) ### Tile palette The Inspector shows the **Tile palette**: every tile model of the level with a thumbnail, its vertex count and how many tiles use it. **Filter (model number)** narrows the list, **Only models used in the level** hides unused ones. Click a model to make it the current one, or **Shift+click** a tile in the viewport to pick it. ### Modes and options | Mode | What a click (or drag) does | |---|---| | **Paint** | puts the palette model into the cell under the cursor | | **Pick** | takes the model, height and rotation of the clicked tile (also **Shift+click** in any mode) | | **Erase** | deletes the clicked tiles | | **Raise / lower** | raises a tile by the height step, **Shift+click** lowers | | **Swap model** | replaces the model of the clicked tile with the palette model | | Option | Meaning | |---|---| | **On surface** | paint at the height of the tile or ground under the cursor; off = the fixed **Height** | | **Height** | height of painted tiles (**Page Up** / **Page Down**) | | **Rotation** | 0°, 90°, 180° or 270° (**[** / **]**) | | **Step** | height step for raising, lowering and Page Up/Down | Painting onto a tile at the same height **swaps its model** instead of stacking a second tile. New tiles copy the vertex colours of an existing tile with the same model. > **Tip:** Prefer swapping, moving or hiding original tiles over erasing them. Object scripts can > address tiles by their number, and erasing a tile shifts the numbers of all later tiles. The > status bar warns you when you erase an original tile. ### Tile section in the Inspector Selecting tiles shows the **Tile** section: * **Left 90°** / **Right 90°**, **Up** / **Down** (by the snap step). * **Use palette model** – gives the selected tiles the Tiles tool's palette model. * A reminder that tiles only turn about the vertical axis and cannot be scaled or mirrored (the level stores one position and one angle per tile). For free shapes use brushes. ### Tile swaps (doors and bridges) Some levels let object scripts switch a tile to another model – an opening door, a bridge that appears. This is a **tile swap**. The Tile section shows the swap of the selected tile: * **Swap entry in cell …** with the current and the alternative model, * **Alternative = palette** – sets the alternative model from the Tiles tool's palette, * **Remove swap** – deletes the swap entry, * **Add swap (door / bridge)** – gives the tile an alternative model. The layer **Tile swap alternatives** (View → Layers) draws alternative models in cyan. Tile swaps need a base level with the feature flag WFPC 0x10000; on other bases the section says so. ## Collision tool The **Collision** tool shows and paints collision materials. Start it from the toolbar or **Geometry → Collision tool**. It switches the collision layer on: every collision polygon is drawn in the colour of its material. ![Painting collision materials](img/geo_collision.jpg) Hover over geometry: the polygon (on a brush: the whole face) under the cursor is highlighted and the status bar names it and its material. Then: | Mode | Action | |---|---| | **Paint material** | click or drag over polygons to give them the current material; **Shift+click** picks the material of a polygon | | **Toggle collision** | click a brush face to switch its collision on or off | The Inspector shows the list **Collision materials**; **Material** in the options bar does the same, and **Other…** accepts any number from 0 to 255. | Material | Name | Effect | |---|---|---| | **0** | Normal | ordinary ground and walls | | **16** | Exit floor (LevelDoor) | the level door only fires while the llama stands on it in the door's cell | | **30** | No floor / death | the llama falls through and loses a life | | **17** | Selective: only flagged objects | only affects some objects | | **18** | Selective: not flagged objects | only affects the other objects | | 1–15, 20, 26–28, 33, 255 | special, meaning unknown | read by object scripts of the original levels | **Shared models**: original tile models are often used by many tiles. Choose **Shared models: change all tiles** (paint the model, every tile using it changes) or **Shared models: copy for this tile** (the painted tile gets its own copy of the model first). Brushes have one material per face class (top, sides, bottom); tile models are painted per polygon. Tile collision cannot be switched off – paint it 30 or hide the tile instead. The layer **Invisible collision volumes** draws invisible walls, invisible blocks and colliders translucent red so you can see them while editing. ## Special floors ### Exit floor The level exit is an object, the **LevelDoor**, but it only fires while the llama stands on collision material **16** in the door's own cell. The quick setup **Exit** in the Objects panel places both at once – the door and a 1×1 floor with material 16 (see [Objects](09-objects.md)). To make an existing surface the exit floor, paint its top face 16 with the Collision tool or set the face's **Material** in the Brush shape section. ### Death floors and the death plane Material **30** means "no floor": the llama falls through and loses a life. Use it for pits, lava and the ground under a parkour: * the **Death plane** primitive – an invisible plane of material 30 in every cell of its area that is not completely covered by floor, * a **Floor** or **Block** with material 30 (a visible deadly floor), * **Water** – carries its own death plane just above the water surface. **Geometry → Death plane height…** moves all death planes at once: death-plane brushes and the original level's material-30 tiles. It shows how many of each exist; **Add a death plane over the whole grid** creates one if there is none. The same height is in [Level settings](14-level-settings.md). ![In the game: stepping onto a death floor](img/geo_game_death.jpg) ### Invisible walls and blocks **Invisible wall** and **Invisible block** draw boxes that have collision but are not drawn in the game – to keep the llama on a path or to give a decoration a simple collision. Any brush becomes invisible with **Visible** off in the Brush shape section. ![In the game: an invisible wall stops the llama at the edge](img/geo_game_invisible_wall.jpg) ### Water The **Water** primitive draws a water surface without collision (the llama sinks) and, by default, a death plane just above it. Its parameters: **Water height**, **Texture**, **Death plane** (`none`, `whole` = under the whole water, `area` = only in **Death plane area**) and **Tile size**. ## Geometry checks **Level → Check for problems** and every build run these checks (see [Building and play-testing](15-build-play.md)): | Problem | What to do | |---|---| | a tile lies outside the grid | move it in or enlarge the grid in Level settings | | a tile model (also one generated from a brush or mesh) has more than **8000 vertices** | simplify or split the shape | | two identical tiles overlap exactly (same model, cell, height and rotation) | delete one – it causes flickering and double collision | | **no floor collision under the player start** | the llama would fall at once – put floor under it | | the player start is far above the floor | lower it | | **no exit floor (collision material 16) in the LevelDoor's cell** | add or paint the exit floor | | a small **gap** (under 0.2 cells) between neighbouring floors at the same height | close it, the llama can get stuck or fall | | brush warnings | messages of the brush compiler | Double-click a problem to select the item. ![A clean build of a brush level](img/geo_build_ok.jpg) ## Engine limits > **Engine limit:** at most 8000 vertices per tile model. Brushes are split into 1×1-cell tiles, so > only very dense meshes or many brushes overlapping one cell reach it. * Tiles only turn about the vertical axis and cannot be scaled or mirrored; brushes can. * Collision materials of brushes are per face class (top, bottom, each side), of tile models per polygon. * Water and death planes are cell based: they can be moved, resized and turned by 90° only. * The gap check looks only at unturned block, platform and floor tops. * Geometry outside the level grid has no collision. ![In the game: a course built from brushes](img/geo_game_course.jpg)