Transform

template<IsFloatingPoint T>
struct Transform

Transform with position, rotation, scale and shear, and kinematic quantities.

Represents a 3D transformation including translation, rotation, scale, shear, velocity, and angular velocity. Provides methods for conversion to matrix, inversion, composition, and application to points, directions, normals, and velocities.

A point is placed at position + rotation * S * point, where S is the upper triangular scale-and-shear matrix

| scale.x  shear.x  shear.y |
| 0        scale.y  shear.z |
| 0        0        scale.z |

the form Embree’s quaternion decomposition takes. A node is given no shear, but combining frames can need one: a child turned within a parent scaled unevenly is slanted by it, which no rotation and scale can describe. Every combination is exactly a rotation times such an S, so composing and inverting keep it.

Template Parameters:

T – Floating point type (float or double)

Public Functions

template<IsFloatingPoint U>
explicit operator Transform<U>() const

Convert this Transform to another floating point type.

Template Parameters:

U – Target floating point type

Returns:

Transform<U> Converted transform

inline bool has_shear() const

Whether the transform has any shear.

Mat3<T> scale_shear_matrix() const

The upper triangular scale-and-shear matrix S (see Transform).

The upper triangular scale-and-shear matrix (see Transform).

Returns:

Mat3<T> The matrix, column-major as glm’s are

Mat4<T> to_matrix() const

Convert the transform to a 4x4 matrix (T * R * S), which places points as apply_to_point() does: M * (p, 1).

Mat4 is column-major, as glm’s matrices are: the first three columns are the rotation times the scale-and-shear matrix, and the fourth is the translation.

Returns:

Mat4<T> Transformation matrix

RTCQuaternionDecomposition to_embree() const

Convert the transform to embree pose information.

Returns:

RTCQuaternionDecomposition Embree pose information

std::array<float, 12> to_embree_matrix() const

The transform as Embree’s 3x4 column-major matrix (RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR).

Convert the transform to Embree’s 3x4 column-major matrix.

Its first three columns are the rotation times the scale-and-shear matrix, and its last the translation: the same transform as to_embree() gives, as a matrix.

Returns:

std::array<float, 12> The matrix, column by column

std::string to_string() const
Transform<T> inverse() const

Compute the inverse of the transform.

Its rotation is this one’s inverse and its scale this one’s reciprocal, when the scale is even along the axes the rotation mixes. Otherwise the inverse of rotating, then scaling, is unscaling, then rotating back, which no rotation and scale along the axes describe: its linear part is factored into a rotation, scale and shear.

Returns:

Transform<T> Inverse transform

Transform<T> operator*(const Transform<T> &b) const

Compose this transform with another.

The rotations compose, and the scales multiply, when b neither shears nor is turned between axes this transform scales differently. Otherwise this transform’s scale slants b, and the product of the two linear parts is factored into a rotation, scale and shear.

Parameters:

b – Other transform

Returns:

Transform<T> Composed transform

Vec3<T> apply_to_point(const Vec3<T> &point) const

Apply the transform to a point (scale and shear, rotate, translate).

Parameters:

point – Point to transform

Returns:

Vec3<T> Transformed point

Vec3<T> apply_to_direction(const Vec3<T> &dir) const

Apply the transform to a direction (scale and shear, rotate).

Parameters:

dir – Direction to transform

Returns:

Vec3<T> Transformed direction

Vec3<T> apply_to_normal(const Vec3<T> &normal) const

Apply the transform to a surface’s normal: by the inverse transpose of what turns its tangents (apply_to_direction()), which keeps it at right angles to them when the scale is uneven or shears. The same direction as apply_to_direction() gives, for an even scale. Not normalized.

Parameters:

normal – Normal to transform

Returns:

Vec3<T> Transformed normal

Vec3<T> apply_to_velocity(const Vec3<T> &vel) const

Apply the transform to a velocity (scale, rotate, add velocity).

Parameters:

vel – Velocity to transform

Returns:

Vec3<T> Transformed velocity

Vec3<T> apply_to_angular_velocity(const Vec3<T> &ang_vel) const

Apply the transform to an angular velocity (rotate, add angular velocity).

Parameters:

ang_vel – Angular velocity to transform

Returns:

Vec3<T> Transformed angular velocity

Vec3<T> velocity_of_point(const Vec3<T> &point) const

Compute the velocity of a point rigidly attached to this frame.

Parameters:

point – Point in world coordinates

Returns:

Vec3<T> Velocity of the point

Vec3<T> velocity_of_local_point(const Vec3<T> &local_point) const

Compute the velocity of a point specified in local coordinates.

Parameters:

local_point – Point in local coordinates

Returns:

Vec3<T> Velocity of the point

Public Members

Vec3<T> position = {0, 0, 0}
Rotation<T> rotation = {}
Vec3<T> scale = {1, 1, 1}
Vec3<T> velocity = {0, 0, 0}

Linear velocity of this frame’s origin, expressed in the PARENT frame’s axes. operator* composes it accordingly (rotating a child’s velocity only by ancestor rotations, never by the child’s own rotation).

Vec3<T> angular_velocity = {0, 0, 0}

Angular velocity of this frame, expressed in the PARENT frame’s axes. This convention is relied upon by operator*, inverse(), apply_to_angular_velocity(), and velocity_of_point(). Body-frame rates must be re-expressed in parent axes (omega_parent = rotation * omega_body) before being stored here.

Vec3<T> shear = {0, 0, 0}

The scale-and-shear matrix’s entries above its diagonal (see Transform): x is its xy entry (how far a point moves along x with its y), y its xz entry, and z its yz entry. Zero, but where combining frames slants something.