/* This file is part of Magnum. Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025 Vladimír Vondruš 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". 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 Math.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 Math.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 Math.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 Math.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 Math.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 Math.cpp matrix-vector-construct-color Similar to axes and scales in vectors, you can create single color shades too: @snippet Math.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 Math.cpp matrix-vector-construct-color-colorspace Finally, the namespace @ref Math::Literals provides convenient @link Math::Literals::ColorLiterals::operator""_rgb() operator""_rgb() @endlink / @link Math::Literals::ColorLiterals::operator""_rgbf() operator""_rgbf() @endlink and @link Math::Literals::ColorLiterals::operator""_rgba() operator""_rgba() @endlink / @link Math::Literals::ColorLiterals::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 Math::Literals::ColorLiterals::operator""_srgb() operator""_srgb() @endlink / @link Math::Literals::ColorLiterals::operator""_srgba() operator""_srgba() @endlink and @link Math::Literals::ColorLiterals::operator""_srgbf() operator""_srgbf() @endlink / @link Math::Literals::ColorLiterals::operator""_srgbaf() operator""_srgbaf() @endlink, see their documentation for more information. @snippet Math.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 Math.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 Math.cpp matrix-vector-access-row Fixed-size vector subclasses have functions for accessing named components and subparts using either `xyzw` or `rgba`: @snippet Math.cpp matrix-vector-access-named For more involved operations with components there are the @ref Math::gather() and @ref Math::scatter() functions: @snippet Math.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 Math.cpp matrix-vector-convert For packing floats into integers and unpacking them back use the @ref Math::pack() and @ref Math::unpack() functions: @snippet Math.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 Math.cpp matrix-vector-operations-vector As in GLSL, vectors can be also multiplied or divided component-wise: @snippet Math.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 Math.cpp matrix-vector-operations-integer You can also use all bitwise operations on integral vectors: @snippet Math.cpp matrix-vector-operations-bitwise Matrices can be added, subtracted and multiplied with matrix multiplication. @snippet Math.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 Math.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 Math.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 Math::Vector::min() "min()", @ref Math::Vector::max() "max()" and @ref Vector2::minmax() "minmax()" for components in one vector. @snippet Math.cpp matrix-vector-operations-minmax The vectors can be also compared component-wise, the result is returned in a @ref Math::BitVector class: @snippet Math.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 Math.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 Math.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 Math.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 Math.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: 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. */ }