BB.Math.Transform (bb v0.15.0)

View Source

Homogeneous transformation matrices for 3D transformations, backed by an Nx tensor.

All transforms are represented as 4x4 matrices in row-major order:

| R11 R12 R13 Tx |
| R21 R22 R23 Ty |
| R31 R32 R33 Tz |
|  0   0   0   1 |

Where the upper-left 3x3 is the rotation matrix and the rightmost column is the translation vector.

Conventions

  • All angles are in radians
  • All distances are in metres
  • Rotations use XYZ Euler angles (roll-pitch-yaw)
  • Coordinate frame follows right-hand rule

Examples

iex> t = BB.Math.Transform.identity()
iex> BB.Math.Transform.get_translation(t) |> BB.Math.Vec3.to_list()
[0.0, 0.0, 0.0]

iex> t = BB.Math.Transform.translation(BB.Math.Vec3.new(1, 2, 3))
iex> BB.Math.Transform.get_translation(t) |> BB.Math.Vec3.to_list()
[1.0, 2.0, 3.0]

Summary

Functions

Apply a transform to a 3D point, returning the transformed point.

Compose (multiply) two transformation matrices.

Compose a list of transforms in order.

Create a rotation transform around an arbitrary axis using the axis-angle representation.

Create a transformation matrix from position and orientation.

Create a 4x4 transformation matrix from position and quaternion orientation.

Create a 4x4 transformation matrix from a quaternion (rotation only).

Creates a transform from an existing {4, 4} tensor.

Get the forward vector (Z-axis) from a transformation matrix.

Extract a quaternion from a transform.

Get the right vector (X-axis) from a transformation matrix.

Get the rotation matrix (3x3) from a transform.

Get the translation component of a transform as a Vec3.

Get the up vector (Y-axis) from a transformation matrix.

Create a 4x4 identity transformation matrix.

Compute the inverse of a transformation matrix.

Create a rotation matrix around the X axis (roll).

Create a rotation matrix around the Y axis (pitch).

Create a rotation matrix around the Z axis (yaw).

Returns the underlying {4, 4} tensor.

Create a pure translation matrix from a Vec3.

Create a translation transform along an arbitrary axis.

Types

t()

@type t() :: %BB.Math.Transform{tensor: Nx.Tensor.t()}

Functions

apply_to_point(transform, vec3)

@spec apply_to_point(t(), BB.Math.Vec3.t()) :: BB.Math.Vec3.t()

Apply a transform to a 3D point, returning the transformed point.

Examples

iex> t = BB.Math.Transform.translation(BB.Math.Vec3.new(1, 2, 3))
iex> p = BB.Math.Transform.apply_to_point(t, BB.Math.Vec3.zero())
iex> BB.Math.Vec3.to_list(p)
[1.0, 2.0, 3.0]

compose(transform1, transform2)

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

Compose (multiply) two transformation matrices.

compose(a, b) returns the transform that applies a first, then b.

Examples

iex> t1 = BB.Math.Transform.translation(BB.Math.Vec3.new(1, 0, 0))
iex> t2 = BB.Math.Transform.translation(BB.Math.Vec3.new(0, 2, 0))
iex> t = BB.Math.Transform.compose(t1, t2)
iex> BB.Math.Transform.get_translation(t) |> BB.Math.Vec3.to_list()
[1.0, 2.0, 0.0]

compose_all(list)

@spec compose_all([t()]) :: t()

Compose a list of transforms in order.

Examples

iex> transforms = [
...>   BB.Math.Transform.translation(BB.Math.Vec3.new(1, 0, 0)),
...>   BB.Math.Transform.translation(BB.Math.Vec3.new(0, 1, 0)),
...>   BB.Math.Transform.translation(BB.Math.Vec3.new(0, 0, 1))
...> ]
iex> t = BB.Math.Transform.compose_all(transforms)
iex> BB.Math.Transform.get_translation(t) |> BB.Math.Vec3.to_list()
[1.0, 1.0, 1.0]

from_axis_angle(axis, angle)

@spec from_axis_angle(BB.Math.Vec3.t(), float()) :: t()

Create a rotation transform around an arbitrary axis using the axis-angle representation.

Uses Rodrigues' rotation formula to compute the rotation matrix.

Parameters

  • axis: normalised axis Vec3
  • angle: rotation angle in radians

Examples

iex> axis = BB.Math.Vec3.unit_z()
iex> t = BB.Math.Transform.from_axis_angle(axis, :math.pi() / 2)
iex> p = BB.Math.Transform.apply_to_point(t, BB.Math.Vec3.unit_x())
iex> {Float.round(BB.Math.Vec3.x(p), 6), Float.round(BB.Math.Vec3.y(p), 6)}
{0.0, 1.0}

from_origin(arg1)

@spec from_origin(%{
  position: {float(), float(), float()},
  orientation: {float(), float(), float()}
}) ::
  t()

Create a transformation matrix from position and orientation.

The origin map should have:

  • position: {x, y, z} in metres
  • orientation: {roll, pitch, yaw} in radians

Rotation is applied in XYZ order (roll around X, then pitch around Y, then yaw around Z).

Examples

iex> origin = %{position: {1.0, 2.0, 3.0}, orientation: {0.0, 0.0, 0.0}}
iex> t = BB.Math.Transform.from_origin(origin)
iex> BB.Math.Transform.get_translation(t) |> BB.Math.Vec3.to_list()
[1.0, 2.0, 3.0]

from_position_quaternion(pos, q)

@spec from_position_quaternion(BB.Math.Vec3.t(), BB.Math.Quaternion.t()) :: t()

Create a 4x4 transformation matrix from position and quaternion orientation.

Examples

iex> pos = BB.Math.Vec3.new(1, 2, 3)
iex> q = BB.Math.Quaternion.identity()
iex> t = BB.Math.Transform.from_position_quaternion(pos, q)
iex> BB.Math.Transform.get_translation(t) |> BB.Math.Vec3.to_list()
[1.0, 2.0, 3.0]

from_quaternion(q)

@spec from_quaternion(BB.Math.Quaternion.t()) :: t()

Create a 4x4 transformation matrix from a quaternion (rotation only).

The resulting matrix has the quaternion's rotation in the upper-left 3x3 and zero translation.

Examples

iex> q = BB.Math.Quaternion.from_axis_angle(BB.Math.Vec3.unit_z(), :math.pi() / 2)
iex> t = BB.Math.Transform.from_quaternion(q)
iex> p = BB.Math.Transform.apply_to_point(t, BB.Math.Vec3.unit_x())
iex> {Float.round(BB.Math.Vec3.x(p), 6), Float.round(BB.Math.Vec3.y(p), 6)}
{0.0, 1.0}

from_tensor(tensor)

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

Creates a transform from an existing {4, 4} tensor.

get_forward_vector(transform)

@spec get_forward_vector(t()) :: BB.Math.Vec3.t()

Get the forward vector (Z-axis) from a transformation matrix.

The forward vector is the third column of the rotation matrix, representing the direction the local Z-axis points in world coordinates.

Examples

iex> t = BB.Math.Transform.identity()
iex> fwd = BB.Math.Transform.get_forward_vector(t)
iex> BB.Math.Vec3.to_list(fwd)
[0.0, 0.0, 1.0]

get_quaternion(transform)

@spec get_quaternion(t()) :: BB.Math.Quaternion.t()

Extract a quaternion from a transform.

Extracts the 3x3 rotation portion and converts it to a unit quaternion.

Examples

iex> t = BB.Math.Transform.rotation_z(:math.pi() / 2)
iex> q = BB.Math.Transform.get_quaternion(t)
iex> {_axis, angle} = BB.Math.Quaternion.to_axis_angle(q)
iex> Float.round(angle, 6)
1.570796

get_right_vector(transform)

@spec get_right_vector(t()) :: BB.Math.Vec3.t()

Get the right vector (X-axis) from a transformation matrix.

The right vector is the first column of the rotation matrix, representing the direction the local X-axis points in world coordinates.

Examples

iex> t = BB.Math.Transform.identity()
iex> right = BB.Math.Transform.get_right_vector(t)
iex> BB.Math.Vec3.to_list(right)
[1.0, 0.0, 0.0]

get_rotation(transform)

@spec get_rotation(t()) :: Nx.Tensor.t()

Get the rotation matrix (3x3) from a transform.

get_translation(transform)

@spec get_translation(t()) :: BB.Math.Vec3.t()

Get the translation component of a transform as a Vec3.

get_up_vector(transform)

@spec get_up_vector(t()) :: BB.Math.Vec3.t()

Get the up vector (Y-axis) from a transformation matrix.

The up vector is the second column of the rotation matrix, representing the direction the local Y-axis points in world coordinates.

Examples

iex> t = BB.Math.Transform.identity()
iex> up = BB.Math.Transform.get_up_vector(t)
iex> BB.Math.Vec3.to_list(up)
[0.0, 1.0, 0.0]

identity()

@spec identity() :: t()

Create a 4x4 identity transformation matrix.

Examples

iex> t = BB.Math.Transform.identity()
iex> BB.Math.Transform.tensor(t) |> Nx.to_list()
[[1.0, 0.0, 0.0, 0.0],
 [0.0, 1.0, 0.0, 0.0],
 [0.0, 0.0, 1.0, 0.0],
 [0.0, 0.0, 0.0, 1.0]]

inverse(transform)

@spec inverse(t()) :: t()

Compute the inverse of a transformation matrix.

For a valid transformation matrix, this computes the inverse transform.

rotation_x(angle)

@spec rotation_x(float()) :: t()

Create a rotation matrix around the X axis (roll).

Examples

iex> t = BB.Math.Transform.rotation_x(:math.pi() / 2)
iex> v = BB.Math.Transform.apply_to_point(t, BB.Math.Vec3.new(0, 1, 0))
iex> Float.round(BB.Math.Vec3.z(v), 6)
1.0

rotation_y(angle)

@spec rotation_y(float()) :: t()

Create a rotation matrix around the Y axis (pitch).

rotation_z(angle)

@spec rotation_z(float()) :: t()

Create a rotation matrix around the Z axis (yaw).

tensor(transform)

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

Returns the underlying {4, 4} tensor.

translation(v)

@spec translation(BB.Math.Vec3.t()) :: t()

Create a pure translation matrix from a Vec3.

Examples

iex> t = BB.Math.Transform.translation(BB.Math.Vec3.new(1, 2, 3))
iex> BB.Math.Transform.get_translation(t) |> BB.Math.Vec3.to_list()
[1.0, 2.0, 3.0]

translation_along(axis, distance)

@spec translation_along(BB.Math.Vec3.t(), float()) :: t()

Create a translation transform along an arbitrary axis.

Parameters

  • axis: normalised axis Vec3
  • distance: translation distance in metres

Examples

iex> axis = BB.Math.Vec3.unit_x()
iex> t = BB.Math.Transform.translation_along(axis, 2.5)
iex> BB.Math.Transform.get_translation(t) |> BB.Math.Vec3.to_list()
[2.5, 0.0, 0.0]