# `CauldronGPU.Sectors`
[🔗](https://github.com/jaman/cauldron/blob/v0.3.3/cauldron_gpu/lib/cauldron_gpu/sectors.ex#L2)

A `Cauldron2D.Sectors.Map` uploaded for drawing: one mesh holding every floor,
ceiling and wall, a material per picture, and a sky cylinder.

    world = CauldronGPU.Sectors.upload(gpu, map, pictures, palette, sky: sky, sky_flats: [f_sky1])
    CauldronGPU.submit(gpu, CauldronGPU.Sectors.instances(world, first_id: 1))

`pictures` is the `Cauldron2D.Sectors.Pictures` set the map's picture ids index, made
with `native: false`; `palette` is 768 bytes. A map without a BSP gets one from
`Cauldron2D.Sectors.Map.with_bsp/2`.

Floors and ceilings come from `CauldronGPU.Sectors.Flats`, walls with Doom's pegging
from `CauldronGPU.Sectors.Walls`. Each sector's light level is baked into the
vertices' lightmap coordinates and read from one lightmap texture
(`CauldronGPU.Sectors.Light`), so surfaces are lit with the environment's ambient
light at `0`. Pictures with a mask are cut out where it is `0`. Ceilings whose picture
is one of `:sky_flats` are left open, and upper walls between two such sectors left
out; the `:sky` picture is drawn unlit on a cylinder far outside the map.

Vertices stay in map units with heights on +Z; `transform/1` turns them into the
renderer's frame (+Y up) at `:scale` metres a unit, and `point/2` does the same for one
point such as a player start.

Options:
  * `:sky` — picture id of the sky, default none (the environment's sky shows)
  * `:sky_flats` — picture ids that mark a sky ceiling, default `[]`
  * `:scale` — metres per map unit, default `1 / 32`
  * `:light_scale` — lightmap multiplier, default `2.0`
  * `:light_distance` — viewing distance in map units the light levels are taken at,
    default `128`
  * `:filter` — texture filtering, `:nearest` (default) or `:linear`
  * `:sky_distance` — the sky cylinder's radius in half widths of the map, default `64`

# `model`

```elixir
@type model() :: %{
  mesh: CauldronGPU.Handle.t(),
  materials: [CauldronGPU.Handle.t()],
  shadows: boolean()
}
```

# `t`

```elixir
@type t() :: %CauldronGPU.Sectors{
  far: float(),
  handles: [CauldronGPU.Handle.t()],
  models: [model()],
  scale: number()
}
```

# `facing`

```elixir
@spec facing(number(), number()) :: CauldronGPU.Quat.t()
```

The camera rotation facing a map angle of `degrees` (0 along +X, counter-clockwise from above).

# `far`

```elixir
@spec far(t()) :: float()
```

A camera far distance, in the renderer's units, that keeps the level and its sky in view.

# `instances`

```elixir
@spec instances(t(), keyword()) :: [CauldronGPU.Stream.change()]
```

Instance changes placing the level and its sky, ids counting up from `:first_id` (default 1).

# `point`

```elixir
@spec point(t(), {number(), number(), number()}) :: {float(), float(), float()}
```

A map point `{x, y, height}` in the renderer's frame.

# `transform`

```elixir
@spec transform(t() | number()) :: CauldronGPU.Transform.t()
```

The transform that places map coordinates in the renderer's frame.

# `upload`

```elixir
@spec upload(
  CauldronGPU.Target.t(),
  Cauldron2D.Sectors.Map.t(),
  Cauldron2D.Sectors.Pictures.t(),
  binary(),
  keyword()
) :: t()
```

Uploads `map`'s floors, ceilings, walls and pictures, and the sky.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
