Files
llamamod/docs/manual/06-geometry.md
T

420 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 the base level has; `#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 by name or number** narrows the list as you type
(model names as in the Outliner; a number matches whole numbers only, so "12" finds Model 12 but not
Model 120), **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.
One drag is one undo step: **Ctrl+Z** brings back all tiles a stroke painted over, erased or swapped.
> **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. A painting drag is one undo step.
### Tiles without collision
To make a tile only visual, select it and tick **No collision** (Inspector, section **Build**; works
for several selected tiles at once). The built level then uses a copy of the tile's model without
collision polygons: the llama walks through the tile (a wall) or falls through it (a floor). Other
tiles of the same model keep their collision. In the editor the tile no longer shows collision
lines, and checks such as "no floor under the player start" ignore it.
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)