Browse Source

Merge branch 'master' into compatibility

Conflicts:
	src/Magnum/DebugTools/ShapeRenderer.h
	src/Magnum/Math/Angle.h
	src/Magnum/Platform/ScreenedApplication.h
	src/Magnum/Primitives/Capsule.cpp
	src/Magnum/Primitives/Circle.cpp
	src/Magnum/Primitives/Crosshair.cpp
	src/Magnum/Primitives/Cube.cpp
	src/Magnum/Primitives/Cylinder.cpp
	src/Magnum/Primitives/Implementation/WireframeSpheroid.cpp
	src/Magnum/Primitives/Line.cpp
	src/Magnum/Primitives/Plane.cpp
	src/Magnum/Primitives/Square.cpp
	src/Magnum/Primitives/UVSphere.cpp
	src/Magnum/ResourceManager.h
	src/Magnum/Text/GlyphCache.cpp
	src/Magnum/Trade/TextureData.h
Vladimír Vondruš 12 years ago
parent
commit
5bc519717f
  1. 12
      CMakeLists.txt
  2. 2311
      Doxyfile
  3. 3
      doc/building.dox
  4. 1
      doc/cmake.dox
  5. 49
      doc/coding-style.dox
  6. 5
      doc/opengl-mapping.dox
  7. 6
      doc/opengl-support.dox
  8. 16
      modules/FindMagnum.cmake
  9. 56
      package/archlinux/PKGBUILD-gcc49
  10. 14
      package/archlinux/PKGBUILD-mingw-w64
  11. 2
      src/Magnum/AbstractFramebuffer.cpp
  12. 17
      src/Magnum/AbstractImage.h
  13. 2
      src/Magnum/AbstractResourceLoader.h
  14. 50
      src/Magnum/AbstractShaderProgram.cpp
  15. 99
      src/Magnum/AbstractShaderProgram.h
  16. 10
      src/Magnum/AbstractTexture.cpp
  17. 1
      src/Magnum/AbstractTexture.h
  18. 10
      src/Magnum/Array.h
  19. 43
      src/Magnum/Audio/AbstractImporter.h
  20. 2
      src/Magnum/Audio/Audio.h
  21. 4
      src/Magnum/Audio/Buffer.h
  22. 8
      src/Magnum/Audio/Context.h
  23. 8
      src/Magnum/Audio/Renderer.h
  24. 8
      src/Magnum/Audio/Source.h
  25. 1
      src/Magnum/Buffer.cpp
  26. 20
      src/Magnum/Buffer.h
  27. 4
      src/Magnum/Color.h
  28. 16
      src/Magnum/ColorFormat.h
  29. 27
      src/Magnum/Context.cpp
  30. 78
      src/Magnum/Context.h
  31. 6
      src/Magnum/CubeMapTexture.h
  32. 6
      src/Magnum/CubeMapTextureArray.h
  33. 6
      src/Magnum/DebugMessage.h
  34. 2
      src/Magnum/DebugTools/DebugTools.h
  35. 5
      src/Magnum/DebugTools/ForceRenderer.h
  36. 5
      src/Magnum/DebugTools/ObjectRenderer.h
  37. 24
      src/Magnum/DebugTools/Profiler.h
  38. 2
      src/Magnum/DebugTools/ResourceManager.h
  39. 10
      src/Magnum/DebugTools/ShapeRenderer.h
  40. 8
      src/Magnum/DefaultFramebuffer.h
  41. 9
      src/Magnum/DimensionTraits.h
  42. 22
      src/Magnum/Extensions.h
  43. 1
      src/Magnum/Framebuffer.cpp
  44. 10
      src/Magnum/Framebuffer.h
  45. 6
      src/Magnum/Implementation/BufferState.cpp
  46. 2
      src/Magnum/Implementation/BufferState.h
  47. 7
      src/Magnum/Implementation/FramebufferState.cpp
  48. 2
      src/Magnum/Implementation/FramebufferState.h
  49. 16
      src/Magnum/Implementation/MeshState.cpp
  50. 6
      src/Magnum/Implementation/MeshState.h
  51. 6
      src/Magnum/Implementation/ShaderProgramState.cpp
  52. 2
      src/Magnum/Implementation/ShaderProgramState.h
  53. 3
      src/Magnum/Implementation/State.h
  54. 6
      src/Magnum/Implementation/TextureState.cpp
  55. 2
      src/Magnum/Implementation/TextureState.h
  56. 1
      src/Magnum/Implementation/setupDriverWorkarounds.cpp
  57. 2
      src/Magnum/Magnum.h
  58. 9
      src/Magnum/Math/Algorithms/GaussJordan.h
  59. 10
      src/Magnum/Math/Algorithms/GramSchmidt.h
  60. 2
      src/Magnum/Math/Algorithms/Svd.h
  61. 20
      src/Magnum/Math/Angle.h
  62. 14
      src/Magnum/Math/BoolVector.h
  63. 64
      src/Magnum/Math/Complex.h
  64. 6
      src/Magnum/Math/Constants.h
  65. 8
      src/Magnum/Math/Dual.h
  66. 49
      src/Magnum/Math/DualComplex.h
  67. 83
      src/Magnum/Math/DualQuaternion.h
  68. 14
      src/Magnum/Math/Functions.h
  69. 53
      src/Magnum/Math/Geometry/Distance.h
  70. 6
      src/Magnum/Math/Geometry/Intersection.h
  71. 2
      src/Magnum/Math/Math.h
  72. 26
      src/Magnum/Math/Matrix.h
  73. 97
      src/Magnum/Math/Matrix3.h
  74. 133
      src/Magnum/Math/Matrix4.h
  75. 101
      src/Magnum/Math/Quaternion.h
  76. 6
      src/Magnum/Math/Range.h
  77. 66
      src/Magnum/Math/RectangularMatrix.h
  78. 2
      src/Magnum/Math/Swizzle.h
  79. 8
      src/Magnum/Math/Test/FunctionsTest.cpp
  80. 8
      src/Magnum/Math/Test/SwizzleTest.cpp
  81. 6
      src/Magnum/Math/TypeTraits.h
  82. 4
      src/Magnum/Math/Unit.h
  83. 135
      src/Magnum/Math/Vector.h
  84. 28
      src/Magnum/Math/Vector2.h
  85. 9
      src/Magnum/Math/Vector3.h
  86. 3
      src/Magnum/Math/Vector4.h
  87. 1
      src/Magnum/Mesh.cpp
  88. 23
      src/Magnum/Mesh.h
  89. 4
      src/Magnum/MeshTools/CombineIndexedArrays.h
  90. 7
      src/Magnum/MeshTools/CompressIndices.h
  91. 15
      src/Magnum/MeshTools/FlipNormals.h
  92. 10
      src/Magnum/MeshTools/GenerateFlatNormals.h
  93. 16
      src/Magnum/MeshTools/Interleave.h
  94. 2
      src/Magnum/MeshTools/Subdivide.h
  95. 2
      src/Magnum/MeshTools/Test/GenerateFlatNormalsTest.cpp
  96. 2
      src/Magnum/MeshTools/Tipsify.h
  97. 20
      src/Magnum/MeshTools/Transform.h
  98. 119
      src/Magnum/MeshView.cpp
  99. 37
      src/Magnum/MeshView.h
  100. 2
      src/Magnum/MultisampleTexture.h
  101. Some files were not shown because too many files have changed in this diff Show More

12
CMakeLists.txt

@ -63,6 +63,10 @@ elseif(CORRADE_TARGET_UNIX AND NOT APPLE)
option(WITH_GLXAPPLICATION "Build GlxApplication library" OFF) option(WITH_GLXAPPLICATION "Build GlxApplication library" OFF)
cmake_dependent_option(WITH_WINDOWLESSGLXAPPLICATION "Build WindowlessGlxApplication library" OFF "NOT WITH_MAGNUMINFO;NOT WITH_FONTCONVERTER;NOT WITH_DISTANCEFIELDCONVERTER" ON) cmake_dependent_option(WITH_WINDOWLESSGLXAPPLICATION "Build WindowlessGlxApplication library" OFF "NOT WITH_MAGNUMINFO;NOT WITH_FONTCONVERTER;NOT WITH_DISTANCEFIELDCONVERTER" ON)
cmake_dependent_option(WITH_XEGLAPPLICATION "Build XEglApplication library" OFF "TARGET_GLES" OFF) cmake_dependent_option(WITH_XEGLAPPLICATION "Build XEglApplication library" OFF "TARGET_GLES" OFF)
# Windows-specific application libraries
elseif(CORRADE_TARGET_WINDOWS)
cmake_dependent_option(WITH_WINDOWLESSWGLAPPLICATION "Build WindowlessWglApplication library" OFF "NOT WITH_MAGNUMINFO;NOT WITH_FONTCONVERTER;NOT WITH_DISTANCEFIELDCONVERTER" ON)
endif() endif()
# Platform-independent (almost) application libraries # Platform-independent (almost) application libraries
@ -71,13 +75,13 @@ if(NOT CORRADE_TARGET_NACL AND NOT CORRADE_TARGET_ANDROID)
option(WITH_SDL2APPLICATION "Build Sdl2Application library" OFF) option(WITH_SDL2APPLICATION "Build Sdl2Application library" OFF)
endif() endif()
# Magnum Info (currently only using GLX or NaCl) # Magnum Info (currently only using GLX or WGL or on NaCl)
if((CORRADE_TARGET_UNIX AND NOT APPLE) OR CORRADE_TARGET_NACL) if((CORRADE_TARGET_UNIX AND NOT APPLE) OR CORRADE_TARGET_NACL OR CORRADE_TARGET_WINDOWS)
option(WITH_MAGNUMINFO "Build magnum-info utility" OFF) option(WITH_MAGNUMINFO "Build magnum-info utility" OFF)
endif() endif()
# Utilities (currently depending on WindowlessGlxApplication) # Utilities (currently only using GLX or WGL)
if(CORRADE_TARGET_UNIX AND NOT APPLE) if((CORRADE_TARGET_UNIX AND NOT APPLE) OR CORRADE_TARGET_WINDOWS)
cmake_dependent_option(WITH_FONTCONVERTER "Build magnum-fontconverter utility" OFF "NOT TARGET_GLES" OFF) cmake_dependent_option(WITH_FONTCONVERTER "Build magnum-fontconverter utility" OFF "NOT TARGET_GLES" OFF)
cmake_dependent_option(WITH_DISTANCEFIELDCONVERTER "Build magnum-distancefieldconverter utility" OFF "NOT TARGET_GLES" OFF) cmake_dependent_option(WITH_DISTANCEFIELDCONVERTER "Build magnum-distancefieldconverter utility" OFF "NOT TARGET_GLES" OFF)
endif() endif()

2311
Doxyfile

File diff suppressed because it is too large Load Diff

3
doc/building.dox

@ -201,9 +201,10 @@ platform best:
- `WITH_XEGLAPPLICATION` - @ref Platform::XEglApplication "XEglApplication" - `WITH_XEGLAPPLICATION` - @ref Platform::XEglApplication "XEglApplication"
- `WITH_WINDOWLESSGLXAPPLICATION` - @ref Platform::WindowlessGlxApplication "WindowlessGlxApplication" - `WITH_WINDOWLESSGLXAPPLICATION` - @ref Platform::WindowlessGlxApplication "WindowlessGlxApplication"
- `WITH_WINDOWLESSNACLAPPLICATION` - @ref Platform::WindowlessNaClApplication "WindowlessNaClApplication" - `WITH_WINDOWLESSNACLAPPLICATION` - @ref Platform::WindowlessNaClApplication "WindowlessNaClApplication"
- `WITH_WINDOWLESSWGLAPPLICATION` - @ref Platform::WindowlessWglApplication "WindowlessWglApplication"
There are also a few command-line utilities. They are currently available only There are also a few command-line utilities. They are currently available only
on Linux and are disabled by default: on Linux and Windows, also disabled by default:
- `WITH_MAGNUMINFO` - `magnum-info` executable, provides information about - `WITH_MAGNUMINFO` - `magnum-info` executable, provides information about
the engine and OpenGL capabilities. the engine and OpenGL capabilities.

1
doc/cmake.dox

@ -90,6 +90,7 @@ Platform namespace is split into more components:
- `%XEglApplication` -- @ref Platform::XEglApplication "XEglApplication" - `%XEglApplication` -- @ref Platform::XEglApplication "XEglApplication"
- `%WindowlessGlxApplication` -- @ref Platform::WindowlessGlxApplication "WindowlessGlxApplication" - `%WindowlessGlxApplication` -- @ref Platform::WindowlessGlxApplication "WindowlessGlxApplication"
- `%WindowlessNaClApplication` -- @ref Platform::WindowlessNaClApplication "WindowlessNaClApplication" - `%WindowlessNaClApplication` -- @ref Platform::WindowlessNaClApplication "WindowlessNaClApplication"
- `%WindowlessWglApplication` -- @ref Platform::WindowlessWglApplication "WindowlessWglApplication"
The library also contains a set of plugins for importing essential file The library also contains a set of plugins for importing essential file
formats. Additional plugins are provided in separate plugin repository, see formats. Additional plugins are provided in separate plugin repository, see

49
doc/coding-style.dox

@ -39,9 +39,9 @@ needed. You are encouraged to read it first:
- @ref corrade-coding-style - @ref corrade-coding-style
@section cpp C++ code @section coding-style-cpp C++ code
@subsection cpp-headers Headers @subsection coding-style-cpp-headers Headers
Headers shouldn't have `using` declarations inside them (unless there is good Headers shouldn't have `using` declarations inside them (unless there is good
excuse, see Magnum.h). excuse, see Magnum.h).
@ -50,9 +50,9 @@ Headers have `*.h` extension, @ref compilation-speedup-hpp "template implementat
have `*.hpp` extension (hinting that they are something between `*.h` and have `*.hpp` extension (hinting that they are something between `*.h` and
`*.cpp` files). `*.cpp` files).
@subsection cpp-format Code format @subsection coding-style-cpp-format Code format
@subsubsection cpp-types Builtin types @subsubsection coding-style-cpp-types Builtin types
Use %Magnum's own type aliases for public API (e.g. @ref UnsignedInt, see Use %Magnum's own type aliases for public API (e.g. @ref UnsignedInt, see
@ref types for more information), but use specific types when interacting with @ref types for more information), but use specific types when interacting with
@ -61,13 +61,13 @@ conversions when converting between them. This helps avoiding sign, truncation
and other issues, e.g. `%Math::%Vector2<GLsizei>` will implicitly convert to and other issues, e.g. `%Math::%Vector2<GLsizei>` will implicitly convert to
@ref Vector2i if and only if @ref Int is the same type as `GLsizei`. @ref Vector2i if and only if @ref Int is the same type as `GLsizei`.
@subsubsection cpp-naming Naming @subsubsection coding-style-cpp-naming Naming
When writing wrappers for OpenGL functions and defines, try to match the When writing wrappers for OpenGL functions and defines, try to match the
original name as closely as possible, although expanding abbrevations (and original name as closely as possible, although expanding abbrevations (and
removing redundant prefixes) is encouraged. removing redundant prefixes) is encouraged.
@subsubsection cpp-forward-declarations Forward declarations and forward declaration headers @subsubsection coding-style-cpp-forward-declarations Forward declarations and forward declaration headers
When a namespace has classes which are commonly forward-declared, consider When a namespace has classes which are commonly forward-declared, consider
making a forward declaration header - it should have the same name as the making a forward declaration header - it should have the same name as the
@ -75,14 +75,14 @@ namespace itself and contain foward declarations for all classes, enums and
copies of all meaningful typedefs. See @ref compilation-forward-declarations copies of all meaningful typedefs. See @ref compilation-forward-declarations
for more information. for more information.
@section compatibility Compatibility with various OpenGL editions @section coding-style-compatibility Compatibility with various OpenGL editions
If any class, function or part of code depends on particular OpenGL edition If any class, function or part of code depends on particular OpenGL edition
(e.g. only for desktop), use conditional compilation to avoid erors on other (e.g. only for desktop), use conditional compilation to avoid erors on other
platforms (see @ref portability-target for more information). Put related platforms (see @ref portability-target for more information). Put related
documentation also into the conditional compilation block and don't forget to documentation also into the conditional compilation block and don't forget to
appropriately mark the class/function (@ref documentation-commands-requires "see below"). appropriately mark the class/function
Example: (@ref coding-style-documentation-commands-requires "see below"). Example:
@code @code
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
// //
@ -94,14 +94,15 @@ void setPolygonMode(PolygonMode mode);
#endif #endif
@endcode @endcode
@section documentation Doxygen documentation @section coding-style-documentation Doxygen documentation
@subsection documentation-commands Special documentation commands @subsection coding-style-documentation-commands Special documentation commands
Additionally to @c \@todoc, @c \@debugoperator @c \@configurationvalue and Additionally to @c \@todoc, @c \@debugoperator, @c \@debugoperatorenum,
@c \@configurationvalueref (same as in Corrade), these are defined: @c \@debugoperatorclassenum, @c \@configurationvalue and
@c \@configurationvalueref (same as in %Corrade), these are defined:
@subsubsection documentation-commands-collisionoperator Shape collision operators @subsubsection coding-style-documentation-commands-collisionoperator Shape collision operators
Out-of-class operators for collision and collision occurence in Shapes Out-of-class operators for collision and collision occurence in Shapes
namespace should be marked with @c \@collisionoperator and @c \@collisionoccurenceoperator, namespace should be marked with @c \@collisionoperator and @c \@collisionoccurenceoperator,
@ -118,7 +119,7 @@ the operator is implemented (not of class in which the operator is
implemented), thus efficiently connecting the two classes together in the implemented), thus efficiently connecting the two classes together in the
documentation. documentation.
@subsubsection documentation-commands-extension Links to OpenGL extensions @subsubsection coding-style-documentation-commands-extension Links to OpenGL extensions
If an OpenGL extension is referenced in the documentation, it should be done If an OpenGL extension is referenced in the documentation, it should be done
with @c \@extension command: with @c \@extension command:
@ -137,7 +138,7 @@ specify extension filename, if the previous command gives 404 error. For example
produces this link: produces this link:
> @es_extension2{NV,read_buffer_front,GL_NV_read_buffer} > @es_extension2{NV,read_buffer_front,GL_NV_read_buffer}
@subsubsection documentation-commands-ref_gl Links to related OpenGL functions and definitions @subsubsection coding-style-documentation-commands-ref_gl Links to related OpenGL functions and definitions
If an function touches OpenGL, related OpenGL functions should be documented If an function touches OpenGL, related OpenGL functions should be documented
in @c \@see block with @c \@fn_gl command. If only specific definition is used in @c \@see block with @c \@fn_gl command. If only specific definition is used
@ -161,7 +162,7 @@ are the same as in @c \@extension command. It produced link to extension
specification, with function name as link text: specification, with function name as link text:
> @fn_gl_extension{NamedCopyBufferSubData,EXT,direct_state_access}. > @fn_gl_extension{NamedCopyBufferSubData,EXT,direct_state_access}.
@subsubsection documentation-commands-requires Classes and functions requiring specific OpenGL version or extensions @subsubsection coding-style-documentation-commands-requires Classes and functions requiring specific OpenGL version or extensions
If any class or function requires specific OpenGL version above 2.1, it should If any class or function requires specific OpenGL version above 2.1, it should
be marked with appropriate command @c \@requires_glXX, where `XX` is version be marked with appropriate command @c \@requires_glXX, where `XX` is version
@ -190,7 +191,19 @@ requirements.
All classes and functions using those commands are cross-referenced in page All classes and functions using those commands are cross-referenced in page
@ref opengl-required-extensions. @ref opengl-required-extensions.
@section unit-tests Unit tests @subsection coding-style-documentation-ordering Section ordering
In detailed documentation the text should be always first, the blocks are then
ordered by their importance. Various @c \@note, @c \@attention and @c \@warning
blocks to highlight some information are always first, then @c \@see block with
links to related stuff, where related %Magnum functions are first and links to
related GL API last, then various support information such as
@c \@requires_glXX, @c \@requires_es_extension etc. (first desktop GL, then ES,
then WebGL), after that @c \@deprecated_gl and @c \@deprecated information and
@c \@todo, @c \@todoc and @c \@bug always last, as they are the least important
and in most cases only for internal use.
@section coding-style-unit-tests Unit tests
All unit tests use Corrade's @ref Corrade::TestSuite "TestSuite". All unit tests use Corrade's @ref Corrade::TestSuite "TestSuite".

5
doc/opengl-mapping.dox

@ -196,8 +196,7 @@ OpenGL function | Matching API
@fn_gl_extension{MapBufferSubData,CHROMIUM,map_sub}, @fn_gl_extension{UnmapBufferSubData,CHROMIUM,map_sub} | @ref Buffer::mapSub(), @ref Buffer::unmapSub() @fn_gl_extension{MapBufferSubData,CHROMIUM,map_sub}, @fn_gl_extension{UnmapBufferSubData,CHROMIUM,map_sub} | @ref Buffer::mapSub(), @ref Buffer::unmapSub()
@fn_gl{MemoryBarrier} | | @fn_gl{MemoryBarrier} | |
@fn_gl{MinSampleShading} | | @fn_gl{MinSampleShading} | |
@fn_gl{MultiDrawArrays}, \n @fn_gl{MultiDrawElements} | | @fn_gl{MultiDrawArrays}, \n @fn_gl{MultiDrawElements}, \n @fn_gl{MultiDrawElementsBaseVertex} | @ref MeshView::draw(AbstractShaderProgram&, std::initializer_list<std::reference_wrapper<MeshView>>)
@fn_gl{MultiDrawElementsBaseVertex} | |
@fn_gl{ObjectLabel}, \n @fn_gl{ObjectPtrLabel}, \n @fn_gl_extension2{LabelObject,EXT,debug_label} | @ref AbstractShaderProgram::setLabel(), \n @ref AbstractQuery::setLabel(), \n @ref AbstractTexture::setLabel(), \n @ref Buffer::setLabel(), \n @ref Framebuffer::setLabel(), \n @ref Mesh::setLabel(), \n @ref Renderbuffer::setLabel(), \n @ref Shader::setLabel() @fn_gl{ObjectLabel}, \n @fn_gl{ObjectPtrLabel}, \n @fn_gl_extension2{LabelObject,EXT,debug_label} | @ref AbstractShaderProgram::setLabel(), \n @ref AbstractQuery::setLabel(), \n @ref AbstractTexture::setLabel(), \n @ref Buffer::setLabel(), \n @ref Framebuffer::setLabel(), \n @ref Mesh::setLabel(), \n @ref Renderbuffer::setLabel(), \n @ref Shader::setLabel()
@fn_gl{PatchParameter} | | @fn_gl{PatchParameter} | |
@fn_gl{PauseTransformFeedback}, @fn_gl{ResumeTransformFeedback} | | @fn_gl{PauseTransformFeedback}, @fn_gl{ResumeTransformFeedback} | |
@ -232,7 +231,7 @@ OpenGL function | Matching API
@fn_gl{TexBuffer}, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} | @ref BufferTexture::setBuffer() @fn_gl{TexBuffer}, \n @fn_gl_extension{TextureBuffer,EXT,direct_state_access}, \n @fn_gl{TexBufferRange}, \n @fn_gl_extension{TextureBufferRange,EXT,direct_state_access} | @ref BufferTexture::setBuffer()
@fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref TextureArray::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage(), \n @ref RectangleTexture::setImage() @fn_gl{TexImage1D}, \n @fn_gl_extension{TextureImage1D,EXT,direct_state_access} \n @fn_gl{TexImage2D}, \n @fn_gl_extension{TextureImage2D,EXT,direct_state_access}, \n @fn_gl{TexImage3D}, \n @fn_gl_extension{TextureImage3D,EXT,direct_state_access} | @ref Texture::setImage(), \n @ref TextureArray::setImage(), \n @ref CubeMapTexture::setImage(), \n @ref CubeMapTextureArray::setImage(), \n @ref RectangleTexture::setImage()
@fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage() @fn_gl{TexImage2DMultisample}, \n @fn_gl{TexImage3DMultisample} | @ref MultisampleTexture::setStorage()
@fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()", \n @ref Texture::setSwizzle() "*Texture::setSwizzle()", \n @ref Texture::setCompareMode() "*Texture::setCompareMode()", \n @ref Texture::setCompareFunction() "*Texture::setCompareFunction()", \n @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()" @fn_gl{TexParameter}, \n @fn_gl_extension{TextureParameter,EXT,direct_state_access} | @ref Texture::setBaseLevel() "*Texture::setBaseLevel()", \n @ref Texture::setMaxLevel() "*Texture::setMaxLevel()", \n @ref Texture::setMinificationFilter() "*Texture::setMinificationFilter()", \n @ref Texture::setMagnificationFilter() "*Texture::setMagnificationFilter()", \n @ref Texture::setMinLod() "*Texture::setMinLod()", \n @ref Texture::setMaxLod() "*Texture::setMaxLod()", \n @ref Texture::setLodBias() "*Texture::setLodBias()", \n @ref Texture::setWrapping() "*Texture::setWrapping()", \n @ref Texture::setBorderColor() "*Texture::setBorderColor()", \n @ref Texture::setMaxAnisotropy() "*Texture::setMaxAnisotropy()", \n @ref Texture::setSRGBDecode() "*Texture::setSRGBDecode()", \n @ref Texture::setSwizzle() "*Texture::setSwizzle()", \n @ref Texture::setCompareMode() "*Texture::setCompareMode()", \n @ref Texture::setCompareFunction() "*Texture::setCompareFunction()", \n @ref Texture::setDepthStencilMode() "*Texture::setDepthStencilMode()"
@fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref TextureArray::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage(), \n @ref RectangleTexture::setStorage() @fn_gl{TexStorage1D}, \n @fn_gl_extension{TextureStorage1D,EXT,direct_state_access}, \n @fn_gl{TexStorage2D}, \n @fn_gl_extension{TextureStorage2D,EXT,direct_state_access}, \n @fn_gl{TexStorage3D}, \n @fn_gl_extension{TextureStorage3D,EXT,direct_state_access} | @ref Texture::setStorage(), \n @ref TextureArray::setStorage(), \n @ref CubeMapTexture::setStorage(), \n @ref CubeMapTextureArray::setStorage(), \n @ref RectangleTexture::setStorage()
@fn_gl{TexStorage2DMultisample}, \n @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}, \n @fn_gl{TexStorage3DMultisample}, \n @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} | @ref MultisampleTexture::setStorage() @fn_gl{TexStorage2DMultisample}, \n @fn_gl_extension{TextureStorage2DMultisample,EXT,direct_state_access}, \n @fn_gl{TexStorage3DMultisample}, \n @fn_gl_extension{TextureStorage3DMultisample,EXT,direct_state_access} | @ref MultisampleTexture::setStorage()
@fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref TextureArray::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage(), \n @ref RectangleTexture::setSubImage() @fn_gl{TexSubImage1D}, \n @fn_gl_extension{TextureSubImage1D,EXT,direct_state_access}, \n @fn_gl{TexSubImage2D}, \n @fn_gl_extension{TextureSubImage2D,EXT,direct_state_access}, \n @fn_gl{TexSubImage3D}, \n @fn_gl_extension{TextureSubImage3D,EXT,direct_state_access} | @ref Texture::setSubImage(), \n @ref TextureArray::setSubImage(), \n @ref CubeMapTexture::setSubImage(), \n @ref CubeMapTextureArray::setSubImage(), \n @ref RectangleTexture::setSubImage()

6
doc/opengl-support.dox

@ -95,7 +95,7 @@ following:
-------------------------------------------- | ------ -------------------------------------------- | ------
@extension{ARB,geometry_shader4} | missing layered attachments @extension{ARB,geometry_shader4} | missing layered attachments
@extension{ARB,depth_clamp} | done @extension{ARB,depth_clamp} | done
@extension{ARB,draw_elements_base_vertex} | missing `Multi*` command @extension{ARB,draw_elements_base_vertex} | done
@extension{ARB,fragment_coord_conventions} | done (shading language only) @extension{ARB,fragment_coord_conventions} | done (shading language only)
@extension{ARB,provoking_vertex} | done @extension{ARB,provoking_vertex} | done
@extension{ARB,seamless_cube_map} | done @extension{ARB,seamless_cube_map} | done
@ -205,7 +205,7 @@ following:
@extension{ARB,query_buffer_object} | | @extension{ARB,query_buffer_object} | |
@extension{ARB,texture_mirror_clamp_to_edge} | done @extension{ARB,texture_mirror_clamp_to_edge} | done
@extension{ARB,texture_stencil8} | done @extension{ARB,texture_stencil8} | done
@extension{ARB,vertex_type_10f_11f_11f_rev} | | @extension{ARB,vertex_type_10f_11f_11f_rev} | done
@subsection opengl-support-extensions OpenGL extensions @subsection opengl-support-extensions OpenGL extensions
@ -222,6 +222,7 @@ following:
@extension{EXT,texture_filter_anisotropic} (also in ES) | done @extension{EXT,texture_filter_anisotropic} (also in ES) | done
@extension{EXT,texture_mirror_clamp} | only GL 4.4 subset @extension{EXT,texture_mirror_clamp} | only GL 4.4 subset
@extension{EXT,direct_state_access} | done for implemented functionality @extension{EXT,direct_state_access} | done for implemented functionality
@extension{EXT,texture_sRGB_decode} (also in ES) | done
@extension{EXT,shader_integer_mix} (also in ES) | done (shading language only) @extension{EXT,shader_integer_mix} (also in ES) | done (shading language only)
@extension2{EXT,debug_label} (also in ES) | missing pipeline, transform feedback and sampler label @extension2{EXT,debug_label} (also in ES) | missing pipeline, transform feedback and sampler label
@extension2{EXT,debug_marker} (also in ES) | missing marker groups @extension2{EXT,debug_marker} (also in ES) | missing marker groups
@ -298,6 +299,7 @@ Only extensions not already listed in above tables are included here.
@es_extension{CHROMIUM,map_sub} | only buffer mapping @es_extension{CHROMIUM,map_sub} | only buffer mapping
@es_extension{EXT,texture_format_BGRA8888} | done @es_extension{EXT,texture_format_BGRA8888} | done
@es_extension{EXT,read_format_bgra} | done @es_extension{EXT,read_format_bgra} | done
@es_extension2{EXT,multi_draw_arrays,multi_draw_arrays} | done
@es_extension{EXT,disjoint_timer_query} | only time elapsed query @es_extension{EXT,disjoint_timer_query} | only time elapsed query
@es_extension{EXT,separate_shader_objects} | only direct uniform binding @es_extension{EXT,separate_shader_objects} | only direct uniform binding
@es_extension{EXT,sRGB} | done @es_extension{EXT,sRGB} | done

16
modules/FindMagnum.cmake

@ -49,6 +49,7 @@
# XEglApplication - X/EGL application # XEglApplication - X/EGL application
# WindowlessGlxApplication - Windowless GLX application # WindowlessGlxApplication - Windowless GLX application
# WindowlessNaClApplication - Windowless NaCl application # WindowlessNaClApplication - Windowless NaCl application
# WindowlessWglApplication - Windowless WGL application
# Example usage with specifying additional components is: # Example usage with specifying additional components is:
# find_package(Magnum [REQUIRED|COMPONENTS] # find_package(Magnum [REQUIRED|COMPONENTS]
# MeshTools Primitives GlutApplication) # MeshTools Primitives GlutApplication)
@ -329,7 +330,7 @@ foreach(component ${Magnum_FIND_COMPONENTS})
if(${component} STREQUAL AndroidApplication) if(${component} STREQUAL AndroidApplication)
find_package(EGL) find_package(EGL)
if(EGL_FOUND) if(EGL_FOUND)
set(_MAGNUM_${_COMPONENT}_LIBRARIES android ${EGL_LIBRARY} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY}) set(_MAGNUM_${_COMPONENT}_LIBRARIES android ${EGL_LIBRARY})
set(_MAGNUM_${_COMPONENT}_INCLUDE_DIRS ${ANDROID_NATIVE_APP_GLUE_INCLUDE_DIR}) set(_MAGNUM_${_COMPONENT}_INCLUDE_DIRS ${ANDROID_NATIVE_APP_GLUE_INCLUDE_DIR})
else() else()
unset(MAGNUM_${_COMPONENT}_LIBRARY) unset(MAGNUM_${_COMPONENT}_LIBRARY)
@ -340,7 +341,7 @@ foreach(component ${Magnum_FIND_COMPONENTS})
if(${component} STREQUAL GlutApplication) if(${component} STREQUAL GlutApplication)
find_package(GLUT) find_package(GLUT)
if(GLUT_FOUND) if(GLUT_FOUND)
set(_MAGNUM_${_COMPONENT}_LIBRARIES ${GLUT_glut_LIBRARY} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY}) set(_MAGNUM_${_COMPONENT}_LIBRARIES ${GLUT_glut_LIBRARY})
else() else()
unset(MAGNUM_${_COMPONENT}_LIBRARY) unset(MAGNUM_${_COMPONENT}_LIBRARY)
endif() endif()
@ -350,7 +351,7 @@ foreach(component ${Magnum_FIND_COMPONENTS})
if(${component} STREQUAL Sdl2Application) if(${component} STREQUAL Sdl2Application)
find_package(SDL2) find_package(SDL2)
if(SDL2_FOUND) if(SDL2_FOUND)
set(_MAGNUM_${_COMPONENT}_LIBRARIES ${SDL2_LIBRARY} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY}) set(_MAGNUM_${_COMPONENT}_LIBRARIES ${SDL2_LIBRARY})
set(_MAGNUM_${_COMPONENT}_INCLUDE_DIRS ${SDL2_INCLUDE_DIR}) set(_MAGNUM_${_COMPONENT}_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})
else() else()
unset(MAGNUM_${_COMPONENT}_LIBRARY) unset(MAGNUM_${_COMPONENT}_LIBRARY)
@ -359,14 +360,14 @@ foreach(component ${Magnum_FIND_COMPONENTS})
# (Windowless) NaCl application dependencies # (Windowless) NaCl application dependencies
if(${component} STREQUAL NaClApplication OR ${component} STREQUAL WindowlessNaClApplication) if(${component} STREQUAL NaClApplication OR ${component} STREQUAL WindowlessNaClApplication)
set(_MAGNUM_${_COMPONENT}_LIBRARIES ppapi_cpp ppapi ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY}) set(_MAGNUM_${_COMPONENT}_LIBRARIES ppapi_cpp ppapi)
endif() endif()
# GLX application dependencies # GLX application dependencies
if(${component} STREQUAL GlxApplication OR ${component} STREQUAL WindowlessGlxApplication) if(${component} STREQUAL GlxApplication OR ${component} STREQUAL WindowlessGlxApplication)
find_package(X11) find_package(X11)
if(X11_FOUND) if(X11_FOUND)
set(_MAGNUM_${_COMPONENT}_LIBRARIES ${X11_LIBRARIES} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY}) set(_MAGNUM_${_COMPONENT}_LIBRARIES ${X11_LIBRARIES})
else() else()
unset(MAGNUM_${_COMPONENT}_LIBRARY) unset(MAGNUM_${_COMPONENT}_LIBRARY)
endif() endif()
@ -377,12 +378,15 @@ foreach(component ${Magnum_FIND_COMPONENTS})
find_package(EGL) find_package(EGL)
find_package(X11) find_package(X11)
if(EGL_FOUND AND X11_FOUND) if(EGL_FOUND AND X11_FOUND)
set(_MAGNUM_${_COMPONENT}_LIBRARIES ${EGL_LIBRARY} ${X11_LIBRARIES} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY}) set(_MAGNUM_${_COMPONENT}_LIBRARIES ${EGL_LIBRARY} ${X11_LIBRARIES})
else() else()
unset(MAGNUM_${_COMPONENT}_LIBRARY) unset(MAGNUM_${_COMPONENT}_LIBRARY)
endif() endif()
endif() endif()
# Common application dependencies
set(_MAGNUM_${_COMPONENT}_LIBRARIES ${_MAGNUM_${_COMPONENT}_LIBRARIES} ${_WINDOWCONTEXT_MAGNUM_LIBRARIES_DEPENDENCY})
# Audio library # Audio library
elseif(${component} STREQUAL Audio) elseif(${component} STREQUAL Audio)
find_package(OpenAL) find_package(OpenAL)

56
package/archlinux/PKGBUILD-gcc49

@ -1,56 +0,0 @@
# Author: mosra <mosra@centrum.cz>
pkgname=magnum
pkgver=dev.gcc49
pkgrel=1
pkgdesc="C++11 and OpenGL 2D/3D graphics engine (built with GCC 4.9)"
arch=('i686' 'x86_64')
url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('corrade' 'openal' 'freeglut' 'sdl2')
makedepends=('cmake' 'ninja' 'gcc-git')
options=('!strip' 'staticlibs')
provides=('magnum-git')
build() {
if [ ! -d "$startdir/build-gcc49" ] ; then
mkdir "$startdir/build-gcc49"
cd "$startdir/build-gcc49"
cmake .. \
-DCMAKE_CXX_COMPILER=g++-4.9 \
-G Ninja
fi
cd "$startdir/build-gcc49"
cmake .. \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_INSTALL_PREFIX=/usr \
-DWITH_AUDIO=ON \
-DWITH_GLUTAPPLICATION=ON \
-DWITH_GLXAPPLICATION=ON \
-DWITH_SDL2APPLICATION=ON \
-DWITH_WINDOWLESSGLXAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \
-DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \
-DWITH_DISTANCEFIELDCONVERTER=ON \
-DWITH_FONTCONVERTER=ON \
-DWITH_MAGNUMINFO=ON \
-DBUILD_TESTS=ON \
-DBUILD_GL_TESTS=ON
ninja
}
check() {
cd "$startdir/build-gcc49"
ctest --output-on-failure -j5
}
package() {
cd "$startdir/build-gcc49"
DESTDIR="$pkgdir/" ninja install
}

14
package/archlinux/PKGBUILD-mingw-w64

@ -20,13 +20,18 @@ build() {
-DCMAKE_INSTALL_PREFIX=/usr/i686-w64-mingw32 \ -DCMAKE_INSTALL_PREFIX=/usr/i686-w64-mingw32 \
-DWITH_AUDIO=ON \ -DWITH_AUDIO=ON \
-DWITH_GLUTAPPLICATION=ON \ -DWITH_GLUTAPPLICATION=ON \
-DWITH_SDL2APPLICATION=ON \
-DWITH_WINDOWLESSWGLAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \ -DWITH_OBJIMPORTER=ON \
-DWITH_SDL2APPLICATION=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
-DWITH_DISTANCEFIELDCONVERTER=ON \
-DWITH_FONTCONVERTER=ON \
-DWITH_MAGNUMINFO=ON \
-DBUILD_TESTS=ON \
-G Ninja -G Ninja
ninja ninja
@ -39,13 +44,18 @@ build() {
-DCMAKE_INSTALL_PREFIX=/usr/x86_64-w64-mingw32 \ -DCMAKE_INSTALL_PREFIX=/usr/x86_64-w64-mingw32 \
-DWITH_AUDIO=ON \ -DWITH_AUDIO=ON \
-DWITH_GLUTAPPLICATION=ON \ -DWITH_GLUTAPPLICATION=ON \
-DWITH_SDL2APPLICATION=ON \
-DWITH_WINDOWLESSWGLAPPLICATION=ON \
-DWITH_MAGNUMFONT=ON \ -DWITH_MAGNUMFONT=ON \
-DWITH_MAGNUMFONTCONVERTER=ON \ -DWITH_MAGNUMFONTCONVERTER=ON \
-DWITH_OBJIMPORTER=ON \ -DWITH_OBJIMPORTER=ON \
-DWITH_SDL2APPLICATION=ON \
-DWITH_TGAIMAGECONVERTER=ON \ -DWITH_TGAIMAGECONVERTER=ON \
-DWITH_TGAIMPORTER=ON \ -DWITH_TGAIMPORTER=ON \
-DWITH_WAVAUDIOIMPORTER=ON \ -DWITH_WAVAUDIOIMPORTER=ON \
-DWITH_DISTANCEFIELDCONVERTER=ON \
-DWITH_FONTCONVERTER=ON \
-DWITH_MAGNUMINFO=ON \
-DBUILD_TESTS=ON \
-G Ninja -G Ninja
ninja ninja
} }

2
src/Magnum/AbstractFramebuffer.cpp

@ -158,6 +158,8 @@ AbstractFramebuffer& AbstractFramebuffer::setViewport(const Range2Di& rectangle)
void AbstractFramebuffer::setViewportInternal() { void AbstractFramebuffer::setViewportInternal() {
Implementation::FramebufferState* state = Context::current()->state().framebuffer; Implementation::FramebufferState* state = Context::current()->state().framebuffer;
/* We are using empty viewport to indicate disengaged state */
CORRADE_INTERNAL_ASSERT(_viewport != Range2Di{});
CORRADE_INTERNAL_ASSERT(state->drawBinding == _id); CORRADE_INTERNAL_ASSERT(state->drawBinding == _id);
/* Already up-to-date, nothing to do */ /* Already up-to-date, nothing to do */

17
src/Magnum/AbstractImage.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::AbstractImage * @brief Class @ref Magnum::AbstractImage
*/ */
#include <cstddef> #include <cstddef>
@ -43,12 +43,12 @@ namespace Magnum {
/** /**
@brief Non-templated base for one-, two- or three-dimensional images @brief Non-templated base for one-, two- or three-dimensional images
See Image, ImageReference, BufferImage, Trade::ImageData documentation for See @ref Image, @ref ImageReference, @ref BufferImage, @ref Trade::ImageData
more information. documentation for more information.
@todo Where to put glClampColor() and glPixelStore() encapsulation? It is @todo Where to put glClampColor() and glPixelStore() encapsulation? It is
needed in AbstractFramebuffer::read(), Texture::setImage() etc (i.e. all needed in AbstractFramebuffer::read(), Texture::setImage() etc (i.e. all
functions operating with images). It also possibly needs to be "stackable" to functions operating with images). It also possibly needs to be "stackable"
easily revert the state back. to easily revert the state back.
*/ */
class MAGNUM_EXPORT AbstractImage { class MAGNUM_EXPORT AbstractImage {
public: public:
@ -57,7 +57,7 @@ class MAGNUM_EXPORT AbstractImage {
* @param format Format of the pixel * @param format Format of the pixel
* @param type Data type of the pixel * @param type Data type of the pixel
* *
* @see pixelSize() const * @see @ref pixelSize()
*/ */
static std::size_t pixelSize(ColorFormat format, ColorType type); static std::size_t pixelSize(ColorFormat format, ColorType type);
@ -70,7 +70,8 @@ class MAGNUM_EXPORT AbstractImage {
/** /**
* @brief Pixel size (in bytes) * @brief Pixel size (in bytes)
* *
* Convenience member alternative for pixelSize(Format, Type). * Convenience member alternative for
* @ref pixelSize(ColorFormat, ColorType).
*/ */
std::size_t pixelSize() const { return pixelSize(_format, _type); } std::size_t pixelSize() const { return pixelSize(_format, _type); }

2
src/Magnum/AbstractResourceLoader.h

@ -60,7 +60,7 @@ In your @ref doLoad() implementation, after your resources are loaded, call
@ref set() to pass them to @ref ResourceManager or call @ref setNotFound() to @ref set() to pass them to @ref ResourceManager or call @ref setNotFound() to
indicate that the resource was not found. indicate that the resource was not found.
You can also implement @ref name() to provide meaningful names for resource You can also implement @ref doName() to provide meaningful names for resource
keys. keys.
Example implementation for synchronous mesh loader: Example implementation for synchronous mesh loader:

50
src/Magnum/AbstractShaderProgram.cpp

@ -198,7 +198,9 @@ Int AbstractShaderProgram::maxTexelOffset() {
} }
#endif #endif
AbstractShaderProgram::AbstractShaderProgram(): _id(glCreateProgram()) {} AbstractShaderProgram::AbstractShaderProgram(): _id(glCreateProgram()) {
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
}
AbstractShaderProgram::AbstractShaderProgram(AbstractShaderProgram&& other) noexcept: _id(other._id) { AbstractShaderProgram::AbstractShaderProgram(AbstractShaderProgram&& other) noexcept: _id(other._id) {
other._id = 0; other._id = 0;
@ -1229,6 +1231,31 @@ UnsignedInt DoubleAttribute::size(GLint components, DataType dataType) {
} }
#endif #endif
UnsignedInt Attribute<Math::Vector<3, Float>>::size(GLint components, DataType dataType) {
switch(dataType) {
case DataType::UnsignedByte:
case DataType::Byte:
return components;
case DataType::UnsignedShort:
case DataType::Short:
case DataType::HalfFloat:
return 2*components;
case DataType::UnsignedInt:
case DataType::Int:
case DataType::Float:
return 4*components;
#ifndef MAGNUM_TARGET_GLES
case DataType::Double:
return 8*components;
case DataType::UnsignedInt10f11f11fRev:
CORRADE_INTERNAL_ASSERT(components == 3);
return 4;
#endif
}
CORRADE_ASSERT_UNREACHABLE();
}
UnsignedInt Attribute<Math::Vector<4, Float>>::size(GLint components, DataType dataType) { UnsignedInt Attribute<Math::Vector<4, Float>>::size(GLint components, DataType dataType) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
if(components == GL_BGRA) components = 4; if(components == GL_BGRA) components = 4;
@ -1405,6 +1432,27 @@ Debug operator<<(Debug debug, DoubleAttribute::DataType value) {
} }
#endif #endif
Debug operator<<(Debug debug, Attribute<Math::Vector<3, Float>>::DataType value) {
switch(value) {
#define _c(value) case Attribute<Math::Vector<3, Float>>::DataType::value: return debug << "AbstractShaderProgram::Attribute::DataType::" #value;
_c(UnsignedByte)
_c(Byte)
_c(UnsignedShort)
_c(Short)
_c(UnsignedInt)
_c(Int)
_c(HalfFloat)
_c(Float)
#ifndef MAGNUM_TARGET_GLES
_c(Double)
_c(UnsignedInt10f11f11fRev)
#endif
#undef _c
}
return debug << "AbstractShaderProgram::Attribute::DataType::(invalid)";
}
Debug operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::DataType value) { Debug operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::DataType value) {
switch(value) { switch(value) {
#define _c(value) case Attribute<Math::Vector<4, Float>>::DataType::value: return debug << "AbstractShaderProgram::Attribute::DataType::" #value; #define _c(value) case Attribute<Math::Vector<4, Float>>::DataType::value: return debug << "AbstractShaderProgram::Attribute::DataType::" #value;

99
src/Magnum/AbstractShaderProgram.h

@ -350,8 +350,8 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_atomic_counters} is * OpenGL calls. If extension @extension{ARB,shader_atomic_counters} is
* not available, returns `0`. * not available, returns `0`.
* @requires_gl Atomic counters are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_ATOMIC_COUNTER_BUFFER_SIZE} * @see @fn_gl{Get} with @def_gl{MAX_ATOMIC_COUNTER_BUFFER_SIZE}
* @requires_gl Atomic counters are not available in OpenGL ES.
*/ */
static Int maxAtomicCounterBufferSize(); static Int maxAtomicCounterBufferSize();
@ -361,8 +361,8 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,compute_shader} is not * OpenGL calls. If extension @extension{ARB,compute_shader} is not
* available, returns `0`. * available, returns `0`.
* @requires_gl Compute shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_COMPUTE_SHARED_MEMORY_SIZE} * @see @fn_gl{Get} with @def_gl{MAX_COMPUTE_SHARED_MEMORY_SIZE}
* @requires_gl Compute shaders are not available in OpenGL ES.
*/ */
static Int maxComputeSharedMemorySize(); static Int maxComputeSharedMemorySize();
@ -372,8 +372,8 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,compute_shader} is not * OpenGL calls. If extension @extension{ARB,compute_shader} is not
* available, returns `0`. * available, returns `0`.
* @requires_gl Compute shaders are not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_COMPUTE_WORK_GROUP_INVOCATIONS} * @see @fn_gl{Get} with @def_gl{MAX_COMPUTE_WORK_GROUP_INVOCATIONS}
* @requires_gl Compute shaders are not available in OpenGL ES.
*/ */
static Int maxComputeWorkGroupInvocations(); static Int maxComputeWorkGroupInvocations();
@ -385,8 +385,8 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_image_load_store} * OpenGL calls. If extension @extension{ARB,shader_image_load_store}
* is not available, returns `0`. * is not available, returns `0`.
* @requires_gl Image load/store is not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_IMAGE_UNITS} * @see @fn_gl{Get} with @def_gl{MAX_IMAGE_UNITS}
* @requires_gl %Image load/store is not available in OpenGL ES.
*/ */
static Int maxImageUnits(); static Int maxImageUnits();
@ -396,8 +396,8 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_image_load_store} * OpenGL calls. If extension @extension{ARB,shader_image_load_store}
* is not available, returns `0`. * is not available, returns `0`.
* @requires_gl Image load/store is not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_IMAGE_SAMPLES} * @see @fn_gl{Get} with @def_gl{MAX_IMAGE_SAMPLES}
* @requires_gl %Image load/store is not available in OpenGL ES.
*/ */
static Int maxImageSamples(); static Int maxImageSamples();
@ -408,8 +408,8 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* OpenGL calls. If neither @extension{ARB,shader_image_load_store} * OpenGL calls. If neither @extension{ARB,shader_image_load_store}
* nor @extension{ARB,shader_storage_buffer_object} extension is * nor @extension{ARB,shader_storage_buffer_object} extension is
* available, returns `0`. * available, returns `0`.
* @requires_gl Image load/store is not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_COMBINED_SHADER_OUTPUT_RESOURCES} * @see @fn_gl{Get} with @def_gl{MAX_COMBINED_SHADER_OUTPUT_RESOURCES}
* @requires_gl %Image load/store is not available in OpenGL ES.
*/ */
static Int maxCombinedShaderOutputResources(); static Int maxCombinedShaderOutputResources();
@ -419,8 +419,8 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,shader_storage_buffer_object} * OpenGL calls. If extension @extension{ARB,shader_storage_buffer_object}
* is not available, returns `0`. * is not available, returns `0`.
* @requires_gl Shader storage is not available in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_SHADER_STORAGE_BLOCK_SIZE} * @see @fn_gl{Get} with @def_gl{MAX_SHADER_STORAGE_BLOCK_SIZE}
* @requires_gl %Shader storage is not available in OpenGL ES.
*/ */
static Long maxShaderStorageBlockSize(); static Long maxShaderStorageBlockSize();
#endif #endif
@ -432,8 +432,8 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_object} * OpenGL calls. If extension @extension{ARB,uniform_buffer_object}
* is not available, returns `0`. * is not available, returns `0`.
* @requires_gles30 Uniform blocks are not available in OpenGL ES 2.0.
* @see @fn_gl{Get} with @def_gl{MAX_UNIFORM_BLOCK_SIZE} * @see @fn_gl{Get} with @def_gl{MAX_UNIFORM_BLOCK_SIZE}
* @requires_gles30 Uniform blocks are not available in OpenGL ES 2.0.
*/ */
static Int maxUniformBlockSize(); static Int maxUniformBlockSize();
#endif #endif
@ -445,8 +445,8 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,explicit_uniform_location} * OpenGL calls. If extension @extension{ARB,explicit_uniform_location}
* is not available, returns `0`. * is not available, returns `0`.
* @requires_gl Explicit uniform location is not supported in OpenGL ES.
* @see @fn_gl{Get} with @def_gl{MAX_UNIFORM_LOCATIONS} * @see @fn_gl{Get} with @def_gl{MAX_UNIFORM_LOCATIONS}
* @requires_gl Explicit uniform location is not supported in OpenGL ES.
*/ */
static Int maxUniformLocations(); static Int maxUniformLocations();
#endif #endif
@ -458,9 +458,9 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{EXT,gpu_shader4} is not * OpenGL calls. If extension @extension{EXT,gpu_shader4} is not
* available, returns `0`. * available, returns `0`.
* @requires_gles30 Texture lookup with offset is not available in
* OpenGL ES 2.0.
* @see @fn_gl{Get} with @def_gl{MIN_PROGRAM_TEXEL_OFFSET} * @see @fn_gl{Get} with @def_gl{MIN_PROGRAM_TEXEL_OFFSET}
* @requires_gles30 %Texture lookup with offset is not available in
* OpenGL ES 2.0.
*/ */
static Int minTexelOffset(); static Int minTexelOffset();
@ -470,9 +470,9 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* The result is cached, repeated queries don't result in repeated * The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{EXT,gpu_shader4} is not * OpenGL calls. If extension @extension{EXT,gpu_shader4} is not
* available, returns `0`. * available, returns `0`.
* @requires_gles30 Texture lookup with offset is not available in
* OpenGL ES 2.0.
* @see @fn_gl{Get} with @def_gl{MAX_PROGRAM_TEXEL_OFFSET} * @see @fn_gl{Get} with @def_gl{MAX_PROGRAM_TEXEL_OFFSET}
* @requires_gles30 %Texture lookup with offset is not available in
* OpenGL ES 2.0.
*/ */
static Int maxTexelOffset(); static Int maxTexelOffset();
#endif #endif
@ -609,15 +609,15 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
/** /**
* @brief Bind attribute to given location * @brief Bind attribute to given location
* @param location Location * @param location Location
* @param name Attribute name * @param name %Attribute name
* *
* Binds attribute to location which is used later for binding vertex * Binds attribute to location which is used later for binding vertex
* buffers. * buffers.
* @see @fn_gl{BindAttribLocation}
* @deprecated_gl Preferred usage is to specify attribute location * @deprecated_gl Preferred usage is to specify attribute location
* explicitly in the shader instead of using this function. See * explicitly in the shader instead of using this function. See
* @ref AbstractShaderProgram-attribute-location "class documentation" * @ref AbstractShaderProgram-attribute-location "class documentation"
* for more information. * for more information.
* @see @fn_gl{BindAttribLocation}
*/ */
void bindAttributeLocation(UnsignedInt location, const std::string& name); void bindAttributeLocation(UnsignedInt location, const std::string& name);
@ -631,11 +631,11 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* Binds fragment data to location which is used later for framebuffer * Binds fragment data to location which is used later for framebuffer
* operations. See also @ref Renderer::BlendFunction for more * operations. See also @ref Renderer::BlendFunction for more
* information about using color input index. * information about using color input index.
* @see @fn_gl{BindFragDataLocationIndexed}
* @deprecated_gl Preferred usage is to specify attribute location * @deprecated_gl Preferred usage is to specify attribute location
* explicitly in the shader instead of using this function. See * explicitly in the shader instead of using this function. See
* @ref AbstractShaderProgram-attribute-location "class documentation" * @ref AbstractShaderProgram-attribute-location "class documentation"
* for more information. * for more information.
* @see @fn_gl{BindFragDataLocationIndexed}
* @requires_gl33 %Extension @extension{ARB,blend_func_extended} * @requires_gl33 %Extension @extension{ARB,blend_func_extended}
* @requires_gl Multiple blend function inputs are not available in * @requires_gl Multiple blend function inputs are not available in
* OpenGL ES. * OpenGL ES.
@ -675,11 +675,11 @@ class MAGNUM_EXPORT AbstractShaderProgram: public AbstractObject {
* @brief Get uniform location * @brief Get uniform location
* @param name Uniform name * @param name Uniform name
* *
* @see @fn_gl{GetUniformLocation}
* @deprecated_gl Preferred usage is to specify uniform location * @deprecated_gl Preferred usage is to specify uniform location
* explicitly in the shader instead of using this function. See * explicitly in the shader instead of using this function. See
* @ref AbstractShaderProgram-uniform-location "class documentation" * @ref AbstractShaderProgram-uniform-location "class documentation"
* for more information. * for more information.
* @see @fn_gl{GetUniformLocation}
*/ */
Int uniformLocation(const std::string& name); Int uniformLocation(const std::string& name);
@ -1066,6 +1066,15 @@ template<UnsignedInt location, class T> class AbstractShaderProgram::Attribute {
* @requires_gl Only floats are available in OpenGL ES. * @requires_gl Only floats are available in OpenGL ES.
*/ */
Double = GL_DOUBLE, Double = GL_DOUBLE,
/**
* Unsigned 10.11.11 packed float. Only for three-component float
* vector attribute type.
* @requires_gl44 %Extension @extension{ARB,vertex_type_10f_11f_11f_rev}
* @requires_gl Packed float attributes are not available in OpenGL
* ES.
*/
UnsignedInt10f11f11fRev = GL_UNSIGNED_INT_10F_11F_11F_REV,
#endif #endif
/* GL_FIXED not supported */ /* GL_FIXED not supported */
@ -1166,10 +1175,10 @@ template<UnsignedInt location, class T> class AbstractShaderProgram::Attribute {
}; };
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
/** @debugoperator{Magnum::AbstractShaderProgram::Attribute} */ /** @debugoperatorclassenum{Magnum::AbstractShaderProgram::Attribute,Magnum::AbstractShaderProgram::Attribute::Components} */
template<class T> Debug operator<<(Debug debug, AbstractShaderProgram::Attribute<T>::Components); template<class T> Debug operator<<(Debug debug, AbstractShaderProgram::Attribute<T>::Components);
/** @debugoperator{Magnum::AbstractShaderProgram::Attribute} */ /** @debugoperatorclassenum{Magnum::AbstractShaderProgram::Attribute,Magnum::AbstractShaderProgram::Attribute::DataType} */
template<class T> Debug operator<<(Debug debug, AbstractShaderProgram::Attribute<T>::DataType); template<class T> Debug operator<<(Debug debug, AbstractShaderProgram::Attribute<T>::DataType);
#endif #endif
@ -1338,6 +1347,8 @@ struct IntAttribute {
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType); static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
}; };
CORRADE_ENUMSET_OPERATORS(IntAttribute::DataOptions)
Debug MAGNUM_EXPORT operator<<(Debug debug, IntAttribute::DataType value); Debug MAGNUM_EXPORT operator<<(Debug debug, IntAttribute::DataType value);
/* Base for unsigned int attributes */ /* Base for unsigned int attributes */
@ -1353,7 +1364,7 @@ struct UnsignedIntAttribute {
DataType DefaultDataType = DataType::UnsignedInt; DataType DefaultDataType = DataType::UnsignedInt;
typedef IntAttribute::DataOption DataOption; typedef IntAttribute::DataOption DataOption;
typedef Containers::EnumSet<DataOption, UnsignedByte> DataOptions; typedef IntAttribute::DataOptions DataOptions;
static UnsignedInt size(GLint components, DataType dataType) { static UnsignedInt size(GLint components, DataType dataType) {
return IntAttribute::size(components, dataType); return IntAttribute::size(components, dataType);
@ -1376,8 +1387,8 @@ struct DoubleAttribute {
#endif #endif
DataType DefaultDataType = DataType::Double; DataType DefaultDataType = DataType::Double;
enum class DataOption: UnsignedByte {}; typedef IntAttribute::DataOption DataOption;
typedef Containers::EnumSet<DataOption, UnsignedByte> DataOptions; typedef IntAttribute::DataOptions DataOptions;
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType); static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
}; };
@ -1385,6 +1396,41 @@ struct DoubleAttribute {
Debug MAGNUM_EXPORT operator<<(Debug debug, DoubleAttribute::DataType value); Debug MAGNUM_EXPORT operator<<(Debug debug, DoubleAttribute::DataType value);
#endif #endif
/* Floating-point three-component vector has additional data type compared to
classic floats */
template<> struct Attribute<Math::Vector<3, Float>>: SizedAttribute<1, 3> {
typedef Float ScalarType;
enum class DataType: GLenum {
UnsignedByte = GL_UNSIGNED_BYTE,
Byte = GL_BYTE,
UnsignedShort = GL_UNSIGNED_SHORT,
Short = GL_SHORT,
UnsignedInt = GL_UNSIGNED_INT,
Int = GL_INT,
#ifndef MAGNUM_TARGET_GLES2
HalfFloat = GL_HALF_FLOAT,
#else
HalfFloat = GL_HALF_FLOAT_OES,
#endif
Float = GL_FLOAT
#ifndef MAGNUM_TARGET_GLES
,
Double = GL_DOUBLE,
UnsignedInt10f11f11fRev = GL_UNSIGNED_INT_10F_11F_11F_REV
#endif
};
constexpr static DataType DefaultDataType = DataType::Float;
typedef FloatAttribute::DataOption DataOption;
typedef FloatAttribute::DataOptions DataOptions;
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
};
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<3, Float>>::DataType value);
/* Floating-point four-component vector is absolutely special case */ /* Floating-point four-component vector is absolutely special case */
template<> struct Attribute<Math::Vector<4, Float>> { template<> struct Attribute<Math::Vector<4, Float>> {
typedef Float ScalarType; typedef Float ScalarType;
@ -1436,19 +1482,14 @@ template<> struct Attribute<Math::Vector<4, Float>> {
#endif #endif
DataType DefaultDataType = DataType::Float; DataType DefaultDataType = DataType::Float;
enum class DataOption: UnsignedByte { typedef FloatAttribute::DataOption DataOption;
Normalized = 1 << 0 typedef FloatAttribute::DataOptions DataOptions;
};
typedef Containers::EnumSet<DataOption, UnsignedByte> DataOptions;
enum: UnsignedInt { VectorCount = 1 }; enum: UnsignedInt { VectorCount = 1 };
static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType); static UnsignedInt MAGNUM_EXPORT size(GLint components, DataType dataType);
}; };
typedef Math::Vector<4, Float> _Vector4;
CORRADE_ENUMSET_OPERATORS(Attribute<_Vector4>::DataOptions)
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::Components value); Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::Components value);
Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::DataType value); Debug MAGNUM_EXPORT operator<<(Debug debug, Attribute<Math::Vector<4, Float>>::DataType value);

10
src/Magnum/AbstractTexture.cpp

@ -171,6 +171,7 @@ void AbstractTexture::bindImplementationMulti(const GLint firstTextureUnit, std:
AbstractTexture::AbstractTexture(GLenum target): _target(target) { AbstractTexture::AbstractTexture(GLenum target): _target(target) {
glGenTextures(1, &_id); glGenTextures(1, &_id);
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
} }
AbstractTexture::~AbstractTexture() { AbstractTexture::~AbstractTexture() {
@ -287,6 +288,11 @@ void AbstractTexture::setMaxAnisotropy(const Float anisotropy) {
(this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy); (this->*Context::current()->state().texture->setMaxAnisotropyImplementation)(anisotropy);
} }
void AbstractTexture::setSRGBDecode(bool decode) {
(this->*Context::current()->state().texture->parameteriImplementation)(GL_TEXTURE_SRGB_DECODE_EXT,
decode ? GL_DECODE_EXT : GL_SKIP_DECODE_EXT);
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void AbstractTexture::setSwizzleInternal(const GLint r, const GLint g, const GLint b, const GLint a) { void AbstractTexture::setSwizzleInternal(const GLint r, const GLint g, const GLint b, const GLint a) {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -386,7 +392,7 @@ ColorFormat AbstractTexture::imageFormatForInternalFormat(const TextureFormat in
#endif #endif
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
case TextureFormat::CompressedRed: case TextureFormat::CompressedRed:
case TextureFormat::CompressedRedRtgc1: case TextureFormat::CompressedRedRgtc1:
case TextureFormat::CompressedSignedRedRgtc1: case TextureFormat::CompressedSignedRedRgtc1:
#endif #endif
return ColorFormat::Red; return ColorFormat::Red;
@ -589,7 +595,7 @@ ColorType AbstractTexture::imageTypeForInternalFormat(const TextureFormat intern
case TextureFormat::CompressedRG: case TextureFormat::CompressedRG:
case TextureFormat::CompressedRGB: case TextureFormat::CompressedRGB:
case TextureFormat::CompressedRGBA: case TextureFormat::CompressedRGBA:
case TextureFormat::CompressedRedRtgc1: case TextureFormat::CompressedRedRgtc1:
case TextureFormat::CompressedRGRgtc2: case TextureFormat::CompressedRGRgtc2:
case TextureFormat::CompressedRGBABptcUnorm: case TextureFormat::CompressedRGBABptcUnorm:
case TextureFormat::CompressedSRGBAlphaBptcUnorm: case TextureFormat::CompressedSRGBAlphaBptcUnorm:

1
src/Magnum/AbstractTexture.h

@ -315,6 +315,7 @@ class MAGNUM_EXPORT AbstractTexture: public AbstractObject {
void setBorderColor(const Vector4ui& color); void setBorderColor(const Vector4ui& color);
#endif #endif
void setMaxAnisotropy(Float anisotropy); void setMaxAnisotropy(Float anisotropy);
void setSRGBDecode(bool decode);
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
template<char r, char g, char b, char a> void setSwizzle() { template<char r, char g, char b, char a> void setSwizzle() {

10
src/Magnum/Array.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Array, Magnum::Array1D, Magnum::Array2D, Magnum::Array3D * @brief Class @ref Magnum::Array, @ref Magnum::Array1D, @ref Magnum::Array2D, @ref Magnum::Array3D
*/ */
#include <type_traits> #include <type_traits>
@ -45,10 +45,10 @@ namespace Magnum {
@tparam dimensions Dimension count @tparam dimensions Dimension count
@tparam T Data type @tparam T Data type
Similar to Math::Vector, but more suitable for storing enum values which don't Similar to @ref Math::Vector, but more suitable for storing enum values which
need any math operations and fuzzy comparison (e.g. enum values). Unlike don't need any math operations and fuzzy comparison (e.g. enum values). Unlike
Math::Vector this class has non-explicit constructor from one value. @ref Math::Vector this class has implicit constructor from one value.
@see Array1D, Array2D, Array3D @see @ref Array1D, @ref Array2D, @ref Array3D
*/ */
template<UnsignedInt dimensions, class T> class Array { template<UnsignedInt dimensions, class T> class Array {
public: public:

43
src/Magnum/Audio/AbstractImporter.h

@ -25,8 +25,8 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
/** @file Audio/AbstractImporter.h /** @file
* @brief Class Magnum::Audio::AbstractImporter * @brief Class @ref Magnum::Audio::AbstractImporter
*/ */
#include <Corrade/PluginManager/AbstractPlugin.h> #include <Corrade/PluginManager/AbstractPlugin.h>
@ -45,16 +45,17 @@ importer plugins.
@section Audio-AbstractImporter-subclassing Subclassing @section Audio-AbstractImporter-subclassing Subclassing
Plugin implements function doFeatures(), doIsOpened(), one of or both Plugin implements function @ref doFeatures(), @ref doIsOpened(), one of or both
doOpenData() and doOpenFile() functions, function doClose() and data access @ref doOpenData() and @ref doOpenFile() functions, function @ref doClose() and
functions doFormat(), doFrequency() and doData(). data access functions @ref doFormat(), @ref doFrequency() and @ref doData().
You don't need to do most of the redundant sanity checks, these things are You don't need to do most of the redundant sanity checks, these things are
checked by the implementation: checked by the implementation:
- Functions doOpenData() and doOpenFile() are called after the previous file - Functions @ref doOpenData() and @ref doOpenFile() are called after the
was closed, function doClose() is called only if there is any file opened. previous file was closed, function @ref doClose() is called only if there
- Function doOpenData() is called only if @ref Feature::OpenData is is any file opened.
- Function @ref doOpenData() is called only if @ref Feature::OpenData is
supported. supported.
- All `do*()` implementations working on opened file are called only if - All `do*()` implementations working on opened file are called only if
there is any file opened. there is any file opened.
@ -66,17 +67,17 @@ class MAGNUM_AUDIO_EXPORT AbstractImporter: public PluginManager::AbstractPlugin
/** /**
* @brief Features supported by this importer * @brief Features supported by this importer
* *
* @see Features, features() * @see @ref Features, @ref features()
*/ */
enum class Feature: UnsignedByte { enum class Feature: UnsignedByte {
/** Opening files from raw data using openData() */ /** Opening files from raw data using @ref openData() */
OpenData = 1 << 0 OpenData = 1 << 0
}; };
/** /**
* @brief Features supported by this importer * @brief Features supported by this importer
* *
* @see features() * @see @ref features()
*/ */
typedef Containers::EnumSet<Feature, UnsignedByte> Features; typedef Containers::EnumSet<Feature, UnsignedByte> Features;
@ -98,7 +99,7 @@ class MAGNUM_AUDIO_EXPORT AbstractImporter: public PluginManager::AbstractPlugin
* Closes previous file, if it was opened, and tries to open given * Closes previous file, if it was opened, and tries to open given
* file. Available only if @ref Feature::OpenData is supported. Returns * file. Available only if @ref Feature::OpenData is supported. Returns
* `true` on success, `false` otherwise. * `true` on success, `false` otherwise.
* @see features(), openFile() * @see @ref features(), @ref openFile()
*/ */
bool openData(Containers::ArrayReference<const unsigned char> data); bool openData(Containers::ArrayReference<const unsigned char> data);
@ -107,7 +108,7 @@ class MAGNUM_AUDIO_EXPORT AbstractImporter: public PluginManager::AbstractPlugin
* *
* Closes previous file, if it was opened, and tries to open given * Closes previous file, if it was opened, and tries to open given
* file. Returns `true` on success, `false` otherwise. * file. Returns `true` on success, `false` otherwise.
* @see features(), openData() * @see @ref features(), @ref openData()
*/ */
bool openFile(const std::string& filename); bool openFile(const std::string& filename);
@ -132,33 +133,33 @@ class MAGNUM_AUDIO_EXPORT AbstractImporter: public PluginManager::AbstractPlugin
#else #else
protected: protected:
#endif #endif
/** @brief Implementation for features() */ /** @brief Implementation for @ref features() */
virtual Features doFeatures() const = 0; virtual Features doFeatures() const = 0;
/** @brief Implementation for isOpened() */ /** @brief Implementation for @ref isOpened() */
virtual bool doIsOpened() const = 0; virtual bool doIsOpened() const = 0;
/** @brief Implementation for openData() */ /** @brief Implementation for @ref openData() */
virtual void doOpenData(Containers::ArrayReference<const unsigned char> data); virtual void doOpenData(Containers::ArrayReference<const unsigned char> data);
/** /**
* @brief Implementation for openFile() * @brief Implementation for @ref openFile()
* *
* If @ref Feature::OpenData is supported, default implementation opens * If @ref Feature::OpenData is supported, default implementation opens
* the file and calls @ref doOpenData() with its contents. * the file and calls @ref doOpenData() with its contents.
*/ */
virtual void doOpenFile(const std::string& filename); virtual void doOpenFile(const std::string& filename);
/** @brief Implementation for close() */ /** @brief Implementation for @ref close() */
virtual void doClose() = 0; virtual void doClose() = 0;
/** @brief Implementation for format() */ /** @brief Implementation for @ref format() */
virtual Buffer::Format doFormat() const = 0; virtual Buffer::Format doFormat() const = 0;
/** @brief Implementation for frequency() */ /** @brief Implementation for @ref frequency() */
virtual UnsignedInt doFrequency() const = 0; virtual UnsignedInt doFrequency() const = 0;
/** @brief Implementation for data() */ /** @brief Implementation for @ref data() */
virtual Containers::Array<unsigned char> doData() = 0; virtual Containers::Array<unsigned char> doData() = 0;
}; };

2
src/Magnum/Audio/Audio.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Forward declarations for Magnum::Audio namespace * @brief Forward declarations for @ref Magnum::Audio namespace
*/ */
namespace Magnum { namespace Audio { namespace Magnum { namespace Audio {

4
src/Magnum/Audio/Buffer.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Audio::Buffer * @brief Class @ref Magnum::Audio::Buffer
*/ */
#include <utility> #include <utility>
@ -104,7 +104,7 @@ class Buffer {
ALuint _id; ALuint _id;
}; };
/** @debugoperator{Magnum::Audio::Buffer} */ /** @debugoperatorclassenum{Magnum::Audio::Buffer,Magnum::Audio::Buffer::Format} */
Debug MAGNUM_AUDIO_EXPORT operator<<(Debug debug, Buffer::Format value); Debug MAGNUM_AUDIO_EXPORT operator<<(Debug debug, Buffer::Format value);
inline Buffer::Buffer(Buffer&& other): _id(other._id) { inline Buffer::Buffer(Buffer&& other): _id(other._id) {

8
src/Magnum/Audio/Context.h

@ -25,8 +25,8 @@
DEALINGS IN THE SOFTWARE. DEALINGS IN THE SOFTWARE.
*/ */
/** @file Audio/Context.h /** @file
* @brief Class Magnum::Audio::Context * @brief Class @ref Magnum::Audio::Context
*/ */
#include <string> #include <string>
@ -66,14 +66,14 @@ class MAGNUM_AUDIO_EXPORT Context {
/** /**
* @brief Vendor string * @brief Vendor string
* *
* @see rendererString(), @fn_al{GetString} with @def_al{VENDOR} * @see @ref rendererString(), @fn_al{GetString} with @def_al{VENDOR}
*/ */
std::string vendorString() const { return alGetString(AL_VENDOR); } std::string vendorString() const { return alGetString(AL_VENDOR); }
/** /**
* @brief %Renderer string * @brief %Renderer string
* *
* @see vendorString(), @fn_al{GetString} with @def_al{RENDERER} * @see @ref vendorString(), @fn_al{GetString} with @def_al{RENDERER}
*/ */
std::string rendererString() const { return alGetString(AL_RENDERER); } std::string rendererString() const { return alGetString(AL_RENDERER); }

8
src/Magnum/Audio/Renderer.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Audio::Renderer * @brief Class @ref Magnum::Audio::Renderer
*/ */
#include <al.h> #include <al.h>
@ -45,7 +45,7 @@ class Renderer {
/** /**
* @brief Error status * @brief Error status
* *
* @see error() * @see @ref error()
*/ */
enum class Error: ALenum { enum class Error: ALenum {
NoError = AL_NO_ERROR, /**< No error occured */ NoError = AL_NO_ERROR, /**< No error occured */
@ -116,7 +116,7 @@ class Renderer {
/** /**
* @brief Distance model * @brief Distance model
* *
* @see setDistanceModel() * @see @ref setDistanceModel()
*/ */
enum class DistanceModel: ALenum { enum class DistanceModel: ALenum {
/** No distance attenuation calculation */ /** No distance attenuation calculation */
@ -185,7 +185,7 @@ class Renderer {
/*@}*/ /*@}*/
}; };
/** @debugoperator{Magnum::Audio::Renderer} */ /** @debugoperatorclassenum{Magnum::Audio::Renderer,Magnum::Audio::Renderer::Error} */
Debug MAGNUM_AUDIO_EXPORT operator<<(Debug debug, Renderer::Error value); Debug MAGNUM_AUDIO_EXPORT operator<<(Debug debug, Renderer::Error value);
inline void Renderer::setListenerOrientation(const Vector3& forward, const Vector3& up) { inline void Renderer::setListenerOrientation(const Vector3& forward, const Vector3& up) {

8
src/Magnum/Audio/Source.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Audio::Source * @brief Class @ref Magnum::Audio::Source
*/ */
#include <functional> #include <functional>
@ -338,7 +338,7 @@ class MAGNUM_AUDIO_EXPORT Source {
}; };
/** /**
* @brief Source type * @brief %Source type
* *
* @see @ref setBuffer(), @fn_al{GetSourcei} with @def_al{SOURCE_TYPE} * @see @ref setBuffer(), @fn_al{GetSourcei} with @def_al{SOURCE_TYPE}
*/ */
@ -346,7 +346,7 @@ class MAGNUM_AUDIO_EXPORT Source {
/** /**
* @brief Attach buffer * @brief Attach buffer
* @param buffer Buffer to attach or `nullptr` * @param buffer %Buffer to attach or `nullptr`
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
* If an buffer is attached, changes source type to @ref Type::Static, * If an buffer is attached, changes source type to @ref Type::Static,
@ -586,7 +586,7 @@ class MAGNUM_AUDIO_EXPORT Source {
ALuint _id; ALuint _id;
}; };
/** @debugoperator{Magnum::Audio::Source} */ /** @debugoperatorclassenum{Magnum::Audio::Source,Magnum::Audio::Source::State} */
Debug MAGNUM_AUDIO_EXPORT operator<<(Debug debug, Source::State value); Debug MAGNUM_AUDIO_EXPORT operator<<(Debug debug, Source::State value);
inline Source::Source(Source&& other): _id(other._id) { inline Source::Source(Source&& other): _id(other._id) {

1
src/Magnum/Buffer.cpp

@ -114,6 +114,7 @@ Buffer::Buffer(Buffer::Target targetHint): _targetHint(targetHint)
#endif #endif
{ {
glGenBuffers(1, &_id); glGenBuffers(1, &_id);
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
} }
Buffer::~Buffer() { Buffer::~Buffer() {

20
src/Magnum/Buffer.h

@ -291,7 +291,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
ShaderStorage = GL_SHADER_STORAGE_BUFFER, ShaderStorage = GL_SHADER_STORAGE_BUFFER,
/** /**
* Source for texel fetches. See BufferTexture. * Source for texel fetches. See @ref BufferTexture.
* @requires_gl31 %Extension @extension{ARB,texture_buffer_object} * @requires_gl31 %Extension @extension{ARB,texture_buffer_object}
* @requires_gl Texture buffers are not available in OpenGL ES. * @requires_gl Texture buffers are not available in OpenGL ES.
*/ */
@ -328,11 +328,11 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
/** /**
* @brief Memory mapping access * @brief Memory mapping access
* *
* @deprecated_gl Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features.
* @see @ref map(MapAccess), @ref mapSub() * @see @ref map(MapAccess), @ref mapSub()
* @requires_es_extension %Extension @es_extension{OES,mapbuffer} or * @requires_es_extension %Extension @es_extension{OES,mapbuffer} or
* @es_extension{CHROMIUM,map_sub} * @es_extension{CHROMIUM,map_sub}
* @deprecated_gl Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features.
*/ */
enum class MapAccess: GLenum { enum class MapAccess: GLenum {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -610,11 +610,11 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* @brief Bind buffer * @brief Bind buffer
* @param target %Target * @param target %Target
* *
* @see @fn_gl{BindBuffer}
* @todo Allow binding to Target::ElementArray only if VAO is bound * @todo Allow binding to Target::ElementArray only if VAO is bound
* to avoid potential issues? * to avoid potential issues?
* @bug Binding to ElementArray if any VAO is active will corrupt the mesh
* @todo Don't allow user to bind buffers? * @todo Don't allow user to bind buffers?
* @see @fn_gl{BindBuffer} * @bug Binding to ElementArray if any VAO is active will corrupt the mesh
*/ */
void bind(Target target) { bind(target, _id); } void bind(Target target) { bind(target, _id); }
@ -746,14 +746,14 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* If @extension{EXT,direct_state_access} is not available and the * If @extension{EXT,direct_state_access} is not available and the
* buffer is not already bound somewhere, it is bound to hinted target * buffer is not already bound somewhere, it is bound to hinted target
* before the operation. * before the operation.
* @deprecated_gl Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features.
* @see @ref minMapAlignment(), @ref unmap(), @ref setTargetHint(), * @see @ref minMapAlignment(), @ref unmap(), @ref setTargetHint(),
* @fn_gl{BindBuffer} and @fn_gl{MapBuffer} or * @fn_gl{BindBuffer} and @fn_gl{MapBuffer} or
* @fn_gl_extension{MapNamedBuffer,EXT,direct_state_access} * @fn_gl_extension{MapNamedBuffer,EXT,direct_state_access}
* @requires_es_extension %Extension @es_extension{OES,mapbuffer} in * @requires_es_extension %Extension @es_extension{OES,mapbuffer} in
* OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" * OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* in OpenGL ES 3.0 instead. * in OpenGL ES 3.0 instead.
* @deprecated_gl Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features.
*/ */
void* map(MapAccess access); void* map(MapAccess access);
@ -767,14 +767,14 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
* *
* If the buffer is not already bound somewhere, it is bound to hinted * If the buffer is not already bound somewhere, it is bound to hinted
* target before the operation. * target before the operation.
* @deprecated_gl Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features.
* @see @ref unmapSub(), @ref setTargetHint(), * @see @ref unmapSub(), @ref setTargetHint(),
* @fn_gl_extension{MapBufferSubData,CHROMIUM,map_sub} * @fn_gl_extension{MapBufferSubData,CHROMIUM,map_sub}
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use * @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)" * @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead. * instead.
* @requires_es_extension %Extension @es_extension{CHROMIUM,map_sub} * @requires_es_extension %Extension @es_extension{CHROMIUM,map_sub}
* @deprecated_gl Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features.
*/ */
void* mapSub(GLintptr offset, GLsizeiptr length, MapAccess access); void* mapSub(GLintptr offset, GLsizeiptr length, MapAccess access);
#endif #endif
@ -926,7 +926,7 @@ class MAGNUM_EXPORT Buffer: public AbstractObject {
CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags) CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags)
/** @debugoperator{Magnum::Buffer} */ /** @debugoperatorclassenum{Magnum::Buffer,Magnum::Buffer::Target} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Buffer::Target value); Debug MAGNUM_EXPORT operator<<(Debug debug, Buffer::Target value);
inline Buffer::Buffer(Buffer&& other) noexcept: _id(other._id), _targetHint(other._targetHint) { inline Buffer::Buffer(Buffer&& other) noexcept: _id(other._id), _targetHint(other._targetHint) {

4
src/Magnum/Color.h

@ -357,7 +357,9 @@ typedef BasicColor3<Float> Color3;
/** @brief Three-component (RGB) unsigned byte color */ /** @brief Three-component (RGB) unsigned byte color */
typedef BasicColor3<UnsignedByte> Color3ub; typedef BasicColor3<UnsignedByte> Color3ub;
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(3, BasicColor3) MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(3, BasicColor3)
#endif
/** /**
@brief Four-component (RGBA) color @brief Four-component (RGBA) color
@ -581,7 +583,9 @@ typedef BasicColor4<Float> Color4;
/** @brief Four-component (RGBA) unsigned byte color */ /** @brief Four-component (RGBA) unsigned byte color */
typedef BasicColor4<UnsignedByte> Color4ub; typedef BasicColor4<UnsignedByte> Color4ub;
#ifndef DOXYGEN_GENERATING_OUTPUT
MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(4, BasicColor4) MAGNUM_VECTORn_OPERATOR_IMPLEMENTATION(4, BasicColor4)
#endif
/** @debugoperator{Magnum::BasicColor3} */ /** @debugoperator{Magnum::BasicColor3} */
template<class T> inline Debug operator<<(Debug debug, const BasicColor3<T>& value) { template<class T> inline Debug operator<<(Debug debug, const BasicColor3<T>& value) {

16
src/Magnum/ColorFormat.h

@ -85,10 +85,10 @@ enum class ColorFormat: GLenum {
/** /**
* Floating-point luminance channel. The value is used for all RGB * Floating-point luminance channel. The value is used for all RGB
* channels. * channels.
* @deprecated_gl Included for compatibility reasons only, use
* @ref Magnum::ColorFormat::Red "ColorFormat::Red" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use * @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::ColorFormat::Red "ColorFormat::Red" instead. * @ref Magnum::ColorFormat::Red "ColorFormat::Red" instead.
* @deprecated_gl Included for compatibility reasons only, use
* @ref Magnum::ColorFormat::Red "ColorFormat::Red" instead.
*/ */
Luminance = GL_LUMINANCE, Luminance = GL_LUMINANCE,
#endif #endif
@ -110,10 +110,10 @@ enum class ColorFormat: GLenum {
/** /**
* Floating-point luminance and alpha channel. First value is used for all * Floating-point luminance and alpha channel. First value is used for all
* RGB channels, second value is used for alpha channel. * RGB channels, second value is used for alpha channel.
* @deprecated_gl Included for compatibility reasons only, use
* @ref Magnum::ColorFormat::RG "ColorFormat::RG" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use * @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::ColorFormat::RG "ColorFormat::RG" instead. * @ref Magnum::ColorFormat::RG "ColorFormat::RG" instead.
* @deprecated_gl Included for compatibility reasons only, use
* @ref Magnum::ColorFormat::RG "ColorFormat::RG" instead.
*/ */
LuminanceAlpha = GL_LUMINANCE_ALPHA, LuminanceAlpha = GL_LUMINANCE_ALPHA,
#endif #endif
@ -372,8 +372,8 @@ enum class ColorType: GLenum {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
/** /**
* BGR, unsigned short, red and blue 5bit, green 6bit. * BGR, unsigned short, red and blue 5bit, green 6bit.
* @requires_gl Only @ref Magnum::ColorType::RGB565 "ColorType::RGB565" is * @requires_gl Only @ref Magnum::ColorType::UnsignedShort565 "ColorType::UnsignedShort565"
* available in OpenGL ES. * is available in OpenGL ES.
*/ */
UnsignedShort565Rev = GL_UNSIGNED_SHORT_5_6_5_REV, UnsignedShort565Rev = GL_UNSIGNED_SHORT_5_6_5_REV,
#endif #endif
@ -491,10 +491,10 @@ enum class ColorType: GLenum {
#endif #endif
}; };
/** @debugoperator{ColorFormat} */ /** @debugoperatorenum{Magnum::ColorFormat} */
Debug MAGNUM_EXPORT operator<<(Debug debug, ColorFormat value); Debug MAGNUM_EXPORT operator<<(Debug debug, ColorFormat value);
/** @debugoperator{ColorFormat} */ /** @debugoperatorenum{Magnum::ColorType} */
Debug MAGNUM_EXPORT operator<<(Debug debug, ColorType value); Debug MAGNUM_EXPORT operator<<(Debug debug, ColorType value);
} }

27
src/Magnum/Context.cpp

@ -45,6 +45,11 @@
#include "Magnum/Renderer.h" #include "Magnum/Renderer.h"
#include "Implementation/State.h" #include "Implementation/State.h"
#include "Implementation/BufferState.h"
#include "Implementation/FramebufferState.h"
#include "Implementation/MeshState.h"
#include "Implementation/ShaderProgramState.h"
#include "Implementation/TextureState.h"
namespace Magnum { namespace Magnum {
@ -61,6 +66,7 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,EXT,texture_filter_anisotropic), _extension(GL,EXT,texture_filter_anisotropic),
_extension(GL,EXT,texture_mirror_clamp), _extension(GL,EXT,texture_mirror_clamp),
_extension(GL,EXT,direct_state_access), _extension(GL,EXT,direct_state_access),
_extension(GL,EXT,texture_sRGB_decode),
_extension(GL,EXT,shader_integer_mix), _extension(GL,EXT,shader_integer_mix),
_extension(GL,EXT,debug_label), _extension(GL,EXT,debug_label),
_extension(GL,EXT,debug_marker), _extension(GL,EXT,debug_marker),
@ -191,9 +197,11 @@ const std::vector<Extension>& Extension::extensions(Version version) {
_extension(GL,EXT,texture_filter_anisotropic), _extension(GL,EXT,texture_filter_anisotropic),
_extension(GL,EXT,texture_format_BGRA8888), _extension(GL,EXT,texture_format_BGRA8888),
_extension(GL,EXT,read_format_bgra), _extension(GL,EXT,read_format_bgra),
_extension(GL,EXT,multi_draw_arrays),
_extension(GL,EXT,debug_label), _extension(GL,EXT,debug_label),
_extension(GL,EXT,debug_marker), _extension(GL,EXT,debug_marker),
_extension(GL,EXT,disjoint_timer_query), _extension(GL,EXT,disjoint_timer_query),
_extension(GL,EXT,texture_sRGB_decode),
_extension(GL,EXT,separate_shader_objects), _extension(GL,EXT,separate_shader_objects),
_extension(GL,EXT,sRGB), _extension(GL,EXT,sRGB),
_extension(GL,EXT,multisampled_render_to_texture), _extension(GL,EXT,multisampled_render_to_texture),
@ -529,6 +537,25 @@ Version Context::supportedVersion(std::initializer_list<Version> versions) const
#endif #endif
} }
void Context::resetState(const States states) {
if(states & State::Buffers)
_state->buffer->reset();
if(states & State::Framebuffers)
_state->framebuffer->reset();
if(states & State::Meshes)
_state->mesh->reset();
/* Nothing to reset for renderer yet */
if(states & State::Shaders) {
/* Nothing to reset for shaders */
_state->shaderProgram->reset();
}
if(states & State::Textures)
_state->texture->reset();
}
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
Debug operator<<(Debug debug, const Context::Flag value) { Debug operator<<(Debug debug, const Context::Flag value) {
switch(value) { switch(value) {

78
src/Magnum/Context.h

@ -45,8 +45,6 @@
namespace Magnum { namespace Magnum {
/** @todoc Resolve conflict with Audio/Context.h (Doxygen doesn't list this file) */
namespace Implementation { namespace Implementation {
struct State; struct State;
} }
@ -89,7 +87,7 @@ class MAGNUM_EXPORT Extension {
}; };
/** /**
@brief Magnum context @brief %Magnum context
Provides access to version and extension information. Instance available Provides access to version and extension information. Instance available
through @ref Context::current() is automatically created during construction of through @ref Context::current() is automatically created during construction of
@ -98,14 +96,9 @@ instance is available during whole lifetime of *Application object. See
@ref platform documentation for more information about engine setup. @ref platform documentation for more information about engine setup.
*/ */
class MAGNUM_EXPORT Context { class MAGNUM_EXPORT Context {
Context(const Context&) = delete;
Context(Context&&) = delete;
Context& operator=(const Context&) = delete;
Context& operator=(Context&&) = delete;
public: public:
/** /**
* @brief Context flag * @brief %Context flag
* *
* @see @ref Flags, @ref flags(), @ref Platform::Sdl2Application::Configuration::setFlags() "Platform::*Application::Configuration::setFlags()" * @see @ref Flags, @ref flags(), @ref Platform::Sdl2Application::Configuration::setFlags() "Platform::*Application::Configuration::setFlags()"
*/ */
@ -142,7 +135,39 @@ class MAGNUM_EXPORT Context {
}; };
/** /**
* @brief Context flags * @brief State to reset
*
* @see @ref States, @ref resetState()
*/
enum class State: UnsignedInt {
/** Reset tracked buffer-related bindings and state */
Buffers = 1 << 0,
/** Reset tracked framebuffer-related bindings and state */
Framebuffers = 1 << 1,
/** Reset tracked mesh-related bindings */
Meshes = 1 << 2,
/** Reset tracked renderer-related state */
Renderer = 1 << 3,
/** Reset tracked shader-related bindings */
Shaders = 1 << 4,
/** Reset tracked texture-related bindings and state */
Textures = 1 << 5
};
/**
* @brief States to reset
*
* @see @ref resetState()
*/
typedef Containers::EnumSet<State, UnsignedInt> States;
/**
* @brief %Context flags
* *
* @see @ref flags() * @see @ref flags()
*/ */
@ -159,8 +184,20 @@ class MAGNUM_EXPORT Context {
*/ */
explicit Context(); explicit Context();
/** @brief Copying is not allowed */
Context(const Context&) = delete;
/** @brief Moving is not allowed */
Context(Context&&) = delete;
~Context(); ~Context();
/** @brief Copying is not allowed */
Context& operator=(const Context&) = delete;
/** @brief Moving is not allowed */
Context& operator=(Context&&) = delete;
/** @brief Current context */ /** @brief Current context */
static Context* current() { return _current; } static Context* current() { return _current; }
@ -246,7 +283,7 @@ class MAGNUM_EXPORT Context {
std::vector<std::string> shadingLanguageVersionStrings() const; std::vector<std::string> shadingLanguageVersionStrings() const;
/** /**
* @brief Extension strings * @brief %Extension strings
* *
* The result is *not* cached, repeated queries will result in repeated * The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. Note that this function returns list of all extensions * OpenGL calls. Note that this function returns list of all extensions
@ -258,7 +295,7 @@ class MAGNUM_EXPORT Context {
*/ */
std::vector<std::string> extensionStrings() const; std::vector<std::string> extensionStrings() const;
/** @brief Context flags */ /** @brief %Context flags */
Flags flags() const { return _flags; } Flags flags() const { return _flags; }
/** /**
@ -295,7 +332,7 @@ class MAGNUM_EXPORT Context {
* OpenGL version (@ref Version::GL210 for desktop OpenGL, * OpenGL version (@ref Version::GL210 for desktop OpenGL,
* @ref Version::GLES200 for OpenGL ES). * @ref Version::GLES200 for OpenGL ES).
* @see isExtensionSupported(Version) const * @see isExtensionSupported(Version) const
* @todoc Explicit reference when Doxygen is sane * @todoc Explicit reference when Doxygen can handle const
*/ */
Version supportedVersion(std::initializer_list<Version> versions) const; Version supportedVersion(std::initializer_list<Version> versions) const;
@ -315,7 +352,7 @@ class MAGNUM_EXPORT Context {
* @see isExtensionSupported(const Extension&) const, * @see isExtensionSupported(const Extension&) const,
* @ref MAGNUM_ASSERT_EXTENSION_SUPPORTED(), * @ref MAGNUM_ASSERT_EXTENSION_SUPPORTED(),
* @ref isExtensionDisabled() * @ref isExtensionDisabled()
* @todoc Explicit reference when Doxygen is sane * @todoc Explicit reference when Doxygen can handle const
*/ */
template<class T> bool isExtensionSupported() const { template<class T> bool isExtensionSupported() const {
return isExtensionSupported<T>(version()); return isExtensionSupported<T>(version());
@ -386,6 +423,17 @@ class MAGNUM_EXPORT Context {
return isVersionSupported(extension._requiredVersion) && extensionStatus[extension._index] && !isVersionSupported(_extensionRequiredVersion[extension._index]); return isVersionSupported(extension._requiredVersion) && extensionStatus[extension._index] && !isVersionSupported(_extensionRequiredVersion[extension._index]);
} }
/**
* @brief Reset internal state tracker
* @param states Tracked states to reset. Default is all state.
*
* The engine internally tracks object bindings and other state to
* avoid redundant OpenGL calls. In some cases (e.g. when non-Magnum
* code makes GL calls) the internal tracker no longer reflects actual
* state and needs to be reset to avoid strange issues.
*/
void resetState(States states = ~States{});
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
Implementation::State& state() { return *_state; } Implementation::State& state() { return *_state; }
#endif #endif
@ -407,7 +455,7 @@ class MAGNUM_EXPORT Context {
Implementation::State* _state; Implementation::State* _state;
}; };
/** @debugoperator{Magnum::Context} */ /** @debugoperatorclassenum{Magnum::Context,Magnum::Context::Flag} */
MAGNUM_EXPORT Debug operator<<(Debug debug, Context::Flag value); MAGNUM_EXPORT Debug operator<<(Debug debug, Context::Flag value);
/** @hideinitializer /** @hideinitializer

6
src/Magnum/CubeMapTexture.h

@ -198,6 +198,12 @@ class MAGNUM_EXPORT CubeMapTexture: public AbstractTexture {
return *this; return *this;
} }
/** @copydoc Texture::setSRGBDecode() */
CubeMapTexture& setSRGBDecode(bool decode) {
AbstractTexture::setSRGBDecode(decode);
return *this;
}
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
/** @copydoc Texture::setSwizzle() */ /** @copydoc Texture::setSwizzle() */
template<char r, char g, char b, char a> CubeMapTexture& setSwizzle() { template<char r, char g, char b, char a> CubeMapTexture& setSwizzle() {

6
src/Magnum/CubeMapTextureArray.h

@ -228,6 +228,12 @@ class CubeMapTextureArray: public AbstractTexture {
return *this; return *this;
} }
/** @copydoc RectangleTexture::setSRGBDecode() */
CubeMapTextureArray& setSRGBDecode(bool decode) {
AbstractTexture::setSRGBDecode(decode);
return *this;
}
/** /**
* @copybrief Texture::setSwizzle() * @copybrief Texture::setSwizzle()
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)

6
src/Magnum/DebugMessage.h

@ -317,13 +317,13 @@ class MAGNUM_EXPORT DebugMessage {
static MAGNUM_LOCAL void callbackImplementationKhr(Callback callback, const void* userParam); static MAGNUM_LOCAL void callbackImplementationKhr(Callback callback, const void* userParam);
}; };
/** @debugoperator{Magnum::DebugMessage} */ /** @debugoperatorclassenum{Magnum::DebugMessage,Magnum::DebugMessage::Source} */
Debug MAGNUM_EXPORT operator<<(Debug debug, DebugMessage::Source value); Debug MAGNUM_EXPORT operator<<(Debug debug, DebugMessage::Source value);
/** @debugoperator{Magnum::DebugMessage} */ /** @debugoperatorclassenum{Magnum::DebugMessage,Magnum::DebugMessage::Type} */
Debug MAGNUM_EXPORT operator<<(Debug debug, DebugMessage::Type value); Debug MAGNUM_EXPORT operator<<(Debug debug, DebugMessage::Type value);
/** @debugoperator{Magnum::DebugMessage} */ /** @debugoperatorclassenum{Magnum::DebugMessage,Magnum::DebugMessage::Severity} */
Debug MAGNUM_EXPORT operator<<(Debug debug, DebugMessage::Severity value); Debug MAGNUM_EXPORT operator<<(Debug debug, DebugMessage::Severity value);
} }

2
src/Magnum/DebugTools/DebugTools.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Forward declarations for Magnum::DebugTools namespace * @brief Forward declarations for @ref Magnum::DebugTools namespace
*/ */
#include "Magnum/Types.h" #include "Magnum/Types.h"

5
src/Magnum/DebugTools/ForceRenderer.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::DebugTools::ForceRenderer, Magnum::DebugTools::ForceRendererOptions, typedef Magnum::DebugTools::ForceRenderer2D, Magnum::DebugTools::ForceRenderer3D * @brief Class @ref Magnum::DebugTools::ForceRenderer, @ref Magnum::DebugTools::ForceRendererOptions, typedef @ref Magnum::DebugTools::ForceRenderer2D, @ref Magnum::DebugTools::ForceRenderer3D
*/ */
#include "Magnum/Color.h" #include "Magnum/Color.h"
@ -122,10 +122,9 @@ template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ForceRenderer: p
/** @overload */ /** @overload */
ForceRenderer(SceneGraph::AbstractObject<dimensions, Float>&, const typename DimensionTraits<dimensions, Float>::VectorType&, typename DimensionTraits<dimensions, Float>::VectorType&&, ResourceKey = ResourceKey(), SceneGraph::DrawableGroup<dimensions, Float>* = nullptr) = delete; ForceRenderer(SceneGraph::AbstractObject<dimensions, Float>&, const typename DimensionTraits<dimensions, Float>::VectorType&, typename DimensionTraits<dimensions, Float>::VectorType&&, ResourceKey = ResourceKey(), SceneGraph::DrawableGroup<dimensions, Float>* = nullptr) = delete;
protected: private:
void draw(const typename DimensionTraits<dimensions, Float>::MatrixType& transformationMatrix, SceneGraph::AbstractCamera<dimensions, Float>& camera) override; void draw(const typename DimensionTraits<dimensions, Float>::MatrixType& transformationMatrix, SceneGraph::AbstractCamera<dimensions, Float>& camera) override;
private:
const typename DimensionTraits<dimensions, Float>::VectorType forcePosition; const typename DimensionTraits<dimensions, Float>::VectorType forcePosition;
const typename DimensionTraits<dimensions, Float>::VectorType& force; const typename DimensionTraits<dimensions, Float>::VectorType& force;

5
src/Magnum/DebugTools/ObjectRenderer.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::DebugTools::ObjectRenderer, Magnum::DebugTools::ObjectRendererOptions, typedef Magnum::DebugTools::ObjectRenderer2D, Magnum::DebugTools::ObjectRenderer3D * @brief Class @ref Magnum::DebugTools::ObjectRenderer, @ref Magnum::DebugTools::ObjectRendererOptions, typedef @ref Magnum::DebugTools::ObjectRenderer2D, @ref Magnum::DebugTools::ObjectRenderer3D
*/ */
#include "Magnum/Resource.h" #include "Magnum/Resource.h"
@ -97,10 +97,9 @@ template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ObjectRenderer:
*/ */
explicit ObjectRenderer(SceneGraph::AbstractObject<dimensions, Float>& object, ResourceKey options = ResourceKey(), SceneGraph::DrawableGroup<dimensions, Float>* drawables = nullptr); explicit ObjectRenderer(SceneGraph::AbstractObject<dimensions, Float>& object, ResourceKey options = ResourceKey(), SceneGraph::DrawableGroup<dimensions, Float>* drawables = nullptr);
protected: private:
void draw(const typename DimensionTraits<dimensions, Float>::MatrixType& transformationMatrix, SceneGraph::AbstractCamera<dimensions, Float>& camera) override; void draw(const typename DimensionTraits<dimensions, Float>::MatrixType& transformationMatrix, SceneGraph::AbstractCamera<dimensions, Float>& camera) override;
private:
Resource<ObjectRendererOptions> options; Resource<ObjectRendererOptions> options;
Resource<AbstractShaderProgram, Shaders::VertexColor<dimensions>> shader; Resource<AbstractShaderProgram, Shaders::VertexColor<dimensions>> shader;
Resource<Mesh> mesh; Resource<Mesh> mesh;

24
src/Magnum/DebugTools/Profiler.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::DebugTools::Profiler * @brief Class @ref Magnum::DebugTools::Profiler
*/ */
#include <chrono> #include <chrono>
@ -44,7 +44,7 @@ namespace Magnum { namespace DebugTools {
@brief %Profiler @brief %Profiler
Measures time passed during specified sections of each frame. It's meant to be Measures time passed during specified sections of each frame. It's meant to be
used in rendering and event loops (e.g. Platform::Sdl2Application::drawEvent()), used in rendering and event loops (e.g. @ref Platform::Sdl2Application::drawEvent()),
but it's possible to use it standalone elsewhere. Example usage: but it's possible to use it standalone elsewhere. Example usage:
@code @code
DebugTools::Profiler p; DebugTools::Profiler p;
@ -95,7 +95,7 @@ p.printStatistics();
@endcode @endcode
It's possible to start profiler only for certain parts of the code and then It's possible to start profiler only for certain parts of the code and then
stop it again using stop(), if you are not interested in profiling the rest. stop it again using @ref stop(), if you are not interested in profiling the rest.
@todo Some unit testing @todo Some unit testing
@todo More time intervals @todo More time intervals
@ -105,14 +105,14 @@ class MAGNUM_DEBUGTOOLS_EXPORT Profiler {
/** /**
* @brief Section ID * @brief Section ID
* *
* @see otherSection, addSection(), start(Section) * @see @ref otherSection, @ref addSection(), @ref start(Section)
*/ */
typedef UnsignedInt Section; typedef UnsignedInt Section;
/** /**
* @brief Default section * @brief Default section
* *
* @see start() * @see @ref start()
*/ */
static const Section otherSection = 0; static const Section otherSection = 0;
@ -137,15 +137,15 @@ class MAGNUM_DEBUGTOOLS_EXPORT Profiler {
* @brief Add named section * @brief Add named section
* *
* @attention This function cannot be called if profiling is enabled. * @attention This function cannot be called if profiling is enabled.
* @see otherSection, start(Section), stop() * @see @ref otherSection, @ref start(Section), @ref stop()
*/ */
Section addSection(const std::string& name); Section addSection(const std::string& name);
/** /**
* @brief Whether profiling is enabled * @brief Whether profiling is enabled
* *
* If the profiling is not enabled, calls to start() and stop() have * If the profiling is not enabled, calls to @ref start() and
* no effect. * @ref stop() have no effect.
*/ */
bool isEnabled() { return enabled; } bool isEnabled() { return enabled; }
@ -153,14 +153,14 @@ class MAGNUM_DEBUGTOOLS_EXPORT Profiler {
* @brief Enable profiling * @brief Enable profiling
* *
* Clears already mesaured data. * Clears already mesaured data.
* @see disable(), isEnabled() * @see @ref disable(), @ref isEnabled()
*/ */
void enable(); void enable();
/** /**
* @brief Disable profiling * @brief Disable profiling
* *
* @see enable(), isEnabled() * @see @ref enable(), @ref isEnabled()
*/ */
void disable(); void disable();
@ -169,14 +169,14 @@ class MAGNUM_DEBUGTOOLS_EXPORT Profiler {
* *
* If profiling is already running, current time is saved for previous * If profiling is already running, current time is saved for previous
* section. * section.
* @see @ref otherSection, start(Section) * @see @ref otherSection, @ref start(Section)
*/ */
void start(Section section); void start(Section section);
/** /**
* @brief Start profiling of "other" section * @brief Start profiling of "other" section
* *
* Same as calling `start(Profiler::otherSection)`. * Same as calling `start(DebugTools::Profiler::otherSection)`.
* @note Does nothing if profiling is disabled. * @note Does nothing if profiling is disabled.
*/ */
void start() { start(otherSection); } void start() { start(otherSection); }

2
src/Magnum/DebugTools/ResourceManager.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::DebugTools::ResourceManager * @brief Class @ref Magnum::DebugTools::ResourceManager
*/ */
#ifndef MAGNUM_RESOURCEMANAGER_DEFINE_INTERNALINSTANCE #ifndef MAGNUM_RESOURCEMANAGER_DEFINE_INTERNALINSTANCE

10
src/Magnum/DebugTools/ShapeRenderer.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::DebugTools::ShapeRenderer, Magnum::DebugTools::ShapeRendererOptions, typedef Magnum::DebugTools::ShapeRenderer2D, Magnum::DebugTools::ShapeRenderer3D * @brief Class @ref Magnum::DebugTools::ShapeRenderer, @ref Magnum::DebugTools::ShapeRendererOptions, typedef @ref Magnum::DebugTools::ShapeRenderer2D, @ref Magnum::DebugTools::ShapeRenderer3D
*/ */
#include "Magnum/Color.h" #include "Magnum/Color.h"
@ -56,7 +56,7 @@ class ShapeRendererOptions {
/** /**
* @brief Shape rendering mode * @brief Shape rendering mode
* *
* @see setRenderMode() * @see @ref setRenderMode()
*/ */
enum class RenderMode: UnsignedByte { enum class RenderMode: UnsignedByte {
Wireframe, /**< Wireframe rendering */ Wireframe, /**< Wireframe rendering */
@ -138,12 +138,14 @@ new DebugTools::ShapeRenderer2D(shape, "red", debugDrawables);
@todo Different drawing style for inverted shapes? (marking the "inside" somehow) @todo Different drawing style for inverted shapes? (marking the "inside" somehow)
*/ */
template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ShapeRenderer: public SceneGraph::Drawable<dimensions, Float> { template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ShapeRenderer: public SceneGraph::Drawable<dimensions, Float> {
#ifndef DOXYGEN_GENERATING_OUTPUT
/* MSVC can't cope with <> here */ /* MSVC can't cope with <> here */
#ifndef CORRADE_MSVC2013_COMPATIBILITY #ifndef CORRADE_MSVC2013_COMPATIBILITY
friend void Implementation::createDebugMesh<>(ShapeRenderer<dimensions>&, const Shapes::Implementation::AbstractShape<dimensions>&); friend void Implementation::createDebugMesh<>(ShapeRenderer<dimensions>&, const Shapes::Implementation::AbstractShape<dimensions>&);
#else #else
template<UnsignedInt dimensions_> friend void Implementation::createDebugMesh(ShapeRenderer<dimensions_>&, const Shapes::Implementation::AbstractShape<dimensions_>&); template<UnsignedInt dimensions_> friend void Implementation::createDebugMesh(ShapeRenderer<dimensions_>&, const Shapes::Implementation::AbstractShape<dimensions_>&);
#endif #endif
#endif
public: public:
/** /**
@ -162,11 +164,9 @@ template<UnsignedInt dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ShapeRenderer: p
~ShapeRenderer(); ~ShapeRenderer();
protected: private:
/** @todoc Remove Float when Doxygen properly treats this as override */
void draw(const typename DimensionTraits<dimensions, Float>::MatrixType& transformationMatrix, SceneGraph::AbstractCamera<dimensions, Float>& camera) override; void draw(const typename DimensionTraits<dimensions, Float>::MatrixType& transformationMatrix, SceneGraph::AbstractCamera<dimensions, Float>& camera) override;
private:
Resource<ShapeRendererOptions> options; Resource<ShapeRendererOptions> options;
std::vector<Implementation::AbstractShapeRenderer<dimensions>*> renderers; std::vector<Implementation::AbstractShapeRenderer<dimensions>*> renderers;
}; };

8
src/Magnum/DefaultFramebuffer.h

@ -145,7 +145,8 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/** /**
* Write output to back buffer. * Write output to back buffer.
* *
* On desktop OpenGL, this is equal to @ref DrawAttachment::BackLeft. * On desktop OpenGL, this is equal to
* @ref DrawAttachment::BackLeft.
*/ */
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
Back = GL_BACK, Back = GL_BACK,
@ -156,7 +157,8 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/** /**
* Write output to front buffer. * Write output to front buffer.
* *
* On desktop OpenGL, this is equal to @ref DrawAttachment::FrontLeft. * On desktop OpenGL, this is equal to
* @ref DrawAttachment::FrontLeft.
*/ */
#ifdef MAGNUM_TARGET_GLES #ifdef MAGNUM_TARGET_GLES
Front = GL_FRONT Front = GL_FRONT
@ -433,7 +435,7 @@ class MAGNUM_EXPORT DefaultFramebuffer: public AbstractFramebuffer {
/** @brief Default framebuffer instance */ /** @brief Default framebuffer instance */
extern DefaultFramebuffer MAGNUM_EXPORT defaultFramebuffer; extern DefaultFramebuffer MAGNUM_EXPORT defaultFramebuffer;
/** @debugoperator{DefaultFramebuffer} */ /** @debugoperatorclassenum{Magnum::DefaultFramebuffer,Magnum::DefaultFramebuffer::Status} */
Debug MAGNUM_EXPORT operator<<(Debug debug, DefaultFramebuffer::Status value); Debug MAGNUM_EXPORT operator<<(Debug debug, DefaultFramebuffer::Status value);
} }

9
src/Magnum/DimensionTraits.h

@ -29,7 +29,7 @@
#include "Magnum/Types.h" #include "Magnum/Types.h"
/** @file /** @file
* @brief Class Magnum::DimensionTraits * @brief Class @ref Magnum::DimensionTraits
*/ */
namespace Magnum { namespace Magnum {
@ -42,15 +42,16 @@ template<UnsignedInt dimensions, class T> struct DimensionTraits {
/** /**
* @brief Vector type * @brief Vector type
* *
* Math::Vector, Math::Vector2 or Math::Vector3 based on dimension count. * @ref Math::Vector, @ref Math::Vector2 or @ref Math::Vector3 based on
* dimension count.
*/ */
typedef U VectorType; typedef U VectorType;
/** /**
* @brief Matrix type * @brief Matrix type
* *
* Floating-point Math::Matrix3 or Math::Matrix4 for 2D or 3D. No matrix * Floating-point @ref Math::Matrix3 or @ref Math::Matrix4 for 2D or 3D. No
* type defined for one dimension and integral types. * matrix type defined for one dimension and integral types.
*/ */
typedef U MatrixType; typedef U MatrixType;
#endif #endif

22
src/Magnum/Extensions.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Namespace Magnum::Extensions * @brief Namespace @ref Magnum::Extensions
*/ */
#include "Magnum/Version.h" #include "Magnum/Version.h"
@ -37,16 +37,21 @@ namespace Magnum {
@brief Compile-time information about OpenGL extensions @brief Compile-time information about OpenGL extensions
Each extension is `struct` named hierarchically by prefix, vendor and Each extension is `struct` named hierarchically by prefix, vendor and
extension name, for example `GL::APPLE::vertex_array_object`. Each struct has extension name taken from list at @ref opengl-support, for example
the same public methods as Extension class (requiredVersion(), coreVersion() `GL::ARB::texture_storage`. Note that desktop extensions are available only on
and string(), but these structs are better suited for compile-time decisions desktop build, OpenGL ES 2.0 extensions which are part of ES 3.0 are available
rather than %Extension instances. See Context::isExtensionSupported() for only on @ref MAGNUM_TARGET_GLES2 "OpenGL ES 2.0 build" and vendor OpenGL ES
example usage. extensions are available only on @ref MAGNUM_TARGET_GLES "OpenGL ES builds".
Each struct has the same public methods as Extension class (requiredVersion(),
coreVersion() and string(), but these structs are better suited for
compile-time decisions rather than %Extension instances. See
@ref Context::isExtensionSupported() for example usage.
This namespace is built by default. To use it, you need to add `${MAGNUM_INCLUDE_DIRS}` This namespace is built by default. To use it, you need to add `${MAGNUM_INCLUDE_DIRS}`
to include path and link to `${MAGNUM_LIBRARIES}`. See @ref building and to include path and link to `${MAGNUM_LIBRARIES}`. See @ref building and
@ref cmake for more information. @ref cmake for more information.
@see MAGNUM_ASSERT_EXTENSION_SUPPORTED() @see @ref MAGNUM_ASSERT_EXTENSION_SUPPORTED()
@todo Manual indices for extensions, this has gaps @todo Manual indices for extensions, this has gaps
*/ */
namespace Extensions { namespace Extensions {
@ -182,6 +187,7 @@ namespace GL {
_extension(GL,EXT,transform_feedback, GL210, GL300) // #352 _extension(GL,EXT,transform_feedback, GL210, GL300) // #352
_extension(GL,EXT,direct_state_access, GL210, None) // #353 _extension(GL,EXT,direct_state_access, GL210, None) // #353
_extension(GL,EXT,texture_snorm, GL300, GL310) // #365 _extension(GL,EXT,texture_snorm, GL300, GL310) // #365
_extension(GL,EXT,texture_sRGB_decode, GL210, None) // #402
_extension(GL,EXT,shader_integer_mix, GL300, None) // #437 _extension(GL,EXT,shader_integer_mix, GL300, None) // #437
_extension(GL,EXT,debug_label, GL210, None) // #439 _extension(GL,EXT,debug_label, GL210, None) // #439
_extension(GL,EXT,debug_marker, GL210, None) // #440 _extension(GL,EXT,debug_marker, GL210, None) // #440
@ -233,6 +239,7 @@ namespace GL {
_extension(GL,EXT,blend_minmax, GLES200, GLES300) // #65 _extension(GL,EXT,blend_minmax, GLES200, GLES300) // #65
#endif #endif
_extension(GL,EXT,read_format_bgra, GLES200, None) // #66 _extension(GL,EXT,read_format_bgra, GLES200, None) // #66
_extension(GL,EXT,multi_draw_arrays, GLES200, None) // #67
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(GL,EXT,shader_texture_lod, GLES200, GLES300) // #77 _extension(GL,EXT,shader_texture_lod, GLES200, GLES300) // #77
#endif #endif
@ -254,6 +261,7 @@ namespace GL {
_extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121 _extension(GL,EXT,map_buffer_range, GLES200, GLES300) // #121
#endif #endif
_extension(GL,EXT,disjoint_timer_query, GLES200, None) // #150 _extension(GL,EXT,disjoint_timer_query, GLES200, None) // #150
_extension(GL,EXT,texture_sRGB_decode, GLES200, None) // #152
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
_extension(GL,EXT,instanced_arrays, GLES200, GLES300) // #156 _extension(GL,EXT,instanced_arrays, GLES200, GLES300) // #156
_extension(GL,EXT,draw_instanced, GLES200, GLES300) // #157 _extension(GL,EXT,draw_instanced, GLES200, GLES300) // #157

1
src/Magnum/Framebuffer.cpp

@ -82,6 +82,7 @@ Framebuffer::Framebuffer(const Range2Di& viewport) {
_viewport = viewport; _viewport = viewport;
glGenFramebuffers(1, &_id); glGenFramebuffers(1, &_id);
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
} }
Framebuffer::~Framebuffer() { Framebuffer::~Framebuffer() {

10
src/Magnum/Framebuffer.h

@ -496,7 +496,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
/** /**
* @brief Attach texture to given buffer * @brief Attach texture to given buffer
* @param attachment %Buffer attachment * @param attachment %Buffer attachment
* @param texture Texture * @param texture %Texture
* @param level Mip level * @param level Mip level
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
@ -514,7 +514,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
/** /**
* @brief Attach texture to given buffer * @brief Attach texture to given buffer
* @param attachment %Buffer attachment * @param attachment %Buffer attachment
* @param texture Texture * @param texture %Texture
* @param level Mip level * @param level Mip level
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
* *
@ -544,7 +544,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
/** /**
* @brief Attach cube map texture to given buffer * @brief Attach cube map texture to given buffer
* @param attachment %Buffer attachment * @param attachment %Buffer attachment
* @param texture Cube map texture * @param texture %Texture
* @param coordinate Cube map coordinate * @param coordinate Cube map coordinate
* @param level Mip level * @param level Mip level
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
@ -561,7 +561,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
/** /**
* @brief Attach texture layer to given buffer * @brief Attach texture layer to given buffer
* @param attachment %Buffer attachment * @param attachment %Buffer attachment
* @param texture Texture * @param texture %Texture
* @param level Mip level * @param level Mip level
* @param layer Layer * @param layer Layer
* @return Reference to self (for method chaining) * @return Reference to self (for method chaining)
@ -663,7 +663,7 @@ class MAGNUM_EXPORT Framebuffer: public AbstractFramebuffer, public AbstractObje
#endif #endif
}; };
/** @debugoperator{DefaultFramebuffer} */ /** @debugoperatorclassenum{Magnum::Framebuffer,Magnum::Framebuffer::Status} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Framebuffer::Status value); Debug MAGNUM_EXPORT operator<<(Debug debug, Framebuffer::Status value);
inline Framebuffer::Framebuffer(Framebuffer&& other) noexcept { inline Framebuffer::Framebuffer(Framebuffer&& other) noexcept {

6
src/Magnum/Implementation/BufferState.cpp

@ -30,6 +30,8 @@
#include "Magnum/Context.h" #include "Magnum/Context.h"
#include "Magnum/Extensions.h" #include "Magnum/Extensions.h"
#include "State.h"
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
const Buffer::Target BufferState::targetForIndex[] = { const Buffer::Target BufferState::targetForIndex[] = {
@ -136,4 +138,8 @@ BufferState::BufferState(Context& context, std::vector<std::string>& extensions)
#endif #endif
} }
void BufferState::reset() {
std::fill_n(bindings, TargetCount, State::DisengagedBinding);
}
}} }}

2
src/Magnum/Implementation/BufferState.h

@ -46,6 +46,8 @@ struct BufferState {
explicit BufferState(Context& context, std::vector<std::string>& extensions); explicit BufferState(Context& context, std::vector<std::string>& extensions);
void reset();
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
void(*copyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr); void(*copyImplementation)(Buffer&, Buffer&, GLintptr, GLintptr, GLsizeiptr);
#endif #endif

7
src/Magnum/Implementation/FramebufferState.cpp

@ -29,6 +29,8 @@
#include "Magnum/Extensions.h" #include "Magnum/Extensions.h"
#include "Magnum/Renderbuffer.h" #include "Magnum/Renderbuffer.h"
#include "State.h"
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
FramebufferState::FramebufferState(Context& context, std::vector<std::string>& extensions): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0) FramebufferState::FramebufferState(Context& context, std::vector<std::string>& extensions): readBinding(0), drawBinding(0), renderbufferBinding(0), maxDrawBuffers(0), maxColorAttachments(0), maxRenderbufferSize(0), maxSamples(0)
@ -138,4 +140,9 @@ FramebufferState::FramebufferState(Context& context, std::vector<std::string>& e
} }
} }
void FramebufferState::reset() {
readBinding = drawBinding = renderbufferBinding = State::DisengagedBinding;
viewport = {};
}
}} }}

2
src/Magnum/Implementation/FramebufferState.h

@ -45,6 +45,8 @@ namespace Magnum { namespace Implementation {
struct FramebufferState { struct FramebufferState {
explicit FramebufferState(Context& context, std::vector<std::string>& extensions); explicit FramebufferState(Context& context, std::vector<std::string>& extensions);
void reset();
GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget); GLenum(AbstractFramebuffer::*checkStatusImplementation)(FramebufferTarget);
void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*); void(AbstractFramebuffer::*drawBuffersImplementation)(GLsizei, const GLenum*);
void(AbstractFramebuffer::*drawBufferImplementation)(GLenum); void(AbstractFramebuffer::*drawBufferImplementation)(GLenum);

16
src/Magnum/Implementation/MeshState.cpp

@ -27,6 +27,9 @@
#include "Magnum/Context.h" #include "Magnum/Context.h"
#include "Magnum/Extensions.h" #include "Magnum/Extensions.h"
#include "Magnum/MeshView.h"
#include "State.h"
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
@ -93,6 +96,15 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
} }
#endif #endif
#ifdef MAGNUM_TARGET_GLES
/* Multi draw implementation on ES */
if(context.isExtensionSupported<Extensions::GL::EXT::multi_draw_arrays>()) {
extensions.push_back(Extensions::GL::EXT::multi_draw_arrays::string());
multiDrawImplementation = &MeshView::multiDrawImplementationDefault;
} else multiDrawImplementation = &MeshView::multiDrawImplementationFallback;
#endif
#ifdef MAGNUM_TARGET_GLES2 #ifdef MAGNUM_TARGET_GLES2
/* Instanced draw ímplementation on ES2 */ /* Instanced draw ímplementation on ES2 */
if(context.isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>()) { if(context.isExtensionSupported<Extensions::GL::ANGLE::instanced_arrays>()) {
@ -138,4 +150,8 @@ MeshState::MeshState(Context& context, std::vector<std::string>& extensions): cu
#endif #endif
} }
void MeshState::reset() {
currentVAO = State::DisengagedBinding;
}
}} }}

6
src/Magnum/Implementation/MeshState.h

@ -35,6 +35,8 @@ namespace Magnum { namespace Implementation {
struct MeshState { struct MeshState {
explicit MeshState(Context& context, std::vector<std::string>& extensions); explicit MeshState(Context& context, std::vector<std::string>& extensions);
void reset();
void(Mesh::*createImplementation)(); void(Mesh::*createImplementation)();
void(Mesh::*destroyImplementation)(); void(Mesh::*destroyImplementation)();
void(Mesh::*attributePointerImplementation)(const Mesh::Attribute&); void(Mesh::*attributePointerImplementation)(const Mesh::Attribute&);
@ -56,6 +58,10 @@ struct MeshState {
void(Mesh::*drawElementsInstancedImplementation)(GLsizei, GLintptr, GLsizei); void(Mesh::*drawElementsInstancedImplementation)(GLsizei, GLintptr, GLsizei);
#endif #endif
#ifdef MAGNUM_TARGET_GLES
void(*multiDrawImplementation)(std::initializer_list<std::reference_wrapper<MeshView>>);
#endif
GLuint currentVAO; GLuint currentVAO;
#ifndef MAGNUM_TARGET_GLES2 #ifndef MAGNUM_TARGET_GLES2
GLint maxElementsIndices, maxElementsVertices; GLint maxElementsIndices, maxElementsVertices;

6
src/Magnum/Implementation/ShaderProgramState.cpp

@ -29,6 +29,8 @@
#include "Magnum/Context.h" #include "Magnum/Context.h"
#include "Magnum/Extensions.h" #include "Magnum/Extensions.h"
#include "State.h"
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
ShaderProgramState::ShaderProgramState(Context& context, std::vector<std::string>& extensions): current(0), maxVertexAttributes(0) ShaderProgramState::ShaderProgramState(Context& context, std::vector<std::string>& extensions): current(0), maxVertexAttributes(0)
@ -185,4 +187,8 @@ ShaderProgramState::ShaderProgramState(Context& context, std::vector<std::string
} }
} }
void ShaderProgramState::reset() {
current = State::DisengagedBinding;
}
}} }}

2
src/Magnum/Implementation/ShaderProgramState.h

@ -42,6 +42,8 @@ namespace Magnum { namespace Implementation {
struct ShaderProgramState { struct ShaderProgramState {
explicit ShaderProgramState(Context& context, std::vector<std::string>& extensions); explicit ShaderProgramState(Context& context, std::vector<std::string>& extensions);
void reset();
void(AbstractShaderProgram::*uniform1fvImplementation)(GLint, GLsizei, const GLfloat*); void(AbstractShaderProgram::*uniform1fvImplementation)(GLint, GLsizei, const GLfloat*);
void(AbstractShaderProgram::*uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*); void(AbstractShaderProgram::*uniform2fvImplementation)(GLint, GLsizei, const Math::Vector<2, GLfloat>*);
void(AbstractShaderProgram::*uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*); void(AbstractShaderProgram::*uniform3fvImplementation)(GLint, GLsizei, const Math::Vector<3, GLfloat>*);

3
src/Magnum/Implementation/State.h

@ -26,6 +26,7 @@
*/ */
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/OpenGL.h"
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
@ -44,6 +45,8 @@ struct State {
~State(); ~State();
enum: GLuint { DisengagedBinding = ~0u };
BufferState* buffer; BufferState* buffer;
DebugState* debug; DebugState* debug;
FramebufferState* framebuffer; FramebufferState* framebuffer;

6
src/Magnum/Implementation/TextureState.cpp

@ -34,6 +34,8 @@
#include "Magnum/Context.h" #include "Magnum/Context.h"
#include "Magnum/Extensions.h" #include "Magnum/Extensions.h"
#include "State.h"
namespace Magnum { namespace Implementation { namespace Magnum { namespace Implementation {
TextureState::TextureState(Context& context, std::vector<std::string>& extensions): maxSize{}, max3DSize{}, maxCubeMapSize{}, TextureState::TextureState(Context& context, std::vector<std::string>& extensions): maxSize{}, max3DSize{}, maxCubeMapSize{},
@ -228,4 +230,8 @@ TextureState::TextureState(Context& context, std::vector<std::string>& extension
TextureState::~TextureState() = default; TextureState::~TextureState() = default;
void TextureState::reset() {
std::fill_n(bindings.begin(), bindings.size(), std::pair<GLenum, GLuint>{{}, State::DisengagedBinding});
}
}} }}

2
src/Magnum/Implementation/TextureState.h

@ -55,6 +55,8 @@ struct TextureState {
explicit TextureState(Context& context, std::vector<std::string>& extensions); explicit TextureState(Context& context, std::vector<std::string>& extensions);
~TextureState(); ~TextureState();
void reset();
void(*unbindImplementation)(GLint); void(*unbindImplementation)(GLint);
void(*bindMultiImplementation)(GLint, std::initializer_list<AbstractTexture*>); void(*bindMultiImplementation)(GLint, std::initializer_list<AbstractTexture*>);
void(AbstractTexture::*bindImplementation)(GLint); void(AbstractTexture::*bindImplementation)(GLint);

1
src/Magnum/Implementation/setupDriverWorkarounds.cpp

@ -56,6 +56,7 @@ void Context::setupDriverWorkarounds() {
#ifndef CORRADE_TARGET_NACL #ifndef CORRADE_TARGET_NACL
_setRequiredVersion(GL::CHROMIUM::map_sub, None); _setRequiredVersion(GL::CHROMIUM::map_sub, None);
#endif #endif
_setRequiredVersion(GL::EXT::multi_draw_arrays, None);
_setRequiredVersion(GL::EXT::debug_label, None); _setRequiredVersion(GL::EXT::debug_label, None);
_setRequiredVersion(GL::EXT::debug_marker, None); _setRequiredVersion(GL::EXT::debug_marker, None);
_setRequiredVersion(GL::EXT::disjoint_timer_query, None); _setRequiredVersion(GL::EXT::disjoint_timer_query, None);

2
src/Magnum/Magnum.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Forward declarations for Magnum namespace * @brief Forward declarations for @ref Magnum namespace
*/ */
#include <Corrade/Utility/Utility.h> #include <Corrade/Utility/Utility.h>

9
src/Magnum/Math/Algorithms/GaussJordan.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Function Magnum::Math::Algorithms::gaussJordanInPlaceTransposed(), Magnum::Math::Algorithms::gaussJordanInPlace() * @brief Function @ref Magnum::Math::Algorithms::gaussJordanInPlaceTransposed(), @ref Magnum::Math::Algorithms::gaussJordanInPlace()
*/ */
#include "Magnum/Math/RectangularMatrix.h" #include "Magnum/Math/RectangularMatrix.h"
@ -42,7 +42,8 @@ namespace Magnum { namespace Math { namespace Algorithms {
As Gauss-Jordan elimination works on rows and matrices in OpenGL are As Gauss-Jordan elimination works on rows and matrices in OpenGL are
column-major, it is more efficient to operate on transposed matrices and treat column-major, it is more efficient to operate on transposed matrices and treat
columns as rows. See also gaussJordanInPlace() which works with non-transposed matrices. columns as rows. See also @ref gaussJordanInPlace() which works with
non-transposed matrices.
The function eliminates matrix @p a and solves @p t in place. For efficiency The function eliminates matrix @p a and solves @p t in place. For efficiency
reasons, only pure Gaussian elimination is done on @p a and the final reasons, only pure Gaussian elimination is done on @p a and the final
@ -94,8 +95,8 @@ template<std::size_t size, std::size_t rows, class T> bool gaussJordanInPlaceTra
/** /**
@brief In-place Gauss-Jordan elimination @brief In-place Gauss-Jordan elimination
Transposes the matrices, calls gaussJordanInPlaceTransposed() on them and then Transposes the matrices, calls @ref gaussJordanInPlaceTransposed() on them and
transposes them back. then transposes them back.
*/ */
template<std::size_t size, std::size_t cols, class T> bool gaussJordanInPlace(RectangularMatrix<size, size, T>& a, RectangularMatrix<cols, size, T>& t) { template<std::size_t size, std::size_t cols, class T> bool gaussJordanInPlace(RectangularMatrix<size, size, T>& a, RectangularMatrix<cols, size, T>& t) {
a = a.transposed(); a = a.transposed();

10
src/Magnum/Math/Algorithms/GramSchmidt.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Function Magnum::Math::Algorithms::gramSchmidtOrthogonalizeInPlace(), Magnum::Math::Algorithms::gramSchmidtOrthogonalize(), Magnum::Math::Algorithms::gramSchmidtOrthonormalizeInPlace(), Magnum::Math::Algorithms::gramSchmidtOrthonormalize() * @brief Function @ref Magnum::Math::Algorithms::gramSchmidtOrthogonalizeInPlace(), @ref Magnum::Math::Algorithms::gramSchmidtOrthogonalize(), @ref Magnum::Math::Algorithms::gramSchmidtOrthonormalizeInPlace(), @ref Magnum::Math::Algorithms::gramSchmidtOrthonormalize()
*/ */
#include "Magnum/Math/RectangularMatrix.h" #include "Magnum/Math/RectangularMatrix.h"
@ -48,8 +48,8 @@ template<std::size_t cols, std::size_t rows, class T> void gramSchmidtOrthogonal
/** /**
@brief Gram-Schmidt matrix orthogonalization @brief Gram-Schmidt matrix orthogonalization
Unlike gramSchmidtOrthogonalizeInPlace() returns the modified matrix instead Unlike @ref gramSchmidtOrthogonalizeInPlace() returns the modified matrix
of performing the orthogonalization in-place. instead of performing the orthogonalization in-place.
*/ */
template<std::size_t cols, std::size_t rows, class T> RectangularMatrix<cols, rows, T> gramSchmidtOrthogonalize(RectangularMatrix<cols, rows, T> matrix) { template<std::size_t cols, std::size_t rows, class T> RectangularMatrix<cols, rows, T> gramSchmidtOrthogonalize(RectangularMatrix<cols, rows, T> matrix) {
gramSchmidtOrthogonalizeInPlace(matrix); gramSchmidtOrthogonalizeInPlace(matrix);
@ -72,8 +72,8 @@ template<std::size_t cols, std::size_t rows, class T> void gramSchmidtOrthonorma
/** /**
@brief Gram-Schmidt matrix orthonormalization @brief Gram-Schmidt matrix orthonormalization
Unlike gramSchmidtOrthonormalizeInPlace() returns the modified matrix instead Unlike @ref gramSchmidtOrthonormalizeInPlace() returns the modified matrix
of performing the orthonormalization in-place. instead of performing the orthonormalization in-place.
*/ */
template<std::size_t cols, std::size_t rows, class T> RectangularMatrix<cols, rows, T> gramSchmidtOrthonormalize(RectangularMatrix<cols, rows, T> matrix) { template<std::size_t cols, std::size_t rows, class T> RectangularMatrix<cols, rows, T> gramSchmidtOrthonormalize(RectangularMatrix<cols, rows, T> matrix) {
gramSchmidtOrthonormalizeInPlace(matrix); gramSchmidtOrthonormalizeInPlace(matrix);

2
src/Magnum/Math/Algorithms/Svd.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Function Magnum::Math::Algorithms::svd() * @brief Function @ref Magnum::Math::Algorithms::svd()
*/ */
#include <tuple> #include <tuple>

20
src/Magnum/Math/Angle.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Deg, Magnum::Math::Rad and related operators. * @brief Class @ref Magnum::Math::Deg, @ref Magnum::Math::Rad and related operators.
*/ */
#include <Corrade/configure.h> #include <Corrade/configure.h>
@ -119,7 +119,7 @@ std::sin(Float(Rad<Float>(b)); // required explicit conversion hints to user
// (i.e., conversion to radians) // (i.e., conversion to radians)
@endcode @endcode
@see Magnum::Deg, Magnum::Degd @see @ref Magnum::Deg, @ref Magnum::Degd
*/ */
template<class T> class Deg: public Unit<Deg, T> { template<class T> class Deg: public Unit<Deg, T> {
public: public:
@ -157,8 +157,9 @@ Double cosine = Math::cos(60.0_deg); // cosine = 0.5
Double cosine = Math::cos(1.047_rad); // cosine = 0.5 Double cosine = Math::cos(1.047_rad); // cosine = 0.5
@endcode @endcode
@see Magnum::operator""_deg(), operator""_degf(), operator""_rad() @see Magnum::operator""_deg(), operator""_degf(), operator""_rad()
@note Not available on GCC < 4.7 and MSVC 2013. Use Deg::Deg(T) instead. @note Not available on GCC < 4.7 and MSVC 2013. Use @ref Deg::Deg(T) instead.
@requires_gl Only single-precision types are available in OpenGL ES. @requires_gl Only single-precision types are available in OpenGL ES.
@todoc Make references explicit when Doxygen can link to operator""
*/ */
constexpr Deg<Double> operator "" _deg(long double value) { return Deg<Double>(value); } constexpr Deg<Double> operator "" _deg(long double value) { return Deg<Double>(value); }
#endif #endif
@ -172,8 +173,9 @@ Float tangent = Math::tan(60.0_degf); // tangent = 1.732f
Float tangent = Math::tan(1.047_radf); // tangent = 1.732f Float tangent = Math::tan(1.047_radf); // tangent = 1.732f
@endcode @endcode
@see Magnum::operator""_degf(), operator""_deg(), operator""_radf() @see Magnum::operator""_degf(), operator""_deg(), operator""_radf()
@note Not available on GCC < 4.7 and MSVC 2013. Use Deg::Deg(T) instead. @note Not available on GCC < 4.7 and MSVC 2013. Use @ref Deg::Deg(T) instead.
@requires_gl Only single-precision types are available in OpenGL ES. @requires_gl Only single-precision types are available in OpenGL ES.
@todoc Make references explicit when Doxygen can link to operator""
*/ */
constexpr Deg<Float> operator "" _degf(long double value) { return Deg<Float>(value); } constexpr Deg<Float> operator "" _degf(long double value) { return Deg<Float>(value); }
#endif #endif
@ -181,8 +183,8 @@ constexpr Deg<Float> operator "" _degf(long double value) { return Deg<Float>(va
/** /**
@brief Angle in radians @brief Angle in radians
See Deg for more information. See @ref Deg for more information.
@see Magnum::Rad, Magnum::Radd @see @ref Magnum::Rad, @ref Magnum::Radd
*/ */
template<class T> class Rad: public Unit<Rad, T> { template<class T> class Rad: public Unit<Rad, T> {
public: public:
@ -216,7 +218,8 @@ template<class T> class Rad: public Unit<Rad, T> {
See operator""_rad() for more information. See operator""_rad() for more information.
@see Magnum::operator""_rad(), operator""_radf(), operator""_deg() @see Magnum::operator""_rad(), operator""_radf(), operator""_deg()
@note Not available on GCC < 4.7 and MSVC 2013. Use Rad::Rad(T) instead. @note Not available on GCC < 4.7 and MSVC 2013. Use @ref Rad::Rad(T) instead.
@todoc Make references explicit when Doxygen can link to operator""
*/ */
constexpr Rad<Double> operator "" _rad(long double value) { return Rad<Double>(value); } constexpr Rad<Double> operator "" _rad(long double value) { return Rad<Double>(value); }
#endif #endif
@ -226,7 +229,8 @@ constexpr Rad<Double> operator "" _rad(long double value) { return Rad<Double>(v
See operator""_degf() for more information. See operator""_degf() for more information.
@see Magnum::operator""_radf(), operator""_rad(), operator""_degf() @see Magnum::operator""_radf(), operator""_rad(), operator""_degf()
@note Not available on GCC < 4.7 and MSVC 2013. Use Rad::Rad(T) instead. @note Not available on GCC < 4.7 and MSVC 2013. Use @ref Rad::Rad(T) instead.
@todoc Make references explicit when Doxygen can link to operator""
*/ */
constexpr Rad<Float> operator "" _radf(long double value) { return Rad<Float>(value); } constexpr Rad<Float> operator "" _radf(long double value) { return Rad<Float>(value); }
#endif #endif

14
src/Magnum/Math/BoolVector.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::BoolVector * @brief Class @ref Magnum::Math::BoolVector
*/ */
#include <Corrade/configure.h> #include <Corrade/configure.h>
@ -63,8 +63,8 @@ namespace Implementation {
Result of component-wise comparison from Vector. The boolean values are stored Result of component-wise comparison from Vector. The boolean values are stored
as bits in array of unsigned bytes, unused bits have undefined value which as bits in array of unsigned bytes, unused bits have undefined value which
doesn't affect comparison or all() / none() / any() functions. See also doesn't affect comparison or @ref all() / @ref none() / @ref any() functions.
@ref matrix-vector for brief introduction. See also @ref matrix-vector for brief introduction.
*/ */
template<std::size_t size> class BoolVector { template<std::size_t size> class BoolVector {
static_assert(size != 0, "BoolVector cannot have zero elements"); static_assert(size != 0, "BoolVector cannot have zero elements");
@ -115,7 +115,7 @@ template<std::size_t size> class BoolVector {
* @brief Raw data * @brief Raw data
* @return %Array of DataSize length * @return %Array of DataSize length
* *
* @see operator[](), set() * @see @ref operator[](), @ref set()
*/ */
UnsignedByte* data() { UnsignedByte* data() {
#ifndef CORRADE_MSVC2013_COMPATIBILITY #ifndef CORRADE_MSVC2013_COMPATIBILITY
@ -180,7 +180,7 @@ template<std::size_t size> class BoolVector {
/** /**
* @brief Bitwise AND * @brief Bitwise AND
* *
* @see operator&=() * @see @ref operator&=()
*/ */
BoolVector<size> operator&(const BoolVector<size>& other) const { BoolVector<size> operator&(const BoolVector<size>& other) const {
return BoolVector<size>(*this) &= other; return BoolVector<size>(*this) &= other;
@ -201,7 +201,7 @@ template<std::size_t size> class BoolVector {
/** /**
* @brief Bitwise OR * @brief Bitwise OR
* *
* @see operator|=() * @see @ref operator|=()
*/ */
BoolVector<size> operator|(const BoolVector<size>& other) const { BoolVector<size> operator|(const BoolVector<size>& other) const {
return BoolVector<size>(*this) |= other; return BoolVector<size>(*this) |= other;
@ -222,7 +222,7 @@ template<std::size_t size> class BoolVector {
/** /**
* @brief Bitwise XOR * @brief Bitwise XOR
* *
* @see operator^=() * @see @ref operator^=()
*/ */
BoolVector<size> operator^(const BoolVector<size>& other) const { BoolVector<size> operator^(const BoolVector<size>& other) const {
return BoolVector<size>(*this) ^= other; return BoolVector<size>(*this) ^= other;

64
src/Magnum/Math/Complex.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Complex * @brief Class @ref Magnum::Math::Complex
*/ */
#include <limits> #include <limits>
@ -51,11 +51,11 @@ namespace Implementation {
@tparam T Data type @tparam T Data type
Represents 2D rotation. See @ref transformations for brief introduction. Represents 2D rotation. See @ref transformations for brief introduction.
@see Magnum::Complex, Magnum::Complexd, Matrix3 @see @ref Magnum::Complex, @ref Magnum::Complexd, @ref Matrix3
*/ */
template<class T> class Complex { template<class T> class Complex {
public: public:
typedef T Type; /**< @brief Underlying data type */ typedef T Type; /**< @brief Underlying data type */
/** /**
* @brief Dot product * @brief Dot product
@ -64,6 +64,7 @@ template<class T> class Complex {
* c_0 \cdot c_1 = a_0 a_1 + b_0 b_1 * c_0 \cdot c_1 = a_0 a_1 + b_0 b_1
* @f] * @f]
* @see dot() const * @see dot() const
* @todoc Explicit reference when Doxygen can handle const
*/ */
static T dot(const Complex<T>& a, const Complex<T>& b) { static T dot(const Complex<T>& a, const Complex<T>& b) {
return a._real*b._real + a._imaginary*b._imaginary; return a._real*b._real + a._imaginary*b._imaginary;
@ -75,7 +76,8 @@ template<class T> class Complex {
* Expects that both complex numbers are normalized. @f[ * Expects that both complex numbers are normalized. @f[
* \theta = acos \left( \frac{Re(c_0 \cdot c_1))}{|c_0| |c_1|} \right) = acos (a_0 a_1 + b_0 b_1) * \theta = acos \left( \frac{Re(c_0 \cdot c_1))}{|c_0| |c_1|} \right) = acos (a_0 a_1 + b_0 b_1)
* @f] * @f]
* @see isNormalized(), Quaternion::angle(), Vector::angle() * @see @ref isNormalized(), @ref Quaternion::angle(),
* @ref Vector::angle()
*/ */
static Rad<T> angle(const Complex<T>& normalizedA, const Complex<T>& normalizedB) { static Rad<T> angle(const Complex<T>& normalizedA, const Complex<T>& normalizedB) {
CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(),
@ -90,7 +92,8 @@ template<class T> class Complex {
* @f[ * @f[
* c = cos \theta + i sin \theta * c = cos \theta + i sin \theta
* @f] * @f]
* @see angle(), Matrix3::rotation(), Quaternion::rotation() * @see @ref angle(), @ref Matrix3::rotation(),
* @ref Quaternion::rotation()
*/ */
static Complex<T> rotation(Rad<T> angle) { static Complex<T> rotation(Rad<T> angle) {
return {std::cos(angle.toUnderlyingType()), std::sin(angle.toUnderlyingType())}; return {std::cos(angle.toUnderlyingType()), std::sin(angle.toUnderlyingType())};
@ -100,7 +103,8 @@ template<class T> class Complex {
* @brief Create complex number from rotation matrix * @brief Create complex number from rotation matrix
* *
* Expects that the matrix is orthogonal (i.e. pure rotation). * Expects that the matrix is orthogonal (i.e. pure rotation).
* @see toMatrix(), DualComplex::fromMatrix(), Matrix::isOrthogonal() * @see @ref toMatrix(), @ref DualComplex::fromMatrix(),
* @ref Matrix::isOrthogonal()
*/ */
static Complex<T> fromMatrix(const Matrix<2, T>& matrix) { static Complex<T> fromMatrix(const Matrix<2, T>& matrix) {
CORRADE_ASSERT(matrix.isOrthogonal(), CORRADE_ASSERT(matrix.isOrthogonal(),
@ -132,7 +136,8 @@ template<class T> class Complex {
* To be used in transformations later. @f[ * To be used in transformations later. @f[
* c = v_x + iv_y * c = v_x + iv_y
* @f] * @f]
* @see operator Vector2(), transformVector() * @see operator Vector2(), @ref transformVector()
* @todoc Explicit reference when Doxygen can handle conversion operators
*/ */
constexpr explicit Complex(const Vector2<T>& vector): _real(vector.x()), _imaginary(vector.y()) {} constexpr explicit Complex(const Vector2<T>& vector): _real(vector.x()), _imaginary(vector.y()) {}
@ -153,7 +158,7 @@ template<class T> class Complex {
* Complex number is normalized if it has unit length: @f[ * Complex number is normalized if it has unit length: @f[
* |c \cdot c - 1| < 2 \epsilon + \epsilon^2 \cong 2 \epsilon * |c \cdot c - 1| < 2 \epsilon + \epsilon^2 \cong 2 \epsilon
* @f] * @f]
* @see dot(), normalized() * @see @ref dot(), @ref normalized()
*/ */
bool isNormalized() const { bool isNormalized() const {
return Implementation::isNormalizedSquared(dot()); return Implementation::isNormalizedSquared(dot());
@ -186,7 +191,7 @@ template<class T> class Complex {
* @f[ * @f[
* \theta = atan2(b, a) * \theta = atan2(b, a)
* @f] * @f]
* @see rotation() * @see @ref rotation()
*/ */
Rad<T> angle() const { Rad<T> angle() const {
return Rad<T>(std::atan2(_imaginary, _real)); return Rad<T>(std::atan2(_imaginary, _real));
@ -201,8 +206,8 @@ template<class T> class Complex {
* b & a * b & a
* \end{pmatrix} * \end{pmatrix}
* @f] * @f]
* @see fromMatrix(), DualComplex::toMatrix(), * @see @ref fromMatrix(), @ref DualComplex::toMatrix(),
* Matrix3::from(const Matrix<2, T>&, const Vector2<T>&) * @ref Matrix3::from(const Matrix<2, T>&, const Vector2<T>&)
*/ */
Matrix<2, T> toMatrix() const { Matrix<2, T> toMatrix() const {
return {Vector<2, T>(_real, _imaginary), return {Vector<2, T>(_real, _imaginary),
@ -225,7 +230,7 @@ template<class T> class Complex {
/** /**
* @brief Add complex number * @brief Add complex number
* *
* @see operator+=() * @see @ref operator+=(const Complex<T>&)
*/ */
Complex<T> operator+(const Complex<T>& other) const { Complex<T> operator+(const Complex<T>& other) const {
return Complex<T>(*this) += other; return Complex<T>(*this) += other;
@ -258,7 +263,7 @@ template<class T> class Complex {
/** /**
* @brief Subtract complex number * @brief Subtract complex number
* *
* @see operator-=() * @see @ref operator-=(const Complex<T>&)
*/ */
Complex<T> operator-(const Complex<T>& other) const { Complex<T> operator-(const Complex<T>& other) const {
return Complex<T>(*this) -= other; return Complex<T>(*this) -= other;
@ -280,7 +285,7 @@ template<class T> class Complex {
/** /**
* @brief Multiply with scalar * @brief Multiply with scalar
* *
* @see operator*=(T) * @see @ref operator*=(T)
*/ */
Complex<T> operator*(T scalar) const { Complex<T> operator*(T scalar) const {
return Complex<T>(*this) *= scalar; return Complex<T>(*this) *= scalar;
@ -302,7 +307,7 @@ template<class T> class Complex {
/** /**
* @brief Divide with scalar * @brief Divide with scalar
* *
* @see operator/=(T) * @see @ref operator/=(T)
*/ */
Complex<T> operator/(T scalar) const { Complex<T> operator/(T scalar) const {
return Complex<T>(*this) /= scalar; return Complex<T>(*this) /= scalar;
@ -323,11 +328,12 @@ template<class T> class Complex {
/** /**
* @brief Dot product of the complex number * @brief Dot product of the complex number
* *
* Should be used instead of length() for comparing complex number length * Should be used instead of @ref length() for comparing complex number
* with other values, because it doesn't compute the square root. @f[ * length with other values, because it doesn't compute the square
* root. @f[
* c \cdot c = a^2 + b^2 * c \cdot c = a^2 + b^2
* @f] * @f]
* @see dot(const Complex&, const Complex&), isNormalized() * @see @ref dot(const Complex&, const Complex&), @ref isNormalized()
*/ */
T dot() const { T dot() const {
return dot(*this, *this); return dot(*this, *this);
@ -336,11 +342,11 @@ template<class T> class Complex {
/** /**
* @brief %Complex number length * @brief %Complex number length
* *
* See also dot() const which is faster for comparing length with other * See also @ref dot() const which is faster for comparing length with
* values. @f[ * other values. @f[
* |c| = \sqrt{c \cdot c} * |c| = \sqrt{c \cdot c}
* @f] * @f]
* @see isNormalized() * @see @ref isNormalized()
*/ */
T length() const { T length() const {
/** @todo Remove when newlib has this fixed */ /** @todo Remove when newlib has this fixed */
@ -354,7 +360,7 @@ template<class T> class Complex {
/** /**
* @brief Normalized complex number (of unit length) * @brief Normalized complex number (of unit length)
* *
* @see isNormalized() * @see @ref isNormalized()
*/ */
Complex<T> normalized() const { Complex<T> normalized() const {
return (*this)/length(); return (*this)/length();
@ -374,7 +380,7 @@ template<class T> class Complex {
/** /**
* @brief Inverted complex number * @brief Inverted complex number
* *
* See invertedNormalized() which is faster for normalized * See @ref invertedNormalized() which is faster for normalized
* complex numbers. @f[ * complex numbers. @f[
* c^{-1} = \frac{c^*}{|c|^2} = \frac{c^*}{c \cdot c} * c^{-1} = \frac{c^*}{|c|^2} = \frac{c^*}{c \cdot c}
* @f] * @f]
@ -386,11 +392,11 @@ template<class T> class Complex {
/** /**
* @brief Inverted normalized complex number * @brief Inverted normalized complex number
* *
* Equivalent to conjugated(). Expects that the complex number is * Equivalent to @ref conjugated(). Expects that the complex number is
* normalized. @f[ * normalized. @f[
* c^{-1} = \frac{c^*}{c \cdot c} = c^* * c^{-1} = \frac{c^*}{c \cdot c} = c^*
* @f] * @f]
* @see isNormalized(), inverted() * @see @ref isNormalized(), @ref inverted()
*/ */
Complex<T> invertedNormalized() const { Complex<T> invertedNormalized() const {
CORRADE_ASSERT(isNormalized(), CORRADE_ASSERT(isNormalized(),
@ -405,7 +411,9 @@ template<class T> class Complex {
* @f[ * @f[
* v' = c v = c (v_x + iv_y) * v' = c v = c (v_x + iv_y)
* @f] * @f]
* @see Complex(const Vector2&), operator Vector2(), Matrix3::transformVector() * @see @ref Complex(const Vector2<T>&), operator Vector2(),
* @ref Matrix3::transformVector()
* @todoc Explicit reference when Doxygen can handle conversion operators
*/ */
Vector2<T> transformVector(const Vector2<T>& vector) const { Vector2<T> transformVector(const Vector2<T>& vector) const {
return Vector2<T>((*this)*Complex<T>(vector)); return Vector2<T>((*this)*Complex<T>(vector));
@ -418,7 +426,7 @@ template<class T> class Complex {
/** @relates Complex /** @relates Complex
@brief Multiply scalar with complex @brief Multiply scalar with complex
Same as Complex::operator*(T) const. Same as @ref Complex::operator*(T) const.
*/ */
template<class T> inline Complex<T> operator*(T scalar, const Complex<T>& complex) { template<class T> inline Complex<T> operator*(T scalar, const Complex<T>& complex) {
return complex*scalar; return complex*scalar;
@ -430,7 +438,7 @@ template<class T> inline Complex<T> operator*(T scalar, const Complex<T>& comple
@f[ @f[
\frac t c = \frac t a + i \frac t b \frac t c = \frac t a + i \frac t b
@f] @f]
@see Complex::operator/() @see @ref Complex::operator/()
*/ */
template<class T> inline Complex<T> operator/(T scalar, const Complex<T>& complex) { template<class T> inline Complex<T> operator/(T scalar, const Complex<T>& complex) {
return {scalar/complex.real(), scalar/complex.imaginary()}; return {scalar/complex.real(), scalar/complex.imaginary()};

6
src/Magnum/Math/Constants.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Constants * @brief Class @ref Magnum::Math::Constants
*/ */
#include "Magnum/Types.h" #include "Magnum/Types.h"
@ -36,7 +36,7 @@ namespace Magnum { namespace Math {
/** /**
@brief Numeric constants @brief Numeric constants
@see Magnum::Constants, Magnum::Constantsd @see @ref Magnum::Constants, @ref Magnum::Constantsd
*/ */
template<class T> struct Constants { template<class T> struct Constants {
Constants() = delete; Constants() = delete;
@ -46,7 +46,7 @@ template<class T> struct Constants {
/** /**
* @brief Pi * @brief Pi
* *
* @see Deg, Rad * @see @ref Deg, @ref Rad
*/ */
static constexpr T pi(); static constexpr T pi();

8
src/Magnum/Math/Dual.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Dual * @brief Class @ref Magnum::Math::Dual
*/ */
#include <cmath> #include <cmath>
@ -95,7 +95,7 @@ template<class T> class Dual {
/** /**
* @brief Add dual number * @brief Add dual number
* *
* @see operator+=() * @see @ref operator+=()
*/ */
Dual<T> operator+(const Dual<T>& other) const { Dual<T> operator+(const Dual<T>& other) const {
return Dual<T>(*this)+=other; return Dual<T>(*this)+=other;
@ -128,7 +128,7 @@ template<class T> class Dual {
/** /**
* @brief Subtract dual number * @brief Subtract dual number
* *
* @see operator-=() * @see @ref operator-=()
*/ */
Dual<T> operator-(const Dual<T>& other) const { Dual<T> operator-(const Dual<T>& other) const {
return Dual<T>(*this)-=other; return Dual<T>(*this)-=other;
@ -213,7 +213,7 @@ template<class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug deb
@f[ @f[
\sqrt{\hat a} = \sqrt{a_0} + \epsilon \frac{a_\epsilon}{2 \sqrt{a_0}} \sqrt{\hat a} = \sqrt{a_0} + \epsilon \frac{a_\epsilon}{2 \sqrt{a_0}}
@f] @f]
@see Math::sqrt(const T&) @see @ref Math::sqrt(const T&)
*/ */
template<class T> Dual<T> sqrt(const Dual<T>& dual) { template<class T> Dual<T> sqrt(const Dual<T>& dual) {
T sqrt0 = std::sqrt(dual.real()); T sqrt0 = std::sqrt(dual.real());

49
src/Magnum/Math/DualComplex.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::DualComplex * @brief Class @ref Magnum::Math::DualComplex
*/ */
#include "Magnum/Math/Complex.h" #include "Magnum/Math/Complex.h"
@ -41,7 +41,8 @@ namespace Magnum { namespace Math {
Represents 2D rotation and translation. See @ref transformations for brief Represents 2D rotation and translation. See @ref transformations for brief
introduction. introduction.
@see Magnum::DualComplex, Magnum::DualComplexd, Dual, Complex, Matrix3 @see @ref Magnum::DualComplex, @ref Magnum::DualComplexd, @ref Dual,
@ref Complex, @ref Matrix3
@todo Can this be done similarly as in dual quaternions? It sort of works, but @todo Can this be done similarly as in dual quaternions? It sort of works, but
the math beneath is weird. the math beneath is weird.
*/ */
@ -56,8 +57,8 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* @f[ * @f[
* \hat c = (cos \theta + i sin \theta) + \epsilon (0 + i0) * \hat c = (cos \theta + i sin \theta) + \epsilon (0 + i0)
* @f] * @f]
* @see angle(), Complex::rotation(), Matrix3::rotation(), * @see @ref Complex::rotation(), @ref Matrix3::rotation(),
* DualQuaternion::rotation() * @ref DualQuaternion::rotation()
*/ */
static DualComplex<T> rotation(Rad<T> angle) { static DualComplex<T> rotation(Rad<T> angle) {
return {Complex<T>::rotation(angle), {{}, {}}}; return {Complex<T>::rotation(angle), {{}, {}}};
@ -70,8 +71,11 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* @f[ * @f[
* \hat c = (0 + i1) + \epsilon (v_x + iv_y) * \hat c = (0 + i1) + \epsilon (v_x + iv_y)
* @f] * @f]
* @see translation() const, Matrix3::translation(const Vector2&), * @see translation() const,
* DualQuaternion::translation(), Vector2::xAxis(), Vector2::yAxis() * @ref Matrix3::translation(const Vector2<T>&),
* @ref DualQuaternion::translation(), @ref Vector2::xAxis(),
* @ref Vector2::yAxis()
* @todoc Explicit reference when Doxygen can handle const
*/ */
static DualComplex<T> translation(const Vector2<T>& vector) { static DualComplex<T> translation(const Vector2<T>& vector) {
return {{}, {vector.x(), vector.y()}}; return {{}, {vector.x(), vector.y()}};
@ -81,8 +85,8 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* @brief Create dual complex number from rotation matrix * @brief Create dual complex number from rotation matrix
* *
* Expects that the matrix represents rigid transformation. * Expects that the matrix represents rigid transformation.
* @see toMatrix(), Complex::fromMatrix(), * @see @ref toMatrix(), @ref Complex::fromMatrix(),
* Matrix3::isRigidTransformation() * @ref Matrix3::isRigidTransformation()
*/ */
static DualComplex<T> fromMatrix(const Matrix3<T>& matrix) { static DualComplex<T> fromMatrix(const Matrix3<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(), CORRADE_ASSERT(matrix.isRigidTransformation(),
@ -96,7 +100,6 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* Creates unit dual complex number. @f[ * Creates unit dual complex number. @f[
* \hat c = (0 + i1) + \epsilon (0 + i0) * \hat c = (0 + i1) + \epsilon (0 + i0)
* @f] * @f]
* @todoc Remove workaround when Doxygen is predictable
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr /*implicit*/ DualComplex(); constexpr /*implicit*/ DualComplex();
@ -119,7 +122,6 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* To be used in transformations later. @f[ * To be used in transformations later. @f[
* \hat c = (0 + i1) + \epsilon(v_x + iv_y) * \hat c = (0 + i1) + \epsilon(v_x + iv_y)
* @f] * @f]
* @todoc Remove workaround when Doxygen is predictable
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr explicit DualComplex(const Vector2<T>& vector); constexpr explicit DualComplex(const Vector2<T>& vector);
@ -136,7 +138,7 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* Dual complex number is normalized if its real part has unit length: @f[ * Dual complex number is normalized if its real part has unit length: @f[
* |c_0|^2 = |c_0| = 1 * |c_0|^2 = |c_0| = 1
* @f] * @f]
* @see Complex::dot(), normalized() * @see @ref Complex::dot(), @ref normalized()
* @todoc Improve the equation as in Complex::isNormalized() * @todoc Improve the equation as in Complex::isNormalized()
*/ */
bool isNormalized() const { bool isNormalized() const {
@ -146,7 +148,7 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
/** /**
* @brief Rotation part of dual complex number * @brief Rotation part of dual complex number
* *
* @see Complex::angle() * @see @ref Complex::angle()
*/ */
constexpr Complex<T> rotation() const { constexpr Complex<T> rotation() const {
return Dual<Complex<T>>::real(); return Dual<Complex<T>>::real();
@ -158,7 +160,7 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* @f[ * @f[
* \boldsymbol a = (c_\epsilon c_0^*) * \boldsymbol a = (c_\epsilon c_0^*)
* @f] * @f]
* @see translation(const Vector2&) * @see @ref translation(const Vector2<T>&)
*/ */
Vector2<T> translation() const { Vector2<T> translation() const {
return Vector2<T>(Dual<Complex<T>>::dual()); return Vector2<T>(Dual<Complex<T>>::dual());
@ -167,7 +169,7 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
/** /**
* @brief Convert dual complex number to transformation matrix * @brief Convert dual complex number to transformation matrix
* *
* @see fromMatrix(), Complex::toMatrix() * @see @ref fromMatrix(), @ref Complex::toMatrix()
*/ */
Matrix3<T> toMatrix() const { Matrix3<T> toMatrix() const {
return Matrix3<T>::from(Dual<Complex<T>>::real().toMatrix(), translation()); return Matrix3<T>::from(Dual<Complex<T>>::real().toMatrix(), translation());
@ -191,7 +193,8 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* @f[ * @f[
* \hat c^* = c^*_0 + c^*_\epsilon * \hat c^* = c^*_0 + c^*_\epsilon
* @f] * @f]
* @see dualConjugated(), conjugated(), Complex::conjugated() * @see @ref dualConjugated(), @ref conjugated(),
* @ref Complex::conjugated()
*/ */
DualComplex<T> complexConjugated() const { DualComplex<T> complexConjugated() const {
return {Dual<Complex<T>>::real().conjugated(), Dual<Complex<T>>::dual().conjugated()}; return {Dual<Complex<T>>::real().conjugated(), Dual<Complex<T>>::dual().conjugated()};
@ -203,7 +206,8 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* @f[ * @f[
* \overline{\hat c} = c_0 - \epsilon c_\epsilon * \overline{\hat c} = c_0 - \epsilon c_\epsilon
* @f] * @f]
* @see complexConjugated(), conjugated(), Dual::conjugated() * @see @ref complexConjugated(), @ref conjugated(),
* @ref Dual::conjugated()
*/ */
DualComplex<T> dualConjugated() const { DualComplex<T> dualConjugated() const {
return Dual<Complex<T>>::conjugated(); return Dual<Complex<T>>::conjugated();
@ -215,8 +219,8 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* Both complex and dual conjugation. @f[ * Both complex and dual conjugation. @f[
* \overline{\hat c^*} = c^*_0 - \epsilon c^*_\epsilon = c^*_0 + \epsilon(-a_\epsilon + ib_\epsilon) * \overline{\hat c^*} = c^*_0 - \epsilon c^*_\epsilon = c^*_0 + \epsilon(-a_\epsilon + ib_\epsilon)
* @f] * @f]
* @see complexConjugated(), dualConjugated(), Complex::conjugated(), * @see @ref complexConjugated(), @ref dualConjugated(),
* Dual::conjugated() * @ref Complex::conjugated(), @ref Dual::conjugated()
*/ */
DualComplex<T> conjugated() const { DualComplex<T> conjugated() const {
return {Dual<Complex<T>>::real().conjugated(), {-Dual<Complex<T>>::dual().real(), Dual<Complex<T>>::dual().imaginary()}}; return {Dual<Complex<T>>::real().conjugated(), {-Dual<Complex<T>>::dual().real(), Dual<Complex<T>>::dual().imaginary()}};
@ -254,7 +258,7 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* @f[ * @f[
* c' = \frac{c_0}{|c_0|} * c' = \frac{c_0}{|c_0|}
* @f] * @f]
* @see isNormalized() * @see @ref isNormalized()
* @todo can this be done similarly to dual quaternions? * @todo can this be done similarly to dual quaternions?
*/ */
DualComplex<T> normalized() const { DualComplex<T> normalized() const {
@ -280,7 +284,7 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* Expects that the complex number is normalized. @f[ * Expects that the complex number is normalized. @f[
* \hat c^{-1} = c_0^{-1} - \epsilon c_\epsilon = c_0^* - \epsilon c_\epsilon * \hat c^{-1} = c_0^{-1} - \epsilon c_\epsilon = c_0^* - \epsilon c_\epsilon
* @f] * @f]
* @see isNormalized(), inverted() * @see @ref isNormalized(), @ref inverted()
* @todo can this be done similarly to dual quaternions? * @todo can this be done similarly to dual quaternions?
*/ */
DualComplex<T> invertedNormalized() const { DualComplex<T> invertedNormalized() const {
@ -294,8 +298,9 @@ template<class T> class DualComplex: public Dual<Complex<T>> {
* complex number. @f[ * complex number. @f[
* v' = \hat c v = \hat c ((0 + i) + \epsilon(v_x + iv_y)) * v' = \hat c v = \hat c ((0 + i) + \epsilon(v_x + iv_y))
* @f] * @f]
* @see DualComplex(const Vector2&), dual(), Matrix3::transformPoint(), * @see @ref DualComplex(const Vector2<T>&), @ref dual(),
* Complex::transformVector(), DualQuaternion::transformPoint() * @ref Matrix3::transformPoint(), @ref Complex::transformVector(),
* @ref DualQuaternion::transformPoint()
*/ */
Vector2<T> transformPoint(const Vector2<T>& vector) const { Vector2<T> transformPoint(const Vector2<T>& vector) const {
return Vector2<T>(((*this)*DualComplex<T>(vector)).dual()); return Vector2<T>(((*this)*DualComplex<T>(vector)).dual());

83
src/Magnum/Math/DualQuaternion.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::DualQuaternion * @brief Class @ref Magnum::Math::DualQuaternion
*/ */
#include "Magnum/Math/Dual.h" #include "Magnum/Math/Dual.h"
@ -41,7 +41,8 @@ namespace Magnum { namespace Math {
Represents 3D rotation and translation. See @ref transformations for brief Represents 3D rotation and translation. See @ref transformations for brief
introduction. introduction.
@see Magnum::DualQuaternion, Magnum::DualQuaterniond, Dual, Quaternion, Matrix4 @see @ref Magnum::DualQuaternion, @ref Magnum::DualQuaterniond, @ref Dual,
@ref Quaternion, @ref Matrix4
*/ */
template<class T> class DualQuaternion: public Dual<Quaternion<T>> { template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
public: public:
@ -55,9 +56,11 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* Expects that the rotation axis is normalized. @f[ * Expects that the rotation axis is normalized. @f[
* \hat q = [\boldsymbol a \cdot sin \frac \theta 2, cos \frac \theta 2] + \epsilon [\boldsymbol 0, 0] * \hat q = [\boldsymbol a \cdot sin \frac \theta 2, cos \frac \theta 2] + \epsilon [\boldsymbol 0, 0]
* @f] * @f]
* @see rotation() const, Quaternion::rotation(), Matrix4::rotation(), * @see rotation() const, @ref Quaternion::rotation(),
* DualComplex::rotation(), Vector3::xAxis(), Vector3::yAxis(), * @ref Matrix4::rotation(), @ref DualComplex::rotation(),
* Vector3::zAxis(), Vector::isNormalized() * @ref Vector3::xAxis(), @ref Vector3::yAxis(),
* @ref Vector3::zAxis(), @ref Vector::isNormalized()
* @todoc Explicit reference when Doxygen can handle const
*/ */
static DualQuaternion<T> rotation(Rad<T> angle, const Vector3<T>& normalizedAxis) { static DualQuaternion<T> rotation(Rad<T> angle, const Vector3<T>& normalizedAxis) {
return {Quaternion<T>::rotation(angle, normalizedAxis), {{}, T(0)}}; return {Quaternion<T>::rotation(angle, normalizedAxis), {{}, T(0)}};
@ -72,9 +75,11 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* @f[ * @f[
* \hat q = [\boldsymbol 0, 1] + \epsilon [\frac{\boldsymbol v}{2}, 0] * \hat q = [\boldsymbol 0, 1] + \epsilon [\frac{\boldsymbol v}{2}, 0]
* @f] * @f]
* @see translation() const, Matrix4::translation(const Vector3&), * @see translation() const,
* DualComplex::translation(), Vector3::xAxis(), Vector3::yAxis(), * @ref Matrix4::translation(const Vector3<T>&),
* Vector3::zAxis() * @ref DualComplex::translation(), @ref Vector3::xAxis(),
* @ref Vector3::yAxis(), @ref Vector3::zAxis()
* @todoc Explicit reference when Doxygen can handle const
*/ */
static DualQuaternion<T> translation(const Vector3<T>& vector) { static DualQuaternion<T> translation(const Vector3<T>& vector) {
return {{}, {vector/T(2), T(0)}}; return {{}, {vector/T(2), T(0)}};
@ -84,8 +89,8 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* @brief Create dual quaternion from transformation matrix * @brief Create dual quaternion from transformation matrix
* *
* Expects that the matrix represents rigid transformation. * Expects that the matrix represents rigid transformation.
* @see toMatrix(), Quaternion::fromMatrix(), * @see @ref toMatrix(), @ref Quaternion::fromMatrix(),
* Matrix4::isRigidTransformation() * @ref Matrix4::isRigidTransformation()
*/ */
static DualQuaternion<T> fromMatrix(const Matrix4<T>& matrix) { static DualQuaternion<T> fromMatrix(const Matrix4<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(), CORRADE_ASSERT(matrix.isRigidTransformation(),
@ -101,7 +106,6 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* Creates unit dual quaternion. @f[ * Creates unit dual quaternion. @f[
* \hat q = [\boldsymbol 0, 1] + \epsilon [\boldsymbol 0, 0] * \hat q = [\boldsymbol 0, 1] + \epsilon [\boldsymbol 0, 0]
* @f] * @f]
* @todoc Remove workaround when Doxygen is predictable
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr /*implicit*/ DualQuaternion(); constexpr /*implicit*/ DualQuaternion();
@ -124,8 +128,7 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* To be used in transformations later. @f[ * To be used in transformations later. @f[
* \hat q = [\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0] * \hat q = [\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]
* @f] * @f]
* @see transformPointNormalized() * @see @ref transformPointNormalized()
* @todoc Remove workaround when Doxygen is predictable
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
constexpr explicit DualQuaternion(const Vector3<T>& vector); constexpr explicit DualQuaternion(const Vector3<T>& vector);
@ -142,7 +145,7 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* Dual quaternion is normalized if it has unit length: @f[ * Dual quaternion is normalized if it has unit length: @f[
* |\hat q|^2 = |\hat q| = 1 + \epsilon 0 * |\hat q|^2 = |\hat q| = 1 + \epsilon 0
* @f] * @f]
* @see lengthSquared(), normalized() * @see @ref lengthSquared(), @ref normalized()
* @todoc Improve the equation as in Quaternion::isNormalized() * @todoc Improve the equation as in Quaternion::isNormalized()
*/ */
bool isNormalized() const { bool isNormalized() const {
@ -156,7 +159,7 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/** /**
* @brief Rotation part of unit dual quaternion * @brief Rotation part of unit dual quaternion
* *
* @see Quaternion::angle(), Quaternion::axis() * @see @ref Quaternion::angle(), @ref Quaternion::axis()
*/ */
constexpr Quaternion<T> rotation() const { constexpr Quaternion<T> rotation() const {
return Dual<Quaternion<T>>::real(); return Dual<Quaternion<T>>::real();
@ -168,7 +171,7 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* @f[ * @f[
* \boldsymbol a = 2 (q_\epsilon q_0^*)_V * \boldsymbol a = 2 (q_\epsilon q_0^*)_V
* @f] * @f]
* @see translation(const Vector3&) * @see @ref translation(const Vector3<T>&)
*/ */
Vector3<T> translation() const { Vector3<T> translation() const {
return (Dual<Quaternion<T>>::dual()*Dual<Quaternion<T>>::real().conjugated()).vector()*T(2); return (Dual<Quaternion<T>>::dual()*Dual<Quaternion<T>>::real().conjugated()).vector()*T(2);
@ -177,7 +180,7 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/** /**
* @brief Convert dual quaternion to transformation matrix * @brief Convert dual quaternion to transformation matrix
* *
* @see fromMatrix(), Quaternion::toMatrix() * @see @ref fromMatrix(), @ref Quaternion::toMatrix()
*/ */
Matrix4<T> toMatrix() const { Matrix4<T> toMatrix() const {
return Matrix4<T>::from(Dual<Quaternion<T>>::real().toMatrix(), translation()); return Matrix4<T>::from(Dual<Quaternion<T>>::real().toMatrix(), translation());
@ -189,7 +192,8 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* @f[ * @f[
* \hat q^* = q_0^* + q_\epsilon^* * \hat q^* = q_0^* + q_\epsilon^*
* @f] * @f]
* @see dualConjugated(), conjugated(), Quaternion::conjugated() * @see @ref dualConjugated(), @ref conjugated(),
* @ref Quaternion::conjugated()
*/ */
DualQuaternion<T> quaternionConjugated() const { DualQuaternion<T> quaternionConjugated() const {
return {Dual<Quaternion<T>>::real().conjugated(), Dual<Quaternion<T>>::dual().conjugated()}; return {Dual<Quaternion<T>>::real().conjugated(), Dual<Quaternion<T>>::dual().conjugated()};
@ -201,7 +205,8 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* @f[ * @f[
* \overline{\hat q} = q_0 - \epsilon q_\epsilon * \overline{\hat q} = q_0 - \epsilon q_\epsilon
* @f] * @f]
* @see quaternionConjugated(), conjugated(), Dual::conjugated() * @see @ref quaternionConjugated(), @ref conjugated(),
* @ref Dual::conjugated()
*/ */
DualQuaternion<T> dualConjugated() const { DualQuaternion<T> dualConjugated() const {
return Dual<Quaternion<T>>::conjugated(); return Dual<Quaternion<T>>::conjugated();
@ -213,8 +218,8 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
* Both quaternion and dual conjugation. @f[ * Both quaternion and dual conjugation. @f[
* \overline{\hat q^*} = q_0^* - \epsilon q_\epsilon^* = q_0^* + \epsilon [\boldsymbol q_{V \epsilon}, -q_{S \epsilon}] * \overline{\hat q^*} = q_0^* - \epsilon q_\epsilon^* = q_0^* + \epsilon [\boldsymbol q_{V \epsilon}, -q_{S \epsilon}]
* @f] * @f]
* @see quaternionConjugated(), dualConjugated(), Quaternion::conjugated(), * @see @ref quaternionConjugated(), @ref dualConjugated(),
* Dual::conjugated() * @ref Quaternion::conjugated(), @ref Dual::conjugated()
*/ */
DualQuaternion<T> conjugated() const { DualQuaternion<T> conjugated() const {
return {Dual<Quaternion<T>>::real().conjugated(), {Dual<Quaternion<T>>::dual().vector(), -Dual<Quaternion<T>>::dual().scalar()}}; return {Dual<Quaternion<T>>::real().conjugated(), {Dual<Quaternion<T>>::dual().vector(), -Dual<Quaternion<T>>::dual().scalar()}};
@ -223,8 +228,9 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/** /**
* @brief %Dual quaternion length squared * @brief %Dual quaternion length squared
* *
* Should be used instead of length() for comparing dual quaternion * Should be used instead of @ref length() for comparing dual
* length with other values, because it doesn't compute the square root. @f[ * quaternion length with other values, because it doesn't compute the
* square root. @f[
* |\hat q|^2 = \sqrt{\hat q^* \hat q}^2 = q_0 \cdot q_0 + \epsilon 2 (q_0 \cdot q_\epsilon) * |\hat q|^2 = \sqrt{\hat q^* \hat q}^2 = q_0 \cdot q_0 + \epsilon 2 (q_0 \cdot q_\epsilon)
* @f] * @f]
*/ */
@ -235,7 +241,7 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/** /**
* @brief %Dual quaternion length * @brief %Dual quaternion length
* *
* See lengthSquared() which is faster for comparing length with other * See @ref lengthSquared() which is faster for comparing length with other
* values. @f[ * values. @f[
* |\hat q| = \sqrt{\hat q^* \hat q} = |q_0| + \epsilon \frac{q_0 \cdot q_\epsilon}{|q_0|} * |\hat q| = \sqrt{\hat q^* \hat q} = |q_0| + \epsilon \frac{q_0 \cdot q_\epsilon}{|q_0|}
* @f] * @f]
@ -247,7 +253,7 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/** /**
* @brief Normalized dual quaternion (of unit length) * @brief Normalized dual quaternion (of unit length)
* *
* @see isNormalized() * @see @ref isNormalized()
*/ */
DualQuaternion<T> normalized() const { DualQuaternion<T> normalized() const {
return (*this)/length(); return (*this)/length();
@ -256,7 +262,7 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/** /**
* @brief Inverted dual quaternion * @brief Inverted dual quaternion
* *
* See invertedNormalized() which is faster for normalized dual * See @ref invertedNormalized() which is faster for normalized dual
* quaternions. @f[ * quaternions. @f[
* \hat q^{-1} = \frac{\hat q^*}{|\hat q|^2} * \hat q^{-1} = \frac{\hat q^*}{|\hat q|^2}
* @f] * @f]
@ -268,11 +274,11 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/** /**
* @brief Inverted normalized dual quaternion * @brief Inverted normalized dual quaternion
* *
* Equivalent to quaternionConjugated(). Expects that the quaternion is * Equivalent to @ref quaternionConjugated(). Expects that the
* normalized. @f[ * quaternion is normalized. @f[
* \hat q^{-1} = \frac{\hat q^*}{|\hat q|^2} = \hat q^* * \hat q^{-1} = \frac{\hat q^*}{|\hat q|^2} = \hat q^*
* @f] * @f]
* @see isNormalized(), inverted() * @see @ref isNormalized(), @ref inverted()
*/ */
DualQuaternion<T> invertedNormalized() const { DualQuaternion<T> invertedNormalized() const {
CORRADE_ASSERT(isNormalized(), CORRADE_ASSERT(isNormalized(),
@ -283,12 +289,14 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/** /**
* @brief Rotate and translate point with dual quaternion * @brief Rotate and translate point with dual quaternion
* *
* See transformPointNormalized(), which is faster for normalized dual * See @ref transformPointNormalized(), which is faster for normalized
* quaternions. @f[ * dual quaternions. @f[
* v' = \hat q v \overline{\hat q^{-1}} = \hat q ([\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]) \overline{\hat q^{-1}} * v' = \hat q v \overline{\hat q^{-1}} = \hat q ([\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]) \overline{\hat q^{-1}}
* @f] * @f]
* @see DualQuaternion(const Vector3&), dual(), Matrix4::transformPoint(), * @see @ref DualQuaternion(const Vector3<T>&), @ref dual(),
* Quaternion::transformVector(), DualComplex::transformPoint() * @ref Matrix4::transformPoint(),
* @ref Quaternion::transformVector(),
* @ref DualComplex::transformPoint()
*/ */
Vector3<T> transformPoint(const Vector3<T>& vector) const { Vector3<T> transformPoint(const Vector3<T>& vector) const {
return ((*this)*DualQuaternion<T>(vector)*inverted().dualConjugated()).dual().vector(); return ((*this)*DualQuaternion<T>(vector)*inverted().dualConjugated()).dual().vector();
@ -297,13 +305,14 @@ template<class T> class DualQuaternion: public Dual<Quaternion<T>> {
/** /**
* @brief Rotate and translate point with normalized dual quaternion * @brief Rotate and translate point with normalized dual quaternion
* *
* Faster alternative to transformPoint(), expects that the dual * Faster alternative to @ref transformPoint(), expects that the dual
* quaternion is normalized. @f[ * quaternion is normalized. @f[
* v' = \hat q v \overline{\hat q^{-1}} = \hat q v \overline{\hat q^*} = \hat q ([\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]) \overline{\hat q^*} * v' = \hat q v \overline{\hat q^{-1}} = \hat q v \overline{\hat q^*} = \hat q ([\boldsymbol 0, 1] + \epsilon [\boldsymbol v, 0]) \overline{\hat q^*}
* @f] * @f]
* @see isNormalized(), DualQuaternion(const Vector3&), dual(), * @see @ref isNormalized(), @ref DualQuaternion(const Vector3<T>&),
* Matrix4::transformPoint(), Quaternion::transformVectorNormalized(), * @ref dual(), @ref Matrix4::transformPoint(),
* DualComplex::transformPointNormalized() * @ref Quaternion::transformVectorNormalized(),
* @ref DualComplex::transformPoint()
*/ */
Vector3<T> transformPointNormalized(const Vector3<T>& vector) const { Vector3<T> transformPointNormalized(const Vector3<T>& vector) const {
CORRADE_ASSERT(isNormalized(), CORRADE_ASSERT(isNormalized(),

14
src/Magnum/Math/Functions.h

@ -68,7 +68,7 @@ template<UnsignedInt exponent, class T> constexpr T pow(T base) {
* @brief Base-2 integral logarithm * @brief Base-2 integral logarithm
* *
* Returns integral logarithm of given number with base `2`. * Returns integral logarithm of given number with base `2`.
* @see log() * @see @ref log()
*/ */
UnsignedInt MAGNUM_EXPORT log2(UnsignedInt number); UnsignedInt MAGNUM_EXPORT log2(UnsignedInt number);
@ -76,7 +76,7 @@ UnsignedInt MAGNUM_EXPORT log2(UnsignedInt number);
* @brief Integral logarithm * @brief Integral logarithm
* *
* Returns integral logarithm of given number with given base. * Returns integral logarithm of given number with given base.
* @see log2() * @see @ref log2()
*/ */
UnsignedInt MAGNUM_EXPORT log(UnsignedInt base, UnsignedInt number); UnsignedInt MAGNUM_EXPORT log(UnsignedInt base, UnsignedInt number);
@ -290,7 +290,7 @@ template<std::size_t size, class T> Vector<size, T> ceil(const Vector<size, T>&
/** /**
@brief Square root @brief Square root
@see sqrtInverted(), Vector::length() @see @ref sqrtInverted(), @ref Vector::length()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T sqrt(const T& a); template<class T> inline T sqrt(const T& a);
@ -309,7 +309,7 @@ template<std::size_t size, class T> Vector<size, T> sqrt(const Vector<size, T>&
/** /**
@brief Inverse square root @brief Inverse square root
@see sqrt(), Vector::lengthInverted() @see @ref sqrt(), @ref Vector::lengthInverted()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T sqrtInverted(const T& a); template<class T> inline T sqrtInverted(const T& a);
@ -327,7 +327,7 @@ template<std::size_t size, class T> Vector<size, T> sqrtInverted(const Vector<si
Values smaller than @p min are set to @p min, values larger than @p max are Values smaller than @p min are set to @p min, values larger than @p max are
set to @p max. set to @p max.
@see min(), max() @see @ref min(), @ref max()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
template<class T, class U> inline T clamp(const T& value, U min, U max); template<class T, class U> inline T clamp(const T& value, U min, U max);
@ -352,7 +352,7 @@ template<std::size_t size, class T> Vector<size, T> clamp(const Vector<size, T>&
The interpolation for vectors is done as in following, similarly for scalars: @f[ The interpolation for vectors is done as in following, similarly for scalars: @f[
\boldsymbol v_{LERP} = (1 - t) \boldsymbol v_A + t \boldsymbol v_B \boldsymbol v_{LERP} = (1 - t) \boldsymbol v_A + t \boldsymbol v_B
@f] @f]
@see lerpInverted(), Quaternion::lerp() @see @ref lerpInverted(), @ref Quaternion::lerp()
@todo http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ @todo http://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/
(when SIMD is in place) (when SIMD is in place)
*/ */
@ -376,7 +376,7 @@ template<std::size_t size, class T, class U> inline Vector<size, T> lerp(const V
Returns interpolation phase *t*: @f[ Returns interpolation phase *t*: @f[
t = \frac{\boldsymbol v_{LERP} - \boldsymbol v_A}{\boldsymbol v_B - \boldsymbol v_A} t = \frac{\boldsymbol v_{LERP} - \boldsymbol v_A}{\boldsymbol v_B - \boldsymbol v_A}
@f] @f]
@see lerp() @see @ref lerp()
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> inline T lerpInverted(const T& a, const T& b, const T& lerp); template<class T> inline T lerpInverted(const T& a, const T& b, const T& lerp);

53
src/Magnum/Math/Geometry/Distance.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Geometry::Distance * @brief Class @ref Magnum::Math::Geometry::Distance
*/ */
#include "Magnum/Math/Functions.h" #include "Magnum/Math/Functions.h"
@ -50,7 +50,7 @@ class Distance {
* d = \frac{|(\boldsymbol b - \boldsymbol a)_\bot \cdot (\boldsymbol a - \boldsymbol p)|} {|\boldsymbol b - \boldsymbol a|} * d = \frac{|(\boldsymbol b - \boldsymbol a)_\bot \cdot (\boldsymbol a - \boldsymbol p)|} {|\boldsymbol b - \boldsymbol a|}
* @f] * @f]
* Source: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html * Source: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
* @see linePointSquared(const Vector2&, const Vector2&, const Vector2&) * @see @ref linePointSquared(const Vector2<T>&, const Vector2<T>&, const Vector2<T>&)
*/ */
template<class T> static T linePoint(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point) { template<class T> static T linePoint(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point) {
const Vector2<T> bMinusA = b - a; const Vector2<T> bMinusA = b - a;
@ -63,7 +63,8 @@ class Distance {
* @param b Second point of the line * @param b Second point of the line
* @param point Point * @param point Point
* *
* More efficient than linePoint(const Vector2&, const Vector2&, const Vector2&) * More efficient than
* @ref linePoint(const Vector2<T>&, const Vector2<T>&, const Vector2<T>&)
* for comparing distance with other values, because it doesn't * for comparing distance with other values, because it doesn't
* compute the square root. * compute the square root.
*/ */
@ -84,7 +85,7 @@ class Distance {
* {|\boldsymbol b - \boldsymbol a|} * {|\boldsymbol b - \boldsymbol a|}
* @f] * @f]
* Source: http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html * Source: http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
* @see linePointSquared(const Vector3&, const Vector3&, const Vector3&) * @see @ref linePointSquared(const Vector3<T>&, const Vector3<T>&, const Vector3<T>&)
*/ */
template<class T> static T linePoint(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) { template<class T> static T linePoint(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) {
return std::sqrt(linePointSquared(a, b, point)); return std::sqrt(linePointSquared(a, b, point));
@ -93,7 +94,7 @@ class Distance {
/** /**
* @brief %Distance of line and point in 3D, squared * @brief %Distance of line and point in 3D, squared
* *
* More efficient than linePoint(const Vector3&, const Vector3&, const Vector3&) * More efficient than @ref linePoint(const Vector3<T>&, const Vector3<T>&, const Vector3<T>&)
* for comparing distance with other values, because it doesn't * for comparing distance with other values, because it doesn't
* compute the square root. * compute the square root.
*/ */
@ -121,19 +122,19 @@ class Distance {
* @f] * @f]
* The last alternative is when the following equation applies. The * The last alternative is when the following equation applies. The
* point then lies between **a** and **b** and the distance is * point then lies between **a** and **b** and the distance is
* computed the same way as in linePoint(). @f[ * computed the same way as in @ref linePoint(). @f[
* |\boldsymbol b - \boldsymbol a|^2 > |\boldsymbol p - \boldsymbol a|^2 + |\boldsymbol p - \boldsymbol b|^2 * |\boldsymbol b - \boldsymbol a|^2 > |\boldsymbol p - \boldsymbol a|^2 + |\boldsymbol p - \boldsymbol b|^2
* @f] * @f]
* *
* @see lineSegmentPointSquared() * @see @ref lineSegmentPointSquared()
*/ */
template<class T> static T lineSegmentPoint(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point); template<class T> static T lineSegmentPoint(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point);
/** /**
* @brief %Distance of point from line segment in 2D, squared * @brief %Distance of point from line segment in 2D, squared
* *
* More efficient than lineSegmentPoint() for comparing distance with * More efficient than @ref lineSegmentPoint() for comparing distance
* other values, because it doesn't compute the square root. * with other values, because it doesn't compute the square root.
*/ */
template<class T> static T lineSegmentPointSquared(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point); template<class T> static T lineSegmentPointSquared(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point);
@ -144,9 +145,9 @@ class Distance {
* @param point Point * @param point Point
* *
* Similar to 2D implementation * Similar to 2D implementation
* lineSegmentPoint(const Vector2&, const Vector2&, const Vector2&). * @ref lineSegmentPoint(const Vector2<T>&, const Vector2<T>&, const Vector2<T>&).
* *
* @see lineSegmentPointSquared(const Vector3&, const Vector3&, const Vector3&) * @see @ref lineSegmentPointSquared(const Vector3<T>&, const Vector3<T>&, const Vector3<T>&)
*/ */
template<class T> static T lineSegmentPoint(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) { template<class T> static T lineSegmentPoint(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) {
return std::sqrt(lineSegmentPointSquared(a, b, point)); return std::sqrt(lineSegmentPointSquared(a, b, point));
@ -155,19 +156,15 @@ class Distance {
/** /**
* @brief %Distance of point from line segment in 3D, squared * @brief %Distance of point from line segment in 3D, squared
* *
* More efficient than lineSegmentPoint(const Vector3&, const Vector3&, const Vector3&) for comparing distance with * More efficient than
* other values, because it doesn't compute the square root. * @ref lineSegmentPoint(const Vector3<T>&, const Vector3<T>&, const Vector3<T>&)
* for comparing distance with other values, because it doesn't compute
* the square root.
*/ */
template<class T> static T lineSegmentPointSquared(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point); template<class T> static T lineSegmentPointSquared(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point);
}; };
/** @todoc Remove workaround when Doxygen is sane */ template<class T> T Distance::lineSegmentPoint(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point) {
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> static
#else
template<class T>
#endif
T Distance::lineSegmentPoint(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point) {
const Vector2<T> pointMinusA = point - a; const Vector2<T> pointMinusA = point - a;
const Vector2<T> pointMinusB = point - b; const Vector2<T> pointMinusB = point - b;
const Vector2<T> bMinusA = b - a; const Vector2<T> bMinusA = b - a;
@ -187,13 +184,7 @@ T Distance::lineSegmentPoint(const Vector2<T>& a, const Vector2<T>& b, const Vec
return std::abs(Vector2<T>::cross(bMinusA, -pointMinusA))/std::sqrt(bDistanceA); return std::abs(Vector2<T>::cross(bMinusA, -pointMinusA))/std::sqrt(bDistanceA);
} }
/** @todoc Remove workaround when Doxygen is sane */ template<class T> T Distance::lineSegmentPointSquared(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point) {
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> static
#else
template<class T>
#endif
T Distance::lineSegmentPointSquared(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point) {
const Vector2<T> pointMinusA = point - a; const Vector2<T> pointMinusA = point - a;
const Vector2<T> pointMinusB = point - b; const Vector2<T> pointMinusB = point - b;
const Vector2<T> bMinusA = b - a; const Vector2<T> bMinusA = b - a;
@ -213,13 +204,7 @@ T Distance::lineSegmentPointSquared(const Vector2<T>& a, const Vector2<T>& b, co
return Math::pow<2>(Vector2<T>::cross(bMinusA, -pointMinusA))/bDistanceA; return Math::pow<2>(Vector2<T>::cross(bMinusA, -pointMinusA))/bDistanceA;
} }
/** @todoc Remove workaround when Doxygen is sane */ template<class T> T Distance::lineSegmentPointSquared(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) {
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> static
#else
template<class T>
#endif
T Distance::lineSegmentPointSquared(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) {
const Vector3<T> pointMinusA = point - a; const Vector3<T> pointMinusA = point - a;
const Vector3<T> pointMinusB = point - b; const Vector3<T> pointMinusB = point - b;
const T pointDistanceA = pointMinusA.dot(); const T pointDistanceA = pointMinusA.dot();

6
src/Magnum/Math/Geometry/Intersection.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Geometry::Intersection * @brief Class @ref Magnum::Math::Geometry::Intersection
*/ */
#include "Magnum/Math/Vector3.h" #include "Magnum/Math/Vector3.h"
@ -66,7 +66,7 @@ class Intersection {
* \end{array} * \end{array}
* @f] * @f]
* *
* See also lineSegmentLine() which computes only **t**, which is * See also @ref lineSegmentLine() which computes only **t**, which is
* useful if you don't need to test that the intersection lies inside * useful if you don't need to test that the intersection lies inside
* line segment defined by `q` and `q + s`. * line segment defined by `q` and `q + s`.
*/ */
@ -89,7 +89,7 @@ class Intersection {
* value is in range @f$ [ 0 ; 1 ] @f$, the intersection is inside * value is in range @f$ [ 0 ; 1 ] @f$, the intersection is inside
* the line segment defined by `p` and `p + r`. * the line segment defined by `p` and `p + r`.
* *
* Unlike lineSegmentLineSegment() computes only **t**. * Unlike @ref lineSegmentLineSegment() computes only **t**.
*/ */
template<class T> static T lineSegmentLine(const Vector2<T>& p, const Vector2<T>& r, const Vector2<T>& q, const Vector2<T>& s) { template<class T> static T lineSegmentLine(const Vector2<T>& p, const Vector2<T>& r, const Vector2<T>& q, const Vector2<T>& s) {
return Vector2<T>::cross(q - p, s)/Vector2<T>::cross(r, s); return Vector2<T>::cross(q - p, s)/Vector2<T>::cross(r, s);

2
src/Magnum/Math/Math.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Forward declarations for Magnum::Math namespace * @brief Forward declarations for @ref Magnum::Math namespace
*/ */
#include <cstddef> #include <cstddef>

26
src/Magnum/Math/Matrix.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Matrix * @brief Class @ref Magnum::Math::Matrix, typedef @ref Magnum::Math::Matrix2x2, @ref Magnum::Math::Matrix3x3, @ref Magnum::Math::Matrix4x4
*/ */
#include "Magnum/Math/RectangularMatrix.h" #include "Magnum/Math/RectangularMatrix.h"
@ -57,7 +57,7 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
/** /**
* @brief Zero-filled matrix constructor * @brief Zero-filled matrix constructor
* *
* Use this constructor by calling `Matrix m(Matrix::Zero);`. * Use this constructor by calling `%Matrix m(Matrix::Zero);`.
*/ */
constexpr explicit Matrix(ZeroType) {} constexpr explicit Matrix(ZeroType) {}
@ -68,7 +68,7 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
* @brief Default constructor * @brief Default constructor
* *
* You can also explicitly call this constructor with * You can also explicitly call this constructor with
* `Matrix m(Matrix::Identity);`. Optional parameter @p value allows * `%Matrix m(Matrix::Identity);`. Optional parameter @p value allows
* you to specify value on diagonal. * you to specify value on diagonal.
*/ */
constexpr /*implicit*/ Matrix(IdentityType = Identity, T value = T(1)): RectangularMatrix<size, size, T>(typename Implementation::GenerateSequence<size>::Type(), constexpr /*implicit*/ Matrix(IdentityType = Identity, T value = T(1)): RectangularMatrix<size, size, T>(typename Implementation::GenerateSequence<size>::Type(),
@ -117,8 +117,9 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
* The matrix is orthogonal if its transpose is equal to its inverse: @f[ * The matrix is orthogonal if its transpose is equal to its inverse: @f[
* Q^T = Q^{-1} * Q^T = Q^{-1}
* @f] * @f]
* @see transposed(), inverted(), Matrix3::isRigidTransformation(), * @see @ref transposed(), @ref inverted(),
* Matrix4::isRigidTransformation() * @ref Matrix3::isRigidTransformation(),
* @ref Matrix4::isRigidTransformation()
*/ */
bool isOrthogonal() const; bool isOrthogonal() const;
@ -140,7 +141,7 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
* Computed recursively using Laplace's formula: @f[ * Computed recursively using Laplace's formula: @f[
* \det(A) = \sum_{j=1}^n (-1)^{i+j} a_{i,j} \det(A^{i,j}) * \det(A) = \sum_{j=1}^n (-1)^{i+j} a_{i,j} \det(A^{i,j})
* @f] @f$ A^{i, j} @f$ is matrix without i-th row and j-th column, see * @f] @f$ A^{i, j} @f$ is matrix without i-th row and j-th column, see
* ij(). The formula is expanded down to 2x2 matrix, where the * @ref ij(). The formula is expanded down to 2x2 matrix, where the
* determinant is computed directly: @f[ * determinant is computed directly: @f[
* \det(A) = a_{0, 0} a_{1, 1} - a_{1, 0} a_{0, 1} * \det(A) = a_{0, 0} a_{1, 1} - a_{1, 0} a_{0, 1}
* @f] * @f]
@ -153,19 +154,22 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
* Computed using Cramer's rule: @f[ * Computed using Cramer's rule: @f[
* A^{-1} = \frac{1}{\det(A)} Adj(A) * A^{-1} = \frac{1}{\det(A)} Adj(A)
* @f] * @f]
* See invertedOrthogonal(), Matrix3::invertedRigid() and Matrix4::invertedRigid() * See @ref invertedOrthogonal(), @ref Matrix3::invertedRigid() and
* which are faster alternatives for particular matrix types. * @ref Matrix4::invertedRigid() which are faster alternatives for
* particular matrix types.
*/ */
Matrix<size, T> inverted() const; Matrix<size, T> inverted() const;
/** /**
* @brief Inverted orthogonal matrix * @brief Inverted orthogonal matrix
* *
* Equivalent to transposed(), expects that the matrix is orthogonal. @f[ * Equivalent to @ref transposed(), expects that the matrix is
* orthogonal. @f[
* A^{-1} = A^T * A^{-1} = A^T
* @f] * @f]
* @see inverted(), isOrthogonal(), Matrix3::invertedRigid(), * @see @ref inverted(), @ref isOrthogonal(),
* Matrix4::invertedRigid() * @ref Matrix3::invertedRigid(),
* @ref Matrix4::invertedRigid()
*/ */
Matrix<size, T> invertedOrthogonal() const { Matrix<size, T> invertedOrthogonal() const {
CORRADE_ASSERT(isOrthogonal(), CORRADE_ASSERT(isOrthogonal(),

97
src/Magnum/Math/Matrix3.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Matrix3 * @brief Class @ref Magnum::Math::Matrix3
*/ */
#include "Magnum/Math/Matrix.h" #include "Magnum/Math/Matrix.h"
@ -35,13 +35,12 @@
namespace Magnum { namespace Math { namespace Magnum { namespace Math {
/** /**
@brief 3x3 matrix @brief 2D transformation matrix
@tparam T Underlying data type @tparam T Underlying data type
Represents 2D transformation. See @ref matrix-vector and @ref transformations See @ref matrix-vector and @ref transformations for brief introduction.
for brief introduction. @see @ref Magnum::Matrix3, @ref Magnum::Matrix3d, @ref Matrix3x3,
@see Magnum::Matrix3, Magnum::Matrix3d, DualComplex, @ref DualComplex, @ref SceneGraph::MatrixTransformation2D
SceneGraph::MatrixTransformation2D
@configurationvalueref{Magnum::Math::Matrix3} @configurationvalueref{Magnum::Math::Matrix3}
*/ */
template<class T> class Matrix3: public Matrix<3, T> { template<class T> class Matrix3: public Matrix<3, T> {
@ -50,9 +49,10 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief 2D translation matrix * @brief 2D translation matrix
* @param vector Translation vector * @param vector Translation vector
* *
* @see translation(), DualComplex::translation(), * @see translation() const, @ref DualComplex::translation(),
* Matrix4::translation(const Vector3&), Vector2::xAxis(), * @ref Matrix4::translation(const Vector3<T>&),
* Vector2::yAxis() * @ref Vector2::xAxis(), @ref Vector2::yAxis()
* @todoc Explicit reference when Doxygen can handle const
*/ */
constexpr static Matrix3<T> translation(const Vector2<T>& vector) { constexpr static Matrix3<T> translation(const Vector2<T>& vector) {
return {{ T(1), T(0), T(0)}, return {{ T(1), T(0), T(0)},
@ -64,8 +64,9 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief 2D scaling matrix * @brief 2D scaling matrix
* @param vector Scaling vector * @param vector Scaling vector
* *
* @see rotationScaling() const, Matrix4::scaling(const Vector3&), * @see @ref rotationScaling(),
* Vector2::xScale(), Vector2::yScale() * @ref Matrix4::scaling(const Vector3<T>&),
* @ref Vector2::xScale(), @ref Vector2::yScale()
*/ */
constexpr static Matrix3<T> scaling(const Vector2<T>& vector) { constexpr static Matrix3<T> scaling(const Vector2<T>& vector) {
return {{vector.x(), T(0), T(0)}, return {{vector.x(), T(0), T(0)},
@ -77,8 +78,10 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief 2D rotation matrix * @brief 2D rotation matrix
* @param angle Rotation angle (counterclockwise) * @param angle Rotation angle (counterclockwise)
* *
* @see rotation() const, Complex::rotation(), DualComplex::rotation(), * @see rotation() const, @ref Complex::rotation(),
* Matrix4::rotation(Rad, const Vector3&) * @ref DualComplex::rotation(),
* @ref Matrix4::rotation(Rad, const Vector3<T>&)
* @todoc Explicit reference when Doxygen can handle const
*/ */
static Matrix3<T> rotation(Rad<T> angle); static Matrix3<T> rotation(Rad<T> angle);
@ -87,7 +90,7 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @param normal Normal of the line through which to reflect * @param normal Normal of the line through which to reflect
* *
* Expects that the normal is normalized. * Expects that the normal is normalized.
* @see Matrix4::reflection(), Vector::isNormalized() * @see @ref Matrix4::reflection(), @ref Vector::isNormalized()
*/ */
static Matrix3<T> reflection(const Vector2<T>& normal) { static Matrix3<T> reflection(const Vector2<T>& normal) {
CORRADE_ASSERT(normal.isNormalized(), CORRADE_ASSERT(normal.isNormalized(),
@ -99,7 +102,8 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief 2D projection matrix * @brief 2D projection matrix
* @param size Size of the view * @param size Size of the view
* *
* @see Matrix4::orthographicProjection(), Matrix4::perspectiveProjection() * @see @ref Matrix4::orthographicProjection(),
* @ref Matrix4::perspectiveProjection()
*/ */
static Matrix3<T> projection(const Vector2<T>& size) { static Matrix3<T> projection(const Vector2<T>& size) {
return scaling(2.0f/size); return scaling(2.0f/size);
@ -112,7 +116,8 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @param translation Translation part (first two elements of * @param translation Translation part (first two elements of
* third column) * third column)
* *
* @see rotationScaling() const, translation() const * @see @ref rotationScaling(), translation() const
* @todoc Explicit reference when Doxygen can handle const
*/ */
constexpr static Matrix3<T> from(const Matrix<2, T>& rotationScaling, const Vector2<T>& translation) { constexpr static Matrix3<T> from(const Matrix<2, T>& rotationScaling, const Vector2<T>& translation) {
return {{rotationScaling[0], T(0)}, return {{rotationScaling[0], T(0)},
@ -127,8 +132,8 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief Default constructor * @brief Default constructor
* *
* Creates identity matrix. You can also explicitly call this * Creates identity matrix. You can also explicitly call this
* constructor with `Matrix3 m(Matrix3::Identity);`. Optional parameter * constructor with `%Matrix3 m(Matrix3::Identity);`. Optional
* @p value allows you to specify value on diagonal. * parameter @p value allows you to specify value on diagonal.
*/ */
constexpr /*implicit*/ Matrix3(typename Matrix<3, T>::IdentityType = (Matrix<3, T>::Identity), T value = T(1)): Matrix<3, T>(Matrix<3, T>::Identity, value) {} constexpr /*implicit*/ Matrix3(typename Matrix<3, T>::IdentityType = (Matrix<3, T>::Identity), T value = T(1)): Matrix<3, T>(Matrix<3, T>::Identity, value) {}
@ -153,7 +158,7 @@ template<class T> class Matrix3: public Matrix<3, T> {
* *
* Rigid transformation consists only of rotation and translation (i.e. * Rigid transformation consists only of rotation and translation (i.e.
* no scaling or projection). * no scaling or projection).
* @see isOrthogonal() * @see @ref isOrthogonal()
*/ */
bool isRigidTransformation() const { bool isRigidTransformation() const {
return rotationScaling().isOrthogonal() && row(2) == Vector3<T>(T(0), T(0), T(1)); return rotationScaling().isOrthogonal() && row(2) == Vector3<T>(T(0), T(0), T(1));
@ -163,9 +168,11 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief 2D rotation and scaling part of the matrix * @brief 2D rotation and scaling part of the matrix
* *
* Upper-left 2x2 part of the matrix. * Upper-left 2x2 part of the matrix.
* @see from(const Matrix<2, T>&, const Vector2&), rotation() const * @see @ref from(const Matrix<2, T>&, const Vector2<T>&),
* rotationNormalized(), @ref uniformScaling(), rotation(T), * rotation() const, @ref rotationNormalized(),
* Matrix4::rotationScaling() const * @ref uniformScaling(), @ref rotation(Rad<T>),
* @ref Matrix4::rotationScaling()
* @todoc Explicit reference when Doxygen can handle const
*/ */
constexpr Matrix<2, T> rotationScaling() const { constexpr Matrix<2, T> rotationScaling() const {
return {(*this)[0].xy(), return {(*this)[0].xy(),
@ -180,6 +187,7 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @see rotation() const, @ref uniformScaling(), * @see rotation() const, @ref uniformScaling(),
* @ref Matrix4::rotationNormalized() * @ref Matrix4::rotationNormalized()
* @todo assert also orthogonality or this is good enough? * @todo assert also orthogonality or this is good enough?
* @todoc Explicit reference when Doxygen can handle const
*/ */
Matrix<2, T> rotationNormalized() const { Matrix<2, T> rotationNormalized() const {
CORRADE_ASSERT((*this)[0].xy().isNormalized() && (*this)[1].xy().isNormalized(), CORRADE_ASSERT((*this)[0].xy().isNormalized() && (*this)[1].xy().isNormalized(),
@ -193,8 +201,10 @@ template<class T> class Matrix3: public Matrix<3, T> {
* *
* Normalized upper-left 2x2 part of the matrix. Expects uniform * Normalized upper-left 2x2 part of the matrix. Expects uniform
* scaling. * scaling.
* @see rotationNormalized(), rotationScaling(), @ref uniformScaling(), * @see @ref rotationNormalized(), @ref rotationScaling(),
* rotation(T), Matrix4::rotation() const * @ref uniformScaling(), @ref rotation(Rad<T>),
* Matrix4::rotation() const
* @todoc Explicit reference when Doxygen can handle const
*/ */
Matrix<2, T> rotation() const { Matrix<2, T> rotation() const {
CORRADE_ASSERT(TypeTraits<T>::equals((*this)[0].xy().dot(), (*this)[1].xy().dot()), CORRADE_ASSERT(TypeTraits<T>::equals((*this)[0].xy().dot(), (*this)[1].xy().dot()),
@ -210,9 +220,10 @@ template<class T> class Matrix3: public Matrix<3, T> {
* Expects that the scaling is the same in all axes. Faster alternative * Expects that the scaling is the same in all axes. Faster alternative
* to @ref uniformScaling(), because it doesn't compute the square * to @ref uniformScaling(), because it doesn't compute the square
* root. * root.
* @see @ref rotationScaling(), @ref rotation(), * @see @ref rotationScaling(), rotation() const,
* @ref rotationNormalized(), @ref scaling(const Vector2<T>&), * @ref rotationNormalized(), @ref scaling(const Vector2<T>&),
* @ref Matrix4::uniformScaling() * @ref Matrix4::uniformScaling()
* @todoc Explicit reference when Doxygen can handle const
*/ */
T uniformScalingSquared() const { T uniformScalingSquared() const {
const T scalingSquared = (*this)[0].xy().dot(); const T scalingSquared = (*this)[0].xy().dot();
@ -227,9 +238,10 @@ template<class T> class Matrix3: public Matrix<3, T> {
* Length of vectors in upper-left 2x2 part of the matrix. Expects that * Length of vectors in upper-left 2x2 part of the matrix. Expects that
* the scaling is the same in all axes. Use faster alternative * the scaling is the same in all axes. Use faster alternative
* @ref uniformScalingSquared() where possible. * @ref uniformScalingSquared() where possible.
* @see @ref rotationScaling(), @ref rotation(), * @see @ref rotationScaling(), rotation() const,
* @ref rotationNormalized(), @ref scaling(const Vector2<T>&), * @ref rotationNormalized(), @ref scaling(const Vector2<T>&),
* @ref Matrix4::uniformScaling() * @ref Matrix4::uniformScaling()
* @todoc Explicit reference when Doxygen can handle const
*/ */
T uniformScaling() const { return std::sqrt(uniformScalingSquared()); } T uniformScaling() const { return std::sqrt(uniformScalingSquared()); }
@ -237,7 +249,7 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief Right-pointing 2D vector * @brief Right-pointing 2D vector
* *
* First two elements of first column. * First two elements of first column.
* @see up(), Vector2::xAxis(), Matrix4::right() * @see @ref up(), @ref Vector2::xAxis(), @ref Matrix4::right()
*/ */
Vector2<T>& right() { return (*this)[0].xy(); } Vector2<T>& right() { return (*this)[0].xy(); }
constexpr Vector2<T> right() const { return (*this)[0].xy(); } /**< @overload */ constexpr Vector2<T> right() const { return (*this)[0].xy(); } /**< @overload */
@ -246,7 +258,7 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief Up-pointing 2D vector * @brief Up-pointing 2D vector
* *
* First two elements of second column. * First two elements of second column.
* @see right(), Vector2::yAxis(), Matrix4::up() * @see @ref right(), @ref Vector2::yAxis(), @ref Matrix4::up()
*/ */
Vector2<T>& up() { return (*this)[1].xy(); } Vector2<T>& up() { return (*this)[1].xy(); }
constexpr Vector2<T> up() const { return (*this)[1].xy(); } /**< @overload */ constexpr Vector2<T> up() const { return (*this)[1].xy(); } /**< @overload */
@ -255,8 +267,9 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief 2D translation part of the matrix * @brief 2D translation part of the matrix
* *
* First two elements of third column. * First two elements of third column.
* @see from(const Matrix<2, T>&, const Vector2&), * @see @ref from(const Matrix<2, T>&, const Vector2<T>&),
* translation(const Vector2&), Matrix4::translation() * @ref translation(const Vector2<T>&),
* @ref Matrix4::translation()
*/ */
Vector2<T>& translation() { return (*this)[2].xy(); } Vector2<T>& translation() { return (*this)[2].xy(); }
constexpr Vector2<T> translation() const { return (*this)[2].xy(); } /**< @overload */ constexpr Vector2<T> translation() const { return (*this)[2].xy(); } /**< @overload */
@ -265,20 +278,27 @@ template<class T> class Matrix3: public Matrix<3, T> {
* @brief Inverted rigid transformation matrix * @brief Inverted rigid transformation matrix
* *
* Expects that the matrix represents rigid transformation. * Expects that the matrix represents rigid transformation.
* Significantly faster than the general algorithm in inverted(). * Significantly faster than the general algorithm in @ref inverted(). @f[
* @see isRigidTransformation(), invertedOrthogonal(), * A^{-1} = \begin{pmatrix} (A^{2,2})^T & (A^{2,2})^T \begin{pmatrix} a_{2,0} \\ a_{2,1} \end{pmatrix} \\ \begin{array}{cc} 0 & 0 \end{array} & 1 \end{pmatrix}
* rotationScaling() const, translation() const * @f]
* @f$ A^{i, j} @f$ is matrix without i-th row and j-th column, see
* @ref ij()
* @see @ref isRigidTransformation(), @ref invertedOrthogonal(),
* @ref rotationScaling(), translation() const,
* @ref Matrix4::invertedRigid()
* @todoc Explicit reference when Doxygen can handle const
*/ */
Matrix3<T> invertedRigid() const; Matrix3<T> invertedRigid() const;
/** /**
* @brief Transform 2D vector with the matrix * @brief Transform 2D vector with the matrix
* *
* Unlike in transformPoint(), translation is not involved in the * Unlike in @ref transformPoint(), translation is not involved in the
* transformation. @f[ * transformation. @f[
* \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ 0 \end{pmatrix} * \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ 0 \end{pmatrix}
* @f] * @f]
* @see Complex::transformVector(), Matrix4::transformVector() * @see @ref Complex::transformVector(),
* @ref Matrix4::transformVector()
* @todo extract 2x2 matrix and multiply directly? (benchmark that) * @todo extract 2x2 matrix and multiply directly? (benchmark that)
*/ */
Vector2<T> transformVector(const Vector2<T>& vector) const { Vector2<T> transformVector(const Vector2<T>& vector) const {
@ -294,11 +314,12 @@ template<class T> class Matrix3: public Matrix<3, T> {
/** /**
* @brief Transform 2D point with the matrix * @brief Transform 2D point with the matrix
* *
* Unlike in transformVector(), translation is also involved in the * Unlike in @ref transformVector(), translation is also involved in
* transformation. @f[ * the transformation. @f[
* \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ 1 \end{pmatrix} * \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ 1 \end{pmatrix}
* @f] * @f]
* @see DualComplex::transformPoint(), Matrix4::transformPoint() * @see @ref DualComplex::transformPoint(),
* @ref Matrix4::transformPoint()
*/ */
Vector2<T> transformPoint(const Vector2<T>& vector) const { Vector2<T> transformPoint(const Vector2<T>& vector) const {
/* Workaround for GCC 4.4 strict-aliasing fascism */ /* Workaround for GCC 4.4 strict-aliasing fascism */

133
src/Magnum/Math/Matrix4.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Matrix4 * @brief Class @ref Magnum::Math::Matrix4
*/ */
#include "Magnum/Math/Matrix.h" #include "Magnum/Math/Matrix.h"
@ -40,13 +40,12 @@
namespace Magnum { namespace Math { namespace Magnum { namespace Math {
/** /**
@brief 4x4 matrix @brief 3D transformation matrix
@tparam T Underlying data type @tparam T Underlying data type
Represents 3D transformation. See @ref matrix-vector and @ref transformations See @ref matrix-vector and @ref transformations for brief introduction.
for brief introduction. @see @ref Magnum::Matrix4, @ref Magnum::Matrix4d, @ref Matrix4x4,
@see Magnum::Matrix4, Magnum::Matrix4d, DualQuaternion, @ref DualQuaternion, @ref SceneGraph::MatrixTransformation3D
SceneGraph::MatrixTransformation3D
@configurationvalueref{Magnum::Math::Matrix4} @configurationvalueref{Magnum::Math::Matrix4}
*/ */
template<class T> class Matrix4: public Matrix<4, T> { template<class T> class Matrix4: public Matrix<4, T> {
@ -55,9 +54,10 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief 3D translation * @brief 3D translation
* @param vector Translation vector * @param vector Translation vector
* *
* @see translation(), DualQuaternion::translation(), * @see @ref translation(), @ref DualQuaternion::translation(),
* Matrix3::translation(const Vector2&), Vector3::xAxis(), * @ref Matrix3::translation(const Vector2<T>&),
* Vector3::yAxis(), Vector3::zAxis() * @ref Vector3::xAxis(), @ref Vector3::yAxis(),
* @ref Vector3::zAxis()
*/ */
constexpr static Matrix4<T> translation(const Vector3<T>& vector) { constexpr static Matrix4<T> translation(const Vector3<T>& vector) {
return {{ T(1), T(0), T(0), T(0)}, return {{ T(1), T(0), T(0), T(0)},
@ -70,8 +70,10 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief 3D scaling * @brief 3D scaling
* @param vector Scaling vector * @param vector Scaling vector
* *
* @see rotationScaling() const, Matrix3::scaling(const Vector2&), * @see @ref rotationScaling(),
* Vector3::xScale(), Vector3::yScale(), Vector3::zScale() * @ref Matrix3::scaling(const Vector2<T>&),
* @ref Vector3::xScale(), @ref Vector3::yScale(),
* @ref Vector3::zScale()
*/ */
constexpr static Matrix4<T> scaling(const Vector3<T>& vector) { constexpr static Matrix4<T> scaling(const Vector3<T>& vector) {
return {{vector.x(), T(0), T(0), T(0)}, return {{vector.x(), T(0), T(0), T(0)},
@ -86,10 +88,13 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @param normalizedAxis Normalized rotation axis * @param normalizedAxis Normalized rotation axis
* *
* Expects that the rotation axis is normalized. If possible, use * Expects that the rotation axis is normalized. If possible, use
* faster alternatives like rotationX(), rotationY() and rotationZ(). * faster alternatives like @ref rotationX(), @ref rotationY() and
* @see rotation() const, Quaternion::rotation(), DualQuaternion::rotation(), * @ref rotationZ().
* Matrix3::rotation(Rad), Vector3::xAxis(), Vector3::yAxis(), * @see rotation() const, @ref Quaternion::rotation(),
* Vector3::zAxis(), Vector::isNormalized() * @ref DualQuaternion::rotation(), @ref Matrix3::rotation(Rad),
* @ref Vector3::xAxis(), @ref Vector3::yAxis(),
* @ref Vector3::zAxis(), @ref Vector::isNormalized()
* @todoc Explicit reference when Doxygen can handle const
*/ */
static Matrix4<T> rotation(Rad<T> angle, const Vector3<T>& normalizedAxis); static Matrix4<T> rotation(Rad<T> angle, const Vector3<T>& normalizedAxis);
@ -97,9 +102,11 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief 3D rotation around X axis * @brief 3D rotation around X axis
* @param angle Rotation angle (counterclockwise) * @param angle Rotation angle (counterclockwise)
* *
* Faster than calling `Matrix4::rotation(angle, Vector3::xAxis())`. * Faster than calling `%Matrix4::rotation(angle, %Vector3::xAxis())`.
* @see rotation(Rad, const Vector3&), rotationY(), rotationZ(), * @see @ref rotation(Rad, const Vector3<T>&), @ref rotationY(),
* rotation() const, Quaternion::rotation(), Matrix3::rotation(Rad) * @ref rotationZ(), rotation() const,
* @ref Quaternion::rotation(), @ref Matrix3::rotation(Rad)
* @todoc Explicit reference when Doxygen can handle const
*/ */
static Matrix4<T> rotationX(Rad<T> angle); static Matrix4<T> rotationX(Rad<T> angle);
@ -107,9 +114,11 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief 3D rotation around Y axis * @brief 3D rotation around Y axis
* @param angle Rotation angle (counterclockwise) * @param angle Rotation angle (counterclockwise)
* *
* Faster than calling `Matrix4::rotation(angle, Vector3::yAxis())`. * Faster than calling `%Matrix4::rotation(angle, %Vector3::yAxis())`.
* @see rotation(Rad, const Vector3&), rotationX(), rotationZ(), * @see @ref rotation(Rad, const Vector3<T>&), @ref rotationX(),
* rotation() const, Quaternion::rotation(), Matrix3::rotation(Rad) * @ref rotationZ(), rotation() const,
* @ref Quaternion::rotation(), @ref Matrix3::rotation(Rad)
* @todoc Explicit reference when Doxygen can handle const
*/ */
static Matrix4<T> rotationY(Rad<T> angle); static Matrix4<T> rotationY(Rad<T> angle);
@ -117,9 +126,11 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief 3D rotation matrix around Z axis * @brief 3D rotation matrix around Z axis
* @param angle Rotation angle (counterclockwise) * @param angle Rotation angle (counterclockwise)
* *
* Faster than calling `Matrix4::rotation(angle, Vector3::zAxis())`. * Faster than calling `%Matrix4::rotation(angle, %Vector3::zAxis())`.
* @see rotation(Rad, const Vector3&), rotationX(), rotationY(), * @see @ref rotation(Rad, const Vector3<T>&), @ref rotationX(),
* rotation() const, Quaternion::rotation(), Matrix3::rotation(Rad) * @ref rotationY(), rotation() const,
* @ref Quaternion::rotation(), @ref Matrix3::rotation(Rad)
* @todoc Explicit reference when Doxygen can handle const
*/ */
static Matrix4<T> rotationZ(Rad<T> angle); static Matrix4<T> rotationZ(Rad<T> angle);
@ -128,7 +139,7 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @param normal Normal of the plane through which to reflect * @param normal Normal of the plane through which to reflect
* *
* Expects that the normal is normalized. * Expects that the normal is normalized.
* @see Matrix3::reflection(), Vector::isNormalized() * @see @ref Matrix3::reflection(), @ref Vector::isNormalized()
*/ */
static Matrix4<T> reflection(const Vector3<T>& normal); static Matrix4<T> reflection(const Vector3<T>& normal);
@ -138,7 +149,7 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @param near Near clipping plane * @param near Near clipping plane
* @param far Far clipping plane * @param far Far clipping plane
* *
* @see perspectiveProjection(), Matrix3::projection() * @see @ref perspectiveProjection(), @ref Matrix3::projection()
*/ */
static Matrix4<T> orthographicProjection(const Vector2<T>& size, T near, T far); static Matrix4<T> orthographicProjection(const Vector2<T>& size, T near, T far);
@ -148,7 +159,7 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @param near Near clipping plane * @param near Near clipping plane
* @param far Far clipping plane * @param far Far clipping plane
* *
* @see orthographicProjection(), Matrix3::projection() * @see @ref orthographicProjection(), @ref Matrix3::projection()
*/ */
static Matrix4<T> perspectiveProjection(const Vector2<T>& size, T near, T far); static Matrix4<T> perspectiveProjection(const Vector2<T>& size, T near, T far);
@ -159,7 +170,7 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @param near Near clipping plane * @param near Near clipping plane
* @param far Far clipping plane * @param far Far clipping plane
* *
* @see orthographicProjection(), Matrix3::projection() * @see @ref orthographicProjection(), @ref Matrix3::projection()
*/ */
static Matrix4<T> perspectiveProjection(Rad<T> fov, T aspectRatio, T near, T far) { static Matrix4<T> perspectiveProjection(Rad<T> fov, T aspectRatio, T near, T far) {
const T xyScale = 2*std::tan(fov.toUnderlyingType()/2)*near; const T xyScale = 2*std::tan(fov.toUnderlyingType()/2)*near;
@ -173,7 +184,8 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @param translation Translation part (first three elements of * @param translation Translation part (first three elements of
* fourth column) * fourth column)
* *
* @see rotationScaling() const, translation() const * @see @ref rotationScaling(), translation() const
* @todoc Explicit reference when Doxygen can handle const
*/ */
constexpr static Matrix4<T> from(const Matrix<3, T>& rotationScaling, const Vector3<T>& translation) { constexpr static Matrix4<T> from(const Matrix<3, T>& rotationScaling, const Vector3<T>& translation) {
return {{rotationScaling[0], T(0)}, return {{rotationScaling[0], T(0)},
@ -189,8 +201,8 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief Default constructor * @brief Default constructor
* *
* Creates identity matrix. You can also explicitly call this * Creates identity matrix. You can also explicitly call this
* constructor with `Matrix4 m(Matrix4::Identity);`. Optional parameter * constructor with `%Matrix4 m(Matrix4::Identity);`. Optional
* @p value allows you to specify value on diagonal. * parameter @p value allows you to specify value on diagonal.
*/ */
constexpr /*implicit*/ Matrix4(typename Matrix<4, T>::IdentityType = (Matrix<4, T>::Identity), T value = T(1)): Matrix<4, T>(Matrix<4, T>::Identity, value) {} constexpr /*implicit*/ Matrix4(typename Matrix<4, T>::IdentityType = (Matrix<4, T>::Identity), T value = T(1)): Matrix<4, T>(Matrix<4, T>::Identity, value) {}
@ -215,7 +227,7 @@ template<class T> class Matrix4: public Matrix<4, T> {
* *
* Rigid transformation consists only of rotation and translation (i.e. * Rigid transformation consists only of rotation and translation (i.e.
* no scaling or projection). * no scaling or projection).
* @see isOrthogonal() * @see @ref isOrthogonal()
*/ */
bool isRigidTransformation() const { bool isRigidTransformation() const {
return rotationScaling().isOrthogonal() && row(3) == Vector4<T>(T(0), T(0), T(0), T(1)); return rotationScaling().isOrthogonal() && row(3) == Vector4<T>(T(0), T(0), T(0), T(1));
@ -225,9 +237,11 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief 3D rotation and scaling part of the matrix * @brief 3D rotation and scaling part of the matrix
* *
* Upper-left 3x3 part of the matrix. * Upper-left 3x3 part of the matrix.
* @see from(const Matrix<3, T>&, const Vector3&), rotation() const, * @see @ref from(const Matrix<3, T>&, const Vector3<T>&),
* rotationNormalized(), @ref uniformScaling(), * rotation() const, @ref rotationNormalized(),
* rotation(T, const Vector3&), Matrix3::rotationScaling() const * @ref uniformScaling(), @ref rotation(Rad, const Vector3<T>&),
* Matrix3::rotationScaling() const
* @todoc Explicit reference when Doxygen can handle const
*/ */
/* Not Matrix3, because it is for affine 2D transformations */ /* Not Matrix3, because it is for affine 2D transformations */
constexpr Matrix<3, T> rotationScaling() const { constexpr Matrix<3, T> rotationScaling() const {
@ -244,6 +258,7 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @see rotation() const, @ref uniformScaling(), * @see rotation() const, @ref uniformScaling(),
* @ref Matrix3::rotationNormalized() * @ref Matrix3::rotationNormalized()
* @todo assert also orthogonality or this is good enough? * @todo assert also orthogonality or this is good enough?
* @todoc Explicit reference when Doxygen can handle const
*/ */
/* Not Matrix3, because it is for affine 2D transformations */ /* Not Matrix3, because it is for affine 2D transformations */
Matrix<3, T> rotationNormalized() const { Matrix<3, T> rotationNormalized() const {
@ -259,9 +274,10 @@ template<class T> class Matrix4: public Matrix<4, T> {
* *
* Normalized upper-left 3x3 part of the matrix. Expects uniform * Normalized upper-left 3x3 part of the matrix. Expects uniform
* scaling. * scaling.
* @see rotationNormalized(), rotationScaling() const, * @see @ref rotationNormalized(), @ref rotationScaling(),
* @ref uniformScaling(), rotation(T, const Vector3&), * @ref uniformScaling(), @ref rotation(Rad, const Vector3<T>&),
* Matrix3::rotation() const * Matrix3::rotation() const
* @todoc Explicit reference when Doxygen can handle const
*/ */
/* Not Matrix3, because it is for affine 2D transformations */ /* Not Matrix3, because it is for affine 2D transformations */
Matrix<3, T> rotation() const; Matrix<3, T> rotation() const;
@ -273,9 +289,10 @@ template<class T> class Matrix4: public Matrix<4, T> {
* Expects that the scaling is the same in all axes. Faster alternative * Expects that the scaling is the same in all axes. Faster alternative
* to @ref uniformScaling(), because it doesn't compute the square * to @ref uniformScaling(), because it doesn't compute the square
* root. * root.
* @see @ref rotationScaling(), @ref rotation(), * @see @ref rotationScaling(), rotation() const,
* @ref rotationNormalized(), @ref scaling(const Vector3<T>&), * @ref rotationNormalized(), @ref scaling(const Vector3<T>&),
* @ref Matrix3::uniformScaling() * @ref Matrix3::uniformScaling()
* @todoc Explicit reference when Doxygen can handle const
*/ */
T uniformScalingSquared() const; T uniformScalingSquared() const;
@ -285,9 +302,10 @@ template<class T> class Matrix4: public Matrix<4, T> {
* Length of vectors in upper-left 3x3 part of the matrix. Expects that * Length of vectors in upper-left 3x3 part of the matrix. Expects that
* the scaling is the same in all axes. Use faster alternative * the scaling is the same in all axes. Use faster alternative
* @ref uniformScalingSquared() where possible. * @ref uniformScalingSquared() where possible.
* @see @ref rotationScaling(), @ref rotation(), * @see @ref rotationScaling(), rotation() const,
* @ref rotationNormalized(), @ref scaling(const Vector3<T>&), * @ref rotationNormalized(), @ref scaling(const Vector3<T>&),
* @ref Matrix3::uniformScaling() * @ref Matrix3::uniformScaling()
* @todoc Explicit reference when Doxygen can handle const
*/ */
T uniformScaling() const { return std::sqrt(uniformScalingSquared()); } T uniformScaling() const { return std::sqrt(uniformScalingSquared()); }
@ -295,7 +313,8 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief Right-pointing 3D vector * @brief Right-pointing 3D vector
* *
* First three elements of first column. * First three elements of first column.
* @see up(), backward(), Vector3::xAxis(), Matrix3::right() * @see @ref up(), @ref backward(), @ref Vector3::xAxis(),
* @ref Matrix3::right()
*/ */
Vector3<T>& right() { return (*this)[0].xyz(); } Vector3<T>& right() { return (*this)[0].xyz(); }
constexpr Vector3<T> right() const { return (*this)[0].xyz(); } /**< @overload */ constexpr Vector3<T> right() const { return (*this)[0].xyz(); } /**< @overload */
@ -304,7 +323,8 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief Up-pointing 3D vector * @brief Up-pointing 3D vector
* *
* First three elements of second column. * First three elements of second column.
* @see right(), backward(), Vector3::yAxis(), Matrix3::up() * @see @ref right(), @ref backward(), @ref Vector3::yAxis(),
* @ref Matrix3::up()
*/ */
Vector3<T>& up() { return (*this)[1].xyz(); } Vector3<T>& up() { return (*this)[1].xyz(); }
constexpr Vector3<T> up() const { return (*this)[1].xyz(); } /**< @overload */ constexpr Vector3<T> up() const { return (*this)[1].xyz(); } /**< @overload */
@ -313,7 +333,7 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief Backward-pointing 3D vector * @brief Backward-pointing 3D vector
* *
* First three elements of third column. * First three elements of third column.
* @see right(), up(), Vector3::yAxis() * @see @ref right(), @ref up(), @ref Vector3::yAxis()
*/ */
Vector3<T>& backward() { return (*this)[2].xyz(); } Vector3<T>& backward() { return (*this)[2].xyz(); }
constexpr Vector3<T> backward() const { return (*this)[2].xyz(); } /**< @overload */ constexpr Vector3<T> backward() const { return (*this)[2].xyz(); } /**< @overload */
@ -322,8 +342,9 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief 3D translation part of the matrix * @brief 3D translation part of the matrix
* *
* First three elements of fourth column. * First three elements of fourth column.
* @see from(const Matrix<3, T>&, const Vector3&), * @see @ref from(const Matrix<3, T>&, const Vector3<T>&),
* translation(const Vector3&), Matrix3::translation() * @ref translation(const Vector3<T>&),
* @ref Matrix3::translation()
*/ */
Vector3<T>& translation() { return (*this)[3].xyz(); } Vector3<T>& translation() { return (*this)[3].xyz(); }
constexpr Vector3<T> translation() const { return (*this)[3].xyz(); } /**< @overload */ constexpr Vector3<T> translation() const { return (*this)[3].xyz(); } /**< @overload */
@ -332,20 +353,27 @@ template<class T> class Matrix4: public Matrix<4, T> {
* @brief Inverted rigid transformation matrix * @brief Inverted rigid transformation matrix
* *
* Expects that the matrix represents rigid transformation. * Expects that the matrix represents rigid transformation.
* Significantly faster than the general algorithm in inverted(). * Significantly faster than the general algorithm in @ref inverted(). @f[
* @see isRigidTransformation(), invertedOrthogonal(), * A^{-1} = \begin{pmatrix} (A^{3,3})^T & (A^{3,3})^T \begin{pmatrix} a_{3,0} \\ a_{3,1} \\ a_{3,2} \\ \end{pmatrix} \\ \begin{array}{ccc} 0 & 0 & 0 \end{array} & 1 \end{pmatrix}
* rotationScaling() const, translation() const * @f]
* @f$ A^{i, j} @f$ is matrix without i-th row and j-th column, see
* @ref ij()
* @see @ref isRigidTransformation(), @ref invertedOrthogonal(),
* @ref rotationScaling(), translation() const,
* @ref Matrix3::invertedRigid()
* @todoc Explicit reference when Doxygen can handle const
*/ */
Matrix4<T> invertedRigid() const; Matrix4<T> invertedRigid() const;
/** /**
* @brief Transform 3D vector with the matrix * @brief Transform 3D vector with the matrix
* *
* Unlike in transformVector(), translation is not involved in the * Unlike in @ref transformVector(), translation is not involved in the
* transformation. @f[ * transformation. @f[
* \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ v_z \\ 0 \end{pmatrix} * \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ v_z \\ 0 \end{pmatrix}
* @f] * @f]
* @see Quaternion::transformVector(), Matrix3::transformVector() * @see @ref Quaternion::transformVector(),
* @ref Matrix3::transformVector()
* @todo extract 3x3 matrix and multiply directly? (benchmark that) * @todo extract 3x3 matrix and multiply directly? (benchmark that)
*/ */
Vector3<T> transformVector(const Vector3<T>& vector) const { Vector3<T> transformVector(const Vector3<T>& vector) const {
@ -361,11 +389,12 @@ template<class T> class Matrix4: public Matrix<4, T> {
/** /**
* @brief Transform 3D point with the matrix * @brief Transform 3D point with the matrix
* *
* Unlike in transformVector(), translation is also involved in the * Unlike in @ref transformVector(), translation is also involved in
* transformation. @f[ * the transformation. @f[
* \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ v_z \\ 1 \end{pmatrix} * \boldsymbol v' = \boldsymbol M \begin{pmatrix} v_x \\ v_y \\ v_z \\ 1 \end{pmatrix}
* @f] * @f]
* @see DualQuaternion::transformPoint(), Matrix3::transformPoint() * @see @ref DualQuaternion::transformPoint(),
* @ref Matrix3::transformPoint()
*/ */
Vector3<T> transformPoint(const Vector3<T>& vector) const { Vector3<T> transformPoint(const Vector3<T>& vector) const {
/* Workaround for GCC 4.4 strict-aliasing fascism */ /* Workaround for GCC 4.4 strict-aliasing fascism */

101
src/Magnum/Math/Quaternion.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Quaternion * @brief Class @ref Magnum::Math::Quaternion
*/ */
#include <cmath> #include <cmath>
@ -44,11 +44,12 @@ namespace Magnum { namespace Math {
@tparam T Underlying data type @tparam T Underlying data type
Represents 3D rotation. See @ref transformations for brief introduction. Represents 3D rotation. See @ref transformations for brief introduction.
@see Magnum::Quaternion, Magnum::Quaterniond, DualQuaternion, Matrix4 @see @ref Magnum::Quaternion, @ref Magnum::Quaterniond, @ref DualQuaternion,
@ref Matrix4
*/ */
template<class T> class Quaternion { template<class T> class Quaternion {
public: public:
typedef T Type; /**< @brief Underlying data type */ typedef T Type; /**< @brief Underlying data type */
/** /**
* @brief Dot product * @brief Dot product
@ -57,6 +58,7 @@ template<class T> class Quaternion {
* p \cdot q = \boldsymbol p_V \cdot \boldsymbol q_V + p_S q_S * p \cdot q = \boldsymbol p_V \cdot \boldsymbol q_V + p_S q_S
* @f] * @f]
* @see dot() const * @see dot() const
* @todoc Explicit reference when Doxygen can handle const
*/ */
static T dot(const Quaternion<T>& a, const Quaternion<T>& b) { static T dot(const Quaternion<T>& a, const Quaternion<T>& b) {
/** @todo Use four-component SIMD implementation when available */ /** @todo Use four-component SIMD implementation when available */
@ -69,7 +71,8 @@ template<class T> class Quaternion {
* Expects that both quaternions are normalized. @f[ * Expects that both quaternions are normalized. @f[
* \theta = acos \left( \frac{p \cdot q}{|p| |q|} \right) = acos(p \cdot q) * \theta = acos \left( \frac{p \cdot q}{|p| |q|} \right) = acos(p \cdot q)
* @f] * @f]
* @see isNormalized(), Complex::angle(), Vector::angle() * @see @ref isNormalized(), @ref Complex::angle(),
* @ref Vector::angle()
*/ */
static Rad<T> angle(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB); static Rad<T> angle(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB);
@ -82,7 +85,7 @@ template<class T> class Quaternion {
* Expects that both quaternions are normalized. @f[ * Expects that both quaternions are normalized. @f[
* q_{LERP} = \frac{(1 - t) q_A + t q_B}{|(1 - t) q_A + t q_B|} * q_{LERP} = \frac{(1 - t) q_A + t q_B}{|(1 - t) q_A + t q_B|}
* @f] * @f]
* @see isNormalized(), slerp(), Math::lerp() * @see @ref isNormalized(), @ref slerp(), @ref Math::lerp()
*/ */
static Quaternion<T> lerp(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t); static Quaternion<T> lerp(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t);
@ -97,7 +100,7 @@ template<class T> class Quaternion {
* ~~~~~~~~~~ * ~~~~~~~~~~
* \theta = acos \left( \frac{q_A \cdot q_B}{|q_A| \cdot |q_B|} \right) = acos(q_A \cdot q_B) * \theta = acos \left( \frac{q_A \cdot q_B}{|q_A| \cdot |q_B|} \right) = acos(q_A \cdot q_B)
* @f] * @f]
* @see isNormalized(), lerp() * @see @ref isNormalized(), @ref lerp()
*/ */
static Quaternion<T> slerp(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t); static Quaternion<T> slerp(const Quaternion<T>& normalizedA, const Quaternion<T>& normalizedB, T t);
@ -109,9 +112,10 @@ template<class T> class Quaternion {
* Expects that the rotation axis is normalized. @f[ * Expects that the rotation axis is normalized. @f[
* q = [\boldsymbol a \cdot sin \frac \theta 2, cos \frac \theta 2] * q = [\boldsymbol a \cdot sin \frac \theta 2, cos \frac \theta 2]
* @f] * @f]
* @see angle(), axis(), DualQuaternion::rotation(), * @see @ref angle(), @ref axis(), @ref DualQuaternion::rotation(),
* Matrix4::rotation(), Complex::rotation(), Vector3::xAxis(), * @ref Matrix4::rotation(), @ref Complex::rotation(),
* Vector3::yAxis(), Vector3::zAxis(), Vector::isNormalized() * @ref Vector3::xAxis(), @ref Vector3::yAxis(),
* @ref Vector3::zAxis(), @ref Vector::isNormalized()
*/ */
static Quaternion<T> rotation(Rad<T> angle, const Vector3<T>& normalizedAxis); static Quaternion<T> rotation(Rad<T> angle, const Vector3<T>& normalizedAxis);
@ -119,7 +123,8 @@ template<class T> class Quaternion {
* @brief Create quaternion from rotation matrix * @brief Create quaternion from rotation matrix
* *
* Expects that the matrix is orthogonal (i.e. pure rotation). * Expects that the matrix is orthogonal (i.e. pure rotation).
* @see toMatrix(), DualComplex::fromMatrix(), Matrix::isOrthogonal() * @see @ref toMatrix(), @ref DualComplex::fromMatrix(),
* @ref Matrix::isOrthogonal()
*/ */
static Quaternion<T> fromMatrix(const Matrix<3, T>& matrix); static Quaternion<T> fromMatrix(const Matrix<3, T>& matrix);
@ -147,7 +152,7 @@ template<class T> class Quaternion {
* To be used in transformations later. @f[ * To be used in transformations later. @f[
* q = [\boldsymbol v, 0] * q = [\boldsymbol v, 0]
* @f] * @f]
* @see transformVector(), transformVectorNormalized() * @see @ref transformVector(), @ref transformVectorNormalized()
*/ */
constexpr explicit Quaternion(const Vector3<T>& vector): _vector(vector), _scalar(T(0)) {} constexpr explicit Quaternion(const Vector3<T>& vector): _vector(vector), _scalar(T(0)) {}
@ -164,10 +169,10 @@ template<class T> class Quaternion {
/** /**
* @brief Whether the quaternion is normalized * @brief Whether the quaternion is normalized
* *
* Quaternion is normalized if it has unit length: @f[ * %Quaternion is normalized if it has unit length: @f[
* |q \cdot q - 1| < 2 \epsilon + \epsilon^2 \cong 2 \epsilon * |q \cdot q - 1| < 2 \epsilon + \epsilon^2 \cong 2 \epsilon
* @f] * @f]
* @see dot(), normalized() * @see @ref dot(), @ref normalized()
*/ */
bool isNormalized() const { bool isNormalized() const {
return Implementation::isNormalizedSquared(dot()); return Implementation::isNormalizedSquared(dot());
@ -185,7 +190,7 @@ template<class T> class Quaternion {
* Expects that the quaternion is normalized. @f[ * Expects that the quaternion is normalized. @f[
* \theta = 2 \cdot acos q_S * \theta = 2 \cdot acos q_S
* @f] * @f]
* @see isNormalized(), axis(), rotation() * @see @ref isNormalized(), @ref axis(), @ref rotation()
*/ */
Rad<T> angle() const; Rad<T> angle() const;
@ -197,15 +202,15 @@ template<class T> class Quaternion {
* default-constructed quaternion. @f[ * default-constructed quaternion. @f[
* \boldsymbol a = \frac{\boldsymbol q_V}{\sqrt{1 - q_S^2}} * \boldsymbol a = \frac{\boldsymbol q_V}{\sqrt{1 - q_S^2}}
* @f] * @f]
* @see isNormalized(), angle(), rotation() * @see @ref isNormalized(), @ref angle(), @ref rotation()
*/ */
Vector3<T> axis() const; Vector3<T> axis() const;
/** /**
* @brief Convert quaternion to rotation matrix * @brief Convert quaternion to rotation matrix
* *
* @see fromMatrix(), DualQuaternion::toMatrix(), * @see @ref fromMatrix(), @ref DualQuaternion::toMatrix(),
* Matrix4::from(const Matrix<3, T>&, const Vector3<T>&) * @ref Matrix4::from(const Matrix<3, T>&, const Vector3<T>&)
*/ */
Matrix<3, T> toMatrix() const; Matrix<3, T> toMatrix() const;
@ -225,7 +230,7 @@ template<class T> class Quaternion {
/** /**
* @brief Add quaternion * @brief Add quaternion
* *
* @see operator+=() * @see @ref operator+=()
*/ */
Quaternion<T> operator+(const Quaternion<T>& other) const { Quaternion<T> operator+(const Quaternion<T>& other) const {
return Quaternion<T>(*this) += other; return Quaternion<T>(*this) += other;
@ -256,7 +261,7 @@ template<class T> class Quaternion {
/** /**
* @brief Subtract quaternion * @brief Subtract quaternion
* *
* @see operator-=() * @see @ref operator-=()
*/ */
Quaternion<T> operator-(const Quaternion<T>& other) const { Quaternion<T> operator-(const Quaternion<T>& other) const {
return Quaternion<T>(*this) -= other; return Quaternion<T>(*this) -= other;
@ -278,7 +283,7 @@ template<class T> class Quaternion {
/** /**
* @brief Multiply with scalar * @brief Multiply with scalar
* *
* @see operator*=(T) * @see @ref operator*=(T)
*/ */
Quaternion<T> operator*(T scalar) const { Quaternion<T> operator*(T scalar) const {
return Quaternion<T>(*this) *= scalar; return Quaternion<T>(*this) *= scalar;
@ -300,7 +305,7 @@ template<class T> class Quaternion {
/** /**
* @brief Divide with scalar * @brief Divide with scalar
* *
* @see operator/=(T) * @see @ref operator/=(T)
*/ */
Quaternion<T> operator/(T scalar) const { Quaternion<T> operator/(T scalar) const {
return Quaternion<T>(*this) /= scalar; return Quaternion<T>(*this) /= scalar;
@ -319,29 +324,32 @@ template<class T> class Quaternion {
/** /**
* @brief Dot product of the quaternion * @brief Dot product of the quaternion
* *
* Should be used instead of length() for comparing quaternion length * Should be used instead of @ref length() for comparing quaternion
* with other values, because it doesn't compute the square root. @f[ * length with other values, because it doesn't compute the square
* root. @f[
* q \cdot q = \boldsymbol q_V \cdot \boldsymbol q_V + q_S^2 * q \cdot q = \boldsymbol q_V \cdot \boldsymbol q_V + q_S^2
* @f] * @f]
* @see isNormalized(), dot(const Quaternion&, const Quaternion&) * @see @ref isNormalized(),
* @ref dot(const Quaternion<T>&, const Quaternion<T>&)
*/ */
T dot() const { return dot(*this, *this); } T dot() const { return dot(*this, *this); }
/** /**
* @brief %Quaternion length * @brief %Quaternion length
* *
* See also dot() const which is faster for comparing length with other * See also dot() const which is faster for comparing length with
* values. @f[ * other values. @f[
* |q| = \sqrt{q \cdot q} * |q| = \sqrt{q \cdot q}
* @f] * @f]
* @see isNormalized() * @see @ref isNormalized()
* @todoc Explicit reference when Doxygen can handle const
*/ */
T length() const { return std::sqrt(dot()); } T length() const { return std::sqrt(dot()); }
/** /**
* @brief Normalized quaternion (of unit length) * @brief Normalized quaternion (of unit length)
* *
* @see isNormalized() * @see @ref isNormalized()
*/ */
Quaternion<T> normalized() const { return (*this)/length(); } Quaternion<T> normalized() const { return (*this)/length(); }
@ -357,7 +365,7 @@ template<class T> class Quaternion {
/** /**
* @brief Inverted quaternion * @brief Inverted quaternion
* *
* See invertedNormalized() which is faster for normalized * See @ref invertedNormalized() which is faster for normalized
* quaternions. @f[ * quaternions. @f[
* q^{-1} = \frac{q^*}{|q|^2} = \frac{q^*}{q \cdot q} * q^{-1} = \frac{q^*}{|q|^2} = \frac{q^*}{q \cdot q}
* @f] * @f]
@ -367,23 +375,25 @@ template<class T> class Quaternion {
/** /**
* @brief Inverted normalized quaternion * @brief Inverted normalized quaternion
* *
* Equivalent to conjugated(). Expects that the quaternion is * Equivalent to @ref conjugated(). Expects that the quaternion is
* normalized. @f[ * normalized. @f[
* q^{-1} = \frac{q^*}{|q|^2} = q^* * q^{-1} = \frac{q^*}{|q|^2} = q^*
* @f] * @f]
* @see isNormalized(), inverted() * @see @ref isNormalized(), @ref inverted()
*/ */
Quaternion<T> invertedNormalized() const; Quaternion<T> invertedNormalized() const;
/** /**
* @brief Rotate vector with quaternion * @brief Rotate vector with quaternion
* *
* See transformVectorNormalized(), which is faster for normalized * See @ref transformVectorNormalized(), which is faster for normalized
* quaternions. @f[ * quaternions. @f[
* v' = qvq^{-1} = q [\boldsymbol v, 0] q^{-1} * v' = qvq^{-1} = q [\boldsymbol v, 0] q^{-1}
* @f] * @f]
* @see Quaternion(const Vector3&), vector(), Matrix4::transformVector(), * @see @ref Quaternion(const Vector3<T>&), @ref vector(),
* DualQuaternion::transformPoint(), Complex::transformVector() * @ref Matrix4::transformVector(),
* @ref DualQuaternion::transformPoint(),
* @ref Complex::transformVector()
*/ */
Vector3<T> transformVector(const Vector3<T>& vector) const { Vector3<T> transformVector(const Vector3<T>& vector) const {
return ((*this)*Quaternion<T>(vector)*inverted()).vector(); return ((*this)*Quaternion<T>(vector)*inverted()).vector();
@ -392,12 +402,14 @@ template<class T> class Quaternion {
/** /**
* @brief Rotate vector with normalized quaternion * @brief Rotate vector with normalized quaternion
* *
* Faster alternative to transformVector(), expects that the quaternion * Faster alternative to @ref transformVector(), expects that the
* is normalized. @f[ * quaternion is normalized. @f[
* v' = qvq^{-1} = qvq^* = q [\boldsymbol v, 0] q^* * v' = qvq^{-1} = qvq^* = q [\boldsymbol v, 0] q^*
* @f] * @f]
* @see isNormalized(), Quaternion(const Vector3&), vector(), Matrix4::transformVector(), * @see @ref isNormalized(), @ref Quaternion(const Vector3<T>&),
* DualQuaternion::transformPointNormalized(), Complex::transformVector() * @ref vector(), @ref Matrix4::transformVector(),
* @ref DualQuaternion::transformPointNormalized(),
* @ref Complex::transformVector()
*/ */
Vector3<T> transformVectorNormalized(const Vector3<T>& vector) const; Vector3<T> transformVectorNormalized(const Vector3<T>& vector) const;
@ -419,7 +431,7 @@ template<class T> class Quaternion {
/** @relates Quaternion /** @relates Quaternion
@brief Multiply scalar with quaternion @brief Multiply scalar with quaternion
Same as Quaternion::operator*(T) const. Same as @ref Quaternion::operator*(T) const.
*/ */
template<class T> inline Quaternion<T> operator*(T scalar, const Quaternion<T>& quaternion) { template<class T> inline Quaternion<T> operator*(T scalar, const Quaternion<T>& quaternion) {
return quaternion*scalar; return quaternion*scalar;
@ -431,7 +443,7 @@ template<class T> inline Quaternion<T> operator*(T scalar, const Quaternion<T>&
@f[ @f[
\frac a q = [\frac a {\boldsymbol q_V}, \frac a {q_S}] \frac a q = [\frac a {\boldsymbol q_V}, \frac a {q_S}]
@f] @f]
@see Quaternion::operator/() @see @ref Quaternion::operator/()
*/ */
template<class T> inline Quaternion<T> operator/(T scalar, const Quaternion<T>& quaternion) { template<class T> inline Quaternion<T> operator/(T scalar, const Quaternion<T>& quaternion) {
return {scalar/quaternion.vector(), scalar/quaternion.scalar()}; return {scalar/quaternion.vector(), scalar/quaternion.scalar()};
@ -446,12 +458,16 @@ template<class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug deb
return debug; return debug;
} }
/** @todoc Remove the workaround when Doxygen is really able to preprocessor */
/* Explicit instantiation for commonly used types */ /* Explicit instantiation for commonly used types */
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
/** @privatesection */
extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Quaternion<Float>&); extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Quaternion<Float>&);
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Quaternion<Double>&); extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Quaternion<Double>&);
#endif #endif
/** @endprivatesection */
#endif #endif
namespace Implementation { namespace Implementation {
@ -472,10 +488,7 @@ template<class T> Quaternion<T> quaternionFromMatrix(const Matrix<3, T>& m) {
} }
/* Diagonal is negative */ /* Diagonal is negative */
std::size_t i = 0; const std::size_t i = diagonal.max();
if(diagonal[1] > diagonal[0]) i = 1;
if(diagonal[2] > diagonal[i]) i = 2;
const std::size_t j = (i + 1) % 3; const std::size_t j = (i + 1) % 3;
const std::size_t k = (i + 2) % 3; const std::size_t k = (i + 2) % 3;

6
src/Magnum/Math/Range.h

@ -62,7 +62,7 @@ template<UnsignedInt dimensions, class T> class Range {
/** /**
* Create range from minimal coordinates and size * Create range from minimal coordinates and size
* @param min Minimal coordinates * @param min Minimal coordinates
* @param size Range size * @param size %Range size
*/ */
static Range<dimensions, T> fromSize(const VectorType& min, const VectorType& size) { static Range<dimensions, T> fromSize(const VectorType& min, const VectorType& size) {
return {min, min+size}; return {min, min+size};
@ -122,7 +122,7 @@ template<UnsignedInt dimensions, class T> class Range {
constexpr const VectorType max() const { return _max; } /**< @overload */ constexpr const VectorType max() const { return _max; } /**< @overload */
/** /**
* @brief Range size * @brief %Range size
* *
* @see @ref min(), @ref max(), @ref Range2D::sizeX(), * @see @ref min(), @ref max(), @ref Range2D::sizeX(),
* @ref Range2D::sizeY(), @ref Range3D::sizeX(), * @ref Range2D::sizeY(), @ref Range3D::sizeX(),
@ -131,7 +131,7 @@ template<UnsignedInt dimensions, class T> class Range {
VectorType size() const { return _max - _min; } VectorType size() const { return _max - _min; }
/** /**
* @brief Range center * @brief %Range center
* *
* @see @ref Range2D::centerX(), @ref Range2D::centerY(), * @see @ref Range2D::centerX(), @ref Range2D::centerY(),
* @ref Range3D::centerX(), @ref Range3D::centerY(), * @ref Range3D::centerX(), @ref Range3D::centerY(),

66
src/Magnum/Math/RectangularMatrix.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::RectangularMatrix * @brief Class @ref Magnum::Math::RectangularMatrix, typedef @ref Magnum::Math::Matrix2x3, @ref Magnum::Math::Matrix3x2, @ref Magnum::Math::Matrix2x4, @ref Magnum::Math::Matrix4x2, @ref Magnum::Math::Matrix3x4, @ref Magnum::Math::Matrix4x3
*/ */
#include "Magnum/Math/Vector.h" #include "Magnum/Math/Vector.h"
@ -43,8 +43,8 @@ namespace Implementation {
@tparam rows Row count @tparam rows Row count
@tparam T Underlying data type @tparam T Underlying data type
See @ref matrix-vector for brief introduction. See also Matrix (square) and See @ref matrix-vector for brief introduction. See also @ref Matrix (square)
Vector. and @ref Vector.
The data are stored in column-major order, to reflect that, all indices in The data are stored in column-major order, to reflect that, all indices in
math formulas are in reverse order (i.e. @f$ \boldsymbol A_{ji} @f$ instead math formulas are in reverse order (i.e. @f$ \boldsymbol A_{ji} @f$ instead
@ -65,13 +65,13 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Size of matrix diagonal * @brief Size of matrix diagonal
* *
* @see fromDiagonal(), diagonal() * @see @ref fromDiagonal(), @ref diagonal()
*/ */
const static std::size_t DiagonalSize = (cols < rows ? cols : rows); const static std::size_t DiagonalSize = (cols < rows ? cols : rows);
/** /**
* @brief %Matrix from array * @brief %Matrix from array
* @return Reference to the data as if it was Matrix, thus doesn't * @return Reference to the data as if it was matrix, thus doesn't
* perform any copying. * perform any copying.
* *
* @attention Use with caution, the function doesn't check whether the * @attention Use with caution, the function doesn't check whether the
@ -90,7 +90,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* *
* Rolls the vector into matrix, i.e. first `rows` elements of the * Rolls the vector into matrix, i.e. first `rows` elements of the
* vector will make first column of resulting matrix. * vector will make first column of resulting matrix.
* @see toVector() * @see @ref toVector()
*/ */
static RectangularMatrix<cols, rows, T> fromVector(const Vector<cols*rows, T>& vector) { static RectangularMatrix<cols, rows, T> fromVector(const Vector<cols*rows, T>& vector) {
return *reinterpret_cast<const RectangularMatrix<cols, rows, T>*>(vector.data()); return *reinterpret_cast<const RectangularMatrix<cols, rows, T>*>(vector.data());
@ -99,7 +99,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Construct diagonal matrix * @brief Construct diagonal matrix
* *
* @see diagonal() * @see @ref diagonal()
*/ */
constexpr static RectangularMatrix<cols, rows, T> fromDiagonal(const Vector<DiagonalSize, T>& diagonal) { constexpr static RectangularMatrix<cols, rows, T> fromDiagonal(const Vector<DiagonalSize, T>& diagonal) {
return RectangularMatrix(typename Implementation::GenerateSequence<cols>::Type(), diagonal); return RectangularMatrix(typename Implementation::GenerateSequence<cols>::Type(), diagonal);
@ -185,7 +185,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* @return One-dimensional array of `cols*rows` length in column-major * @return One-dimensional array of `cols*rows` length in column-major
* order. * order.
* *
* @see operator[] * @see @ref operator[]()
*/ */
T* data() { return _data[0].data(); } T* data() { return _data[0].data(); }
constexpr const T* data() const { return _data[0].data(); } /**< @overload */ constexpr const T* data() const { return _data[0].data(); } /**< @overload */
@ -193,13 +193,14 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief %Matrix column * @brief %Matrix column
* *
* Particular elements can be accessed using Vector::operator[], e.g.: * Particular elements can be accessed using @ref Vector::operator[](),
* e.g.:
* @code * @code
* RectangularMatrix<4, 3, Float> m; * RectangularMatrix<4, 3, Float> m;
* Float a = m[2][1]; * Float a = m[2][1];
* @endcode * @endcode
* *
* @see row(), data() * @see @ref row(), @ref data()
*/ */
Vector<rows, T>& operator[](std::size_t col) { return _data[col]; } Vector<rows, T>& operator[](std::size_t col) { return _data[col]; }
constexpr const Vector<rows, T>& operator[](std::size_t col) const { return _data[col]; } /**< @overload */ constexpr const Vector<rows, T>& operator[](std::size_t col) const { return _data[col]; } /**< @overload */
@ -207,9 +208,10 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief %Matrix row * @brief %Matrix row
* *
* Consider using transposed() when accessing rows frequently, as this * Consider using @ref transposed() when accessing rows frequently, as
* is slower than accessing columns due to the way the matrix is stored. * this is slower than accessing columns due to the way the matrix is
* @see operator[]() * stored.
* @see @ref operator[]()
*/ */
Vector<cols, T> row(std::size_t row) const; Vector<cols, T> row(std::size_t row) const;
@ -224,8 +226,8 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Non-equality operator * @brief Non-equality operator
* *
* @see Vector::operator<(), Vector::operator<=(), Vector::operator>=(), * @see @ref Vector::operator<(), @ref Vector::operator<=(),
* Vector::operator>() * @ref Vector::operator>=(), @ref Vector::operator>()
*/ */
bool operator!=(const RectangularMatrix<cols, rows, T>& other) const { bool operator!=(const RectangularMatrix<cols, rows, T>& other) const {
return !operator==(other); return !operator==(other);
@ -257,7 +259,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Add matrix * @brief Add matrix
* *
* @see operator+=() * @see @ref operator+=()
*/ */
RectangularMatrix<cols, rows, T> operator+(const RectangularMatrix<cols, rows, T>& other) const { RectangularMatrix<cols, rows, T> operator+(const RectangularMatrix<cols, rows, T>& other) const {
return RectangularMatrix<cols, rows, T>(*this)+=other; return RectangularMatrix<cols, rows, T>(*this)+=other;
@ -280,7 +282,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Subtract matrix * @brief Subtract matrix
* *
* @see operator-=() * @see @ref operator-=()
*/ */
RectangularMatrix<cols, rows, T> operator-(const RectangularMatrix<cols, rows, T>& other) const { RectangularMatrix<cols, rows, T> operator-(const RectangularMatrix<cols, rows, T>& other) const {
return RectangularMatrix<cols, rows, T>(*this)-=other; return RectangularMatrix<cols, rows, T>(*this)-=other;
@ -303,7 +305,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Multiply matrix with number * @brief Multiply matrix with number
* *
* @see operator*=(T), operator*(T, const RectangularMatrix<cols, rows, T>&) * @see @ref operator*=(T), @ref operator*(T, const RectangularMatrix<cols, rows, T>&)
*/ */
RectangularMatrix<cols, rows, T> operator*(T number) const { RectangularMatrix<cols, rows, T> operator*(T number) const {
return RectangularMatrix<cols, rows, T>(*this) *= number; return RectangularMatrix<cols, rows, T>(*this) *= number;
@ -326,8 +328,8 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Divide matrix with number * @brief Divide matrix with number
* *
* @see operator/=(T), * @see @ref operator/=(T),
* operator/(T, const RectangularMatrix<cols, rows, T>&) * @ref operator/(T, const RectangularMatrix<cols, rows, T>&)
*/ */
RectangularMatrix<cols, rows, T> operator/(T number) const { RectangularMatrix<cols, rows, T> operator/(T number) const {
return RectangularMatrix<cols, rows, T>(*this) /= number; return RectangularMatrix<cols, rows, T>(*this) /= number;
@ -357,14 +359,14 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Transposed matrix * @brief Transposed matrix
* *
* @see row() * @see @ref row()
*/ */
RectangularMatrix<rows, cols, T> transposed() const; RectangularMatrix<rows, cols, T> transposed() const;
/** /**
* @brief Values on diagonal * @brief Values on diagonal
* *
* @see fromDiagonal() * @see @ref fromDiagonal()
*/ */
constexpr Vector<DiagonalSize, T> diagonal() const; constexpr Vector<DiagonalSize, T> diagonal() const;
@ -375,7 +377,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* of the matrix will make first `rows` elements of resulting vector. * of the matrix will make first `rows` elements of resulting vector.
* Useful for performing vector operations with the matrix (e.g. * Useful for performing vector operations with the matrix (e.g.
* summing the elements etc.). * summing the elements etc.).
* @see fromVector() * @see @ref fromVector()
*/ */
Vector<rows*cols, T> toVector() const { Vector<rows*cols, T> toVector() const {
return *reinterpret_cast<const Vector<rows*cols, T>*>(data()); return *reinterpret_cast<const Vector<rows*cols, T>*>(data());
@ -423,7 +425,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
#ifndef CORRADE_GCC46_COMPATIBILITY #ifndef CORRADE_GCC46_COMPATIBILITY
/** /**
@brief Matrix with 2 columns and 3 rows @brief %Matrix with 2 columns and 3 rows
Convenience alternative to <tt>%RectangularMatrix<2, 3, T></tt>. See Convenience alternative to <tt>%RectangularMatrix<2, 3, T></tt>. See
@ref RectangularMatrix for more information. @ref RectangularMatrix for more information.
@ -436,7 +438,7 @@ template<class T> using Matrix2x3 = RectangularMatrix<2, 3, T>;
#endif #endif
/** /**
@brief Matrix with 3 columns and 2 rows @brief %Matrix with 3 columns and 2 rows
Convenience alternative to <tt>%RectangularMatrix<3, 2, T></tt>. See Convenience alternative to <tt>%RectangularMatrix<3, 2, T></tt>. See
@ref RectangularMatrix for more information. @ref RectangularMatrix for more information.
@ -449,7 +451,7 @@ template<class T> using Matrix3x2 = RectangularMatrix<3, 2, T>;
#endif #endif
/** /**
@brief Matrix with 2 columns and 4 rows @brief %Matrix with 2 columns and 4 rows
Convenience alternative to <tt>%RectangularMatrix<2, 4, T></tt>. See Convenience alternative to <tt>%RectangularMatrix<2, 4, T></tt>. See
@ref RectangularMatrix for more information. @ref RectangularMatrix for more information.
@ -462,7 +464,7 @@ template<class T> using Matrix2x4 = RectangularMatrix<2, 4, T>;
#endif #endif
/** /**
@brief Matrix with 4 columns and 2 rows @brief %Matrix with 4 columns and 2 rows
Convenience alternative to <tt>%RectangularMatrix<4, 2, T></tt>. See Convenience alternative to <tt>%RectangularMatrix<4, 2, T></tt>. See
@ref RectangularMatrix for more information. @ref RectangularMatrix for more information.
@ -475,7 +477,7 @@ template<class T> using Matrix4x2 = RectangularMatrix<4, 2, T>;
#endif #endif
/** /**
@brief Matrix with 3 columns and 4 rows @brief %Matrix with 3 columns and 4 rows
Convenience alternative to <tt>%RectangularMatrix<3, 4, T></tt>. See Convenience alternative to <tt>%RectangularMatrix<3, 4, T></tt>. See
@ref RectangularMatrix for more information. @ref RectangularMatrix for more information.
@ -488,7 +490,7 @@ template<class T> using Matrix3x4 = RectangularMatrix<3, 4, T>;
#endif #endif
/** /**
@brief Matrix with 4 columns and 3 rows @brief %Matrix with 4 columns and 3 rows
Convenience alternative to <tt>%RectangularMatrix<4, 3, T></tt>. See Convenience alternative to <tt>%RectangularMatrix<4, 3, T></tt>. See
@ref RectangularMatrix for more information. @ref RectangularMatrix for more information.
@ -504,7 +506,7 @@ template<class T> using Matrix4x3 = RectangularMatrix<4, 3, T>;
/** @relates RectangularMatrix /** @relates RectangularMatrix
@brief Multiply number with matrix @brief Multiply number with matrix
Same as RectangularMatrix::operator*(T) const. Same as @ref RectangularMatrix::operator*(T) const.
*/ */
template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> operator*( template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> operator*(
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -523,7 +525,7 @@ template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<c
The computation is done column-wise. @f[ The computation is done column-wise. @f[
\boldsymbol B_j = \frac a {\boldsymbol A_j} \boldsymbol B_j = \frac a {\boldsymbol A_j}
@f] @f]
@see RectangularMatrix::operator/(T) const @see @ref RectangularMatrix::operator/(T) const
*/ */
template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> operator/( template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> operator/(
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -547,7 +549,7 @@ template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<c
Internally the same as multiplying one-column matrix with one-row matrix. @f[ Internally the same as multiplying one-column matrix with one-row matrix. @f[
(\boldsymbol {aA})_{ji} = \boldsymbol a_i \boldsymbol A_j (\boldsymbol {aA})_{ji} = \boldsymbol a_i \boldsymbol A_j
@f] @f]
@see RectangularMatrix::operator*(const RectangularMatrix<size, cols, T>&) const @see @ref RectangularMatrix::operator*(const RectangularMatrix<size, cols, T>&) const
*/ */
template<std::size_t size, std::size_t cols, class T> inline RectangularMatrix<cols, size, T> operator*(const Vector<size, T>& vector, const RectangularMatrix<cols, 1, T>& matrix) { template<std::size_t size, std::size_t cols, class T> inline RectangularMatrix<cols, size, T> operator*(const Vector<size, T>& vector, const RectangularMatrix<cols, 1, T>& matrix) {
return RectangularMatrix<1, size, T>(vector)*matrix; return RectangularMatrix<1, size, T>(vector)*matrix;

2
src/Magnum/Math/Swizzle.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Function Magnum::Math::swizzle() * @brief Function @ref Magnum::Math::swizzle()
*/ */
#include "Magnum/Math/Vector.h" #include "Magnum/Math/Vector.h"

8
src/Magnum/Math/Test/FunctionsTest.cpp

@ -213,10 +213,10 @@ void FunctionsTest::lerp() {
CORRADE_COMPARE(Math::lerp(a, b, 0.25f), Vector3(0.0f, 1.0f, 5.0f)); CORRADE_COMPARE(Math::lerp(a, b, 0.25f), Vector3(0.0f, 1.0f, 5.0f));
/* Integer vector */ /* Integer vector */
typedef Math::Vector<3, Int> Vector3ub; typedef Math::Vector<3, Int> Vector3i;
Vector3ub c(0, 128, 64); Vector3i c(0, 128, 64);
Vector3ub d(16, 0, 32); Vector3i d(16, 0, 32);
CORRADE_COMPARE(Math::lerp(c, d, 0.25f), Vector3ub(4, 96, 56)); CORRADE_COMPARE(Math::lerp(c, d, 0.25f), Vector3i(4, 96, 56));
/* Vector as interpolation phase */ /* Vector as interpolation phase */
CORRADE_COMPARE(Math::lerp(a, b, Vector3(0.25f, 0.5f, 0.75f)), Vector3(0.0f, 0.0f, 9.0f)); CORRADE_COMPARE(Math::lerp(a, b, Vector3(0.25f, 0.5f, 0.75f)), Vector3(0.0f, 0.0f, 9.0f));

8
src/Magnum/Math/Test/SwizzleTest.cpp

@ -64,14 +64,14 @@ void SwizzleTest::rgba() {
} }
void SwizzleTest::sizes() { void SwizzleTest::sizes() {
constexpr auto a = swizzle<'y', 'x', 'x'>(Math::Vector<2, Int>(1, 2)); constexpr auto a = swizzle<'y', 'x', 'x'>(Vector<2, Int>(1, 2));
CORRADE_COMPARE(a, (Math::Vector<3, Int>(2, 1, 1))); CORRADE_COMPARE(a, (Vector<3, Int>(2, 1, 1)));
constexpr auto b = swizzle<'z'>(Vector4i(1, 2, 3, 4)); constexpr auto b = swizzle<'z'>(Vector4i(1, 2, 3, 4));
CORRADE_COMPARE(b, (Math::Vector<1, Int>(3))); CORRADE_COMPARE(b, (Vector<1, Int>(3)));
constexpr auto c = swizzle<'z', 'x', 'w', 'y', 'z', 'y', 'x'>(Vector4i(1, 2, 3, 4)); constexpr auto c = swizzle<'z', 'x', 'w', 'y', 'z', 'y', 'x'>(Vector4i(1, 2, 3, 4));
CORRADE_COMPARE(c, (Math::Vector<7, Int>(3, 1, 4, 2, 3, 2, 1))); CORRADE_COMPARE(c, (Vector<7, Int>(3, 1, 4, 2, 3, 2, 1)));
} }
}}} }}}

6
src/Magnum/Math/TypeTraits.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::TypeTraits * @brief Class @ref Magnum::Math::TypeTraits
*/ */
#include <cmath> #include <cmath>
@ -100,8 +100,8 @@ template<class T> struct TypeTraits: Implementation::TypeTraitsDefault<T> {
/** /**
* @brief Fuzzy compare * @brief Fuzzy compare
* *
* Uses fuzzy compare for floating-point types (using epsilon() value), * Uses fuzzy compare for floating-point types (using @ref epsilon()
* pure equality comparison everywhere else. * value), pure equality comparison everywhere else.
*/ */
static bool equals(T a, T b); static bool equals(T a, T b);
#endif #endif

4
src/Magnum/Math/Unit.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Unit * @brief Class @ref Magnum::Math::Unit
*/ */
#include "Magnum/Math/TypeTraits.h" #include "Magnum/Math/TypeTraits.h"
@ -37,7 +37,7 @@ namespace Magnum { namespace Math {
@brief Base class for units @brief Base class for units
@tparam T Underlying data type @tparam T Underlying data type
@see Deg, Rad @see @ref Deg, @ref Rad
*/ */
template<template<class> class Derived, class T> class Unit { template<template<class> class Derived, class T> class Unit {
template<template<class> class, class> friend class Unit; template<template<class> class, class> friend class Unit;

135
src/Magnum/Math/Vector.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Vector * @brief Class @ref Magnum::Math::Vector
*/ */
#include <cmath> #include <cmath>
@ -92,7 +92,9 @@ template<std::size_t size, class T> class Vector {
* antiparallel. @f[ * antiparallel. @f[
* \boldsymbol a \cdot \boldsymbol b = \sum_{i=0}^{n-1} \boldsymbol a_i \boldsymbol b_i * \boldsymbol a \cdot \boldsymbol b = \sum_{i=0}^{n-1} \boldsymbol a_i \boldsymbol b_i
* @f] * @f]
* @see dot() const, operator-(), Vector2::perpendicular() * @see dot() const, @ref operator-(),
* @ref Vector2::perpendicular()
* @todoc Explicit reference when Doxygen can handle const
*/ */
static T dot(const Vector<size, T>& a, const Vector<size, T>& b) { static T dot(const Vector<size, T>& a, const Vector<size, T>& b) {
return (a*b).sum(); return (a*b).sum();
@ -104,7 +106,8 @@ template<std::size_t size, class T> class Vector {
* Expects that both vectors are normalized. @f[ * Expects that both vectors are normalized. @f[
* \theta = acos \left( \frac{\boldsymbol a \cdot \boldsymbol b}{|\boldsymbol a| |\boldsymbol b|} \right) = acos (\boldsymbol a \cdot \boldsymbol b) * \theta = acos \left( \frac{\boldsymbol a \cdot \boldsymbol b}{|\boldsymbol a| |\boldsymbol b|} \right) = acos (\boldsymbol a \cdot \boldsymbol b)
* @f] * @f]
* @see isNormalized(), Quaternion::angle(), Complex::angle() * @see @ref isNormalized(), @ref Quaternion::angle(),
* @ref Complex::angle()
*/ */
static Rad<T> angle(const Vector<size, T>& normalizedA, const Vector<size, T>& normalizedB); static Rad<T> angle(const Vector<size, T>& normalizedA, const Vector<size, T>& normalizedB);
@ -202,7 +205,7 @@ template<std::size_t size, class T> class Vector {
* @brief Raw data * @brief Raw data
* @return One-dimensional array of `size` length. * @return One-dimensional array of `size` length.
* *
* @see operator[]() * @see @ref operator[]()
*/ */
T* data() { T* data() {
#ifndef CORRADE_MSVC2013_COMPATIBILITY #ifndef CORRADE_MSVC2013_COMPATIBILITY
@ -224,7 +227,7 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief Value at given position * @brief Value at given position
* *
* @see data() * @see @ref data()
*/ */
T& operator[](std::size_t pos) { return _data[pos]; } T& operator[](std::size_t pos) { return _data[pos]; }
constexpr T operator[](std::size_t pos) const { return _data[pos]; } /**< @overload */ constexpr T operator[](std::size_t pos) const { return _data[pos]; } /**< @overload */
@ -260,7 +263,7 @@ template<std::size_t size, class T> class Vector {
* @f[ * @f[
* |\boldsymbol a \cdot \boldsymbol a - 0| < \epsilon^2 \cong \epsilon * |\boldsymbol a \cdot \boldsymbol a - 0| < \epsilon^2 \cong \epsilon
* @f] * @f]
* @see dot(), normalized() * @see @ref dot(), @ref normalized()
*/ */
bool isZero() const { bool isZero() const {
return Implementation::isZeroSquared(dot()); return Implementation::isZeroSquared(dot());
@ -272,7 +275,7 @@ template<std::size_t size, class T> class Vector {
* The vector is normalized if it has unit length: @f[ * The vector is normalized if it has unit length: @f[
* |\boldsymbol a \cdot \boldsymbol a - 1| < 2 \epsilon + \epsilon^2 \cong 2 \epsilon * |\boldsymbol a \cdot \boldsymbol a - 1| < 2 \epsilon + \epsilon^2 \cong 2 \epsilon
* @f] * @f]
* @see dot(), normalized() * @see @ref dot(), @ref normalized()
*/ */
bool isNormalized() const { bool isNormalized() const {
return Implementation::isNormalizedSquared(dot()); return Implementation::isNormalizedSquared(dot());
@ -284,7 +287,7 @@ template<std::size_t size, class T> class Vector {
* @f[ * @f[
* \boldsymbol b_i = -\boldsymbol a_i * \boldsymbol b_i = -\boldsymbol a_i
* @f] * @f]
* @see Vector2::perpendicular() * @see @ref Vector2::perpendicular()
*/ */
Vector<size, T> operator-() const; Vector<size, T> operator-() const;
@ -305,7 +308,7 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief Add vector * @brief Add vector
* *
* @see operator+=(), sum() * @see @ref operator+=(), @ref sum()
*/ */
Vector<size, T> operator+(const Vector<size, T>& other) const { Vector<size, T> operator+(const Vector<size, T>& other) const {
return Vector<size, T>(*this) += other; return Vector<size, T>(*this) += other;
@ -328,7 +331,7 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief Subtract vector * @brief Subtract vector
* *
* @see operator-=() * @see @ref operator-=()
*/ */
Vector<size, T> operator-(const Vector<size, T>& other) const { Vector<size, T> operator-(const Vector<size, T>& other) const {
return Vector<size, T>(*this) -= other; return Vector<size, T>(*this) -= other;
@ -340,8 +343,8 @@ template<std::size_t size, class T> class Vector {
* The computation is done in-place. @f[ * The computation is done in-place. @f[
* \boldsymbol a_i = b \boldsymbol a_i * \boldsymbol a_i = b \boldsymbol a_i
* @f] * @f]
* @see operator*=(const Vector<size, T>&), * @see @ref operator*=(const Vector<size, T>&),
* operator*=(Vector<size, Integral>&, FloatingPoint) * @ref operator*=(Vector<size, Integral>&, FloatingPoint)
*/ */
Vector<size, T>& operator*=(T number) { Vector<size, T>& operator*=(T number) {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
@ -353,9 +356,9 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief Multiply vector with number * @brief Multiply vector with number
* *
* @see operator*(const Vector<size, T>&) const, * @see @ref operator*(const Vector<size, T>&) const,
* operator*=(T), operator*(T, const Vector<size, T>&), * @ref operator*=(T), operator*(T, const Vector<size, T>&),
* operator*(const Vector<size, Integral>&, FloatingPoint) * @ref operator*(const Vector<size, Integral>&, FloatingPoint)
*/ */
Vector<size, T> operator*(T number) const { Vector<size, T> operator*(T number) const {
return Vector<size, T>(*this) *= number; return Vector<size, T>(*this) *= number;
@ -367,8 +370,8 @@ template<std::size_t size, class T> class Vector {
* The computation is done in-place. @f[ * The computation is done in-place. @f[
* \boldsymbol a_i = \frac{\boldsymbol a_i} b * \boldsymbol a_i = \frac{\boldsymbol a_i} b
* @f] * @f]
* @see operator/=(const Vector<size, T>&), * @see @ref operator/=(const Vector<size, T>&),
* operator/=(Vector<size, Integral>&, FloatingPoint) * @ref operator/=(Vector<size, Integral>&, FloatingPoint)
*/ */
Vector<size, T>& operator/=(T number) { Vector<size, T>& operator/=(T number) {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
@ -380,9 +383,9 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief Divide vector with number * @brief Divide vector with number
* *
* @see operator/(const Vector<size, T>&) const, * @see @ref operator/(const Vector<size, T>&) const,
* operator/=(T), operator/(T, const Vector<size, T>&), * @ref operator/=(T), operator/(T, const Vector<size, T>&),
* operator/(const Vector<size, Integral>&, FloatingPoint) * @ref operator/(const Vector<size, Integral>&, FloatingPoint)
*/ */
Vector<size, T> operator/(T number) const { Vector<size, T> operator/(T number) const {
return Vector<size, T>(*this) /= number; return Vector<size, T>(*this) /= number;
@ -394,8 +397,8 @@ template<std::size_t size, class T> class Vector {
* The computation is done in-place. @f[ * The computation is done in-place. @f[
* \boldsymbol a_i = \boldsymbol a_i \boldsymbol b_i * \boldsymbol a_i = \boldsymbol a_i \boldsymbol b_i
* @f] * @f]
* @see operator*=(T), * @see @ref operator*=(T),
* operator*=(Vector<size, Integral>&, const Vector<size, FloatingPoint>&) * @ref operator*=(Vector<size, Integral>&, const Vector<size, FloatingPoint>&)
*/ */
Vector<size, T>& operator*=(const Vector<size, T>& other) { Vector<size, T>& operator*=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
@ -407,8 +410,8 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief Multiply vector component-wise * @brief Multiply vector component-wise
* *
* @see operator*(T) const, operator*=(const Vector<size, T>&), * @see @ref operator*(T) const, @ref operator*=(const Vector<size, T>&),
* operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&), * @ref operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&),
* @ref product() * @ref product()
*/ */
Vector<size, T> operator*(const Vector<size, T>& other) const { Vector<size, T> operator*(const Vector<size, T>& other) const {
@ -421,8 +424,8 @@ template<std::size_t size, class T> class Vector {
* The computation is done in-place. @f[ * The computation is done in-place. @f[
* \boldsymbol a_i = \frac{\boldsymbol a_i}{\boldsymbol b_i} * \boldsymbol a_i = \frac{\boldsymbol a_i}{\boldsymbol b_i}
* @f] * @f]
* @see operator/=(T), * @see @ref operator/=(T),
* operator/=(Vector<size, Integral>&, const Vector<size, FloatingPoint>&) * @ref operator/=(Vector<size, Integral>&, const Vector<size, FloatingPoint>&)
*/ */
Vector<size, T>& operator/=(const Vector<size, T>& other) { Vector<size, T>& operator/=(const Vector<size, T>& other) {
for(std::size_t i = 0; i != size; ++i) for(std::size_t i = 0; i != size; ++i)
@ -434,8 +437,8 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief Divide vector component-wise * @brief Divide vector component-wise
* *
* @see operator/(T) const, operator/=(const Vector<size, T>&), * @see @ref operator/(T) const, @ref operator/=(const Vector<size, T>&),
* operator/(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&) * @ref operator/(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&)
*/ */
Vector<size, T> operator/(const Vector<size, T>& other) const { Vector<size, T> operator/(const Vector<size, T>& other) const {
return Vector<size, T>(*this) /= other; return Vector<size, T>(*this) /= other;
@ -444,22 +447,24 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief Dot product of the vector * @brief Dot product of the vector
* *
* Should be used instead of length() for comparing vector length with * Should be used instead of @ref length() for comparing vector length
* other values, because it doesn't compute the square root. @f[ * with other values, because it doesn't compute the square root. @f[
* \boldsymbol a \cdot \boldsymbol a = \sum_{i=0}^{n-1} \boldsymbol a_i^2 * \boldsymbol a \cdot \boldsymbol a = \sum_{i=0}^{n-1} \boldsymbol a_i^2
* @f] * @f]
* @see dot(const Vector<size, T>&, const Vector<size, T>&), isNormalized() * @see @ref dot(const Vector<size, T>&, const Vector<size, T>&),
* @ref isNormalized()
*/ */
T dot() const { return dot(*this, *this); } T dot() const { return dot(*this, *this); }
/** /**
* @brief %Vector length * @brief %Vector length
* *
* See also dot() const which is faster for comparing length with other * See also @ref dot() const which is faster for comparing length with
* values. @f[ * other values. @f[
* |\boldsymbol a| = \sqrt{\boldsymbol a \cdot \boldsymbol a} * |\boldsymbol a| = \sqrt{\boldsymbol a \cdot \boldsymbol a}
* @f] * @f]
* @see lengthInverted(), Math::sqrt(), normalized(), resized() * @see @ref lengthInverted(), @ref Math::sqrt(), @ref normalized(),
* @ref resized()
* @todo something like std::hypot() for possibly better precision? * @todo something like std::hypot() for possibly better precision?
*/ */
T length() const { return std::sqrt(dot()); } T length() const { return std::sqrt(dot()); }
@ -470,14 +475,15 @@ template<std::size_t size, class T> class Vector {
* @f[ * @f[
* \frac{1}{|\boldsymbol a|} = \frac{1}{\sqrt{\boldsymbol a \cdot \boldsymbol a}} * \frac{1}{|\boldsymbol a|} = \frac{1}{\sqrt{\boldsymbol a \cdot \boldsymbol a}}
* @f] * @f]
* @see length(), Math::sqrtInverted(), normalized(), resized() * @see @ref length(), @ref Math::sqrtInverted(), @ref normalized(),
* @ref resized()
*/ */
T lengthInverted() const { return T(1)/length(); } T lengthInverted() const { return T(1)/length(); }
/** /**
* @brief Normalized vector (of unit length) * @brief Normalized vector (of unit length)
* *
* @see isNormalized(), lengthInverted(), resized() * @see @ref isNormalized(), @ref lengthInverted(), @ref resized()
*/ */
Vector<size, T> normalized() const { return *this*lengthInverted(); } Vector<size, T> normalized() const { return *this*lengthInverted(); }
@ -485,12 +491,12 @@ template<std::size_t size, class T> class Vector {
* @brief Resized vector * @brief Resized vector
* *
* Convenience equivalent to the following code. Due to operation order * Convenience equivalent to the following code. Due to operation order
* this function is faster than the obvious way of sizing normalized() * this function is faster than the obvious way of sizing
* vector. * @ref normalized() vector.
* @code * @code
* vec*(vec.lengthInverted()*length) // the brackets are important * vec*(vec.lengthInverted()*length) // the brackets are important
* @endcode * @endcode
* @see normalized() * @see @ref normalized()
*/ */
Vector<size, T> resized(T length) const { Vector<size, T> resized(T length) const {
return *this*(lengthInverted()*length); return *this*(lengthInverted()*length);
@ -502,7 +508,7 @@ template<std::size_t size, class T> class Vector {
* Returns vector projected onto @p line. @f[ * Returns vector projected onto @p line. @f[
* \boldsymbol a_1 = \frac{\boldsymbol a \cdot \boldsymbol b}{\boldsymbol b \cdot \boldsymbol b} \boldsymbol b * \boldsymbol a_1 = \frac{\boldsymbol a \cdot \boldsymbol b}{\boldsymbol b \cdot \boldsymbol b} \boldsymbol b
* @f] * @f]
* @see dot(), projectedOntoNormalized() * @see @ref dot(), @ref projectedOntoNormalized()
*/ */
Vector<size, T> projected(const Vector<size, T>& line) const { Vector<size, T> projected(const Vector<size, T>& line) const {
return line*dot(*this, line)/line.dot(); return line*dot(*this, line)/line.dot();
@ -511,26 +517,27 @@ template<std::size_t size, class T> class Vector {
/** /**
* @brief %Vector projected onto normalized line * @brief %Vector projected onto normalized line
* *
* Slightly faster alternative to projected(), expects @p line to be * Slightly faster alternative to @ref projected(), expects @p line to
* normalized. @f[ * be normalized. @f[
* \boldsymbol a_1 = \frac{\boldsymbol a \cdot \boldsymbol b}{\boldsymbol b \cdot \boldsymbol b} \boldsymbol b = * \boldsymbol a_1 = \frac{\boldsymbol a \cdot \boldsymbol b}{\boldsymbol b \cdot \boldsymbol b} \boldsymbol b =
* (\boldsymbol a \cdot \boldsymbol b) \boldsymbol b * (\boldsymbol a \cdot \boldsymbol b) \boldsymbol b
* @f] * @f]
* @see dot() * @see dot() const
* @todoc Explicit reference when Doxygen can handle const
*/ */
Vector<size, T> projectedOntoNormalized(const Vector<size, T>& line) const; Vector<size, T> projectedOntoNormalized(const Vector<size, T>& line) const;
/** /**
* @brief Sum of values in the vector * @brief Sum of values in the vector
* *
* @see operator+() * @see @ref operator+()
*/ */
T sum() const; T sum() const;
/** /**
* @brief Product of values in the vector * @brief Product of values in the vector
* *
* @see operator*(const Vector<size, T>&) const * @see @ref operator*(const Vector<size, T>&) const
*/ */
T product() const; T product() const;
@ -575,7 +582,7 @@ template<std::size_t size, class T> class Vector {
/** @relates Vector /** @relates Vector
@brief Multiply number with vector @brief Multiply number with vector
Same as Vector::operator*(T) const. Same as @ref Vector::operator*(T) const.
*/ */
template<std::size_t size, class T> inline Vector<size, T> operator*( template<std::size_t size, class T> inline Vector<size, T> operator*(
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -594,7 +601,7 @@ template<std::size_t size, class T> inline Vector<size, T> operator*(
@f[ @f[
\boldsymbol c_i = \frac b {\boldsymbol a_i} \boldsymbol c_i = \frac b {\boldsymbol a_i}
@f] @f]
@see Vector::operator/(T) const @see @ref Vector::operator/(T) const
*/ */
template<std::size_t size, class T> inline Vector<size, T> operator/( template<std::size_t size, class T> inline Vector<size, T> operator/(
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -883,8 +890,8 @@ operator>>(const Vector<size, Integral>& vector,
/** @relates Vector /** @relates Vector
@brief Multiply integral vector with floating-point number and assign @brief Multiply integral vector with floating-point number and assign
Similar to Vector::operator*=(T), except that the multiplication is done in Similar to @ref Vector::operator*=(T), except that the multiplication is done
floating-point. The computation is done in-place. in floating-point. The computation is done in-place.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -902,8 +909,8 @@ operator*=(Vector<size, Integral>& vector, FloatingPoint number) {
/** @relates Vector /** @relates Vector
@brief Multiply integral vector with floating-point number @brief Multiply integral vector with floating-point number
Similar to Vector::operator*(T) const, except that the multiplication is done Similar to @ref Vector::operator*(T) const, except that the multiplication is
in floating-point. done in floating-point.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -919,7 +926,7 @@ operator*(const Vector<size, Integral>& vector, FloatingPoint number) {
/** @relates Vector /** @relates Vector
@brief Multiply floating-point number with integral vector @brief Multiply floating-point number with integral vector
Same as operator*(const Vector<size, Integral>&, FloatingPoint). Same as @ref operator*(const Vector<size, Integral>&, FloatingPoint).
*/ */
template<std::size_t size, class FloatingPoint, class Integral> inline template<std::size_t size, class FloatingPoint, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -934,7 +941,7 @@ operator*(FloatingPoint number, const Vector<size, Integral>& vector) {
/** @relates Vector /** @relates Vector
@brief Divide integral vector with floating-point number and assign @brief Divide integral vector with floating-point number and assign
Similar to Vector::operator/=(T), except that the division is done in Similar to @ref Vector::operator/=(T), except that the division is done in
floating-point. The computation is done in-place. floating-point. The computation is done in-place.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline
@ -953,7 +960,7 @@ operator/=(Vector<size, Integral>& vector, FloatingPoint number) {
/** @relates Vector /** @relates Vector
@brief Divide integral vector with floating-point number @brief Divide integral vector with floating-point number
Similar to Vector::operator/(T) const, except that the division is done in Similar to @ref Vector::operator/(T) const, except that the division is done in
floating-point. floating-point.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline
@ -970,7 +977,7 @@ operator/(const Vector<size, Integral>& vector, FloatingPoint number) {
/** @relates Vector /** @relates Vector
@brief Multiply integral vector with floating-point vector component-wise and assign @brief Multiply integral vector with floating-point vector component-wise and assign
Similar to Vector::operator*=(const Vector<size, T>&), except that the Similar to @ref Vector::operator*=(const Vector<size, T>&), except that the
multiplication is done in floating-point. The computation is done in-place. multiplication is done in floating-point. The computation is done in-place.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline
@ -989,10 +996,10 @@ operator*=(Vector<size, Integral>& a, const Vector<size, FloatingPoint>& b) {
/** @relates Vector /** @relates Vector
@brief Multiply integral vector with floating-point vector component-wise @brief Multiply integral vector with floating-point vector component-wise
Similar to Vector::operator*(const Vector<size, T>&) const, except that the Similar to @ref Vector::operator*(const Vector<size, T>&) const, except that
multiplication is done in floating-point. The result is always integral vector, the multiplication is done in floating-point. The result is always integral
convert both arguments to the same floating-point type to have floating-point vector, convert both arguments to the same floating-point type to have
result. floating-point result.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -1008,7 +1015,7 @@ operator*(const Vector<size, Integral>& a, const Vector<size, FloatingPoint>& b)
/** @relates Vector /** @relates Vector
@brief Multiply floating-point vector with integral vector component-wise @brief Multiply floating-point vector with integral vector component-wise
Same as operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&). Same as @ref operator*(const Vector<size, Integral>&, const Vector<size, FloatingPoint>&).
*/ */
template<std::size_t size, class FloatingPoint, class Integral> inline template<std::size_t size, class FloatingPoint, class Integral> inline
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -1023,8 +1030,8 @@ operator*(const Vector<size, FloatingPoint>& a, const Vector<size, Integral>& b)
/** @relates Vector /** @relates Vector
@brief Divide integral vector with floating-point vector component-wise and assign @brief Divide integral vector with floating-point vector component-wise and assign
Similar to Vector::operator/=(const Vector<size, T>&), except that the division Similar to @ref Vector::operator/=(const Vector<size, T>&), except that the
is done in floating-point. The computation is done in-place. division is done in floating-point. The computation is done in-place.
*/ */
template<std::size_t size, class Integral, class FloatingPoint> inline template<std::size_t size, class Integral, class FloatingPoint> inline
#ifdef DOXYGEN_GENERATING_OUTPUT #ifdef DOXYGEN_GENERATING_OUTPUT
@ -1042,8 +1049,8 @@ operator/=(Vector<size, Integral>& a, const Vector<size, FloatingPoint>& b) {
/** @relates Vector /** @relates Vector
@brief Divide integral vector with floating-point vector component-wise @brief Divide integral vector with floating-point vector component-wise
Similar to Vector::operator/(const Vector<size, T>&) const, except that the Similar to @ref Vector::operator/(const Vector<size, T>&) const, except that
division is done in floating-point. The result is always integral vector, the division is done in floating-point. The result is always integral vector,
convert both arguments to the same floating-point type to have floating-point convert both arguments to the same floating-point type to have floating-point
result. result.
*/ */

28
src/Magnum/Math/Vector2.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Vector2 * @brief Class @ref Magnum::Math::Vector2
*/ */
#include "Magnum/Math/Vector.h" #include "Magnum/Math/Vector.h"
@ -38,7 +38,8 @@ namespace Magnum { namespace Math {
@tparam T Data type @tparam T Data type
See @ref matrix-vector for brief introduction. See @ref matrix-vector for brief introduction.
@see Magnum::Vector2, Magnum::Vector2i, Magnum::Vector2ui, Magnum::Vector2d @see @ref Magnum::Vector2, @ref Magnum::Vector2i, @ref Magnum::Vector2ui,
@ref Magnum::Vector2d
@configurationvalueref{Magnum::Math::Vector2} @configurationvalueref{Magnum::Math::Vector2}
*/ */
template<class T> class Vector2: public Vector<2, T> { template<class T> class Vector2: public Vector<2, T> {
@ -50,15 +51,15 @@ template<class T> class Vector2: public Vector<2, T> {
* @code * @code
* Matrix3::translation(Vector2::xAxis(5.0f)); // same as Matrix3::translation({5.0f, 0.0f}); * Matrix3::translation(Vector2::xAxis(5.0f)); // same as Matrix3::translation({5.0f, 0.0f});
* @endcode * @endcode
* @see yAxis(), xScale(), Matrix3::right() * @see @ref yAxis(), @ref xScale(), @ref Matrix3::right()
*/ */
constexpr static Vector2<T> xAxis(T length = T(1)) { return {length, T(0)}; } constexpr static Vector2<T> xAxis(T length = T(1)) { return {length, T(0)}; }
/** /**
* @brief %Vector in direction of Y axis (up) * @brief %Vector in direction of Y axis (up)
* *
* See xAxis() for more information. * See @ref xAxis() for more information.
* @see yScale(), Matrix3::up() * @see @ref yScale(), @ref Matrix3::up()
*/ */
constexpr static Vector2<T> yAxis(T length = T(1)) { return {T(0), length}; } constexpr static Vector2<T> yAxis(T length = T(1)) { return {T(0), length}; }
@ -69,15 +70,15 @@ template<class T> class Vector2: public Vector<2, T> {
* @code * @code
* Matrix3::scaling(Vector2::xScale(-2.0f)); // same as Matrix3::scaling({-2.0f, 1.0f}); * Matrix3::scaling(Vector2::xScale(-2.0f)); // same as Matrix3::scaling({-2.0f, 1.0f});
* @endcode * @endcode
* @see yScale(), xAxis() * @see @ref yScale(), @ref xAxis()
*/ */
constexpr static Vector2<T> xScale(T scale) { return {scale, T(1)}; } constexpr static Vector2<T> xScale(T scale) { return {scale, T(1)}; }
/** /**
* @brief Scaling vector in direction of Y axis (height) * @brief Scaling vector in direction of Y axis (height)
* *
* See xScale() for more information. * See @ref xScale() for more information.
* @see yAxis() * @see @ref yAxis()
*/ */
constexpr static Vector2<T> yScale(T scale) { return {T(1), scale}; } constexpr static Vector2<T> yScale(T scale) { return {T(1), scale}; }
@ -85,12 +86,13 @@ template<class T> class Vector2: public Vector<2, T> {
* @brief 2D cross product * @brief 2D cross product
* *
* 2D version of cross product, also called perp-dot product, * 2D version of cross product, also called perp-dot product,
* equivalent to calling Vector3::cross() with Z coordinate set to `0` * equivalent to calling @ref Vector3::cross() with Z coordinate set to
* and extracting only Z coordinate from the result (X and Y * `0` and extracting only Z coordinate from the result (X and Y
* coordinates are always zero). @f[ * coordinates are always zero). @f[
* \boldsymbol a \times \boldsymbol b = \boldsymbol a_\bot \cdot \boldsymbol b = a_xb_y - a_yb_x * \boldsymbol a \times \boldsymbol b = \boldsymbol a_\bot \cdot \boldsymbol b = a_xb_y - a_yb_x
* @f] * @f]
* @see perpendicular(), dot(const Vector&, const Vector&) * @see @ref perpendicular(),
* @ref dot(const Vector<size, T>&, const Vector<size, T>&)
*/ */
static T cross(const Vector2<T>& a, const Vector2<T>& b) { static T cross(const Vector2<T>& a, const Vector2<T>& b) {
return Vector<2, T>::dot(a.perpendicular(), b); return Vector<2, T>::dot(a.perpendicular(), b);
@ -135,7 +137,9 @@ template<class T> class Vector2: public Vector<2, T> {
* Returns vector rotated 90° counterclockwise. @f[ * Returns vector rotated 90° counterclockwise. @f[
* \boldsymbol v_\bot = \begin{pmatrix} -v_y \\ v_x \end{pmatrix} * \boldsymbol v_\bot = \begin{pmatrix} -v_y \\ v_x \end{pmatrix}
* @f] * @f]
* @see cross(), dot(const Vector&, const Vector&), operator-() const * @see @ref cross(),
* @ref dot(const Vector<size, T>&, const Vector<size, T>&),
* @ref operator-() const
*/ */
Vector2<T> perpendicular() const { return {-y(), x()}; } Vector2<T> perpendicular() const { return {-y(), x()}; }

9
src/Magnum/Math/Vector3.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Class Magnum::Math::Vector3 * @brief Class @ref Magnum::Math::Vector3
*/ */
#include "Magnum/Math/Vector2.h" #include "Magnum/Math/Vector2.h"
@ -39,7 +39,8 @@ namespace Magnum { namespace Math {
@tparam T Data type @tparam T Data type
See @ref matrix-vector for brief introduction. See @ref matrix-vector for brief introduction.
@see Magnum::Vector3, Magnum::Vector3i, Magnum::Vector3ui, Magnum::Vector3d @see @ref Magnum::Vector3, @ref Magnum::Vector3i, @ref Magnum::Vector3ui,
@ref Magnum::Vector3d
@configurationvalueref{Magnum::Math::Vector3} @configurationvalueref{Magnum::Math::Vector3}
*/ */
template<class T> class Vector3: public Vector<3, T> { template<class T> class Vector3: public Vector<3, T> {
@ -107,7 +108,7 @@ template<class T> class Vector3: public Vector<3, T> {
* \boldsymbol a \times \boldsymbol b = * \boldsymbol a \times \boldsymbol b =
* \begin{pmatrix}a_yb_z - a_zb_y \\ a_zb_y - a_xb_z \\ a_xb_y - a_yb_x \end{pmatrix} * \begin{pmatrix}a_yb_z - a_zb_y \\ a_zb_y - a_xb_z \\ a_xb_y - a_yb_x \end{pmatrix}
* @f] * @f]
* @see Vector2::cross() * @see @ref Vector2::cross()
*/ */
static Vector3<T> cross(const Vector3<T>& a, const Vector3<T>& b) { static Vector3<T> cross(const Vector3<T>& a, const Vector3<T>& b) {
return swizzle<'y', 'z', 'x'>(a)*swizzle<'z', 'x', 'y'>(b) - return swizzle<'y', 'z', 'x'>(a)*swizzle<'z', 'x', 'y'>(b) -
@ -203,7 +204,7 @@ template<class T> class Vector3: public Vector<3, T> {
* @brief XY part of the vector * @brief XY part of the vector
* @return First two components of the vector * @return First two components of the vector
* *
* @see swizzle() * @see @ref swizzle()
*/ */
Vector2<T>& xy() { return Vector2<T>::from(Vector<3, T>::data()); } Vector2<T>& xy() { return Vector2<T>::from(Vector<3, T>::data()); }
constexpr const Vector2<T> xy() const { return {x(), y()}; } /**< @overload */ constexpr const Vector2<T> xy() const { return {x(), y()}; } /**< @overload */

3
src/Magnum/Math/Vector4.h

@ -38,7 +38,8 @@ namespace Magnum { namespace Math {
@tparam T Data type @tparam T Data type
See @ref matrix-vector for brief introduction. See @ref matrix-vector for brief introduction.
@see Magnum::Vector4, Magnum::Vector4i, Magnum::Vector4ui, Magnum::Vector4d @see @ref Magnum::Vector4, @ref Magnum::Vector4i, @ref Magnum::Vector4ui,
@ref Magnum::Vector4d
@configurationvalueref{Magnum::Math::Vector4} @configurationvalueref{Magnum::Math::Vector4}
*/ */
template<class T> class Vector4: public Vector<4, T> { template<class T> class Vector4: public Vector<4, T> {

1
src/Magnum/Mesh.cpp

@ -307,6 +307,7 @@ void Mesh::createImplementationVAO() {
//glGenVertexArraysOES(1, &_id); //glGenVertexArraysOES(1, &_id);
CORRADE_INTERNAL_ASSERT(false); CORRADE_INTERNAL_ASSERT(false);
#endif #endif
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
} }
void Mesh::destroyImplementationDefault() {} void Mesh::destroyImplementationDefault() {}

23
src/Magnum/Mesh.h

@ -743,18 +743,21 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
/** /**
* @brief Draw the mesh * @brief Draw the mesh
* @param shader Shader to use for drawing * @param shader %Shader to use for drawing
* *
* Expects that the shader is compatible with this mesh and is fully * Expects that the shader is compatible with this mesh and is fully
* set up. If vertex/index count or instance count is `0`, no draw * set up. If vertex/index count or instance count is `0`, no draw
* commands are issued. See also * commands are issued. See also
* @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation" * @ref AbstractShaderProgram-rendering-workflow "AbstractShaderProgram documentation"
* for more information. * for more information.
* @see @ref setCount(), @ref setInstanceCount(), @fn_gl{UseProgram}, * @see @ref setCount(), @ref setInstanceCount(),
* @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer}, * @ref MeshView::draw(AbstractShaderProgram&),
* @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray} * @ref MeshView::draw(AbstractShaderProgram&, std::initializer_list<std::reference_wrapper<MeshView>>),
* or @fn_gl{BindVertexArray} (if @extension{APPLE,vertex_array_object} * @fn_gl{UseProgram}, @fn_gl{EnableVertexAttribArray},
* is available), @fn_gl{DrawArrays}/@fn_gl{DrawArraysInstanced}/ * @fn_gl{BindBuffer}, @fn_gl{VertexAttribPointer},
* @fn_gl{DisableVertexAttribArray} or @fn_gl{BindVertexArray} (if
* @extension{APPLE,vertex_array_object} is available),
* @fn_gl{DrawArrays}/@fn_gl{DrawArraysInstanced}/
* @fn_gl{DrawArraysInstancedBaseInstance} or @fn_gl{DrawElements}/ * @fn_gl{DrawArraysInstancedBaseInstance} or @fn_gl{DrawElements}/
* @fn_gl{DrawRangeElements}/@fn_gl{DrawElementsBaseVertex}/ * @fn_gl{DrawRangeElements}/@fn_gl{DrawElementsBaseVertex}/
* @fn_gl{DrawRangeElementsBaseVertex}/@fn_gl{DrawElementsInstanced}/ * @fn_gl{DrawRangeElementsBaseVertex}/@fn_gl{DrawElementsInstanced}/
@ -985,17 +988,17 @@ class MAGNUM_EXPORT Mesh: public AbstractObject {
#endif #endif
}; };
/** @debugoperator{Magnum::Mesh} */ /** @debugoperatorenum{Magnum::MeshPrimitive} */
Debug MAGNUM_EXPORT operator<<(Debug debug, MeshPrimitive value); Debug MAGNUM_EXPORT operator<<(Debug debug, MeshPrimitive value);
/** @debugoperator{Magnum::Mesh} */ /** @debugoperatorclassenum{Magnum::Mesh,Magnum::Mesh::IndexType} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Mesh::IndexType value); Debug MAGNUM_EXPORT operator<<(Debug debug, Mesh::IndexType value);
} }
namespace Corrade { namespace Utility { namespace Corrade { namespace Utility {
/** @configurationvalue{Magnum::Mesh} */ /** @configurationvalue{Magnum::MeshPrimitive} */
template<> struct MAGNUM_EXPORT ConfigurationValue<Magnum::MeshPrimitive> { template<> struct MAGNUM_EXPORT ConfigurationValue<Magnum::MeshPrimitive> {
ConfigurationValue() = delete; ConfigurationValue() = delete;
@ -1014,7 +1017,7 @@ template<> struct MAGNUM_EXPORT ConfigurationValue<Magnum::MeshPrimitive> {
static Magnum::MeshPrimitive fromString(const std::string& stringValue, ConfigurationValueFlags); static Magnum::MeshPrimitive fromString(const std::string& stringValue, ConfigurationValueFlags);
}; };
/** @configurationvalue{Magnum::Mesh} */ /** @configurationvalue{Magnum::Mesh::IndexType} */
template<> struct MAGNUM_EXPORT ConfigurationValue<Magnum::Mesh::IndexType> { template<> struct MAGNUM_EXPORT ConfigurationValue<Magnum::Mesh::IndexType> {
ConfigurationValue() = delete; ConfigurationValue() = delete;

4
src/Magnum/MeshTools/CombineIndexedArrays.h

@ -194,8 +194,8 @@ template<class ...T> std::vector<UnsignedInt> combineIndexedArrays(const std::pa
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
/** /**
* @copybrief combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&...) * @copybrief combineIndexedArrays()
* @deprecated Use @ref Magnum::MeshTools::combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&...) "combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&...)" instead. * @deprecated Use @ref Magnum::MeshTools::combineIndexedArrays() "combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&...)" instead.
*/ */
template<class ...T> inline CORRADE_DEPRECATED("use combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&...) instead") std::vector<UnsignedInt> combineIndexedArrays(const std::tuple<const std::vector<UnsignedInt>&, std::vector<T>&>&... indexedArrays) { template<class ...T> inline CORRADE_DEPRECATED("use combineIndexedArrays(const std::pair<const std::vector<UnsignedInt>&, std::vector<T>&>&...) instead") std::vector<UnsignedInt> combineIndexedArrays(const std::tuple<const std::vector<UnsignedInt>&, std::vector<T>&>&... indexedArrays) {
return combineIndexedArrays(std::make_pair(std::cref(std::get<0>(indexedArrays)), std::ref(std::get<1>(indexedArrays)))...); return combineIndexedArrays(std::make_pair(std::cref(std::get<0>(indexedArrays)), std::ref(std::get<1>(indexedArrays)))...);

7
src/Magnum/MeshTools/CompressIndices.h

@ -78,14 +78,13 @@ std::tuple<Containers::Array<char>, Mesh::IndexType, UnsignedInt, UnsignedInt> M
@param usage Index buffer usage @param usage Index buffer usage
@param indices Index array @param indices Index array
@deprecated Use general-purpose
@ref Magnum::MeshTools::compressIndices(const std::vector<UnsignedInt>&) "compressIndices(const std::vector<UnsignedInt>&)"
instead.
The same as @ref compressIndices(const std::vector<UnsignedInt>&), but this The same as @ref compressIndices(const std::vector<UnsignedInt>&), but this
function writes the output to given buffer and calls @ref Mesh::setCount() and function writes the output to given buffer and calls @ref Mesh::setCount() and
@ref Mesh::setIndexBuffer(), thus you don't need to do anything else for mesh @ref Mesh::setIndexBuffer(), thus you don't need to do anything else for mesh
index configuration. index configuration.
@deprecated Use general-purpose
@ref Magnum::MeshTools::compressIndices(const std::vector<UnsignedInt>&) "compressIndices(const std::vector<UnsignedInt>&)"
instead.
*/ */
void MAGNUM_MESHTOOLS_EXPORT compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector<UnsignedInt>& indices); void MAGNUM_MESHTOOLS_EXPORT compressIndices(Mesh& mesh, Buffer& buffer, BufferUsage usage, const std::vector<UnsignedInt>& indices);
#endif #endif

15
src/Magnum/MeshTools/FlipNormals.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Function Magnum::MeshTools::flipNormals() * @brief Function @ref Magnum::MeshTools::flipFaceWinding(), @ref Magnum::MeshTools::flipNormals()
*/ */
#include <vector> #include <vector>
@ -38,16 +38,21 @@ namespace Magnum { namespace MeshTools {
/** /**
@brief Flip face winding @brief Flip face winding
@param[in,out] indices Index array to operate on
The same as flipNormals(std::vector<UnsignedInt>&, std::vector<Vector3>&), The same as @ref flipNormals(std::vector<UnsignedInt>&, std::vector<Vector3>&),
but flips only face winding. but flips only face winding.
@attention The function requires the mesh to have triangle faces, thus index
count must be divisible by 3.
*/ */
void MAGNUM_MESHTOOLS_EXPORT flipFaceWinding(std::vector<UnsignedInt>& indices); void MAGNUM_MESHTOOLS_EXPORT flipFaceWinding(std::vector<UnsignedInt>& indices);
/** /**
@brief Flip mesh normals @brief Flip mesh normals
@param[in,out] normals Normal array to operate on
The same as flipNormals(std::vector<UnsignedInt>&, std::vector<Vector3>&), The same as @ref flipNormals(std::vector<UnsignedInt>&, std::vector<Vector3>&),
but flips only normals, not face winding. but flips only normals, not face winding.
*/ */
void MAGNUM_MESHTOOLS_EXPORT flipNormals(std::vector<Vector3>& normals); void MAGNUM_MESHTOOLS_EXPORT flipNormals(std::vector<Vector3>& normals);
@ -58,8 +63,8 @@ void MAGNUM_MESHTOOLS_EXPORT flipNormals(std::vector<Vector3>& normals);
@param[in,out] normals Normal array to operate on @param[in,out] normals Normal array to operate on
Flips normal vectors and face winding in index array for face culling to work Flips normal vectors and face winding in index array for face culling to work
properly too. See also flipNormals(std::vector<Vector3>&) and properly too. See also @ref flipNormals(std::vector<Vector3>&) and
flipFaceWinding(), which flip normals or face winding only. @ref flipFaceWinding(), which flip normals or face winding only.
@attention The function requires the mesh to have triangle faces, thus index @attention The function requires the mesh to have triangle faces, thus index
count must be divisible by 3. count must be divisible by 3.

10
src/Magnum/MeshTools/GenerateFlatNormals.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Function Magnum::MeshTools::generateFlatNormals() * @brief Function @ref Magnum::MeshTools::generateFlatNormals()
*/ */
#include <tuple> #include <tuple>
@ -53,11 +53,11 @@ std::vector<UnsignedInt> normalIndices;
std::vector<Vector3> normals; std::vector<Vector3> normals;
std::tie(normalIndices, normals) = MeshTools::generateFlatNormals(vertexIndices, positions); std::tie(normalIndices, normals) = MeshTools::generateFlatNormals(vertexIndices, positions);
@endcode @endcode
You can then use combineIndexedArrays() to combine normal and vertex array to You can then use @ref combineIndexedArrays() to combine normal and vertex array
use the same indices. to use the same indices.
@attention Index count must be divisible by 3, otherwise zero length result @attention The function requires the mesh to have triangle faces, thus index
is generated. count must be divisible by 3.
*/ */
std::tuple<std::vector<UnsignedInt>, std::vector<Vector3>> MAGNUM_MESHTOOLS_EXPORT generateFlatNormals(const std::vector<UnsignedInt>& indices, const std::vector<Vector3>& positions); std::tuple<std::vector<UnsignedInt>, std::vector<Vector3>> MAGNUM_MESHTOOLS_EXPORT generateFlatNormals(const std::vector<UnsignedInt>& indices, const std::vector<Vector3>& positions);

16
src/Magnum/MeshTools/Interleave.h

@ -193,10 +193,6 @@ template<class T, class ...U> void interleaveInto(Containers::ArrayReference<cha
@param usage Vertex buffer usage @param usage Vertex buffer usage
@param attributes Attribute arrays and gaps @param attributes Attribute arrays and gaps
@deprecated Use general-purpose
@ref Magnum::MeshTools::interleave(const T&...) "interleave(const T&...)"
instead.
The same as @ref interleave(const T&, const U&...), but this function also The same as @ref interleave(const T&, const U&...), but this function also
writes the output to given array buffer. If given mesh is not indexed, it also writes the output to given array buffer. If given mesh is not indexed, it also
updates vertex count in the mesh accordingly, so you don't have to call updates vertex count in the mesh accordingly, so you don't have to call
@ -206,6 +202,10 @@ updates vertex count in the mesh accordingly, so you don't have to call
@ref Mesh::addVertexBuffer() on the mesh afterwards. @ref Mesh::addVertexBuffer() on the mesh afterwards.
@see @ref compressIndices(), @ref compile() @see @ref compressIndices(), @ref compile()
@deprecated Use general-purpose
@ref Magnum::MeshTools::interleave(const T&...) "interleave(const T&...)"
instead.
*/ */
template<class ...T> CORRADE_DEPRECATED("Use interleave(const T&...) instead") void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) { template<class ...T> CORRADE_DEPRECATED("Use interleave(const T&...) instead") void interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T&... attributes) {
if(!mesh.isIndexed()) mesh.setCount(Implementation::AttributeCount{}(attributes...)); if(!mesh.isIndexed()) mesh.setCount(Implementation::AttributeCount{}(attributes...));
@ -215,16 +215,16 @@ template<class ...T> CORRADE_DEPRECATED("Use interleave(const T&...) instead") v
/** /**
@brief Write vertex attribute to array buffer and configure the mesh @brief Write vertex attribute to array buffer and configure the mesh
@deprecated Use general-purpose
@ref Magnum::MeshTools::interleave(const T&...) "interleave(const T&...)"
instead.
Simplified specialization of the above function for only one attribute array, Simplified specialization of the above function for only one attribute array,
equivalent to the following: equivalent to the following:
@code @code
if(!mesh.isIndexed()) mesh.setCount(attribute.size()); if(!mesh.isIndexed()) mesh.setCount(attribute.size());
buffer.setData(attribute, usage); buffer.setData(attribute, usage);
@endcode @endcode
@deprecated Use general-purpose
@ref Magnum::MeshTools::interleave(const T&...) "interleave(const T&...)"
instead.
*/ */
template<class T> CORRADE_DEPRECATED("Use interleave(const T&...) instead") typename std::enable_if<!std::is_convertible<T, std::size_t>::value, void>::type interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) { template<class T> CORRADE_DEPRECATED("Use interleave(const T&...) instead") typename std::enable_if<!std::is_convertible<T, std::size_t>::value, void>::type interleave(Mesh& mesh, Buffer& buffer, BufferUsage usage, const T& attribute) {
if(!mesh.isIndexed()) mesh.setCount(attribute.size()); if(!mesh.isIndexed()) mesh.setCount(attribute.size());

2
src/Magnum/MeshTools/Subdivide.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Function Magnum::MeshTools::subdivide() * @brief Function @ref Magnum::MeshTools::subdivide()
*/ */
#include <vector> #include <vector>

2
src/Magnum/MeshTools/Test/GenerateFlatNormalsTest.cpp

@ -51,7 +51,7 @@ void GenerateFlatNormalsTest::wrongIndexCount() {
std::vector<Vector3> normals; std::vector<Vector3> normals;
std::tie(indices, normals) = MeshTools::generateFlatNormals({ std::tie(indices, normals) = MeshTools::generateFlatNormals({
0, 1 0, 1
}, std::vector<Vector3>{}); }, {});
CORRADE_COMPARE(indices.size(), 0); CORRADE_COMPARE(indices.size(), 0);
CORRADE_COMPARE(normals.size(), 0); CORRADE_COMPARE(normals.size(), 0);

2
src/Magnum/MeshTools/Tipsify.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Function Magnum::MeshTools::tipsify() * @brief Function @ref Magnum::MeshTools::tipsify()
*/ */
#include <vector> #include <vector>

20
src/Magnum/MeshTools/Transform.h

@ -26,7 +26,7 @@
*/ */
/** @file /** @file
* @brief Function Magnum::MeshTools::transformVectorsInPlace(), Magnum::MeshTools::transformVectors(), Magnum::MeshTools::transformPointsInPlace(), Magnum::MeshTools::transformPoints() * @brief Function @ref Magnum::MeshTools::transformVectorsInPlace(), @ref Magnum::MeshTools::transformVectors(), @ref Magnum::MeshTools::transformPointsInPlace(), @ref Magnum::MeshTools::transformPoints()
*/ */
#include "Magnum/Math/DualQuaternion.h" #include "Magnum/Math/DualQuaternion.h"
@ -43,7 +43,7 @@ with compatible vector type as @p vectors. Expects that @ref Math::Quaternion "Q
is normalized, no further requirements are for other transformation is normalized, no further requirements are for other transformation
representations. representations.
Unlike in transformPointsInPlace(), the transformation does not involve Unlike in @ref transformPointsInPlace(), the transformation does not involve
translation. translation.
Example usage: Example usage:
@ -53,8 +53,9 @@ auto transformation = Quaternion::rotation(35.0_degf, Vector3::yAxis());
MeshTools::transformVectorsInPlace(rotation, vectors); MeshTools::transformVectorsInPlace(rotation, vectors);
@endcode @endcode
@see transformVectors(), Matrix3::transformVector(), Matrix4::transformVector(), @see @ref transformVectors(), @ref Matrix3::transformVector(),
Complex::transformVectorNormalized(), Quaternion::transformVectorNormalized() @ref Matrix4::transformVector(), @ref Complex::transformVector(),
@ref Quaternion::transformVectorNormalized()
@todo GPU transform feedback implementation (otherwise this is only bad joke) @todo GPU transform feedback implementation (otherwise this is only bad joke)
*/ */
template<class T, class U> void transformVectorsInPlace(const Math::Quaternion<T>& normalizedQuaternion, U& vectors) { template<class T, class U> void transformVectorsInPlace(const Math::Quaternion<T>& normalizedQuaternion, U& vectors) {
@ -84,7 +85,7 @@ template<class T, class U> void transformVectorsInPlace(const Math::Matrix4<T>&
@brief Transform vectors using given transformation @brief Transform vectors using given transformation
Returns transformed vectors instead of modifying them in-place. See Returns transformed vectors instead of modifying them in-place. See
transformVectorsInPlace() for more information. @ref transformVectorsInPlace() for more information.
*/ */
template<class T, class U> U transformVectors(const T& transformation, U vectors) { template<class T, class U> U transformVectors(const T& transformation, U vectors) {
U result(std::move(vectors)); U result(std::move(vectors));
@ -101,7 +102,7 @@ with compatible vector type as @p vectors. Expects that
@ref Math::DualQuaternion "DualQuaternion" is normalized, no further @ref Math::DualQuaternion "DualQuaternion" is normalized, no further
requirements are for other transformation representations. requirements are for other transformation representations.
Unlike in transformVectorsInPlace(), the transformation also involves Unlike in @ref transformVectorsInPlace(), the transformation also involves
translation. translation.
Example usage: Example usage:
@ -112,8 +113,9 @@ auto transformation = DualQuaternion::rotation(35.0_degf, Vector3::yAxis())*
MeshTools::transformPointsInPlace(rotation, points); MeshTools::transformPointsInPlace(rotation, points);
@endcode @endcode
@see transformPoints(), Matrix3::transformPoint(), Matrix4::transformPoint(), @see @ref transformPoints(), @ref Matrix3::transformPoint(),
DualQuaternion::transformPointNormalized() @ref Matrix4::transformPoint(),
@ref DualQuaternion::transformPointNormalized()
*/ */
template<class T, class U> void transformPointsInPlace(const Math::DualQuaternion<T>& normalizedDualQuaternion, U& points) { template<class T, class U> void transformPointsInPlace(const Math::DualQuaternion<T>& normalizedDualQuaternion, U& points) {
for(auto it = points.begin(); it != points.end(); ++it) for(auto it = points.begin(); it != points.end(); ++it)
@ -142,7 +144,7 @@ template<class T, class U> void transformPointsInPlace(const Math::Matrix4<T>& m
@brief Transform points using given transformation @brief Transform points using given transformation
Returns transformed points instead of modifying them in-place. See Returns transformed points instead of modifying them in-place. See
transformPointsInPlace() for more information. @ref transformPointsInPlace() for more information.
*/ */
template<class T, class U> U transformPoints(const T& transformation, U vectors) { template<class T, class U> U transformPoints(const T& transformation, U vectors) {
U result(std::move(vectors)); U result(std::move(vectors));

119
src/Magnum/MeshView.cpp

@ -25,12 +25,117 @@
#include "MeshView.h" #include "MeshView.h"
#include <Corrade/Containers/Array.h>
#include <Corrade/Utility/Assert.h>
#include "Magnum/Context.h"
#include "Magnum/Mesh.h" #include "Magnum/Mesh.h"
#include "Implementation/State.h"
#include "Implementation/MeshState.h"
namespace Magnum { namespace Magnum {
void MeshView::draw(AbstractShaderProgram& shader, std::initializer_list<std::reference_wrapper<MeshView>> meshes) {
/* Why std::initializer_list doesn't have empty()? */
if(!meshes.size()) return;
shader.use();
#ifndef CORRADE_NO_ASSERT
const Mesh* original = &meshes.begin()->get()._original.get();
for(MeshView& mesh: meshes)
CORRADE_ASSERT(&mesh._original.get() == original, "MeshView::draw(): all meshes must be views of the same original mesh", );
#endif
#ifndef MAGNUM_TARGET_GLES
multiDrawImplementationDefault(meshes);
#else
Context::current()->state().mesh->multiDrawImplementation(meshes);
#endif
}
void MeshView::multiDrawImplementationDefault(std::initializer_list<std::reference_wrapper<MeshView>> meshes) {
CORRADE_INTERNAL_ASSERT(meshes.size());
const Implementation::MeshState& state = *Context::current()->state().mesh;
Mesh& original = meshes.begin()->get()._original;
Containers::Array<GLsizei> count{meshes.size()};
Containers::Array<GLvoid*> indices{meshes.size()};
Containers::Array<GLint> baseVertex{meshes.size()};
/* Gather the parameters */
#ifndef MAGNUM_TARGET_GLES
bool hasBaseVertex = false;
#endif
std::size_t i = 0;
for(MeshView& mesh: meshes) {
CORRADE_ASSERT(mesh._instanceCount == 1, "MeshView::draw(): cannot draw multiple instanced meshes", );
count[i] = mesh._count;
indices[i] = reinterpret_cast<GLvoid*>(mesh._indexOffset);
baseVertex[i] = mesh._baseVertex;
if(mesh._baseVertex) {
#ifndef MAGNUM_TARGET_GLES
hasBaseVertex = true;
#else
CORRADE_ASSERT(!original._indexBuffer, "MeshView::draw(): desktop OpenGL is required for base vertex specification in indexed meshes", );
#endif
}
++i;
}
(original.*state.bindImplementation)();
/* Non-indexed meshes */
if(!original._indexBuffer) {
#ifndef MAGNUM_TARGET_GLES
glMultiDrawArrays(GLenum(original._primitive), baseVertex, count, meshes.size());
#else
//glMultiDrawArraysEXT(GLenum(original._primitive), baseVertex, count, meshes.size());
CORRADE_INTERNAL_ASSERT(false);
#endif
/* Indexed meshes */
} else {
/* Indexed meshes with base vertex */
#ifndef MAGNUM_TARGET_GLES
if(hasBaseVertex) {
glMultiDrawElementsBaseVertex(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size(), baseVertex);
/* Indexed meshes */
} else
#endif
{
#ifndef MAGNUM_TARGET_GLES
glMultiDrawElements(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size());
#else
//glMultiDrawElements(GLenum(original._primitive), count, GLenum(original._indexType), indices, meshes.size());
CORRADE_INTERNAL_ASSERT(false);
#endif
}
}
(original.*state.unbindImplementation)();
}
#ifdef MAGNUM_TARGET_GLES
void MeshView::multiDrawImplementationFallback(std::initializer_list<std::reference_wrapper<MeshView>> meshes) {
for(MeshView& mesh: meshes) {
#ifndef MAGNUM_TARGET_GLES2
mesh._original.drawInternal(mesh._count, mesh._baseVertex, mesh._instanceCount, mesh._indexOffset, mesh._indexStart, mesh._indexEnd);
#else
mesh._original.drawInternal(mesh._count, mesh._baseVertex, mesh._instanceCount, mesh._indexOffset);
#endif
}
}
#endif
MeshView& MeshView::setIndexRange(Int first) { MeshView& MeshView::setIndexRange(Int first) {
_indexOffset = _original->_indexOffset + first*_original->indexSize(); _indexOffset = _original.get()._indexOffset + first*_original.get().indexSize();
return *this; return *this;
} }
@ -38,22 +143,22 @@ void MeshView::draw(AbstractShaderProgram& shader) {
shader.use(); shader.use();
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_original->drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd); _original.get().drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2) #elif !defined(MAGNUM_TARGET_GLES2)
_original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd); _original.get().drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd);
#else #else
_original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset); _original.get().drawInternal(_count, _baseVertex, _instanceCount, _indexOffset);
#endif #endif
} }
#ifdef MAGNUM_BUILD_DEPRECATED #ifdef MAGNUM_BUILD_DEPRECATED
void MeshView::draw() { void MeshView::draw() {
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_original->drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd); _original.get().drawInternal(_count, _baseVertex, _instanceCount, _baseInstance, _indexOffset, _indexStart, _indexEnd);
#elif !defined(MAGNUM_TARGET_GLES2) #elif !defined(MAGNUM_TARGET_GLES2)
_original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd); _original.get().drawInternal(_count, _baseVertex, _instanceCount, _indexOffset, _indexStart, _indexEnd);
#else #else
_original->drawInternal(_count, _baseVertex, _instanceCount, _indexOffset); _original.get().drawInternal(_count, _baseVertex, _instanceCount, _indexOffset);
#endif #endif
} }
#endif #endif

37
src/Magnum/MeshView.h

@ -29,12 +29,17 @@
* @brief Class @ref Magnum::MeshView * @brief Class @ref Magnum::MeshView
*/ */
#include <functional>
#include <initializer_list>
#include "Magnum/Magnum.h" #include "Magnum/Magnum.h"
#include "Magnum/OpenGL.h" #include "Magnum/OpenGL.h"
#include "Magnum/visibility.h" #include "Magnum/visibility.h"
namespace Magnum { namespace Magnum {
namespace Implementation { struct MeshState; }
/** /**
@brief %Mesh view @brief %Mesh view
@ -52,7 +57,31 @@ You must ensure that the original mesh remains available for whole view
lifetime. lifetime.
*/ */
class MAGNUM_EXPORT MeshView { class MAGNUM_EXPORT MeshView {
friend struct Implementation::MeshState;
public: public:
/**
* @brief Draw multiple meshes at once
*
* In OpenGL ES, if @es_extension2{EXT,multi_draw_arrays,multi_draw_arrays}
* is not present, the functionality is emulated using sequence of
* @ref draw(AbstractShaderProgram&) calls.
* @attention All meshes must be views of the same original mesh and
* must not be instanced.
* @see @ref draw(AbstractShaderProgram&), @fn_gl{UseProgram},
* @fn_gl{EnableVertexAttribArray}, @fn_gl{BindBuffer},
* @fn_gl{VertexAttribPointer}, @fn_gl{DisableVertexAttribArray}
* or @fn_gl{BindVertexArray} (if @extension{APPLE,vertex_array_object}
* is available), @fn_gl{MultiDrawArrays} or
* @fn_gl{MultiDrawElements}/@fn_gl{MultiDrawElementsBaseVertex}
*/
static void draw(AbstractShaderProgram& shader, std::initializer_list<std::reference_wrapper<MeshView>> meshes);
/** @overload */
static void draw(AbstractShaderProgram&& shader, std::initializer_list<std::reference_wrapper<MeshView>> meshes) {
draw(shader, meshes);
}
/** /**
* @brief Constructor * @brief Constructor
* @param original Original, already configured mesh * @param original Original, already configured mesh
@ -212,6 +241,7 @@ class MAGNUM_EXPORT MeshView {
* @brief Draw the mesh * @brief Draw the mesh
* *
* See @ref Mesh::draw() for more information. * See @ref Mesh::draw() for more information.
* @see @ref draw(AbstractShaderProgram&, std::initializer_list<std::reference_wrapper<MeshView>>)
*/ */
void draw(AbstractShaderProgram& shader); void draw(AbstractShaderProgram& shader);
void draw(AbstractShaderProgram&& shader) { draw(shader); } /**< @overload */ void draw(AbstractShaderProgram&& shader) { draw(shader); } /**< @overload */
@ -226,7 +256,10 @@ class MAGNUM_EXPORT MeshView {
#endif #endif
private: private:
Mesh* _original; static MAGNUM_LOCAL void multiDrawImplementationDefault(std::initializer_list<std::reference_wrapper<MeshView>> meshes);
static MAGNUM_LOCAL void multiDrawImplementationFallback(std::initializer_list<std::reference_wrapper<MeshView>> meshes);
std::reference_wrapper<Mesh> _original;
Int _count, _baseVertex, _instanceCount; Int _count, _baseVertex, _instanceCount;
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
@ -238,7 +271,7 @@ class MAGNUM_EXPORT MeshView {
#endif #endif
}; };
inline MeshView::MeshView(Mesh& original): _original(&original), _count(0), _baseVertex(0), _instanceCount{1}, inline MeshView::MeshView(Mesh& original): _original(original), _count(0), _baseVertex(0), _instanceCount{1},
#ifndef MAGNUM_TARGET_GLES #ifndef MAGNUM_TARGET_GLES
_baseInstance{0}, _baseInstance{0},
#endif #endif

2
src/Magnum/MultisampleTexture.h

@ -65,7 +65,7 @@ Template class for 2D mulitsample texture and 2D multisample texture array.
Used only from shaders for manual multisample resolve and other operations. See Used only from shaders for manual multisample resolve and other operations. See
also @ref AbstractTexture documentation for more information. also @ref AbstractTexture documentation for more information.
@section Texture-usage Usage @section MultisampleTexture-usage Usage
As multisample textures have no sampler state, the only thing you need is to As multisample textures have no sampler state, the only thing you need is to
set storage: set storage:

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save