mirror of https://github.com/mosra/magnum.git
Browse Source
DDD - documentation driven development. Not all advertised features are available right now, but they will come.vectorfields
12 changed files with 211 additions and 13 deletions
@ -0,0 +1,181 @@
|
||||
namespace Magnum { namespace Math { |
||||
/** @page matrix-vector Operations with matrices and vectors |
||||
|
||||
@brief Introduction to essential classes of the graphics pipeline. |
||||
|
||||
@tableofcontents |
||||
|
||||
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. This |
||||
page will overview their usage and introduce some tricks to make your life |
||||
easier. |
||||
|
||||
@section matrix-vector-hierarchy Matrix and vector classes |
||||
|
||||
%Magnum has three main matrix and vector classes: RectangularMatrix, (square) |
||||
Matrix and Vector. To achieve greatest code reuse, %Matrix is internally |
||||
square %RectangularMatrix and %Vector is internally one-column |
||||
%RectangularMatrix. Both vectors and matrices can have arbitrary size (known |
||||
at compile time) and can store any meaningful type. |
||||
|
||||
Each subclass brings some specialization to its superclass and for most common |
||||
vector and matrix sizes there are specialized classes Matrix3 and Matrix4, |
||||
implementing various transformation in 2D and 3D, Vector2, Vector3 and 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 - Point2D, Point3D for |
||||
creating points with homogeneous coordinates and Color3, Color4 for color |
||||
handling and conversion. |
||||
|
||||
@section matrix-vector-construction Constructing matrices and vectors |
||||
|
||||
Default constructors of RectangularMatrix and Vector (and Vector2, Vector3, |
||||
Vector4, Color3) create zero-filled objects. Matrix (and Matrix3, Matrix4) is |
||||
by default constructed as identity matrix. Point2D and Point3D have |
||||
homogeneous component set to one, Color4 has alpha value set to opaque. |
||||
@code |
||||
RectangularMatrix<2, 3, int> a; // zero-filled |
||||
Vector<3, int> b; // zero-filled |
||||
|
||||
Matrix<3, int> identity; // diagonal set to 1 |
||||
Matrix<3, int> zero(Matrix<3, int>::Zero); // zero-filled |
||||
|
||||
Point2D<int> c; // {0, 0, 1} |
||||
Point3D<int> d; // {0, 0, 0, 1} |
||||
|
||||
Color4<float> black1; // {0.0f, 0.0f, 0.0f, 1.0f} |
||||
Color4<unsigned char> black2; // {0, 0, 0, 255} |
||||
@endcode |
||||
|
||||
Most common and most efficient way to create matrix or vector is to pass |
||||
values of all components to the constructor. |
||||
@code |
||||
Matrix3<int> mat(0, 1, 2, |
||||
3, 4, 5, |
||||
6, 7, 8); // column-major (see explanation why below) |
||||
|
||||
Vector3<int> vec(0, 1, 2); |
||||
@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: |
||||
@code |
||||
Matrix3<int> diag(Matrix3<int>::Identity, 2); // diagonal set to 2, zeros elsewhere |
||||
Vector3<int> fill(10); // {10, 10, 10} |
||||
@endcode |
||||
|
||||
Vectors are commonly used to specify various axes and scaling coefficients in |
||||
transformations, you can use convenience functions instead of typing out all |
||||
other elements: |
||||
@code |
||||
Matrix4::rotation(deg(5.0f), Vector3::xAxis()); // {1.0f, 0.0f, 0.0f} |
||||
Matrix3::translation(Vector2::yAxis(2.0f)); // {0.0f, 2.0f} |
||||
Matrix4::scaling(Vector3::zScale(-10.0f)); // {1.0f, 1.0f, -10.0f} |
||||
@endcode |
||||
|
||||
It is possible to create matrices from other matrices and vectors with the |
||||
same row count; vectors from vector and scalar: |
||||
@code |
||||
RectangularMatrix<2, 3, int> a; |
||||
Vector3<int> b, c; |
||||
Matrix3<int> mat = Matrix3<int>::from(b, a, c); |
||||
Vector<8, int> vec = Vector<8, int>::from(1, b, 2, c); |
||||
@endcode |
||||
|
||||
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 }; |
||||
RectangularMatrix<2, 3, 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 convert between data types: |
||||
@code |
||||
Vector4<float> floating(1.3f, 2.7f, -15.0f, 7.0f); |
||||
Vector4<int> integral(Vector4<int>::from(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 |
||||
RectangularMatrix<3, 2, int> a; |
||||
a[2] /= 2; // third column (column major indexing, see explanation below) |
||||
a[0][1] = 5; // first column, second element |
||||
a(0, 1) += 3; // first column, second element (preferred) |
||||
|
||||
Vector<3, int> b; |
||||
b[1] = 1; // second element |
||||
@endcode |
||||
For accessing matrix element prefer round bracket operator, as it is possibly |
||||
faster than the double square brackets (but never slower) and isn't prone to |
||||
compiler mis-optimizations. |
||||
|
||||
Fixed-size vector subclasses have functions for accessing named components |
||||
and subparts: |
||||
@code |
||||
Vector4<int> a; |
||||
int x = a.x(); |
||||
a.y() += 5; |
||||
|
||||
Vector3<int> xyz = a.xyz(); |
||||
xyz.xy() *= 5; |
||||
@endcode |
||||
Color3 and Color4 name their components `rgba` instead of `xyzw`. |
||||
|
||||
For more involved operations with components there are two swizzle() functions, |
||||
they have the same features, but one is guaranteed to do most of the work at |
||||
compile-time, while the second has more convenient syntax: |
||||
@code |
||||
Vector4<int> original(1, 2, 3, 4); |
||||
Vector4<int> bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, 1, 4 } |
||||
Vector<6, int> a10rgb = swizzle(original, "a10rgb"); // { 4, 1, 0, 1, 2, 3 } |
||||
@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 RectangularMatrix is also |
||||
column-major: |
||||
@code |
||||
RectangularMatrix<2, 3, int> mat; // two columns, three rows |
||||
@endcode |
||||
- Order of components in matrix constructors is also column-major, so the |
||||
elements passed in constructor doesn't need to be reordered internally |
||||
before putting them into data array: |
||||
@code |
||||
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. It costs virtually no time to |
||||
return reference to portion of data array as column vector, thus the bracket |
||||
operator is accessing columns. Returned vector has also its own bracket |
||||
operator, which is indexing rows. To avoid confusion, first parameter of |
||||
round bracket operator is thus also column index. |
||||
@code |
||||
mat[0] *= 2; // first column |
||||
mat[2][0] = 5; // first element of first column vector |
||||
mat(2, 0) += 3; // first element of first column |
||||
@endcode |
||||
- Various algorithms which commonly operate on matrix rows (such as |
||||
@ref Algorithms::GaussJordan "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. |
||||
*/ |
||||
}} |
||||
Loading…
Reference in new issue