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.
269 lines
9.9 KiB
269 lines
9.9 KiB
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014 |
|
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. |
|
|
|
- Previous page: @ref types |
|
- Next page: @ref transformations |
|
|
|
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. |
|
|
|
@tableofcontents |
|
|
|
@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, %Matrix is internally square %RectangularMatrix and %RectangularMatrix |
|
is internally array of one or more %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 and for most common |
|
vector and matrix sizes there are specialized classes @ref Math::Matrix3 and |
|
@ref Math::Matrix4, implementing various transformations in 2D and 3D, |
|
@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 %RectangularMatrix are returned as %Vector, but when accessing |
|
columns of e.g. %Matrix3, they are returned as %Vector3. |
|
|
|
There are also even more specialized subclasses, e.g. @ref Color3 and |
|
@ref Color4 for color handling and conversion. |
|
|
|
Commonly used types have convenience aliases in @ref Magnum namespace, so you |
|
can write e.g. `%Vector3i` instead of `%Math::Vector3<Int>`. See @ref types and |
|
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 Color3) create |
|
zero-filled objects. @ref Math::Matrix (and @ref Math::Matrix3, @ref Math::Matrix4) |
|
is by default constructed as identity matrix. @ref Color4 has alpha value set |
|
to opaque. |
|
@code |
|
Matrix2x3 a; // zero-filled |
|
Vector3i b; // zero-filled |
|
|
|
Matrix3 identity; // diagonal set to 1 |
|
Matrix3 zero(Matrix::Zero); // zero-filled |
|
|
|
Color4 black1; // {0.0f, 0.0f, 0.0f, 1.0f} |
|
BasicColor4<UnsignedByte> black2; // {0, 0, 0, 255} |
|
@endcode |
|
|
|
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. |
|
@code |
|
Vector3i vec(0, 1, 2); |
|
|
|
Matrix3 mat({0.0f, 1.9f, 2.2f}, |
|
{3.5f, 4.0f, 5.1f}, |
|
{6.0f, 7.3f, 8.0f}); |
|
@endcode |
|
All constructors check number of passed arguments and the errors are catched |
|
at compile time. |
|
|
|
You can specify all components of vector or whole diagonal of square matrix at |
|
once or you can create diagonal matrix from vector: |
|
@code |
|
Matrix3 diag(Matrix3::Identity, 2.0f); // diagonal set to 2.0f, zeros elsewhere |
|
Vector3i fill(10); // {10, 10, 10} |
|
auto diag2 = Matrix3::fromDiagonal({3.0f, 2.0f, 1.0f}); |
|
@endcode |
|
|
|
It is possible to create matrices from other matrices and vectors with the same |
|
row count; vectors from vector and scalar: |
|
@code |
|
Math::Matrix2x3<Int> a; |
|
Math::Vector3<Int> b, c; |
|
Math::Matrix3<Int> mat(a, b); |
|
Math::Vector<8, Int> vec(1, b, 2, c); |
|
@endcode |
|
|
|
@todo Implement this ^ already. |
|
|
|
It is also possible to create them 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: |
|
@code |
|
Int[] mat = { 2, 4, 6, |
|
1, 3, 5 }; |
|
Math::Matrix2x3<Int>::from(mat) *= 2; // mat == { 4, 8, 12, 2, 6, 10 } |
|
@endcode |
|
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. |
|
|
|
You can also *explicitly* convert between data types: |
|
@code |
|
Vector4 floating(1.3f, 2.7f, -15.0f, 7.0f); |
|
auto integral = Vector4i(floating); // {1, 2, -15, 7} |
|
@endcode |
|
|
|
@section matrix-vector-component-access Accessing matrix and vector components |
|
|
|
Column vectors of matrices and vector components can be accessed using square |
|
brackets, there is also round bracket operator for accessing matrix components |
|
directly: |
|
@code |
|
Matrix3x2 a; |
|
a[2] /= 2.0f; // third column (column major indexing, see explanation below) |
|
a[0][1] = 5.3f; // first column, second element |
|
|
|
Vector3i b; |
|
b[1] = 1; // second element |
|
@endcode |
|
|
|
Row vectors can be accessed too, but only for reading, and the access is slower |
|
due to the way the matrix is stored (see explanation below): |
|
@code |
|
Vector2i c = a.row(2); // third row |
|
@endcode |
|
|
|
Fixed-size vector subclasses have functions for accessing named components |
|
and subparts: |
|
@code |
|
Vector4i a; |
|
Int x = a.x(); |
|
a.y() += 5; |
|
|
|
Vector3i xyz = a.xyz(); |
|
xyz.xy() *= 5; |
|
@endcode |
|
Color3 and Color4 name their components `rgba` instead of `xyzw`. |
|
|
|
For more involved operations with components there is the @ref swizzle() |
|
function: |
|
@code |
|
Vector4i original(-1, 2, 3, 4); |
|
Vector4i bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, -1, 4 } |
|
Math::Vector<6, Int> w10xyz = swizzle<'w', '1', '0', 'x', 'y', 'z'>(original); // { 4, 1, 0, -1, 2, 3 } |
|
@endcode |
|
|
|
@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: |
|
@code |
|
Vector3 a(1.0f, 2.0f, 3.0f); |
|
Vector3 b = a*5.0f - Vector3(3.0f, -0.5f, -7.5f); // b == {5.0f, 9.5f, 7.5f} |
|
Vector3 c = 1.0f/a; // c == {1.0f, 0.5f, 0.333f} |
|
@endcode |
|
|
|
As in GLSL, vectors can be also multiplied or divided component-wise: |
|
@code |
|
Vector3 a(1.0f, 2.0f, 3.0f); |
|
Vector3 b = a*Vector3(-0.5f, 2.0f, -7.0f); // b == {-0.5f, 4.0f, -21.0f} |
|
@endcode |
|
|
|
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 mulitplication/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. |
|
@code |
|
BasicColor3<UnsignedByte> color(80, 116, 34); |
|
BasicColor3<UnsignedByte> lighter = color*1.5f; // lighter = {120, 174, 51} |
|
|
|
Vector3i a(4, 18, -90); |
|
Vector3 multiplier(2.2f, 0.25f, 0.1f); |
|
Vector3i b = a*multiplier; // b == {8, 4, -9} |
|
Vector3 c = Vector3(a)*multiplier; // c == {8.0f, 4.5f, -9.0f} |
|
@endcode |
|
|
|
You can use also all bitwise operations on integral vectors: |
|
@code |
|
Vector2i size(256, 256); |
|
Vector2i mipLevel3Size = size >> 3; // == {32, 32} |
|
@endcode |
|
|
|
Matrices can be added, subtracted and multiplied with matrix multiplication. |
|
@code |
|
Matrix3x2 a; |
|
Matrix3x2 b; |
|
Matrix3x2 c = a + (-b); |
|
|
|
Matrix2x3 d; |
|
Matrix2x2 e = d*b; |
|
Matrix3x3 f = b*d; |
|
@endcode |
|
|
|
You can also multiply (properly sized) vectors with matrices. These operations |
|
are just convenience shortcuts for multiplying with single-column matrices: |
|
@code |
|
Matrix3x4 a; |
|
Vector3 b; |
|
Vector4 c = a*b; |
|
|
|
Math::RectangularMatrix<4, 1, Float> d; |
|
Matrix4x3 e = b*d; |
|
@endcode |
|
|
|
@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: |
|
|
|
- Order of template arguments in specification of @ref Math::RectangularMatrix |
|
is also column-major: |
|
@code |
|
Math::RectangularMatrix<2, 5, Int> mat; // two columns, five rows |
|
@endcode |
|
- Order of components in matrix constructors is also column-major, further |
|
emphasized by requirement that you have to pass directly column vectors: |
|
@code |
|
Math::Matrix3<Int> mat({0, 1, 2}, |
|
{3, 4, 5}, |
|
{6, 7, 8}); // first column is {0, 1, 2} |
|
@endcode |
|
- 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. |
|
@code |
|
mat[0] *= 2; // first column |
|
mat[2][0] = 5; // first element of third column |
|
@endcode |
|
- 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. |
|
|
|
|
|
|
|
- Previous page: @ref types |
|
- Next page: @ref transformations |
|
*/ |
|
}
|
|
|