diff --git a/Doxyfile b/Doxyfile
index 9bb7567bd..18a8b85e8 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -203,7 +203,7 @@ ALIASES = \
"debugoperator{1}=@relates \1\n@brief Debug output operator @xrefitem debugoperators \"Debug output operator\" \"Debug output operators for custom types\" Allows printing \1 with Corrade::Utility::Debug and friends." \
"configurationvalueref{1}=@see @ref configurationvalues \"Corrade::Utility::ConfigurationValue<\1>\"" \
"configurationvalue{1}=@brief %Configuration value parser and writer @xrefitem configurationvalues \"Configuration value parser and writer\" \"Configuration value parsers and writers for custom types\" Allows parsing and writing \1 from and to Corrade::Utility::Configuration." \
- "collisionoperator{2}=@relates \1\n@brief Collision of %\1 and %\2\n@see \2::operator%(const \1&) const" \
+ "collisionoccurenceoperator{2}=@relates \1\n@brief %Collision occurence of %\1 and %\2\n@see \2::operator%(const \1&) const" \
"todoc=@xrefitem todoc \"Documentation todo\" \"Documentation-related todo list\"" \
"fn_gl{1}=gl\1()" \
"fn_gl_extension{3}=gl\1\2()" \
diff --git a/README.md b/README.md
index 530a996e4..18fc6b706 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
Magnum is 2D/3D graphics engine written in C++11 and modern OpenGL. Its goal is
to simplify low-level graphics development and interaction with OpenGL using
-recent C++11 features and abstract away platform-specific issues.
+recent C++11 features and to abstract away platform-specific issues.
DESIGN GOALS
============
diff --git a/doc/best-practices.dox b/doc/best-practices.dox
index 2cddea322..1d64c1929 100644
--- a/doc/best-practices.dox
+++ b/doc/best-practices.dox
@@ -33,6 +33,10 @@ Here is collection of carefully selected links to official guidelines and
other articles with valuable information to help developers create better
applications. Feel free to add one, if it contains new unique information.
+@section best-practices-general General best practices
+
+- [Writing Portable OpenGL ES 2.0](https://www.khronos.org/assets/uploads/developers/library/2011-siggraph-mobile/Writing-Portable-OpenGL-ES-2.0_Aug-11.pdf)
+
@section best-practices-platform Platform-specific
Some platforms need special care, see their respective sections for more
diff --git a/doc/coding-style.dox b/doc/coding-style.dox
index 8c686005d..d520b14cf 100644
--- a/doc/coding-style.dox
+++ b/doc/coding-style.dox
@@ -102,10 +102,10 @@ Additionally to @c \@todoc, @c \@debugoperator @c \@configurationvalue and
@subsubsection documentation-commands-collisionoperator Shape collision operators
-Out-of-class operators for collision in Shapes namespace should be marked with
-@c \@collisionoperator, e.g.:
+Out-of-class operators for collision occurence in Shapes namespace should be
+marked with @c \@collisionoccurenceoperator, e.g.:
@code
-// @collisionoperator{Point,Sphere}
+// @collisionoccurenceoperator{Point,Sphere}
inline bool operator%(const Point& a, const Sphere& b) { return b % a; }
@endcode
They will appear as related functions within documentation of class for which
diff --git a/doc/compilation-speedup.dox b/doc/compilation-speedup.dox
index efdd3db0a..1e87b8532 100644
--- a/doc/compilation-speedup.dox
+++ b/doc/compilation-speedup.dox
@@ -33,31 +33,31 @@ directives in both headers and source files. %Magnum is strictly applying this
policy in all header files, so all types which are not directly used in the
header have only forward declarations.
-For example, when including Magnum.h, you get shortcut typedefs for
+For example, when including @ref Magnum.h, you get shortcut typedefs for
floating-point vectors and matrices like @ref Vector3 and @ref Matrix4, but to
actually use any of them, you have to include the respective header, e.g.
-Math/Vector3.h.
+@ref Math/Vector3.h.
You are encouraged to use forward declarations also in your code. However, for
some types it can be too cumbersome -- e.g. too many template parameters,
typedefs etc. In this case a header with forward declarations is usually
available, each namespace has its own:
- - Math/Math.h
- - Magnum.h
- - DebugTools/DebugTools.h
- - SceneGraph/SceneGraph.h
- - Shaders/Shaders.h
- - Shapes/Shapes.h
- - Text/Text.h
- - Trade/Trade.h
+ - @ref Math/Math.h
+ - @ref Magnum.h
+ - @ref DebugTools/DebugTools.h
+ - @ref SceneGraph/SceneGraph.h
+ - @ref Shaders/Shaders.h
+ - @ref Shapes/Shapes.h
+ - @ref Text/Text.h
+ - @ref Trade/Trade.h
@section compilation-speedup-templates Templates
Many things in %Magnum are templated to allow handling of various types and
-sizes of data, for example whole Scene graph can operate either with @ref Float
-or @ref Double data type. However, having templated classes and function usually
-means that the compiler compiles the whole templated code again in each
+sizes of data, for example whole scene graph can operate either with @ref Float
+or @ref Double data type. However, having templated classes and function
+usually means that the compiler compiles the whole templated code again in each
compilation unit (i.e. source file). In linking stage of the application or
library the duplicates are just thrown out, which is a waste of compilation
time. A few techniques are employed in %Magnum to avoid this.
@@ -67,48 +67,51 @@ time. A few techniques are employed in %Magnum to avoid this.
When templated code is too large, it is not stored in header file, but in
so-called *template implementation file*. Generally, all header files in
%Magnum have `*.h` extension and all source files have `*.cpp` extension.
-Template implementation files have `*.hpp` extension (hinting that they are
-something between `*.h` and `*.cpp` files).
+Template implementation files have `*.hpp` extension, hinting that they are
+something between `*.h` and `*.cpp` files.
Template implementation file can be included along the header itself and it
will just work, but it will negatively affect compilation time. If you are
using one template specialization in many places, the compiler performs
-compilation of the same template specialization many times. Template
-implementation files give you the ability to explicitly instantiate the
-template only once in some dedicated source file. Then you can include just
+compilation of the same template specialization many times, as said above.
+Template implementation files give you the ability to explicitly instantiate
+the template only once in some dedicated source file. Then you can include just
the header everywhere else and leave the rest on the linker.
-Templated classes which have implementation files state in their documentation
-all common specializations that are already compiled in the libraries. So,
-unless the templated class is too generic or you need something special, you
-don't have to mess with template implementation files at all. See
-SceneGraph::Object or SceneGraph::AbstractCamera for an example.
-
-Sometimes you however need to use your own specialization and that's why
-template implementation files are included in the library. For example we want
-to use @ref SceneGraph::Object "Object" from SceneGraph with
-@ref SceneGraph::MatrixTransformation3D "MatrixTransformation3D" with
-@ref Double as underlying type, because our scene will span the whole universe.
-We include the implementation file in dedicated source file and explicitly
-instantiate the template:
+Templated classes having code in template implementation files state in their
+documentation all common specializations that are already compiled in the
+libraries. So, unless the templated class is too generic or you need something
+special, you don't have to mess with template implementation files at all. See
+@ref SceneGraph::Object or @ref SceneGraph::AbstractCamera for an example.
+
+Sometimes, however, you need to use your own specialization and that's why
+template implementation files are installed along with the library. For example
+we want to use @ref SceneGraph::Object "Object" from @ref SceneGraph with
+@ref SceneGraph::BasicMatrixTransformation3D "BasicMatrixTransformation3D" with
+@ref Double instead of @ref Float as underlying type, because our scene will
+span the whole universe. We include the implementation file in dedicated source
+file and explicitly instantiate the template:
@code
// Object.cpp
#include "SceneGraph/Object.hpp"
+#include "SceneGraph/MatrixTransformation3D.h"
-using namespace Magnum::SceneGraph;
+using namespace Magnum;
-template class Object>;
+template class SceneGraph::Object>;
@endcode
+
All other files using the same object specialization now need to include only
-SceneGraph/Object.h header. Thus the Object specialization will be compiled
-only once in our `Object.cpp` file, saving precious compilation time.
+@ref SceneGraph/Object.h header. Thus the @ref SceneGraph::Object "Object"
+specialization will be compiled only once in our `Object.cpp` file, saving
+precious compilation time.
@subsection compilation-speedup-extern-templates Extern templates
-Keyword `extern template` is new thing in C++11, attempting to solve
-compilation time problems. However, when used on whole classes, on some
-compilers it causes conflicting symbol errors, so in %Magnum its used only for
-specific functions.
+Keyword `extern template` is a new thing in C++11, attempting to solve
+compilation time problems related to templated code. However, on some compilers
+it causes conflicting symbol errors when used on whole classes, thus in %Magnum
+it's used only for specific functions.
This is completely transparent to end user, so no special care is needed.
Extern template is used for example for @ref debugoperators "debug operators"
diff --git a/doc/mainpage.dox b/doc/mainpage.dox
index fe47ce03c..d24de7caf 100644
--- a/doc/mainpage.dox
+++ b/doc/mainpage.dox
@@ -27,7 +27,7 @@ namespace Magnum {
%Magnum is 2D/3D graphics engine written in C++11 and modern OpenGL. Its goal
is to simplify low-level graphics development and interaction with OpenGL using
-recent C++11 features and abstract away platform-specific issues.
+recent C++11 features and to abstract away platform-specific issues.
@section mainpage-design-goals Design goals
diff --git a/doc/matrix-vector.dox b/doc/matrix-vector.dox
index 82ab2d98b..c5703196a 100644
--- a/doc/matrix-vector.dox
+++ b/doc/matrix-vector.dox
@@ -22,7 +22,7 @@
DEALINGS IN THE SOFTWARE.
*/
-namespace Magnum { namespace Math {
+namespace Magnum {
/** @page matrix-vector Operations with matrices and vectors
@brief Introduction to essential classes of the graphics pipeline.
@@ -36,68 +36,79 @@ 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 %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.
+%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 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.
+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. Color3 and Color4 for
-color handling and conversion.
+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`. See @ref types and
+namespace documentation for more information.
@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. Color4 has alpha value set to opaque.
+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
-RectangularMatrix<2, 3, Int> a; // zero-filled
-Vector<3, Int> b; // zero-filled
+Matrix2x3 a; // zero-filled
+Vector3i b; // zero-filled
-Matrix<3, Int> identity; // diagonal set to 1
-Matrix<3, Int> zero(Matrix<3, Int>::Zero); // zero-filled
+Matrix3 identity; // diagonal set to 1
+Matrix3 zero(Matrix::Zero); // zero-filled
-Color4 black1; // {0.0f, 0.0f, 0.0f, 1.0f}
-Color4 black2; // {0, 0, 0, 255}
+Color4 black1; // {0.0f, 0.0f, 0.0f, 1.0f}
+BasicColor4 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
-Vector3 vec(0, 1, 2);
+Vector3i vec(0, 1, 2);
-Matrix3 mat({0, 1, 2},
- {3, 4, 5},
- {6, 7, 8});
+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:
+once or you can create diagonal matrix from vector:
@code
-Matrix3 diag(Matrix3::Identity, 2); // diagonal set to 2, zeros elsewhere
-Vector3 fill(10); // {10, 10, 10}
+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:
+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 b, c;
-Matrix3 mat(a, b);
-Vector<8, Int> vec(1, b, 2, c);
+Math::RectangularMatrix<2, 3, Int> a;
+Math::Vector<3, Int> b, c;
+Math::Matrix3 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:
@@ -111,8 +122,8 @@ 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);
-Vector4 integral(floating); // {1, 2, -15, 7}
+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
@@ -121,37 +132,98 @@ 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
+Matrix3x2 a;
+a[2] /= 2.0f; // third column (column major indexing, see explanation below)
+a[0][1] = 5.3f; // first column, second element
-Vector<3, Int> b;
+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
-Vector<2, Int> c = a.row(2); // third row
+Vector2i c = a.row(2); // third row
@endcode
Fixed-size vector subclasses have functions for accessing named components
and subparts:
@code
-Vector4 a;
+Vector4i a;
Int x = a.x();
a.y() += 5;
-Vector3 xyz = a.xyz();
+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 swizzle() function:
+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
-Vector<4, Int> original(-1, 2, 3, 4);
-Vector<4, Int> bgra = swizzle<'b', 'g', 'r', 'a'>(original); // { 3, 2, -1, 4 }
-Vector<6, Int> w10xyz = swizzle<'w', '1', '0', 'x', 'y', 'z'>(original); // { 4, 1, 0, -1, 2, 3 }
+BasicColor3 color(80, 116, 34);
+BasicColor3 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
@@ -163,21 +235,21 @@ 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
+Math::RectangularMatrix<2, 3, Int> mat; // two columns, three 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
-Matrix3 mat({0, 1, 2},
- {3, 4, 5},
- {6, 7, 8}); // first column is {0, 1, 2}
+Math::Matrix3 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 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
diff --git a/doc/portability.dox b/doc/portability.dox
index 9c5031a6f..b8dc2971c 100644
--- a/doc/portability.dox
+++ b/doc/portability.dox
@@ -46,7 +46,7 @@ If you include Magnum.h, you get these predefined macros:
Example usage:
@code
#ifndef MAGNUM_TARGET_GLES
-Mesh::setPolygonMode(Mesh::PolygonMode::Lines);
+Renderer::setPolygonMode(Renderer::PolygonMode::Lines);
// draw mesh as wireframe...
#else
// use different mesh, as polygon mode is not supported in OpenGL ES...
@@ -54,7 +54,7 @@ Mesh::setPolygonMode(Mesh::PolygonMode::Lines);
@endcode
Each feature is marked accordingly if it is not available in some targets. See
-also @ref requires-gl and @ref requires-gles30.
+also @ref requires-gl, @ref requires-gles20 and @ref requires-gles30.
@section portability-compiler Compiler-specific code
@@ -62,38 +62,39 @@ also @ref requires-gl and @ref requires-gles30.
possible. Many features from C++11 are used to simplify things and make them
faster and more secure, but on the other hand it requires fairly recent
compiler with good enough support of the new standard. Currently %Magnum is
-written with GCC 4.7 and Clang 3.1 in mind, but support for some other
-compilers is also available and handled by Corrade library. See Corrade.h for
-more information.
+written with GCC 4.8 and Clang 3.1 in mind, but support for some other
+compilers is also available and handled by Corrade library. See @ref Corrade.h
+for more information.
Each feature is marked accordingly if it is not available on some compilers,
see @ref SceneGraph::DrawableGroup3D for an example. It is up to you (or your
-platform) which compiler your code will support, code written for GCC 4.7 will
-work also on Magnum compiled with support for older compilers.
+platform) which compiler your code will support, code written for e.g. GCC 4.6
+will work also on Magnum compiled with support for newer compilers, although
+newer compilers may catch errors that weren't spotted by earlier versions.
@section portability-extensions Extension-aware code
Some functionality is depending on support of particular extension and thus
-the decision cannot be made at compile time. Header Extensions.h contains list
-of extensions, which you can pass to Context::isExtensionSupported() and
-decide based on that:
+the decision cannot be made at compile time. Header @ref Extensions.h contains
+list of extensions, which you can pass to @ref Context::isExtensionSupported()
+and decide based on that:
@code
if(Context::instance()->isExtensionSupported()) {
// draw mesh with wireframe on top in one pass using geometry shader...
} else {
// draw underlying mesh...
- Mesh::setPolygonMode(Mesh::PolygonMode::Lines);
+ Renderer::setPolygonMode(Renderer::PolygonMode::Lines);
// draw mesh as wirefreame in second pass...
}
@endcode
-You can also decide on particular OpenGL version using Context::isVersionSupported(),
+You can also decide on particular OpenGL version using @ref Context::isVersionSupported(),
but remember that some features from that version might be available even if
the drivers don't expose that version.
On the other hand, if you don't want to write fallback code for unsupported
-extensions, you can use macros MAGNUM_ASSERT_EXTENSION_SUPPORTED() or
-MAGNUM_ASSERT_VERSION_SUPPORTED() to add mandatory requirement of given
+extensions, you can use macros @ref MAGNUM_ASSERT_EXTENSION_SUPPORTED() or
+@ref MAGNUM_ASSERT_VERSION_SUPPORTED() to add mandatory requirement of given
extension or version:
@code
MAGNUM_ASSERT_EXTENSION_SUPPORTED(GL::ARB::geometry_shader4);
@@ -103,7 +104,7 @@ MAGNUM_ASSERT_EXTENSION_SUPPORTED(GL::ARB::geometry_shader4);
Each class, function or enum value is marked accordingly if it needs specific
extension or specific OpenGL version. Various classes in %Magnum are taking
advantage of some extensions and enable faster code paths if given extension is
-available, but also have proper fallback when it's not, for example
+available, but also have proper fallback when it's not, see for example
@ref AbstractShaderProgram-performance-optimization "AbstractShaderProgram",
@ref AbstractTexture-performance-optimization "AbstractTexture" or
@ref Mesh-performance-optimization "Mesh". See also @ref required-extensions.
@@ -117,8 +118,8 @@ texture uniform locations, required precision qualifiers in OpenGL ES etc.
Shader class allows you to explicitly specify shader version and based on that
you can decide on the syntax in your shader code. You can also use
-Context::supportedVersion() to conveniently select highest supported version
-from a list:
+@ref Context::supportedVersion() to conveniently select highest supported
+version from a list:
@code
// MyShader.vert
#if __VERSION__ < 130
@@ -141,22 +142,22 @@ Version version = Context::instance()->supportedVersion({Version::GL430, Version
attachShader(Shader::fromFile(version, "MyShader.vert"));
@endcode
-All shaders in Shaders namespace support desktop OpenGL starting from version
-2.1 and also OpenGL ES 2.0 and 3.0. Feel free to look into their sources to
-see how portability is handled there.
+All shaders in @ref Shaders namespace support desktop OpenGL starting from
+version 2.1 and also OpenGL ES 2.0 and 3.0. Feel free to look into their
+sources to see how portability is handled there.
@section portability-applications Platform-specific application support
Your application might run on Windows box, on some embedded Linux or even in
browser - each platform has different requirements how to create entry point
to the application, how to handle input events, how to create window and
-OpenGL context etc. Namespace Platform contains base classes for applications
+OpenGL context etc. Namespace @ref Platform contains application base classes
which are abstracting out most of it for your convenience.
All the classes support limited form of static polymorphism, which means you
-can switch to another base class and probably don't need to change any other
-code. It has its limitations, though - some toolkits don't support all keys,
-mouse movement events etc.
+can just switch to another base class and in many cases you won't need to
+change any other code. It has its limitations, though - some toolkits don't
+support all keys, mouse movement events etc.
In most cases the entry point is classic `main()` function, but some platforms
(e.g. Native Client) have different requirements. To make things easier, entry
@@ -174,8 +175,8 @@ variables.
Example application, which targets both embedded Linux (using plain X and EGL)
and desktop (using SDL2 toolkit). Thanks to static polymorphism most of the
-functions will work on both without changes, the main difference will be in
-particular *Event class implementations:
+functions will work on both without changes, the main difference might (or
+might not, depending what you use) be in particular event handlers:
@code
#ifndef MAGNUM_TARGET_GLES
#include
diff --git a/src/AbstractResourceLoader.h b/src/AbstractResourceLoader.h
index 6100eddc9..892f13de3 100644
--- a/src/AbstractResourceLoader.h
+++ b/src/AbstractResourceLoader.h
@@ -162,7 +162,7 @@ template class AbstractResourceLoader {
/** @overload */
template void set(ResourceKey key, U&& data, ResourceDataState state, ResourcePolicy policy) {
- set(key, new typename std::remove_cv::type>::type(std::forward(data)), state, policy);
+ set(key, new typename std::decay::type(std::forward(data)), state, policy);
}
/**
@@ -177,7 +177,7 @@ template class AbstractResourceLoader {
/** @overload */
template void set(ResourceKey key, U&& data) {
- set(key, new typename std::remove_cv::type>::type(std::forward(data)));
+ set(key, new typename std::decay::type(std::forward(data)));
}
/**
diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp
index b175094d2..cb9c2a948 100644
--- a/src/AbstractTexture.cpp
+++ b/src/AbstractTexture.cpp
@@ -684,10 +684,8 @@ void AbstractTexture::storageImplementationFallback(const GLenum target, const G
const ImageFormat format = imageFormatForInternalFormat(internalFormat);
const ImageType type = imageTypeForInternalFormat(internalFormat);
- auto levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
- (this->*image1DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr);
- levelSize = Math::max(Math::Vector<1, GLsizei>(1), levelSize/2);
+ (this->*image1DImplementation)(target, level, internalFormat, Math::max(Math::Vector<1, GLsizei>(1), size >> level), format, type, nullptr);
}
}
@@ -721,15 +719,12 @@ void AbstractTexture::storageImplementationFallback(const GLenum target, const G
if(target == GL_TEXTURE_2D)
#endif
{
- Vector2i levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
- (this->*image2DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr);
- levelSize = Math::max(Vector2i(1), levelSize/2);
+ (this->*image2DImplementation)(target, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr);
}
/* Cube map additionally needs to specify all faces */
} else if(target == GL_TEXTURE_CUBE_MAP) {
- Vector2i levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
const std::initializer_list faces = {
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
@@ -740,17 +735,14 @@ void AbstractTexture::storageImplementationFallback(const GLenum target, const G
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
};
for(auto it = faces.begin(); it != faces.end(); ++it)
- (this->*image2DImplementation)(*it, level, internalFormat, levelSize, format, type, nullptr);
- levelSize = Math::max(Vector2i(1), levelSize/2);
+ (this->*image2DImplementation)(*it, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr);
}
#ifndef MAGNUM_TARGET_GLES
/* Array texture is not scaled in "layer" dimension */
} else if(target == GL_TEXTURE_1D_ARRAY) {
- Vector2i levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
- (this->*image2DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr);
- levelSize.x() = Math::max(1, levelSize.x()/2);
+ (this->*image2DImplementation)(target, level, internalFormat, Math::max(Vector2i(1), size >> level), format, type, nullptr);
}
#endif
@@ -789,10 +781,8 @@ void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei level
if(target == GL_TEXTURE_3D_OES)
#endif
{
- Vector3i levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
- (this->*image3DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr);
- levelSize = Math::max(Vector3i(1), levelSize/2);
+ (this->*image3DImplementation)(target, level, internalFormat, Math::max(Vector3i(1), size >> level), format, type, nullptr);
}
#ifndef MAGNUM_TARGET_GLES2
@@ -804,10 +794,8 @@ void AbstractTexture::storageImplementationFallback(GLenum target, GLsizei level
else if(target == GL_TEXTURE_2D_ARRAY)
#endif
{
- Vector3i levelSize = size;
for(GLsizei level = 0; level != levels; ++level) {
- (this->*image3DImplementation)(target, level, internalFormat, levelSize, format, type, nullptr);
- levelSize.xy() = Math::max(Vector2i(1), levelSize.xy()/2);
+ (this->*image3DImplementation)(target, level, internalFormat, Math::max(Vector3i(1), size >> level), format, type, nullptr);
}
#endif
diff --git a/src/Audio/Context.h b/src/Audio/Context.h
index b28bba470..3969fb87b 100644
--- a/src/Audio/Context.h
+++ b/src/Audio/Context.h
@@ -24,7 +24,7 @@
DEALINGS IN THE SOFTWARE.
*/
-/** @file
+/** @file Audio/Context.h
* @brief Class Magnum::Audio::Context
*/
diff --git a/src/Color.h b/src/Color.h
index 685e4c149..0c3de3ac4 100644
--- a/src/Color.h
+++ b/src/Color.h
@@ -254,13 +254,13 @@ template class BasicColor3: public Math::Vector3 {
return Implementation::value(*this);
}
- MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(BasicColor3, 3)
+ MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(3, BasicColor3)
};
/** @brief Three-component (RGB) float color */
typedef BasicColor3 Color3;
-MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(BasicColor3, 3)
+MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(3, BasicColor3)
/**
@brief Four-component (RGBA) color
@@ -374,13 +374,13 @@ class BasicColor4: public Math::Vector4 {
return Implementation::value(rgb());
}
- MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(BasicColor4, 4)
+ MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(4, BasicColor4)
};
/** @brief Four-component (RGBA) float color */
typedef BasicColor4 Color4;
-MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(BasicColor4, 4)
+MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(4, BasicColor4)
/** @debugoperator{Magnum::BasicColor3} */
template inline Debug operator<<(Debug debug, const BasicColor3& value) {
diff --git a/src/Context.h b/src/Context.h
index cf36f0dc3..7ad05901e 100644
--- a/src/Context.h
+++ b/src/Context.h
@@ -38,6 +38,8 @@
namespace Magnum {
+/** @todoc Resolve conflict with Audio/Context.h (Doxygen doesn't list this file) */
+
namespace Implementation {
struct State;
}
diff --git a/src/DimensionTraits.h b/src/DimensionTraits.h
index 6ca6df1ad..69eb13a05 100644
--- a/src/DimensionTraits.h
+++ b/src/DimensionTraits.h
@@ -55,6 +55,12 @@ template struct DimensionTraits {
#endif
};
+/**
+@todo `using VectorTypeForDimension = typename DimensionTraits::VectorType`
+ etc. shortcuts when support for GCC 4.6 is dropped (similarly to what C++14
+ does with type traits)
+ */
+
#ifndef DOXYGEN_GENERATING_OUTPUT
/* One dimension */
template struct DimensionTraits<1, T> {
diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h
index e53f21c06..39a5d4bd8 100644
--- a/src/Math/Matrix.h
+++ b/src/Math/Matrix.h
@@ -184,17 +184,7 @@ template class Matrix: public RectangularMatrix inline typename std::enable_if::value, Matrix>::type operator*(U number, const Matrix& matrix) {
- return number*RectangularMatrix(matrix);
-}
-template inline typename std::enable_if::value, Matrix>::type operator/(U number, const Matrix& matrix) {
- return number/RectangularMatrix(matrix);
-}
-template inline Matrix operator*(const Vector& vector, const RectangularMatrix& matrix) {
- return RectangularMatrix<1, size, T>(vector)*matrix;
-}
-#endif
+MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(Matrix)
/** @debugoperator{Magnum::Math::Matrix} */
template inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix& value) {
@@ -202,7 +192,7 @@ template inline Corrade::Utility::Debug operator<<(Co
}
#ifndef DOXYGEN_GENERATING_OUTPUT
-#define MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Type, VectorType, size) \
+#define MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(size, Type, VectorType) \
VectorType& operator[](std::size_t col) { \
return static_cast&>(Matrix::operator[](col)); \
} \
@@ -229,17 +219,6 @@ template inline Corrade::Utility::Debug operator<<(Co
return Matrix::invertedOrthogonal(); \
}
-#define MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Type, size) \
- template inline typename std::enable_if::value, Type>::type operator*(U number, const Type& matrix) { \
- return number*Matrix(matrix); \
- } \
- template inline typename std::enable_if::value, Type>::type operator/(U number, const Type& matrix) { \
- return number/Matrix(matrix); \
- } \
- template inline Type operator*(const Vector& vector, const RectangularMatrix& matrix) { \
- return RectangularMatrix<1, size, T>(vector)*matrix; \
- }
-
namespace Implementation {
template class MatrixDeterminant {
diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h
index 07f2c204a..921a92e18 100644
--- a/src/Math/Matrix3.h
+++ b/src/Math/Matrix3.h
@@ -315,10 +315,10 @@ template class Matrix3: public Matrix<3, T> {
}
MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(3, 3, Matrix3)
- MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Matrix3, Vector3, 3)
+ MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(3, Matrix3, Vector3)
};
-MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Matrix3, 3)
+MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(3, Matrix3)
/** @debugoperator{Magnum::Math::Matrix3} */
template inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix3& value) {
diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h
index bb8b1b604..145105b57 100644
--- a/src/Math/Matrix4.h
+++ b/src/Math/Matrix4.h
@@ -383,10 +383,10 @@ template class Matrix4: public Matrix<4, T> {
}
MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(4, 4, Matrix4)
- MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Matrix4, Vector4, 4)
+ MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(4, Matrix4, Vector4)
};
-MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Matrix4, 4)
+MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(4, Matrix4)
/** @debugoperator{Magnum::Math::Matrix4} */
template inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix4& value) {
diff --git a/src/Math/RectangularMatrix.h b/src/Math/RectangularMatrix.h
index 1a76f704d..4baff2d57 100644
--- a/src/Math/RectangularMatrix.h
+++ b/src/Math/RectangularMatrix.h
@@ -286,11 +286,7 @@ template class RectangularMatrix {
* \boldsymbol A_j = a \boldsymbol A_j
* @f]
*/
- #ifndef DOXYGEN_GENERATING_OUTPUT
- template inline typename std::enable_if::value, RectangularMatrix&>::type operator*=(U number) {
- #else
- template RectangularMatrix& operator*=(U number) {
- #endif
+ RectangularMatrix& operator*=(T number) {
for(std::size_t i = 0; i != cols; ++i)
_data[i] *= number;
@@ -300,14 +296,10 @@ template class RectangularMatrix {
/**
* @brief Multiply matrix with number
*
- * @see operator*=(U), operator*(U, const RectangularMatrix&)
+ * @see operator*=(T), operator*(T, const RectangularMatrix&)
*/
- #ifndef DOXYGEN_GENERATING_OUTPUT
- template inline typename std::enable_if::value, RectangularMatrix>::type operator*(U number) const {
- #else
- template RectangularMatrix operator*(U number) const {
- #endif
- return RectangularMatrix(*this)*=number;
+ RectangularMatrix operator*(T number) const {
+ return RectangularMatrix(*this) *= number;
}
/**
@@ -317,11 +309,7 @@ template class RectangularMatrix {
* \boldsymbol A_j = \frac{\boldsymbol A_j} a
* @f]
*/
- #ifndef DOXYGEN_GENERATING_OUTPUT
- template inline typename std::enable_if::value, RectangularMatrix&>::type operator/=(U number) {
- #else
- template RectangularMatrix& operator/=(U number) {
- #endif
+ RectangularMatrix& operator/=(T number) {
for(std::size_t i = 0; i != cols; ++i)
_data[i] /= number;
@@ -331,14 +319,11 @@ template class RectangularMatrix {
/**
* @brief Divide matrix with number
*
- * @see operator/=(), operator/(U, const RectangularMatrix&)
+ * @see operator/=(T),
+ * operator/(T, const RectangularMatrix&)
*/
- #ifndef DOXYGEN_GENERATING_OUTPUT
- template inline typename std::enable_if::value, RectangularMatrix>::type operator/(U number) const {
- #else
- template RectangularMatrix operator/(U number) const {
- #endif
- return RectangularMatrix(*this)/=number;
+ RectangularMatrix operator/(T number) const {
+ return RectangularMatrix(*this) /= number;
}
/**
@@ -358,8 +343,8 @@ template class RectangularMatrix {
* (\boldsymbol {Aa})_i = \sum_{k=0}^{m-1} \boldsymbol A_{ki} \boldsymbol a_k
* @f]
*/
- Vector operator*(const Vector& other) const {
- return operator*(RectangularMatrix<1, rows, T>(other))[0];
+ Vector operator*(const Vector& other) const {
+ return operator*(RectangularMatrix<1, cols, T>(other))[0];
}
/**
@@ -414,13 +399,16 @@ template class RectangularMatrix {
/** @relates RectangularMatrix
@brief Multiply number with matrix
-Same as RectangularMatrix::operator*(U) const.
+Same as RectangularMatrix::operator*(T) const.
*/
-#ifdef DOXYGEN_GENERATING_OUTPUT
-template inline RectangularMatrix operator*(U number, const RectangularMatrix& matrix) {
-#else
-template inline typename std::enable_if::value, RectangularMatrix>::type operator*(U number, const RectangularMatrix& matrix) {
-#endif
+template inline RectangularMatrix operator*(
+ #ifdef DOXYGEN_GENERATING_OUTPUT
+ T
+ #else
+ typename std::common_type::type
+ #endif
+ number, const RectangularMatrix& matrix)
+{
return matrix*number;
}
@@ -430,13 +418,16 @@ template inline typename s
The computation is done column-wise. @f[
\boldsymbol B_j = \frac a {\boldsymbol A_j}
@f]
-@see RectangularMatrix::operator/(U) const
+@see RectangularMatrix::operator/(T) const
*/
-#ifdef DOXYGEN_GENERATING_OUTPUT
-template inline RectangularMatrix operator/(U number, const RectangularMatrix& matrix) {
-#else
-template inline typename std::enable_if::value, RectangularMatrix>::type operator/(U number, const RectangularMatrix& matrix) {
-#endif
+template inline RectangularMatrix operator/(
+ #ifdef DOXYGEN_GENERATING_OUTPUT
+ T
+ #else
+ typename std::common_type::type
+ #endif
+ number, const RectangularMatrix& matrix)
+{
RectangularMatrix out;
for(std::size_t i = 0; i != cols; ++i)
@@ -509,11 +500,6 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
return *reinterpret_cast(data); \
} \
\
- __VA_ARGS__& operator=(const Math::RectangularMatrix& other) { \
- Math::RectangularMatrix::operator=(other); \
- return *this; \
- } \
- \
__VA_ARGS__ operator-() const { \
return Math::RectangularMatrix::operator-(); \
} \
@@ -531,20 +517,42 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
__VA_ARGS__ operator-(const Math::RectangularMatrix& other) const { \
return Math::RectangularMatrix::operator-(other); \
} \
- template typename std::enable_if::value, __VA_ARGS__&>::type operator*=(U number) { \
+ __VA_ARGS__& operator*=(T number) { \
Math::RectangularMatrix::operator*=(number); \
return *this; \
} \
- template typename std::enable_if::value, __VA_ARGS__>::type operator*(U number) const { \
+ __VA_ARGS__ operator*(T number) const { \
return Math::RectangularMatrix::operator*(number); \
} \
- template typename std::enable_if::value, __VA_ARGS__&>::type operator/=(U number) { \
+ __VA_ARGS__& operator/=(T number) { \
Math::RectangularMatrix::operator/=(number); \
return *this; \
} \
- template typename std::enable_if::value, __VA_ARGS__>::type operator/(U number) const { \
+ __VA_ARGS__ operator/(T number) const { \
return Math::RectangularMatrix::operator/(number); \
}
+
+#define MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(...) \
+ template inline __VA_ARGS__ operator*(typename std::common_type::type number, const __VA_ARGS__& matrix) { \
+ return number*static_cast&>(matrix); \
+ } \
+ template inline __VA_ARGS__ operator/(typename std::common_type::type number, const __VA_ARGS__& matrix) { \
+ return number/static_cast&>(matrix); \
+ } \
+ template inline __VA_ARGS__ operator*(const Vector& vector, const RectangularMatrix& matrix) { \
+ return Math::RectangularMatrix<1, size, T>(vector)*matrix; \
+ }
+
+#define MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(size, Type) \
+ template inline Type operator*(typename std::common_type::type number, const Type& matrix) { \
+ return number*static_cast&>(matrix); \
+ } \
+ template inline Type operator/(typename std::common_type::type number, const Type& matrix) { \
+ return number/static_cast&>(matrix); \
+ } \
+ template inline Type operator*(const Vector& vector, const RectangularMatrix& matrix) { \
+ return Math::RectangularMatrix<1, size, T>(vector)*matrix; \
+ }
#endif
template inline RectangularMatrix RectangularMatrix::fromDiagonal(const Vector& diagonal) {
diff --git a/src/Math/Test/MatrixTest.cpp b/src/Math/Test/MatrixTest.cpp
index 5d66b05b6..3f6a81e8b 100644
--- a/src/Math/Test/MatrixTest.cpp
+++ b/src/Math/Test/MatrixTest.cpp
@@ -75,6 +75,9 @@ class MatrixTest: public Corrade::TestSuite::Tester {
void inverted();
void invertedOrthogonal();
+ void subclassTypes();
+ void subclass();
+
void debug();
void configuration();
};
@@ -103,6 +106,10 @@ MatrixTest::MatrixTest() {
&MatrixTest::determinant,
&MatrixTest::inverted,
&MatrixTest::invertedOrthogonal,
+
+ &MatrixTest::subclassTypes,
+ &MatrixTest::subclass,
+
&MatrixTest::debug,
&MatrixTest::configuration});
}
@@ -293,6 +300,62 @@ void MatrixTest::invertedOrthogonal() {
CORRADE_COMPARE(a.invertedOrthogonal(), a.inverted());
}
+template class BasicVec2: public Math::Vector<2, T> {
+ public:
+ template BasicVec2(U&&... args): Math::Vector<2, T>{std::forward(args)...} {}
+};
+
+template class BasicMat2: public Math::Matrix<2, T> {
+ public:
+ template BasicMat2(U&&... args): Math::Matrix<2, T>{std::forward(args)...} {}
+
+ MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(2, BasicMat2, BasicVec2)
+};
+
+typedef BasicVec2 Vec2;
+typedef BasicMat2 Mat2;
+
+void MatrixTest::subclassTypes() {
+ const Mat2 c;
+ Mat2 a;
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+
+ const Mat2 c2;
+ const Vec2 cv;
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+}
+
+void MatrixTest::subclass() {
+ const Mat2 a(Vec2(2.0f, 3.5f),
+ Vec2(3.0f, 1.0f));
+ Mat2 b(Vec2(2.0f, 3.5f),
+ Vec2(3.0f, 1.0f));
+ CORRADE_COMPARE(a[1], Vec2(3.0f, 1.0f));
+ CORRADE_COMPARE(b[1], Vec2(3.0f, 1.0f));
+ CORRADE_COMPARE(a.row(1), Vec2(3.5f, 1.0f));
+
+ CORRADE_COMPARE(a*b, Mat2(Vec2(14.5f, 10.5f),
+ Vec2(9.0f, 11.5f)));
+ CORRADE_COMPARE(a*Vec2(1.0f, 0.5f), Vec2(3.5f, 4.0f));
+
+ CORRADE_COMPARE(a.transposed(), Mat2(Vec2(2.0f, 3.0f),
+ Vec2(3.5f, 1.0f)));
+
+ Mat2 c(Vec2(Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f),
+ Vec2(-Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f));
+ CORRADE_COMPARE(c.inverted(), Mat2(Vec2(Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f),
+ Vec2(Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f)));
+ CORRADE_COMPARE(c.invertedOrthogonal(), Mat2(Vec2(Constants::sqrt2()/2.0f, -Constants::sqrt2()/2.0f),
+ Vec2(Constants::sqrt2()/2.0f, Constants::sqrt2()/2.0f)));
+}
+
void MatrixTest::debug() {
Matrix4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.0f),
diff --git a/src/Math/Test/RectangularMatrixTest.cpp b/src/Math/Test/RectangularMatrixTest.cpp
index fb686d222..4da3c411f 100644
--- a/src/Math/Test/RectangularMatrixTest.cpp
+++ b/src/Math/Test/RectangularMatrixTest.cpp
@@ -74,12 +74,16 @@ class RectangularMatrixTest: public Corrade::TestSuite::Tester {
void addSubtract();
void multiplyDivide();
void multiply();
+ void multiplyVector();
void transposed();
void diagonal();
void vector();
+ void subclassTypes();
+ void subclass();
+
void debug();
void configuration();
};
@@ -91,6 +95,11 @@ typedef RectangularMatrix<2, 2, Int> Matrix2i;
typedef Vector<4, Float> Vector4;
typedef Vector<3, Float> Vector3;
typedef Vector<2, Float> Vector2;
+
+typedef RectangularMatrix<4, 3, Int> Matrix4x3i;
+typedef RectangularMatrix<3, 4, Int> Matrix3x4i;
+typedef Vector<4, Int> Vector4i;
+typedef Vector<3, Int> Vector3i;
typedef Vector<2, Int> Vector2i;
RectangularMatrixTest::RectangularMatrixTest() {
@@ -111,12 +120,16 @@ RectangularMatrixTest::RectangularMatrixTest() {
&RectangularMatrixTest::addSubtract,
&RectangularMatrixTest::multiplyDivide,
&RectangularMatrixTest::multiply,
+ &RectangularMatrixTest::multiplyVector,
&RectangularMatrixTest::transposed,
&RectangularMatrixTest::diagonal,
&RectangularMatrixTest::vector,
+ &RectangularMatrixTest::subclassTypes,
+ &RectangularMatrixTest::subclass,
+
&RectangularMatrixTest::debug,
&RectangularMatrixTest::configuration});
}
@@ -313,19 +326,12 @@ void RectangularMatrixTest::multiplyDivide() {
CORRADE_COMPARE(-1.5f*matrix, multiplied);
CORRADE_COMPARE(multiplied/-1.5f, matrix);
- Math::RectangularMatrix<1, 1, Byte> matrixChar(32);
- Math::RectangularMatrix<1, 1, Byte> multipliedChar(-48);
- CORRADE_COMPARE(matrixChar*-1.5f, multipliedChar);
- CORRADE_COMPARE(multipliedChar/-1.5f, matrixChar);
- CORRADE_COMPARE(-1.5f*matrixChar, multipliedChar);
-
/* Divide vector with number and inverse */
Matrix2 divisor(Vector2( 1.0f, 2.0f),
Vector2(-4.0f, 8.0f));
Matrix2 result(Vector2( 1.0f, 0.5f),
Vector2(-0.25f, 0.125f));
CORRADE_COMPARE(1.0f/divisor, result);
- CORRADE_COMPARE(-1550.0f/multipliedChar, matrixChar);
}
void RectangularMatrixTest::multiply() {
@@ -355,6 +361,22 @@ void RectangularMatrixTest::multiply() {
CORRADE_COMPARE(left*right, expected);
}
+void RectangularMatrixTest::multiplyVector() {
+ Vector4i a(-5, 27, 10, 33);
+ RectangularMatrix<3, 1, Int> b(1, 2, 3);
+ CORRADE_COMPARE(a*b, Matrix3x4i(
+ Vector4i( -5, 27, 10, 33),
+ Vector4i(-10, 54, 20, 66),
+ Vector4i(-15, 81, 30, 99)
+ ));
+
+ Matrix3x4i c(Vector4i(0, 4, 8, 12),
+ Vector4i(1, 5, 9, 13),
+ Vector4i(3, 7, 11, 15));
+ Vector3i d(2, -2, 3);
+ CORRADE_COMPARE(c*d, Vector4i(7, 19, 31, 43));
+}
+
void RectangularMatrixTest::transposed() {
Matrix4x3 original(Vector3( 0.0f, 1.0f, 3.0f),
Vector3( 4.0f, 5.0f, 7.0f),
@@ -399,6 +421,110 @@ void RectangularMatrixTest::vector() {
CORRADE_COMPARE(Matrix4x3i::fromVector(b), a);
}
+template class BasicMat: public Math::RectangularMatrix {
+ public:
+ template BasicMat(U&&... args): Math::RectangularMatrix{std::forward(args)...} {}
+
+ MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(size, size, BasicMat)
+};
+
+MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(BasicMat)
+
+template class BasicMat2x2: public BasicMat<2, T> {
+ public:
+ template BasicMat2x2(U&&... args): BasicMat<2, T>{std::forward(args)...} {}
+
+ MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(2, 2, BasicMat2x2)
+};
+
+MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(2, BasicMat2x2)
+
+typedef BasicMat2x2 Mat2x2;
+
+void RectangularMatrixTest::subclassTypes() {
+ Float* const data = nullptr;
+ const Float* const cdata = nullptr;
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+
+ /* Const operators */
+ const Mat2x2 c;
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same()), Mat2x2>::value));
+
+ /* Assignment operators */
+ Mat2x2 a;
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+ CORRADE_VERIFY((std::is_same::value));
+
+ /* Operators on variable-sized matrix */
+ const BasicMat<3, Float> c2;
+ CORRADE_VERIFY((std::is_same>::value));
+ CORRADE_VERIFY((std::is_same>::value));
+ CORRADE_VERIFY((std::is_same()), BasicMat<3, Float>>::value));
+}
+
+void RectangularMatrixTest::subclass() {
+ Float data[] = {1.0f, -2.0f, 3.0f, -4.5f};
+ CORRADE_COMPARE(Mat2x2::from(data), Mat2x2(Vector2(1.0f, -2.0f),
+ Vector2(3.0f, -4.5f)));
+
+ const Float cdata[] = {1.0f, -2.0f, 3.0f, -4.5f};
+ CORRADE_COMPARE(Mat2x2::from(cdata), Mat2x2(Vector2(1.0f, -2.0f),
+ Vector2(3.0f, -4.5f)));
+
+ const Mat2x2 a(Vector2(1.0f, -3.0f),
+ Vector2(-3.0f, 1.0f));
+ CORRADE_COMPARE(-a, Mat2x2(Vector2(-1.0f, 3.0f),
+ Vector2(3.0f, -1.0f)));
+
+ Mat2x2 b(Vector2(-2.0f, 5.0f),
+ Vector2(5.0f, -2.0f));
+ const Mat2x2 bExpected(Vector2(-1.0f, 2.0f),
+ Vector2(2.0f, -1.0f));
+ CORRADE_COMPARE(b + a, bExpected);
+
+ Mat2x2 c(Vector2(-2.0f, 5.0f),
+ Vector2(5.0f, -2.0f));
+ const Mat2x2 cExpected(Vector2(-3.0f, 8.0f),
+ Vector2(8.0f, -3.0f));
+ CORRADE_COMPARE(c - a, cExpected);
+
+ Mat2x2 d(Vector2(-2.0f, 5.0f),
+ Vector2(5.0f, -2.0f));
+ const Mat2x2 dExpected(Vector2(-4.0f, 10.0f),
+ Vector2(10.0f, -4.0f));
+ CORRADE_COMPARE(d*2.0f, dExpected);
+ CORRADE_COMPARE(2.0f*d, dExpected);
+
+ Mat2x2 e(Vector2(-2.0f, 5.0f),
+ Vector2(5.0f, -2.0f));
+ CORRADE_COMPARE(e/0.5f, dExpected);
+ CORRADE_COMPARE(2.0f/e, Mat2x2(Vector2(-1.0f, 0.4f),
+ Vector2(0.4f, -1.0f)));
+ const Vector2 f(2.0f, 5.0f);
+ const Math::RectangularMatrix<2, 1, Float> g(3.0f, -1.0f);
+ CORRADE_COMPARE(f*g, Mat2x2(Vector2(6.0f, 15.0f),
+ Vector2(-2.0f, -5.0f)));
+
+ /* Operators on variable-sized matrix */
+ const BasicMat<1, Float> h(-2.0f);
+ CORRADE_COMPARE(2.0f*h, (BasicMat<1, Float>(-4.0f)));
+ CORRADE_COMPARE(2.0f/h, (BasicMat<1, Float>(-1.0f)));
+
+ const Math::Vector<1, Float> i(2.0f);
+ const Math::RectangularMatrix<1, 1, Float> j(3.0f);
+ CORRADE_COMPARE(i*j, (BasicMat<1, Float>(6.0f)));
+}
+
void RectangularMatrixTest::debug() {
Matrix3x4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.0f),
diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp
index 63869ef00..1c114ac4e 100644
--- a/src/Math/Test/VectorTest.cpp
+++ b/src/Math/Test/VectorTest.cpp
@@ -62,6 +62,7 @@ class VectorTest: public Corrade::TestSuite::Tester {
void constructConversion();
void constructCopy();
+ void isZero();
void isNormalized();
void convert();
@@ -70,7 +71,10 @@ class VectorTest: public Corrade::TestSuite::Tester {
void negative();
void addSubtract();
void multiplyDivide();
+ void multiplyDivideIntegral();
void multiplyDivideComponentWise();
+ void multiplyDivideComponentWiseIntegral();
+ void bitwise();
void compare();
void compareComponentWise();
@@ -91,6 +95,9 @@ class VectorTest: public Corrade::TestSuite::Tester {
void projectedOntoNormalized();
void angle();
+ void subclassTypes();
+ void subclass();
+
void debug();
void configuration();
};
@@ -109,6 +116,7 @@ VectorTest::VectorTest() {
&VectorTest::constructConversion,
&VectorTest::constructCopy,
+ &VectorTest::isZero,
&VectorTest::isNormalized,
&VectorTest::convert,
@@ -117,7 +125,10 @@ VectorTest::VectorTest() {
&VectorTest::negative,
&VectorTest::addSubtract,
&VectorTest::multiplyDivide,
+ &VectorTest::multiplyDivideIntegral,
&VectorTest::multiplyDivideComponentWise,
+ &VectorTest::multiplyDivideComponentWiseIntegral,
+ &VectorTest::bitwise,
&VectorTest::compare,
&VectorTest::compareComponentWise,
@@ -138,6 +149,9 @@ VectorTest::VectorTest() {
&VectorTest::projectedOntoNormalized,
&VectorTest::angle,
+ &VectorTest::subclassTypes,
+ &VectorTest::subclass,
+
&VectorTest::debug,
&VectorTest::configuration});
}
@@ -198,6 +212,11 @@ void VectorTest::constructCopy() {
CORRADE_COMPARE(b, Vector4(1.0f, 3.5f, 4.0f, -2.7f));
}
+void VectorTest::isZero() {
+ CORRADE_VERIFY(!Vector3(0.01f, 0.0f, 0.0f).isZero());
+ CORRADE_VERIFY(Vector3(0.0f, 0.0f, 0.0f).isZero());
+}
+
void VectorTest::isNormalized() {
CORRADE_VERIFY(!Vector3(1.0f, 2.0f, -1.0f).isNormalized());
CORRADE_VERIFY(Vector3(0.0f, 1.0f, 0.0f).isNormalized());
@@ -285,17 +304,21 @@ void VectorTest::multiplyDivide() {
CORRADE_COMPARE(-1.5f*vector, multiplied);
CORRADE_COMPARE(multiplied/-1.5f, vector);
- Math::Vector<1, Byte> vectorChar(32);
- Math::Vector<1, Byte> multipliedChar(-48);
- CORRADE_COMPARE(vectorChar*-1.5f, multipliedChar);
- CORRADE_COMPARE(multipliedChar/-1.5f, vectorChar);
- CORRADE_COMPARE(-1.5f*vectorChar, multipliedChar);
-
- /* Divide vector with number and inverse */
+ /* Divide vector with number and invert */
Vector4 divisor(1.0f, 2.0f, -4.0f, 8.0f);
Vector4 result(1.0f, 0.5f, -0.25f, 0.125f);
CORRADE_COMPARE(1.0f/divisor, result);
- CORRADE_COMPARE(-1550.0f/multipliedChar, vectorChar);
+}
+
+void VectorTest::multiplyDivideIntegral() {
+ Vector4i vector(32, 10, -6, 2);
+ Vector4i multiplied(-48, -15, 9, -3);
+
+ CORRADE_COMPARE(vector*-1.5f, multiplied);
+ CORRADE_COMPARE(-1.5f*vector, multiplied);
+
+ CORRADE_COMPARE(multiplied/-1.5f, vector);
+ /* Using integer vector as divisor is not supported */
}
void VectorTest::multiplyDivideComponentWise() {
@@ -307,6 +330,33 @@ void VectorTest::multiplyDivideComponentWise() {
CORRADE_COMPARE(multiplied/multiplier, vec);
}
+void VectorTest::multiplyDivideComponentWiseIntegral() {
+ Vector4i vec(7, 2, -16, -1);
+ Vector4 multiplier(2.0f, -1.5f, 0.5f, 10.0f);
+ Vector4i multiplied(14, -3, -8, -10);
+
+ CORRADE_COMPARE(vec*multiplier, multiplied);
+ CORRADE_COMPARE(multiplier*vec, multiplied);
+
+ CORRADE_COMPARE(multiplied/multiplier, vec);
+ /* Using integer vector as divisor is not supported */
+}
+
+void VectorTest::bitwise() {
+ typedef Math::Vector<2, Int> Vector2i;
+
+ const Vector2i a(85, 240);
+ const Vector2i b(170, 85);
+ CORRADE_COMPARE(~a, Vector2i(-86, -241));
+ CORRADE_COMPARE(a & b, Vector2i(0, 80));
+ CORRADE_COMPARE(a | b, Vector2i(255, 245));
+ CORRADE_COMPARE(a ^ b, Vector2i(255, 165));
+
+ const Vector2i c(7, 32);
+ CORRADE_COMPARE(c << 2, Vector2i(28, 128));
+ CORRADE_COMPARE(c >> 2, Vector2i(1, 8));
+}
+
void VectorTest::dot() {
CORRADE_COMPARE(Vector4::dot({1.0f, 0.5f, 0.75f, 1.5f}, {2.0f, 4.0f, 1.0f, 7.0f}), 15.25f);
}
@@ -394,6 +444,120 @@ void VectorTest::angle() {
Rad(1.162514f));
}
+template class BasicVec2: public Math::Vector<2, T> {
+ public:
+ template