|
|
|
|
/*
|
|
|
|
|
This file is part of Magnum.
|
|
|
|
|
|
|
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016
|
|
|
|
|
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 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 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.
|
|
|
|
|
@code
|
|
|
|
|
Matrix2x3 a; // zero-filled
|
|
|
|
|
Vector3i b; // zero-filled
|
|
|
|
|
|
|
|
|
|
Matrix3 identity; // diagonal set to 1
|
|
|
|
|
Matrix3 zero(Matrix::Zero); // zero-filled
|
|
|
|
|
@endcode
|
|
|
|
|
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
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.
|
|
|
|
|
@code
|
|
|
|
|
Vector3i vec(0, 1, 2);
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
|
|
|
|
|
Matrix3 mat({0.0f, 1.9f, 2.2f},
|
|
|
|
|
{3.5f, 4.0f, 5.1f},
|
|
|
|
|
{6.0f, 7.3f, 8.0f});
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
You can specify all components of vector or whole diagonal of square matrix
|
|
|
|
|
with single value or 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
|
|
|
|
|
|
|
|
|
|
There are also shortcuts to create a vector with all but one component set to
|
|
|
|
|
zero or one, useful for transformations:
|
|
|
|
|
@code
|
|
|
|
|
auto x = Vector3::xAxis(); // {1.0f, 0.0f, 0.0f}
|
|
|
|
|
auto y = Vector2::yAxis(3.0f); // {0.0f, 3.0f}
|
|
|
|
|
auto z = Vector3::zScale(3.0f); // {1.0f, 1.0f, 3.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.
|
|
|
|
|
|
|
|
|
|
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 `1.0f` for @ref Color4 and `255` for
|
|
|
|
|
@ref Color4ub):
|
|
|
|
|
@code
|
|
|
|
|
Color4 a = Color3{0.2f, 0.7f, 0.5f}; // {0.2f, 0.7f, 0.5f, 1.0f}
|
|
|
|
|
Color4ub b = Color3ub{0x33, 0xb2, 0x7f}; // {0x33, 0xb2, 0x7f, 0xff}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Similarly to axes in vectors, you can create single color shades too, or create
|
|
|
|
|
a RGB color from HSV representation:
|
|
|
|
|
@code
|
|
|
|
|
auto green = Color3::green(); // {0.0f, 1.0f, 0.0f}
|
|
|
|
|
auto cyan = Color4::cyan(0.5f, 0.95f); // {0.5f, 1.0f, 1.0f, 0.95f}
|
|
|
|
|
auto fadedRed = Color3::fromHSV(219.0_degf, 0.50f, 0.57f)
|
|
|
|
|
@endcode
|
|
|
|
|
|
Math: sRGB support in Color classes.
At first I designed a hugely disrupting change that basically deprecated
everything related to 8-bit linear RGB colors, but then I took a step
back and reconsidered 8-bit linear RGB as a valid use case.
The documentation of Color classes, typedefs and literals was clarified
to mention that these classes should always represent linear RGB and
that 8-bit colors are commonly treated as *not* linear and one should be
aware of it.
There is now a new Color3::fromSrgb() and Color3::toSrgb() that converts
from sRGB representation to a linear RGB usable for calculations and
then back. For four-component colors, there is now
Color4::fromSrgbAlpha() and Color4::toSrgbAlpha(). Similarly to what
OpenGL sRGB behavior is regarding to alpha, the alpha channel is kept
linear, that's why I'm also calling it sRGB + alpha instead of sRGBA.
Besides that, there are four new literals _srgb, _srgba, _srgbf and
_srgbaf that have different semantics to support the sRGB workflow. The
8-bit versions are equivalent to _rgb and _rgba, though they don't
return Color3 but a non-color Vector3 to hint that the result is not a
linear RGB color. Main purpose of these is documentation. The float
versions apply an inverse sRGB curve to the input, returning a linear
RGB color.
10 years ago
|
|
|
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.
|
|
|
|
|
@code
|
Math: sRGB support in Color classes.
At first I designed a hugely disrupting change that basically deprecated
everything related to 8-bit linear RGB colors, but then I took a step
back and reconsidered 8-bit linear RGB as a valid use case.
The documentation of Color classes, typedefs and literals was clarified
to mention that these classes should always represent linear RGB and
that 8-bit colors are commonly treated as *not* linear and one should be
aware of it.
There is now a new Color3::fromSrgb() and Color3::toSrgb() that converts
from sRGB representation to a linear RGB usable for calculations and
then back. For four-component colors, there is now
Color4::fromSrgbAlpha() and Color4::toSrgbAlpha(). Similarly to what
OpenGL sRGB behavior is regarding to alpha, the alpha channel is kept
linear, that's why I'm also calling it sRGB + alpha instead of sRGBA.
Besides that, there are four new literals _srgb, _srgba, _srgbf and
_srgbaf that have different semantics to support the sRGB workflow. The
8-bit versions are equivalent to _rgb and _rgba, though they don't
return Color3 but a non-color Vector3 to hint that the result is not a
linear RGB color. Main purpose of these is documentation. The float
versions apply an inverse sRGB curve to the input, returning a linear
RGB color.
10 years ago
|
|
|
Color3ub a = 0x33b27f_rgb; // {0x33, 0xb2, 0x7f}
|
|
|
|
|
Color4 b = 0x33b27fcc_rgbaf; // {0.2f, 0.7f, 0.5f, 0.8f}
|
|
|
|
|
Color4 c = 0x33b27fcc_srgbaf; // {0.0331048f, 0.445201f, 0.212231f, 0.8f}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
@section matrix-vector-component-access Accessing matrix and vector components
|
|
|
|
|
|
|
|
|
|
Column vectors of matrices and vector components can be accessed using square
|
|
|
|
|
brackets:
|
|
|
|
|
@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 @ref matrix-vector-column-major "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-conversion Converting between different underlying types
|
|
|
|
|
|
|
|
|
|
All vector, matrix and other classes in @ref Math namespace and also
|
|
|
|
|
@ref Color3 and @ref Color4 classes are able to be constructed from type 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 `auto b = Type{a}` instead of `Type b{a}`.
|
|
|
|
|
@code
|
|
|
|
|
Vector3 a{2.2f, 0.25f, -5.1f};
|
|
|
|
|
//Vector3i b = a; // error, implicit conversion not allowed
|
|
|
|
|
auto c = Vector3i{a}; // {2, 0, -5}
|
|
|
|
|
auto d = Vector3d{a}; // {2.2, 0.25, -5.1}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
For packing and unpacking there are @ref Math::pack() and @ref Math::unpack()
|
|
|
|
|
functions:
|
|
|
|
|
@code
|
|
|
|
|
Color3 a{0.8f, 1.0f, 0.3f};
|
|
|
|
|
auto b = Math::unpack<Color3ub>(a); // {204, 255, 76}
|
|
|
|
|
|
|
|
|
|
Color3ub c{64, 127, 89};
|
|
|
|
|
auto d = Math::pack<Color3>(c); // {0.251, 0.498, 0.349}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
@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
|
|
|
|
|
Color3ub color(80, 116, 34);
|
|
|
|
|
Color3ub 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-componentwise Component-wise and inter-vector operations
|
|
|
|
|
|
|
|
|
|
As shown above, vectors can be added and multiplied component-wise using the
|
|
|
|
|
`+` or `*` operator. You can use @ref Math::Vector::sum() "sum()" and
|
|
|
|
|
@ref Math::Vector::product() "product()" for sum or product of components in
|
|
|
|
|
one vector:
|
|
|
|
|
@code
|
|
|
|
|
Float a = Vector3{1.5f, 0.3f, 8.0f}.sum(); // 8.8f
|
|
|
|
|
Int b = Vector3i{32, -5, 7}.product() // 1120
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
@code
|
|
|
|
|
Vector3i a{-5, 7, 24};
|
|
|
|
|
Vector3i b{8, -2, 12};
|
|
|
|
|
|
|
|
|
|
Vector3i min = Math::min(a, b); // {-5, -2, 12}
|
|
|
|
|
Int max = a.max(); // 24
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
The vectors can be also compared component-wise, the result is returned in
|
|
|
|
|
@ref Math::BoolVector class:
|
|
|
|
|
@code
|
|
|
|
|
BoolVector<3> largerOrEqual = a >= b; // {false, true, true}
|
|
|
|
|
bool anySmaller = (a < b).any(); // true
|
|
|
|
|
bool allLarger = (a > b).all(); // false
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
There are also function for component-wise rounding, sign operations, square
|
|
|
|
|
root, various interpolation and (de)normalization functionality:
|
|
|
|
|
@code
|
|
|
|
|
Vector3 a{5.5f, -0.3f, 75.0f};
|
|
|
|
|
Vector3 b = Math::round(a); // {5.0f, 0.0f, 75.0f}
|
|
|
|
|
Vector3 c = Math::abs(a); // {5.5f, -0.3f, 75.0f}
|
|
|
|
|
Vector3 d = Math::clamp(a, -0.2f, 55.0f); // {5.5f, -0.2f, 55.0f}
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
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):
|
|
|
|
|
@code
|
|
|
|
|
Matrix3x2 mat;
|
|
|
|
|
Math::Vector<6, Float> vec = mat.toVector();
|
|
|
|
|
// ...
|
|
|
|
|
mat = Matrix3x2::fromVector(vec);
|
|
|
|
|
@endcode
|
|
|
|
|
|
|
|
|
|
Note that all component-wise functions in Math namespace work also for scalars:
|
|
|
|
|
@code
|
|
|
|
|
std::pair<Int, Int> minmax = Math::minmax(24, -5); // -5, 24
|
|
|
|
|
Int a = Math::lerp(0, 360, 0.75f); // 270
|
|
|
|
|
auto b = Math::denormalize<UnsignedByte>(0.89f); // 226
|
|
|
|
|
@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
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
- 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
|
Math: matrix/vector rework, part 2: matrix as array of column vectors.
Overall architecture is simplififed with this change and also it's not
needed to use reinterpret_cast in matrix internals anymore, thus there
is no need for operator() and [][] works now always as expected without
any risk of GCC misoptimizations.
On the other side, constructing matrix from list of elements is not
possible anymore. You have to specify the elements as list of
column vectors, which might be less convenient to write, but it helps to
distinguish what is column and what is row:
Matrix<2, int> a(1, 2, // before
3, 4);
Matrix<2, int> a(Vector<2, int>(1, 2), // now
Vector<2, int>(3, 4));
For some matrix specializations (i.e. Matrix3 and Matrix4) it is
possible to use list-initialization instead of explicit type
specification:
Matrix<3, int>({1, 2, 3},
{4, 5, 6},
{7, 8, 9});
I didn't yet figure out how to properly implement the general
(constexpr) constructor to also take lists, so it's a bit ugly for now.
Matrix operations are now done column-wise, which should help with
future SIMD implementations, documentation is also updated accordingly.
I also removed forgotten remains of matrix/matrix operator*=(), which
can be confusing, as the multiplication is not commutative. Why it is
not present is explained in d9c900f076f2f87c7b7ba3f37a3179c0c0e4a02c.
13 years ago
|
|
|
- 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
|
|
|
|
|
*/
|
|
|
|
|
}
|