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.
287 lines
12 KiB
287 lines
12 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020 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 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. |
|
|
|
@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 |
|
@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. |
|
|
|
@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. |
|
|
|
@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. |
|
|
|
@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: |
|
|
|
@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 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): |
|
|
|
@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: |
|
|
|
@snippet MagnumMath.cpp matrix-vector-construct-color-hue |
|
|
|
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 vector components 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"): |
|
|
|
@snippet MagnumMath.cpp matrix-vector-access-row |
|
|
|
Fixed-size vector subclasses have functions for accessing named components |
|
and subparts: |
|
|
|
@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() |
|
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 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 and unpacking 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. |
|
|
|
@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 integers within the result, you need to convert both arguments to the same |
|
floating-point type to have 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 just convenience shortcuts for 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: |
|
|
|
@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 |
|
@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: |
|
|
|
@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): |
|
|
|
@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-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: |
|
|
|
<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. |
|
*/ |
|
}
|
|
|