Browse Source

Merge branch 'master' into compatibility

Conflicts:
	modules/FindCorrade.cmake
	src/Math/Test/MatrixTest.cpp
	src/Platform/AbstractXApplication.cpp
	src/Platform/AbstractXApplication.h
	src/Platform/GlxApplication.h
	src/Platform/Implementation/AbstractContextHandler.h
	src/Platform/Implementation/GlxContextHandler.h
	src/Platform/XEglApplication.h
	src/Test/SwizzleTest.cpp
Vladimír Vondruš 13 years ago
parent
commit
03775e1a29
  1. 14
      CMakeLists.txt
  2. 3
      Doxyfile
  3. 9
      PKGBUILD
  4. 37
      PKGBUILD-emscripten
  5. 8
      README.md
  6. 172
      doc/building.dox
  7. 18
      doc/cmake.dox
  8. 11
      doc/debug-tools.dox
  9. 2
      doc/features.dox
  10. 8
      doc/mainpage.dox
  11. 34
      doc/matrix-vector.dox
  12. 118
      doc/namespaces.dox
  13. 118
      doc/platform.dox
  14. 16
      doc/portability.dox
  15. 108
      doc/scenegraph.dox
  16. 15
      doc/shapes.dox
  17. 21
      doc/transformations.dox
  18. 46
      doc/types.dox
  19. 14
      doc/unsupported.dox
  20. 24
      external/OpenGL/GL/gl_magnum.c
  21. 4
      external/Optional/optional.hpp
  22. 13
      modules/FindCorrade.cmake
  23. 35
      modules/FindMagnum.cmake
  24. 8
      src/AbstractShaderProgram.h
  25. 3
      src/AbstractTexture.cpp
  26. 2
      src/AbstractTexture.h
  27. 5
      src/Audio/Audio.cpp
  28. 5
      src/Audio/CMakeLists.txt
  29. 64
      src/Buffer.h
  30. 2
      src/BufferImage.cpp
  31. 19
      src/CMakeLists.txt
  32. 40
      src/Color.h
  33. 4
      src/ColorFormat.h
  34. 5
      src/DebugTools/CMakeLists.txt
  35. 8
      src/DebugTools/Test/CapsuleRendererTest.cpp
  36. 4
      src/DebugTools/Test/CylinderRendererTest.cpp
  37. 5
      src/Extensions.h
  38. 8
      src/ImageFormat.h
  39. 172
      src/Magnum.h
  40. 36
      src/Math/Algorithms/Test/GaussJordanTest.cpp
  41. 30
      src/Math/Algorithms/Test/GramSchmidtTest.cpp
  42. 16
      src/Math/Math.h
  43. 40
      src/Math/Matrix.h
  44. 73
      src/Math/RectangularMatrix.h
  45. 31
      src/Math/Swizzle.h
  46. 4
      src/Math/Test/ComplexTest.cpp
  47. 30
      src/Math/Test/Matrix3Test.cpp
  48. 38
      src/Math/Test/Matrix4Test.cpp
  49. 187
      src/Math/Test/MatrixTest.cpp
  50. 6
      src/Math/Test/QuaternionTest.cpp
  51. 62
      src/Math/Test/RectangularMatrixTest.cpp
  52. 7
      src/Math/Test/SwizzleTest.cpp
  53. 17
      src/Math/Test/Vector2Test.cpp
  54. 16
      src/Math/Test/Vector3Test.cpp
  55. 21
      src/Math/Test/Vector4Test.cpp
  56. 14
      src/Math/Vector2.h
  57. 52
      src/Math/Vector3.h
  58. 81
      src/Math/Vector4.h
  59. 10
      src/MeshTools/CMakeLists.txt
  60. 2
      src/MeshTools/CompressIndices.cpp
  61. 2
      src/MeshTools/Interleave.h
  62. 16
      src/Platform/AbstractXApplication.cpp
  63. 113
      src/Platform/AbstractXApplication.h
  64. 57
      src/Platform/CMakeLists.txt
  65. 44
      src/Platform/EmscriptenApplication.js
  66. 2
      src/Platform/GlutApplication.cpp
  67. 60
      src/Platform/GlutApplication.h
  68. 35
      src/Platform/GlxApplication.cpp
  69. 34
      src/Platform/GlxApplication.h
  70. 12
      src/Platform/Implementation/AbstractContextHandler.h
  71. 4
      src/Platform/Implementation/EglContextHandler.cpp
  72. 12
      src/Platform/Implementation/EglContextHandler.h
  73. 4
      src/Platform/Implementation/GlxContextHandler.cpp
  74. 12
      src/Platform/Implementation/GlxContextHandler.h
  75. 12
      src/Platform/NaClApplication.cpp
  76. 124
      src/Platform/NaClApplication.h
  77. 74
      src/Platform/Sdl2Application.cpp
  78. 118
      src/Platform/Sdl2Application.h
  79. 0
      src/Platform/WebApplication.css
  80. 24
      src/Platform/WindowlessGlxApplication.h
  81. 24
      src/Platform/WindowlessNaClApplication.h
  82. 35
      src/Platform/XEglApplication.cpp
  83. 35
      src/Platform/XEglApplication.h
  84. 74
      src/Platform/magnum-info-nacl.html
  85. 6
      src/Platform/magnum-info.cpp
  86. 5
      src/Primitives/CMakeLists.txt
  87. 24
      src/RenderbufferFormat.h
  88. 4
      src/Sampler.h
  89. 88
      src/SceneGraph/AbstractTransformation.h
  90. 142
      src/SceneGraph/AbstractTranslation.h
  91. 22
      src/SceneGraph/AbstractTranslationRotation2D.h
  92. 23
      src/SceneGraph/AbstractTranslationRotation3D.h
  93. 12
      src/SceneGraph/CMakeLists.txt
  94. 93
      src/SceneGraph/DualComplexTransformation.h
  95. 97
      src/SceneGraph/DualQuaternionTransformation.h
  96. 63
      src/SceneGraph/MatrixTransformation2D.h
  97. 72
      src/SceneGraph/MatrixTransformation3D.h
  98. 6
      src/SceneGraph/Object.h
  99. 23
      src/SceneGraph/Object.hpp
  100. 102
      src/SceneGraph/RigidMatrixTransformation2D.h
  101. Some files were not shown because too many files have changed in this diff Show More

14
CMakeLists.txt

@ -63,6 +63,11 @@ else()
option(WITH_SDL2APPLICATION "Build Sdl2Application library" OFF)
endif()
option(BUILD_DEPRECATED "Include deprecated API in the build" ON)
if(BUILD_DEPRECATED)
set(MAGNUM_BUILD_DEPRECATED 1)
endif()
option(BUILD_STATIC "Build static libraries (default are shared)" OFF)
cmake_dependent_option(BUILD_STATIC_PIC "Build static libraries with position-independent code" OFF "BUILD_STATIC" OFF)
option(BUILD_TESTS "Build unit tests." OFF)
@ -83,11 +88,12 @@ endif()
if(CORRADE_TARGET_NACL OR CORRADE_TARGET_EMSCRIPTEN)
set(TARGET_GLES 1)
set(TARGET_GLES2 1)
endif()
# Newlib toolchain supports only static linking
if(CORRADE_TARGET_NACL_NEWLIB)
set(BUILD_STATIC ON)
endif()
# NaCl newlib toolchain supports only static linking, dynamic linking is
# meaningless on Emscripten
if(CORRADE_TARGET_NACL_NEWLIB OR CORRADE_TARGET_EMSCRIPTEN)
set(BUILD_STATIC ON)
endif()
if(BUILD_STATIC)

3
Doxyfile

@ -210,6 +210,7 @@ ALIASES = \
"fn_gl_extension{3}=<a href=\"http://www.opengl.org/registry/specs/\2/\3.txt\">gl\1<b></b>\2()</a>" \
"fn_gles_extension{3}=<a href=\"http://www.khronos.org/registry/gles/extensions/\2/\2_\3.txt\">gl\1<b></b>\2()</a>" \
"def_gl{1}=`GL_\1`" \
"deprecated_gl=@xrefitem deprecated-gl \"Deprecated OpenGL API\" \"Deprecated OpenGL API list\"" \
"requires_gl30=@xrefitem requires-gl30 \"Requires OpenGL 3.0\" \"Functionality requiring OpenGL 3.0\"" \
"requires_gl31=@xrefitem requires-gl31 \"Requires OpenGL 3.1\" \"Functionality requiring OpenGL 3.1\"" \
"requires_gl32=@xrefitem requires-gl32 \"Requires OpenGL 3.2\" \"Functionality requiring OpenGL 3.2\"" \
@ -1644,7 +1645,7 @@ INCLUDE_FILE_PATTERNS =
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.
PREDEFINED = DOXYGEN_GENERATING_OUTPUT
PREDEFINED = DOXYGEN_GENERATING_OUTPUT MAGNUM_BUILD_DEPRECATED
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.

9
PKGBUILD

@ -7,7 +7,7 @@ arch=('i686' 'x86_64')
url="https://github.com/mosra/magnum"
license=('MIT')
depends=('corrade' 'openal' 'freeglut' 'sdl2')
makedepends=('cmake')
makedepends=('cmake' 'ninja')
options=(!strip)
provides=('magnum-git')
@ -30,8 +30,9 @@ build() {
-DWITH_GLUTAPPLICATION=ON \
-DWITH_GLXAPPLICATION=ON \
-DWITH_SDL2APPLICATION=ON \
-DBUILD_TESTS=TRUE
make
-DBUILD_TESTS=TRUE \
-G Ninja
ninja
}
check() {
@ -41,5 +42,5 @@ check() {
package() {
cd "$startdir/build"
make DESTDIR="$pkgdir/" install
DESTDIR="$pkgdir/" ninja install
}

37
PKGBUILD-emscripten

@ -0,0 +1,37 @@
# Author: mosra <mosra@centrum.cz>
pkgname=emscripten-magnum
pkgver=dev
pkgrel=1
pkgdesc="C++11 and OpenGL 2D/3D graphics engine (Emscripten)"
arch=('any')
url="http://mosra.cz/blog/magnum.php"
license=('MIT')
depends=('emscripten-corrade')
makedepends=('cmake')
options=(!strip !buildflags)
build() {
if [ ! -d "$startdir/build-emscripten" ] ; then
mkdir "$startdir/build-emscripten"
cd "$startdir/build-emscripten"
cmake .. \
-DCMAKE_MODULE_PATH="$startdir/toolchains/modules" \
-DCMAKE_TOOLCHAIN_FILE="$startdir/toolchains/generic/Emscripten.cmake" \
-DWITH_AUDIO=OFF
fi
cd "$startdir/build-emscripten"
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/emscripten/system \
-DWITH_AUDIO=OFF \
-DWITH_SDL2APPLICATION=ON
make
}
package() {
cd "$startdir/build-emscripten"
make DESTDIR="$pkgdir/" install
}

8
README.md

@ -39,14 +39,22 @@ DESIGN GOALS
SUPPORTED PLATFORMS
===================
Graphics APIs:
* **OpenGL** 2.1 through 4.4, core profile functionality and modern
extensions
* **OpenGL ES** 2.0, 3.0 and extensions to match desktop OpenGL functionality
* **WebGL** 1.0 and extensions to match desktop OpenGL functionality
Platforms:
* **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through
GLUT or SDL2 toolkit)
* **Windows** (through GLUT or SDL2 toolkit)
* **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt))
* **Google Chrome** (through [Native Client](https://developers.google.com/native-client/),
both `newlib` and `glibc` toolchains are supported)
* **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki))
FEATURES
========

172
doc/building.dox

@ -23,15 +23,10 @@
*/
namespace Magnum {
/** @page building Downloading and building
@brief Guide how to download and build %Magnum on different platforms.
%Magnum can be downloaded from GitHub and built either
@ref building-compilation "manually" or using already prepared packaging files,
currently only @ref building-arch "ArchLinux PKGBUILDs". Guide how to
crosscompile for @ref building-win "Windows" and
@ref building-nacl "Google Chrome Native Client" is also available.
@tableofcontents
Minimal set of tools and libraries required for building is:
@ -44,6 +39,8 @@ Minimal set of tools and libraries required for building is:
- **Corrade** - Plugin management and utility library. See
@ref building-corrade "Corrade download and installation guide" for more
information.
- **OpenAL** - By default needed by Audio library, but you can disable building
of it by setting `WITH_AUDIO` to `OFF` (see below).
@section building-download Downloading the sources
@ -53,16 +50,12 @@ compressed archive or use the command line:
git clone git://github.com/mosra/magnum.git
If you need toolchains for crosscompiling, run also the following commands, or,
if you build from source archive, download snapshot of toolchains repository
from https://github.com/mosra/toolchains and put them in `toolchains/`
subdirectory.
git submodule init
git submodule update
@section building-compilation Compilation, installation
Relevant information about CMake usage was described in
@ref building-corrade "Corrade download and installation guide", this guide is
assuming you have at least basic knowledge of CMake.
@subsection building-linux Via command-line (on Linux/Unix)
On Unix-based OSs, the library (for example with support for GLUT applications)
@ -75,12 +68,7 @@ can be built and installed using these four commands:
make
make install
The library provides a lot of CMake options (described in sections later). They
can be passed to CMake either as `-Dname=value` parameters on command-line
(like above) or set conveniently using `cmake-gui`:
cd build
cmake-gui .
See @ref building-features "below" for additional configuration options.
@subsection building-windows Using QtCreator and CMake GUI (on Windows)
@ -96,14 +84,11 @@ and you won't need to explicitly specify path to each one.
Then just open project's root `CMakeLists.txt` file within QtCreator. It then
asks you where to create build directory, allows you to specify initial CMake
parameters and then you can just press Configure and everything should be ready
to be built. You might need to set some CMake parameters before configuring,
they can be set with `-Dname=value`. See below for more information.
parameters and then you can just press *Configure* and everything is be ready
to be built.
After the initial import you might want to reconfigure some CMake variables
(more information below). Start CMake GUI, point it to the recently created
build dir, modify the variables and press Generate. QtCreator will detect the
changes and reparse the project accordingly.
After the initial import you might want to reconfigure some CMake variables,
see @ref building-features "below" for more information.
For most convenient usage it's best to set `CMAKE_INSTALL_PREFIX` to directory
where MinGW is installed (e.g. `C:/MinGW/`) and add `C:/MinGW/bin` and
@ -112,7 +97,7 @@ within QtCreator by adding new `make install` build rule.
@subsubsection building-windows-troubleshooting Windows troubleshooting
If CMake isn't able to find dependencies (e.g. Corrade is not found) and you
If CMake isn't able to find dependencies (e.g. %Corrade is not found) and you
have installed them to MinGW directory, point to `CMAKE_FIND_ROOT_PATH` to
MinGW installation prefix, e.g. specify `-DCMAKE_FIND_ROOT_PATH=C:/MinGW/`
CMake parameter.
@ -132,6 +117,12 @@ Clang), pass `-DCMAKE_CXX_COMPILER=clang++` to CMake.
the module with your code instead of depending on it being in system location.
You can install it by enabling `WITH_FIND_MODULE`.
The library is constantly evolving and thus some APIs are deprecated and then
later removed in favor of better ones. To preserve backwards compatibility,
%Magnum is by default built with all deprecated APIs. However, to make your
code more robust and future-proof, it's recommended to build the library with
`BUILD_DEPRECATED` disabled.
By default the engine is built for desktop OpenGL. Using `TARGET_*` CMake
parameters you can target other platforms. Note that some features are
available for desktop OpenGL only, see @ref requires-gl.
@ -151,7 +142,7 @@ By default the engine is built with everything except application libraries
(see below). Using `WITH_*` CMake parameters you can specify which parts will
be built and which not:
- `WITH_AUDIO` - Audio library. Requires **OpenAL** library.
- `WITH_AUDIO` - Audio library.
- `WITH_DEBUGTOOLS` - DebugTools library. Enables also building of MeshTools,
Primitives, SceneGraph, Shaders and Shapes libraries.
- `WITH_MESHTOOLS` - MeshTools library. Enabled automatically if `WITH_DEBUGTOOLS`
@ -177,44 +168,52 @@ None of the @ref Platform "application libraries" is built by default (and you
need at least one). Choose the one which suits your requirements and your
platform best:
- `WITH_GLUTAPPLICATION` - @ref Platform::GlutApplication "GlutApplication",
available only if targeting desktop OpenGL. Requires **GLUT** library.
- `WITH_GLXAPPLICATION` - @ref Platform::GlxApplication "GlxApplication".
Requires **X11** and **GLX** libraries.
- `WITH_NACLAPPLICATION` - @ref Platform::NaClApplication "NaClApplication",
available only if targeting Google Chrome Native Client (see below).
- `WITH_SDL2APPLICATION` - @ref Platform::Sdl2Application "Sdl2Application".
Requires **SDL2** library.
- `WITH_XEGLAPPLICATION` - @ref Platform::XEglApplication "XEglApplication",
available only if targeting OpenGL ES (see above). Requires **X11** and **EGL**
libraries.
- `WITH_WINDOWLESSGLXAPPLICATION` - @ref Platform::WindowlessGlxApplication "WindowlessGlxApplication".
Requires **X11** and **GLX** libraries.
- `WITH_GLUTAPPLICATION` - @ref Platform::GlutApplication "GlutApplication"
- `WITH_GLXAPPLICATION` - @ref Platform::GlxApplication "GlxApplication"
- `WITH_NACLAPPLICATION` - @ref Platform::NaClApplication "NaClApplication"
- `WITH_SDL2APPLICATION` - @ref Platform::Sdl2Application "Sdl2Application"
- `WITH_XEGLAPPLICATION` - @ref Platform::XEglApplication "XEglApplication"
- `WITH_WINDOWLESSGLXAPPLICATION` - @ref Platform::WindowlessGlxApplication "WindowlessGlxApplication"
- `WITH_WINDOWLESSNACLAPPLICATION` - @ref Platform::WindowlessNaClApplication "WindowlessNaClApplication"
Note that [each namespace](namespaces.html) and all @ref Platform libraries
contain more detailed information about dependencies, availability on
particular platform and also guide how to enable given library in build and use
it with CMake.
@subsection building-tests Building and running unit tests
If you want to build also unit tests (which are not built by default), enable
`BUILD_TEST` in CMake. Unit tests use Corrade's @ref Corrade::TestSuite
`BUILD_TESTS` in CMake. Unit tests use Corrade's @ref Corrade::TestSuite
"TestSuite" framework and can be run either manually (the binaries are located
in `Test/` subdirectories of build directory) or using
ctest --output-on-failure
in build directory. On Windows the tests require the library to be installed
with DLLs accessible through `PATH`. See above for more information.
with DLLs accessible through `PATH`. See
@ref building-windows "above Windows documentation" for more information.
Platforms which have windowless context creation implemented (currently only
desktop Linux) can build also tests for OpenGL functionality. You can enable
them with `BUILD_GL_TESTS`.
@subsection building-doc Building documentation
The documentation (which you are currently reading) is written in **Doxygen**
(version 1.8 with Markdown support is used, but older versions should do good
job too) and additionally uses **Graphviz** for class diagrams and **TeX**
for math formulas. The documentation can be build by running
job too) and additionally uses **TeX** for math formulas. The documentation can
be build by running
doxygen
in root directory (i.e. where `Doxyfile` is). Resulting HTML documentation
will be in `build/doc/` directory. You might need to create `build/` directory
if it doesn't exist yet.
if it doesn't exist yet. If %Corrade with generated documentation is placed in
`corrade` directory next to `magnum`, the documentation will be crosslinked
with %Corrade's one. If related projects (`magnum-plugins`, `magnum-integration`
and `magnum-examples`, see below) are places along these, their documentation
will be also included in generated output.
@section building-related Related projects
@ -225,7 +224,9 @@ formats are maintained in @ref building-plugins "Plugins repository",
Integration with various external math and physics libraries is provided by
@ref building-integration "Integration library".
@section building-arch Building ArchLinux packages
@section building-packages Prepared packages
@subsection building-packages-arch ArchLinux packages
In `package/archlinux` directory is currently one PKGBUILD for Git development
build. The package is also in AUR under the same name.
@ -242,7 +243,22 @@ If you want to build with another compiler (e.g. Clang), run makepkg this way:
Development PKGBUILDs can detect when Clang is used and remove unsupported CXX
flags.
@section building-win Crosscompiling for Windows using MinGW
@section building-crosscompiling Crosscompiling
For crosscompiling you need to have *both* target and native version of
%Corrade installed, because %Corrade needs to run `corrade-rc` utility on the
host system as part of the build process. If native version of `corrade-rc` is
not found on the system, crosscompilation will fail.
You also need to have the toolchains submodule updated. Either run the
following commands, or, if you build from source archive, download snapshot of
toolchains repository from https://github.com/mosra/toolchains and put the
contents in `toolchains/` subdirectory.
git submodule init
git submodule update
@subsection building-cross-win Crosscompiling for Windows using MinGW
@note This guide is tailored mainly for crosscompiling from ArchLinux. For
this system there is also prepared `mingw32-magnum` development package in
@ -255,10 +271,9 @@ You will need MinGW32 versions of the compiler and all dependent libraries
- `mingw32-runtime`
- `mingw32-corrade`
Make sure you have `toolchains` submodule updated, as
@ref building-download "explained above". Then create build directory and run
cmake and make. You may need to modify the `basic-mingw32.cmake` file and
`CMAKE_INSTALL_PREFIX` to suit your distribution filesystem hierarchy.
Then create build directory and run cmake and make. You may need to modify the
`basic-mingw32.cmake` file and `CMAKE_INSTALL_PREFIX` to suit your distribution
filesystem hierarchy.
mkdir build-win
cd build-win
@ -270,20 +285,18 @@ cmake and make. You may need to modify the `basic-mingw32.cmake` file and
Then you can install the package using `make install` to make it available for
depending projects.
@section building-nacl Compiling for Google Chrome Native Client
@subsection building-cross-nacl Crosscompiling for Google Chrome Native Client
You will need [Native Client SDK](https://developers.google.com/native-client/beta/sdk/download).
Tested version is `pepper_22`.
Make sure you have `toolchains` submodule updated, as
@ref building-download "explained above". You can choose from either `glibc` or
`newlib` toolchain. `Newlib` supports only static linking, thus `BUILD_STATIC`
is always enabled. Don't forget to adapt `NACL_PREFIX` variable in
`generic/NaCl-*-x86-32.cmake` and `generic/NaCl-*-x86-64.cmake` to path where
your SDK is installed. Default is `/usr/nacl`. You may need to adapt also
`NACL_TOOLCHAIN_PATH` so CMake is able to find the compiler. NaCl currently
supports only OpenGL ES 2, thus `TARGET_GLES` and `TARGET_GLES2` is always
enabled.
You can choose from either `glibc` or `newlib` toolchain. `Newlib` supports
only static linking, thus `BUILD_STATIC` is always enabled. Don't forget to
adapt `NACL_PREFIX` variable in `generic/NaCl-*-x86-32.cmake` and
`generic/NaCl-*-x86-64.cmake` to path where your SDK is installed. Default is
`/usr/nacl`. You may need to adapt also `NACL_TOOLCHAIN_PATH` so CMake is able
to find the compiler. NaCl currently supports only OpenGL ES 2, thus
`TARGET_GLES` and `TARGET_GLES2` is always enabled.
Then create build directories for x86-32 and x86-64 and run cmake and make in
them. The toolchains need access to its platform file, so be sure to properly
@ -318,5 +331,38 @@ for depending projects. The headers are shared by both versions.
For ArchLinux there are also prepared package files in root, named
`PKGBUILD-nacl-glibc` and `PKGBUILD-nacl-newlib`.
@subsection building-cross-emscripten Crosscompiling for Emscripten
You will need [Emscripten](https://github.com/kripken/emscripten/wiki/Tutorial)
installed and configured.
Don't forget to adapt `EMSCRIPTEN_PREFIX` variable in `generic/Emscripten.cmake`
to path where Emscripten is installed. Default is `/usr/emscripten`. Emscripten
supports dynamic only to simplify porting and they are generally slower, thus
`BUILD_STATIC` is implicitly enabled.
Then create build directory and run cmake and make in it. The toolchain needs
access to its platform file, so be sure to properly set **absolute** path to
`modules/` directory containing `Platform/Emscripten.cmake`. Default is
`/usr/emscripten`. Also set `CMAKE_INSTALL_PREFIX` to value which is contained
in `CMAKE_FIND_ROOT_PATH` in toolchain file.
mkdir -p build-emscripten
cd build-emscripten
cmake .. \
-DCMAKE_MODULE_PATH="/absolute/path/to/toolchains/modules" \
-DCMAKE_TOOLCHAIN_FILE="../toolchains/generic/Emscripten.cmake" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr/emscripten/system \
-DWITH_SDL2APPLICATION=ON
make
Then you can install the library using `make install` to make it available for
depending projects.
If you have Node.js installed, you can also build and run unit tests using
`ctest`. See `BUILD_TESTS` above.
*/
}

18
doc/cmake.dox

@ -51,7 +51,7 @@ components. The base library depends on %Corrade and OpenGL libraries (or
OpenGL ES libraries). Additional dependencies are specified by the components.
The optional components are:
- `%Audio` -- Audio library (depends on OpenAL library)
- `%Audio` -- Audio library
- `%DebugTools` -- DebugTools library (depends on `%MeshTools`,
`%Primitives`, `%SceneGraph`, `%Shaders` and `%Shapes` components)
- `%MeshTools` -- MeshTools library
@ -65,17 +65,17 @@ The optional components are:
Platform namespace is split into more components:
- `%GlutApplication` -- @ref Platform::GlutApplication "GlutApplication"
(depends on GLUT library)
- `%GlxApplication` -- @ref Platform::GlxApplication "GlxApplication" (depends
on GLX and X11 libraries)
- `%GlxApplication` -- @ref Platform::GlxApplication "GlxApplication"
- `%NaClApplication` -- @ref Platform::NaClApplication "NaClApplication"
(only if targeting Google Chrome Native Client)
- `%Sdl2Application` -- @ref Platform::Sdl2Application "Sdl2Application"
(depends on SDL2 library)
- `%XEglApplication` -- @ref Platform::XEglApplication "XEglApplication"
(depends on EGL and X11 libraries)
- `%WindowlessNaClApplication` -- @ref Platform::WindowlessNaClApplication "WindowlessNaClApplication"
- `%WindowlessGlxApplication` -- @ref Platform::WindowlessGlxApplication "WindowlessGlxApplication"
(depends on GLX and X11 libraries)
Note that [each namespace](namespaces.html) and all @ref Platform libraries
contain more detailed information about dependencies, availability on
particular platform and also guide how to enable given library in build and use
it with CMake.
Example usage with specifying additional components is:
@ -96,6 +96,8 @@ convenience aliases `MAGNUM_APPLICATION_LIBRARIES` /
Features of found %Magnum library are exposed in these CMake variables, they
are also available as preprocessor variables if including Magnum.h:
- `MAGNUM_BUILD_DEPRECATED` -- Defined if compiled with deprecated APIs
included
- `MAGNUM_BUILD_STATIC` -- Defined if built as static libraries. Default are
shared libraries.
- `MAGNUM_TARGET_GLES` -- Defined if compiled for OpenGL ES

11
doc/debug-tools.dox

@ -24,15 +24,17 @@
namespace Magnum {
/** @page debug-tools Debugging helpers
@brief Convenience classes to help you during development.
@tableofcontents
- Previous page: @ref shapes
DebugTools library provides various helper classes to help you with
@ref DebugTools library provides various helper classes to help you with
prototyping and debugging applications without the need to write too much
common code. They probably have no usage in production code, but can be useful
in development.
in development. See documentation of @ref DebugTools namespace for more
information about building and usage with CMake.
@tableofcontents
@section debug-tools-renderers Debug renderers
@ -75,5 +77,6 @@ new DebugTools::ObjectRenderer2D(*object, "my", debugDrawables);
See DebugTools::ObjectRenderer and DebugTools::ShapeRenderer for more
information.
- Previous page: @ref shapes
*/
}

2
doc/features.dox

@ -24,7 +24,7 @@
namespace Magnum {
/** @page features Feature overview
@brief Fundamental principles and design goals
@brief Fundamental principles and design goals.
- @subpage platform -- @copybrief platform
- @subpage types -- @copybrief types

8
doc/mainpage.dox

@ -64,14 +64,22 @@ recent C++11 features and to abstract away platform-specific issues.
@section mainpage-platforms Supported platforms
Graphics APIs:
- **OpenGL** 2.1 through 4.4, core profile functionality and modern
extensions
- **OpenGL ES** 2.0, 3.0 and extensions to match desktop OpenGL functionality
- **WebGL** 1.0 and extensions to match desktop OpenGL functionality
Platforms:
- **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through
GLUT or SDL2 toolkit)
- **Windows** (through GLUT or SDL2 toolkit)
- **OS X** (through SDL2 toolkit, thanks to [Miguel Martin](https://github.com/miguelishawt))
- **Google Chrome** (through [Native Client](https://developers.google.com/native-client/),
both `newlib` and `glibc` toolchains are supported)
- **HTML5/JavaScript** (through [Emscripten](https://github.com/kripken/emscripten/wiki))
@section mainpage-features Features

34
doc/matrix-vector.dox

@ -24,15 +24,18 @@
namespace Magnum {
/** @page matrix-vector Operations with matrices and vectors
@brief Introduction to essential classes of the graphics pipeline.
@tableofcontents
- Previous page: @ref types
- Next page: @ref transformations
Matrices and vectors are the most important part of graphics programming and
one of goals of %Magnum is to make their usage as intuitive as possible. This
page will overview their usage and introduce some tricks to make your life
easier.
one of goals of %Magnum is to make their usage as intuitive as possible. They
are contained in @ref Math namespace and common variants also have aliases in
root @ref Magnum namespace. See documentation of these namespaces for more
information about usage with CMake.
@tableofcontents
@section matrix-vector-hierarchy Matrix and vector classes
@ -101,8 +104,8 @@ auto diag2 = Matrix3::fromDiagonal({3.0f, 2.0f, 1.0f});
It is possible to create matrices from other matrices and vectors with the same
row count; vectors from vector and scalar:
@code
Math::RectangularMatrix<2, 3, Int> a;
Math::Vector<3, Int> b, c;
Math::Matrix2x3<Int> a;
Math::Vector3<Int> b, c;
Math::Matrix3<Int> mat(a, b);
Math::Vector<8, Int> vec(1, b, 2, c);
@endcode
@ -115,7 +118,7 @@ on the array itself:
@code
Int[] mat = { 2, 4, 6,
1, 3, 5 };
RectangularMatrix<2, 3, Int>::from(mat) *= 2; // mat == { 4, 8, 12, 2, 6, 10 }
Math::Matrix2x3<Int>::from(mat) *= 2; // mat == { 4, 8, 12, 2, 6, 10 }
@endcode
Note that unlike constructors, this function has no way to check whether the
array is long enough to contain all elements, so use with caution.
@ -169,7 +172,7 @@ Math::Vector<6, Int> w10xyz = swizzle<'w', '1', '0', 'x', 'y', 'z'>(original); /
@section matrix-vector-operations Operations with matrices and vectors
Vectors can be added, subtracted, negated and multiplied or divided with
scalars, as is common in mathematics, Magnum also adds the ability to divide
scalars, as is common in mathematics, %Magnum also adds the ability to divide
scalar with vector:
@code
Vector3 a(1.0f, 2.0f, 3.0f);
@ -232,10 +235,10 @@ OpenGL matrices are column-major, thus it is reasonable to have matrices in
%Magnum also column major (and vectors as columns). This has naturally some
implications and it may differ from what is common in mathematics:
- Order of template arguments in specification of RectangularMatrix is also
column-major:
- Order of template arguments in specification of @ref Math::RectangularMatrix
is also column-major:
@code
Math::RectangularMatrix<2, 3, Int> mat; // two columns, three rows
Math::RectangularMatrix<2, 5, Int> mat; // two columns, five rows
@endcode
- Order of components in matrix constructors is also column-major, further
emphasized by requirement that you have to pass directly column vectors:
@ -256,5 +259,10 @@ mat[2][0] = 5; // first element of third column
alternatives which operate on columns. It's then up to user decision to
operate with transposed matrices or use the slower non-transposed
alternative of the algorithm.
&nbsp;
- Previous page: @ref types
- Next page: @ref transformations
*/
}}
}

118
doc/namespaces.dox

@ -33,8 +33,9 @@
Contains classes for interacting with OpenGL.
This library is built by default and found by default in CMake. See
@ref building and @ref cmake for more information.
This library 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
@ref cmake for more information.
*/
/** @dir Platform
@ -43,12 +44,15 @@ This library is built by default and found by default in CMake. See
/** @namespace Magnum::Platform
@brief Platform-specific application and context creation
Base classes for creating applications with various toolkits. See @ref platform
for introduction.
Base classes for creating applications with various toolkits.
Parts of this namespace are built when `WITH_*APPLICATION` is enabled and found
as `*Application` component in CMake. See @ref building and @ref cmake for more
information.
Parts of this namespace are built if `WITH_*APPLICATION` is enabled in CMake,
with each library having specific toolkit dependencies and platform
requirements. To use particular application library, you need to request given
`*Application` component in CMake, add `${MAGNUM_*APPLICATION_INCLUDE_DIRS}` to
include path and link to `${MAGNUM_*APPLICATION_LIBRARIES}`. See particular
`*Application` class documentation, @ref building, @ref cmake and @ref platform
for more information.
*/
/** @dir Math
@ -57,11 +61,11 @@ information.
/** @namespace Magnum::Math
@brief %Math library
Template classes for matrix and vector calculations. See @ref matrix-vector
and @ref transformations for introduction.
Template classes for matrix and vector calculations.
This library is built by default and found by default in CMake. See
@ref building and @ref cmake for more information.
This library 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,
@ref cmake, @ref matrix-vector and @ref transformations for more information.
*/
/** @dir Math/Algorithms
@ -72,8 +76,9 @@ This library is built by default and found by default in CMake. See
Various matrix and vector algorithms.
This library is built by default and found by default in CMake. See
@ref building and @ref cmake for more information.
This library 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
@ref cmake for more information.
*/
/** @dir Math/Geometry
@ -84,8 +89,9 @@ This library is built by default and found by default in CMake. See
Functions for computing intersections, distances, areas and volumes.
This library is built by default and found by default in CMake. See
@ref building and @ref cmake for more information.
This library 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
@ref cmake for more information.
*/
/** @dir Audio
@ -96,10 +102,13 @@ This library is built by default and found by default in CMake. See
Audio import, playback and integration with @ref SceneGraph.
This library is built when `WITH_AUDIO` is enabled and found as `%Audio`
component in CMake. See @ref building and @ref cmake for more information.
Additional plugins are part of plugin repository, see @ref building-plugins and
@ref cmake-plugins for more information.
This library depends on **OpenAL** library. It is built if `WITH_AUDIO` is
enabled in CMake. To use this library, you need to request `%Audio` component
in CMake, add `${MAGNUM_AUDIO_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_AUDIO_LIBRARIES}`. See @ref building and @ref cmake for more
information. Additional plugins are part of plugin repository, see particular
`*Importer` class documentation, @ref building-plugins and @ref cmake-plugins
for more information.
*/
/** @dir DebugTools
@ -108,12 +117,12 @@ Additional plugins are part of plugin repository, see @ref building-plugins and
/** @namespace Magnum::DebugTools
@brief %Debug tools
Debugging helpers, renderers and profilers. See @ref debug-tools for
introduction.
Debugging helpers, renderers and profilers.
This library is built when `WITH_DEBUGTOOLS` is enabled and found as
`%DebugTools` component in CMake. See @ref building and @ref cmake for more
information.
This library is built if `WITH_DEBUGTOOLS` is enabled in CMake. To use this
library, you need to request `%DebugTools` component in CMake and link to
`${MAGNUM_DEBUGTOOLS_LIBRARIES}`. See @ref building, @ref cmake and
@ref debug-tools for more information.
*/
/** @dir MeshTools
@ -124,8 +133,9 @@ information.
Tools for generating, optimizing and cleaning meshes.
This library is built when `WITH_MESHTOOLS` is enabled and found as
`%MeshTools` component in CMake. See @ref building and @ref cmake for more
This library is built if `WITH_MESHTOOLS` is enabled in CMake. To use this
library, you need to request `%MeshTools` component in CMake and link to
`${MAGNUM_MESHTOOLS_LIBRARIES}`. See @ref building and @ref cmake for more
information.
*/
@ -137,8 +147,9 @@ information.
Basic primitives for testing purposes.
This library is built when `WITH_PRIMITIVES` is enabled and found as
`%Primitives` component in CMake. See @ref building and @ref cmake for more
This library is built if `WITH_PRIMITIVES` is enabled in CMake. To use this
library, you need to request `%Primitives` component in CMake and link to
`${MAGNUM_PRIMITIVES_LIBRARIES}`. See @ref building and @ref cmake for more
information.
*/
@ -149,24 +160,26 @@ information.
@namespace Magnum::SceneGraph
@brief %Scene graph library
Managing object hierarchy, transformations and interactions. See
@ref scenegraph for introduction.
Managing object hierarchy, transformations and interactions.
This library is built when `WITH_SCENEGRAPH` is enabled and found as
`%SceneGraph` component in CMake. See @ref building and @ref cmake for more
information.
This library is built if `WITH_SCENEGRAPH` is enabled in CMake. To use this
library, you need to request `%SceneGraph` component in CMake and link to
`${MAGNUM_SCENEGRAPH_LIBRARIES}`. See @ref building, @ref cmake and
@ref scenegraph for more information.
*/
/** @dir Shaders
* @brief Namespace Magnum::Shaders
*/
/** @namespace Magnum::Shaders
@brief Sample shaders
@brief Builtin shaders
Collection of shaders for testing purposes.
Collection of shaders for easy prototyping and basic usage.
This library is built when `WITH_SHADERS` is enabled and found as `%Shaders`
component in CMake. See @ref building and @ref cmake for more information.
This library is built if `WITH_SHADERS` is enabled in CMake. To use this
library, you need to request `%Shaders` component in CMake and link to
`${MAGNUM_MESHTOOLS_SHADERS}`. See @ref building and @ref cmake for more
information.
*/
/** @dir Shapes
@ -175,10 +188,12 @@ component in CMake. See @ref building and @ref cmake for more information.
/** @namespace Magnum::Shapes
@brief %Shape library
Collision detection system. See @ref shapes for introduction.
Collision detection system.
This library is built when `WITH_SHAPES` is enabled and found as `%Shapes`
component in CMake. See @ref building and @ref cmake for more information.
This library is built if `WITH_SHAPES` is enabled in CMake. To use this
library, you need to request `%Shapes` component in CMake and link to
`${MAGNUM_SHAPES_LIBRARIES}`. See @ref building, @ref cmake and @ref shapes for
more information.
*/
/** @dir Text
@ -189,10 +204,12 @@ component in CMake. See @ref building and @ref cmake for more information.
Font texture creation and text layouting.
This library is built when `WITH_TEXT` is enabled and found as `%Text`
component in CMake. See @ref building and @ref cmake for more information.
Additional plugins are part of plugin repository, see @ref building-plugins and
@ref cmake-plugins for more information.
This library is built if `WITH_TEXT` is enabled in CMake. To use this library,
you need to request `%Text` component in CMake and link to `${MAGNUM_TEXT_LIBRARIES}`.
See @ref building and @ref cmake for more information. Additional plugins are
part of plugin repository, see particular `*Font` and `*FontConverter` class
documentation, @ref building-plugins and @ref cmake-plugins for more
information.
*/
/** @dir TextureTools
@ -203,8 +220,9 @@ Additional plugins are part of plugin repository, see @ref building-plugins and
Tools for generating, compressing and optimizing textures.
This library is built when `WITH_TEXTURETOOLS` is enabled and found as
`%TextureTools` component in CMake. See @ref building and @ref cmake for more
This library is built if `WITH_TEXTURETOOLS` is enabled in CMake. To use this
library, you need to request `%TextureTools` component in CMake and link to
`${MAGNUM_TEXTURETOOLS_LIBRARIES}`. See @ref building and @ref cmake for more
information.
*/
@ -217,8 +235,10 @@ information.
Contains plugin interfaces for importing data of various formats and classes
for direct access to the data.
This library is built by default and found by default in CMake. See
@ref building and @ref cmake for more information. Additional plugins are part
of plugin repository, see @ref building-plugins and @ref cmake-plugins for more
This library 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
@ref cmake for more information. Additional plugins are part of plugin
repository, see particular `*Importer` and `*ImageConverter` class
documentation, @ref building-plugins and @ref cmake-plugins for more
information.
*/

118
doc/platform.dox

@ -24,39 +24,55 @@
namespace Magnum { namespace Platform {
/** @page platform Platform support
@brief Integration into windowing toolkits and creation of windowless contexts.
@brief Integration into windowing toolkits and creation of windowless contexts
- Next page: @ref types
@tableofcontents
@ref Platform namespace contains classes integrating %Magnum engine into
various toolkits, both windowed and windowless. Each class has slightly
different dependencies and platform requirements, see documentation of
@ref Platform namespace and particular `*Application` classes for more
information about building and usage with CMake.
Platform namespace provides classes integrating %Magnum engine into various
toolkits, both windowed and windowless. All the classes have common API to
achieve static polymorphism, so basically you can use different toolkits on
different platforms and the only thing you need to change is the class name,
everything else is the same.
@tableofcontents
Basic usage is to subclass the chosen `*Application` class and implement
required methods.
All the classes have common API to achieve static polymorphism, so basically
you can use different toolkits on different platforms and the only thing you
need to change is the class name, everything else is the same. Basic usage is
to subclass the chosen `*Application` class and implement required methods.
@section platform-windowed Windowed applications
Windowed applications provide a window and keyboard and mouse handling. The
most basic toolkit (and toolkit available on most platforms) is GLUT, which is
is implemented in GlutApplication. As said above, the usage is similar for all
toolkits, you must provide two-argument constructor and implement at least
@ref GlutApplication::viewportEvent() "viewportEvent()" and
@ref GlutApplication::drawEvent() "drawEvent()".
most basic toolkit (and toolkit packaged for most systems) is GLUT, which is
implemented in @ref Platform::GlutApplication. As said above, the usage is
similar for all toolkits, you must provide one-argument constructor and
implement at least @ref GlutApplication::viewportEvent() "viewportEvent()" and
@ref GlutApplication::drawEvent() "drawEvent()". The class can be then used
directly in `main()`, but for convenience and portability it's better to use
@ref MAGNUM_GLUTAPPLICATION_MAIN() macro.
To simplify the porting, the library provides `Platform::Application` typedef
and `MAGNUM_APPLICATION_MAIN()` macro (but only if only one application header
is included, to avoid ambiguity). Changing the code to use different toolkit is
then matter of replacing only the <tt>#</tt>`include` statement.
Barebone application implementation which will just clear the window to dark
blue color:
blue color is shown in the following code listing.
@note Fully contained base application along with CMake setup is available in
`base` branch of [Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap)
repository.
@code
#include <Color.h>
#include <DefaultFramebuffer.h>
#include <Renderer.h>
#include <Platform/GlutApplication.h>
using namespace Magnum;
class MyApplication: public Platform::GlutApplication {
class MyApplication: public Platform::Application {
public:
MyApplication(const Arguments& arguments);
@ -64,7 +80,7 @@ class MyApplication: public Platform::GlutApplication {
void drawEvent() override;
};
MyApplication::MyApplication(const Arguments& arguments): Platform::GlutApplication(arguments) {
MyApplication::MyApplication(const Arguments& arguments): Platform::Application(arguments) {
// Set clear color to dark blue
Renderer::setClearColor({0.0f, 0.0f, 0.4f});
}
@ -83,7 +99,7 @@ void MyApplication::drawEvent() {
}
// main() function implementation
MAGNUM_GLUTAPPLICATION_MAIN(MyApplication)
MAGNUM_APPLICATION_MAIN(MyApplication)
@endcode
@section platform-windowless Windowless applications
@ -91,25 +107,42 @@ MAGNUM_GLUTAPPLICATION_MAIN(MyApplication)
Windowless applications provide just a context for ofscreen rendering or
performing tasks on GPU. There is not yet any platform-independent toolkit
which could handle this in portable way, thus you have to use platform-specific
ones. As example we use WindowlessGlxApplication, you need to implement just
@ref WindowlessGlxApplication::exec() "exec()" function.
ones. As example we use @ref Platform::WindowlessGlxApplication, you need to
implement just @ref WindowlessGlxApplication::exec() "exec()" function. The
class can be then used directly in `main()`, but again, for convenience and
portability it's better to use @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN()
macro.
Similarly as with windowed applications, to simplify the porting, the library
provides `Platform::WindowlessApplication` typedef and `MAGNUM_WINDOWLESSAPPLICATION_MAIN()`
macro, but only if only one windowless application header is included. Changing
the code to use different toolkit is then matter of replacing only the
<tt>#</tt>`include` statement. Aliases for windowless applications are
separated from aliases for windowed applications, because projects commonly
contain both graphics application and command-line tools (for data preparation
etc.).
Barebone application which will just print out current OpenGL version and
renderer string and exits:
renderer string and exits is in the following code listing.
@note Fully contained windowless application along with CMake setup is
available in `windowless` branch of [Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap)
repository.
@code
#include <Context.h>
#include <Platform/WindowlessGlxApplication.h>
using namespace Magnum;
class MyApplication: public Platform::WindowlessGlxApplication {
class MyApplication: public Platform::WindowlessApplication {
public:
MyApplication(const Arguments& arguments);
int exec() override;
};
MyApplication::MyApplication(const Arguments& arguments): Platform::WindowlessGlxApplication(arguments) {}
MyApplication::MyApplication(const Arguments& arguments): Platform::WindowlessApplication(arguments) {}
int MyApplication::exec() {
Debug() << "OpenGL version:" << Context::current()->versionString();
@ -120,23 +153,31 @@ int MyApplication::exec() {
}
// main() function implementation
MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(MyApplication)
MAGNUM_WINDOWLESSAPPLICATION_MAIN(MyApplication)
@endcode
@section platform-compilation Compilation with CMake
Barebone compilation consists just of finding %Magnum library with required
`*Application` component, compilation of the executable and linking the
libraries to it:
`*Application` component, adding %Magnum's `${MAGNUM_INCLUDE_DIRS}` and application-specific `${MAGNUM_GLUTAPPLICATION_INCLUDE_DIRS}` to include path, compilation of the
executable and linking `${MAGNUM_LIBRARIES}` and `${MAGNUM_GLUTAPPLICATION_LIBRARIES}`
to it.
Again, to simplify porting, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}`
and `${MAGNUM_WAPPLICATION_LIBRARIES}` aliases (or `${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}`, `${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` for windowless applications), but
only if only one application (windowless application) component is requested to
avoid ambiguity. Changing the code to use different toolkit is then matter of
replacing only the requested `*Application` component.
@code
find_package(Magnum REQUIRED GlutApplication)
include_directories(${MAGNUM_INCLUDE_DIRS})
include_directories(${MAGNUM_INCLUDE_DIRS} ${MAGNUM_APPLICATION_INCLUDE_DIRS})
add_executable(myapplication MyApplication.cpp)
target_link_libraries(myapplication
${MAGNUM_LIBRARIES}
${MAGNUM_GLUTAPPLICATION_LIBRARIES})
${MAGNUM_APPLICATION_LIBRARIES})
@endcode
@section platform-configuration Specifying configuration
@ -147,20 +188,20 @@ window size 800x600 pixels). If you want something else, you can pass
constructor. Using method chaining it can be done conveniently like this:
@code
MyApplication::MyApplication(int& argc, char** argv):
Platform::GlutApplication(argc, argv, Configuration()
Platform::Application(argc, argv, Configuration()
.setTitle("My Application")
.setSize({800, 600})
{
{
// ...
}
@endcode
However, sometimes you would need to configure the application based on some
configuration file or system introspection. In that case you can pass `nullptr`
instead of Configuration instance and then specify it later with
@ref GlutApplication::createContext() "createContext()":
instead of @ref GlutApplication::Configuration "Configuration" instance and
then specify it later with @ref GlutApplication::createContext() "createContext()":
@code
MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(argc, argv, nullptr) {
MyApplication::MyApplication(int& argc, char** argv): Platform::Application(argc, argv, nullptr) {
// ...
createContext(Configuration()
@ -173,12 +214,12 @@ MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(
If the context creation in constructor or @ref GlutApplication::createContext() "createContext()"
fails, the application exits. However, it is also possible to negotiate the
context using @ref GlutApplication::tryCreateContext() "tryCreateContext()". The
only difference is that this function returns `false` instead of exiting. You
can for example try enabling MSAA and if the context creation fails, fall back
to no-AA rendering:
context using @ref GlutApplication::tryCreateContext() "tryCreateContext()".
The only difference is that this function returns `false` instead of exiting.
You can for example try enabling MSAA and if the context creation fails, fall
back to no-AA rendering:
@code
MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(argc, argv, nullptr) {
MyApplication::MyApplication(int& argc, char** argv): Platform::Application(argc, argv, nullptr) {
// ...
Configuration conf;
@ -192,5 +233,6 @@ MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(
}
@endcode
- Next page: @ref types
*/
}}

16
doc/portability.dox

@ -175,19 +175,9 @@ can just switch to another base class and in many cases you won't need to
change any other code. It has its limitations, though - some toolkits don't
support all keys, mouse movement events etc.
In most cases the entry point is classic `main()` function, but some platforms
(e.g. Native Client) have different requirements. To make things easier, entry
points are handled using macros, which take care of the rest.
If exactly one `*Application` or `*Windowless*Application` header is included,
the application class is aliased to `Platform::Application` or
`Platform::WindowlessApplication` and the macro is aliased to
`MAGNUM_APPLICATION_MAIN()` or `MAGNUM_WINDOWLESSAPPLICATION_MAIN()` to
simplify porting. The same is with CMake code, if exactly one `*Application` or
`Windowless*Application` component , the libraries and include dirs are
available in `MAGNUM_APPLICATION_LIBRARIES` / `MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES`
and `MAGNUM_APPLICATION_INCLUDE_DIRS` / `MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS`
variables.
As mentioned in @ref platform, all the classes, macros and CMake variables have
generic aliases, thus using different toolkit is in most cases only matter of
replacing two lines of code.
Example application, which targets both embedded Linux (using plain X and EGL)
and desktop (using SDL2 toolkit). Thanks to static polymorphism most of the

108
doc/scenegraph.dox

@ -26,30 +26,41 @@ namespace Magnum { namespace SceneGraph {
/** @page scenegraph Using scene graph
@brief Overview of scene management capabilities.
@tableofcontents
- Previous page: @ref transformations
- Next page: @ref shapes
%Scene graph provides way to hiearchically manage your objects, their
transformation, physics interaction, animation and rendering. There are
naturally many possible combinations (2D vs. 3D, different transformation
representations, animated vs. static, object can have collision shape,
participate in physics events, have forward vs. deferred rendering...). To
make everything possible without combinatiorial explosion and allow the users
to provide their own features, scene graph in %Magnum is composed of three
main components:
transformation, physics interaction, animation and rendering. The library is
contained in @ref SceneGraph namespace, see its documentation for more
information about building and usage with CMake.
@tableofcontents
There are naturally many possible feature combinations (2D vs. 3D, different
transformation representations, animated vs. static, object can have collision
shape, participate in physics events, have forward vs. deferred rendering...)
and to make everything possible without combinatiorial explosion and allow the
users to provide their own features, scene graph in %Magnum is composed of
three main components:
- objects, providing parent/children hierarchy
- transformations, implementing particular transformation type
- features, providing rendering capabilities, collision detection, physics
etc.
@note Fully contained applications with initial scene graph setup are available
in `scenegraph2D` and `scenegraph3D` branches of
[Magnum Bootstrap](https://github.com/mosra/magnum-bootstrap) repository.
@section scenegraph-transformation Transformations
Transformation handles object position, rotation etc. and its basic property
is dimension count (2D or 3D) and underlying floating-point type.
@note All classes in SceneGraph are templated on underlying type. However, in
most cases Float is used and thus nearly all classes have convenience
aliases so you don't have to explicitly specify it.
@note All classes in @ref SceneGraph are templated on underlying type. However,
in most cases @ref Magnum::Float "Float" is used and thus nearly all
classes have convenience aliases so you don't have to explicitly specify
it.
%Scene graph has implementation of transformations in both 2D and 3D, using
either matrices or combination of position and rotation. Each implementation
@ -60,24 +71,23 @@ won't allow you to scale or shear objects, but are more memory efficient than
matrices.
It's also possible to implement your own transformation class for specific
needs, see @ref AbstractTransformation-subclassing
"AbstractTransformation documentation" for more information.
needs, see source of other transformation classes for more information.
@section scenegraph-hierarchy Scene hierarchy
%Scene hierarchy is skeleton part of scene graph. In the root there is Scene
and its children are Object instances. The hierarchy has some transformation
type, identical for all objects (because for example having part of the tree
in 2D and part in 3D just wouldn't make sense). Common usage is to typedef
%Scene and %Object with desired transformation type to save unnecessary typing
later:
%Scene hierarchy is skeleton part of scene graph. In the root there is
@ref Scene and its children are @ref Object instances. The hierarchy has some
transformation type, identical for all objects (because for example having part
of the tree in 2D and part in 3D just wouldn't make sense). Common usage is to
typedef %Scene and %Object with desired transformation type to save unnecessary
typing later:
@code
typedef SceneGraph::Scene<SceneGraph::MatrixTransformation3D> Scene3D;
typedef SceneGraph::Object<SceneGraph::MatrixTransformation3D> Object3D;
@endcode
Then you can start building the hierarchy by *parenting* one object to another.
Parent object can be either passed in constructor or using Object::setParent().
Parent object can be either passed in constructor or using @ref Object::setParent().
%Scene is always root object, so it naturally cannot have parent object.
@code
Scene3D scene;
@ -86,10 +96,10 @@ auto first = new Object3D(&scene);
auto second = new Object3D(first);
@endcode
%Object children can be accessed using Object::firstChild() and
Object::lastChild(), then you can traverse siblings (objects with the same
parent) with Object::previousSibling() and Object::nextSibling(). For example
all children of an object can be traversed the following way:
%Object children can be accessed using @ref Object::firstChild() and
@ref Object::lastChild(), then you can traverse siblings (objects with the same
parent) with @ref Object::previousSibling() and @ref Object::nextSibling(). For
example all children of an object can be traversed the following way:
@code
Object3D* o;
for(Object3D* child = o->firstChild(); child; child = child->nextSibling()) {
@ -127,9 +137,9 @@ Object3D* o;
new MyFeature(o);
@endcode
Features of an object can be accessed using Object::firstFeature() and
Object::lastFeature(), then you can traverse the features using
AbstractFeature::previousFeature() and AbstractFeature::nextFeature(),
Features of an object can be accessed using @ref Object::firstFeature() and
@ref Object::lastFeature(), then you can traverse the features using
@ref AbstractFeature::previousFeature() and @ref AbstractFeature::nextFeature(),
similarly to traversing object children:
@code
Object3D* o;
@ -144,11 +154,11 @@ Active features require the user to implement some virtual function (for
example to draw the object on screen or perform animation step). To make things
convenient, features can be added directly to object itself using multiple
inheritance, so you can conveniently add all the active features you want and
implement needed functions in your own Object subclass without having to
implement needed functions in your own @ref Object subclass without having to
subclass each feature individually (and making the code overly verbose).
Simplified example:
@code
class Bomb: public Object3D, SceneGraph::Drawable3D, SceneGraph:.Animable3D {
class Bomb: public Object3D, SceneGraph::Drawable3D, SceneGraph::Animable3D {
public:
Bomb(Object3D* parent): Object3D(parent), SceneGraph::Drawable3D(*this), SceneGraph::Animable3D(*this) {}
@ -179,20 +189,21 @@ objects etc. To avoid computing the transformations from scratch every time,
the feature can cache them.
The cached data stay until the object is marked as dirty - that is by changing
transformation, changing parent or explicitly calling Object::setDirty(). If
the object is marked as dirty, all its children are marked as dirty too and
AbstractFeature::markDirty() is called on every feature. Calling
Object::setClean() cleans the dirty object and all its dirty parents.
The function goes through all object features and calls AbstractFeature::clean()
or AbstractFeature::cleanInverted() depending on which caching is enabled on
given feature. If the object is already clean, Object::setClean() does nothing.
Most probably you will need caching in Object itself -- which doesn't support
it on its own -- however you can take advantage of multiple inheritance and
implement it using AbstractFeature. In order to have caching, you must enable
it first, because by default the caching is disabled. You can enable it using
AbstractFeature::setCachedTransformations() and then implement corresponding
cleaning function(s):
transformation, changing parent or explicitly calling @ref Object::setDirty().
If the object is marked as dirty, all its children are marked as dirty too and
@ref AbstractFeature::markDirty() is called on every feature. Calling
@ref Object::setClean() cleans the dirty object and all its dirty parents.
The function goes through all object features and calls @ref AbstractFeature::clean()
or @ref AbstractFeature::cleanInverted() depending on which caching is enabled
on given feature. If the object is already clean, @ref Object::setClean() does
nothing.
Most probably you will need caching in @ref Object itself -- which doesn't
support it on its own -- however you can take advantage of multiple inheritance
and implement it using @ref AbstractFeature. In order to have caching, you must
enable it first, because by default the caching is disabled. You can enable it
using @ref AbstractFeature::setCachedTransformations() and then implement
corresponding cleaning function(s):
@code
class CachingObject: public Object3D, SceneGraph::AbstractFeature3D {
public:
@ -211,9 +222,9 @@ class CachingObject: public Object3D, SceneGraph::AbstractFeature3D {
@endcode
When you need to use the cached value, you can explicitly request the cleanup
by calling Object::setClean(). Camera, for example, calls it automatically
before it starts rendering, as it needs its own inverse transformation to
properly draw the objects.
by calling @ref Object::setClean(). @ref Camera3D "Camera", for example, calls
it automatically before it starts rendering, as it needs its own inverse
transformation to properly draw the objects.
See @ref AbstractFeature-subclassing-caching for more information.
@ -284,7 +295,7 @@ wouldn't help either:
@code
class MyObject: MyFeature, public Object3D {
public:
MyObject(Object3D* parent): Object3D(parent), MyFeature(this) {}
MyObject(Object3D* parent): Object3D(parent), MyFeature(*this) {}
// crash on destruction!
};
@ -292,5 +303,8 @@ class MyObject: MyFeature, public Object3D {
On destruction, Object3D destructor is called first, deleting MyFeature,
which is wrong, because MyFeature is in the same object. After that (if the
program didn't already crash) destructor of MyFeature is called (again).
- Previous page: @ref transformations
- Next page: @ref shapes
*/
}}

15
doc/shapes.dox

@ -26,13 +26,19 @@ namespace Magnum { namespace Shapes {
/** @page shapes Collision detection
@brief Collection of simple shapes for high performance collision detection.
- Previous page: @ref scenegraph
- Next page: @ref debug-tools
The essential thing in collision detection is to define a complex object with
collection of simple shapes, for which it is easy to detect collisions. These
shapes can be either one-, two- or three-dimensional and they can be grouped
together using various operations.
collection of simple shapes, for which it is easy to detect collisions. The
library is contained in @ref Shapes namespace, see its documentation for more
information about building and usage with CMake.
@tableofcontents
These shapes can be either one-, two- or three-dimensional and they can be
grouped together using various operations.
@section shapes-collection Available shapes
%Magnum provides a set of simple shapes for collision detection, similarly to
@ -140,5 +146,8 @@ auto shape = Shapes::Shape<Shapes::Sphere3D>(object, {{}, 23.0f});
See also @ref scenegraph for introduction.
- Previous page: @ref scenegraph
- Next page: @ref debug-tools
*/
}}}

21
doc/transformations.dox

@ -24,16 +24,22 @@
namespace Magnum { namespace Math {
/** @page transformations 2D and 3D transformations
@brief Introduction to essential operations on vectors and points.
@tableofcontents
- Previous page: @ref matrix-vector
- Next page: @ref scenegraph
Transformations are essential operations involved in scene management -- object
relations, hierarchies, animations etc. %Magnum provides classes for
transformations in both 2D and 3D. Each class is suited for different purposes,
but their usage is nearly the same to make your life simpler. This page will
explain the basic operation and differences between various representations.
relations, hierarchies, animations etc. They extend basic vectors and matrices
in @ref Math namespace, see its documentation for more information about usage
with CMake.
@tableofcontents
%Magnum provides classes for transformations in both 2D and 3D. Each class is
suited for different purposes, but their usage is nearly the same to make your
life simpler. This page will explain the basic operation and differences
between various representations.
@section transformations-representation Representing transformations
@ -310,5 +316,8 @@ are always of unit length, thus normalizing them reduces the drift.
DualQuaternion transformation;
transformation = transformation.normalized();
@endcode
- Previous page: @ref matrix-vector
- Next page: @ref scenegraph
*/
}}

46
doc/types.dox

@ -24,15 +24,20 @@
namespace Magnum {
/** @page types Type system
@brief Type aliases, naming and compatibility with OpenGL and GLSL types.
@brief Type aliases, naming and compatibility with OpenGL and GLSL types
- Previous page: @ref platform
- Next page: @ref matrix-vector
The root @ref Magnum namespace defines a few aliases for essential types. See
its documentation for more information about usage with CMake.
@section types-builtin Builtin types
%Magnum provides typedefs for builtin integral and floating-point arithmetic
types to ensure portability (e.g. Int is *always* 32bit), maintain consistency
and reduce confusion (e.g. `std::int32_t`, `int` and `GLint` all refer to the
same type).
types to ensure portability (e.g. @ref Int is *always* 32bit), maintain
consistency and reduce confusion (e.g. `std::int32_t`, `int` and `GLint` all
refer to the same type).
| %Magnum type | Size | Equivalent GLSL type |
| ------------------ | -------------- | -------------------- |
@ -52,9 +57,10 @@ types which cannot be directly passed to GLSL shaders (such as `long double`)
have no typedefs.
Types from the above table are then used to define other types. All following
types are aliases of corresponding types in Math namespace. No suffix after type
name means @ref Float underlying type, `ui` means @ref UnsignedInt underlying
type, `i` is @ref Int underlying type and `d` is for @ref Double underlying type.
types are aliases of corresponding types in @ref Math namespace. No suffix
after type name means @ref Float underlying type, `ui` means @ref UnsignedInt
underlying type, `i` is @ref Int underlying type and `d` is for @ref Double
underlying type.
@section types-matrix Matrix/vector types
@ -65,20 +71,20 @@ type, `i` is @ref Int underlying type and `d` is for @ref Double underlying type
| @ref Vector2i, @ref Vector3i, @ref Vector4i | `ivec2`, `ivec3`, `ivec4` |
| @ref Vector2d, @ref Vector3d, @ref Vector4d | `dvec2`, `dvec3`, `dvec4` |
| %Magnum matrix type | Equivalent GLSL type |
| --------------------------------- | ------------------------------------ |
| @ref Matrix2 or @ref Matrix2d | `mat2`/`mat2x2` or `dmat2`/`dmat2x2` |
| @ref Matrix3 or @ref Matrix3d | `mat3`/`mat3x3` or `dmat3`/`dmat3x3` |
| @ref Matrix4 or @ref Matrix4d | `mat4`/`mat4x4` or `dmat4`/`dmat4x4` |
| @ref Matrix2x3 or @ref Matrix2x3d | `mat2x3` or `dmat2x3` |
| @ref Matrix3x2 or @ref Matrix3x2d | `mat3x2` or `dmat3x2` |
| @ref Matrix2x4 or @ref Matrix2x4d | `mat2x4` or `dmat2x4` |
| @ref Matrix4x2 or @ref Matrix4x2d | `mat4x2` or `dmat4x2` |
| @ref Matrix3x4 or @ref Matrix3x4d | `mat3x4` or `dmat3x4` |
| @ref Matrix4x3 or @ref Matrix4x3d | `mat4x3` or `dmat4x3` |
| %Magnum matrix type | Equivalent GLSL type |
| ---------------------------------------------------------------- | ------------------------------------ |
| @ref Matrix2x2 or @ref Matrix2x2d | `mat2`/`mat2x2` or `dmat2`/`dmat2x2` |
| @ref Matrix3 / @ref Matrix3x3 or @ref Matrix3d / @ref Matrix3x3d | `mat3`/`mat3x3` or `dmat3`/`dmat3x3` |
| @ref Matrix4 / @ref Matrix4x4 or @ref Matrix4d / @ref Matrix4x4d | `mat4`/`mat4x4` or `dmat4`/`dmat4x4` |
| @ref Matrix2x3 or @ref Matrix2x3d | `mat2x3` or `dmat2x3` |
| @ref Matrix3x2 or @ref Matrix3x2d | `mat3x2` or `dmat3x2` |
| @ref Matrix2x4 or @ref Matrix2x4d | `mat2x4` or `dmat2x4` |
| @ref Matrix4x2 or @ref Matrix4x2d | `mat4x2` or `dmat4x2` |
| @ref Matrix3x4 or @ref Matrix3x4d | `mat3x4` or `dmat3x4` |
| @ref Matrix4x3 or @ref Matrix4x3d | `mat4x3` or `dmat4x3` |
Any super- or sub-class of the same size and underlying type can be used
equivalently (e.g. Math::Vector or Color3 instead of @ref Vector3).
equivalently (e.g. @ref Math::Vector or @ref Color3 instead of @ref Vector3).
@section types-other Other types
@ -95,5 +101,7 @@ quaternion to matrix).
For your convenience, there is also alias for class with often used constants --
@ref Constants or @ref Constantsd.
- Previous page: @ref platform
- Next page: @ref matrix-vector
*/
}

14
doc/unsupported.dox

@ -25,7 +25,7 @@
/** @page unsupported Unsupported OpenGL features
Some functionality, which is either soon-to-be deprecated or isn't proven to
add any performance gains, is not supported in %Magnum.
add any performance gains, is not supported in %Magnum. See also @ref deprecated-gl.
@section unsupported-features Unsupported features
@ -48,3 +48,15 @@ add any performance gains, is not supported in %Magnum.
doesn't make any full-screen postprocessing easier, as shaders are excluded.
*/
/** @page deprecated-gl Deprecated OpenGL API list
See also @ref unsupported and @ref deprecated.
*/
/** @page deprecated Deprecated list
See also @ref deprecated-gl.
*/

24
external/OpenGL/GL/gl_magnum.c vendored

@ -4,27 +4,15 @@
#include "gl_magnum.h"
#if defined(__APPLE__)
#include <mach-o/dyld.h>
#include <dlfcn.h>
static void* AppleGLGetProcAddress (const GLubyte *name)
static void* AppleGLGetProcAddress (const char *name)
{
static const struct mach_header* image = NULL;
NSSymbol symbol;
char* symbolName;
static void* image = NULL;
if (NULL == image)
{
image = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
}
/* prepend a '_' for the Unix C symbol mangling convention */
symbolName = malloc(strlen((const char*)name) + 2);
strcpy(symbolName+1, (const char*)name);
symbolName[0] = '_';
symbol = NULL;
/* if (NSIsSymbolNameDefined(symbolName))
symbol = NSLookupAndBindSymbol(symbolName); */
symbol = image ? NSLookupSymbolInImage(image, symbolName, NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) : NULL;
free(symbolName);
return symbol ? NSAddressOfSymbol(symbol) : NULL;
image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
return image ? dlsym(image, name) : NULL;
}
#endif /* __APPLE__ */

4
external/Optional/optional.hpp vendored

@ -155,7 +155,9 @@ template <class T> inline constexpr typename std::remove_reference<T>::type&& co
# define ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : (fail(#CHECK, __FILE__, __LINE__), (EXPR)))
inline void fail(const char* expr, const char* file, unsigned line)
{
# if defined __clang__ || defined __GNU_LIBRARY__
# if defined(EMSCRIPTEN) && EMSCRIPTEN
__assert_fail(expr, file, line, "");
# elif defined __clang__ || defined __GNU_LIBRARY__
__assert(expr, file, line);
# elif defined __GNUC__
_assert(expr, file, line);

13
modules/FindCorrade.cmake

@ -27,6 +27,8 @@
# mode for GCC 4.5
# CORRADE_GCC44_COMPATIBILITY - Defined if compiled with compatibility
# mode for GCC 4.4
# CORRADE_BUILD_DEPRECATED - Defined if compiled with deprecated APIs
# included
# CORRADE_BUILD_STATIC - Defined if compiled as static libraries
# CORRADE_TARGET_NACL - Defined if compiled for Google Chrome
# Native Client
@ -128,9 +130,14 @@ find_path(CORRADE_INCLUDE_DIR
# CMake module dir
find_path(_CORRADE_MODULE_DIR
NAMES UseCorrade.cmake CorradeLibSuffix.cmake
PATHS ${CMAKE_ROOT}/Modules
PATH_SUFFIXES share/cmake/Corrade)
# If not found, try system module dir
find_path(_CORRADE_MODULE_DIR
NAMES UseCorrade.cmake CorradeLibSuffix.cmake
PATHS ${CMAKE_ROOT}/Modules
NO_CMAKE_FIND_ROOT_PATH)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Corrade DEFAULT_MSG
CORRADE_UTILITY_LIBRARY
@ -165,6 +172,10 @@ string(FIND "${_corradeConfigure}" "#define CORRADE_GCC47_COMPATIBILITY" _GCC47_
if(NOT _GCC47_COMPATIBILITY EQUAL -1)
set(CORRADE_GCC47_COMPATIBILITY 1)
endif()
string(FIND "${_corradeConfigure}" "#define CORRADE_BUILD_DEPRECATED" _BUILD_DEPRECATED)
if(NOT _BUILD_DEPRECATED EQUAL -1)
set(CORRADE_BUILD_DEPRECATED 1)
endif()
string(FIND "${_corradeConfigure}" "#define CORRADE_BUILD_STATIC" _BUILD_STATIC)
if(NOT _BUILD_STATIC EQUAL -1)
set(CORRADE_BUILD_STATIC 1)

35
modules/FindMagnum.cmake

@ -20,7 +20,7 @@
# components. The base library depends on Corrade and OpenGL libraries (or
# OpenGL ES libraries). Additional dependencies are specified by the
# components. The optional components are:
# Audio - Audio library (depends on OpenAL library)
# Audio - Audio library
# DebugTools - DebugTools library (depends on MeshTools, Primitives,
# SceneGraph, Shaders and Shapes components)
# MeshTools - MeshTools library
@ -30,14 +30,13 @@
# Shapes - Shapes library (depends on SceneGraph component)
# Text - Text library (depends on TextureTools component)
# TextureTools - TextureTools library
# GlutApplication - GLUT application (depends on GLUT library)
# GlxApplication - GLX application (depends on GLX and X11 libraries)
# NaClApplication - NaCl application (only if targeting Google Chrome
# Native Client)
# Sdl2Application - SDL2 application (depends on SDL2 library)
# XEglApplication - X/EGL application (depends on EGL and X11 libraries)
# WindowlessGlxApplication - Windowless GLX application (depends on GLX
# and X11 libraries)
# GlutApplication - GLUT application
# GlxApplication - GLX application
# NaClApplication - NaCl application
# Sdl2Application - SDL2 application
# XEglApplication - X/EGL application
# WindowlessNaClApplication - Windowless NaCl application
# WindowlessGlxApplication - Windowless GLX application
# Example usage with specifying additional components is:
# find_package(Magnum [REQUIRED|COMPONENTS]
# MeshTools Primitives GlutApplication)
@ -52,11 +51,13 @@
# / MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS to simplify porting.
#
# Features of found Magnum library are exposed in these variables:
# MAGNUM_BUILD_STATIC - Defined if compiled as static libraries
# MAGNUM_TARGET_GLES - Defined if compiled for OpenGL ES
# MAGNUM_TARGET_GLES2 - Defined if compiled for OpenGL ES 2.0
# MAGNUM_TARGET_GLES3 - Defined if compiled for OpenGL ES 3.0
# MAGNUM_TARGET_DESKTOP_GLES - Defined if compiled with OpenGL ES
# MAGNUM_BUILD_DEPRECATED - Defined if compiled with deprecated APIs
# included
# MAGNUM_BUILD_STATIC - Defined if compiled as static libraries
# MAGNUM_TARGET_GLES - Defined if compiled for OpenGL ES
# MAGNUM_TARGET_GLES2 - Defined if compiled for OpenGL ES 2.0
# MAGNUM_TARGET_GLES3 - Defined if compiled for OpenGL ES 3.0
# MAGNUM_TARGET_DESKTOP_GLES - Defined if compiled with OpenGL ES
# emulation on desktop OpenGL
#
# Additionally these variables are defined for internal usage:
@ -76,7 +77,7 @@
# installation directory
# MAGNUM_PLUGINS_IMPORTER_INSTALL_DIR - Importer plugin installation
# directory
# MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR - Audio omporter plugin
# MAGNUM_PLUGINS_AUDIOIMPORTER_INSTALL_DIR - Audio omporter plugin
# installation directory
# MAGNUM_CMAKE_FIND_MODULE_INSTALL_DIR - Installation dir for CMake
# Find* modules
@ -123,6 +124,10 @@ find_path(MAGNUM_INCLUDE_DIR
# Configuration
file(READ ${MAGNUM_INCLUDE_DIR}/magnumConfigure.h _magnumConfigure)
string(FIND "${_magnumConfigure}" "#define MAGNUM_BUILD_DEPRECATED" _BUILD_DEPRECATED)
if(NOT _BUILD_DEPRECATED EQUAL -1)
set(MAGNUM_BUILD_DEPRECATED 1)
endif()
string(FIND "${_magnumConfigure}" "#define MAGNUM_BUILD_STATIC" _BUILD_STATIC)
if(NOT _BUILD_STATIC EQUAL -1)
set(MAGNUM_BUILD_STATIC 1)

8
src/AbstractShaderProgram.h

@ -309,12 +309,14 @@ class MAGNUM_EXPORT AbstractShaderProgram {
*/
static Int maxVertexAttributes();
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copydoc maxVertexAttributes()
* @deprecated Use @ref Magnum::AbstractShaderProgram::maxVertexAttributes() "maxVertexAttributes()"
* instead.
*/
static Int maxSupportedVertexAttributeCount() { return maxVertexAttributes(); }
#endif
#ifndef MAGNUM_TARGET_GLES
/**
@ -544,7 +546,7 @@ class MAGNUM_EXPORT AbstractShaderProgram {
*
* Binds attribute to location which is used later for binding vertex
* buffers.
* @deprecated 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
* @ref AbstractShaderProgram-attribute-location "class documentation"
* for more information.
@ -562,7 +564,7 @@ class MAGNUM_EXPORT AbstractShaderProgram {
* Binds fragment data to location which is used later for framebuffer
* operations. See also Framebuffer::BlendFunction for more
* information about using color input index.
* @deprecated 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
* @ref AbstractShaderProgram-attribute-location "class documentation"
* for more information.
@ -604,7 +606,7 @@ class MAGNUM_EXPORT AbstractShaderProgram {
* @brief Get uniform location
* @param name Uniform name
*
* @deprecated 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
* @ref AbstractShaderProgram-uniform-location "class documentation"
* for more information.

3
src/AbstractTexture.cpp

@ -234,6 +234,9 @@ void AbstractTexture::bindInternal() {
}
void AbstractTexture::initializeContextBasedFunctionality(Context& context) {
/* Resize bindings array to hold all possible layers */
context.state().texture->bindings.resize(maxLayers());
#ifndef MAGNUM_TARGET_GLES
if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
Debug() << "AbstractTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features";

2
src/AbstractTexture.h

@ -115,12 +115,14 @@ class MAGNUM_EXPORT AbstractTexture {
*/
static Int maxLayers();
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief maxLayers()
* @deprecated Use @ref Magnum::AbstractTexture::maxLayers() "maxLayers()"
* instead.
*/
static Int maxSupportedLayerCount() { return maxLayers(); }
#endif
#ifndef MAGNUM_TARGET_GLES
/**

5
src/Audio/Audio.cpp

@ -31,7 +31,12 @@ namespace Magnum { namespace Audio {
/* Verify types */
static_assert(std::is_same<ALubyte, UnsignedByte>::value, "ALubyte is not the same as UnsignedByte");
/** @todo Why `ALbyte` is defined as `char` and not `signed char` on OSX? */
#ifndef __APPLE__
static_assert(std::is_same<ALbyte, Byte>::value, "ALbyte is not the same as Byte");
#else
static_assert(std::is_signed<ALbyte>::value && sizeof(ALbyte) == 1, "ALbyte does not have the same characteristics as Byte");
#endif
static_assert(std::is_same<ALushort, UnsignedShort>::value, "ALushort is not the same as UnsignedShort");
static_assert(std::is_same<ALshort, Short>::value, "ALshort is not the same as Short");
static_assert(std::is_same<ALuint, UnsignedInt>::value, "ALuint is not the same as UnsignedInt");

5
src/Audio/CMakeLists.txt

@ -47,7 +47,10 @@ set(MagnumAudio_HEADERS
add_library(MagnumAudio ${SHARED_OR_STATIC} ${MagnumAudio_SOURCES})
target_link_libraries(MagnumAudio ${CORRADE_PLUGINMANAGER_LIBRARIES} ${OPENAL_LIBRARY})
install(TARGETS MagnumAudio DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumAudio
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(FILES ${MagnumAudio_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Audio)
if(BUILD_TESTS)

64
src/Buffer.h

@ -319,7 +319,7 @@ class MAGNUM_EXPORT Buffer {
/**
* @brief Memory mapping access
*
* @deprecated Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* @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 map(MapAccess), mapSub()
* @requires_es_extension %Extension @es_extension{OES,mapbuffer} or
@ -642,8 +642,7 @@ class MAGNUM_EXPORT Buffer {
/**
* @brief Set buffer data
* @param size Data size
* @param data Pointer to data
* @param data Data
* @param usage %Buffer usage
* @return Reference to self (for method chaining)
*
@ -653,28 +652,20 @@ class MAGNUM_EXPORT Buffer {
* @see setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferData} or
* @fn_gl_extension{NamedBufferData,EXT,direct_state_access}
*/
Buffer& setData(GLsizeiptr size, const GLvoid* data, Usage usage) {
(this->*dataImplementation)(size, data, usage);
Buffer& setData(Containers::ArrayReference<const void> data, Usage usage) {
(this->*dataImplementation)(data.size(), data, usage);
return *this;
}
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Set buffer data
* @param data Fixed-size array with data
* @param usage %Buffer usage
* @return Reference to self (for method chaining)
*
* @see setData(GLsizeiptr, const GLvoid*, Usage).
* @deprecated Use @ref Magnum::Buffer::setData(Containers::ArrayReference<const void>, Usage) "setData(Containers::ArrayReference<const void>, Usage)"
* instead.
*/
#ifdef CORRADE_GCC46_COMPATIBILITY
#define size size_ /* With GCC 4.6 it conflicts with size(). WTF. */
#endif
template<std::size_t size, class T> Buffer& setData(const T(&data)[size], Usage usage) {
setData(size*sizeof(T), data, usage);
return *this;
Buffer& setData(GLsizeiptr size, const GLvoid* data, Usage usage) {
return setData({data, std::size_t(size)}, usage);
}
#ifdef CORRADE_GCC46_COMPATIBILITY
#undef size
#endif
/**
@ -686,21 +677,20 @@ class MAGNUM_EXPORT Buffer {
* @see setData(GLsizeiptr, const GLvoid*, Usage)
*/
template<class T> Buffer& setData(const std::vector<T>& data, Usage usage) {
setData(data.size()*sizeof(T), data.data(), usage);
setData({data.data(), data.size()}, usage);
return *this;
}
/** @overload */
template<std::size_t size, class T> Buffer& setData(const std::array<T, size>& data, Usage usage) {
setData(data.size()*sizeof(T), data.data(), usage);
setData({data.data(), data.size()}, usage);
return *this;
}
/**
* @brief Set buffer subdata
* @param offset Offset in the buffer
* @param size Data size
* @param data Pointer to data
* @param data Data
* @return Reference to self (for method chaining)
*
* If @extension{EXT,direct_state_access} is not available and the
@ -709,28 +699,20 @@ class MAGNUM_EXPORT Buffer {
* @see setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferSubData}
* or @fn_gl_extension{NamedBufferSubData,EXT,direct_state_access}
*/
Buffer& setSubData(GLintptr offset, GLsizeiptr size, const GLvoid* data) {
(this->*subDataImplementation)(offset, size, data);
Buffer& setSubData(GLintptr offset, Containers::ArrayReference<const void> data) {
(this->*subDataImplementation)(offset, data.size(), data);
return *this;
}
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @brief Set buffer subdata
* @param offset Offset in the buffer
* @param data Fixed-size array with data
* @return Reference to self (for method chaining)
*
* @see setSubData(GLintptr, GLsizeiptr, const GLvoid*)
* @deprecated Use @ref Magnum::Buffer::setSubData(GLintptr, Containers::ArrayReference<const void>) "setSubData(GLintptr, Containers::ArrayReference<const void>)"
* instead.
*/
#ifdef CORRADE_GCC46_COMPATIBILITY
#define size size_ /* With GCC 4.6 it conflicts with size(). WTF. */
#endif
template<std::size_t size, class T> Buffer& setSubData(GLintptr offset, const T(&data)[size]) {
setSubData(offset, size*sizeof(T), data);
return *this;
Buffer& setSubData(GLintptr offset, GLsizeiptr size, const GLvoid* data) {
return setSubData(offset, {data, std::size_t(size)});
}
#ifdef CORRADE_GCC46_COMPATIBILITY
#undef size
#endif
/**
@ -742,13 +724,13 @@ class MAGNUM_EXPORT Buffer {
* @see setSubData(GLintptr, GLsizeiptr, const GLvoid*)
*/
template<class T> Buffer& setSubData(GLintptr offset, const std::vector<T>& data) {
setSubData(offset, data.size()*sizeof(T), data.data());
setSubData(offset, {data.data(), data.size()});
return *this;
}
/** @overload */
template<std::size_t size, class T> Buffer& setSubData(GLintptr offset, const std::array<T, size>& data) {
setSubData(offset, data.size()*sizeof(T), data.data());
setSubData(offset, {data.data(), data.size()});
return *this;
}
@ -791,7 +773,7 @@ class MAGNUM_EXPORT Buffer {
* If @extension{EXT,direct_state_access} is not available and the
* buffer is not already bound somewhere, it is bound to hinted target
* before the operation.
* @deprecated Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* @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(),
* @fn_gl{BindBuffer} and @fn_gl{MapBuffer} or
@ -815,7 +797,7 @@ class MAGNUM_EXPORT Buffer {
*
* If the buffer is not already bound somewhere, it is bound to hinted
* target before the operation.
* @deprecated Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* @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 unmapSub(), setTargetHint(), @fn_gl_extension{MapBufferSubData,CHROMIUM,map_sub}
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use

2
src/BufferImage.cpp

@ -31,7 +31,7 @@ template<UnsignedInt dimensions> void BufferImage<dimensions>::setData(const typ
_format = format;
_type = type;
_size = size;
_buffer.setData(pixelSize()*size.product(), data, usage);
_buffer.setData({data, pixelSize()*size.product()}, usage);
}
#ifndef DOXYGEN_GENERATING_OUTPUT

19
src/CMakeLists.txt

@ -122,7 +122,6 @@ set(Magnum_HEADERS
Extensions.h
Framebuffer.h
Image.h
ImageFormat.h
ImageReference.h
Magnum.h
Mesh.h
@ -136,7 +135,6 @@ set(Magnum_HEADERS
ResourceManager.h
Sampler.h
Shader.h
Swizzle.h
Texture.h
TextureFormat.h
Timeline.h
@ -144,6 +142,13 @@ set(Magnum_HEADERS
magnumVisibility.h)
# Deprecated headers
if(BUILD_DEPRECATED)
set(Magnum_HEADERS ${Magnum_HEADERS}
ImageFormat.h
Swizzle.h)
endif()
# Desktop-only headers and libraries
if(NOT TARGET_GLES)
set(Magnum_HEADERS ${Magnum_HEADERS}
@ -191,7 +196,10 @@ else()
endif()
target_link_libraries(Magnum ${Magnum_LIBS})
install(TARGETS Magnum DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS Magnum
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(FILES ${Magnum_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/magnumConfigure.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR})
@ -251,7 +259,10 @@ if(BUILD_TESTS)
# On Windows we need to install first and then run the tests to avoid "DLL
# not found" hell, thus we need to install this too
if(WIN32 AND NOT CMAKE_CROSSCOMPILING)
install(TARGETS MagnumMathTestLib MagnumTestLib DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumMathTestLib MagnumTestLib
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
endif()
add_subdirectory(Test)

40
src/Color.h

@ -202,13 +202,6 @@ template<class T> class BasicColor3: public Math::Vector3<T> {
/** @brief Copy constructor */
constexpr BasicColor3(const Math::Vector<3, T>& other): Math::Vector3<T>(other) {}
T& r() { return Math::Vector3<T>::x(); } /**< @brief R component */
constexpr T r() const { return Math::Vector3<T>::x(); } /**< @overload */
T& g() { return Math::Vector3<T>::y(); } /**< @brief G component */
constexpr T g() const { return Math::Vector3<T>::y(); } /**< @overload */
T& b() { return Math::Vector3<T>::z(); } /**< @brief B component */
constexpr T b() const { return Math::Vector3<T>::z(); } /**< @overload */
/**
* @brief Convert to HSV
*
@ -336,42 +329,24 @@ class BasicColor4: public Math::Vector4<T> {
/** @brief Copy constructor */
constexpr BasicColor4(const Math::Vector<4, T>& other): Math::Vector4<T>(other) {}
T& r() { return Math::Vector4<T>::x(); } /**< @brief R component */
constexpr T r() const { return Math::Vector4<T>::x(); } /**< @overload */
T& g() { return Math::Vector4<T>::y(); } /**< @brief G component */
constexpr T g() const { return Math::Vector4<T>::y(); } /**< @overload */
T& b() { return Math::Vector4<T>::z(); } /**< @brief B component */
constexpr T b() const { return Math::Vector4<T>::z(); } /**< @overload */
T& a() { return Math::Vector4<T>::w(); } /**< @brief A component */
constexpr T a() const { return Math::Vector4<T>::w(); } /**< @overload */
/**
* @brief RGB part of the vector
* @return First three components of the vector
*
* @see swizzle()
*/
BasicColor3<T>& rgb() { return BasicColor3<T>::from(Math::Vector4<T>::data()); }
constexpr BasicColor3<T> rgb() const { return BasicColor3<T>::from(Math::Vector4<T>::data()); } /**< @overload */
/** @copydoc BasicColor3::toHSV() */
constexpr HSV toHSV() const {
return Implementation::toHSV<T>(rgb());
return Implementation::toHSV<T>(Math::Vector4<T>::rgb());
}
/** @copydoc BasicColor3::hue() */
constexpr Math::Deg<FloatingPointType> hue() const {
return Implementation::hue<T>(rgb());
return Implementation::hue<T>(Math::Vector4<T>::rgb());
}
/** @copydoc BasicColor3::saturation() */
constexpr FloatingPointType saturation() const {
return Implementation::saturation<T>(rgb());
return Implementation::saturation<T>(Math::Vector4<T>::rgb());
}
/** @copydoc BasicColor3::value() */
constexpr FloatingPointType value() const {
return Implementation::value<T>(rgb());
return Implementation::value<T>(Math::Vector4<T>::rgb());
}
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(4, BasicColor4)
@ -392,6 +367,13 @@ template<class T> inline Debug operator<<(Debug debug, const BasicColor4<T>& val
return debug << static_cast<const Math::Vector4<T>&>(value);
}
namespace Math { namespace Implementation {
template<class T> struct TypeForSize<3, BasicColor3<T>> { typedef BasicColor3<T> Type; };
template<class T> struct TypeForSize<3, BasicColor4<T>> { typedef BasicColor3<T> Type; };
template<class T> struct TypeForSize<4, BasicColor3<T>> { typedef BasicColor4<T> Type; };
template<class T> struct TypeForSize<4, BasicColor4<T>> { typedef BasicColor4<T> Type; };
}}
}
namespace Corrade { namespace Utility {

4
src/ColorFormat.h

@ -74,7 +74,7 @@ enum class ColorFormat: GLenum {
/**
* Floating-point luminance channel. The value is used for all RGB
* channels.
* @deprecated Included for compatibility reasons only, use
* @deprecated_gl Included for compatibility reasons only, use
* @ref Magnum::ColorFormat "ColorFormat::Red" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::ColorFormat "ColorFormat::Red" instead.
@ -98,7 +98,7 @@ enum class ColorFormat: GLenum {
/**
* Floating-point luminance and alpha channel. First value is used for all
* RGB channels, second value is used for alpha channel.
* @deprecated Included for compatibility reasons only, use
* @deprecated_gl Included for compatibility reasons only, use
* @ref Magnum::ColorFormat "ColorFormat::RG" instead.
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::ColorFormat "ColorFormat::RG" instead.

5
src/DebugTools/CMakeLists.txt

@ -62,7 +62,10 @@ target_link_libraries(MagnumDebugTools
MagnumShaders
MagnumShapes)
install(TARGETS MagnumDebugTools DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumDebugTools
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(FILES ${MagnumDebugTools_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/DebugTools)
if(BUILD_TESTS)

8
src/DebugTools/Test/CapsuleRendererTest.cpp

@ -55,9 +55,9 @@ void CapsuleRendererTest::zeroLength2D() {
const Vector2 a(0.5f, 3.0f);
std::array<Matrix3, 3> transformation = Implementation::capsuleRendererTransformation<2>(a, a, 3.5f);
const auto scaling = Math::Matrix<2, Float>::fromDiagonal(Vector2(3.5f));
const auto scaling = Matrix2x2::fromDiagonal(Vector2(3.5f));
CORRADE_COMPARE(transformation[0].rotationScaling(), scaling);
CORRADE_COMPARE(transformation[1].rotationScaling(), (Math::Matrix<2, Float>::fromDiagonal({3.5f, 0.0f})));
CORRADE_COMPARE(transformation[1].rotationScaling(), Matrix2x2::fromDiagonal({3.5f, 0.0f}));
CORRADE_COMPARE(transformation[2].rotationScaling(), scaling);
CORRADE_COMPARE(transformation[0].translation(), a);
@ -94,9 +94,9 @@ void CapsuleRendererTest::zeroLength3D() {
const Vector3 a(0.5f, 3.0f, 7.0f);
std::array<Matrix4, 3> transformation = Implementation::capsuleRendererTransformation<3>(a, a, 3.5f);
const auto scaling = Math::Matrix<3, Float>::fromDiagonal(Vector3(3.5f));
const auto scaling = Matrix3x3::fromDiagonal(Vector3(3.5f));
CORRADE_COMPARE(transformation[0].rotationScaling(), scaling);
CORRADE_COMPARE(transformation[1].rotationScaling(), (Math::Matrix<3, Float>::fromDiagonal({3.5f, 0.0f, 3.5f})));
CORRADE_COMPARE(transformation[1].rotationScaling(), Matrix3x3::fromDiagonal({3.5f, 0.0f, 3.5f}));
CORRADE_COMPARE(transformation[2].rotationScaling(), scaling);
CORRADE_COMPARE(transformation[0].translation(), a);

4
src/DebugTools/Test/CylinderRendererTest.cpp

@ -55,7 +55,7 @@ void CylinderRendererTest::zeroLength2D() {
const Vector2 a(0.5f, 3.0f);
const Matrix3 transformation = Implementation::cylinderRendererTransformation<2>(a, a, 3.5f);
CORRADE_COMPARE(transformation.rotationScaling(), (Math::Matrix<2, Float>::fromDiagonal({3.5f, 0.0f})));
CORRADE_COMPARE(transformation.rotationScaling(), Matrix2x2::fromDiagonal({3.5f, 0.0f}));
CORRADE_COMPARE(transformation.translation(), a);
}
@ -76,7 +76,7 @@ void CylinderRendererTest::zeroLength3D() {
const Vector3 a(0.5f, 3.0f, 7.0f);
const Matrix4 transformation = Implementation::cylinderRendererTransformation<3>(a, a, 3.5f);
CORRADE_COMPARE(transformation.rotationScaling(), (Math::Matrix<3, Float>::fromDiagonal({3.5f, 0.0f, 3.5f})));
CORRADE_COMPARE(transformation.rotationScaling(), Matrix3x3::fromDiagonal({3.5f, 0.0f, 3.5f}));
CORRADE_COMPARE(transformation.translation(), a);
}

5
src/Extensions.h

@ -42,8 +42,9 @@ and string(), but these structs are better suited for compile-time decisions
rather than %Extension instances. See Context::isExtensionSupported() for
example usage.
This namespace is built by default and found by default in CMake. See
@ref building and @ref cmake for more information.
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
@ref cmake for more information.
@see MAGNUM_ASSERT_EXTENSION_SUPPORTED()
@todo Manual indices for extensions, this has gaps
*/

8
src/ImageFormat.h

@ -31,20 +31,24 @@
#include "ColorFormat.h"
#ifdef MAGNUM_BUILD_DEPRECATED
namespace Magnum {
/**
@copybrief ColorFormat
@deprecated Use @ref ColorFormat instead.
@deprecated Use @ref Magnum::ColorFormat "ColorFormat" instead.
*/
typedef ColorFormat ImageFormat;
/**
@copybrief ColorType
@deprecated Use @ref ColorType instead.
@deprecated Use @ref Magnum::ColorType "ColorType" instead.
*/
typedef ColorType ImageType;
}
#else
#error
#endif
#endif

172
src/Magnum.h

@ -65,11 +65,22 @@ using Corrade::Utility::Warning;
using Corrade::Utility::Error;
#ifdef DOXYGEN_GENERATING_OUTPUT
/**
@brief Build with deprecated API included
Defined if the library contains deprecated API (which will be removed in the
future). To preserve backward compatibility, %Magnum is by default built with
deprecated API included.
@see @ref building
*/
#define MAGNUM_BUILD_DEPRECATED
/* (enabled by default) */
/**
@brief Static library build
Defined if built as static libraries. Default are shared libraries.
@see @ref building-corrade
@see @ref building
*/
#define MAGNUM_BUILD_STATIC
#undef MAGNUM_BUILD_STATIC
@ -174,32 +185,100 @@ typedef Math::Vector3<Int> Vector3i;
/** @brief Four-component signed integer vector */
typedef Math::Vector4<Int> Vector4i;
/** @brief 2x2 float matrix */
typedef Math::Matrix<2, Float> Matrix2;
/**
@brief 3x3 float transformation matrix
/** @brief 3x3 float matrix */
@see @ref Matrix3x3
*/
typedef Math::Matrix3<Float> Matrix3;
/** @brief 4x4 float matrix */
/**
@brief 4x4 float transformation matrix
@see @ref Matrix4x4
*/
typedef Math::Matrix4<Float> Matrix4;
/** @brief 2x2 float matrix */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix2x2<Float> Matrix2x2;
#else
typedef Math::Matrix<2, Float> Matrix2x2;
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
/**
@copybrief Matrix2x2
@deprecated Use @ref Magnum::Matrix2x2 "Matrix2x2" instead.
*/
typedef Math::Matrix<2, Float> Matrix2;
#endif
/**
@brief 3x3 float matrix
Note that this is different from @ref Matrix3, which contains additional
functions for transformations in 2D.
*/
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix3x3<Float> Matrix3x3;
#else
typedef Math::Matrix<3, Float> Matrix3x3;
#endif
/**
@brief 4x4 float matrix
Note that this is different from @ref Matrix4, which contains additional
functions for transformations in 3D.
*/
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix4x4<Float> Matrix4x4;
#else
typedef Math::Matrix<4, Float> Matrix4x4;
#endif
/** @brief Float matrix with 2 columns and 3 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix2x3<Float> Matrix2x3;
#else
typedef Math::RectangularMatrix<2, 3, Float> Matrix2x3;
#endif
/** @brief Float matrix with 3 columns and 2 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix3x2<Float> Matrix3x2;
#else
typedef Math::RectangularMatrix<3, 2, Float> Matrix3x2;
#endif
/** @brief Float matrix with 2 columns and 4 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix2x4<Float> Matrix2x4;
#else
typedef Math::RectangularMatrix<2, 4, Float> Matrix2x4;
#endif
/** @brief Float matrix with 4 columns and 2 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix4x2<Float> Matrix4x2;
#else
typedef Math::RectangularMatrix<4, 2, Float> Matrix4x2;
#endif
/** @brief Float matrix with 3 columns and 4 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix3x4<Float> Matrix3x4;
#else
typedef Math::RectangularMatrix<3, 4, Float> Matrix3x4;
#endif
/** @brief Float matrix with 4 columns and 3 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix4x3<Float> Matrix4x3;
#else
typedef Math::RectangularMatrix<4, 3, Float> Matrix4x3;
#endif
/** @brief Float complex number */
typedef Math::Complex<Float> Complex;
@ -249,32 +328,100 @@ typedef Math::Vector3<Double> Vector3d;
/** @brief Four-component double vector */
typedef Math::Vector4<Double> Vector4d;
/** @brief 2x2 double matrix */
typedef Math::Matrix<2, Double> Matrix2d;
/**
@brief 3x3 double transformation matrix
/** @brief 3x3 double matrix */
@see @ref Matrix3x3d
*/
typedef Math::Matrix3<Double> Matrix3d;
/** @brief 4x4 double matrix */
/**
@brief 4x4 double transformation matrix
@see @ref Matrix4x4d
*/
typedef Math::Matrix4<Double> Matrix4d;
/** @brief 2x2 double matrix */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix2x2<Double> Matrix2x2d;
#else
typedef Math::Matrix<2, Double> Matrix2x2d;
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
/**
@copybrief Matrix2x2d
@deprecated Use @ref Magnum::Matrix2x2d "Matrix2x2d" instead.
*/
typedef Math::Matrix<2, Double> Matrix2d;
#endif
/**
@brief 3x3 double matrix
Note that this is different from @ref Matrix3d, which contains additional
functions for transformations in 2D.
*/
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix3x3<Double> Matrix3x3d;
#else
typedef Math::Matrix<3, Double> Matrix3x3d;
#endif
/**
@brief 4x4 double matrix
Note that this is different from @ref Matrix4d, which contains additional
functions for transformations in 3D.
*/
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix4x4<Double> Matrix4x4d;
#else
typedef Math::Matrix<4, Double> Matrix4x4d;
#endif
/** @brief Double matrix with 2 columns and 3 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix2x3<Double> Matrix2x3d;
#else
typedef Math::RectangularMatrix<2, 3, Double> Matrix2x3d;
#endif
/** @brief Double matrix with 3 columns and 2 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix3x2<Double> Matrix3x2d;
#else
typedef Math::RectangularMatrix<3, 2, Double> Matrix3x2d;
#endif
/** @brief Double matrix with 2 columns and 4 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix2x4<Double> Matrix2x4d;
#else
typedef Math::RectangularMatrix<2, 4, Double> Matrix2x4d;
#endif
/** @brief Double matrix with 4 columns and 2 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix4x2<Double> Matrix4x2d;
#else
typedef Math::RectangularMatrix<4, 2, Double> Matrix4x2d;
#endif
/** @brief Double matrix with 3 columns and 4 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix3x4<Double> Matrix3x4d;
#else
typedef Math::RectangularMatrix<3, 4, Double> Matrix3x4d;
#endif
/** @brief Double matrix with 4 columns and 3 rows */
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef Math::Matrix4x3<Double> Matrix4x3d;
#else
typedef Math::RectangularMatrix<4, 3, Double> Matrix4x3d;
#endif
/** @brief Double complex number */
typedef Math::Complex<Double> Complexd;
@ -423,11 +570,4 @@ class Timeline;
}
namespace std {
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class> struct hash;
#endif
template<> struct hash<Magnum::ResourceKey>;
}
#endif

36
src/Math/Algorithms/Test/GaussJordanTest.cpp

@ -36,7 +36,7 @@ class GaussJordanTest: public Corrade::TestSuite::Tester {
void invert();
};
typedef RectangularMatrix<4, 4, Float> Matrix4;
typedef RectangularMatrix<4, 4, Float> Matrix4x4;
typedef Vector<4, Float> Vector4;
GaussJordanTest::GaussJordanTest() {
@ -45,32 +45,32 @@ GaussJordanTest::GaussJordanTest() {
}
void GaussJordanTest::singular() {
Matrix4 a(Vector4(1.0f, 2.0f, 3.0f, 4.0f),
Vector4(2.0f, 3.0f, -7.0f, 11.0f),
Vector4(2.0f, 4.0f, 6.0f, 8.0f),
Vector4(1.0f, 2.0f, 7.0f, 40.0f));
Matrix4x4 a(Vector4(1.0f, 2.0f, 3.0f, 4.0f),
Vector4(2.0f, 3.0f, -7.0f, 11.0f),
Vector4(2.0f, 4.0f, 6.0f, 8.0f),
Vector4(1.0f, 2.0f, 7.0f, 40.0f));
RectangularMatrix<4, 1, Float> t;
CORRADE_VERIFY(!gaussJordanInPlaceTransposed(a, t));
}
void GaussJordanTest::invert() {
Matrix4 a(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.0f),
Vector4(7.0f, -1.0f, 8.0f, 0.0f),
Vector4(9.0f, 4.0f, 5.0f, 9.0f));
Matrix4 expectedInverse(Vector4(-60/103.0f, 71/103.0f, -4/103.0f, 3/103.0f),
Vector4(-66/103.0f, 109/103.0f, -25/103.0f, -7/103.0f),
Vector4(177/412.0f, -97/206.0f, 53/412.0f, -7/206.0f),
Vector4(259/412.0f, -185/206.0f, 31/412.0f, 27/206.0f));
Matrix4 a2(a);
Matrix4 inverse = Matrix4::fromDiagonal(Vector4(1.0f));
Matrix4x4 a(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.0f),
Vector4(7.0f, -1.0f, 8.0f, 0.0f),
Vector4(9.0f, 4.0f, 5.0f, 9.0f));
Matrix4x4 expectedInverse(Vector4(-60/103.0f, 71/103.0f, -4/103.0f, 3/103.0f),
Vector4(-66/103.0f, 109/103.0f, -25/103.0f, -7/103.0f),
Vector4(177/412.0f, -97/206.0f, 53/412.0f, -7/206.0f),
Vector4(259/412.0f, -185/206.0f, 31/412.0f, 27/206.0f));
Matrix4x4 a2(a);
Matrix4x4 inverse = Matrix4x4::fromDiagonal(Vector4(1.0f));
CORRADE_VERIFY(gaussJordanInPlace(a2, inverse));
CORRADE_COMPARE(inverse, expectedInverse);
CORRADE_COMPARE(a*inverse, Matrix4::fromDiagonal(Vector4(1.0f)));
CORRADE_COMPARE(a*inverse, Matrix4x4::fromDiagonal(Vector4(1.0f)));
}
}}}}

30
src/Math/Algorithms/Test/GramSchmidtTest.cpp

@ -36,7 +36,7 @@ class GramSchmidtTest: public Corrade::TestSuite::Tester {
void orthonormalize();
};
typedef RectangularMatrix<3, 3, Float> Matrix3;
typedef RectangularMatrix<3, 3, Float> Matrix3x3;
typedef Vector<3, Float> Vector3;
GramSchmidtTest::GramSchmidtTest() {
@ -45,11 +45,11 @@ GramSchmidtTest::GramSchmidtTest() {
}
void GramSchmidtTest::orthogonalize() {
Matrix3 m(Vector3(3.0f, 5.0f, 1.0f),
Vector3(4.0f, 4.0f, 7.0f),
Vector3(7.0f, -1.0f, -3.0f));
Matrix3x3 m(Vector3(3.0f, 5.0f, 1.0f),
Vector3(4.0f, 4.0f, 7.0f),
Vector3(7.0f, -1.0f, -3.0f));
Matrix3 orthogonalized = Algorithms::gramSchmidtOrthogonalize(m);
Matrix3x3 orthogonalized = Algorithms::gramSchmidtOrthogonalize(m);
/* Verify the first vector is in direction of first original */
CORRADE_COMPARE(orthogonalized[0], m[0]);
@ -62,18 +62,18 @@ void GramSchmidtTest::orthogonalize() {
CORRADE_COMPARE(Vector3::dot(orthogonalized[1], orthogonalized[2]), 0.0f);
/* Just to be sure */
Matrix3 expected(Vector3( 3.0f, 5.0f, 1.0f),
Vector3(0.657143f, -1.571429f, 5.885714f),
Vector3(6.086759f, -3.3379f, -1.570777f));
Matrix3x3 expected(Vector3( 3.0f, 5.0f, 1.0f),
Vector3(0.657143f, -1.571429f, 5.885714f),
Vector3(6.086759f, -3.3379f, -1.570777f));
CORRADE_COMPARE(orthogonalized, expected);
}
void GramSchmidtTest::orthonormalize() {
Matrix3 m(Vector3(3.0f, 5.0f, 8.0f),
Vector3(4.0f, 4.0f, 7.0f),
Vector3(7.0f, -1.0f, 8.0f));
Matrix3x3 m(Vector3(3.0f, 5.0f, 8.0f),
Vector3(4.0f, 4.0f, 7.0f),
Vector3(7.0f, -1.0f, 8.0f));
Matrix3 orthonormalized = Algorithms::gramSchmidtOrthonormalize(m);
Matrix3x3 orthonormalized = Algorithms::gramSchmidtOrthonormalize(m);
/* Verify the first vector is in direction of first original */
CORRADE_COMPARE(orthonormalized[0], m[0].normalized());
@ -89,9 +89,9 @@ void GramSchmidtTest::orthonormalize() {
CORRADE_COMPARE(Vector3::dot(orthonormalized[1], orthonormalized[2]), 0.0f);
/* Just to be sure */
Matrix3 expected(Vector3( 0.303046f, 0.505076f, 0.808122f),
Vector3( 0.928316f, -0.348119f, -0.130544f),
Vector3(-0.215388f, -0.789754f, 0.574367f));
Matrix3x3 expected(Vector3( 0.303046f, 0.505076f, 0.808122f),
Vector3( 0.928316f, -0.348119f, -0.130544f),
Vector3(-0.215388f, -0.789754f, 0.574367f));
CORRADE_COMPARE(orthonormalized, expected);
}

16
src/Math/Math.h

@ -30,6 +30,8 @@
#include <cstddef>
#include "corradeConfigure.h"
namespace Magnum { namespace Math {
/** @todo Denormals to zero */
@ -42,12 +44,26 @@ template<class> class DualComplex;
template<class> class DualQuaternion;
template<std::size_t, class> class Matrix;
#ifndef CORRADE_GCC46_COMPATIBILITY
template<class T> using Matrix2x2 = Matrix<2, T>;
template<class T> using Matrix3x3 = Matrix<3, T>;
template<class T> using Matrix4x4 = Matrix<4, T>;
#endif
template<class> class Matrix3;
template<class> class Matrix4;
template<class> class Quaternion;
template<std::size_t, std::size_t, class> class RectangularMatrix;
#ifndef CORRADE_GCC46_COMPATIBILITY
template<class T> using Matrix2x3 = RectangularMatrix<2, 3, T>;
template<class T> using Matrix3x2 = RectangularMatrix<3, 2, T>;
template<class T> using Matrix2x4 = RectangularMatrix<2, 4, T>;
template<class T> using Matrix4x2 = RectangularMatrix<4, 2, T>;
template<class T> using Matrix3x4 = RectangularMatrix<3, 4, T>;
template<class T> using Matrix4x3 = RectangularMatrix<4, 3, T>;
#endif
template<template<class> class, class> class Unit;
template<class> class Deg;

40
src/Math/Matrix.h

@ -44,7 +44,7 @@ namespace Implementation {
See @ref matrix-vector for brief introduction.
@configurationvalueref{Magnum::Math::Matrix}
@see Magnum::Matrix2, Magnum::Matrix2d
@see @ref Matrix2x2, @ref Matrix3x3, @ref Matrix4x4
*/
template<std::size_t size, class T> class Matrix: public RectangularMatrix<size, size, T> {
public:
@ -89,9 +89,9 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
* Performs only default casting on the values, no rounding or
* anything else. Example usage:
* @code
* Matrix<2, Float> floatingPoint({1.3f, 2.7f},
* Matrix2x2<Float> floatingPoint({1.3f, 2.7f},
* {-15.0f, 7.0f});
* Matrix<2, Byte> integral(floatingPoint);
* Matrix2x2<Byte> integral(floatingPoint);
* // integral == {{1, 2}, {-15, 7}}
* @endcode
*/
@ -184,6 +184,40 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
#endif
};
#ifndef CORRADE_GCC46_COMPATIBILITY
/**
@brief 2x2 matrix
Convenience alternative to <tt>%Matrix<2, T></tt>. See @ref Matrix for more
information.
@note Not available on GCC < 4.7. Use <tt>%Matrix<2, T></tt> instead.
@see @ref Magnum::Matrix2x2, @ref Magnum::Matrix2x2d
*/
template<class T> using Matrix2x2 = Matrix<2, T>;
/**
@brief 3x3 matrix
Convenience alternative to <tt>%Matrix<3, T></tt>. See @ref Matrix for more
information. Note that this is different from @ref Matrix3, which contains
additional functions for transformations in 2D.
@note Not available on GCC < 4.7. Use <tt>%Matrix<3, T></tt> instead.
@see @ref Magnum::Matrix3x3, @ref Magnum::Matrix3x3d
*/
template<class T> using Matrix3x3 = Matrix<3, T>;
/**
@brief 4x4 matrix
Convenience alternative to <tt>%Matrix<4, T></tt>. See @ref Matrix for more
information. Note that this is different from @ref Matrix4, which contains
additional functions for transformations in 3D.
@note Not available on GCC < 4.7. Use <tt>%Matrix<3, T></tt> instead.
@see @ref Magnum::Matrix4x4, @ref Magnum::Matrix4x4d
*/
template<class T> using Matrix4x4 = Matrix<4, T>;
#endif
MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(Matrix<size, T>)
/** @debugoperator{Magnum::Math::Matrix} */

73
src/Math/RectangularMatrix.h

@ -48,9 +48,8 @@ Vector.
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
of @f$ \boldsymbol A_{ij} @f$).
@see Magnum::Matrix2x3, Magnum::Matrix3x2, Magnum::Matrix2x4, Magnum::Matrix4x2,
Magnum::Matrix3x4, Magnum::Matrix4x3, Magnum::Matrix2x3d, Magnum::Matrix3x2d,
Magnum::Matrix2x4d, Magnum::Matrix4x2d, Magnum::Matrix3x4d, Magnum::Matrix4x3d
@see @ref Matrix2x3, @ref Matrix3x2, @ref Matrix2x4, @ref Matrix4x2,
@ref Matrix3x4, @ref Matrix4x3
*/
template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
static_assert(cols != 0 && rows != 0, "RectangularMatrix cannot have zero elements");
@ -396,6 +395,74 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
Vector<rows, T> _data[cols];
};
#ifndef CORRADE_GCC46_COMPATIBILITY
/**
@brief Matrix with 2 columns and 3 rows
Convenience alternative to <tt>%RectangularMatrix<2, 3, T></tt>. See
@ref RectangularMatrix for more information.
@note Not available on GCC < 4.7. Use <tt>%RectangularMatrix<2, 3, T></tt>
instead.
@see @ref Magnum::Matrix2x3, @ref Magnum::Matrix2x3d
*/
template<class T> using Matrix2x3 = RectangularMatrix<2, 3, T>;
/**
@brief Matrix with 3 columns and 2 rows
Convenience alternative to <tt>%RectangularMatrix<3, 2, T></tt>. See
@ref RectangularMatrix for more information.
@note Not available on GCC < 4.7. Use <tt>%RectangularMatrix<3, 2, T></tt>
instead.
@see @ref Magnum::Matrix3x2, @ref Magnum::Matrix3x2d
*/
template<class T> using Matrix3x2 = RectangularMatrix<3, 2, T>;
/**
@brief Matrix with 2 columns and 4 rows
Convenience alternative to <tt>%RectangularMatrix<2, 4, T></tt>. See
@ref RectangularMatrix for more information.
@note Not available on GCC < 4.7. Use <tt>%RectangularMatrix<2, 4, T></tt>
instead.
@see @ref Magnum::Matrix2x4, @ref Magnum::Matrix2x4d
*/
template<class T> using Matrix2x4 = RectangularMatrix<2, 4, T>;
/**
@brief Matrix with 4 columns and 2 rows
Convenience alternative to <tt>%RectangularMatrix<4, 2, T></tt>. See
@ref RectangularMatrix for more information.
@note Not available on GCC < 4.7. Use <tt>%RectangularMatrix<4, 2, T></tt>
instead.
@see @ref Magnum::Matrix4x2, @ref Magnum::Matrix4x2d
*/
template<class T> using Matrix4x2 = RectangularMatrix<4, 2, T>;
/**
@brief Matrix with 3 columns and 4 rows
Convenience alternative to <tt>%RectangularMatrix<3, 4, T></tt>. See
@ref RectangularMatrix for more information.
@note Not available on GCC < 4.7. Use <tt>%RectangularMatrix<3, 4, T></tt>
instead.
@see @ref Magnum::Matrix3x4, @ref Magnum::Matrix3x4d
*/
template<class T> using Matrix3x4 = RectangularMatrix<3, 4, T>;
/**
@brief Matrix with 4 columns and 3 rows
Convenience alternative to <tt>%RectangularMatrix<4, 3, T></tt>. See
@ref RectangularMatrix for more information.
@note Not available on GCC < 4.7. Use <tt>%RectangularMatrix<4, 3, T></tt>
instead.
@see @ref Magnum::Matrix4x3, @ref Magnum::Matrix4x3d
*/
template<class T> using Matrix4x3 = RectangularMatrix<4, 3, T>;
#endif
/** @relates RectangularMatrix
@brief Multiply number with matrix

31
src/Math/Swizzle.h

@ -44,12 +44,20 @@ namespace Implementation {
template<std::size_t size> struct Component<size, 'y'>: public ComponentAtPosition<size, 1> {};
template<std::size_t size> struct Component<size, 'z'>: public ComponentAtPosition<size, 2> {};
template<std::size_t size> struct Component<size, 'w'>: public ComponentAtPosition<size, 3> {};
template<std::size_t size> struct Component<size, 'r'>: public ComponentAtPosition<size, 0> {};
template<std::size_t size> struct Component<size, 'g'>: public ComponentAtPosition<size, 1> {};
template<std::size_t size> struct Component<size, 'b'>: public ComponentAtPosition<size, 2> {};
template<std::size_t size> struct Component<size, 'a'>: public ComponentAtPosition<size, 3> {};
template<std::size_t size> struct Component<size, '0'> {
template<class T> constexpr static T value(const Math::Vector<size, T>&) { return T(0); }
};
template<std::size_t size> struct Component<size, '1'> {
template<class T> constexpr static T value(const Math::Vector<size, T>&) { return T(1); }
};
template<std::size_t size, class T> struct TypeForSize {
typedef Math::Vector<size, typename T::Type> Type;
};
}
/**
@ -57,23 +65,22 @@ namespace Implementation {
Creates new vector from given components. Example:
@code
Vector4<Int> original(-1, 2, 3, 4);
Vector4i original(-1, 2, 3, 4);
auto vec = swizzle<'w', '1', '0', 'x', 'y', 'z'>(original);
// vec == { 4, 1, 0, -1, 2, 3 }
@endcode
You can use letters `x`, `y`, `z`, `w` for addressing components or letters
`0` and `1` for zero and one. Count of elements is unlimited, but must be at
least one.
See also Magnum::swizzle() which has some added convenience features not
present in this lightweight implementation for Math namespace.
@see @ref matrix-vector-component-access, Vector4::xyz(),
Vector4::xy(), Vector3::xy()
You can use letters `x`, `y`, `z`, `w` and `r`, `g`, `b`, `a` for addressing
components or letters `0` and `1` for zero and one. Count of elements is
unlimited, but must be at least one. If the resulting vector is two, three or
four-component, corresponding @ref Math::Vector2, @ref Math::Vector3,
@ref Math::Vector4, @ref Color3 or @ref Color4 specialization is returned.
@see @ref matrix-vector-component-access, @ref Vector4::xyz(),
@ref Vector4::xy(), @ref Vector3::xy(), @ref Color4::rgb()
*/
template<char ...components, std::size_t size, class T> constexpr Vector<sizeof...(components), T> swizzle(const Vector<size, T>& vector) {
return {Implementation::Component<size, components>::value(vector)...};
template<char ...components, class T> constexpr typename Implementation::TypeForSize<sizeof...(components), T>::Type swizzle(const T& vector) {
return {Implementation::Component<T::Size, components>::value(vector)...};
}
}}

4
src/Math/Test/ComplexTest.cpp

@ -100,7 +100,7 @@ typedef Math::Rad<Float> Rad;
typedef Math::Complex<Float> Complex;
typedef Math::Vector2<Float> Vector2;
typedef Math::Matrix3<Float> Matrix3;
typedef Math::Matrix<2, Float> Matrix2;
typedef Math::Matrix<2, Float> Matrix2x2;
void ComplexTest::construct() {
constexpr Complex a(0.5f, -3.7f);
@ -280,7 +280,7 @@ void ComplexTest::rotation() {
void ComplexTest::matrix() {
Complex a = Complex::rotation(Deg(37.0f));
Matrix2 m = Matrix3::rotation(Deg(37.0f)).rotationScaling();
Matrix2x2 m = Matrix3::rotation(Deg(37.0f)).rotationScaling();
CORRADE_COMPARE(a.toMatrix(), m);

30
src/Math/Test/Matrix3Test.cpp

@ -90,7 +90,7 @@ class Matrix3Test: public Corrade::TestSuite::Tester {
typedef Math::Deg<Float> Deg;
typedef Math::Matrix3<Float> Matrix3;
typedef Math::Matrix3<Int> Matrix3i;
typedef Math::Matrix<2, Float> Matrix2;
typedef Math::Matrix<2, Float> Matrix2x2;
typedef Math::Vector3<Float> Vector3;
typedef Math::Vector2<Float> Vector2;
@ -274,8 +274,8 @@ void Matrix3Test::projection() {
}
void Matrix3Test::fromParts() {
constexpr Matrix2 rotationScaling(Vector2(3.0f, 5.0f),
Vector2(4.0f, 4.0f));
constexpr Matrix2x2 rotationScaling(Vector2(3.0f, 5.0f),
Vector2(4.0f, 4.0f));
constexpr Vector2 translation(7.0f, -1.0f);
constexpr Matrix3 a = Matrix3::from(rotationScaling, translation);
@ -288,10 +288,10 @@ void Matrix3Test::rotationScalingPart() {
constexpr Matrix3 a({3.0f, 5.0f, 8.0f},
{4.0f, 4.0f, 7.0f},
{7.0f, -1.0f, 8.0f});
constexpr Matrix2 b = a.rotationScaling();
constexpr Matrix2x2 b = a.rotationScaling();
CORRADE_COMPARE(b, Matrix2(Vector2(3.0f, 5.0f),
Vector2(4.0f, 4.0f)));
CORRADE_COMPARE(b, Matrix2x2(Vector2(3.0f, 5.0f),
Vector2(4.0f, 4.0f)));
}
void Matrix3Test::rotationNormalizedPart() {
@ -308,34 +308,34 @@ void Matrix3Test::rotationNormalizedPart() {
Matrix3 b({ 0.965926f, 0.258819f, 1.0f},
{-0.258819f, 0.965926f, 3.0f},
{ 0.0f, 0.0f, 1.0f});
CORRADE_COMPARE(b.rotationNormalized(), Matrix2(Vector2( 0.965926f, 0.258819f),
Vector2(-0.258819f, 0.965926f)));
CORRADE_COMPARE(b.rotationNormalized(), Matrix2x2(Vector2( 0.965926f, 0.258819f),
Vector2(-0.258819f, 0.965926f)));
}
void Matrix3Test::rotationPart() {
Matrix3 rotation = Matrix3::rotation(Deg(15.0f));
Matrix2 expectedRotationPart(Vector2( 0.965926f, 0.258819f),
Vector2(-0.258819f, 0.965926f));
Matrix2x2 expectedRotationPart(Vector2( 0.965926f, 0.258819f),
Vector2(-0.258819f, 0.965926f));
/* For rotation and translation this is the same as rotationScaling() */
Matrix3 rotationTranslation = rotation*Matrix3::translation({2.0f, 5.0f});
Matrix2 rotationTranslationPart = rotationTranslation.rotation();
Matrix2x2 rotationTranslationPart = rotationTranslation.rotation();
CORRADE_COMPARE(rotationTranslationPart, rotationTranslation.rotationScaling());
CORRADE_COMPARE(rotationTranslationPart, expectedRotationPart);
/* Test uniform scaling */
Matrix3 rotationScaling = rotation*Matrix3::scaling(Vector2(3.0f));
Matrix2 rotationScalingPart = rotationScaling.rotation();
Matrix2x2 rotationScalingPart = rotationScaling.rotation();
CORRADE_COMPARE(rotationScalingPart.determinant(), 1.0f);
CORRADE_COMPARE(rotationScalingPart*rotationScalingPart.transposed(), Matrix2());
CORRADE_COMPARE(rotationScalingPart*rotationScalingPart.transposed(), Matrix2x2());
CORRADE_COMPARE(rotationScalingPart, expectedRotationPart);
/* Fails on non-uniform scaling */
std::ostringstream o;
Error::setOutput(&o);
Matrix2 rotationScaling2 = (rotation*Matrix3::scaling(Vector2::yScale(3.5f))).rotation();
Matrix2x2 rotationScaling2 = (rotation*Matrix3::scaling(Vector2::yScale(3.5f))).rotation();
CORRADE_COMPARE(o.str(), "Math::Matrix3::rotation(): the matrix doesn't have uniform scaling\n");
CORRADE_COMPARE(rotationScaling2, Matrix2());
CORRADE_COMPARE(rotationScaling2, Matrix2x2());
}
void Matrix3Test::uniformScalingPart() {

38
src/Math/Test/Matrix4Test.cpp

@ -98,7 +98,7 @@ typedef Math::Deg<Float> Deg;
typedef Math::Rad<Float> Rad;
typedef Math::Matrix4<Float> Matrix4;
typedef Math::Matrix4<Int> Matrix4i;
typedef Math::Matrix<3, Float> Matrix3;
typedef Math::Matrix<3, Float> Matrix3x3;
typedef Math::Vector3<Float> Vector3;
Matrix4Test::Matrix4Test() {
@ -353,9 +353,9 @@ void Matrix4Test::perspectiveProjectionFov() {
}
void Matrix4Test::fromParts() {
constexpr Matrix3 rotationScaling(Vector3(3.0f, 5.0f, 8.0f),
Vector3(4.0f, 4.0f, 7.0f),
Vector3(7.0f, -1.0f, 8.0f));
constexpr Matrix3x3 rotationScaling(Vector3(3.0f, 5.0f, 8.0f),
Vector3(4.0f, 4.0f, 7.0f),
Vector3(7.0f, -1.0f, 8.0f));
constexpr Vector3 translation(9.0f, 4.0f, 5.0f);
constexpr Matrix4 a = Matrix4::from(rotationScaling, translation);
@ -370,11 +370,11 @@ void Matrix4Test::rotationScalingPart() {
{4.0f, 4.0f, 7.0f, 3.0f},
{7.0f, -1.0f, 8.0f, 0.0f},
{9.0f, 4.0f, 5.0f, 9.0f});
constexpr Matrix3 b = a.rotationScaling();
constexpr Matrix3x3 b = a.rotationScaling();
CORRADE_COMPARE(b, Matrix3(Vector3(3.0f, 5.0f, 8.0f),
Vector3(4.0f, 4.0f, 7.0f),
Vector3(7.0f, -1.0f, 8.0f)));
CORRADE_COMPARE(b, Matrix3x3(Vector3(3.0f, 5.0f, 8.0f),
Vector3(4.0f, 4.0f, 7.0f),
Vector3(7.0f, -1.0f, 8.0f)));
}
void Matrix4Test::rotationNormalizedPart() {
@ -392,36 +392,36 @@ void Matrix4Test::rotationNormalizedPart() {
{ 0.47987163f, 0.59757638f, 0.6423595f, 3.0f},
{-0.80181062f, 0.0015183985f, 0.59757638f, 4.0f},
{ 0.0f, 0.0f, 0.0f, 1.0f});
CORRADE_COMPARE(b.rotationNormalized(), Matrix3(Vector3( 0.35612214f, -0.80181062f, 0.47987163f),
Vector3( 0.47987163f, 0.59757638f, 0.6423595f),
Vector3(-0.80181062f, 0.0015183985f, 0.59757638f)));
CORRADE_COMPARE(b.rotationNormalized(), Matrix3x3(Vector3( 0.35612214f, -0.80181062f, 0.47987163f),
Vector3( 0.47987163f, 0.59757638f, 0.6423595f),
Vector3(-0.80181062f, 0.0015183985f, 0.59757638f)));
}
void Matrix4Test::rotationPart() {
Matrix4 rotation = Matrix4::rotation(Deg(-74.0f), Vector3(-1.0f, 2.0f, 2.0f).normalized());
Matrix3 expectedRotationPart(Vector3( 0.35612214f, -0.80181062f, 0.47987163f),
Vector3( 0.47987163f, 0.59757638f, 0.6423595f),
Vector3(-0.80181062f, 0.0015183985f, 0.59757638f));
Matrix3x3 expectedRotationPart(Vector3( 0.35612214f, -0.80181062f, 0.47987163f),
Vector3( 0.47987163f, 0.59757638f, 0.6423595f),
Vector3(-0.80181062f, 0.0015183985f, 0.59757638f));
/* For rotation and translation this is the same as rotationScaling() */
Matrix4 rotationTranslation = rotation*Matrix4::translation({2.0f, 5.0f, -3.0f});
Matrix3 rotationTranslationPart = rotationTranslation.rotation();
Matrix3x3 rotationTranslationPart = rotationTranslation.rotation();
CORRADE_COMPARE(rotationTranslationPart, rotationTranslation.rotationScaling());
CORRADE_COMPARE(rotationTranslationPart, expectedRotationPart);
/* Test uniform scaling */
Matrix4 rotationScaling = rotation*Matrix4::scaling(Vector3(3.0f));
Matrix3 rotationScalingPart = rotationScaling.rotation();
Matrix3x3 rotationScalingPart = rotationScaling.rotation();
CORRADE_COMPARE(rotationScalingPart.determinant(), 1.0f);
CORRADE_COMPARE(rotationScalingPart*rotationScalingPart.transposed(), Matrix3());
CORRADE_COMPARE(rotationScalingPart*rotationScalingPart.transposed(), Matrix3x3());
CORRADE_COMPARE(rotationScalingPart, expectedRotationPart);
/* Fails on non-uniform scaling */
std::ostringstream o;
Error::setOutput(&o);
Matrix3 rotationScaling2 = (rotation*Matrix4::scaling(Vector3::yScale(3.5f))).rotation();
Matrix3x3 rotationScaling2 = (rotation*Matrix4::scaling(Vector3::yScale(3.5f))).rotation();
CORRADE_COMPARE(o.str(), "Math::Matrix4::rotation(): the matrix doesn't have uniform scaling\n");
CORRADE_COMPARE(rotationScaling2, Matrix3());
CORRADE_COMPARE(rotationScaling2, Matrix3x3());
}
void Matrix4Test::uniformScalingPart() {

187
src/Math/Test/MatrixTest.cpp

@ -82,9 +82,9 @@ class MatrixTest: public Corrade::TestSuite::Tester {
void configuration();
};
typedef Matrix<4, Float> Matrix4;
typedef Matrix<4, Int> Matrix4i;
typedef Matrix<3, Float> Matrix3;
typedef Matrix<4, Float> Matrix4x4;
typedef Matrix<4, Int> Matrix4x4i;
typedef Matrix<3, Float> Matrix3x3;
typedef Vector<4, Float> Vector4;
typedef Vector<4, Int> Vector4i;
typedef Vector<3, Float> Vector3;
@ -116,37 +116,37 @@ MatrixTest::MatrixTest() {
void MatrixTest::construct() {
#ifndef CORRADE_GCC44_COMPATIBILITY
constexpr Matrix4 a = {Vector4(3.0f, 5.0f, 8.0f, -3.0f),
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f)};
constexpr Matrix4x4 a = {Vector4(3.0f, 5.0f, 8.0f, -3.0f),
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f)};
#else
/* Ambiguity with default copy constructor */
constexpr Matrix4 a(Vector4(3.0f, 5.0f, 8.0f, -3.0f),
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f));
constexpr Matrix4x4 a(Vector4(3.0f, 5.0f, 8.0f, -3.0f),
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f));
#endif
CORRADE_COMPARE(a, Matrix4(Vector4(3.0f, 5.0f, 8.0f, -3.0f),
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f)));
CORRADE_COMPARE(a, Matrix4x4(Vector4(3.0f, 5.0f, 8.0f, -3.0f),
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f)));
}
void MatrixTest::constructIdentity() {
Matrix4 identity;
Matrix4 identity2(Matrix4::Identity);
Matrix4 identity3(Matrix4::Identity, 4.0f);
Matrix4x4 identity;
Matrix4x4 identity2(Matrix4x4::Identity);
Matrix4x4 identity3(Matrix4x4::Identity, 4.0f);
Matrix4 identityExpected(Vector4(1.0f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, 1.0f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, 1.0f, 0.0f),
Vector4(0.0f, 0.0f, 0.0f, 1.0f));
Matrix4x4 identityExpected(Vector4(1.0f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, 1.0f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, 1.0f, 0.0f),
Vector4(0.0f, 0.0f, 0.0f, 1.0f));
Matrix4 identity3Expected(Vector4(4.0f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, 4.0f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, 4.0f, 0.0f),
Vector4(0.0f, 0.0f, 0.0f, 4.0f));
Matrix4x4 identity3Expected(Vector4(4.0f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, 4.0f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, 4.0f, 0.0f),
Vector4(0.0f, 0.0f, 0.0f, 4.0f));
CORRADE_COMPARE(identity, identityExpected);
CORRADE_COMPARE(identity2, identityExpected);
@ -154,30 +154,29 @@ void MatrixTest::constructIdentity() {
}
void MatrixTest::constructZero() {
constexpr Matrix4 a(Matrix4::Zero);
CORRADE_COMPARE(a, Matrix4(Vector4(0.0f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, 0.0f, 0.0f)));
constexpr Matrix4x4 a(Matrix4x4::Zero);
CORRADE_COMPARE(a, Matrix4x4(Vector4(0.0f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, 0.0f, 0.0f),
Vector4(0.0f, 0.0f, 0.0f, 0.0f)));
}
void MatrixTest::constructConversion() {
constexpr Matrix4 a(Vector4(3.0f, 5.0f, 8.0f, -3.0f),
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f));
constexpr Matrix4x4 a(Vector4(3.0f, 5.0f, 8.0f, -3.0f),
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f));
#ifndef CORRADE_GCC46_COMPATIBILITY
constexpr Matrix4i b(a);
#else
Matrix4i b(a); /* Not constexpr under GCC < 4.7 */
constexpr /* Not constexpr under GCC < 4.7 */
#endif
CORRADE_COMPARE(b, Matrix4i(Vector4i(3, 5, 8, -3),
Vector4i(4, 4, 7, 2),
Vector4i(1, 2, 3, -1),
Vector4i(7, -1, 8, -1)));
Matrix4x4i b(a);
CORRADE_COMPARE(b, Matrix4x4i(Vector4i(3, 5, 8, -3),
Vector4i(4, 4, 7, 2),
Vector4i(1, 2, 3, -1),
Vector4i(7, -1, 8, -1)));
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!(std::is_convertible<Matrix4, Matrix4i>::value));
CORRADE_VERIFY(!(std::is_convertible<Matrix4x4, Matrix4x4i>::value));
}
void MatrixTest::constructCopy() {
@ -185,22 +184,22 @@ void MatrixTest::constructCopy() {
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f));
constexpr Matrix4 b(a);
CORRADE_COMPARE(b, Matrix4(Vector4(3.0f, 5.0f, 8.0f, -3.0f),
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f)));
constexpr Matrix4x4 b(a);
CORRADE_COMPARE(b, Matrix4x4(Vector4(3.0f, 5.0f, 8.0f, -3.0f),
Vector4(4.5f, 4.0f, 7.0f, 2.0f),
Vector4(1.0f, 2.0f, 3.0f, -1.0f),
Vector4(7.9f, -1.0f, 8.0f, -1.5f)));
}
void MatrixTest::convert() {
constexpr Mat3 a{{1.5f, 2.0f, -3.5f,
2.0f, -3.1f, 0.4f,
9.5f, -1.5f, 0.1f}};
constexpr Matrix3 b(Vector3(1.5f, 2.0f, -3.5f),
Vector3(2.0f, -3.1f, 0.4f),
Vector3(9.5f, -1.5f, 0.1f));
constexpr Matrix3x3 b(Vector3(1.5f, 2.0f, -3.5f),
Vector3(2.0f, -3.1f, 0.4f),
Vector3(9.5f, -1.5f, 0.1f));
constexpr Matrix3 c(b);
constexpr Matrix3x3 c(b);
CORRADE_COMPARE(c, b);
#ifndef CORRADE_GCC46_COMPATIBILITY
@ -211,25 +210,25 @@ void MatrixTest::convert() {
CORRADE_COMPARE(d.a[i], a.a[i]);
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!(std::is_convertible<Mat3, Matrix3>::value));
CORRADE_VERIFY(!(std::is_convertible<Mat3, Matrix3x3>::value));
{
#ifdef CORRADE_GCC44_COMPATIBILITY
CORRADE_EXPECT_FAIL("GCC 4.4 doesn't have explicit conversion operators");
#endif
CORRADE_VERIFY(!(std::is_convertible<Matrix3, Mat3>::value));
CORRADE_VERIFY(!(std::is_convertible<Matrix3x3, Mat3>::value));
}
}
void MatrixTest::isOrthogonal() {
CORRADE_VERIFY(!Matrix3(Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f),
Vector3(0.0f, 0.1f, 1.0f)).isOrthogonal());
CORRADE_VERIFY(!Matrix3(Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f)).isOrthogonal());
CORRADE_VERIFY(Matrix3(Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f),
Vector3(0.0f, 0.0f, 1.0f)).isOrthogonal());
CORRADE_VERIFY(!Matrix3x3(Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f),
Vector3(0.0f, 0.1f, 1.0f)).isOrthogonal());
CORRADE_VERIFY(!Matrix3x3(Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f)).isOrthogonal());
CORRADE_VERIFY(Matrix3x3(Vector3(1.0f, 0.0f, 0.0f),
Vector3(0.0f, 1.0f, 0.0f),
Vector3(0.0f, 0.0f, 1.0f)).isOrthogonal());
}
void MatrixTest::trace() {
@ -245,14 +244,14 @@ void MatrixTest::trace() {
}
void MatrixTest::ij() {
Matrix4 original(Vector4( 0.0f, 1.0f, 2.0f, 3.0f),
Vector4( 4.0f, 5.0f, 6.0f, 7.0f),
Vector4( 8.0f, 9.0f, 10.0f, 11.0f),
Vector4(12.0f, 13.0f, 14.0f, 15.0f));
Matrix4x4 original(Vector4( 0.0f, 1.0f, 2.0f, 3.0f),
Vector4( 4.0f, 5.0f, 6.0f, 7.0f),
Vector4( 8.0f, 9.0f, 10.0f, 11.0f),
Vector4(12.0f, 13.0f, 14.0f, 15.0f));
Matrix3 skipped(Vector3( 0.0f, 1.0f, 3.0f),
Vector3( 8.0f, 9.0f, 11.0f),
Vector3(12.0f, 13.0f, 15.0f));
Matrix3x3 skipped(Vector3( 0.0f, 1.0f, 3.0f),
Vector3( 8.0f, 9.0f, 11.0f),
Vector3(12.0f, 13.0f, 15.0f));
CORRADE_COMPARE(original.ij(1, 2), skipped);
}
@ -270,33 +269,33 @@ void MatrixTest::determinant() {
}
void MatrixTest::inverted() {
Matrix4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.0f),
Vector4(7.0f, -1.0f, 8.0f, 0.0f),
Vector4(9.0f, 4.0f, 5.0f, 9.0f));
Matrix4x4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.0f),
Vector4(7.0f, -1.0f, 8.0f, 0.0f),
Vector4(9.0f, 4.0f, 5.0f, 9.0f));
Matrix4 inverse(Vector4(-60/103.0f, 71/103.0f, -4/103.0f, 3/103.0f),
Vector4(-66/103.0f, 109/103.0f, -25/103.0f, -7/103.0f),
Vector4(177/412.0f, -97/206.0f, 53/412.0f, -7/206.0f),
Vector4(259/412.0f, -185/206.0f, 31/412.0f, 27/206.0f));
Matrix4x4 inverse(Vector4(-60/103.0f, 71/103.0f, -4/103.0f, 3/103.0f),
Vector4(-66/103.0f, 109/103.0f, -25/103.0f, -7/103.0f),
Vector4(177/412.0f, -97/206.0f, 53/412.0f, -7/206.0f),
Vector4(259/412.0f, -185/206.0f, 31/412.0f, 27/206.0f));
Matrix4 _inverse = m.inverted();
Matrix4x4 _inverse = m.inverted();
CORRADE_COMPARE(_inverse, inverse);
CORRADE_COMPARE(_inverse*m, Matrix4());
CORRADE_COMPARE(_inverse*m, Matrix4x4());
}
void MatrixTest::invertedOrthogonal() {
std::ostringstream o;
Error::setOutput(&o);
Matrix3 a(Vector3(Constants::sqrt3()/2.0f, 0.5f, 0.0f),
Vector3(-0.5f, Constants::sqrt3()/2.0f, 0.0f),
Vector3(0.0f, 0.0f, 1.0f));
Matrix3x3 a(Vector3(Constants::sqrt3()/2.0f, 0.5f, 0.0f),
Vector3(-0.5f, Constants::sqrt3()/2.0f, 0.0f),
Vector3(0.0f, 0.0f, 1.0f));
(a*2).invertedOrthogonal();
CORRADE_COMPARE(o.str(), "Math::Matrix::invertedOrthogonal(): the matrix is not orthogonal\n");
CORRADE_COMPARE(a.invertedOrthogonal()*a, Matrix3());
CORRADE_COMPARE(a.invertedOrthogonal()*a, Matrix3x3());
CORRADE_COMPARE(a.invertedOrthogonal(), a.inverted());
}
@ -357,10 +356,10 @@ void MatrixTest::subclass() {
}
void MatrixTest::debug() {
Matrix4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.0f),
Vector4(7.0f, -1.0f, 8.0f, 0.0f),
Vector4(9.0f, 4.0f, 5.0f, 9.0f));
Matrix4x4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.0f),
Vector4(7.0f, -1.0f, 8.0f, 0.0f),
Vector4(9.0f, 4.0f, 5.0f, 9.0f));
std::ostringstream o;
Debug(&o) << m;
@ -370,7 +369,7 @@ void MatrixTest::debug() {
" 4, 3, 0, 9)\n");
o.str({});
Debug(&o) << "a" << Matrix4() << "b" << Matrix4();
Debug(&o) << "a" << Matrix4x4() << "b" << Matrix4x4();
CORRADE_COMPARE(o.str(), "a Matrix(1, 0, 0, 0,\n"
" 0, 1, 0, 0,\n"
" 0, 0, 1, 0,\n"
@ -383,15 +382,15 @@ void MatrixTest::debug() {
void MatrixTest::configuration() {
Corrade::Utility::Configuration c;
Matrix4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.125f),
Vector4(7.0f, -1.0f, 8.0f, 0.0f),
Vector4(9.0f, 4.0f, 5.0f, 9.55f));
Matrix4x4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.125f),
Vector4(7.0f, -1.0f, 8.0f, 0.0f),
Vector4(9.0f, 4.0f, 5.0f, 9.55f));
std::string value("3 4 7 9 5 4 -1 4 8 7 8 5 4 3.125 0 9.55");
c.setValue("matrix", m);
CORRADE_COMPARE(c.value("matrix"), value);
CORRADE_COMPARE(c.value<Matrix4>("matrix"), m);
CORRADE_COMPARE(c.value<Matrix4x4>("matrix"), m);
}
}}}

6
src/Math/Test/QuaternionTest.cpp

@ -69,7 +69,7 @@ class QuaternionTest: public Corrade::TestSuite::Tester {
typedef Math::Deg<Float> Deg;
typedef Math::Rad<Float> Rad;
typedef Math::Matrix<3, Float> Matrix3;
typedef Math::Matrix<3, Float> Matrix3x3;
typedef Math::Matrix4<Float> Matrix4;
typedef Math::Quaternion<Float> Quaternion;
typedef Math::Vector3<Float> Vector3;
@ -283,7 +283,7 @@ void QuaternionTest::matrix() {
Vector3 axis = Vector3(1.0f, -3.0f, 5.0f).normalized();
Quaternion q = Quaternion::rotation(Deg(37.0f), axis);
Matrix3 m = Matrix4::rotation(Deg(37.0f), axis).rotationScaling();
Matrix3x3 m = Matrix4::rotation(Deg(37.0f), axis).rotationScaling();
/* Verify that negated quaternion gives the same rotation */
CORRADE_COMPARE(q.toMatrix(), m);
@ -299,7 +299,7 @@ void QuaternionTest::matrix() {
CORRADE_COMPARE(Quaternion::fromMatrix(m), q);
/* Trace < 0 */
Matrix3 m2 = Matrix4::rotation(Deg(130.0f), axis).rotationScaling();
Matrix3x3 m2 = Matrix4::rotation(Deg(130.0f), axis).rotationScaling();
Quaternion q2 = Quaternion::rotation(Deg(130.0f), axis);
CORRADE_VERIFY(m2.trace() < 0.0f);
CORRADE_COMPARE(Quaternion::fromMatrix(m2), q2);

62
src/Math/Test/RectangularMatrixTest.cpp

@ -90,8 +90,8 @@ class RectangularMatrixTest: public Corrade::TestSuite::Tester {
typedef RectangularMatrix<4, 3, Float> Matrix4x3;
typedef RectangularMatrix<3, 4, Float> Matrix3x4;
typedef RectangularMatrix<2, 2, Float> Matrix2;
typedef RectangularMatrix<2, 2, Int> Matrix2i;
typedef RectangularMatrix<2, 2, Float> Matrix2x2;
typedef RectangularMatrix<2, 2, Int> Matrix2x2i;
typedef Vector<4, Float> Vector4;
typedef Vector<3, Float> Vector3;
typedef Vector<2, Float> Vector2;
@ -152,19 +152,19 @@ void RectangularMatrixTest::constructDefault() {
}
void RectangularMatrixTest::constructConversion() {
constexpr Matrix2 a(Vector2( 1.3f, 2.7f),
Vector2(-15.0f, 7.0f));
constexpr Matrix2x2 a(Vector2( 1.3f, 2.7f),
Vector2(-15.0f, 7.0f));
#ifndef CORRADE_GCC46_COMPATIBILITY
constexpr Matrix2i b(a);
constexpr Matrix2x2i b(a);
#else
Matrix2i b(a); /* Not constexpr under GCC < 4.7 */
Matrix2x2i b(a); /* Not constexpr under GCC < 4.7 */
#endif
CORRADE_COMPARE(b, Matrix2i(Vector2i( 1, 2),
Vector2i(-15, 7)));
CORRADE_COMPARE(b, Matrix2x2i(Vector2i( 1, 2),
Vector2i(-15, 7)));
/* Implicit conversion is not allowed */
CORRADE_VERIFY(!(std::is_convertible<Matrix2, Matrix2i>::value));
CORRADE_VERIFY(!(std::is_convertible<Matrix2x2, Matrix2x2i>::value));
}
void RectangularMatrixTest::constructFromData() {
@ -273,28 +273,28 @@ void RectangularMatrixTest::row() {
}
void RectangularMatrixTest::compare() {
Matrix2 a(Vector2(1.0f, -3.0f),
Vector2(5.0f, -10.0f));
Matrix2 b(Vector2(1.0f + TypeTraits<Float>::epsilon()/2, -3.0f),
Vector2(5.0f, -10.0f));
Matrix2 c(Vector2(1.0f, -1.0f + TypeTraits<Float>::epsilon()*2),
Vector2(5.0f, -10.0f));
Matrix2x2 a(Vector2(1.0f, -3.0f),
Vector2(5.0f, -10.0f));
Matrix2x2 b(Vector2(1.0f + TypeTraits<Float>::epsilon()/2, -3.0f),
Vector2(5.0f, -10.0f));
Matrix2x2 c(Vector2(1.0f, -1.0f + TypeTraits<Float>::epsilon()*2),
Vector2(5.0f, -10.0f));
CORRADE_VERIFY(a == b);
CORRADE_VERIFY(a != c);
Matrix2i ai(Vector2i(1, -3),
Vector2i(5, -10));
Matrix2i bi(Vector2i(1, -2),
Vector2i(5, -10));
Matrix2x2i ai(Vector2i(1, -3),
Vector2i(5, -10));
Matrix2x2i bi(Vector2i(1, -2),
Vector2i(5, -10));
CORRADE_VERIFY(ai == ai);
CORRADE_VERIFY(ai != bi);
}
void RectangularMatrixTest::negative() {
Matrix2 matrix(Vector2(1.0f, -3.0f),
Vector2(5.0f, -10.0f));
Matrix2 negated(Vector2(-1.0f, 3.0f),
Vector2(-5.0f, 10.0f));
Matrix2x2 matrix(Vector2(1.0f, -3.0f),
Vector2(5.0f, -10.0f));
Matrix2x2 negated(Vector2(-1.0f, 3.0f),
Vector2(-5.0f, 10.0f));
CORRADE_COMPARE(-matrix, negated);
}
@ -317,20 +317,20 @@ void RectangularMatrixTest::addSubtract() {
}
void RectangularMatrixTest::multiplyDivide() {
Matrix2 matrix(Vector2(1.0f, 2.0f),
Vector2(3.0f, 4.0f));
Matrix2 multiplied(Vector2(-1.5f, -3.0f),
Vector2(-4.5f, -6.0f));
Matrix2x2 matrix(Vector2(1.0f, 2.0f),
Vector2(3.0f, 4.0f));
Matrix2x2 multiplied(Vector2(-1.5f, -3.0f),
Vector2(-4.5f, -6.0f));
CORRADE_COMPARE(matrix*-1.5f, multiplied);
CORRADE_COMPARE(-1.5f*matrix, multiplied);
CORRADE_COMPARE(multiplied/-1.5f, matrix);
/* Divide vector with number and inverse */
Matrix2 divisor(Vector2( 1.0f, 2.0f),
Vector2(-4.0f, 8.0f));
Matrix2 result(Vector2( 1.0f, 0.5f),
Vector2(-0.25f, 0.125f));
Matrix2x2 divisor(Vector2( 1.0f, 2.0f),
Vector2(-4.0f, 8.0f));
Matrix2x2 result(Vector2( 1.0f, 0.5f),
Vector2(-0.25f, 0.125f));
CORRADE_COMPARE(1.0f/divisor, result);
}

7
src/Math/Test/SwizzleTest.cpp

@ -34,6 +34,7 @@ class SwizzleTest: public Corrade::TestSuite::Tester {
void components();
void constants();
void rgba();
void sizes();
};
@ -42,6 +43,7 @@ typedef Vector<4, Int> Vector4i;
SwizzleTest::SwizzleTest() {
addTests({&SwizzleTest::components,
&SwizzleTest::constants,
&SwizzleTest::rgba,
&SwizzleTest::sizes});
}
@ -55,6 +57,11 @@ void SwizzleTest::constants() {
CORRADE_COMPARE(a, Vector4i(1, 7, 0, 4));
}
void SwizzleTest::rgba() {
constexpr auto a = swizzle<'b', 'r', 'a', 'g'>(Vector4i(2, 4, 5, 7));
CORRADE_COMPARE(a, Vector4i(5, 2, 7, 4));
}
void SwizzleTest::sizes() {
constexpr auto a = swizzle<'y', 'x', 'x'>(Math::Vector<2, Int>(1, 2));
CORRADE_COMPARE(a, (Math::Vector<3, Int>(2, 1, 1)));

17
src/Math/Test/Vector2Test.cpp

@ -26,7 +26,7 @@
#include <TestSuite/Tester.h>
#include <Utility/Configuration.h>
#include "Math/Vector3.h"
#include "Math/Vector3.h" /* Vector3 used in Vector2::cross() */
struct Vec2 {
float x, y;
@ -67,7 +67,9 @@ class Vector2Test: public Corrade::TestSuite::Tester {
void axes();
void scales();
void perpendicular();
void aspectRatio();
void swizzleType();
void debug();
void configuration();
};
@ -90,7 +92,9 @@ Vector2Test::Vector2Test() {
&Vector2Test::axes,
&Vector2Test::scales,
&Vector2Test::perpendicular,
&Vector2Test::aspectRatio,
&Vector2Test::swizzleType,
&Vector2Test::debug,
&Vector2Test::configuration});
}
@ -205,6 +209,17 @@ void Vector2Test::perpendicular() {
CORRADE_COMPARE(Vector2::xAxis().perpendicular(), Vector2::yAxis());
}
void Vector2Test::aspectRatio() {
const Vector2 a(3.0f, 4.0f);
CORRADE_COMPARE(a.aspectRatio(), 0.75f);
}
void Vector2Test::swizzleType() {
constexpr Vector<4, Int> orig;
constexpr auto a = swizzle<'y', 'a'>(orig);
CORRADE_VERIFY((std::is_same<decltype(a), const Vector2i>::value));
}
void Vector2Test::debug() {
std::ostringstream o;
Debug(&o) << Vector2(0.5f, 15.0f);

16
src/Math/Test/Vector3Test.cpp

@ -69,6 +69,7 @@ class Vector3Test: public Corrade::TestSuite::Tester {
void scales();
void twoComponent();
void swizzleType();
void debug();
void configuration();
};
@ -176,16 +177,25 @@ void Vector3Test::convert() {
void Vector3Test::access() {
Vector3 vec(1.0f, -2.0f, 5.0f);
CORRADE_COMPARE(vec.x(), 1.0f);
CORRADE_COMPARE(vec.r(), 1.0f);
CORRADE_COMPARE(vec.y(), -2.0f);
CORRADE_COMPARE(vec.g(), -2.0f);
CORRADE_COMPARE(vec.z(), 5.0f);
CORRADE_COMPARE(vec.b(), 5.0f);
constexpr Vector3 cvec(1.0f, -2.0f, 5.0f);
constexpr Float x = cvec.x();
constexpr Float r = cvec.r();
constexpr Float y = cvec.y();
constexpr Float g = cvec.g();
constexpr Float z = cvec.z();
constexpr Float b = cvec.b();
CORRADE_COMPARE(x, 1.0f);
CORRADE_COMPARE(r, 1.0f);
CORRADE_COMPARE(y, -2.0f);
CORRADE_COMPARE(g, -2.0f);
CORRADE_COMPARE(z, 5.0f);
CORRADE_COMPARE(b, 5.0f);
}
void Vector3Test::cross() {
@ -224,6 +234,12 @@ void Vector3Test::twoComponent() {
CORRADE_COMPARE(d, 2.0f);
}
void Vector3Test::swizzleType() {
constexpr Vector<4, Int> orig;
constexpr auto b = swizzle<'y', 'z', 'a'>(orig);
CORRADE_VERIFY((std::is_same<decltype(b), const Vector3i>::value));
}
void Vector3Test::debug() {
std::ostringstream o;
Debug(&o) << Vector3(0.5f, 15.0f, 1.0f);

21
src/Math/Test/Vector4Test.cpp

@ -67,6 +67,7 @@ class Vector4Test: public Corrade::TestSuite::Tester {
void threeComponent();
void twoComponent();
void swizzleType();
void debug();
void configuration();
};
@ -90,6 +91,7 @@ Vector4Test::Vector4Test() {
&Vector4Test::threeComponent,
&Vector4Test::twoComponent,
&Vector4Test::swizzleType,
&Vector4Test::debug,
&Vector4Test::configuration});
}
@ -174,24 +176,37 @@ void Vector4Test::convert() {
void Vector4Test::access() {
Vector4 vec(1.0f, -2.0f, 5.0f, 0.5f);
CORRADE_COMPARE(vec.x(), 1.0f);
CORRADE_COMPARE(vec.r(), 1.0f);
CORRADE_COMPARE(vec.y(), -2.0f);
CORRADE_COMPARE(vec.g(), -2.0f);
CORRADE_COMPARE(vec.z(), 5.0f);
CORRADE_COMPARE(vec.b(), 5.0f);
CORRADE_COMPARE(vec.w(), 0.5f);
CORRADE_COMPARE(vec.a(), 0.5f);
constexpr Vector4 cvec(1.0f, -2.0f, 5.0f, 0.5f);
constexpr Float x = cvec.x();
constexpr Float r = cvec.r();
constexpr Float y = cvec.y();
constexpr Float g = cvec.g();
constexpr Float z = cvec.z();
constexpr Float b = cvec.b();
constexpr Float w = cvec.w();
constexpr Float a = cvec.a();
CORRADE_COMPARE(x, 1.0f);
CORRADE_COMPARE(r, 1.0f);
CORRADE_COMPARE(y, -2.0f);
CORRADE_COMPARE(g, -2.0f);
CORRADE_COMPARE(z, 5.0f);
CORRADE_COMPARE(b, 5.0f);
CORRADE_COMPARE(w, 0.5f);
CORRADE_COMPARE(a, 0.5f);
}
void Vector4Test::threeComponent() {
Vector4 a(1.0f, 2.0f, 3.0f, 4.0f);
CORRADE_COMPARE(a.xyz(), Vector3(1.0f, 2.0f, 3.0f));
CORRADE_COMPARE(a.rgb(), Vector3(1.0f, 2.0f, 3.0f));
constexpr Vector4 b(1.0f, 2.0f, 3.0f, 4.0f);
constexpr Vector3 c = b.xyz();
@ -211,6 +226,12 @@ void Vector4Test::twoComponent() {
CORRADE_COMPARE(d, 1.0f);
}
void Vector4Test::swizzleType() {
constexpr Vector4i orig;
constexpr auto c = swizzle<'y', 'a', 'y', 'x'>(orig);
CORRADE_VERIFY((std::is_same<decltype(c), const Vector4i>::value));
}
void Vector4Test::debug() {
std::ostringstream o;
Debug(&o) << Vector4(0.5f, 15.0f, 1.0f, 1.0f);

14
src/Math/Vector2.h

@ -138,6 +138,15 @@ template<class T> class Vector2: public Vector<2, T> {
*/
Vector2<T> perpendicular() const { return {-y(), x()}; }
/**
* @brief Aspect ratio
*
* Returns quotient of the two elements. @f[
* a = \frac{v_x}{v_y}
* @f]
*/
T aspectRatio() const { return x()/y(); }
MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(2, Vector2)
};
@ -148,6 +157,11 @@ template<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::De
return debug << static_cast<const Vector<2, T>&>(value);
}
namespace Implementation {
template<std::size_t, class> struct TypeForSize;
template<class T> struct TypeForSize<2, T> { typedef Math::Vector2<typename T::Type> Type; };
}
}}
namespace Corrade { namespace Utility {

52
src/Math/Vector3.h

@ -149,13 +149,55 @@ template<class T> class Vector3: public Vector<3, T> {
/** @brief Copy constructor */
constexpr Vector3(const Vector<3, T>& other): Vector<3, T>(other) {}
T& x() { return (*this)[0]; } /**< @brief X component */
/**
* @brief X component
*
* @see @ref r()
*/
T& x() { return (*this)[0]; }
constexpr T x() const { return (*this)[0]; } /**< @overload */
T& y() { return (*this)[1]; } /**< @brief Y component */
/**
* @brief Y component
*
* @see @ref g()
*/
T& y() { return (*this)[1]; }
constexpr T y() const { return (*this)[1]; } /**< @overload */
T& z() { return (*this)[2]; } /**< @brief Z component */
/**
* @brief Z component
*
* @see @ref b()
*/
T& z() { return (*this)[2]; }
constexpr T z() const { return (*this)[2]; } /**< @overload */
/**
* @brief R component
*
* Equivalent to @ref x().
*/
T& r() { return x(); }
constexpr T r() const { return x(); } /**< @overload */
/**
* @brief G component
*
* Equivalent to @ref y().
*/
T& g() { return y(); }
constexpr T g() const { return y(); } /**< @overload */
/**
* @brief B component
*
* Equivalent to @ref z().
*/
T& b() { return z(); }
constexpr T b() const { return z(); } /**< @overload */
/**
* @brief XY part of the vector
* @return First two components of the vector
@ -175,6 +217,10 @@ template<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::De
return debug << static_cast<const Vector<3, T>&>(value);
}
namespace Implementation {
template<class T> struct TypeForSize<3, T> { typedef Math::Vector3<typename T::Type> Type; };
}
}}
namespace Corrade { namespace Utility {

81
src/Math/Vector4.h

@ -79,29 +79,94 @@ template<class T> class Vector4: public Vector<4, T> {
/** @brief Copy constructor */
constexpr Vector4(const Vector<4, T>& other): Vector<4, T>(other) {}
T& x() { return (*this)[0]; } /**< @brief X component */
/**
* @brief X component
*
* @see @ref r()
*/
T& x() { return (*this)[0]; }
constexpr T x() const { return (*this)[0]; } /**< @overload */
T& y() { return (*this)[1]; } /**< @brief Y component */
/**
* @brief Y component
*
* @see @ref g()
*/
T& y() { return (*this)[1]; }
constexpr T y() const { return (*this)[1]; } /**< @overload */
T& z() { return (*this)[2]; } /**< @brief Z component */
/**
* @brief Z component
*
* @see @ref b()
*/
T& z() { return (*this)[2]; }
constexpr T z() const { return (*this)[2]; } /**< @overload */
T& w() { return (*this)[3]; } /**< @brief W component */
/**
* @brief W component
*
* @see @ref a()
*/
T& w() { return (*this)[3]; }
constexpr T w() const { return (*this)[3]; } /**< @overload */
/**
* @brief R component
*
* Equivalent to @ref x().
*/
T& r() { return x(); }
constexpr T r() const { return x(); } /**< @overload */
/**
* @brief G component
*
* Equivalent to @ref y().
*/
T& g() { return y(); }
constexpr T g() const { return y(); } /**< @overload */
/**
* @brief B component
*
* Equivalent to @ref z().
*/
T& b() { return z(); }
constexpr T b() const { return z(); } /**< @overload */
/**
* @brief A component
*
* Equivalent to @ref w().
*/
T& a() { return w(); }
constexpr T a() const { return w(); } /**< @overload */
/**
* @brief XYZ part of the vector
* @return First three components of the vector
*
* @see swizzle()
* @see @ref swizzle(), @ref rgb()
*/
Vector3<T>& xyz() { return Vector3<T>::from(Vector<4, T>::data()); }
constexpr const Vector3<T> xyz() const { return {x(), y(), z()}; } /**< @overload */
/**
* @brief RGB part of the vector
* @return First three components of the vector
*
* Equivalent to @ref xyz().
* @see @ref swizzle()
*/
Vector3<T>& rgb() { return xyz(); }
constexpr const Vector3<T> rgb() const { return xyz(); } /**< @overload */
/**
* @brief XY part of the vector
* @return First two components of the vector
*
* @see swizzle()
* @see @ref swizzle()
*/
Vector2<T>& xy() { return Vector2<T>::from(Vector<4, T>::data()); }
constexpr const Vector2<T> xy() const { return {x(), y()}; } /**< @overload */
@ -116,6 +181,10 @@ template<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::De
return debug << static_cast<const Vector<4, T>&>(value);
}
namespace Implementation {
template<class T> struct TypeForSize<4, T> { typedef Math::Vector4<typename T::Type> Type; };
}
}}
namespace Corrade { namespace Utility {

10
src/MeshTools/CMakeLists.txt

@ -68,7 +68,10 @@ if(BUILD_STATIC_PIC)
endif()
target_link_libraries(MagnumMeshTools Magnum)
install(TARGETS MagnumMeshTools DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumMeshTools
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(FILES ${MagnumMeshTools_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/MeshTools)
if(BUILD_TESTS)
@ -82,7 +85,10 @@ if(BUILD_TESTS)
# On Windows we need to install first and then run the tests to avoid "DLL
# not found" hell, thus we need to install this too
if(WIN32 AND NOT CMAKE_CROSSCOMPILING)
install(TARGETS MagnumMeshToolsTestLib DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumMeshToolsTestLib
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
endif()
add_subdirectory(Test)

2
src/MeshTools/CompressIndices.cpp

@ -81,7 +81,7 @@ void compressIndices(Mesh& mesh, Buffer& buffer, Buffer::Usage usage, const std:
mesh.setIndexCount(indices.size())
.setIndexBuffer(buffer, 0, indexType, *minmax.first, *minmax.second);
buffer.setData(indexCount*Mesh::indexSize(indexType), data, usage);
buffer.setData({data, indexCount*Mesh::indexSize(indexType)}, usage);
delete[] data;
}

2
src/MeshTools/Interleave.h

@ -64,7 +64,7 @@ class Interleave {
operator()(attributes...);
mesh.setVertexCount(_attributeCount);
buffer.setData(_attributeCount*_stride, _data, usage);
buffer.setData({_data, _attributeCount*_stride}, usage);
delete[] _data;
}

16
src/Platform/AbstractXApplication.cpp

@ -27,6 +27,7 @@
#include <Utility/utilities.h>
#include "Context.h"
#include "Platform/Implementation/AbstractContextHandler.h"
#define None 0L // redef Xlib nonsense
@ -37,21 +38,21 @@ namespace Magnum { namespace Platform {
/** @todo Delegating constructor when support for GCC 4.6 is dropped */
AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments&, const Configuration& configuration): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) {
AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments&, const Configuration& configuration): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) {
createContext(configuration);
}
#ifndef DOXYGEN_GENERATING_OUTPUT
AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments&): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) {
AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments&): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) {
/* GCC 4.5 can't handle {} here (wtf) */
createContext(Configuration());
}
#endif
#ifndef CORRADE_GCC45_COMPATIBILITY
AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments&, std::nullptr_t)
AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments&, std::nullptr_t)
#else
AbstractXApplication::AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments&, void*)
AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments&, void*)
#endif
: contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) {}
@ -115,13 +116,14 @@ AbstractXApplication::~AbstractXApplication() {
XCloseDisplay(display);
}
void AbstractXApplication::swapBuffers() {
contextHandler->swapBuffers();
}
int AbstractXApplication::exec() {
/* Show window */
XMapWindow(display, window);
/* Call viewportEvent for the first time */
viewportEvent(viewportSize);
while(!(flags & Flag::Exit)) {
XEvent event;

113
src/Platform/AbstractXApplication.h

@ -25,7 +25,7 @@
*/
/** @file
* @brief Class Magnum::Platform::AbstractXApplication
* @brief Class @ref Magnum::Platform::AbstractXApplication
*/
#include <Containers/EnumSet.h>
@ -40,7 +40,6 @@
#undef Always
#include "Math/Vector2.h"
#include "AbstractContextHandler.h"
namespace Magnum {
@ -48,11 +47,17 @@ class Context;
namespace Platform {
namespace Implementation {
template<class, class, class> class AbstractContextHandler;
}
/** @nosubgrouping
@brief Base for X11-based applications
Supports keyboard and mouse handling. See @ref platform for brief introduction.
@note Not meant to be used directly, see subclasses.
@note Not meant to be used directly, see @ref GlxApplication and
@ref XEglApplication subclasses.
*/
class AbstractXApplication {
public:
@ -68,38 +73,6 @@ class AbstractXApplication {
class MouseEvent;
class MouseMoveEvent;
/**
* @brief Default constructor
* @param contextHandler OpenGL context handler
* @param arguments Application arguments
* @param configuration %Configuration
*
* Creates application with default or user-specified configuration.
* See Configuration for more information. The program exits if the
* context cannot be created, see below for an alternative.
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
explicit AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments& arguments, const Configuration& configuration = Configuration());
#else
/* To avoid "invalid use of incomplete type" */
explicit AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments& arguments, const Configuration& configuration);
explicit AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments& arguments);
#endif
/**
* @brief Constructor
* @param contextHandler OpenGL context handler
* @param arguments Application arguments
*
* Unlike above, the context is not created and must be created later
* with createContext() or tryCreateContext().
*/
#ifndef CORRADE_GCC45_COMPATIBILITY
explicit AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments& arguments, std::nullptr_t);
#else
explicit AbstractXApplication(AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments& arguments, void*);
#endif
/**
* @brief Execute main loop
* @return Value for returning from `main()`.
@ -131,7 +104,7 @@ class AbstractXApplication {
virtual void drawEvent() = 0;
/** @copydoc GlutApplication::swapBuffers() */
void swapBuffers() { contextHandler->swapBuffers(); }
void swapBuffers();
/** @copydoc GlutApplication::redraw() */
void redraw() { flags |= Flag::Redraw; }
@ -161,6 +134,22 @@ class AbstractXApplication {
/*@}*/
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#else
protected:
#endif
/* These two are split to avoid "invalid use of incomplete type" when
using default argument for configuration */
explicit AbstractXApplication(Implementation::AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments& arguments, const Configuration& configuration);
explicit AbstractXApplication(Implementation::AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments& arguments);
#ifndef CORRADE_GCC45_COMPATIBILITY
explicit AbstractXApplication(Implementation::AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments& arguments, std::nullptr_t);
#else
explicit AbstractXApplication(Implementation::AbstractContextHandler<Display*, VisualID, Window>* contextHandler, const Arguments& arguments, void*);
#endif
private:
enum class Flag: unsigned int {
Redraw = 1 << 0,
@ -174,7 +163,7 @@ class AbstractXApplication {
Window window;
Atom deleteWindow;
AbstractContextHandler<Display*, VisualID, Window>* contextHandler;
Implementation::AbstractContextHandler<Display*, VisualID, Window>* contextHandler;
Context* c;
@ -261,9 +250,31 @@ class AbstractXApplication::InputEvent {
Alt = Mod1Mask, /**< Alt */
AltGr = Mod5Mask, /**< AltGr */
LeftButton = Button1Mask, /**< Left mouse button */
MiddleButton = Button2Mask, /**< Middle mouse button */
RightButton = Button3Mask, /**< Right mouse button */
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief Button::Left
* @deprecated Use @ref Magnum::Platform::AbstractXApplication::InputEvent::buttons() "buttons()"
* and @ref Magnum::Platform::AbstractXApplication::InputEvent::Button::Left "Button::Left"
* instead.
*/
LeftButton = Button1Mask,
/**
* @copybrief Button::Middle
* @deprecated Use @ref Magnum::Platform::AbstractXApplication::InputEvent::buttons() "buttons()"
* and @ref Magnum::Platform::AbstractXApplication::InputEvent::Button::Middle "Button::Middle"
* instead.
*/
MiddleButton = Button2Mask,
/**
* @copybrief Button::Right
* @deprecated Use @ref Magnum::Platform::AbstractXApplication::InputEvent::buttons() "buttons()"
* and @ref Magnum::Platform::AbstractXApplication::InputEvent::Button::Right "Button::Right"
* instead.
*/
RightButton = Button3Mask,
#endif
CapsLock = LockMask, /**< Caps lock */
NumLock = Mod2Mask /**< Num lock */
@ -276,6 +287,24 @@ class AbstractXApplication::InputEvent {
*/
typedef Containers::EnumSet<Modifier, unsigned int> Modifiers;
/**
* @brief Mouse button
*
* @see @ref Buttons, @ref buttons()
*/
enum class Button: unsigned int {
Left = Button1Mask, /**< Left button */
Middle = Button2Mask, /**< Middle button */
Right = Button3Mask /**< Right button */
};
/**
* @brief Set of mouse buttons
*
* @see @ref buttons()
*/
typedef Containers::EnumSet<Button, unsigned int> Buttons;
/** @copydoc GlutApplication::InputEvent::setAccepted() */
void setAccepted(bool accepted = true) { _accepted = accepted; }
@ -285,6 +314,9 @@ class AbstractXApplication::InputEvent {
/** @brief Modifiers */
constexpr Modifiers modifiers() const { return _modifiers; }
/** @brief Mouse buttons */
constexpr Buttons buttons() const { return Button(static_cast<unsigned int>(_modifiers)); }
#ifndef DOXYGEN_GENERATING_OUTPUT
protected:
constexpr InputEvent(Modifiers modifiers): _modifiers(modifiers), _accepted(false) {}
@ -306,6 +338,7 @@ AbstractXApplication::InputEvent::~InputEvent() = default;
#endif
CORRADE_ENUMSET_OPERATORS(AbstractXApplication::InputEvent::Modifiers)
CORRADE_ENUMSET_OPERATORS(AbstractXApplication::InputEvent::Buttons)
/**
@brief Key event

57
src/Platform/CMakeLists.txt

@ -22,16 +22,16 @@
# DEALINGS IN THE SOFTWARE.
#
set(MagnumPlatform_HEADERS AbstractContextHandler.h)
install(FILES ${MagnumPlatform_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
# GLUT application
if(WITH_GLUTAPPLICATION)
find_package(GLUT)
if(GLUT_FOUND)
add_library(MagnumGlutApplication STATIC GlutApplication.cpp)
install(FILES GlutApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumGlutApplication DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumGlutApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
else()
message(FATAL_ERROR "GLUT library, required by GlutApplication, was not found. Set WITH_GLUTAPPLICATION to OFF to skip building it.")
endif()
@ -44,7 +44,10 @@ if(WITH_SDL2APPLICATION)
include_directories(${SDL2_INCLUDE_DIR})
add_library(MagnumSdl2Application STATIC Sdl2Application.cpp)
install(FILES Sdl2Application.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumSdl2Application DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumSdl2Application
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
else()
message(FATAL_ERROR "SDL2 library, required by Sdl2Application, was not found. Set WITH_SDL2APPLICATION to OFF to skip building it.")
endif()
@ -58,7 +61,10 @@ if(WITH_NACLAPPLICATION)
add_library(MagnumNaClApplication STATIC NaClApplication.cpp)
install(FILES NaClApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumNaClApplication DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumNaClApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
endif()
# Windowless NaCl application
@ -69,12 +75,20 @@ if(WITH_WINDOWLESSNACLAPPLICATION)
add_library(MagnumWindowlessNaClApplication STATIC WindowlessNaClApplication.cpp)
install(FILES WindowlessNaClApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumWindowlessNaClApplication DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumWindowlessNaClApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
endif()
# JavaScript and CSS stuff for NaCl
if(WITH_NACLAPPLICATION OR WITH_WINDOWLESSNACLAPPLICATION)
install(FILES NaClApplication.js NaClApplication.css DESTINATION ${MAGNUM_DATA_INSTALL_DIR})
install(FILES NaClApplication.js WebApplication.css DESTINATION ${MAGNUM_DATA_INSTALL_DIR})
endif()
# JavaScript and CSS stuff for Emscripten
if(WITH_SDL2APPLICATION AND CORRADE_TARGET_EMSCRIPTEN)
install(FILES EmscriptenApplication.js WebApplication.css DESTINATION ${MAGNUM_DATA_INSTALL_DIR})
endif()
# GLX application
@ -83,9 +97,13 @@ if(WITH_GLXAPPLICATION)
set(NEED_GLXCONTEXT 1)
add_library(MagnumGlxApplication STATIC
$<TARGET_OBJECTS:MagnumAbstractXApplication>
$<TARGET_OBJECTS:MagnumGlxContextHandler>)
$<TARGET_OBJECTS:MagnumGlxContextHandler>
GlxApplication.cpp)
install(FILES GlxApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumGlxApplication DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumGlxApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
endif()
# X/EGL application
@ -94,9 +112,13 @@ if(WITH_XEGLAPPLICATION)
set(NEED_EGLCONTEXT 1)
add_library(MagnumXEglApplication STATIC
$<TARGET_OBJECTS:MagnumAbstractXApplication>
$<TARGET_OBJECTS:MagnumEglContextHandler>)
$<TARGET_OBJECTS:MagnumEglContextHandler>
XEglApplication.cpp)
install(FILES XEglApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumXEglApplication DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumXEglApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
endif()
if(WITH_WINDOWLESSGLXAPPLICATION OR NEED_ABSTRACTXAPPLICATION)
@ -112,7 +134,10 @@ if(WITH_WINDOWLESSGLXAPPLICATION)
# X11 macros are a mess, disable warnings for C-style casts
set_target_properties(MagnumWindowlessGlxApplication PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast")
install(FILES WindowlessGlxApplication.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
install(TARGETS MagnumWindowlessGlxApplication DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumWindowlessGlxApplication
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
endif()
# Abstract X application
@ -125,10 +150,9 @@ endif()
# GLX context
if(NEED_GLXCONTEXT)
add_library(MagnumGlxContextHandler OBJECT GlxContextHandler.cpp)
add_library(MagnumGlxContextHandler OBJECT Implementation/GlxContextHandler.cpp)
# X11 macros are a mess, disable warnings for C-style casts
set_target_properties(MagnumGlxContextHandler PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast")
install(FILES GlxContextHandler.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
endif()
# EGL context
@ -137,10 +161,9 @@ if(NEED_EGLCONTEXT)
if(NOT EGL_FOUND)
message(FATAL_ERROR "EGL library, required by some window contexts, was not found. Set WITH_*EGL*APPLICATION to OFF to skip building them.")
endif()
add_library(MagnumEglContextHandler OBJECT EglContextHandler.cpp)
add_library(MagnumEglContextHandler OBJECT Implementation/EglContextHandler.cpp)
# X11 macros are a mess, disable warnings for C-style casts
set_target_properties(MagnumEglContextHandler PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast")
install(FILES EglContextHandler.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Platform)
endif()
# Magnum Info

44
src/Platform/EmscriptenApplication.js

@ -0,0 +1,44 @@
var Module = {
preRun: [],
postRun: [],
printErr: function(message) {
console.error(Array.prototype.slice.call(arguments).join(' '));
},
print: function(message) {
console.log(Array.prototype.slice.call(arguments).join(' '));
},
canvas: document.getElementById('module'),
setStatus: function(message) {
var status = document.getElementById('status');
if(status) status.innerHTML = message;
},
setStatusDescription: function(message) {
var statusDescription = document.getElementById('statusDescription');
if(statusDescription) statusDescription.innerHTML = message;
},
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
if(left) {
Module.setStatus('Downloading...');
Module.setStatusDescription((this.totalDependencies - left) + '/' + this.totalDependencies);
} else {
Module.setStatus('Download complete');
Module.setStatusDescription('');
}
}
};
Module.setStatus('Downloading...');
Module.canvas.addEventListener('contextmenu', function(event) {
event.preventDefault();
}, true);

2
src/Platform/GlutApplication.cpp

@ -111,7 +111,7 @@ void GlutApplication::staticMouseEvent(int button, int state, int x, int y) {
}
void GlutApplication::staticMouseMoveEvent(int x, int y) {
MouseMoveEvent e({x, y});
MouseMoveEvent e({x, y}, MouseMoveEvent::Button::Left);
instance->mouseMoveEvent(e);
}

60
src/Platform/GlutApplication.h

@ -25,7 +25,7 @@
*/
/** @file
* @brief Class Magnum::Platform::GlutApplication
* @brief Class @ref Magnum::Platform::GlutApplication
*/
#include <string>
@ -45,23 +45,32 @@ namespace Platform {
/** @nosubgrouping
@brief GLUT application
Supports keyboard handling for limited subset of keys, mouse handling with
support for changing cursor and mouse tracking and warping. See @ref platform
for brief introduction.
Application using GLUT toolkit. Supports keyboard handling for limited subset
of keys, mouse handling with support for changing cursor and mouse tracking and
warping.
This application library is available only on desktop OpenGL (Linux, Windows,
OS X). It depends on **GLUT** library and is built if `WITH_GLUTAPPLICATION` is
enabled in CMake. To use it, you need to request `%GlutApplication` component
in CMake, add `${MAGNUM_GLUTAPPLICATION_INCLUDE_DIRS}` to include path and link
to `${MAGNUM_GLUTAPPLICATION_LIBRARIES}`. If no other application is requested,
you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building, @ref cmake and @ref platform for more information.
@section GlutApplication-usage Usage
You need to implement at least drawEvent() and viewportEvent() to be able to
draw on the screen. The subclass can be then used directly in `main()` -- see
convenience macro MAGNUM_GLUTAPPLICATION_MAIN().
You need to implement at least @ref drawEvent() and @ref viewportEvent() to be
able to draw on the screen. The subclass can be then used directly in `main()`
-- see convenience macro @ref MAGNUM_GLUTAPPLICATION_MAIN().
@code
class MyApplication: public Magnum::Platform::GlutApplication {
class MyApplication: public Platform::GlutApplication {
// implement required methods...
};
MAGNUM_GLUTAPPLICATION_MAIN(MyApplication)
@endcode
If no other application header is included this class is also aliased to
If no other application header is included, this class is also aliased to
`Platform::Application` and the macro is aliased to `MAGNUM_APPLICATION_MAIN()`
to simplify porting.
*/
@ -148,6 +157,11 @@ class GlutApplication {
* Called when window size changes. You should pass the new size to
* DefaultFramebuffer::setViewport() and possibly elsewhere (cameras,
* other framebuffers...).
*
* Note that this function might not get called at all if the window
* size doesn't change. You are responsible for configuring the initial
* state yourself, viewport of default framebuffer can be retrieved
* from @ref DefaultFramebuffer::viewport().
*/
virtual void viewportEvent(const Vector2i& size) = 0;
@ -474,13 +488,37 @@ class GlutApplication::MouseMoveEvent: public GlutApplication::InputEvent {
friend class GlutApplication;
public:
/**
* @brief Mouse button
*
* @see Buttons, buttons()
*/
enum class Button: UnsignedByte {
/**
* Any button. Note that GLUT doesn't differentiate between mouse
* buttons when firing the event.
*/
Left = 1
};
/**
* @brief Set of mouse buttons
*
* @see buttons()
*/
typedef Containers::EnumSet<Button, UnsignedByte> Buttons;
/** @brief Position */
constexpr Vector2i position() const { return _position; }
/** @brief Mouse buttons */
constexpr Buttons buttons() const { return _buttons; }
private:
constexpr MouseMoveEvent(const Vector2i& position): _position(position) {}
constexpr MouseMoveEvent(const Vector2i& position, Buttons buttons): _position(position), _buttons(buttons) {}
const Vector2i _position;
const Buttons _buttons;
};
/** @hideinitializer
@ -514,6 +552,8 @@ typedef GlutApplication Application;
#endif
#endif
CORRADE_ENUMSET_OPERATORS(GlutApplication::MouseMoveEvent::Buttons)
/* Implementations for inline functions with unused parameters */
inline void GlutApplication::keyPressEvent(KeyEvent&) {}
inline void GlutApplication::mousePressEvent(MouseEvent&) {}

35
src/Platform/GlxApplication.cpp

@ -0,0 +1,35 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "GlxApplication.h"
#include "Platform/Implementation/GlxContextHandler.h"
namespace Magnum { namespace Platform {
GlxApplication::GlxApplication(const Arguments& arguments, const Configuration& configuration): AbstractXApplication(new Implementation::GlxContextHandler, arguments, configuration) {}
GlxApplication::GlxApplication(const Arguments& arguments, std::nullptr_t): AbstractXApplication(new Implementation::GlxContextHandler, arguments, nullptr) {}
}}

34
src/Platform/GlxApplication.h

@ -25,47 +25,55 @@
*/
/** @file
* @brief Class Magnum::Platform::GlxApplication
* @brief Class @ref Magnum::Platform::GlxApplication
*/
#include "AbstractXApplication.h"
#include "GlxContextHandler.h"
#include "Platform/AbstractXApplication.h"
namespace Magnum { namespace Platform {
/**
@brief GLX application
Uses GlxContextHandler. See @ref platform for brief introduction.
Application using pure X11 and GLX. Supports keyboard and mouse handling.
This application library is available on desktop OpenGL and
@ref MAGNUM_TARGET_DESKTOP_GLES "OpenGL ES emulation on desktop" on Linux. It
depends on **X11** library and is built if `WITH_GLXAPPLICATION` is enabled in
CMake. To use it, you need to request `%GlxApplication` component in CMake, add
`${MAGNUM_GLXAPPLICATION_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_GLXAPPLICATION_LIBRARIES}`. If no other application is requested, you
can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building, @ref cmake and @ref platform for more information.
@section GlxApplication-usage Usage
You need to implement at least drawEvent() and viewportEvent() to be able to
draw on the screen. The subclass can be then used directly in `main()` - see
convenience macro MAGNUM_GLXAPPLICATION_MAIN().
You need to implement at least @ref drawEvent() and @ref viewportEvent() to be
able to draw on the screen. The subclass can be then used directly in `main()`
-- see convenience macro @ref MAGNUM_GLXAPPLICATION_MAIN().
@code
class MyApplication: public Magnum::Platform::GlxApplication {
class MyApplication: public Platform::GlxApplication {
// implement required methods...
};
MAGNUM_GLXAPPLICATION_MAIN(MyApplication)
@endcode
If no other application header is included this class is also aliased to
If no other application header is included, this class is also aliased to
`Platform::Application` and the macro is aliased to `MAGNUM_APPLICATION_MAIN()`
to simplify porting.
*/
class GlxApplication: public AbstractXApplication {
public:
/** @copydoc GlutApplication::GlutApplication(const Arguments&, const Configuration&) */
explicit GlxApplication(const Arguments& arguments, const Configuration& configuration = Configuration()): AbstractXApplication(new GlxContextHandler, arguments, configuration) {}
explicit GlxApplication(const Arguments& arguments, const Configuration& configuration = Configuration());
/** @copydoc GlutApplication::GlutApplication(const Arguments&, std::nullptr_t) */
#ifndef CORRADE_GCC45_COMPATIBILITY
explicit GlxApplication(const Arguments& arguments, std::nullptr_t)
explicit GlxApplication(const Arguments& arguments, std::nullptr_t);
#else
explicit GlxApplication(const Arguments& arguments, void*)
explicit GlxApplication(const Arguments& arguments, void*);
#endif
: AbstractXApplication(new GlxContextHandler, arguments, nullptr) {}
protected:
/* Nobody will need to have (and delete) GlxApplication*, thus this is

12
src/Platform/AbstractContextHandler.h → src/Platform/Implementation/AbstractContextHandler.h

@ -1,5 +1,5 @@
#ifndef Magnum_Platform_AbstractContextHandler_h
#define Magnum_Platform_AbstractContextHandler_h
#ifndef Magnum_Platform_Implementation_AbstractContextHandler_h
#define Magnum_Platform_Implementation_AbstractContextHandler_h
/*
This file is part of Magnum.
@ -24,11 +24,7 @@
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class Magnum::Platform::AbstractContextHandler
*/
namespace Magnum { namespace Platform {
namespace Magnum { namespace Platform { namespace Implementation {
/**
@brief Base for OpenGL context handlers
@ -65,6 +61,6 @@ template<class Display, class VisualId, class Window> class AbstractContextHandl
template<class Display, class VisualId, class Window> inline AbstractContextHandler<Display, VisualId, Window>::AbstractContextHandler() = default;
}}
}}}
#endif

4
src/Platform/EglContextHandler.cpp → src/Platform/Implementation/EglContextHandler.cpp

@ -28,7 +28,7 @@
#include "Context.h"
namespace Magnum { namespace Platform {
namespace Magnum { namespace Platform { namespace Implementation {
EglContextHandler::~EglContextHandler() {
eglDestroyContext(display, context);
@ -131,4 +131,4 @@ const char* EglContextHandler::errorString(EGLint error) {
return {};
}
}}
}}}

12
src/Platform/EglContextHandler.h → src/Platform/Implementation/EglContextHandler.h

@ -1,5 +1,5 @@
#ifndef Magnum_Platform_EglContextHandler_h
#define Magnum_Platform_EglContextHandler_h
#ifndef Magnum_Platform_Implementation_EglContextHandler_h
#define Magnum_Platform_Implementation_EglContextHandler_h
/*
This file is part of Magnum.
@ -24,10 +24,6 @@
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class Magnum::Platform::EglContextHandler
*/
#include "Magnum.h"
#ifndef SUPPORT_X11
@ -42,7 +38,7 @@
#include "corradeCompatibility.h"
namespace Magnum { namespace Platform {
namespace Magnum { namespace Platform { namespace Implementation {
#ifndef DOXYGEN_GENERATING_OUTPUT
/* EGL returns visual ID as int, but Xorg expects long unsigned int */
@ -83,6 +79,6 @@ class EglContextHandler: public AbstractContextHandler<EGLNativeDisplayType, Vis
EGLContext context;
};
}}
}}}
#endif

4
src/Platform/GlxContextHandler.cpp → src/Platform/Implementation/GlxContextHandler.cpp

@ -31,7 +31,7 @@
#define None 0L // redef Xlib nonsense
namespace Magnum { namespace Platform {
namespace Magnum { namespace Platform { namespace Implementation {
VisualID GlxContextHandler::getVisualId(Display* nativeDisplay) {
display = nativeDisplay;
@ -97,4 +97,4 @@ GlxContextHandler::~GlxContextHandler() {
glXDestroyContext(display, context);
}
}}
}}}

12
src/Platform/GlxContextHandler.h → src/Platform/Implementation/GlxContextHandler.h

@ -1,5 +1,5 @@
#ifndef Magnum_Platform_GlxContextHandler_h
#define Magnum_Platform_GlxContextHandler_h
#ifndef Magnum_Platform_Implementation_GlxContextHandler_h
#define Magnum_Platform_Implementation_GlxContextHandler_h
/*
This file is part of Magnum.
@ -24,10 +24,6 @@
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class Magnum::Platform::GlxContextHandler
*/
#include "OpenGL.h"
#include <GL/glx.h>
/* undef Xlib nonsense to avoid conflicts */
@ -39,7 +35,7 @@
#include "corradeCompatibility.h"
namespace Magnum { namespace Platform {
namespace Magnum { namespace Platform { namespace Implementation {
/**
@brief GLX context
@ -70,6 +66,6 @@ class GlxContextHandler: public AbstractContextHandler<Display*, VisualID, Windo
GlxContextHandler::GlxContextHandler() = default;
}}
}}}
#endif

12
src/Platform/NaClApplication.cpp

@ -116,9 +116,6 @@ bool NaClApplication::tryCreateContext(const Configuration& configuration) {
RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE|PP_INPUTEVENT_CLASS_WHEEL);
RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
/* Make sure viewportEvent() is called for first time */
flags |= Flag::ViewportUpdated;
c = new Context;
return true;
}
@ -171,14 +168,7 @@ void NaClApplication::DidChangeView(const pp::View& view) {
/* Canvas resized */
if(viewportSize != size) {
graphics->ResizeBuffers(size.x(), size.y());
viewportSize = size;
flags |= Flag::ViewportUpdated;
}
/* Update viewport, if changed */
if(flags & Flag::ViewportUpdated) {
flags &= ~Flag::ViewportUpdated;
viewportEvent(size);
viewportEvent(viewportSize = size);
}
drawEvent();

124
src/Platform/NaClApplication.h

@ -25,7 +25,7 @@
*/
/** @file
* @brief Class Magnum::Platform::NaClApplication
* @brief Class @ref Magnum::Platform::NaClApplication
*/
#include <string>
@ -53,21 +53,30 @@ namespace Magnum { namespace Platform {
@brief NaCl application
Application running in [Google Chrome Native Client](https://developers.google.com/native-client/).
Supports keyboard and mouse handling. See @ref platform for brief introduction.
Supports keyboard and mouse handling.
This application library is available only in @ref CORRADE_TARGET_NACL "Native Client".
It is built if `WITH_NACLAPPLICATION` is enabled in CMake. To use it, you need
to request `%NaClApplication` component in CMake, add
`${MAGNUM_NACLAPPLICATION_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_NACLAPPLICATION_LIBRARIES}`. If no other application is requested,
you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building, @ref cmake and @ref platform for more information.
@section NaClApplication-usage Usage
You need to implement at least drawEvent() and viewportEvent() to be able to
draw on the screen. The subclass must be then registered to NaCl API using
MAGNUM_NACLAPPLICATION_MAIN() macro.
You need to implement at least @ref drawEvent() and @ref viewportEvent() to be
able to draw on the screen. The subclass must be then registered to NaCl API
using @ref MAGNUM_NACLAPPLICATION_MAIN() macro.
@code
class MyApplication: public Magnum::Platform::NaClApplication {
class MyApplication: public Platform::NaClApplication {
// implement required methods...
};
MAGNUM_NACLAPPLICATION_MAIN(MyApplication)
@endcode
If no other application header is included this class is also aliased to
If no other application header is included, this class is also aliased to
`Platform::Application` and the macro is aliased to `MAGNUM_APPLICATION_MAIN()`
to simplify porting.
@ -75,26 +84,26 @@ to simplify porting.
You need to provide HTML markup for your application. Template one is below,
you can modify it to your liking. The markup references two files,
`NaClApplication.js` and `NaClApplication.css`, both are in `Platform/`
`NaClApplication.js` and `WebApplication.css`, both are in `Platform/`
directory in the source tree and are also installed into `share/magnum/` inside
your NaCl toolchain.
your NaCl toolchain. Change `&lt;application&gt;` to name of your executable.
@code
<!DOCTYPE html>
<html>
<head>
<title>Magnum NaCl Application</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="NaClApplication.css" />
</head>
<body>
<h1>Magnum NaCl Application</h1>
<div id="listener">
<script type="text/javascript" src="NaClApplication.js"></script>
<embed id="module" type="application/x-nacl" src="application.nmf" />
<div id="status">Initialization...</div>
<div id="statusDescription"></div>
</div>
</body>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Magnum NaCl Application</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="WebApplication.css" />
</head>
<body>
<h1>Magnum NaCl Application</h1>
<div id="listener">
<embed id="module" type="application/x-nacl" src="<application>.nmf" />
<div id="status">Initialization...</div>
<div id="statusDescription" />
<script src="NaClApplication.js"></script>
</div>
</body>
</html>
@endcode
@ -106,12 +115,12 @@ The CSS file contains rudimentary style to avoid eye bleeding.
The `&lt;embed&gt;` file references NMF file which you need to provide too. If
you target @ref CORRADE_TARGET_NACL_NEWLIB "newlib", the file is pretty simple,
for example:
for example (change `&lt;application&gt;` to name of your executable):
@code
{
"program": {
"x86-32": {"url": "application-x86-32.nexe"},
"x86-64": {"url": "application-x86-64.nexe"}
"x86-32": {"url": "<application>-x86-32.nexe"},
"x86-64": {"url": "<application>-x86-64.nexe"}
}
}
@endcode
@ -265,12 +274,11 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public
struct ConsoleDebugOutput;
enum class Flag: UnsignedByte {
ViewportUpdated = 1 << 0,
SwapInProgress = 1 << 1,
Redraw = 1 << 2,
FullscreenSwitchInProgress = 1 << 3,
WillBeFullscreen = 1 << 4,
MouseLocked = 1 << 5
SwapInProgress = 1 << 0,
Redraw = 1 << 1,
FullscreenSwitchInProgress = 1 << 2,
WillBeFullscreen = 1 << 3,
MouseLocked = 1 << 4
};
typedef Containers::EnumSet<Flag, UnsignedByte> Flags;
@ -376,9 +384,31 @@ class NaClApplication::InputEvent {
Alt = PP_INPUTEVENT_MODIFIER_ALTKEY, /**< Alt */
Meta = PP_INPUTEVENT_MODIFIER_METAKEY, /**< Meta */
LeftButton = PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN, /**< Left mouse button */
MiddleButton = PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN, /**< Middle mouse button */
RightButton = PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN, /**< Right mouse button */
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief Button::Left
* @deprecated Use @ref Magnum::Platform::NaClApplication::InputEvent::buttons() "buttons()"
* and @ref Magnum::Platform::NaClApplication::InputEvent::Button::Left "Button::Left"
* instead.
*/
LeftButton = PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN,
/**
* @copybrief Button::Middle
* @deprecated Use @ref Magnum::Platform::NaClApplication::InputEvent::buttons() "buttons()"
* and @ref Magnum::Platform::NaClApplication::InputEvent::Button::Middle "Button::Middle"
* instead.
*/
MiddleButton = PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN,
/**
* @copybrief Button::Right
* @deprecated Use @ref Magnum::Platform::NaClApplication::InputEvent::buttons() "buttons()"
* and @ref Magnum::Platform::NaClApplication::InputEvent::Button::Right "Button::Right"
* instead.
*/
RightButton = PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN,
#endif
CapsLock = PP_INPUTEVENT_MODIFIER_CAPSLOCKKEY, /**< Caps lock */
NumLock = PP_INPUTEVENT_MODIFIER_NUMLOCKKEY /**< Num lock */
@ -391,9 +421,30 @@ class NaClApplication::InputEvent {
*/
typedef Containers::EnumSet<Modifier, std::uint32_t> Modifiers;
/**
* @brief Mouse button
*
* @see @ref Buttons, @ref buttons()
*/
enum class Button: std::uint32_t {
Left = PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN, /**< Left button */
Middle = PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN, /**< Middle button */
Right = PP_INPUTEVENT_MODIFIER_RIGHTBUTTONDOWN /**< Right button */
};
/**
* @brief Set of mouse buttons
*
* @see @ref buttons()
*/
typedef Containers::EnumSet<Button, std::uint32_t> Buttons;
/** @brief Modifiers */
constexpr Modifiers modifiers() const { return _modifiers; }
/** @brief Mouse buttons */
constexpr Buttons buttons() const { return Buttons(_modifiers); }
/**
* @brief Set event as accepted
*
@ -625,6 +676,7 @@ typedef NaClApplication Application;
#endif
CORRADE_ENUMSET_OPERATORS(NaClApplication::InputEvent::Modifiers)
CORRADE_ENUMSET_OPERATORS(NaClApplication::InputEvent::Buttons)
/* Implementations for inline functions with unused parameters */
inline void NaClApplication::keyPressEvent(KeyEvent&) {}

74
src/Platform/Sdl2Application.cpp

@ -24,6 +24,10 @@
#include "Sdl2Application.h"
#ifdef CORRADE_TARGET_EMSCRIPTEN
#include <emscripten/emscripten.h>
#endif
#include "Context.h"
namespace Magnum { namespace Platform {
@ -46,6 +50,13 @@ Sdl2Application::InputEvent::Modifiers fixedModifiers(Uint16 mod) {
}
#ifdef CORRADE_TARGET_EMSCRIPTEN
Sdl2Application* Sdl2Application::instance = nullptr;
void Sdl2Application::staticMainLoop() {
instance->mainLoop();
}
#endif
/** @todo Delegating constructor when support for GCC 4.6 is dropped */
Sdl2Application::Sdl2Application(const Arguments&, const Configuration& configuration): context(nullptr), flags(Flag::Redraw) {
@ -72,6 +83,11 @@ Sdl2Application::Sdl2Application(const Arguments&, void*)
}
void Sdl2Application::initialize() {
#ifdef CORRADE_TARGET_EMSCRIPTEN
CORRADE_ASSERT(!instance, "Platform::Sdl2Application::Sdl2Application(): the instance is already created", );
instance = this;
#endif
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
Error() << "Cannot initialize SDL.";
std::exit(1);
@ -100,6 +116,8 @@ bool Sdl2Application::tryCreateContext(const Configuration& configuration) {
Uint32 flags(configuration.flags());
if(!(configuration.flags() & Configuration::Flag::Hidden)) flags |= SDL_WINDOW_SHOWN;
/** @todo Remove when Emscripten has proper SDL2 support */
#ifndef CORRADE_TARGET_EMSCRIPTEN
if(!(window = SDL_CreateWindow(configuration.title().data(),
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
configuration.size().x(), configuration.size().y(),
@ -111,32 +129,53 @@ bool Sdl2Application::tryCreateContext(const Configuration& configuration) {
window = nullptr;
return false;
}
/* Push resize event, so viewportEvent() is called at startup */
SDL_Event* sizeEvent = new SDL_Event;
sizeEvent->type = SDL_WINDOWEVENT;
sizeEvent->window.event = SDL_WINDOWEVENT_RESIZED;
sizeEvent->window.data1 = configuration.size().x();
sizeEvent->window.data2 = configuration.size().y();
SDL_PushEvent(sizeEvent);
#else
context = SDL_SetVideoMode(configuration.size().x(), configuration.size().y(), 24, SDL_OPENGL|SDL_HWSURFACE|SDL_DOUBLEBUF);
#endif
c = new Context;
return true;
}
void Sdl2Application::swapBuffers() {
#ifndef CORRADE_TARGET_EMSCRIPTEN
SDL_GL_SwapWindow(window);
#else
SDL_Flip(context);
#endif
}
Sdl2Application::~Sdl2Application() {
delete c;
#ifndef CORRADE_TARGET_EMSCRIPTEN
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
#else
SDL_FreeSurface(context);
CORRADE_INTERNAL_ASSERT(instance == this);
instance = nullptr;
#endif
SDL_Quit();
}
int Sdl2Application::exec() {
#ifndef CORRADE_TARGET_EMSCRIPTEN
while(!(flags & Flag::Exit)) mainLoop();
#else
emscripten_set_main_loop(staticMainLoop, 0, true);
#endif
return 0;
}
void Sdl2Application::exit() {
#ifndef CORRADE_TARGET_EMSCRIPTEN
flags |= Flag::Exit;
#else
emscripten_cancel_main_loop();
#endif
}
void Sdl2Application::mainLoop() {
SDL_Event event;
@ -172,13 +211,17 @@ void Sdl2Application::mainLoop() {
} break;
case SDL_MOUSEMOTION: {
MouseMoveEvent e({event.motion.x, event.motion.y}, {event.motion.xrel, event.motion.yrel});
MouseMoveEvent e({event.motion.x, event.motion.y}, {event.motion.xrel, event.motion.yrel}, static_cast<MouseMoveEvent::Button>(event.motion.state));
mouseMoveEvent(e);
break;
}
case SDL_QUIT:
#ifndef CORRADE_TARGET_EMSCRIPTEN
flags |= Flag::Exit;
#else
emscripten_cancel_main_loop();
#endif
return;
}
}
@ -186,12 +229,23 @@ void Sdl2Application::mainLoop() {
if(flags & Flag::Redraw) {
flags &= ~Flag::Redraw;
drawEvent();
} else SDL_WaitEvent(nullptr);
return;
}
#ifndef CORRADE_TARGET_EMSCRIPTEN
SDL_WaitEvent(nullptr);
#endif
}
void Sdl2Application::setMouseLocked(bool enabled) {
/** @todo Implement this in Emscripten */
#ifndef CORRADE_TARGET_EMSCRIPTEN
SDL_SetWindowGrab(window, enabled ? SDL_TRUE : SDL_FALSE);
SDL_SetRelativeMouseMode(enabled ? SDL_TRUE : SDL_FALSE);
#else
CORRADE_ASSERT(false, "Sdl2Application::setMouseLocked(): not implemented", );
static_cast<void>(enabled);
#endif
}
Sdl2Application::Configuration::Configuration(): _title("Magnum SDL2 Application"), _size(800, 600), _flags(Flag::Resizable), _sampleCount(0) {}

118
src/Platform/Sdl2Application.h

@ -25,9 +25,11 @@
*/
/** @file
* @brief Class Magnum::Platform::Sdl2Application
* @brief Class @ref Magnum::Platform::Sdl2Application
*/
#include <Containers/EnumSet.h>
#include "Math/Vector2.h"
#include "Magnum.h"
@ -36,7 +38,8 @@
#endif
#include <SDL.h>
#include <SDL_scancode.h>
#include <Corrade/Containers/EnumSet.h>
#include <Containers/EnumSet.h>
#include <Corrade.h>
namespace Magnum {
@ -47,24 +50,75 @@ namespace Platform {
/** @nosubgrouping
@brief SDL2 application
Application using [Simple DirectMedia Layer](www.libsdl.org/). Supports
keyboard and mouse handling. See @ref platform for brief introduction.
Application using [Simple DirectMedia Layer](www.libsdl.org/) toolkit. Supports
keyboard and mouse handling.
This application library is available on desktop OpenGL (Linux, Windows, OS X)
and in @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten". It depends on **SDL2**
library (Emscripten has it built in) and is built if `WITH_SDL2APPLICATION` is
enabled in CMake. To use it, you need to copy `FindSDL2.cmake` from `modules/`
directory in %Magnum source to `modules/` dir in your project (so CMake is able
to find SDL2), request `%Sdl2Application` component in CMake, add
`${MAGNUM_SDL2APPLICATION_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_SDL2APPLICATION_LIBRARIES}`. If no other application is requested,
you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building, @ref cmake and @ref platform for more information.
@section Sdl2Application-usage Usage
You need to implement at least drawEvent() and viewportEvent() to be able to
draw on the screen. The subclass can be then used directly in `main()` -- see
convenience macro MAGNUM_SDL2APPLICATION_MAIN().
You need to implement at least @ref drawEvent() and @ref viewportEvent() to be
able to draw on the screen. The subclass can be then used directly in `main()`
-- see convenience macro @ref MAGNUM_SDL2APPLICATION_MAIN().
@code
class MyApplication: public Magnum::Platform::Sdl2Application {
class MyApplication: public Platform::Sdl2Application {
// implement required methods...
};
MAGNUM_SDL2APPLICATION_MAIN(MyApplication)
@endcode
If no other application header is included this class is also aliased to
If no other application header is included, this class is also aliased to
`Platform::Application` and the macro is aliased to `MAGNUM_APPLICATION_MAIN()`
to simplify porting.
@section Sdl2Application-html Usage with Emscripten
If you are targetting @ref CORRADE_TARGET_EMSCRIPTEN "Emscripten", you need to
provide HTML markup for your application. Template one is below, you can modify
it to your liking. The markup references two files, `EmscriptenApplication.js`
and `WebApplication.css`, both are in `Platform/` directory in the source tree
and are also installed into `share/magnum/` inside your Emscripten toolchain.
Change `&lt;application&gt;` to name of your executable.
@code
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Magnum Emscripten Application</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="WebApplication.css" />
</head>
<body>
<h1>Magnum Emscripten Application</h1>
<div id="listener">
<canvas id="module"></canvas>
<div id="status">Initialization...</div>
<div id="statusDescription" />
<script src="EmscriptenApplication.js"></script>
<script async="async" src="<application>.js"></script>
</div>
</body>
</html>
@endcode
You can modify all the files to your liking, but the HTML file must contain at
least the `&lt;canvas&gt;` enclosed in listener `&lt;div&gt;`. The JavaScript
file contains event listeners which print loading status on the page. The
status displayed in the remaining two `&lt;div&gt;`s, if they are available.
The CSS file contains rudimentary style to avoid eye bleeding.
The application redirects @ref Corrade::Utility::Debug "Debug",
@ref Corrade::Utility::Warning "Warning" and @ref Corrade::Utility::Error "Error"
output to JavaScript console.
*/
class Sdl2Application {
public:
@ -100,7 +154,7 @@ class Sdl2Application {
int exec();
/** @brief Exit application main loop */
void exit() { flags |= Flag::Exit; }
void exit();
protected:
/* Nobody will need to have (and delete) Sdl2Application*, thus this is
@ -122,7 +176,7 @@ class Sdl2Application {
virtual void drawEvent() = 0;
/** @copydoc GlutApplication::swapBuffers() */
void swapBuffers() { SDL_GL_SwapWindow(window); }
void swapBuffers();
/** @copydoc GlutApplication::redraw() */
void redraw() { flags |= Flag::Redraw; }
@ -177,17 +231,28 @@ class Sdl2Application {
private:
enum class Flag: UnsignedByte {
Redraw = 1 << 0,
#ifndef CORRADE_TARGET_EMSCRIPTEN
Exit = 1 << 1
#endif
};
typedef Containers::EnumSet<Flag, UnsignedByte> Flags;
CORRADE_ENUMSET_FRIEND_OPERATORS(Flags)
#ifdef CORRADE_TARGET_EMSCRIPTEN
static Sdl2Application* instance;
static void staticMainLoop();
#endif
void initialize();
void mainLoop();
#ifndef CORRADE_TARGET_EMSCRIPTEN
SDL_Window* window;
SDL_GLContext context;
#else
SDL_Surface* context;
#endif
Context* c;
@ -482,8 +547,8 @@ class Sdl2Application::MouseEvent: public Sdl2Application::InputEvent {
Left = SDL_BUTTON_LEFT, /**< Left button */
Middle = SDL_BUTTON_MIDDLE, /**< Middle button */
Right = SDL_BUTTON_RIGHT, /**< Right button */
WheelUp = 4, /**< Wheel up */
WheelDown = 5 /**< Wheel down */
WheelUp = SDL_BUTTON_X1, /**< Wheel up */
WheelDown = SDL_BUTTON_X2 /**< Wheel down */
};
/** @brief Button */
@ -517,6 +582,26 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent {
friend class Sdl2Application;
public:
/**
* @brief Mouse button
*
* @see @ref Buttons, @ref buttons()
*/
enum class Button: Uint32 {
Left = SDL_BUTTON_LMASK, /**< Left button */
Middle = SDL_BUTTON_MMASK, /**< Middle button */
Right = SDL_BUTTON_RMASK, /**< Right button */
WheelUp = SDL_BUTTON_X1MASK, /**< Wheel up */
WheelDown = SDL_BUTTON_X2MASK /**< Wheel down */
};
/**
* @brief Set of mouse buttons
*
* @see @ref buttons()
*/
typedef Containers::EnumSet<Button, Uint32> Buttons;
/** @brief Position */
constexpr Vector2i position() const { return _position; }
@ -527,6 +612,9 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent {
*/
constexpr Vector2i relativePosition() const { return _relativePosition; }
/** @brief Mouse buttons */
constexpr Buttons buttons() const { return _buttons; }
/**
* @brief Modifiers
*
@ -535,10 +623,11 @@ class Sdl2Application::MouseMoveEvent: public Sdl2Application::InputEvent {
Modifiers modifiers();
private:
constexpr MouseMoveEvent(const Vector2i& position, const Vector2i& relativePosition): _position(position), _relativePosition(relativePosition), modifiersLoaded(false) {}
constexpr MouseMoveEvent(const Vector2i& position, const Vector2i& relativePosition, Buttons buttons): _position(position), _relativePosition(relativePosition), modifiersLoaded(false), _buttons(buttons) {}
const Vector2i _position, _relativePosition;
bool modifiersLoaded;
Buttons _buttons;
Modifiers _modifiers;
};
@ -574,6 +663,7 @@ typedef Sdl2Application Application;
#endif
CORRADE_ENUMSET_OPERATORS(Sdl2Application::InputEvent::Modifiers)
CORRADE_ENUMSET_OPERATORS(Sdl2Application::MouseMoveEvent::Buttons)
/* Implementations for inline functions with unused parameters */
inline void Sdl2Application::keyPressEvent(KeyEvent&) {}

0
src/Platform/NaClApplication.css → src/Platform/WebApplication.css

24
src/Platform/WindowlessGlxApplication.h

@ -25,7 +25,7 @@
*/
/** @file
* @brief Class Magnum::Platform::WindowlessGlxApplication
* @brief Class @ref Magnum::Platform::WindowlessGlxApplication
*/
#include <utility>
@ -39,27 +39,37 @@
#undef Always
#include "Magnum.h"
#include "Platform/AbstractContextHandler.h"
namespace Magnum { namespace Platform {
/**
@brief Windowless GLX application
See @ref platform for brief introduction.
Application for offscreen rendering using pure X11 and GLX.
This application library is available on desktop OpenGL and
@ref MAGNUM_TARGET_DESKTOP_GLES "OpenGL ES emulation on desktop" on Linux. It
depends on **X11** library and is built if `WITH_WINDOWLESSGLXAPPLICATION` is
enabled in CMake. To use it, you need to request `%WindowlessGlxApplication`
component in CMake, add `${MAGNUM_WINDOWLESSGLXAPPLICATION_INCLUDE_DIRS}` to
include path and link to `${MAGNUM_WINDOWLESSGLXAPPLICATION_LIBRARIES}`. If no
other windowless application is requested, you can also use generic
`${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building, @ref cmake and @ref platform for more information.
@section WindowlessGlxApplication-usage Usage
Place your code into exec(). The subclass can be then used directly in
`main()` -- see convenience macro MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN().
Place your code into @ref exec(). The subclass can be then used directly in
`main()` -- see convenience macro @ref MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN().
@code
class MyApplication: public Magnum::Platform::WindowlessGlxApplication {
class MyApplication: public Platform::WindowlessGlxApplication {
// implement required methods...
};
MAGNUM_WINDOWLESSGLXAPPLICATION_MAIN(MyApplication)
@endcode
If no other application header is included this class is also aliased to
If no other application header is included, this class is also aliased to
`Platform::WindowlessApplication` and the macro is aliased to
`MAGNUM_WINDOWLESSAPPLICATION_MAIN()` to simplify porting.
*/

24
src/Platform/WindowlessNaClApplication.h

@ -25,7 +25,7 @@
*/
/** @file
* @brief Class Magnum::Platform::WindowlessNaClApplication
* @brief Class @ref Magnum::Platform::WindowlessNaClApplication
*/
#include <string>
@ -50,21 +50,31 @@ namespace Magnum { namespace Platform {
/** @nosubgrouping
@brief Windowless NaCl application
Application running in [Google Chrome Native Client](https://developers.google.com/native-client/).
See @ref platform for brief introduction.
Application for offscreen rendering running in
[Google Chrome Native Client](https://developers.google.com/native-client/).
This application library is available only in @ref CORRADE_TARGET_NACL "Native Client".
It is built if `WITH_WINDOWLESSNACLAPPLICATION` is enabled in CMake. To use it,
you need to request `%WindowlessNaClApplication` component in CMake, add
`${MAGNUM_WINDOWLESSNACLAPPLICATION_INCLUDE_DIRS}` to include path and link to
`${MAGNUM_WINDOWLESSNACLAPPLICATION_LIBRARIES}`. If no other windowless
application is requested, you can also use generic
`${MAGNUM_WINDOWLESSAPPLICATION_INCLUDE_DIRS}` and
`${MAGNUM_WINDOWLESSAPPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building, @ref cmake and @ref platform for more information.
@section WindowlessNaClApplication-usage Usage
Place your code into exec(). The subclass must be then registered to NaCl API
using MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN() macro.
Place your code into @ref exec(). The subclass must be then registered to NaCl
API using @ref MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN() macro.
@code
class MyApplication: public Magnum::Platform::WindowlessNaClApplication {
class MyApplication: public Platform::WindowlessNaClApplication {
// implement required methods...
};
MAGNUM_WINDOWLESSNACLAPPLICATION_MAIN(MyApplication)
@endcode
If no other application header is included this class is also aliased to
If no other application header is included, this class is also aliased to
`Platform::WindowlessApplication` and the macro is aliased to
`MAGNUM_WINDOWLESSAPPLICATION_MAIN()` to simplify porting.

35
src/Platform/XEglApplication.cpp

@ -0,0 +1,35 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "XEglApplication.h"
#include "Platform/Implementation/EglContextHandler.h"
namespace Magnum { namespace Platform {
XEglApplication::XEglApplication(const Arguments& arguments, const Configuration& configuration): AbstractXApplication(new Implementation::EglContextHandler, arguments, configuration) {}
XEglApplication::XEglApplication(const Arguments& arguments, std::nullptr_t): AbstractXApplication(new Implementation::EglContextHandler, arguments, nullptr) {}
}}

35
src/Platform/XEglApplication.h

@ -25,47 +25,56 @@
*/
/** @file
* @brief Class Magnum::Platform::XEglApplication
* @brief Class @ref Magnum::Platform::XEglApplication
*/
#include "AbstractXApplication.h"
#include "EglContextHandler.h"
#include "Platform/AbstractXApplication.h"
namespace Magnum { namespace Platform {
/**
@brief X/EGL application
Uses EglContextHandler. See @ref platform for brief introduction.
Application using pure X11 and EGL. Supports keyboard and mouse handling.
This application library is available on both desktop OpenGL and
@ref MAGNUM_TARGET_GLES "OpenGL ES" on Linux. It depends on **X11** and **EGL**
libraries and is built if `WITH_XEGLAPPLICATION` is enabled in CMake. To use
it, you need to copy `FindEGL.cmake` from `modules/` directory in %Magnum
source to `modules/` dir in your project (so CMake is able to find EGL),
request `%XEglApplication` component in CMake, add `${MAGNUM_XEGLAPPLICATION_INCLUDE_DIRS}`
to include path and link to `${MAGNUM_XEGLAPPLICATION_LIBRARIES}`. If no other
application is requested, you can also use generic `${MAGNUM_APPLICATION_INCLUDE_DIRS}`
and `${MAGNUM_APPLICATION_LIBRARIES}` aliases to simplify porting. See
@ref building, @ref cmake and @ref platform for more information.
@section XEglApplication-usage Usage
You need to implement at least drawEvent() and viewportEvent() to be able to
draw on the screen. The subclass can be then used directly in `main()` - see
convenience macro MAGNUM_XEGLAPPLICATION_MAIN().
You need to implement at least @ref drawEvent() and @ref viewportEvent() to be
able to draw on the screen. The subclass can be then used directly in `main()`
-- see convenience macro @ref MAGNUM_XEGLAPPLICATION_MAIN().
@code
class MyApplication: public Magnum::Platform::XEglApplication {
class MyApplication: public Platform::XEglApplication {
// implement required methods...
};
MAGNUM_XEGLAPPLICATION_MAIN(MyApplication)
@endcode
If no other application header is included this class is also aliased to
If no other application header is included, this class is also aliased to
`Platform::Application` and the macro is aliased to `MAGNUM_APPLICATION_MAIN()`
to simplify porting.
*/
class XEglApplication: public AbstractXApplication {
public:
/** @copydoc GlutApplication::GlutApplication(const Arguments&, const Configuration&) */
explicit XEglApplication(const Arguments& arguments, const Configuration& configuration = Configuration()): AbstractXApplication(new EglContextHandler, arguments, configuration) {}
explicit XEglApplication(const Arguments& arguments, const Configuration& configuration = Configuration());
/** @copydoc GlutApplication::GlutApplication(const Arguments&, std::nullptr_t) */
#ifndef CORRADE_GCC45_COMPATIBILITY
explicit XEglApplication(const Arguments& arguments, std::nullptr_t)
explicit XEglApplication(const Arguments& arguments, std::nullptr_t);
#else
explicit XEglApplication(const Arguments& arguments, void*)
explicit XEglApplication(const Arguments& arguments, void*);
#endif
: AbstractXApplication(new EglContextHandler, nullptr) {}
protected:
/* Nobody will need to have (and delete) XEglApplication*, thus this is

74
src/Platform/magnum-info-nacl.html

@ -1,41 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Magnum Info</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="NaClApplication.css" />
<style type="text/css">
#module {
position: absolute;
visibility: hidden; /* The module doesn't display anything */
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Magnum Info</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="WebApplication.css" />
<style type="text/css">
#module {
position: absolute;
visibility: hidden; /* The module doesn't display anything */
}
#info {
width: 640px;
height: 480px;
overflow: auto;
font-family: monospace;
white-space: pre-wrap;
}
</style>
</head>
<body>
<h1>Magnum Info</h1>
<div id="listener">
<script type="text/javascript" src="NaClApplication.js"></script>
<script type="text/javascript">
function messageReceived(message) {
var info = document.getElementById('info');
info.innerHTML += message.data;
}
#info {
width: 640px;
height: 480px;
overflow: auto;
font-family: monospace;
white-space: pre-wrap;
}
</style>
</head>
<body>
<h1>Magnum Info</h1>
<div id="listener">
<embed id="module" type="application/x-nacl" src="magnum-info.nmf" />
<div id="status">Initialization...</div>
<div id="statusDescription" />
<div id="info" />
<script src="NaClApplication.js"></script>
<script type="text/javascript">
function messageReceived(message) {
var info = document.getElementById('info');
info.innerHTML += message.data;
}
var listener = document.getElementById('listener');
listener.addEventListener('message', messageReceived, true);
</script>
<embed id="module" type="application/x-nacl" src="magnum-info.nmf" />
<div id="status">Initialization...</div>
<div id="statusDescription"></div>
<div id="info"></div>
</div>
</body>
var listener = document.getElementById('listener');
listener.addEventListener('message', messageReceived, true);
</script>
</div>
</body>
</html>

6
src/Platform/magnum-info.cpp

@ -101,6 +101,9 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
#ifdef CORRADE_GCC47_COMPATIBILITY
Debug() << " CORRADE_GCC47_COMPATIBILITY";
#endif
#ifdef CORRADE_BUILD_DEPRECATED
Debug() << " CORRADE_BUILD_DEPRECATED";
#endif
#ifdef CORRADE_BUILD_STATIC
Debug() << " CORRADE_BUILD_STATIC";
#endif
@ -116,6 +119,9 @@ MagnumInfo::MagnumInfo(const Arguments& arguments): Platform::WindowlessApplicat
#ifdef CORRADE_TARGET_EMSCRIPTEN
Debug() << " CORRADE_TARGET_EMSCRIPTEN";
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
Debug() << " MAGNUM_BUILD_DEPRECATED";
#endif
#ifdef MAGNUM_BUILD_STATIC
Debug() << " MAGNUM_BUILD_STATIC";
#endif

5
src/Primitives/CMakeLists.txt

@ -58,7 +58,10 @@ if(BUILD_STATIC_PIC)
endif()
target_link_libraries(MagnumPrimitives Magnum)
install(TARGETS MagnumPrimitives DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumPrimitives
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(FILES ${MagnumPrimitives_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Primitives)
if(BUILD_TESTS)

24
src/RenderbufferFormat.h

@ -43,8 +43,8 @@ enum class RenderbufferFormat: GLenum {
#ifndef MAGNUM_TARGET_GLES
/**
* Red component, normalized unsigned, size implementation-dependent.
* @deprecated Prefer to use the exactly specified version of this format,
* e.g. @ref Magnum::RenderbufferFormat "RenderbufferFormat::R8".
* @deprecated_gl Prefer to use the exactly specified version of this
* format, e.g. @ref Magnum::RenderbufferFormat "RenderbufferFormat::R8".
* @requires_gl30 %Extension @extension{ARB,texture_rg}
* @requires_gl Use exactly specified format in OpenGL ES instead.
*/
@ -66,8 +66,8 @@ enum class RenderbufferFormat: GLenum {
/**
* Red and green component, normalized unsigned, size
* implementation-dependent.
* @deprecated Prefer to use the exactly specified version of this format,
* e.g. @ref Magnum::RenderbufferFormat "RenderbufferFormat::RG8".
* @deprecated_gl Prefer to use the exactly specified version of this
* format, e.g. @ref Magnum::RenderbufferFormat "RenderbufferFormat::RG8".
* @requires_gl30 %Extension @extension{ARB,texture_rg}
* @requires_gl Use exactly specified format in OpenGL ES instead.
*/
@ -88,8 +88,8 @@ enum class RenderbufferFormat: GLenum {
#ifndef MAGNUM_TARGET_GLES
/**
* RGBA, normalized unsigned, size implementation-dependent.
* @deprecated Prefer to use the exactly specified version of this format,
* e.g. @ref Magnum::RenderbufferFormat "RenderbufferFormat::RGBA8".
* @deprecated_gl Prefer to use the exactly specified version of this
* format, e.g. @ref Magnum::RenderbufferFormat "RenderbufferFormat::RGBA8".
* @requires_gl Use exactly specified format in OpenGL ES 2.0 instead.
*/
RGBA = GL_RGBA,
@ -383,8 +383,8 @@ enum class RenderbufferFormat: GLenum {
/**
* Depth component, size implementation-dependent.
* @todo is this allowed in core?
* @deprecated Prefer to use exactly specified version of this format, e.g.
* @ref Magnum::RenderbufferFormat "RenderbufferFormat::DepthComponent16".
* @deprecated_gl Prefer to use the exactly specified version of this
* format, e.g. @ref Magnum::RenderbufferFormat "RenderbufferFormat::DepthComponent16".
* @requires_gl Use exactly specified format in OpenGL ES instead.
*/
DepthComponent = GL_DEPTH_COMPONENT,
@ -428,8 +428,8 @@ enum class RenderbufferFormat: GLenum {
#ifndef MAGNUM_TARGET_GLES
/**
* Stencil index, size implementation-dependent.
* @deprecated Prefer to use exactly specified version of this format, e.g.
* @ref Magnum::RenderbufferFormat "RenderbufferFormat::StencilIndex8".
* @deprecated_gl Prefer to use the exactly specified version of this
* format, e.g. @ref Magnum::RenderbufferFormat "RenderbufferFormat::StencilIndex8".
* @requires_gl Use exactly specified format in OpenGL ES instead.
*/
StencilIndex = GL_STENCIL_INDEX,
@ -469,8 +469,8 @@ enum class RenderbufferFormat: GLenum {
/**
* Depth and stencil component, size implementation-dependent.
* @deprecated Prefer to use exactly specified version of this format, e.g.
* @ref Magnum::RenderbufferFormat "RenderbufferFormat::Depth24Stencil8".
* @deprecated_gl Prefer to use the exactly specified version of this
* format, e.g. @ref Magnum::RenderbufferFormat "RenderbufferFormat::Depth24Stencil8".
* @requires_gl Use exactly specified format in OpenGL ES instead.
*/
DepthStencil = GL_DEPTH_STENCIL,

4
src/Sampler.h

@ -146,13 +146,15 @@ class MAGNUM_EXPORT Sampler {
*/
static Float maxAnisotropy();
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief maxAnisotropy()
* @deprecated Use @ref Magnum::Shader::maxAnisotropy() "maxAnisotropy()"
* @deprecated Use @ref Magnum::Sampler::maxAnisotropy() "maxAnisotropy()"
* instead.
*/
static Float maxSupportedAnisotropy() { return maxAnisotropy(); }
#endif
#endif
};
/** @debugoperator{Magnum::Sampler} */

88
src/SceneGraph/AbstractTransformation.h

@ -28,11 +28,7 @@
* @brief Class Magnum::SceneGraph::AbstractTransformation, alias Magnum::SceneGraph::AbstractBasicTransformation2D, Magnum::SceneGraph::AbstractBasicTransformation3D, typedef Magnum::SceneGraph::AbstractTransformation2D, Magnum::SceneGraph::AbstractTransformation3D, enum Magnum::SceneGraph::TransformationType
*/
#include <vector>
#include "DimensionTraits.h"
#include "SceneGraph.h"
#include "SceneGraph/SceneGraph.h"
#include "SceneGraph/magnumSceneGraphVisibility.h"
namespace Magnum { namespace SceneGraph {
@ -40,15 +36,7 @@ namespace Magnum { namespace SceneGraph {
/**
@brief Base for transformations
Provides transformation implementation for Object instances. See @ref scenegraph
for introduction.
@section AbstractTransformation-subclassing Subclassing
When subclassing, you have to:
- Implement all members listed in **Subclass implementation** group above
- Provide implicit (parameterless) constructor
Provides transformation implementation for @ref Object instances.
@see @ref scenegraph, @ref AbstractBasicTransformation2D,
@ref AbstractBasicTransformation3D, @ref AbstractTransformation2D,
@ -64,76 +52,6 @@ template<UnsignedInt dimensions, class T> class MAGNUM_SCENEGRAPH_EXPORT Abstrac
explicit AbstractTransformation();
#ifdef DOXYGEN_GENERATING_OUTPUT
/**
* @{ @name Subclass implementation
*
* These members must be defined by the implementation.
*/
/**
* @todo Common way to call setClean() on the object after setting
* transformation & disallowing transformation setting on scene,
* so the implementer doesn't forget to do it? It could also
* allow to hide Object::isScene() from unwanted publicity.
*/
/**
* @brief Transformation data type
*
* The type must satisfy the following requirements:
*
* - Default constructor must create identity transformation
*
* Defined in subclasses.
*/
typedef U DataType;
/**
* @brief Convert transformation to matrix
*
* Defined in subclasses.
*/
static typename DimensionTraits<dimensions, T>::MatrixType toMatrix(const DataType& transformation);
/**
* @brief Convert transformation from matrix
*
* Defined in subclasses.
*/
static DataType fromMatrix(const typename DimensionTraits<dimensions, T>::MatrixType& matrix);
/**
* @brief Compose transformations
*
* Defined in subclasses.
*/
static DataType compose(const DataType& parent, const DataType& child);
/**
* @brief Inverted transformation
*
* Defined in subclasses.
*/
static DataType inverted(const DataType& transformation);
/**
* @brief %Object transformation
*
* Relative to parent. Defined in subclasses.
*/
DataType transformation() const;
/**
* @brief Absolute transformation
*
* Relative to root object. Defined in subclasses.
*/
DataType absoluteTransformation() const;
/*@}*/
#endif
/**
* @brief Reset object transformation
* @return Reference to self (for method chaining)
@ -198,7 +116,7 @@ Convenience alternative to <tt>%AbstractTransformation<3, T></tt>. See
AbstractTransformation for more information.
@note Not available on GCC < 4.7. Use <tt>%AbstractTransformation<3, T></tt>
instead.
@see @ref AbstractTransformation3D, @ref AbstractBasicTransformation3D
@see @ref AbstractTransformation3D, @ref AbstractBasicTransformation2D
*/
template<class T> using AbstractBasicTransformation3D = AbstractTransformation<3, T>;
#endif

142
src/SceneGraph/AbstractTranslation.h

@ -0,0 +1,142 @@
#ifndef Magnum_SceneGraph_AbstractTranslation_h
#define Magnum_SceneGraph_AbstractTranslation_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class @ref Magnum::SceneGraph::AbstractTranslation, alias @ref Magnum::SceneGraph::AbstractBasicTranslation2D, @ref Magnum::SceneGraph::AbstractBasicTranslation3D, typedef @ref Magnum::SceneGraph::AbstractTranslation2D, @ref Magnum::SceneGraph::AbstractBasicTranslation3D
*/
#include "Math/Vector3.h"
#include "DimensionTraits.h"
#include "SceneGraph/AbstractTransformation.h"
namespace Magnum { namespace SceneGraph {
/**
@brief Base transformation for two-dimensional scenes supporting translation
By default the translation is stored with the same underlying type as resulting
transformation matrix, but it's possible to store translation in e.g. integral
coordinates while having floating-point transformation matrix.
@see @ref AbstractBasicTranslation2D, @ref AbstractBasicTranslation3D,
@ref AbstractTranslation2D, @ref AbstractTranslation3D, @ref scenegraph
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<UnsignedInt dimensions, class T, class TranslationType = T>
#else
template<UnsignedInt dimensions, class T, class TranslationType>
#endif
class AbstractTranslation: public AbstractTransformation<dimensions, T> {
public:
explicit AbstractTranslation() = default;
/**
* @brief Translate object
* @param vector Translation vector
* @param type Transformation type
* @return Reference to self (for method chaining)
*
* @see @ref Vector2::xAxis(), @ref Vector2::yAxis(), @ref Vector3::xAxis(),
* @ref Vector3::yAxis(), @ref Vector3::zAxis()
*/
AbstractTranslation<dimensions, T>& translate(const typename DimensionTraits<dimensions, TranslationType>::VectorType& vector, TransformationType type = TransformationType::Global) {
doTranslate(vector, type);
return *this;
}
protected:
~AbstractTranslation() = default;
#ifdef DOXYGEN_GENERATING_OUTPUT
protected:
#else
private:
#endif
/** @brief Polymorphic implementation for translate() */
virtual void doTranslate(const typename DimensionTraits<dimensions, TranslationType>::VectorType& vector, TransformationType type) = 0;
};
#ifndef CORRADE_GCC46_COMPATIBILITY
/**
@brief Base transformation for two-dimensional scenes supporting translation
Convenience alternative to <tt>%AbstractTranslation<2, T, TranslationType></tt>.
See @ref AbstractTranslation for more information.
@note Not available on GCC < 4.7. Use <tt>%AbstractTranslation<2, T, TranslationType></tt>
instead.
@see @ref AbstractTranslation2D, @ref AbstractBasicTranslation3D
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T, class TranslationType = T>
#else
template<class T, class TranslationType>
#endif
using AbstractBasicTranslation2D = AbstractTranslation<2, T, TranslationType>;
#endif
/**
@brief Base transformation for two-dimensional float scenes supporting translation
@see @ref AbstractTranslation3D
*/
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef AbstractBasicTranslation2D<Float> AbstractTranslation2D;
#else
typedef AbstractTranslation<2, Float> AbstractTranslation2D;
#endif
#ifndef CORRADE_GCC46_COMPATIBILITY
/**
@brief Base transformation for three-dimensional scenes supporting translation
Convenience alternative to <tt>%AbstractTranslation<3, T, TranslationType></tt>.
See @ref AbstractTranslation for more information.
@note Not available on GCC < 4.7. Use <tt>%AbstractTranslation<3, T, TranslationType></tt>
instead.
@see @ref AbstractTranslation3D, @ref AbstractBasicTranslation2D
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T, class TranslationType = T>
#else
template<class T, class TranslationType>
#endif
using AbstractBasicTranslation3D = AbstractTranslation<3, T, TranslationType>;
#endif
/**
@brief Base transformation for three-dimensional float scenes supporting translation
@see @ref AbstractTranslation2D
*/
#ifndef CORRADE_GCC46_COMPATIBILITY
typedef AbstractBasicTranslation3D<Float> AbstractTranslation3D;
#else
typedef AbstractTranslation<3, Float> AbstractTranslation3D;
#endif
}}
#endif

22
src/SceneGraph/AbstractTranslationRotation2D.h

@ -28,33 +28,20 @@
* @brief Class Magnum::SceneGraph::AbstractBasicTranslationRotation2D, typedef Magnum::SceneGraph::AbstractTranslationRotation2D
*/
#include "AbstractTransformation.h"
#include "SceneGraph/AbstractTranslation.h"
namespace Magnum { namespace SceneGraph {
/**
@brief Base translation for two-dimensional scenes supporting translation and rotation
@brief Base transformation for two-dimensional scenes supporting translation and rotation
@see @ref AbstractTranslationRotation2D, @ref scenegraph, @ref AbstractBasicTranslationRotation3D
@todo Use AbstractBasicTransformation2D<T> when support for GCC 4.6 is dropped
*/
template<class T> class AbstractBasicTranslationRotation2D: public AbstractTransformation<2, T> {
template<class T> class AbstractBasicTranslationRotation2D: public AbstractTranslation<2, T> {
public:
explicit AbstractBasicTranslationRotation2D();
/**
* @brief Translate object
* @param vector Translation vector
* @param type Transformation type
* @return Reference to self (for method chaining)
*
* @see Vector2::xAxis(), Vector2::yAxis()
*/
AbstractBasicTranslationRotation2D<T>& translate(const Math::Vector2<T>& vector, TransformationType type = TransformationType::Global) {
doTranslate(vector, type);
return *this;
}
/**
* @brief Rotate object
* @param angle Angle (counterclockwise)
@ -82,9 +69,6 @@ template<class T> class AbstractBasicTranslationRotation2D: public AbstractTrans
#else
private:
#endif
/** @brief Polymorphic implementation for translate() */
virtual void doTranslate(const Math::Vector2<T>& vector, TransformationType type) = 0;
/** @brief Polymorphic implementation for rotate() */
virtual void doRotate(Math::Rad<T> angle, TransformationType type) = 0;
};

23
src/SceneGraph/AbstractTranslationRotation3D.h

@ -28,34 +28,20 @@
* @brief Class Magnum::SceneGraph::AbstractBasicTranslationRotation3D, typedef Magnum::SceneGraph::AbstractTranslationRotation3D
*/
#include "AbstractTransformation.h"
#include "Math/Vector3.h"
#include "SceneGraph/AbstractTranslation.h"
namespace Magnum { namespace SceneGraph {
/**
@brief Base translation for three-dimensional scenes supporting translation and rotation
@brief Base transformation for three-dimensional scenes supporting translation and rotation
@see @ref AbstractTranslationRotation3D @ref scenegraph, @ref AbstractBasicTranslationRotation2D
@todo Use AbstractBasicTransformation3D<T> when support for GCC 4.6 is dropped
*/
template<class T> class AbstractBasicTranslationRotation3D: public AbstractTransformation<3, T> {
template<class T> class AbstractBasicTranslationRotation3D: public AbstractTranslation<3, T> {
public:
explicit AbstractBasicTranslationRotation3D();
/**
* @brief Translate object
* @param vector Translation vector
* @param type Transformation type
* @return Reference to self (for method chaining)
*
* @see Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis()
*/
AbstractBasicTranslationRotation3D<T>& translate(const Math::Vector3<T>& vector, TransformationType type = TransformationType::Global) {
doTranslate(vector, type);
return *this;
}
/**
* @brief Rotate object
* @param angle Angle (counterclockwise)
@ -129,9 +115,6 @@ template<class T> class AbstractBasicTranslationRotation3D: public AbstractTrans
#else
private:
#endif
/** @brief Polymorphic implementation for translate() */
virtual void doTranslate(const Math::Vector3<T>& vector, TransformationType type) = 0;
/** @brief Polymorphic implementation for rotate() */
virtual void doRotate(Math::Rad<T> angle, const Math::Vector3<T>& normalizedAxis, TransformationType type) = 0;

12
src/SceneGraph/CMakeLists.txt

@ -38,6 +38,7 @@ set(MagnumSceneGraph_HEADERS
AbstractGroupedFeature.h
AbstractObject.h
AbstractTransformation.h
AbstractTranslation.h
AbstractTranslationRotation2D.h
AbstractTranslationRotation3D.h
AbstractTranslationRotationScaling2D.h
@ -62,6 +63,7 @@ set(MagnumSceneGraph_HEADERS
Object.hpp
Scene.h
SceneGraph.h
TranslationTransformation.h
magnumSceneGraphVisibility.h)
@ -81,7 +83,10 @@ add_library(MagnumSceneGraph ${SHARED_OR_STATIC}
${MagnumSceneGraph_GracefulAssert_SRCS})
target_link_libraries(MagnumSceneGraph Magnum)
install(TARGETS MagnumSceneGraph DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumSceneGraph
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(FILES ${MagnumSceneGraph_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/SceneGraph)
if(BUILD_TESTS)
@ -95,7 +100,10 @@ if(BUILD_TESTS)
# On Windows we need to install first and then run the tests to avoid "DLL
# not found" hell, thus we need to install this too
if(WIN32 AND NOT CMAKE_CROSSCOMPILING)
install(TARGETS MagnumSceneGraphTestLib DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(TARGETS MagnumSceneGraphTestLib
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
endif()
add_subdirectory(Test)

93
src/SceneGraph/DualComplexTransformation.h

@ -46,40 +46,8 @@ template<class T> class BasicDualComplexTransformation: public AbstractBasicTran
/** @brief Transformation type */
typedef Math::DualComplex<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
static Math::DualComplex<T> fromMatrix(const Math::Matrix3<T>& matrix) {
return Math::DualComplex<T>::fromMatrix(matrix);
}
constexpr static Math::Matrix3<T> toMatrix(const Math::DualComplex<T>& transformation) {
return transformation.toMatrix();
}
static Math::DualComplex<T> compose(const Math::DualComplex<T>& parent, const Math::DualComplex<T>& child) {
return parent*child;
}
static Math::DualComplex<T> inverted(const Math::DualComplex<T>& transformation) {
return transformation.invertedNormalized();
}
Math::DualComplex<T> transformation() const {
return _transformation;
}
#endif
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part to prevent rounding errors when rotating
* the object subsequently.
* @see DualComplex::normalized()
*/
Object<BasicDualComplexTransformation<T>>& normalizeRotation() {
setTransformationInternal(_transformation.normalized());
return static_cast<Object<BasicDualComplexTransformation<T>>&>(*this);
}
/** @brief Object transformation */
Math::DualComplex<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -92,14 +60,24 @@ template<class T> class BasicDualComplexTransformation: public AbstractBasicTran
CORRADE_ASSERT(transformation.isNormalized(),
"SceneGraph::DualComplexTransformation::setTransformation(): the dual complex number is not normalized",
static_cast<Object<BasicDualComplexTransformation<T>>&>(*this));
setTransformationInternal(transformation);
return static_cast<Object<BasicDualComplexTransformation<T>>&>(*this);
return setTransformationInternal(transformation);
}
/** @copydoc AbstractTranslationRotationScaling2D::resetTransformation() */
Object<BasicDualComplexTransformation<T>>& resetTransformation() {
setTransformationInternal({});
return static_cast<Object<BasicDualComplexTransformation<T>>&>(*this);
return setTransformationInternal({});
}
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part to prevent rounding errors when rotating
* the object subsequently.
* @see DualComplex::normalized()
*/
Object<BasicDualComplexTransformation<T>>& normalizeRotation() {
return setTransformationInternal(_transformation.normalized());
}
/**
@ -115,8 +93,7 @@ template<class T> class BasicDualComplexTransformation: public AbstractBasicTran
CORRADE_ASSERT(transformation.isNormalized(),
"SceneGraph::DualComplexTransformation::transform(): the dual complex number is not normalized",
static_cast<Object<BasicDualComplexTransformation<T>>&>(*this));
transformInternal(transformation, type);
return static_cast<Object<BasicDualComplexTransformation<T>>&>(*this);
return transformInternal(transformation, type);
}
/**
@ -124,8 +101,7 @@ template<class T> class BasicDualComplexTransformation: public AbstractBasicTran
* Same as calling transform() with DualComplex::translation().
*/
Object<BasicDualComplexTransformation<T>>& translate(const Math::Vector2<T>& vector, TransformationType type = TransformationType::Global) {
transformInternal(Math::DualComplex<T>::translation(vector), type);
return static_cast<Object<BasicDualComplexTransformation<T>>&>(*this);
return transformInternal(Math::DualComplex<T>::translation(vector), type);
}
/**
@ -138,8 +114,7 @@ template<class T> class BasicDualComplexTransformation: public AbstractBasicTran
* @see normalizeRotation()
*/
Object<BasicDualComplexTransformation<T>>& rotate(Math::Rad<T> angle, TransformationType type = TransformationType::Global) {
transformInternal(Math::DualComplex<T>::rotation(angle), type);
return static_cast<Object<BasicDualComplexTransformation<T>>&>(*this);
return transformInternal(Math::DualComplex<T>::rotation(angle), type);
}
/**
@ -169,7 +144,7 @@ template<class T> class BasicDualComplexTransformation: public AbstractBasicTran
}
/* No assertions fired, for internal use */
void setTransformationInternal(const Math::DualComplex<T>& transformation) {
Object<BasicDualComplexTransformation<T>>& setTransformationInternal(const Math::DualComplex<T>& transformation) {
/* Setting transformation is forbidden for the scene */
/** @todo Assert for this? */
/** @todo Do this in some common code so we don't need to include Object? */
@ -177,11 +152,13 @@ template<class T> class BasicDualComplexTransformation: public AbstractBasicTran
_transformation = transformation;
static_cast<Object<BasicDualComplexTransformation<T>>*>(this)->setDirty();
}
return static_cast<Object<BasicDualComplexTransformation<T>>&>(*this);
}
/* No assertions fired, for internal use */
void transformInternal(const Math::DualComplex<T>& transformation, TransformationType type) {
setTransformation(type == TransformationType::Global ?
Object<BasicDualComplexTransformation<T>>& transformInternal(const Math::DualComplex<T>& transformation, TransformationType type) {
return setTransformationInternal(type == TransformationType::Global ?
transformation*_transformation : _transformation*transformation);
}
@ -197,6 +174,28 @@ template<class T> inline BasicDualComplexTransformation<T>::BasicDualComplexTran
*/
typedef BasicDualComplexTransformation<Float> DualComplexTransformation;
namespace Implementation {
template<class T> struct Transformation<BasicDualComplexTransformation<T>> {
static Math::DualComplex<T> fromMatrix(const Math::Matrix3<T>& matrix) {
return Math::DualComplex<T>::fromMatrix(matrix);
}
constexpr static Math::Matrix3<T> toMatrix(const Math::DualComplex<T>& transformation) {
return transformation.toMatrix();
}
static Math::DualComplex<T> compose(const Math::DualComplex<T>& parent, const Math::DualComplex<T>& child) {
return parent*child;
}
static Math::DualComplex<T> inverted(const Math::DualComplex<T>& transformation) {
return transformation.invertedNormalized();
}
};
}
}}
#endif

97
src/SceneGraph/DualQuaternionTransformation.h

@ -46,42 +46,8 @@ template<class T> class BasicDualQuaternionTransformation: public AbstractBasicT
/** @brief Underlying transformation type */
typedef Math::DualQuaternion<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
static Math::DualQuaternion<T> fromMatrix(const Math::Matrix4<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(),
"SceneGraph::DualQuaternionTransformation::fromMatrix(): the matrix doesn't represent rigid transformation", {});
return Math::DualQuaternion<T>::fromMatrix(matrix);
}
constexpr static Math::Matrix4<T> toMatrix(const Math::DualQuaternion<T>& transformation) {
return transformation.toMatrix();
}
static Math::DualQuaternion<T> compose(const Math::DualQuaternion<T>& parent, const Math::DualQuaternion<T>& child) {
return parent*child;
}
static Math::DualQuaternion<T> inverted(const Math::DualQuaternion<T>& transformation) {
return transformation.invertedNormalized();
}
Math::DualQuaternion<T> transformation() const {
return _transformation;
}
#endif
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part to prevent rounding errors when rotating
* the object subsequently.
* @see DualQuaternion::normalized()
*/
Object<BasicDualQuaternionTransformation<T>>& normalizeRotation() {
setTransformation(_transformation.normalized());
return static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this);
}
/** @brief Object transformation */
Math::DualQuaternion<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -94,14 +60,24 @@ template<class T> class BasicDualQuaternionTransformation: public AbstractBasicT
CORRADE_ASSERT(transformation.isNormalized(),
"SceneGraph::DualQuaternionTransformation::setTransformation(): the dual quaternion is not normalized",
static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this));
setTransformationInternal(transformation);
return static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this);
return setTransformationInternal(transformation);
}
/** @copydoc AbstractTranslationRotationScaling3D::resetTransformation() */
Object<BasicDualQuaternionTransformation<T>>& resetTransformation() {
setTransformation({});
return static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this);
return setTransformationInternal({});
}
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part to prevent rounding errors when rotating
* the object subsequently.
* @see DualQuaternion::normalized()
*/
Object<BasicDualQuaternionTransformation<T>>& normalizeRotation() {
return setTransformationInternal(_transformation.normalized());
}
/**
@ -117,8 +93,7 @@ template<class T> class BasicDualQuaternionTransformation: public AbstractBasicT
CORRADE_ASSERT(transformation.isNormalized(),
"SceneGraph::DualQuaternionTransformation::transform(): the dual quaternion is not normalized",
static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this));
transformInternal(transformation, type);
return static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this);
return transformInternal(transformation, type);
}
/**
@ -126,8 +101,7 @@ template<class T> class BasicDualQuaternionTransformation: public AbstractBasicT
* Same as calling transform() with DualQuaternion::translation().
*/
Object<BasicDualQuaternionTransformation<T>>& translate(const Math::Vector3<T>& vector, TransformationType type = TransformationType::Global) {
transformInternal(Math::DualQuaternion<T>::translation(vector), type);
return static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this);
return transformInternal(Math::DualQuaternion<T>::translation(vector), type);
}
/**
@ -142,8 +116,7 @@ template<class T> class BasicDualQuaternionTransformation: public AbstractBasicT
* normalizeRotation()
*/
Object<BasicDualQuaternionTransformation<T>>& rotate(Math::Rad<T> angle, const Math::Vector3<T>& normalizedAxis, TransformationType type = TransformationType::Global) {
transformInternal(Math::DualQuaternion<T>::rotation(angle, normalizedAxis), type);
return static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this);
return transformInternal(Math::DualQuaternion<T>::rotation(angle, normalizedAxis), type);
}
/* Overloads to remove WTF-factor from method chaining order */
@ -175,7 +148,7 @@ template<class T> class BasicDualQuaternionTransformation: public AbstractBasicT
}
/* No assertions fired, for internal use */
void setTransformationInternal(const Math::DualQuaternion<T>& transformation) {
Object<BasicDualQuaternionTransformation<T>>& setTransformationInternal(const Math::DualQuaternion<T>& transformation) {
/* Setting transformation is forbidden for the scene */
/** @todo Assert for this? */
/** @todo Do this in some common code so we don't need to include Object? */
@ -183,11 +156,13 @@ template<class T> class BasicDualQuaternionTransformation: public AbstractBasicT
_transformation = transformation;
static_cast<Object<BasicDualQuaternionTransformation<T>>*>(this)->setDirty();
}
return static_cast<Object<BasicDualQuaternionTransformation<T>>&>(*this);
}
/* No assertions fired, for internal use */
void transformInternal(const Math::DualQuaternion<T>& transformation, TransformationType type) {
setTransformation(type == TransformationType::Global ?
Object<BasicDualQuaternionTransformation<T>>& transformInternal(const Math::DualQuaternion<T>& transformation, TransformationType type) {
return setTransformationInternal(type == TransformationType::Global ?
transformation*_transformation : _transformation*transformation);
}
@ -203,6 +178,30 @@ template<class T> inline BasicDualQuaternionTransformation<T>::BasicDualQuaterni
*/
typedef BasicDualQuaternionTransformation<Float> DualQuaternionTransformation;
namespace Implementation {
template<class T> struct Transformation<BasicDualQuaternionTransformation<T>> {
static Math::DualQuaternion<T> fromMatrix(const Math::Matrix4<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(),
"SceneGraph::DualQuaternionTransformation: the matrix doesn't represent rigid transformation", {});
return Math::DualQuaternion<T>::fromMatrix(matrix);
}
constexpr static Math::Matrix4<T> toMatrix(const Math::DualQuaternion<T>& transformation) {
return transformation.toMatrix();
}
static Math::DualQuaternion<T> compose(const Math::DualQuaternion<T>& parent, const Math::DualQuaternion<T>& child) {
return parent*child;
}
static Math::DualQuaternion<T> inverted(const Math::DualQuaternion<T>& transformation) {
return transformation.invertedNormalized();
}
};
}
}}
#endif

63
src/SceneGraph/MatrixTransformation2D.h

@ -45,27 +45,8 @@ template<class T> class BasicMatrixTransformation2D: public AbstractBasicTransla
/** @brief Underlying transformation type */
typedef Math::Matrix3<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
constexpr static Math::Matrix3<T> fromMatrix(const Math::Matrix3<T>& matrix) {
return matrix;
}
constexpr static Math::Matrix3<T> toMatrix(const Math::Matrix3<T>& transformation) {
return transformation;
}
static Math::Matrix3<T> compose(const Math::Matrix3<T>& parent, const Math::Matrix3<T>& child) {
return parent*child;
}
static Math::Matrix3<T> inverted(const Math::Matrix3<T>& transformation) {
return transformation.inverted();
}
Math::Matrix3<T> transformation() const {
return _transformation;
}
#endif
/** @brief Object transformation */
Math::Matrix3<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -90,15 +71,13 @@ template<class T> class BasicMatrixTransformation2D: public AbstractBasicTransla
* @return Reference to self (for method chaining)
*/
Object<BasicMatrixTransformation2D<T>>& transform(const Math::Matrix3<T>& transformation, TransformationType type = TransformationType::Global) {
setTransformation(type == TransformationType::Global ?
return setTransformation(type == TransformationType::Global ?
transformation*_transformation : _transformation*transformation);
return static_cast<Object<BasicMatrixTransformation2D<T>>&>(*this);
}
/** @copydoc AbstractTranslationRotationScaling2D::resetTransformation() */
Object<BasicMatrixTransformation2D<T>>& resetTransformation() {
setTransformation({});
return static_cast<Object<BasicMatrixTransformation2D<T>>&>(*this);
return setTransformation({});
}
/**
@ -106,8 +85,7 @@ template<class T> class BasicMatrixTransformation2D: public AbstractBasicTransla
* Same as calling transform() with Matrix3::translation().
*/
Object<BasicMatrixTransformation2D<T>>& translate(const Math::Vector2<T>& vector, TransformationType type = TransformationType::Global) {
transform(Math::Matrix3<T>::translation(vector), type);
return static_cast<Object<BasicMatrixTransformation2D<T>>&>(*this);
return transform(Math::Matrix3<T>::translation(vector), type);
}
/**
@ -115,8 +93,7 @@ template<class T> class BasicMatrixTransformation2D: public AbstractBasicTransla
* Same as calling transform() with Matrix3::rotation().
*/
Object<BasicMatrixTransformation2D<T>>& rotate(Math::Rad<T> angle, TransformationType type = TransformationType::Global) {
transform(Math::Matrix3<T>::rotation(angle), type);
return static_cast<Object<BasicMatrixTransformation2D<T>>&>(*this);
return transform(Math::Matrix3<T>::rotation(angle), type);
}
/**
@ -124,8 +101,7 @@ template<class T> class BasicMatrixTransformation2D: public AbstractBasicTransla
* Same as calling transform() with Matrix3::scaling().
*/
Object<BasicMatrixTransformation2D<T>>& scale(const Math::Vector2<T>& vector, TransformationType type = TransformationType::Global) {
transform(Math::Matrix3<T>::scaling(vector), type);
return static_cast<Object<BasicMatrixTransformation2D<T>>&>(*this);
return transform(Math::Matrix3<T>::scaling(vector), type);
}
/**
@ -138,8 +114,7 @@ template<class T> class BasicMatrixTransformation2D: public AbstractBasicTransla
* Same as calling transform() with Matrix3::reflection().
*/
Object<BasicMatrixTransformation2D<T>>& reflect(const Math::Vector2<T>& normal, TransformationType type = TransformationType::Global) {
transform(Math::Matrix3<T>::reflection(normal), type);
return static_cast<Object<BasicMatrixTransformation2D<T>>&>(*this);
return transform(Math::Matrix3<T>::reflection(normal), type);
}
/**
@ -184,6 +159,28 @@ template<class T> inline BasicMatrixTransformation2D<T>::BasicMatrixTransformati
*/
typedef BasicMatrixTransformation2D<Float> MatrixTransformation2D;
namespace Implementation {
template<class T> struct Transformation<BasicMatrixTransformation2D<T>> {
constexpr static Math::Matrix3<T> fromMatrix(const Math::Matrix3<T>& matrix) {
return matrix;
}
constexpr static Math::Matrix3<T> toMatrix(const Math::Matrix3<T>& transformation) {
return transformation;
}
static Math::Matrix3<T> compose(const Math::Matrix3<T>& parent, const Math::Matrix3<T>& child) {
return parent*child;
}
static Math::Matrix3<T> inverted(const Math::Matrix3<T>& transformation) {
return transformation.inverted();
}
};
}
}}
#endif

72
src/SceneGraph/MatrixTransformation3D.h

@ -45,27 +45,8 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
/** @brief Underlying transformation type */
typedef Math::Matrix4<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
constexpr static Math::Matrix4<T> fromMatrix(const Math::Matrix4<T>& matrix) {
return matrix;
}
constexpr static Math::Matrix4<T> toMatrix(const Math::Matrix4<T>& transformation) {
return transformation;
}
static Math::Matrix4<T> compose(const Math::Matrix4<T>& parent, const Math::Matrix4<T>& child) {
return parent*child;
}
static Math::Matrix4<T> inverted(const Math::Matrix4<T>& transformation) {
return transformation.inverted();
}
Math::Matrix4<T> transformation() const {
return _transformation;
}
#endif
/** @brief Object transformation */
Math::Matrix4<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -85,8 +66,7 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
/** @copydoc AbstractTranslationRotationScaling3D::resetTransformation() */
Object<BasicMatrixTransformation3D<T>>& resetTransformation() {
setTransformation({});
return static_cast<Object<BasicMatrixTransformation3D<T>>&>(*this);
return setTransformation({});
}
/**
@ -96,9 +76,8 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
* @return Reference to self (for method chaining)
*/
Object<BasicMatrixTransformation3D<T>>& transform(const Math::Matrix4<T>& transformation, TransformationType type = TransformationType::Global) {
setTransformation(type == TransformationType::Global ?
return setTransformation(type == TransformationType::Global ?
transformation*_transformation : _transformation*transformation);
return static_cast<Object<BasicMatrixTransformation3D<T>>&>(*this);
}
/**
@ -106,8 +85,7 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
* Same as calling transform() with Matrix4::translation().
*/
Object<BasicMatrixTransformation3D<T>>& translate(const Math::Vector3<T>& vector, TransformationType type = TransformationType::Global) {
transform(Math::Matrix4<T>::translation(vector), type);
return static_cast<Object<BasicMatrixTransformation3D<T>>&>(*this);
return transform(Math::Matrix4<T>::translation(vector), type);
}
/**
@ -115,8 +93,7 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
* Same as calling transform() with Matrix4::rotation().
*/
Object<BasicMatrixTransformation3D<T>>& rotate(Math::Rad<T> angle, const Math::Vector3<T>& normalizedAxis, TransformationType type = TransformationType::Global) {
transform(Math::Matrix4<T>::rotation(angle, normalizedAxis), type);
return static_cast<Object<BasicMatrixTransformation3D<T>>&>(*this);
return transform(Math::Matrix4<T>::rotation(angle, normalizedAxis), type);
}
/**
@ -128,8 +105,7 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
* Same as calling transform() with Matrix4::rotationX().
*/
Object<BasicMatrixTransformation3D<T>>& rotateX(Math::Rad<T> angle, TransformationType type = TransformationType::Global) {
transform(Math::Matrix4<T>::rotationX(angle), type);
return static_cast<Object<BasicMatrixTransformation3D<T>>&>(*this);
return transform(Math::Matrix4<T>::rotationX(angle), type);
}
/**
@ -141,8 +117,7 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
* Same as calling transform() with Matrix4::rotationY().
*/
Object<BasicMatrixTransformation3D<T>>& rotateY(Math::Rad<T> angle, TransformationType type = TransformationType::Global) {
transform(Math::Matrix4<T>::rotationY(angle), type);
return static_cast<Object<BasicMatrixTransformation3D<T>>&>(*this);
return transform(Math::Matrix4<T>::rotationY(angle), type);
}
/**
@ -154,8 +129,7 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
* Same as calling transform() with Matrix4::rotationZ().
*/
Object<BasicMatrixTransformation3D<T>>& rotateZ(Math::Rad<T> angle, TransformationType type = TransformationType::Global) {
transform(Math::Matrix4<T>::rotationZ(angle), type);
return static_cast<Object<BasicMatrixTransformation3D<T>>&>(*this);
return transform(Math::Matrix4<T>::rotationZ(angle), type);
}
/**
@ -163,8 +137,7 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
* Same as calling transform() with Matrix4::scaling().
*/
Object<BasicMatrixTransformation3D<T>>& scale(const Math::Vector3<T>& vector, TransformationType type = TransformationType::Global) {
transform(Math::Matrix4<T>::scaling(vector), type);
return static_cast<Object<BasicMatrixTransformation3D<T>>&>(*this);
return transform(Math::Matrix4<T>::scaling(vector), type);
}
/**
@ -177,8 +150,7 @@ template<class T> class BasicMatrixTransformation3D: public AbstractBasicTransla
* Same as calling transform() with Matrix4::reflection().
*/
Object<BasicMatrixTransformation3D<T>>& reflect(const Math::Vector3<T>& normal, TransformationType type = TransformationType::Global) {
transform(Math::Matrix4<T>::reflection(normal), type);
return static_cast<Object<BasicMatrixTransformation3D<T>>&>(*this);
return transform(Math::Matrix4<T>::reflection(normal), type);
}
protected:
@ -224,6 +196,28 @@ template<class T> inline BasicMatrixTransformation3D<T>::BasicMatrixTransformati
*/
typedef BasicMatrixTransformation3D<Float> MatrixTransformation3D;
namespace Implementation {
template<class T> struct Transformation<BasicMatrixTransformation3D<T>> {
constexpr static Math::Matrix4<T> fromMatrix(const Math::Matrix4<T>& matrix) {
return matrix;
}
constexpr static Math::Matrix4<T> toMatrix(const Math::Matrix4<T>& transformation) {
return transformation;
}
static Math::Matrix4<T> compose(const Math::Matrix4<T>& parent, const Math::Matrix4<T>& child) {
return parent*child;
}
static Math::Matrix4<T> inverted(const Math::Matrix4<T>& transformation) {
return transformation.inverted();
}
};
}
}}
#endif

6
src/SceneGraph/Object.h

@ -85,6 +85,8 @@ See @ref compilation-speedup-hpp for more information.
- @ref MatrixTransformation3D "Object<MatrixTransformation3D<Float>>"
- @ref RigidMatrixTransformation2D "Object<RigidMatrixTransformation2D<Float>>"
- @ref RigidMatrixTransformation3D "Object<RigidMatrixTransformation3D<Float>>"
- @ref TranslationTransformation2D "Object<TranslationTransformation2D<Float>>"
- @ref TranslationTransformation3D "Object<TranslationTransformation3D<Float>>"
@see Scene, AbstractFeature, AbstractTransformation, DebugTools::ObjectRenderer
*/
@ -215,7 +217,7 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
* @see transformation()
*/
MatrixType transformationMatrix() const {
return Transformation::toMatrix(Transformation::transformation());
return Implementation::Transformation<Transformation>::toMatrix(Transformation::transformation());
}
/**
@ -224,7 +226,7 @@ template<class Transformation> class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs
* @see absoluteTransformation()
*/
MatrixType absoluteTransformationMatrix() const {
return Transformation::toMatrix(absoluteTransformation());
return Implementation::Transformation<Transformation>::toMatrix(absoluteTransformation());
}
/**

23
src/SceneGraph/Object.hpp

@ -92,8 +92,8 @@ template<class Transformation> Object<Transformation>& Object<Transformation>::s
template<class Transformation> Object<Transformation>& Object<Transformation>::setParentKeepTransformation(Object<Transformation>* parent) {
CORRADE_ASSERT(scene() == parent->scene(), "SceneGraph::Object::setParentKeepTransformation(): both parents must be in the same scene", *this);
const auto transformation = Transformation::compose(
Transformation::inverted(parent->absoluteTransformation()), absoluteTransformation());
const auto transformation = Implementation::Transformation<Transformation>::compose(
Implementation::Transformation<Transformation>::inverted(parent->absoluteTransformation()), absoluteTransformation());
setParent(parent);
Transformation::setTransformation(transformation);
@ -102,7 +102,7 @@ template<class Transformation> Object<Transformation>& Object<Transformation>::s
template<class Transformation> typename Transformation::DataType Object<Transformation>::absoluteTransformation() const {
if(!parent()) return Transformation::transformation();
return Transformation::compose(parent()->absoluteTransformation(), Transformation::transformation());
return Implementation::Transformation<Transformation>::compose(parent()->absoluteTransformation(), Transformation::transformation());
}
template<class Transformation> void Object<Transformation>::setDirty() {
@ -154,7 +154,7 @@ template<class Transformation> void Object<Transformation>::setClean() {
objects.pop();
/* Compose transformation and clean object */
absoluteTransformation = Transformation::compose(absoluteTransformation, o->transformation());
absoluteTransformation = Implementation::Transformation<Transformation>::compose(absoluteTransformation, o->transformation());
CORRADE_INTERNAL_ASSERT(o->isDirty());
o->setClean(absoluteTransformation);
CORRADE_ASSERT(!o->isDirty(), "SceneGraph::Object::setClean(): original implementation was not called", );
@ -172,10 +172,10 @@ template<class Transformation> auto Object<Transformation>::doTransformationMatr
}
template<class Transformation> auto Object<Transformation>::transformationMatrices(const std::vector<Object<Transformation>*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector<MatrixType> {
std::vector<typename Transformation::DataType> transformations = this->transformations(std::move(objects), Transformation::fromMatrix(initialTransformationMatrix));
std::vector<typename Transformation::DataType> transformations = this->transformations(std::move(objects), Implementation::Transformation<Transformation>::fromMatrix(initialTransformationMatrix));
std::vector<MatrixType> transformationMatrices(transformations.size());
for(std::size_t i = 0; i != objects.size(); ++i)
transformationMatrices[i] = Transformation::toMatrix(transformations[i]);
transformationMatrices[i] = Implementation::Transformation<Transformation>::toMatrix(transformations[i]);
return transformationMatrices;
}
@ -324,16 +324,16 @@ template<class Transformation> typename Transformation::DataType Object<Transfor
if(!parent) {
CORRADE_INTERNAL_ASSERT(o->isScene());
return (jointTransformations[joint] =
Transformation::compose(initialTransformation, jointTransformations[joint]));
Implementation::Transformation<Transformation>::compose(initialTransformation, jointTransformations[joint]));
/* Joint object, compose transformation with the joint, done */
} else if(parent->flags & Flag::Joint) {
return (jointTransformations[joint] =
Transformation::compose(computeJointTransformation(jointObjects, jointTransformations, parent->counter, initialTransformation), jointTransformations[joint]));
Implementation::Transformation<Transformation>::compose(computeJointTransformation(jointObjects, jointTransformations, parent->counter, initialTransformation), jointTransformations[joint]));
/* Else compose transformation with parent, go up the hierarchy */
} else {
jointTransformations[joint] = Transformation::compose(parent->transformation(), jointTransformations[joint]);
jointTransformations[joint] = Implementation::Transformation<Transformation>::compose(parent->transformation(), jointTransformations[joint]);
o = parent;
}
}
@ -406,7 +406,7 @@ template<class Transformation> void Object<Transformation>::setClean(const typen
if(i->cachedTransformations() & CachedTransformation::Absolute) {
if(!(cached & CachedTransformation::Absolute)) {
cached |= CachedTransformation::Absolute;
matrix = Transformation::toMatrix(absoluteTransformation);
matrix = Implementation::Transformation<Transformation>::toMatrix(absoluteTransformation);
}
i->clean(matrix);
@ -417,7 +417,8 @@ template<class Transformation> void Object<Transformation>::setClean(const typen
if(i->cachedTransformations() & CachedTransformation::InvertedAbsolute) {
if(!(cached & CachedTransformation::InvertedAbsolute)) {
cached |= CachedTransformation::InvertedAbsolute;
invertedMatrix = Transformation::toMatrix(Transformation::inverted(absoluteTransformation));
invertedMatrix = Implementation::Transformation<Transformation>::toMatrix(
Implementation::Transformation<Transformation>::inverted(absoluteTransformation));
}
i->cleanInverted(invertedMatrix);

102
src/SceneGraph/RigidMatrixTransformation2D.h

@ -49,43 +49,8 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
/** @brief Underlying transformation type */
typedef Math::Matrix3<T> DataType;
#ifndef DOXYGEN_GENERATING_OUTPUT
static Math::Matrix3<T> fromMatrix(const Math::Matrix3<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(),
"SceneGraph::RigidMatrixTransformation2D::fromMatrix(): the matrix doesn't represent rigid transformation", {});
return matrix;
}
constexpr static Math::Matrix3<T> toMatrix(const Math::Matrix3<T>& transformation) {
return transformation;
}
static Math::Matrix3<T> compose(const Math::Matrix3<T>& parent, const Math::Matrix3<T>& child) {
return parent*child;
}
static Math::Matrix3<T> inverted(const Math::Matrix3<T>& transformation) {
return transformation.invertedRigid();
}
Math::Matrix3<T> transformation() const {
return _transformation;
}
#endif
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part using Math::Algorithms::gramSchmidt()
* to prevent rounding errors when rotating the object subsequently.
*/
Object<BasicRigidMatrixTransformation2D<T>>& normalizeRotation() {
setTransformationInternal(Math::Matrix3<T>::from(
Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()),
_transformation.translation()));
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
}
/** @brief Object transformation */
Math::Matrix3<T> transformation() const { return _transformation; }
/**
* @brief Set transformation
@ -98,14 +63,25 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
CORRADE_ASSERT(transformation.isRigidTransformation(),
"SceneGraph::RigidMatrixTransformation2D::setTransformation(): the matrix doesn't represent rigid transformation",
static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this));
setTransformationInternal(transformation);
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
return setTransformationInternal(transformation);
}
/** @copydoc AbstractTranslationRotationScaling2D::resetTransformation() */
Object<BasicRigidMatrixTransformation2D<T>>& resetTransformation() {
setTransformationInternal({});
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
return setTransformationInternal({});
}
/**
* @brief Normalize rotation part
* @return Reference to self (for method chaining)
*
* Normalizes the rotation part using Math::Algorithms::gramSchmidt()
* to prevent rounding errors when rotating the object subsequently.
*/
Object<BasicRigidMatrixTransformation2D<T>>& normalizeRotation() {
return setTransformationInternal(Math::Matrix3<T>::from(
Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()),
_transformation.translation()));
}
/**
@ -121,8 +97,7 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
CORRADE_ASSERT(transformation.isRigidTransformation(),
"SceneGraph::RigidMatrixTransformation2D::transform(): the matrix doesn't represent rigid transformation",
static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this));
transformInternal(transformation, type);
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
return transformInternal(transformation, type);
}
/**
@ -130,8 +105,7 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
* Same as calling transform() with Matrix3::translation().
*/
Object<BasicRigidMatrixTransformation2D<T>>& translate(const Math::Vector2<T>& vector, TransformationType type = TransformationType::Global) {
transformInternal(Math::Matrix3<T>::translation(vector), type);
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
return transformInternal(Math::Matrix3<T>::translation(vector), type);
}
/**
@ -144,8 +118,7 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
* @see normalizeRotation()
*/
Object<BasicRigidMatrixTransformation2D<T>>& rotate(Math::Rad<T> angle, TransformationType type = TransformationType::Global) {
transformInternal(Math::Matrix3<T>::rotation(angle), type);
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
return transformInternal(Math::Matrix3<T>::rotation(angle), type);
}
/**
@ -158,8 +131,7 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
* Same as calling transform() with Matrix3::reflection().
*/
Object<BasicRigidMatrixTransformation2D<T>>& reflect(const Math::Vector2<T>& normal, TransformationType type = TransformationType::Global) {
transformInternal(Math::Matrix3<T>::reflection(normal), type);
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
return transformInternal(Math::Matrix3<T>::reflection(normal), type);
}
/**
@ -189,7 +161,7 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
}
/* No assertions fired, for internal use */
void setTransformationInternal(const Math::Matrix3<T>& transformation) {
Object<BasicRigidMatrixTransformation2D<T>>& setTransformationInternal(const Math::Matrix3<T>& transformation) {
/* Setting transformation is forbidden for the scene */
/** @todo Assert for this? */
/** @todo Do this in some common code so we don't need to include Object? */
@ -197,11 +169,13 @@ template<class T> class BasicRigidMatrixTransformation2D: public AbstractBasicTr
_transformation = transformation;
static_cast<Object<BasicRigidMatrixTransformation2D<T>>*>(this)->setDirty();
}
return static_cast<Object<BasicRigidMatrixTransformation2D<T>>&>(*this);
}
/* No assertions fired, for internal use */
void transformInternal(const Math::Matrix3<T>& transformation, TransformationType type) {
setTransformation(type == TransformationType::Global ?
Object<BasicRigidMatrixTransformation2D<T>>& transformInternal(const Math::Matrix3<T>& transformation, TransformationType type) {
return setTransformationInternal(type == TransformationType::Global ?
transformation*_transformation : _transformation*transformation);
}
@ -217,6 +191,30 @@ template<class T> inline BasicRigidMatrixTransformation2D<T>::BasicRigidMatrixTr
*/
typedef BasicRigidMatrixTransformation2D<Float> RigidMatrixTransformation2D;
namespace Implementation {
template<class T> struct Transformation<BasicRigidMatrixTransformation2D<T>> {
static Math::Matrix3<T> fromMatrix(const Math::Matrix3<T>& matrix) {
CORRADE_ASSERT(matrix.isRigidTransformation(),
"SceneGraph::RigidMatrixTransformation2D: the matrix doesn't represent rigid transformation", {});
return matrix;
}
constexpr static Math::Matrix3<T> toMatrix(const Math::Matrix3<T>& transformation) {
return transformation;
}
static Math::Matrix3<T> compose(const Math::Matrix3<T>& parent, const Math::Matrix3<T>& child) {
return parent*child;
}
static Math::Matrix3<T> inverted(const Math::Matrix3<T>& transformation) {
return transformation.invertedRigid();
}
};
}
}}
#endif

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

Loading…
Cancel
Save