# `BB.Math.Vec3`
[🔗](https://github.com/beam-bots/bb/blob/main/lib/bb/math/vec3.ex#L5)

3D vector backed by an Nx tensor.

All operations are performed using Nx for consistent performance
and potential GPU acceleration.

## Examples

    iex> v = BB.Math.Vec3.new(1, 2, 3)
    iex> BB.Math.Vec3.x(v)
    1.0

    iex> a = BB.Math.Vec3.new(1, 0, 0)
    iex> b = BB.Math.Vec3.new(0, 1, 0)
    iex> c = BB.Math.Vec3.cross(a, b)
    iex> BB.Math.Vec3.z(c)
    1.0

# `t`

```elixir
@type t() :: %BB.Math.Vec3{tensor: Nx.Tensor.t()}
```

# `add`

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

Adds two vectors.

## Examples

    iex> a = BB.Math.Vec3.new(1, 2, 3)
    iex> b = BB.Math.Vec3.new(4, 5, 6)
    iex> c = BB.Math.Vec3.add(a, b)
    iex> BB.Math.Vec3.to_list(c)
    [5.0, 7.0, 9.0]

# `cross`

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

Computes the cross product of two vectors.

## Examples

    iex> a = BB.Math.Vec3.new(1, 0, 0)
    iex> b = BB.Math.Vec3.new(0, 1, 0)
    iex> c = BB.Math.Vec3.cross(a, b)
    iex> BB.Math.Vec3.to_list(c)
    [0.0, 0.0, 1.0]

# `distance`

```elixir
@spec distance(t(), t()) :: float()
```

Computes the distance between two points (as vectors).

## Examples

    iex> a = BB.Math.Vec3.new(0, 0, 0)
    iex> b = BB.Math.Vec3.new(3, 4, 0)
    iex> BB.Math.Vec3.distance(a, b)
    5.0

# `dot`

```elixir
@spec dot(t(), t()) :: float()
```

Computes the dot product of two vectors.

## Examples

    iex> a = BB.Math.Vec3.new(1, 2, 3)
    iex> b = BB.Math.Vec3.new(4, 5, 6)
    iex> BB.Math.Vec3.dot(a, b)
    32.0

# `from_list`

```elixir
@spec from_list([number()]) :: t()
```

Creates a vector from a list of three numbers.

## Examples

    iex> v = BB.Math.Vec3.from_list([1, 2, 3])
    iex> BB.Math.Vec3.to_list(v)
    [1.0, 2.0, 3.0]

# `from_tensor`

```elixir
@spec from_tensor(Nx.Tensor.t()) :: t()
```

Creates a vector from an existing `{3}` tensor.

# `lerp`

```elixir
@spec lerp(t(), t(), number()) :: t()
```

Linearly interpolates between two vectors.

## Examples

    iex> a = BB.Math.Vec3.new(0, 0, 0)
    iex> b = BB.Math.Vec3.new(10, 10, 10)
    iex> c = BB.Math.Vec3.lerp(a, b, 0.5)
    iex> BB.Math.Vec3.to_list(c)
    [5.0, 5.0, 5.0]

# `magnitude`

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

Computes the magnitude (length) of a vector.

## Examples

    iex> v = BB.Math.Vec3.new(3, 4, 0)
    iex> BB.Math.Vec3.magnitude(v)
    5.0

# `magnitude_squared`

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

Computes the squared magnitude of a vector.

More efficient than `magnitude/1` when you only need to compare lengths.

## Examples

    iex> v = BB.Math.Vec3.new(3, 4, 0)
    iex> BB.Math.Vec3.magnitude_squared(v)
    25.0

# `negate`

```elixir
@spec negate(t()) :: t()
```

Negates a vector.

## Examples

    iex> v = BB.Math.Vec3.new(1, -2, 3)
    iex> n = BB.Math.Vec3.negate(v)
    iex> BB.Math.Vec3.to_list(n)
    [-1.0, 2.0, -3.0]

# `new`

```elixir
@spec new(number(), number(), number()) :: t()
```

Creates a new vector from x, y, z components.

## Examples

    iex> v = BB.Math.Vec3.new(1, 2, 3)
    iex> {BB.Math.Vec3.x(v), BB.Math.Vec3.y(v), BB.Math.Vec3.z(v)}
    {1.0, 2.0, 3.0}

# `normalise`

```elixir
@spec normalise(t()) :: t()
```

Normalises a vector to unit length.

Returns zero vector if input has zero magnitude.

## Examples

    iex> v = BB.Math.Vec3.new(3, 0, 0)
    iex> n = BB.Math.Vec3.normalise(v)
    iex> BB.Math.Vec3.to_list(n)
    [1.0, 0.0, 0.0]

# `scale`

```elixir
@spec scale(t(), number()) :: t()
```

Scales a vector by a scalar.

## Examples

    iex> v = BB.Math.Vec3.new(1, 2, 3)
    iex> s = BB.Math.Vec3.scale(v, 2)
    iex> BB.Math.Vec3.to_list(s)
    [2.0, 4.0, 6.0]

# `subtract`

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

Subtracts vector b from vector a.

## Examples

    iex> a = BB.Math.Vec3.new(4, 5, 6)
    iex> b = BB.Math.Vec3.new(1, 2, 3)
    iex> c = BB.Math.Vec3.subtract(a, b)
    iex> BB.Math.Vec3.to_list(c)
    [3.0, 3.0, 3.0]

# `tensor`

```elixir
@spec tensor(t()) :: Nx.Tensor.t()
```

Returns the underlying tensor.

# `to_list`

```elixir
@spec to_list(t()) :: [float()]
```

Returns the components as a list [x, y, z].

# `unit_x`

```elixir
@spec unit_x() :: t()
```

Returns the unit X vector (1, 0, 0).

# `unit_y`

```elixir
@spec unit_y() :: t()
```

Returns the unit Y vector (0, 1, 0).

# `unit_z`

```elixir
@spec unit_z() :: t()
```

Returns the unit Z vector (0, 0, 1).

# `x`

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

Returns the X component.

# `y`

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

Returns the Y component.

# `z`

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

Returns the Z component.

# `zero`

```elixir
@spec zero() :: t()
```

Returns the zero vector.

## Examples

    iex> v = BB.Math.Vec3.zero()
    iex> {BB.Math.Vec3.x(v), BB.Math.Vec3.y(v), BB.Math.Vec3.z(v)}
    {0.0, 0.0, 0.0}

---

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