# `ExRatatui.ThreeD.Transform`
[🔗](https://github.com/mcass19/ex_ratatui/blob/v0.13.0/lib/ex_ratatui/three_d/transform.ex#L1)

Position, rotation, and scale of a 3D object.

The model matrix is composed scale, then rotate, then translate.

## Fields

  * `:position` - `{x, y, z}` translation (floats), defaults to the origin
  * `:rotation` - one of the rotation forms below, defaults to identity
  * `:scale` - `{x, y, z}` scale factors, defaults to `{1.0, 1.0, 1.0}`

## Rotation forms

  * `{:euler_xyz, {rx, ry, rz}}` - intrinsic X then Y then Z, in radians
  * `{:axis_angle, {ax, ay, az}, angle}` - rotation of `angle` radians about
    the (non-zero) axis
  * `{:quat, {x, y, z, w}}` - a raw quaternion

## Examples

    iex> %ExRatatui.ThreeD.Transform{}
    %ExRatatui.ThreeD.Transform{
      position: {0.0, 0.0, 0.0},
      rotation: {:quat, {0.0, 0.0, 0.0, 1.0}},
      scale: {1.0, 1.0, 1.0}
    }

    iex> %ExRatatui.ThreeD.Transform{
    ...>   position: {1.0, 0.0, 0.0},
    ...>   rotation: {:axis_angle, {0.0, 1.0, 0.0}, 0.7}
    ...> }.rotation
    {:axis_angle, {0.0, 1.0, 0.0}, 0.7}

# `rotation`

```elixir
@type rotation() ::
  {:euler_xyz, vec3()}
  | {:axis_angle, vec3(), number()}
  | {:quat, {number(), number(), number(), number()}}
```

# `t`

```elixir
@type t() :: %ExRatatui.ThreeD.Transform{
  position: vec3(),
  rotation: rotation(),
  scale: vec3()
}
```

# `vec3`

```elixir
@type vec3() :: {number(), number(), number()}
```

# `compose`

```elixir
@spec compose(t(), t()) :: t()
```

Compose two transforms: `compose(parent, child)` is the single transform equal
to the matrix product `M_parent · M_child` (parent applied outermost).

Exact when `parent.scale == {1.0, 1.0, 1.0}` (the rigid-frame contract used by
`ExRatatui.ThreeD.Node`); for a non-uniform parent scale with a rotated child the
result is approximate. The result rotation is always `{:quat, _}`.

## Examples

    iex> alias ExRatatui.ThreeD.Transform
    iex> parent = %Transform{position: {1.0, 0.0, 0.0}}
    iex> child = %Transform{position: {0.0, 2.0, 0.0}}
    iex> Transform.compose(parent, child).position
    {1.0, 2.0, 0.0}

# `to_quat`

```elixir
@spec to_quat(rotation()) :: {float(), float(), float(), float()}
```

Normalize any rotation form to a unit quaternion `{x, y, z, w}`.

---

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