Overview

Imath is a basic, light-weight, and efficient C++ representation of 2D and 3D vectors and matrices and other simple but useful mathematical objects, functions, and data types common in computer graphics applications, including the half 16-bit floating-point type.

Imath also includes optional python bindings for all types and functions, including optimized implementations of vector and matrix arrays.

The Imath library emphasizes simplicity, ease of use, correctness and verifiability, performance, and breadth of adoption. Imath is not intended to be a comprehensive linear algebra or numerical analysis package.

Imath is not Eigen! It’s not a full-featured linear algebra package, and it doesn’t represent vectors and matrices of arbitrary dimension. Its greatest utility is as a geometric data representation, primarily for 2D images and 3D scenes and coordinate transformations, along with an accompanying set of utility methods and functions.

Example

A basic program:

#include <Imath/ImathVec.h>
#include <iostream>

int
main()
{
    Imath::V3f v (3.0, 4.0, 5.0);

    v.normalize();

    Imath::M33f M;
    M.translate (1.0, 2.0, 3.0);
    Imath::V3f p = v * M;

    std::cout << "What's your vector, Victor? " << p << std::endl;

    return 0;
}

Matrices Are Row-Major

Imath stores matrices in row-major layout, originally inspired by compatibility with OpenGL matrices.

A matrix described as:

\[\begin{split}\begin{bmatrix} m_{00} & m_{01} & m_{02} & m_{03} \\ m_{10} & m_{11} & m_{12} & m_{13} \\ m_{20} & m_{21} & m_{22} & m_{23} \\ m_{30} & m_{31} & m_{32} & m_{33} \\ \end{bmatrix}\end{split}\]

is laid out in memory as:

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

\(m_{00}\)

\(m_{01}\)

\(m_{02}\)

\(m_{03}\)

\(m_{10}\)

\(m_{11}\)

\(m_{12}\)

\(m_{13}\)

\(m_{20}\)

\(m_{21}\)

\(m_{22}\)

\(m_{23}\)

\(m_{30}\)

\(m_{31}\)

\(m_{32}\)

\(m_{33}\)

A matrix representing a homogeneous transform has a right-hand column of \(\begin{bmatrix} 0 & 0 & 0 & 1\end{bmatrix}\) and the translation component across the bottom row.

As a result, it is best to think of Imath vectors as row-vectors, and vector-matrix multiplication with the vector on the left and matrix on the right:

\[\begin{split}\begin{bmatrix} v_{0}' & v_{1}' & v_{2}' & 1' \end{bmatrix} = \begin{bmatrix} v_{0} & v_{1} & v_{2} & 1 \end{bmatrix} \begin{bmatrix} m_{00} & m_{01} & m_{02} & 0 \\ m_{10} & m_{11} & m_{12} & 0 \\ m_{20} & m_{21} & m_{22} & 0 \\ m_{30} & m_{31} & m_{32} & 1 \end{bmatrix}\end{split}\]

This further implies that you should interpret local transformations as pre-multiplication:

M44f M;
M.translate (tx, ty, tz);
m.rotate (r, 0, 0);
m.scale (s);
\[\begin{split}\begin{bmatrix} m_{00} & m_{01} & m_{02} & m_{03} \\ m_{10} & m_{11} & m_{12} & m_{13} \\ m_{20} & m_{21} & m_{22} & m_{23} \\ m_{30} & m_{31} & m_{32} & m_{33} \\ \end{bmatrix} = \begin{bmatrix} s & 0 & 0 & 0 \\ 0 & s & 0 & 0 \\ 0 & 0 & s & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos(r) & \sin(r) & 0 \\ 0 & -\sin(r) & \cos(r) & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ tx & ty & tz & 1 \\ \end{bmatrix}\end{split}\]

About

Imath originated at Industrial Light & Magic in the late 1990’s and early 2000’s, and it was originally distributed publicly as a component of OpenEXR. Imath is now a project of the Academy Software Foundation and is still maintained by the OpenEXR project.

Imath is Version 3 because it was previously distributed as a component of OpenEXR v1 and v2.