|
|
|
|
namespace Magnum { namespace Math {
|
|
|
|
|
/** @page matrix-vector Operations with matrices and vectors
|
|
|
|
|
|
|
|
|
|
@brief Introduction to essential classes of the graphics pipeline.
|
|
|
|
|
|
|
|
|
|
@tableofcontents
|
|
|
|
|
|
|
|
|
|
Matrices and vectors are the most important part of graphics programming and
|
|
|
|
|
one of goals of %Magnum is to make their usage as intuitive as possible. This
|
|
|
|
|
page will overview their usage and introduce some tricks to make your life
|
|
|
|
|
easier.
|
|
|
|
|
|
|
|
|
|
@section matrix-vector-hierarchy Matrix and vector classes
|
|
|
|
|
|
|
|
|
|
%Magnum has three main matrix and vector classes: RectangularMatrix, (square)
|
|
|
|
|
Matrix and Vector. To achieve greatest code reuse, %Matrix is internally
|
|
|
|
|
square %RectangularMatrix and %Vector is internally one-column
|
|
|
|
|
%RectangularMatrix. Both vectors and matrices can have arbitrary size (known
|
|
|
|
|
at compile time) and can store any meaningful type.
|
|
|
|
|
|
|
|
|
|
Each subclass brings some specialization to its superclass and for most common
|
|
|
|
|
vector and matrix sizes there are specialized classes Matrix3 and Matrix4,
|
|
|
|
|
implementing various transformation in 2D and 3D, Vector2, Vector3 and Vector4,
|
|
|
|
|
implementing direct access to named components. Functions of each class try to
|
|
|
|
|
return the most specialized type known to make subsequent operations more
|
|
|
|
|
convenient - columns of %RectangularMatrix are returned as %Vector, but when
|
|
|
|
|
accessing columns of e.g. %Matrix3, they are returned as %Vector3.
|
|
|
|
|
|
|
|
|
|
There are also even more specialized subclasses - Point2D, Point3D for
|
|
|
|
|
creating points with homogeneous coordinates and Color3, Color4 for color
|
|
|
|
|
handling and conversion.
|
|
|
|
|
|
|
|
|
|
@section matrix-vector-construction Constructing matrices and vectors
|
|
|
|
|
|
|
|
|
|
Default constructors of RectangularMatrix and Vector (and Vector2, Vector3,
|
|
|
|
|
Vector4, Color3) create zero-filled objects. Matrix (and Matrix3, Matrix4) is
|
|
|
|
|
by default constructed as identity matrix. Point2D and Point3D have
|
|
|
|
|
homogeneous component set to one, Color4 has alpha value set to opaque.
|
|
|
|
|
@code
|
|
|
|
|
RectangularMatrix<2, 3, int> a; // zero-filled
|
|
|
|
|
Vector<3, int> b; // zero-filled
|
|
|
|
|
|
|
|
|
|
Matrix<3, int> identity; // diagonal set to 1
|
|
|
|
|
Matrix<3, int> zero(Matrix<3, int>::Zero); // zero-filled
|
|
|
|
|
|
|
|
|
|
Point2D<int> c; // {0, 0, 1}
|
|
|
|
|
Point3D<int> d; // {0, 0, 0, 1}
|
|
|
|
|
|
|
|
|
|
Color4<float> black1; // {0.0f, 0.0f, 0.0f, 1.0f}
|
|
|
|
|
Color4<unsigned char> black2; // {0, 0, 0, 255}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Most common and most efficient way to create matrix or vector is to pass
|
|
|
|
|
values of all components to the constructor.
|
|
|
|
|
@code
|
|
|
|
|
Matrix3<int> mat(0, 1, 2,
|
|
|
|
|
3, 4, 5,
|
|
|
|
|
6, 7, 8); // column-major (see explanation why below)
|
|
|
|
|
|
|
|
|
|
Vector3<int> vec(0, 1, 2);
|
|
|
|
|
@endcode
|
|
|
|
|
All constructors check number of passed arguments and the errors are catched
|
|
|
|
|
at compile time.
|
|
|
|
|
|
|
|
|
|
You can specify all components of vector or whole diagonal of square matrix at
|
|
|
|
|
once:
|
|
|
|
|
@code
|
|
|
|
|
Matrix3<int> diag(Matrix3<int>::Identity, 2); // diagonal set to 2, zeros elsewhere
|
|
|
|
|
Vector3<int> fill(10); // {10, 10, 10}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Vectors are commonly used to specify various axes and scaling coefficients in
|
|
|
|
|
transformations, you can use convenience functions instead of typing out all
|
|
|
|
|
other elements:
|
|
|
|
|
@code
|
|
|
|
|
Matrix4::rotation(deg(5.0f), Vector3::xAxis()); // {1.0f, 0.0f, 0.0f}
|
|
|
|
|
Matrix3::translation(Vector2::yAxis(2.0f)); // {0.0f, 2.0f}
|
|
|
|
|
Matrix4::scaling(Vector3::zScale(-10.0f)); // {1.0f, 1.0f, -10.0f}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
It is possible to create matrices from other matrices and vectors with the
|
|
|
|
|
same row count; vectors from vector and scalar:
|
|
|
|
|
@code
|
|
|
|
|
RectangularMatrix<2, 3, int> a;
|
|
|
|
|
Vector3<int> b, c;
|
|
|
|
|
Matrix3<int> mat = Matrix3<int>::from(b, a, c);
|
|
|
|
|
Vector<8, int> vec = Vector<8, int>::from(1, b, 2, c);
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
It is also possible to create them from an C-style array. The function does
|
|
|
|
|
simple type cast without any copying, so it's possible to conveniently operate
|
|
|
|
|
on the array itself:
|
|
|
|
|
@code
|
|
|
|
|
int[] mat = { 2, 4, 6,
|
|
|
|
|
1, 3, 5 };
|
|
|
|
|
RectangularMatrix<2, 3, int>::from(mat) *= 2; // mat == { 4, 8, 12, 2, 6, 10 }
|
|
|
|
|
@endcode
|
|
|
|
|
Note that unlike constructors, this function has no way to check whether the
|
|
|
|
|
array is long enough to contain all elements, so use with caution.
|
|
|
|
|
|
|
|
|
|
You can also convert between data types:
|
|
|
|
|
@code
|
|
|
|
|
Vector4<float> floating(1.3f, 2.7f, -15.0f, 7.0f);
|
|
|
|
|
Vector4<int> integral(Vector4<int>::from(floating)); // {1, 2, -15, 7}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@section matrix-vector-component-access Accessing matrix and vector components
|
|
|
|
|
|
|
|
|
|
Column vectors of matrices and vector components can be accessed using square
|
|
|
|
|
brackets, there is also round bracket operator for accessing matrix components
|
|
|
|
|
directly:
|
|
|
|
|
@code
|
|
|
|
|
RectangularMatrix<3, 2, int> a;
|
|
|
|
|
a[2] /= 2; // third column (column major indexing, see explanation below)
|
|
|
|
|
a[0][1] = 5; // first column, second element
|
|
|
|
|
a(0, 1) += 3; // first column, second element (preferred)
|
|
|
|
|
|
|
|
|
|
Vector<3, int> b;
|
|
|
|
|
b[1] = 1; // second element
|
|
|
|
|
@endcode
|
|
|
|
|
For accessing matrix element prefer round bracket operator, as it is possibly
|
|
|
|
|
faster than the double square brackets (but never slower) and isn't prone to
|
|
|
|
|
compiler mis-optimizations.
|
|
|
|
|
|
|
|
|
|
Fixed-size vector subclasses have functions for accessing named components
|
|
|
|
|
and subparts:
|
|
|
|
|
@code
|
|
|
|
|
Vector4<int> a;
|
|
|
|
|
int x = a.x();
|
|
|
|
|
a.y() += 5;
|
|
|
|
|
|
|
|
|
|
Vector3<int> xyz = a.xyz();
|
|
|
|
|
xyz.xy() *= 5;
|
|
|
|
|
@endcode
|
|
|
|
|
Color3 and Color4 name their components `rgba` instead of `xyzw`.
|
|
|
|
|
|
|
|
|
|
For more involved operations with components there are two swizzle() functions,
|
|
|
|
|
they have the same features, but one is guaranteed to do most of the work at
|
|
|
|
|
compile-time, while the second has more convenient syntax:
|
|
|
|
|
@code
|
|
|
|
|
Vector4<int> original(-1, 2, 3, 4);
|
|
|
|
|
Vector4<int> bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, -1, 4 }
|
|
|
|
|
Vector<6, int> a10rgb = swizzle(original, "a10rgb"); // { 4, 1, 0, -1, 2, 3 }
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@section matrix-vector-column-major Matrices are column-major and vectors are columns
|
|
|
|
|
|
|
|
|
|
OpenGL matrices are column-major, thus it is reasonable to have matrices in
|
|
|
|
|
%Magnum also column major (and vectors as columns). This has naturally some
|
|
|
|
|
implications and it may differ from what is common in mathematics:
|
|
|
|
|
|
|
|
|
|
- Order of template arguments in specification of RectangularMatrix is also
|
|
|
|
|
column-major:
|
|
|
|
|
@code
|
|
|
|
|
RectangularMatrix<2, 3, int> mat; // two columns, three rows
|
|
|
|
|
@endcode
|
|
|
|
|
- Order of components in matrix constructors is also column-major, so the
|
|
|
|
|
elements passed in constructor doesn't need to be reordered internally
|
|
|
|
|
before putting them into data array:
|
|
|
|
|
@code
|
|
|
|
|
Matrix3<int> mat(0, 1, 2,
|
|
|
|
|
3, 4, 5,
|
|
|
|
|
6, 7, 8); // first column is {0, 1, 2}
|
|
|
|
|
@endcode
|
|
|
|
|
- Element accessing order is also column-major. It costs virtually no time to
|
|
|
|
|
return reference to portion of data array as column vector, thus the bracket
|
|
|
|
|
operator is accessing columns. Returned vector has also its own bracket
|
|
|
|
|
operator, which is indexing rows. To avoid confusion, first parameter of
|
|
|
|
|
round bracket operator is thus also column index.
|
|
|
|
|
@code
|
|
|
|
|
mat[0] *= 2; // first column
|
|
|
|
|
mat[2][0] = 5; // first element of first column vector
|
|
|
|
|
mat(2, 0) += 3; // first element of first column
|
|
|
|
|
@endcode
|
|
|
|
|
- Various algorithms which commonly operate on matrix rows (such as
|
|
|
|
|
@ref Algorithms::GaussJordan "Gauss-Jordan elimination") have faster
|
|
|
|
|
alternatives which operate on columns. It's then up to user decision to
|
|
|
|
|
operate with transposed matrices or use the slower non-transposed
|
|
|
|
|
alternative of the algorithm.
|
|
|
|
|
*/
|
|
|
|
|
}}
|