Browse Source

doc: mention more features in math documentation.

Introduce angle classes, more thoroughly explain the type conversion and
do overview of component-wise functions.
pull/51/head
Vladimír Vondruš 12 years ago
parent
commit
35e49c47e2
  1. 104
      doc/matrix-vector.dox
  2. 60
      doc/types.dox

104
doc/matrix-vector.dox

@ -83,7 +83,8 @@ Color4ub black2; // {0, 0, 0, 255}
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.
constructor. All constructors check number of passed arguments and the errors
are catched at compile time.
@code
Vector3i vec(0, 1, 2);
@ -91,11 +92,9 @@ 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:
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}
@ -125,12 +124,6 @@ Math::Matrix2x3<Int>::from(mat) *= 2; // mat == { 4, 8, 12, 2, 6, 10 }
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
@ -170,6 +163,38 @@ 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 normalizing and denormalizing there are @ref Math::normalize() and
@ref Math::denormalize() functions:
@code
Color3 a{0.8f, 1.0f, 0.3f};
auto b = Math::denormalize<Color3ub>(a); // {204, 255, 76}
Color3ub c{64, 127, 89};
auto d = Math::normalize<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
@ -230,6 +255,63 @@ 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 Vector::sum() "sum()" and
@ref 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

60
doc/types.dox

@ -87,6 +87,66 @@ underlying type.
Any super- or sub-class of the same size and underlying type can be used
equivalently (e.g. @ref Math::Vector or @ref Color3 instead of @ref Vector3).
@section types-binary Binary representation
Scalar types with GLSL equivalent are verified to be exactly the same as
corresponding `GL*` types. Matrix and vector classes have the same binary
representation as corresponding array of numeric values without any additional
data or padding (e.g. `sizeof(Vector3i) == sizeof(Int[3])`), all matrices are
stored in column-major order.
This means that all scalar, matrix and vector types can be used directly for
filling GPU buffers and textures without any need for data extraction or
conversion. For convenience all vector and matrix classes provide
@ref Math::RectangularMatrix::data() "data()" function, which returns pointer
to the internal data array.
@section types-special Special types
%Magnum has special type for strongly-typed representation of angles, namely
the @ref Deg and @ref Rad classes (or @ref Degd and @ref Radd with @ref Double
as underlying type). Their only purpose is to avoid common degree-vs-radian
bugs (i.e. entering degree value where radians should be) and make the
conversion between these two representations easier. They are just a tiny
`inline` `constexpr` wrapper around the native type and they support all
meaningful numeric operations, so using them won't have any performance or
usability impact in practice.
These classes are *not* implicitly constructible or convertible from/to
@ref Float or @ref Double, you have to either construct/convert them explicitly
or use custom `_degf`/`_deg` and `_radf`/`_rad` literals:
@code
//Deg a = 60.0f // error, no implicit conversion from Float
Deg a = 60.0_degf; // okay
Float b = 3.2831853f;
auto tau = Rad{b} + 3.0_radf;
Radd pi = 3.141592653589793_rad;
//Double c = pi; // error, no implicit conversion to Double
auto c = Double{pi}; // okay
@endcode
They can be implicitly converted to each other, but conversion to different
underlying type is *explicit* to avoid precision loss (or, on the other hand,
unnecessarily high precision) during computations:
@code
Rad d = 60.0_degf; // 1.0471976f
auto e = Degd{pi}; // 180.0
//Rad f = pi; // error, no implicit conversion of underlying types
auto f = Rad{pi}; // 3.141592654f
@endcode
These classes are used exclusively in all functions taking and returning angles
-- trigonometry, angle computation, rotating transformation etc. Thanks to
implicit conversion you can seamlessly use either radians or degrees without
any need to care about what input the function expects:
@code
Float a = Math::sin(1.32457_radf);
Complex b = Complex::rotation(60.0_degf);
@endcode
@section types-other Other types
Other types, which don't have their GLSL equivalent, are:

Loading…
Cancel
Save