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.
 
 
 
 
 

260 lines
14 KiB

/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020, 2021 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 types Math type system
@brief Type aliases, naming and compatibility with OpenGL, Vulkan and GLSL types.
@tableofcontents
@m_footernavigation
@m_keyword{Type system,,}
Magnum defines a variety of scalar, vector and matrix types. Most of the
functionality is implemented using template classes in the @ref Math library,
with the most common variants brought as typedefs into the root @ref Magnum
namespace.
@section types-builtin Builtin types
Magnum provides its own typedefs for builtin integral and floating-point
arithmetic types to ensure portability, maintain consistency and reduce
confusion. E.g., the @ref Int typedef is guaranteed to *always* be 32-bit and
Magnum's own code and documentation prefers to use it over a wild mixture of
@ref std::int32_t, @cpp int @ce, @cpp GLint @ce or @cpp ALint @ce that all
refer to the same type.
| Magnum type | Size | Equivalent GLSL type |
| ------------------ | -------------- | ----------------------- |
| @ref UnsignedByte | 8bit unsigned | (*none*) |
| @ref Byte | 8bit signed | (*none*) |
| @ref UnsignedShort | 16bit unsigned | (*none*) |
| @ref Short | 16bit signed | (*none*) |
| @ref UnsignedInt | 32bit unsigned | @glsl uint @ce <b></b> |
| @ref Int | 32bit signed | @glsl int @ce <b></b> |
| @ref UnsignedLong | 64bit unsigned | (*none*) |
| @ref Long | 64bit signed | (*none*) |
| @ref Half | 16bit | (*none*) |
| @ref Float | 32bit | @glsl float @ce <b></b> |
| @ref Double | 64bit | @glsl double @ce <b></b> |
Types not meant to be used in arithmetic (such as @cpp bool @ce or
@cpp std::size_t @ce) or types which have no use in GPU computations (such as
@cpp long double @ce) have no typedefs.
Types from the above table are then used to define other types. All following
types are aliases of corresponding types in @ref Math namespace. No suffix
after type name means @ref Float underlying type, `h` means @ref Half, `d` is
@ref Double, `ub` @ref UnsignedByte, `b` @ref Byte, `us` @ref UnsignedShort,
`s` @ref Short, `ui` @ref UnsignedInt and `i` is @ref Int.
@section types-matrix Matrix/vector types
| Magnum vector type | Equivalent GLSL type |
| ---------------------------------------------- | ------------------------- |
| @ref BoolVector2, @ref BoolVector3, @ref BoolVector4 | @glsl bvec2 @ce, @glsl bvec3 @ce, @glsl bvec4 @ce |
| @ref Vector2, @ref Vector3, @ref Color3, @ref Vector4, @ref Color4 | @glsl vec2 @ce, @glsl vec3 @ce, @glsl vec4 @ce |
| @ref Vector2h, @ref Vector3h, @ref Color3h, @ref Vector4h, @ref Color4h | (*none*) |
| @ref Vector2d, @ref Vector3d, @ref Vector4d | @glsl dvec2 @ce, @glsl dvec3 @ce, @glsl dvec4 @ce |
| @ref Vector2ub, @ref Vector3ub, @ref Vector4ub, @ref Color3ub, @ref Color4ub | (*none*) |
| @ref Vector2b, @ref Vector3b, @ref Vector4b | (*none*) |
| @ref Vector2us, @ref Vector3us, @ref Vector4us, @ref Color3us, @ref Color4us | (*none*) |
| @ref Vector2s, @ref Vector3s, @ref Vector4s | (*none*) |
| @ref Vector2ui, @ref Vector3ui, @ref Vector4ui | @glsl uvec2 @ce, @glsl uvec3 @ce, @glsl uvec4 @ce |
| @ref Vector2i, @ref Vector3i, @ref Vector4i | @glsl ivec2 @ce, @glsl ivec3 @ce, @glsl ivec4 @ce |
| Magnum matrix type | Equivalent GLSL type |
| ---------------------------------------------------------------- | ------------------------------------- |
| @ref Matrix2x2 or @ref Matrix2x2d | @glsl mat2 @ce / @glsl mat2x2 @ce or @glsl dmat2 @ce / @glsl dmat2x2 @ce |
| @ref Matrix2x2h, @ref Matrix2x2b, @ref Matrix2x2s | (*none*) |
| @ref Matrix3 / @ref Matrix3x3 or @ref Matrix3d / @ref Matrix3x3d | @glsl mat3 @ce / @glsl mat3x3 @ce or @glsl dmat3 @ce / @glsl dmat3x3 @ce |
| @ref Matrix3x3h, @ref Matrix3x3b, @ref Matrix3x3s | (*none*) |
| @ref Matrix4 / @ref Matrix4x4 or @ref Matrix4d / @ref Matrix4x4d | @glsl mat4 @ce / @glsl mat4x4 @ce or @glsl dmat4 @ce / @glsl dmat4x4 @ce |
| @ref Matrix4x4h, @ref Matrix4x4b, @ref Matrix4x4s | (*none*) |
| @ref Matrix2x3 or @ref Matrix2x3d | @glsl mat2x3 @ce or @glsl dmat2x3 @ce |
| @ref Matrix2x3h, @ref Matrix2x3b, @ref Matrix2x3s | (*none*) |
| @ref Matrix3x2 or @ref Matrix3x2d | @glsl mat3x2 @ce or @glsl dmat3x2 @ce |
| @ref Matrix3x2h, @ref Matrix3x2b, @ref Matrix3x2s | (*none*) |
| @ref Matrix2x4 or @ref Matrix2x4d | @glsl mat2x4 @ce or @glsl dmat2x4 @ce |
| @ref Matrix2x4h, @ref Matrix2x4b, @ref Matrix2x4s | (*none*) |
| @ref Matrix4x2 or @ref Matrix4x2d | @glsl mat4x2 @ce or @glsl dmat4x2 @ce |
| @ref Matrix4x2h, @ref Matrix4x2b, @ref Matrix4x2s | (*none*) |
| @ref Matrix3x4 or @ref Matrix3x4d | @glsl mat3x4 @ce or @glsl dmat3x4 @ce |
| @ref Matrix3x4h, @ref Matrix3x4b, @ref Matrix3x4s | (*none*) |
| @ref Matrix4x3 or @ref Matrix4x3d | @glsl mat4x3 @ce or @glsl dmat4x3 @ce |
| @ref Matrix4x3h, @ref Matrix4x3b, @ref Matrix4x3s | (*none*) |
Any super- or sub-class of the same size and underlying type can be used
equivalently (e.g. @ref Math::Vector "Math::Vector<Float>" or @ref Color3
instead of @ref Vector3).
For easier entering of (s)RGB colors in hexadecimal format there are
@link Math::Literals::operator""_srgb() _srgb @endlink /
@link Math::Literals::operator""_srgbf() _srgbf @endlink,
@link Math::Literals::operator""_srgba() _srgba @endlink /
@link Math::Literals::operator""_srgbaf() _srgbaf @endlink,
@link Math::Literals::operator""_rgb() _rgb @endlink /
@link Math::Literals::operator""_rgbf() _rgbf @endlink and
@link Math::Literals::operator""_rgba() _rgba @endlink /
@link Math::Literals::operator""_rgbaf() _rgbaf @endlink literals in
@ref Math::Literals namespace. See their documentation for more information
about the differences.
@snippet MagnumMath.cpp types-literals-colors
@section types-binary Binary representation
Scalar types with a GLSL equivalent are guaranteed to have exactly the same
binary representation. Consequently, matrix and vector classes also have the
same binary representation as corresponding array of numeric values without any
additional data or padding (e.g. @cpp sizeof(Vector3i) == sizeof(Int[3]) @ce).
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 a
@ref Math::RectangularMatrix::data() "data()" function, which returns a pointer
to the internal data array.
@section types-half Half-precision arithmetic
The @ref Half type represents half-precision floating point values. The sole
purpose of the type is to make creation, conversion and visualization of
half-float values easier. By design it doesn't support any arithmetic
operations as not all CPU architecture have native support for half-floats and
thus the operations would be done faster in a regular single-precision
@ref Float. The class provides explicit constructors and conversion operators
from/to @ref Float and @ref UnsignedShort and you can also use the
@link Math::Literals::operator""_h() _h @endlink literal that is provided in
the @ref Math::Literals namespace:
@snippet MagnumMath.cpp types-literals-half
Half-precision vector and matrix types such as @ref Vector3h or @ref Matrix3x3h
work similarly --- you can construct them and convert them from/to other types,
but can't perform any arithmetic.
@section types-special Special types
Magnum has a special type for strongly-typed representation of angles, namely
the @ref Deg and @ref Rad classes (or @ref Degd / @ref Degh and @ref Radd /
@ref Radh with @ref Double / @ref Half as underlying type). Their purpose is to
avoid common degree-vs-radian bugs (i.e. entering a degree value where radians
should be and vice versa) and make the conversion between these two
representations easier. They are just a tiny @cpp constexpr @ce wrapper around
the native type and they support all meaningful numeric operations. The wrapper
API may have a slight overhead on debug builds, but the safety benefits
outweight that in most practical use cases.
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 @link Math::Literals::operator""_degf() _degf @endlink /
@link Math::Literals::operator""_deg() _deg @endlink and @link Math::Literals::operator""_radf() _radf @endlink
/ @link Math::Literals::operator""_rad() _rad @endlink literals that are
provided in the @ref Math::Literals namespace:
@snippet MagnumMath.cpp types-literals-angles
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:
@snippet MagnumMath.cpp types-literals-angle-conversion
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:
@snippet MagnumMath.cpp types-literals-usage
@section types-other Other types
Other types, which don't have their GLSL equivalent, are:
- @ref QuadraticBezier2D or @ref QuadraticBezier2Dd, @ref QuadraticBezier3D
or @ref QuadraticBezier3Dd
- @ref CubicBezier2D or @ref CubicBezier2Dd, @ref CubicBezier3D
or @ref CubicBezier3Dd
- @ref CubicHermite1D or @ref CubicHermite1Dd, @ref CubicHermite2D or
@ref CubicHermite2Dd, @ref CubicHermite3D or @ref CubicHermite3Dd
- @ref Complex or @ref Complexd, @ref DualComplex or @ref DualComplexd
- @ref Frustum or @ref Frustumd
- @ref Quaternion or @ref Quaterniond, @ref DualQuaternion or
@ref DualQuaterniond
- @ref CubicHermiteComplex or @ref CubicHermiteComplexd
- @ref CubicHermiteQuaternion or @ref CubicHermiteQuaterniond
- @ref Range1D / @ref Range2D / @ref Range3D, @ref Range1Di / @ref Range2Di /
@ref Range3Di or @ref Range1Dd / @ref Range2Dd / @ref Range3Dd
These types can be used in GLSL either by extracting values from their
underlying structure or converting them to types supported by GLSL (e.g.
quaternion to matrix).
For your convenience, there is also a structure with often used constants
--- @ref Constants, or @ref Constantsd for the double-precision variants.
@section types-initialization Initialization
Vectors, general matrices and range types are by default zero-initialized,
transformation types (square matrices, (dual) complex numbers and quaternions)
are set to identity transformation. It is possible to initialize the instances
differently using so-called *tags* or use the tag to make the choice appear
explicit:
- @ref Math::ZeroInit zero-initializes the contents (works for all types).
- @ref Math::IdentityInit initializes the contents to identity transformation
(works only for transformation types, where it is also the default).
- @ref NoInit leaves the contents uninitialized (useful if you will overwrite
the contents anyway, works for all types).
Example:
@snippet MagnumMath.cpp types-literals-init
@section types-thirdparty-integration Integration with types from 3rd party APIs
To simplify the workflow when interacting with 3rd party APIs, all Magnum math
types can be made explicitly convertible to and from types coming from external
libraries. Currently, various Magnum libraries provide these conversion, see
documentation of each `Integration.h` header for details:
- Math-related Vulkan structures --- @ref Magnum/Vk/Integration.h, part of
the @ref Vk library
- All Eigen types --- @ref Magnum/EigenIntegration/Integration.h and
@ref Magnum/EigenIntegration/GeometryIntegration.h, part of the
@ref EigenIntegration library
- All GLM types --- @ref Magnum/GlmIntegration/Integration.h,
@ref Magnum/GlmIntegration/GtcIntegration.h and
@ref Magnum/GlmIntegration/GtxIntegration.h, part of the
@ref GlmIntegration library
- Bullet Physics math types --- @ref Magnum/BulletIntegration/Integration.h,
part of the @ref BulletIntegration library
- Oculus VR SDK math types -- @ref Magnum/OvrIntegration/Integration.h, part
of the @ref OvrIntegration library
- Dear ImGui math types --- @ref Magnum/ImGuiIntegration/Integration.h, part
of the @ref ImGuiIntegration library
*/
}