# `Cauldron3D.Bsp`
[🔗](https://github.com/jaman/cauldron/blob/v0.2.2/cauldron_3d/lib/cauldron_3d/bsp.ex#L1)

A world cut into convex leaves by a binary space partition, with its faces, textures,
lightmaps, what each leaf can see, and its brush models.

A loader fills the struct from its own file format; the engine draws it
(`Cauldron3D.Bsp.Draw`), lights its faces (`Cauldron3D.Bsp.Surfaces`) and moves things
through it (`Cauldron3D.Hull`).

  * `planes` — a tuple of `{normal, distance}`; a point `p` is in front when
    `Vec.dot(p, normal) - distance >= 0`
  * `nodes` — a tuple of `%{plane: index, front: child, back: child, mins: Vec, maxs: Vec}`;
    a child at or above zero is a node, below zero the leaf `-child - 1`
  * `leaves` — a tuple of `%{contents: integer, faces: [face index], mins: Vec, maxs: Vec}`
  * `faces` — a tuple of `Cauldron3D.Bsp.Face`
  * `textures` — a tuple of `%{name: String.t(), kind: kind, mips: [Texture.t()]}`, the
    mips halving in size, `kind` one of `:solid`, `:masked` (solid but see-through
    where it is colour 255), `:sky`, `:liquid` or `:hidden`
  * `lightmaps` — the lightmap bytes faces point into
  * `light_channels` — bytes per lightmap sample: 1 for a grey level, 3 for red, green
    and blue
  * `world_leaves` — how many leaves after leaf 0 belong to the world itself (model 0);
    the leaves after them belong to the brush models. `nil` when every leaf is the
    world's
  * `game` — the game the map was made for, `:quake` or `:half_life`
  * `visibility` — a tuple holding for each leaf a bitset of the leaves it can see
    (bit `i` of byte `div(i, 8)`, least significant first), or `nil` where it can see
    every world leaf; `nil` for a world that keeps none. A brush model's leaves are
    never among those seen
  * `models` — a tuple of `%{mins:, maxs:, origin:, heads: [node per hull], first_face:,
    face_count:}`; model 0 is the world itself
  * `hulls` — the collision hulls, as `Cauldron3D.Hull`s with the head of model 0

Contents follow one convention: -1 empty, -2 solid, -3 water, -4 slime, -5 lava,
-6 sky.

# `kind`

```elixir
@type kind() :: :solid | :masked | :sky | :liquid | :hidden
```

# `t`

```elixir
@type t() :: %Cauldron3D.Bsp{
  faces: tuple(),
  game: :quake | :half_life,
  hulls: [Cauldron3D.Hull.t()],
  leaves: tuple(),
  light_channels: 1 | 3,
  lightmaps: binary(),
  models: tuple(),
  nodes: tuple(),
  planes: tuple(),
  textures: tuple(),
  visibility: tuple() | nil,
  world_leaves: non_neg_integer() | nil
}
```

# `contents`

```elixir
@spec contents(t(), Cauldron3D.Vec.t()) :: integer()
```

What `point` is inside: the contents of its leaf.

# `empty`

```elixir
@spec empty() :: integer()
```

The contents value for open space.

# `leaf_at`

```elixir
@spec leaf_at(t(), Cauldron3D.Vec.t(), non_neg_integer()) :: non_neg_integer()
```

The leaf `point` is in, walking from model `model`'s first node (default the world).

# `leaves_touching`

```elixir
@spec leaves_touching(t(), Cauldron3D.Vec.t(), Cauldron3D.Vec.t()) :: [
  non_neg_integer()
]
```

The leaves whose boxes overlap the box `mins`..`maxs`.

# `plane`

```elixir
@spec plane(t(), non_neg_integer()) :: {Cauldron3D.Vec.t(), float()}
```

The plane of `index`: `{normal, distance}`.

# `sees?`

```elixir
@spec sees?(t(), non_neg_integer(), non_neg_integer()) :: boolean()
```

Whether leaf `to` is among those leaf `from` can see.

# `solid`

```elixir
@spec solid() :: integer()
```

The contents value for solid.

# `visible_leaves`

```elixir
@spec visible_leaves(t(), non_neg_integer()) :: [non_neg_integer()]
```

The leaves `leaf` can see, itself included, in ascending order.

---

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