mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
301 lines
13 KiB
301 lines
13 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020, 2021 Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
copy of this software and associated documentation files (the "Software"), |
|
to deal in the Software without restriction, including without limitation |
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
and/or sell copies of the Software, and to permit persons to whom the |
|
Software is furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included |
|
in all copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
namespace Magnum { |
|
/** @page matrix-vector Operations with matrices and vectors |
|
@brief Introduction to essential classes of the graphics pipeline. |
|
|
|
@m_keyword{Matrices and vectors,,} |
|
|
|
@tableofcontents |
|
@m_footernavigation |
|
|
|
Matrices and vectors are the most important part of graphics programming and |
|
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 --- 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 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, 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 *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 a vector or a matrix with a single value, or |
|
specify just values on the matrix diagonal: |
|
|
|
@snippet MagnumMath.cpp matrix-vector-construct-diagonal |
|
|
|
There are also shortcuts to create a vector with all but one component set to |
|
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: |
|
|
|
@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. |
|
|
|
To make handling colors easier, their behavior is a bit different with a |
|
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 and scales in vectors, you can create single color shades too: |
|
|
|
@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 / |
|
@link Literals::operator""_rgbf() operator""_rgbf() @endlink and |
|
@link Literals::operator""_rgba() operator""_rgba() @endlink / |
|
@link Literals::operator""_rgbaf() operator""_rgbaf() @endlink literals for |
|
entering colors in hex representation. These literals assume linear RGB input |
|
and don't do any gamma correction. For sRGB input, there is |
|
@link Literals::operator""_srgb() operator""_srgb() @endlink / |
|
@link Literals::operator""_srgba() operator""_srgba() @endlink and |
|
@link Literals::operator""_srgbf() operator""_srgbf() @endlink / |
|
@link Literals::operator""_srgbaf() operator""_srgbaf() @endlink, see their |
|
documentation for more information. |
|
|
|
@snippet MagnumMath.cpp matrix-vector-construct-color-literal |
|
|
|
@section matrix-vector-component-access Accessing matrix and vector components |
|
|
|
Column vectors of matrices and components of vectors 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 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 using either `xyzw` or `rgba`: |
|
|
|
@snippet MagnumMath.cpp matrix-vector-access-named |
|
|
|
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 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 precision |
|
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. |
|
|
|
@snippet MagnumMath.cpp matrix-vector-convert |
|
|
|
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 below for more information about other available |
|
@ref matrix-vector-componentwise "component-wise operations". |
|
|
|
@section matrix-vector-operations Operations with matrices and vectors |
|
|
|
Vectors can be added, subtracted, negated and multiplied or divided with |
|
scalars, as is common in mathematics. Magnum also adds the ability to divide |
|
a scalar with vector: |
|
|
|
@snippet MagnumMath.cpp matrix-vector-operations-vector |
|
|
|
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 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 |
|
|
|
You can also use all bitwise operations on integral vectors: |
|
|
|
@snippet MagnumMath.cpp matrix-vector-operations-bitwise |
|
|
|
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 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. 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 |
|
|
|
Component-wise minimum and maximum of two vectors can be done using |
|
@ref Math::min(), @ref Math::max() or @ref Math::minmax(), similarly with |
|
@ref Vector::min() "min()", @ref Vector::max() "max()" and |
|
@ref Vector2::minmax() "minmax()" for components in one vector. |
|
|
|
@snippet MagnumMath.cpp matrix-vector-operations-minmax |
|
|
|
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 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 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 |
|
|
|
Note that all component-wise functions in the @ref Math namespace also work for |
|
scalars --- and on the special @ref Deg / @ref Rad types too. |
|
|
|
@snippet MagnumMath.cpp matrix-vector-operations-functions-scalar |
|
|
|
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 |
|
|
|
For consistency with GLSL, Magnum stores matrices as column-major (the vectors |
|
are columns). This naturally has some implications and it may differ from what |
|
you're used to from linear algebra or other graphics toolkits: |
|
|
|
<ul><li> |
|
Order of template arguments in specification of @ref Math::RectangularMatrix |
|
is also column-major: |
|
|
|
@snippet MagnumMath.cpp matrix-vector-column-major-template |
|
</li><li> |
|
Order of components in matrix constructors is also column-major, further |
|
emphasized by the requirement that you must pass column vectors directly: |
|
|
|
@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. |
|
|
|
@snippet MagnumMath.cpp matrix-vector-column-major-access |
|
</li><li> |
|
Various algorithms which commonly operate on matrix rows (such as |
|
@ref Algorithms::gaussJordanInPlace() "Gauss-Jordan elimination") have |
|
faster alternatives which operate on columns. It's then up to the user |
|
to operate with transposed matrices or use the slower non-transposed |
|
alternative of the algorithm. |
|
</li></ul> |
|
|
|
Note that the @ref Corrade::Utility::Debug utility always prints the matrices |
|
in the expected layout --- rows are rows and columns are columns. You are |
|
encouraged to use it for data visualization purposes. |
|
*/ |
|
}
|
|
|