@ -33,56 +33,56 @@ namespace Magnum {
@m_footernavigation
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. They
are contained in @ref Math namespace and common variants also have aliases in
root @ref Magnum namespace. See the documentation of these namespaces for more
information about usage with CMake.
one of Magnum goals is to make their usage as intuitive as possible.
@section matrix-vector-hierarchy Matrix and vector classes
Magnum has three main matrix and vector classes: @ref Math::RectangularMatrix,
(square) @ref Math::Matrix and @ref Math::Vector. To maximize code reuse,
@ref Math::Matrix is internally square @ref Math::RectangularMatrix and
@ref Math::RectangularMatrix is internally array of one or more @ref Math::Vector
instances. Both vectors and matrices can have arbitrary size (known at compile
time) and can store any arithmetic type.
Each subclass brings some specialization to its superclass. For the most common
vector and matrix sizes there are specialized classes @ref Math::Matrix3 and
@ref Math::Matrix4, implementing various transformations in 2D and 3D and
@ref Math::Vector2, @ref Math::Vector3 and @ref Math::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 @ref Math::RectangularMatrix are returned as @ref Math::Vector, but
when accessing columns of e.g. @ref Math::Matrix3, they are returned as
Magnum has three main matrix and vector classes --- a
@ref Math::RectangularMatrix, a (square) @ref Math::Matrix and a
@ref Math::Vector. To maximize code reuse, the @ref Math::Matrix is internally
a square @ref Math::RectangularMatrix and a @ref Math::RectangularMatrix is
internally an array of one or more @ref Math::Vector instances. Both vectors
and matrices can have arbitrary size (known at compile time) and can store any
arithmetic type, including a @ref Half or e.g. a @ref Rad.
Each subclass brings some specialization to its superclass. The
@ref Math::Vector2, @ref Math::Vector3 and @ref Math::Vector4 classes implement
direct access to named components, @ref Math::Matrix adds determinant
calculation or matrix inversion and @ref Math::Matrix3 / @ref Math::Matrix4
implement 2D and 3D transformations. Functions of each class return the most
specialized type known to make subsequent operations more convenient ---
columns of @ref Math::RectangularMatrix are returned as a @ref Math::Vector,
but when accessing columns of e.g. @ref Math::Matrix3, they are returned as a
@ref Math::Vector3.
There are also even more specialized subclasses, e.g. @ref Math::Color3 and
@ref Math::Color4 for color handling and conversion.
Commonly used types have convenience aliases in @ref Magnum namespace, so you
can write e.g. @ref Vector3i instead of @ref Math::Vector3 "Math::Vector3<Int>".
See @ref types and @ref Magnum namespace documentation for more information.
Commonly used types have convenience aliases in the @ref Magnum namespace, so
you can write e.g. @ref Vector3i instead of
@ref Math::Vector3 "Math::Vector3<Int>". See @ref types and the @ref Magnum
namespace documentation for more information.
@section matrix-vector-construction Constructing matrices and vectors
The default constructors of @ref Math::RectangularMatrix and @ref Math::Vector (and
@ref Math::Vector2, @ref Math::Vector3, @ref Math::Vector4, @ref Math::Color3,
@ref Math::Color4) create zero-filled objects. @ref Math::Matrix (and
@ref Math::Matrix3, @ref Math::Matrix4) is by default constructed as an identity
matrix.
The default constructors of @ref Math::RectangularMatrix and @ref Math::Vector
(and @ref Math::Vector2, @ref Math::Vector3, @ref Math::Vector4,
@ref Math::Color3, @ref Math::Color4) create zero-filled objects, equivalent
to using the @ref Math::ZeroInit tag. @ref Math::Matrix (and
@ref Math::Matrix3, @ref Math::Matrix4) is by default constructed as an
identity matrix, equivalent to using the @ref Math::IdentityInit tag.
@snippet MagnumMath.cpp matrix-vector-construct
The most common and most efficient way to create a vector is to pass all values to
the constructor. A matrix is created by passing all the column vectors to the
constructor. These constructors check the number of passed arguments and errors
are caught at compile time.
The most common and most efficient way to create a vector is to pass all values
to t he constructor. A matrix is created by passing all *column* vectors to the
constructor. The constructors check correct number of passed arguments at
compile time.
@snippet MagnumMath.cpp matrix-vector-construct-value
You can specify all components of vectors or the diagonal of a square matrix
with a single value or create a diagonal matrix from a vector :
You can specify all components of a vector or a matrix with a single value, or
specify just values on the matrix diagonal :
@snippet MagnumMath.cpp matrix-vector-construct-diagonal
@ -92,26 +92,31 @@ zero or one which are useful for transformations:
@snippet MagnumMath.cpp matrix-vector-construct-axis
It is also possible to create matrices and vectors from a C-style array. The
function performs a simple type cast without copying anything, so it's possible to
conveniently operate on the array itself:
function performs a simple type cast without copying anything, so it's possible
to conveniently operate on the array itself:
@snippet MagnumMath.cpp matrix-vector-construct-from
@attention Note that, unlike a constructor, this function has no way to check
whether the array is long enough to contain all the elements, so use it with
caution.
whether the array is long enough to contain all the elements, so use it
with caution.
To make handling colors easier, their behavior is a bit different with a
richer feature set. Implicit construction of @ref Color4 from @ref Color3 will
set the alpha to the max value (thus @cpp 1.0f @ce for @ref Color4 and @cpp 255 @ce
for @ref Color4ub):
richer feature set. Implicit construction of @ref Math::Color4 from just the
RGB components will set the alpha to the max value (thus @cpp 1.0f @ce for
@ref Color4 and @cpp 255 @ce for @ref Color4ub):
@snippet MagnumMath.cpp matrix-vector-construct-color
Similar to axes in vectors, you can create single color shades too, or create
a RGB color from a HSV representation:
Similar to axes and scales in vectors, you can create single color shades too:
@snippet MagnumMath.cpp matrix-vector-construct-color-hue
@snippet MagnumMath.cpp matrix-vector-construct-color-axis
There are also builtin colorspace conversion functions --- it's possible to
create a RGB color from a HSV value, a linear color value from a sRGB
representation, or convert from CIE XYZ / xyY. And the other way as well:
@snippet MagnumMath.cpp matrix-vector-construct-color-colorspace
Finally, the namespace @ref Math::Literals provides convenient
@link Literals::operator""_rgb() operator""_rgb() @endlink /
@ -130,51 +135,49 @@ documentation for more information.
@section matrix-vector-component-access Accessing matrix and vector components
Column vectors of matrices and vector components can be accessed using square
brackets:
Column vectors of matrices and components of vector s can be accessed using
square brackets:
@snippet MagnumMath.cpp matrix-vector-access
Row vectors can be accessed too, but only for reading, and access is slower
due to the way the matrix is stored (see @ref matrix-vector-column-major "explanation below") :
due to the matrix being stored @ref matrix-vector-column-major "in column-major order" :
@snippet MagnumMath.cpp matrix-vector-access-row
Fixed-size vector subclasses have functions for accessing named components
and subparts:
and subparts using either `xyzw` or `rgba` :
@snippet MagnumMath.cpp matrix-vector-access-named
@ref Color3 and @ref Color4 name their components `rgba` instead of `xyzw`.
For more involved operations with components there is the @ref Math::gather()
For more involved operations with components there are the @ref Math::gather()
and @ref Math::scatter() functions:
@snippet MagnumMath.cpp matrix-vector-access-swizzle
@section matrix-vector-conversion Converting between different underlying types
All vector, matrix and other classes in @ref Math namespace can be
constructed from an instance with a different underlying type (e.g. convert
between integer and floating-point or betweeen @ref Float and @ref Double).
Unlike with plain C++ data types, the conversion is done via an *explicit*
constructor. That might sound inconvenient, but performing the conver sion
explicitly avoids common issues like precision loss (or, on the other hand,
expensive computation with unnecessarily high precision).
All classes in @ref Math namespace can be constructed from an instance with a
different underlying type (e.g. convert between integer and floating-point type
or betweeen @ref Float, @ref Double and @ref Half). Unlike with plain C++ data
types, the conversion is *explicit*. That might sound inconvenient at first,
but performing the conversion explicitly avoids common issues like preci sion
loss (or, on the other hand, expensive computation with unnecessarily high
precision).
To further emphasise the intent of conversion (so it doesn't look like an accident
or a typo), you are encouraged to use @cpp auto b = Type{a} @ce instead of
@cpp Type b{a} @ce.
To further emphasise the intent of conversion (so it doesn't look like an
accident or a typo), you are encouraged to use @cpp auto b = Type{a} @ce
instead of @cpp Type b{a} @ce.
@snippet MagnumMath.cpp matrix-vector-convert
For packing and unpacking use the @ref Math::pack() and @ref Math::unpack()
functions:
For packing floats into integers and unpacking them back use the
@ref Math::pack() and @ref Math::unpack() functions:
@snippet MagnumMath.cpp matrix-vector-convert-pack
See @ref matrix-vector-componentwise " below" for more information about other
available component-wise operations .
See below for more information about other available
@ref matrix-vector-componentwise "component-wise operations" .
@section matrix-vector-operations Operations with matrices and vectors
@ -189,10 +192,10 @@ As in GLSL, vectors can be also multiplied or divided component-wise:
@snippet MagnumMath.cpp matrix-vector-operations-multiply
When working with integral vectors (i.e. 24bit RGB values), it is often
desirable to multiply them with floating-point values but retain an integral result.
In Magnum, all multiplication/division operations involving integral vectors
will return integers within the result, you need to convert both arguments to the same
floating-point type to have floating-point result.
desirable to multiply them with floating-point values but retain an integral
result. In Magnum, all multiplication/division operations involving integral
vectors will return an integer result, you need to convert both arguments to
the same floating-point type to have a floating-point result.
@snippet MagnumMath.cpp matrix-vector-operations-integer
@ -205,16 +208,16 @@ Matrices can be added, subtracted and multiplied with matrix multiplication.
@snippet MagnumMath.cpp matrix-vector-operations-matrix
You can also multiply (properly sized) vectors with matrices. These operations
are just convenience shortcuts for multiplying with single-column matrices:
are equivalent to multiplying with single-column matrices:
@snippet MagnumMath.cpp matrix-vector-operations-multiply-matrix
@section matrix-vector-componentwise Component-wise and inter-vector operations
As shown above, vectors can be added and multiplied component-wise using the
@cpp + @ce or @cpp * @ce operator. You can use @ref Math::Vector::sum() "sum()"
and @ref Math::Vector::product() "product()" for sum or product of components
in one vector :
@cpp + @ce or @cpp * @ce operator. For a sum or product of components *inside*
a vector you can use @ref Math::Vector::sum() "sum()" and
@ref Math::Vector::product() "product()" instead :
@snippet MagnumMath.cpp matrix-vector-operations-componentwise
@ -225,19 +228,21 @@ Component-wise minimum and maximum of two vectors can be done using
@snippet MagnumMath.cpp matrix-vector-operations-minmax
The vectors can be also compared component-wise, the result is returned in
The vectors can be also compared component-wise, the result is returned in a
@ref Math::BoolVector class:
@snippet MagnumMath.cpp matrix-vector-operations-compare
There are also function for component-wise rounding, sign operations, square
root, various interpolation and (de)normalization functionality:
root and various interpolation and (de)normalization functionality:
@snippet MagnumMath.cpp matrix-vector-operations-functions
Component-wise functions are implemented only for vectors and not for matrices
to keep the math library a sane and maintainable size. Instead, you can
reinterpret the matrix as vector and do the operation on it (and vice versa):
to keep the math library in a sane and maintainable size. Instead, you can
reinterpret the matrix as a vector and do the operation on it (and vice versa)
--- because you get a reference that way, the operation will affect the
original data:
@snippet MagnumMath.cpp matrix-vector-operations-functions-componentwise
@ -250,11 +255,20 @@ For types with units the only exception are power functions such as
@ref Math::pow() or @ref Math::log() --- the resulting unit of such an
operation cannot be represented and thus will only work on unitless types.
@section matrix-vector-linear-algebra Linear algebra operations
Also available are common linear algebra operations --- the dot or cross
product, vector, reflection or angle calculation. These are mostly available
as free functions in the @ref Math namespace, with more advanced functionality
such as QR or SVD decomposition in @ref Math::Algorithms.
@snippet MagnumMath.cpp matrix-vector-linear-algebra
@section matrix-vector-column-major Matrices are column-major and vectors are columns
OpenGL matrices are column-major, thus in Magnum it is reasonable to use matrices
also as column-major (the vectors are the columns). This naturally has some
implications and it may differ from what is common in mathematics:
For consistency with GLSL, Magnum stores matrices as column-major (the vector s
are columns). This naturally has some implications and it may differ from what
you're used to from linear algebra or other graphics toolkit s:
<ul><li>
Order of template arguments in specification of @ref Math::RectangularMatrix
@ -268,8 +282,8 @@ implications and it may differ from what is common in mathematics:
@snippet MagnumMath.cpp matrix-vector-column-major-construct
</li><li>
Element access order is also column-major, thus the bracket operator
accesses columns. The returned vector also has its own bracket operator, which
then indexes rows.
accesses columns. The returned vector also has its own bracket operator,
which then indexes rows.
@snippet MagnumMath.cpp matrix-vector-column-major-access
</li><li>