Imath
<navlinks>
<page>

# Concepts

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 a substitute for 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/ImathMatrix.h>
    #include <Imath/ImathVec.h>
    #include <iostream>
    #include <cassert>

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

        Imath::M44f M;
        const Imath::V3f t(1.0f, 2.0f, 3.0f);
        M.translate (t);

        Imath::V3f p;
        M.multVecMatrix(v, p);

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

        Imath::V3f vt = v + t;
        assert (p.equalWithAbsError(vt, 1e-6f));

        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}\]
</page>