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.

284 lines
12 KiB

/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
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 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 achieve greatest 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
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 identity
matrix.
@snippet MagnumMath.cpp matrix-vector-construct
Most common and most efficient way to create vector is to pass all values to
constructor, matrix is created by passing all column vectors to the
constructor. All constructors check number of passed arguments and the errors
are catched at compile time.
@snippet MagnumMath.cpp matrix-vector-construct-value
You can specify all components of vector or whole diagonal of square matrix
with single value or create diagonal matrix from 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, useful for transformations:
@snippet MagnumMath.cpp matrix-vector-construct-axis
It is also possible to create matrices and vectors 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:
@snippet MagnumMath.cpp matrix-vector-construct-from
12 years ago
@attention 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.
To make handling of 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 full value (thus @cpp 1.0f @ce for @ref Color4 and @cpp 255 @ce
for @ref Color4ub):
@snippet MagnumMath.cpp matrix-vector-construct-color
Similarly to axes in vectors, you can create single color shades too, or create
a RGB color from HSV representation:
@snippet MagnumMath.cpp matrix-vector-construct-color-hue
Lastly, 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 on it. 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
12 years ago
brackets:
@snippet MagnumMath.cpp matrix-vector-access
Row vectors can be accessed too, but only for reading, and the access is slower
12 years ago
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::swizzle()
function:
@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 are able to be
constructed from an instance with 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 *explicit*
constructor. That might sound inconvenient, but doing the conversion explicitly
avoids common issues like precision loss (or, on the other hand, doing
computations in unnecessarily high precision).
To further emphasise the intent of conversion (so it doesn't look like accident
or 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 there are @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
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 with integral result.
In Magnum, all multiplication/division operations involving integral vectors
will have integral 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
13 years ago
@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 in 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 @ref Math namespace work also for
scalars:
@snippet MagnumMath.cpp matrix-vector-operations-functions-scalar
@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:
<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 requirement that you have to pass directly column vectors:
@snippet MagnumMath.cpp matrix-vector-column-major-construct
</li><li>
Element accessing order is also column-major, thus the bracket operator is
accessing columns. Returned vector has also its own bracket operator, which
is then indexing 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 user decision
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.
*/
}