diff --git a/CMakeLists.txt b/CMakeLists.txt index 4909b4f95..4aa84607b 100644 --- a/CMakeLists.txt +++ b/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) diff --git a/Doxyfile b/Doxyfile index 90af7401d..ee684d052 100644 --- a/Doxyfile +++ b/Doxyfile @@ -210,6 +210,7 @@ ALIASES = \ "fn_gl_extension{3}=gl\1\2()" \ "fn_gles_extension{3}=gl\1\2()" \ "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. diff --git a/PKGBUILD b/PKGBUILD index 893f31af4..c04bc16ee 100644 --- a/PKGBUILD +++ b/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 } diff --git a/PKGBUILD-emscripten b/PKGBUILD-emscripten new file mode 100644 index 000000000..f80ca8080 --- /dev/null +++ b/PKGBUILD-emscripten @@ -0,0 +1,37 @@ +# Author: mosra +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 +} diff --git a/README.md b/README.md index 18fc6b706..b927853e1 100644 --- a/README.md +++ b/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 ======== diff --git a/doc/building.dox b/doc/building.dox index f3e414ecd..10db305a4 100644 --- a/doc/building.dox +++ b/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. + */ + } diff --git a/doc/cmake.dox b/doc/cmake.dox index 6493356b5..fbea44ae0 100644 --- a/doc/cmake.dox +++ b/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 diff --git a/doc/debug-tools.dox b/doc/debug-tools.dox index 95f4ded6d..2ffe8df0f 100644 --- a/doc/debug-tools.dox +++ b/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 */ } diff --git a/doc/features.dox b/doc/features.dox index a2e0e22db..bd0ba5ff9 100644 --- a/doc/features.dox +++ b/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 diff --git a/doc/mainpage.dox b/doc/mainpage.dox index d24de7caf..4cea30e2d 100644 --- a/doc/mainpage.dox +++ b/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 diff --git a/doc/matrix-vector.dox b/doc/matrix-vector.dox index c5703196a..e3b112bbc 100644 --- a/doc/matrix-vector.dox +++ b/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 a; +Math::Vector3 b, c; Math::Matrix3 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::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. + +  + +- Previous page: @ref types +- Next page: @ref transformations */ -}} +} diff --git a/doc/namespaces.dox b/doc/namespaces.dox index 229abad25..043c7676e 100644 --- a/doc/namespaces.dox +++ b/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. */ diff --git a/doc/platform.dox b/doc/platform.dox index ffecf7b8d..18293bca0 100644 --- a/doc/platform.dox +++ b/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 #`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 #include #include #include 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 +#`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 #include 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 */ }} diff --git a/doc/portability.dox b/doc/portability.dox index d2b2870d7..1596e55d0 100644 --- a/doc/portability.dox +++ b/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 diff --git a/doc/scenegraph.dox b/doc/scenegraph.dox index 3d59a8849..739d52ce8 100644 --- a/doc/scenegraph.dox +++ b/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 Scene3D; typedef SceneGraph::Object 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 */ }} diff --git a/doc/shapes.dox b/doc/shapes.dox index 37bc127ca..78de697db 100644 --- a/doc/shapes.dox +++ b/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(object, {{}, 23.0f}); See also @ref scenegraph for introduction. +- Previous page: @ref scenegraph +- Next page: @ref debug-tools + */ }}} diff --git a/doc/transformations.dox b/doc/transformations.dox index 138adb951..14ccd13f5 100644 --- a/doc/transformations.dox +++ b/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 */ }} diff --git a/doc/types.dox b/doc/types.dox index 3ddb332a6..3dae4a703 100644 --- a/doc/types.dox +++ b/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 */ } diff --git a/doc/unsupported.dox b/doc/unsupported.dox index 3fb080cdf..e4e371880 100644 --- a/doc/unsupported.dox +++ b/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. + +*/ diff --git a/external/OpenGL/GL/gl_magnum.c b/external/OpenGL/GL/gl_magnum.c index d1d89afb6..3276c865c 100644 --- a/external/OpenGL/GL/gl_magnum.c +++ b/external/OpenGL/GL/gl_magnum.c @@ -4,27 +4,15 @@ #include "gl_magnum.h" #if defined(__APPLE__) -#include +#include -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__ */ diff --git a/external/Optional/optional.hpp b/external/Optional/optional.hpp index aca993222..69b9f1c4b 100644 --- a/external/Optional/optional.hpp +++ b/external/Optional/optional.hpp @@ -155,7 +155,9 @@ template inline constexpr typename std::remove_reference::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); diff --git a/modules/FindCorrade.cmake b/modules/FindCorrade.cmake index 6aa24e864..e62d66519 100644 --- a/modules/FindCorrade.cmake +++ b/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) diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index b950d1026..c6223bf79 100644 --- a/modules/FindMagnum.cmake +++ b/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) diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index da4256007..c6504d974 100644 --- a/src/AbstractShaderProgram.h +++ b/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. diff --git a/src/AbstractTexture.cpp b/src/AbstractTexture.cpp index efed4f597..1a9278b81 100644 --- a/src/AbstractTexture.cpp +++ b/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()) { Debug() << "AbstractTexture: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index 38e4272e0..6147dfc10 100644 --- a/src/AbstractTexture.h +++ b/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 /** diff --git a/src/Audio/Audio.cpp b/src/Audio/Audio.cpp index 25c70e5e4..fa382b100 100644 --- a/src/Audio/Audio.cpp +++ b/src/Audio/Audio.cpp @@ -31,7 +31,12 @@ namespace Magnum { namespace Audio { /* Verify types */ static_assert(std::is_same::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::value, "ALbyte is not the same as Byte"); +#else +static_assert(std::is_signed::value && sizeof(ALbyte) == 1, "ALbyte does not have the same characteristics as Byte"); +#endif static_assert(std::is_same::value, "ALushort is not the same as UnsignedShort"); static_assert(std::is_same::value, "ALshort is not the same as Short"); static_assert(std::is_same::value, "ALuint is not the same as UnsignedInt"); diff --git a/src/Audio/CMakeLists.txt b/src/Audio/CMakeLists.txt index ba125c954..3f1a20870 100644 --- a/src/Audio/CMakeLists.txt +++ b/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) diff --git a/src/Buffer.h b/src/Buffer.h index 18810d0b2..57437c452 100644 --- a/src/Buffer.h +++ b/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 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, Usage) "setData(Containers::ArrayReference, Usage)" + * instead. */ - #ifdef CORRADE_GCC46_COMPATIBILITY - #define size size_ /* With GCC 4.6 it conflicts with size(). WTF. */ - #endif - template 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 Buffer& setData(const std::vector& data, Usage usage) { - setData(data.size()*sizeof(T), data.data(), usage); + setData({data.data(), data.size()}, usage); return *this; } /** @overload */ template Buffer& setData(const std::array& 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 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) "setSubData(GLintptr, Containers::ArrayReference)" + * instead. */ - #ifdef CORRADE_GCC46_COMPATIBILITY - #define size size_ /* With GCC 4.6 it conflicts with size(). WTF. */ - #endif - template 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 Buffer& setSubData(GLintptr offset, const std::vector& data) { - setSubData(offset, data.size()*sizeof(T), data.data()); + setSubData(offset, {data.data(), data.size()}); return *this; } /** @overload */ template Buffer& setSubData(GLintptr offset, const std::array& 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 diff --git a/src/BufferImage.cpp b/src/BufferImage.cpp index 35edf27d9..9099845d8 100644 --- a/src/BufferImage.cpp +++ b/src/BufferImage.cpp @@ -31,7 +31,7 @@ template void BufferImage::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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 60fae1f64..c3b7b0688 100644 --- a/src/CMakeLists.txt +++ b/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) diff --git a/src/Color.h b/src/Color.h index 0c3de3ac4..dc0ca3108 100644 --- a/src/Color.h +++ b/src/Color.h @@ -202,13 +202,6 @@ template class BasicColor3: public Math::Vector3 { /** @brief Copy constructor */ constexpr BasicColor3(const Math::Vector<3, T>& other): Math::Vector3(other) {} - T& r() { return Math::Vector3::x(); } /**< @brief R component */ - constexpr T r() const { return Math::Vector3::x(); } /**< @overload */ - T& g() { return Math::Vector3::y(); } /**< @brief G component */ - constexpr T g() const { return Math::Vector3::y(); } /**< @overload */ - T& b() { return Math::Vector3::z(); } /**< @brief B component */ - constexpr T b() const { return Math::Vector3::z(); } /**< @overload */ - /** * @brief Convert to HSV * @@ -336,42 +329,24 @@ class BasicColor4: public Math::Vector4 { /** @brief Copy constructor */ constexpr BasicColor4(const Math::Vector<4, T>& other): Math::Vector4(other) {} - T& r() { return Math::Vector4::x(); } /**< @brief R component */ - constexpr T r() const { return Math::Vector4::x(); } /**< @overload */ - T& g() { return Math::Vector4::y(); } /**< @brief G component */ - constexpr T g() const { return Math::Vector4::y(); } /**< @overload */ - T& b() { return Math::Vector4::z(); } /**< @brief B component */ - constexpr T b() const { return Math::Vector4::z(); } /**< @overload */ - T& a() { return Math::Vector4::w(); } /**< @brief A component */ - constexpr T a() const { return Math::Vector4::w(); } /**< @overload */ - - /** - * @brief RGB part of the vector - * @return First three components of the vector - * - * @see swizzle() - */ - BasicColor3& rgb() { return BasicColor3::from(Math::Vector4::data()); } - constexpr BasicColor3 rgb() const { return BasicColor3::from(Math::Vector4::data()); } /**< @overload */ - /** @copydoc BasicColor3::toHSV() */ constexpr HSV toHSV() const { - return Implementation::toHSV(rgb()); + return Implementation::toHSV(Math::Vector4::rgb()); } /** @copydoc BasicColor3::hue() */ constexpr Math::Deg hue() const { - return Implementation::hue(rgb()); + return Implementation::hue(Math::Vector4::rgb()); } /** @copydoc BasicColor3::saturation() */ constexpr FloatingPointType saturation() const { - return Implementation::saturation(rgb()); + return Implementation::saturation(Math::Vector4::rgb()); } /** @copydoc BasicColor3::value() */ constexpr FloatingPointType value() const { - return Implementation::value(rgb()); + return Implementation::value(Math::Vector4::rgb()); } MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(4, BasicColor4) @@ -392,6 +367,13 @@ template inline Debug operator<<(Debug debug, const BasicColor4& val return debug << static_cast&>(value); } +namespace Math { namespace Implementation { + template struct TypeForSize<3, BasicColor3> { typedef BasicColor3 Type; }; + template struct TypeForSize<3, BasicColor4> { typedef BasicColor3 Type; }; + template struct TypeForSize<4, BasicColor3> { typedef BasicColor4 Type; }; + template struct TypeForSize<4, BasicColor4> { typedef BasicColor4 Type; }; +}} + } namespace Corrade { namespace Utility { diff --git a/src/ColorFormat.h b/src/ColorFormat.h index a1150e10f..918ff0d42 100644 --- a/src/ColorFormat.h +++ b/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. diff --git a/src/DebugTools/CMakeLists.txt b/src/DebugTools/CMakeLists.txt index d348e3b8b..987e07a5e 100644 --- a/src/DebugTools/CMakeLists.txt +++ b/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) diff --git a/src/DebugTools/Test/CapsuleRendererTest.cpp b/src/DebugTools/Test/CapsuleRendererTest.cpp index 4c0f7d762..0ec537c9c 100644 --- a/src/DebugTools/Test/CapsuleRendererTest.cpp +++ b/src/DebugTools/Test/CapsuleRendererTest.cpp @@ -55,9 +55,9 @@ void CapsuleRendererTest::zeroLength2D() { const Vector2 a(0.5f, 3.0f); std::array 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 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); diff --git a/src/DebugTools/Test/CylinderRendererTest.cpp b/src/DebugTools/Test/CylinderRendererTest.cpp index 958003f96..9c18c51fa 100644 --- a/src/DebugTools/Test/CylinderRendererTest.cpp +++ b/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); } diff --git a/src/Extensions.h b/src/Extensions.h index e9fce378a..98b20519a 100644 --- a/src/Extensions.h +++ b/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 */ diff --git a/src/ImageFormat.h b/src/ImageFormat.h index 803b6372c..5ec6e8a31 100644 --- a/src/ImageFormat.h +++ b/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 diff --git a/src/Magnum.h b/src/Magnum.h index 2d5e8302e..4bb9a4943 100644 --- a/src/Magnum.h +++ b/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 Vector3i; /** @brief Four-component signed integer vector */ typedef Math::Vector4 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 Matrix3; -/** @brief 4x4 float matrix */ +/** +@brief 4x4 float transformation matrix + +@see @ref Matrix4x4 +*/ typedef Math::Matrix4 Matrix4; +/** @brief 2x2 float matrix */ +#ifndef CORRADE_GCC46_COMPATIBILITY +typedef Math::Matrix2x2 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 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 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 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 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 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 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 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 Matrix4x3; +#else typedef Math::RectangularMatrix<4, 3, Float> Matrix4x3; +#endif /** @brief Float complex number */ typedef Math::Complex Complex; @@ -249,32 +328,100 @@ typedef Math::Vector3 Vector3d; /** @brief Four-component double vector */ typedef Math::Vector4 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 Matrix3d; -/** @brief 4x4 double matrix */ +/** +@brief 4x4 double transformation matrix + +@see @ref Matrix4x4d +*/ typedef Math::Matrix4 Matrix4d; +/** @brief 2x2 double matrix */ +#ifndef CORRADE_GCC46_COMPATIBILITY +typedef Math::Matrix2x2 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 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 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 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 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 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 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 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 Matrix4x3d; +#else typedef Math::RectangularMatrix<4, 3, Double> Matrix4x3d; +#endif /** @brief Double complex number */ typedef Math::Complex Complexd; @@ -423,11 +570,4 @@ class Timeline; } -namespace std { - #ifndef DOXYGEN_GENERATING_OUTPUT - template struct hash; - #endif - template<> struct hash; -} - #endif diff --git a/src/Math/Algorithms/Test/GaussJordanTest.cpp b/src/Math/Algorithms/Test/GaussJordanTest.cpp index 80ef9c1e5..b20652c18 100644 --- a/src/Math/Algorithms/Test/GaussJordanTest.cpp +++ b/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))); } }}}} diff --git a/src/Math/Algorithms/Test/GramSchmidtTest.cpp b/src/Math/Algorithms/Test/GramSchmidtTest.cpp index 28700089d..494615329 100644 --- a/src/Math/Algorithms/Test/GramSchmidtTest.cpp +++ b/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); } diff --git a/src/Math/Math.h b/src/Math/Math.h index 77b237b9a..ab239d11b 100644 --- a/src/Math/Math.h +++ b/src/Math/Math.h @@ -30,6 +30,8 @@ #include +#include "corradeConfigure.h" + namespace Magnum { namespace Math { /** @todo Denormals to zero */ @@ -42,12 +44,26 @@ template class DualComplex; template class DualQuaternion; template class Matrix; +#ifndef CORRADE_GCC46_COMPATIBILITY +template using Matrix2x2 = Matrix<2, T>; +template using Matrix3x3 = Matrix<3, T>; +template using Matrix4x4 = Matrix<4, T>; +#endif + template class Matrix3; template class Matrix4; template class Quaternion; template class RectangularMatrix; +#ifndef CORRADE_GCC46_COMPATIBILITY +template using Matrix2x3 = RectangularMatrix<2, 3, T>; +template using Matrix3x2 = RectangularMatrix<3, 2, T>; +template using Matrix2x4 = RectangularMatrix<2, 4, T>; +template using Matrix4x2 = RectangularMatrix<4, 2, T>; +template using Matrix3x4 = RectangularMatrix<3, 4, T>; +template using Matrix4x3 = RectangularMatrix<4, 3, T>; +#endif template class, class> class Unit; template class Deg; diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index 39a5d4bd8..b1e7313f0 100644 --- a/src/Math/Matrix.h +++ b/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 class Matrix: public RectangularMatrix { public: @@ -89,9 +89,9 @@ template class Matrix: public RectangularMatrix floatingPoint({1.3f, 2.7f}, + * Matrix2x2 floatingPoint({1.3f, 2.7f}, * {-15.0f, 7.0f}); - * Matrix<2, Byte> integral(floatingPoint); + * Matrix2x2 integral(floatingPoint); * // integral == {{1, 2}, {-15, 7}} * @endcode */ @@ -184,6 +184,40 @@ template class Matrix: public RectangularMatrix%Matrix<2, T>. See @ref Matrix for more +information. +@note Not available on GCC < 4.7. Use %Matrix<2, T> instead. +@see @ref Magnum::Matrix2x2, @ref Magnum::Matrix2x2d +*/ +template using Matrix2x2 = Matrix<2, T>; + +/** +@brief 3x3 matrix + +Convenience alternative to %Matrix<3, T>. 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 %Matrix<3, T> instead. +@see @ref Magnum::Matrix3x3, @ref Magnum::Matrix3x3d +*/ +template using Matrix3x3 = Matrix<3, T>; + +/** +@brief 4x4 matrix + +Convenience alternative to %Matrix<4, T>. 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 %Matrix<3, T> instead. +@see @ref Magnum::Matrix4x4, @ref Magnum::Matrix4x4d +*/ +template using Matrix4x4 = Matrix<4, T>; +#endif + MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(Matrix) /** @debugoperator{Magnum::Math::Matrix} */ diff --git a/src/Math/RectangularMatrix.h b/src/Math/RectangularMatrix.h index 4baff2d57..b0d03d52d 100644 --- a/src/Math/RectangularMatrix.h +++ b/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 class RectangularMatrix { static_assert(cols != 0 && rows != 0, "RectangularMatrix cannot have zero elements"); @@ -396,6 +395,74 @@ template class RectangularMatrix { Vector _data[cols]; }; +#ifndef CORRADE_GCC46_COMPATIBILITY +/** +@brief Matrix with 2 columns and 3 rows + +Convenience alternative to %RectangularMatrix<2, 3, T>. See +@ref RectangularMatrix for more information. +@note Not available on GCC < 4.7. Use %RectangularMatrix<2, 3, T> + instead. +@see @ref Magnum::Matrix2x3, @ref Magnum::Matrix2x3d +*/ +template using Matrix2x3 = RectangularMatrix<2, 3, T>; + +/** +@brief Matrix with 3 columns and 2 rows + +Convenience alternative to %RectangularMatrix<3, 2, T>. See +@ref RectangularMatrix for more information. +@note Not available on GCC < 4.7. Use %RectangularMatrix<3, 2, T> + instead. +@see @ref Magnum::Matrix3x2, @ref Magnum::Matrix3x2d +*/ +template using Matrix3x2 = RectangularMatrix<3, 2, T>; + +/** +@brief Matrix with 2 columns and 4 rows + +Convenience alternative to %RectangularMatrix<2, 4, T>. See +@ref RectangularMatrix for more information. +@note Not available on GCC < 4.7. Use %RectangularMatrix<2, 4, T> + instead. +@see @ref Magnum::Matrix2x4, @ref Magnum::Matrix2x4d +*/ +template using Matrix2x4 = RectangularMatrix<2, 4, T>; + +/** +@brief Matrix with 4 columns and 2 rows + +Convenience alternative to %RectangularMatrix<4, 2, T>. See +@ref RectangularMatrix for more information. +@note Not available on GCC < 4.7. Use %RectangularMatrix<4, 2, T> + instead. +@see @ref Magnum::Matrix4x2, @ref Magnum::Matrix4x2d +*/ +template using Matrix4x2 = RectangularMatrix<4, 2, T>; + +/** +@brief Matrix with 3 columns and 4 rows + +Convenience alternative to %RectangularMatrix<3, 4, T>. See +@ref RectangularMatrix for more information. +@note Not available on GCC < 4.7. Use %RectangularMatrix<3, 4, T> + instead. +@see @ref Magnum::Matrix3x4, @ref Magnum::Matrix3x4d +*/ +template using Matrix3x4 = RectangularMatrix<3, 4, T>; + +/** +@brief Matrix with 4 columns and 3 rows + +Convenience alternative to %RectangularMatrix<4, 3, T>. See +@ref RectangularMatrix for more information. +@note Not available on GCC < 4.7. Use %RectangularMatrix<4, 3, T> + instead. +@see @ref Magnum::Matrix4x3, @ref Magnum::Matrix4x3d +*/ +template using Matrix4x3 = RectangularMatrix<4, 3, T>; +#endif + /** @relates RectangularMatrix @brief Multiply number with matrix diff --git a/src/Math/Swizzle.h b/src/Math/Swizzle.h index 1ac9746b3..0a8606ffa 100644 --- a/src/Math/Swizzle.h +++ b/src/Math/Swizzle.h @@ -44,12 +44,20 @@ namespace Implementation { template struct Component: public ComponentAtPosition {}; template struct Component: public ComponentAtPosition {}; template struct Component: public ComponentAtPosition {}; + template struct Component: public ComponentAtPosition {}; + template struct Component: public ComponentAtPosition {}; + template struct Component: public ComponentAtPosition {}; + template struct Component: public ComponentAtPosition {}; template struct Component { template constexpr static T value(const Math::Vector&) { return T(0); } }; template struct Component { template constexpr static T value(const Math::Vector&) { return T(1); } }; + + template struct TypeForSize { + typedef Math::Vector Type; + }; } /** @@ -57,23 +65,22 @@ namespace Implementation { Creates new vector from given components. Example: @code -Vector4 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 constexpr Vector swizzle(const Vector& vector) { - return {Implementation::Component::value(vector)...}; +template constexpr typename Implementation::TypeForSize::Type swizzle(const T& vector) { + return {Implementation::Component::value(vector)...}; } }} diff --git a/src/Math/Test/ComplexTest.cpp b/src/Math/Test/ComplexTest.cpp index ca5af8f47..6f9fd6521 100644 --- a/src/Math/Test/ComplexTest.cpp +++ b/src/Math/Test/ComplexTest.cpp @@ -100,7 +100,7 @@ typedef Math::Rad Rad; typedef Math::Complex Complex; typedef Math::Vector2 Vector2; typedef Math::Matrix3 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); diff --git a/src/Math/Test/Matrix3Test.cpp b/src/Math/Test/Matrix3Test.cpp index 778f78e3a..f774392e7 100644 --- a/src/Math/Test/Matrix3Test.cpp +++ b/src/Math/Test/Matrix3Test.cpp @@ -90,7 +90,7 @@ class Matrix3Test: public Corrade::TestSuite::Tester { typedef Math::Deg Deg; typedef Math::Matrix3 Matrix3; typedef Math::Matrix3 Matrix3i; -typedef Math::Matrix<2, Float> Matrix2; +typedef Math::Matrix<2, Float> Matrix2x2; typedef Math::Vector3 Vector3; typedef Math::Vector2 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() { diff --git a/src/Math/Test/Matrix4Test.cpp b/src/Math/Test/Matrix4Test.cpp index 0ccfbc13f..5a5065608 100644 --- a/src/Math/Test/Matrix4Test.cpp +++ b/src/Math/Test/Matrix4Test.cpp @@ -98,7 +98,7 @@ typedef Math::Deg Deg; typedef Math::Rad Rad; typedef Math::Matrix4 Matrix4; typedef Math::Matrix4 Matrix4i; -typedef Math::Matrix<3, Float> Matrix3; +typedef Math::Matrix<3, Float> Matrix3x3; typedef Math::Vector3 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() { diff --git a/src/Math/Test/MatrixTest.cpp b/src/Math/Test/MatrixTest.cpp index 3f6a81e8b..2f9d0c226 100644 --- a/src/Math/Test/MatrixTest.cpp +++ b/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::value)); + CORRADE_VERIFY(!(std::is_convertible::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::value)); + CORRADE_VERIFY(!(std::is_convertible::value)); { #ifdef CORRADE_GCC44_COMPATIBILITY CORRADE_EXPECT_FAIL("GCC 4.4 doesn't have explicit conversion operators"); #endif - CORRADE_VERIFY(!(std::is_convertible::value)); + CORRADE_VERIFY(!(std::is_convertible::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("matrix"), m); + CORRADE_COMPARE(c.value("matrix"), m); } }}} diff --git a/src/Math/Test/QuaternionTest.cpp b/src/Math/Test/QuaternionTest.cpp index 1ab42012f..1d4413861 100644 --- a/src/Math/Test/QuaternionTest.cpp +++ b/src/Math/Test/QuaternionTest.cpp @@ -69,7 +69,7 @@ class QuaternionTest: public Corrade::TestSuite::Tester { typedef Math::Deg Deg; typedef Math::Rad Rad; -typedef Math::Matrix<3, Float> Matrix3; +typedef Math::Matrix<3, Float> Matrix3x3; typedef Math::Matrix4 Matrix4; typedef Math::Quaternion Quaternion; typedef Math::Vector3 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); diff --git a/src/Math/Test/RectangularMatrixTest.cpp b/src/Math/Test/RectangularMatrixTest.cpp index 4da3c411f..f3a591ecf 100644 --- a/src/Math/Test/RectangularMatrixTest.cpp +++ b/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::value)); + CORRADE_VERIFY(!(std::is_convertible::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::epsilon()/2, -3.0f), - Vector2(5.0f, -10.0f)); - Matrix2 c(Vector2(1.0f, -1.0f + TypeTraits::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::epsilon()/2, -3.0f), + Vector2(5.0f, -10.0f)); + Matrix2x2 c(Vector2(1.0f, -1.0f + TypeTraits::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); } diff --git a/src/Math/Test/SwizzleTest.cpp b/src/Math/Test/SwizzleTest.cpp index 5f01b4e62..19968ca72 100644 --- a/src/Math/Test/SwizzleTest.cpp +++ b/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))); diff --git a/src/Math/Test/Vector2Test.cpp b/src/Math/Test/Vector2Test.cpp index 848968a80..52a9b97e8 100644 --- a/src/Math/Test/Vector2Test.cpp +++ b/src/Math/Test/Vector2Test.cpp @@ -26,7 +26,7 @@ #include #include -#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::value)); +} + void Vector2Test::debug() { std::ostringstream o; Debug(&o) << Vector2(0.5f, 15.0f); diff --git a/src/Math/Test/Vector3Test.cpp b/src/Math/Test/Vector3Test.cpp index 7ebb20eb8..e30f60a57 100644 --- a/src/Math/Test/Vector3Test.cpp +++ b/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::value)); +} + void Vector3Test::debug() { std::ostringstream o; Debug(&o) << Vector3(0.5f, 15.0f, 1.0f); diff --git a/src/Math/Test/Vector4Test.cpp b/src/Math/Test/Vector4Test.cpp index fc345eeb5..c055870a5 100644 --- a/src/Math/Test/Vector4Test.cpp +++ b/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::value)); +} + void Vector4Test::debug() { std::ostringstream o; Debug(&o) << Vector4(0.5f, 15.0f, 1.0f, 1.0f); diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index c6ba1ecfc..229e48e20 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -138,6 +138,15 @@ template class Vector2: public Vector<2, T> { */ Vector2 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 inline Corrade::Utility::Debug operator<<(Corrade::Utility::De return debug << static_cast&>(value); } +namespace Implementation { + template struct TypeForSize; + template struct TypeForSize<2, T> { typedef Math::Vector2 Type; }; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index f43875c89..be129bd4c 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -149,13 +149,55 @@ template 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 inline Corrade::Utility::Debug operator<<(Corrade::Utility::De return debug << static_cast&>(value); } +namespace Implementation { + template struct TypeForSize<3, T> { typedef Math::Vector3 Type; }; +} + }} namespace Corrade { namespace Utility { diff --git a/src/Math/Vector4.h b/src/Math/Vector4.h index 5aeb9ff83..8ea29bd86 100644 --- a/src/Math/Vector4.h +++ b/src/Math/Vector4.h @@ -79,29 +79,94 @@ template 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& xyz() { return Vector3::from(Vector<4, T>::data()); } constexpr const Vector3 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& rgb() { return xyz(); } + constexpr const Vector3 rgb() const { return xyz(); } /**< @overload */ + /** * @brief XY part of the vector * @return First two components of the vector * - * @see swizzle() + * @see @ref swizzle() */ Vector2& xy() { return Vector2::from(Vector<4, T>::data()); } constexpr const Vector2 xy() const { return {x(), y()}; } /**< @overload */ @@ -116,6 +181,10 @@ template inline Corrade::Utility::Debug operator<<(Corrade::Utility::De return debug << static_cast&>(value); } +namespace Implementation { + template struct TypeForSize<4, T> { typedef Math::Vector4 Type; }; +} + }} namespace Corrade { namespace Utility { diff --git a/src/MeshTools/CMakeLists.txt b/src/MeshTools/CMakeLists.txt index 65f52a8dd..8f47e0c20 100644 --- a/src/MeshTools/CMakeLists.txt +++ b/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) diff --git a/src/MeshTools/CompressIndices.cpp b/src/MeshTools/CompressIndices.cpp index 3735abd2e..e81c890c9 100644 --- a/src/MeshTools/CompressIndices.cpp +++ b/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; } diff --git a/src/MeshTools/Interleave.h b/src/MeshTools/Interleave.h index 82e424d03..4a5c2d2c9 100644 --- a/src/MeshTools/Interleave.h +++ b/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; } diff --git a/src/Platform/AbstractXApplication.cpp b/src/Platform/AbstractXApplication.cpp index 2951900c0..c4d523d37 100644 --- a/src/Platform/AbstractXApplication.cpp +++ b/src/Platform/AbstractXApplication.cpp @@ -27,6 +27,7 @@ #include #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* contextHandler, const Arguments&, const Configuration& configuration): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) { +AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments&, const Configuration& configuration): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) { createContext(configuration); } #ifndef DOXYGEN_GENERATING_OUTPUT -AbstractXApplication::AbstractXApplication(AbstractContextHandler* contextHandler, const Arguments&): contextHandler(contextHandler), c(nullptr), flags(Flag::Redraw) { +AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* 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* contextHandler, const Arguments&, std::nullptr_t) +AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments&, std::nullptr_t) #else -AbstractXApplication::AbstractXApplication(AbstractContextHandler* contextHandler, const Arguments&, void*) +AbstractXApplication::AbstractXApplication(Implementation::AbstractContextHandler* 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; diff --git a/src/Platform/AbstractXApplication.h b/src/Platform/AbstractXApplication.h index b773411c3..9c330faff 100644 --- a/src/Platform/AbstractXApplication.h +++ b/src/Platform/AbstractXApplication.h @@ -25,7 +25,7 @@ */ /** @file - * @brief Class Magnum::Platform::AbstractXApplication + * @brief Class @ref Magnum::Platform::AbstractXApplication */ #include @@ -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 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* contextHandler, const Arguments& arguments, const Configuration& configuration = Configuration()); - #else - /* To avoid "invalid use of incomplete type" */ - explicit AbstractXApplication(AbstractContextHandler* contextHandler, const Arguments& arguments, const Configuration& configuration); - explicit AbstractXApplication(AbstractContextHandler* 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* contextHandler, const Arguments& arguments, std::nullptr_t); - #else - explicit AbstractXApplication(AbstractContextHandler* 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* contextHandler, const Arguments& arguments, const Configuration& configuration); + explicit AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments& arguments); + + #ifndef CORRADE_GCC45_COMPATIBILITY + explicit AbstractXApplication(Implementation::AbstractContextHandler* contextHandler, const Arguments& arguments, std::nullptr_t); + #else + explicit AbstractXApplication(Implementation::AbstractContextHandler* 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* contextHandler; + Implementation::AbstractContextHandler* 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 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 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(_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 diff --git a/src/Platform/CMakeLists.txt b/src/Platform/CMakeLists.txt index 127e8f9fe..46b60f929 100644 --- a/src/Platform/CMakeLists.txt +++ b/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 $ - $) + $ + 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 $ - $) + $ + 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 diff --git a/src/Platform/EmscriptenApplication.js b/src/Platform/EmscriptenApplication.js new file mode 100644 index 000000000..96717b5f8 --- /dev/null +++ b/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); diff --git a/src/Platform/GlutApplication.cpp b/src/Platform/GlutApplication.cpp index 718db343f..86c4532ce 100644 --- a/src/Platform/GlutApplication.cpp +++ b/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); } diff --git a/src/Platform/GlutApplication.h b/src/Platform/GlutApplication.h index f76f081fc..ef5aa22a6 100644 --- a/src/Platform/GlutApplication.h +++ b/src/Platform/GlutApplication.h @@ -25,7 +25,7 @@ */ /** @file - * @brief Class Magnum::Platform::GlutApplication + * @brief Class @ref Magnum::Platform::GlutApplication */ #include @@ -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 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&) {} diff --git a/src/Platform/GlxApplication.cpp b/src/Platform/GlxApplication.cpp new file mode 100644 index 000000000..848ba0af0 --- /dev/null +++ b/src/Platform/GlxApplication.cpp @@ -0,0 +1,35 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + 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) {} + +}} diff --git a/src/Platform/GlxApplication.h b/src/Platform/GlxApplication.h index 136cf75a0..3280fec13 100644 --- a/src/Platform/GlxApplication.h +++ b/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 diff --git a/src/Platform/AbstractContextHandler.h b/src/Platform/Implementation/AbstractContextHandler.h similarity index 91% rename from src/Platform/AbstractContextHandler.h rename to src/Platform/Implementation/AbstractContextHandler.h index 6d88ce491..3c279c003 100644 --- a/src/Platform/AbstractContextHandler.h +++ b/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 AbstractContextHandl template inline AbstractContextHandler::AbstractContextHandler() = default; -}} +}}} #endif diff --git a/src/Platform/EglContextHandler.cpp b/src/Platform/Implementation/EglContextHandler.cpp similarity index 98% rename from src/Platform/EglContextHandler.cpp rename to src/Platform/Implementation/EglContextHandler.cpp index 56dd92cd1..ed7d523a0 100644 --- a/src/Platform/EglContextHandler.cpp +++ b/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 {}; } -}} +}}} diff --git a/src/Platform/EglContextHandler.h b/src/Platform/Implementation/EglContextHandler.h similarity index 92% rename from src/Platform/EglContextHandler.h rename to src/Platform/Implementation/EglContextHandler.h index 6c1869b7c..32cc2da94 100644 --- a/src/Platform/EglContextHandler.h +++ b/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 /* 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 AbstractContextHandlerResizeBuffers(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(); diff --git a/src/Platform/NaClApplication.h b/src/Platform/NaClApplication.h index 38353e3be..914906368 100644 --- a/src/Platform/NaClApplication.h +++ b/src/Platform/NaClApplication.h @@ -25,7 +25,7 @@ */ /** @file - * @brief Class Magnum::Platform::NaClApplication + * @brief Class @ref Magnum::Platform::NaClApplication */ #include @@ -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 `<application>` to name of your executable. @code - - -Magnum NaCl Application - - - - -

Magnum NaCl Application

-
- - -
Initialization...
-
-
- + + + Magnum NaCl Application + + + + +

Magnum NaCl Application

+
+ +
Initialization...
+
+ +
+ @endcode @@ -106,12 +115,12 @@ The CSS file contains rudimentary style to avoid eye bleeding. The `<embed>` 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 `<application>` to name of your executable): @code { "program": { - "x86-32": {"url": "application-x86-32.nexe"}, - "x86-64": {"url": "application-x86-64.nexe"} + "x86-32": {"url": "-x86-32.nexe"}, + "x86-64": {"url": "-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 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 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 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&) {} diff --git a/src/Platform/Sdl2Application.cpp b/src/Platform/Sdl2Application.cpp index 7fb919d46..efb7338c5 100644 --- a/src/Platform/Sdl2Application.cpp +++ b/src/Platform/Sdl2Application.cpp @@ -24,6 +24,10 @@ #include "Sdl2Application.h" +#ifdef CORRADE_TARGET_EMSCRIPTEN +#include +#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(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(enabled); + #endif } Sdl2Application::Configuration::Configuration(): _title("Magnum SDL2 Application"), _size(800, 600), _flags(Flag::Resizable), _sampleCount(0) {} diff --git a/src/Platform/Sdl2Application.h b/src/Platform/Sdl2Application.h index 9fafc78f8..025b28553 100644 --- a/src/Platform/Sdl2Application.h +++ b/src/Platform/Sdl2Application.h @@ -25,9 +25,11 @@ */ /** @file - * @brief Class Magnum::Platform::Sdl2Application + * @brief Class @ref Magnum::Platform::Sdl2Application */ +#include + #include "Math/Vector2.h" #include "Magnum.h" @@ -36,7 +38,8 @@ #endif #include #include -#include +#include +#include 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 `<application>` to name of your executable. +@code + + + + Magnum Emscripten Application + + + + +

Magnum Emscripten Application

+
+ +
Initialization...
+
+ + +
+ + +@endcode + +You can modify all the files to your liking, but the HTML file must contain at +least the `<canvas>` enclosed in listener `<div>`. The JavaScript +file contains event listeners which print loading status on the page. The +status displayed in the remaining two `<div>`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 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 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&) {} diff --git a/src/Platform/NaClApplication.css b/src/Platform/WebApplication.css similarity index 100% rename from src/Platform/NaClApplication.css rename to src/Platform/WebApplication.css diff --git a/src/Platform/WindowlessGlxApplication.h b/src/Platform/WindowlessGlxApplication.h index d5a94aea1..0e32c43cd 100644 --- a/src/Platform/WindowlessGlxApplication.h +++ b/src/Platform/WindowlessGlxApplication.h @@ -25,7 +25,7 @@ */ /** @file - * @brief Class Magnum::Platform::WindowlessGlxApplication + * @brief Class @ref Magnum::Platform::WindowlessGlxApplication */ #include @@ -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. */ diff --git a/src/Platform/WindowlessNaClApplication.h b/src/Platform/WindowlessNaClApplication.h index 249aebe13..cb5ceaacd 100644 --- a/src/Platform/WindowlessNaClApplication.h +++ b/src/Platform/WindowlessNaClApplication.h @@ -25,7 +25,7 @@ */ /** @file - * @brief Class Magnum::Platform::WindowlessNaClApplication + * @brief Class @ref Magnum::Platform::WindowlessNaClApplication */ #include @@ -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. diff --git a/src/Platform/XEglApplication.cpp b/src/Platform/XEglApplication.cpp new file mode 100644 index 000000000..4449db1b6 --- /dev/null +++ b/src/Platform/XEglApplication.cpp @@ -0,0 +1,35 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + 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) {} + +}} diff --git a/src/Platform/XEglApplication.h b/src/Platform/XEglApplication.h index 8eb94415f..d8981f9e9 100644 --- a/src/Platform/XEglApplication.h +++ b/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 diff --git a/src/Platform/magnum-info-nacl.html b/src/Platform/magnum-info-nacl.html index cd679fb9d..eb9941637 100644 --- a/src/Platform/magnum-info-nacl.html +++ b/src/Platform/magnum-info-nacl.html @@ -1,41 +1,41 @@ - - -Magnum Info - - - - - -

Magnum Info

-
- - + - -
Initialization...
-
-
-
- + var listener = document.getElementById('listener'); + listener.addEventListener('message', messageReceived, true); + +
+ diff --git a/src/Platform/magnum-info.cpp b/src/Platform/magnum-info.cpp index ca8ebfbc8..134ec7529 100644 --- a/src/Platform/magnum-info.cpp +++ b/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 diff --git a/src/Primitives/CMakeLists.txt b/src/Primitives/CMakeLists.txt index ae364551e..9dd217025 100644 --- a/src/Primitives/CMakeLists.txt +++ b/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) diff --git a/src/RenderbufferFormat.h b/src/RenderbufferFormat.h index 9cb0add81..9397bab46 100644 --- a/src/RenderbufferFormat.h +++ b/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, diff --git a/src/Sampler.h b/src/Sampler.h index 1991ae216..a19249ab8 100644 --- a/src/Sampler.h +++ b/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} */ diff --git a/src/SceneGraph/AbstractTransformation.h b/src/SceneGraph/AbstractTransformation.h index 01aa13ec3..b4b6c0d80 100644 --- a/src/SceneGraph/AbstractTransformation.h +++ b/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 - -#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 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::MatrixType toMatrix(const DataType& transformation); - - /** - * @brief Convert transformation from matrix - * - * Defined in subclasses. - */ - static DataType fromMatrix(const typename DimensionTraits::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 %AbstractTransformation<3, T>. See AbstractTransformation for more information. @note Not available on GCC < 4.7. Use %AbstractTransformation<3, T> instead. -@see @ref AbstractTransformation3D, @ref AbstractBasicTransformation3D +@see @ref AbstractTransformation3D, @ref AbstractBasicTransformation2D */ template using AbstractBasicTransformation3D = AbstractTransformation<3, T>; #endif diff --git a/src/SceneGraph/AbstractTranslation.h b/src/SceneGraph/AbstractTranslation.h new file mode 100644 index 000000000..df64b3d58 --- /dev/null +++ b/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š + + 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 +#else +template +#endif +class AbstractTranslation: public AbstractTransformation { + 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& translate(const typename DimensionTraits::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::VectorType& vector, TransformationType type) = 0; +}; + +#ifndef CORRADE_GCC46_COMPATIBILITY +/** +@brief Base transformation for two-dimensional scenes supporting translation + +Convenience alternative to %AbstractTranslation<2, T, TranslationType>. +See @ref AbstractTranslation for more information. +@note Not available on GCC < 4.7. Use %AbstractTranslation<2, T, TranslationType> + instead. +@see @ref AbstractTranslation2D, @ref AbstractBasicTranslation3D +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#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 AbstractTranslation2D; +#else +typedef AbstractTranslation<2, Float> AbstractTranslation2D; +#endif + +#ifndef CORRADE_GCC46_COMPATIBILITY +/** +@brief Base transformation for three-dimensional scenes supporting translation + +Convenience alternative to %AbstractTranslation<3, T, TranslationType>. +See @ref AbstractTranslation for more information. +@note Not available on GCC < 4.7. Use %AbstractTranslation<3, T, TranslationType> + instead. +@see @ref AbstractTranslation3D, @ref AbstractBasicTranslation2D +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#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 AbstractTranslation3D; +#else +typedef AbstractTranslation<3, Float> AbstractTranslation3D; +#endif + +}} + +#endif diff --git a/src/SceneGraph/AbstractTranslationRotation2D.h b/src/SceneGraph/AbstractTranslationRotation2D.h index 2d667e491..045379bcd 100644 --- a/src/SceneGraph/AbstractTranslationRotation2D.h +++ b/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 when support for GCC 4.6 is dropped */ -template class AbstractBasicTranslationRotation2D: public AbstractTransformation<2, T> { +template 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& translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { - doTranslate(vector, type); - return *this; - } - /** * @brief Rotate object * @param angle Angle (counterclockwise) @@ -82,9 +69,6 @@ template class AbstractBasicTranslationRotation2D: public AbstractTrans #else private: #endif - /** @brief Polymorphic implementation for translate() */ - virtual void doTranslate(const Math::Vector2& vector, TransformationType type) = 0; - /** @brief Polymorphic implementation for rotate() */ virtual void doRotate(Math::Rad angle, TransformationType type) = 0; }; diff --git a/src/SceneGraph/AbstractTranslationRotation3D.h b/src/SceneGraph/AbstractTranslationRotation3D.h index 48f4a5f69..66e494567 100644 --- a/src/SceneGraph/AbstractTranslationRotation3D.h +++ b/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 when support for GCC 4.6 is dropped */ -template class AbstractBasicTranslationRotation3D: public AbstractTransformation<3, T> { +template 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& translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { - doTranslate(vector, type); - return *this; - } - /** * @brief Rotate object * @param angle Angle (counterclockwise) @@ -129,9 +115,6 @@ template class AbstractBasicTranslationRotation3D: public AbstractTrans #else private: #endif - /** @brief Polymorphic implementation for translate() */ - virtual void doTranslate(const Math::Vector3& vector, TransformationType type) = 0; - /** @brief Polymorphic implementation for rotate() */ virtual void doRotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type) = 0; diff --git a/src/SceneGraph/CMakeLists.txt b/src/SceneGraph/CMakeLists.txt index 8238973a5..32b018ceb 100644 --- a/src/SceneGraph/CMakeLists.txt +++ b/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) diff --git a/src/SceneGraph/DualComplexTransformation.h b/src/SceneGraph/DualComplexTransformation.h index db0931dd5..a95d94365 100644 --- a/src/SceneGraph/DualComplexTransformation.h +++ b/src/SceneGraph/DualComplexTransformation.h @@ -46,40 +46,8 @@ template class BasicDualComplexTransformation: public AbstractBasicTran /** @brief Transformation type */ typedef Math::DualComplex DataType; - #ifndef DOXYGEN_GENERATING_OUTPUT - static Math::DualComplex fromMatrix(const Math::Matrix3& matrix) { - return Math::DualComplex::fromMatrix(matrix); - } - - constexpr static Math::Matrix3 toMatrix(const Math::DualComplex& transformation) { - return transformation.toMatrix(); - } - - static Math::DualComplex compose(const Math::DualComplex& parent, const Math::DualComplex& child) { - return parent*child; - } - - static Math::DualComplex inverted(const Math::DualComplex& transformation) { - return transformation.invertedNormalized(); - } - - Math::DualComplex 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>& normalizeRotation() { - setTransformationInternal(_transformation.normalized()); - return static_cast>&>(*this); - } + /** @brief Object transformation */ + Math::DualComplex transformation() const { return _transformation; } /** * @brief Set transformation @@ -92,14 +60,24 @@ template class BasicDualComplexTransformation: public AbstractBasicTran CORRADE_ASSERT(transformation.isNormalized(), "SceneGraph::DualComplexTransformation::setTransformation(): the dual complex number is not normalized", static_cast>&>(*this)); - setTransformationInternal(transformation); - return static_cast>&>(*this); + return setTransformationInternal(transformation); } /** @copydoc AbstractTranslationRotationScaling2D::resetTransformation() */ Object>& resetTransformation() { - setTransformationInternal({}); - return static_cast>&>(*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>& normalizeRotation() { + return setTransformationInternal(_transformation.normalized()); } /** @@ -115,8 +93,7 @@ template class BasicDualComplexTransformation: public AbstractBasicTran CORRADE_ASSERT(transformation.isNormalized(), "SceneGraph::DualComplexTransformation::transform(): the dual complex number is not normalized", static_cast>&>(*this)); - transformInternal(transformation, type); - return static_cast>&>(*this); + return transformInternal(transformation, type); } /** @@ -124,8 +101,7 @@ template class BasicDualComplexTransformation: public AbstractBasicTran * Same as calling transform() with DualComplex::translation(). */ Object>& translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { - transformInternal(Math::DualComplex::translation(vector), type); - return static_cast>&>(*this); + return transformInternal(Math::DualComplex::translation(vector), type); } /** @@ -138,8 +114,7 @@ template class BasicDualComplexTransformation: public AbstractBasicTran * @see normalizeRotation() */ Object>& rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { - transformInternal(Math::DualComplex::rotation(angle), type); - return static_cast>&>(*this); + return transformInternal(Math::DualComplex::rotation(angle), type); } /** @@ -169,7 +144,7 @@ template class BasicDualComplexTransformation: public AbstractBasicTran } /* No assertions fired, for internal use */ - void setTransformationInternal(const Math::DualComplex& transformation) { + Object>& setTransformationInternal(const Math::DualComplex& 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 BasicDualComplexTransformation: public AbstractBasicTran _transformation = transformation; static_cast>*>(this)->setDirty(); } + + return static_cast>&>(*this); } /* No assertions fired, for internal use */ - void transformInternal(const Math::DualComplex& transformation, TransformationType type) { - setTransformation(type == TransformationType::Global ? + Object>& transformInternal(const Math::DualComplex& transformation, TransformationType type) { + return setTransformationInternal(type == TransformationType::Global ? transformation*_transformation : _transformation*transformation); } @@ -197,6 +174,28 @@ template inline BasicDualComplexTransformation::BasicDualComplexTran */ typedef BasicDualComplexTransformation DualComplexTransformation; +namespace Implementation { + +template struct Transformation> { + static Math::DualComplex fromMatrix(const Math::Matrix3& matrix) { + return Math::DualComplex::fromMatrix(matrix); + } + + constexpr static Math::Matrix3 toMatrix(const Math::DualComplex& transformation) { + return transformation.toMatrix(); + } + + static Math::DualComplex compose(const Math::DualComplex& parent, const Math::DualComplex& child) { + return parent*child; + } + + static Math::DualComplex inverted(const Math::DualComplex& transformation) { + return transformation.invertedNormalized(); + } +}; + +} + }} #endif diff --git a/src/SceneGraph/DualQuaternionTransformation.h b/src/SceneGraph/DualQuaternionTransformation.h index fadfa662d..718be0c70 100644 --- a/src/SceneGraph/DualQuaternionTransformation.h +++ b/src/SceneGraph/DualQuaternionTransformation.h @@ -46,42 +46,8 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT /** @brief Underlying transformation type */ typedef Math::DualQuaternion DataType; - #ifndef DOXYGEN_GENERATING_OUTPUT - static Math::DualQuaternion fromMatrix(const Math::Matrix4& matrix) { - CORRADE_ASSERT(matrix.isRigidTransformation(), - "SceneGraph::DualQuaternionTransformation::fromMatrix(): the matrix doesn't represent rigid transformation", {}); - return Math::DualQuaternion::fromMatrix(matrix); - } - - constexpr static Math::Matrix4 toMatrix(const Math::DualQuaternion& transformation) { - return transformation.toMatrix(); - } - - static Math::DualQuaternion compose(const Math::DualQuaternion& parent, const Math::DualQuaternion& child) { - return parent*child; - } - - static Math::DualQuaternion inverted(const Math::DualQuaternion& transformation) { - return transformation.invertedNormalized(); - } - - Math::DualQuaternion 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>& normalizeRotation() { - setTransformation(_transformation.normalized()); - return static_cast>&>(*this); - } + /** @brief Object transformation */ + Math::DualQuaternion transformation() const { return _transformation; } /** * @brief Set transformation @@ -94,14 +60,24 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT CORRADE_ASSERT(transformation.isNormalized(), "SceneGraph::DualQuaternionTransformation::setTransformation(): the dual quaternion is not normalized", static_cast>&>(*this)); - setTransformationInternal(transformation); - return static_cast>&>(*this); + return setTransformationInternal(transformation); } /** @copydoc AbstractTranslationRotationScaling3D::resetTransformation() */ Object>& resetTransformation() { - setTransformation({}); - return static_cast>&>(*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>& normalizeRotation() { + return setTransformationInternal(_transformation.normalized()); } /** @@ -117,8 +93,7 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT CORRADE_ASSERT(transformation.isNormalized(), "SceneGraph::DualQuaternionTransformation::transform(): the dual quaternion is not normalized", static_cast>&>(*this)); - transformInternal(transformation, type); - return static_cast>&>(*this); + return transformInternal(transformation, type); } /** @@ -126,8 +101,7 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT * Same as calling transform() with DualQuaternion::translation(). */ Object>& translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { - transformInternal(Math::DualQuaternion::translation(vector), type); - return static_cast>&>(*this); + return transformInternal(Math::DualQuaternion::translation(vector), type); } /** @@ -142,8 +116,7 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT * normalizeRotation() */ Object>& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { - transformInternal(Math::DualQuaternion::rotation(angle, normalizedAxis), type); - return static_cast>&>(*this); + return transformInternal(Math::DualQuaternion::rotation(angle, normalizedAxis), type); } /* Overloads to remove WTF-factor from method chaining order */ @@ -175,7 +148,7 @@ template class BasicDualQuaternionTransformation: public AbstractBasicT } /* No assertions fired, for internal use */ - void setTransformationInternal(const Math::DualQuaternion& transformation) { + Object>& setTransformationInternal(const Math::DualQuaternion& 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 BasicDualQuaternionTransformation: public AbstractBasicT _transformation = transformation; static_cast>*>(this)->setDirty(); } + + return static_cast>&>(*this); } /* No assertions fired, for internal use */ - void transformInternal(const Math::DualQuaternion& transformation, TransformationType type) { - setTransformation(type == TransformationType::Global ? + Object>& transformInternal(const Math::DualQuaternion& transformation, TransformationType type) { + return setTransformationInternal(type == TransformationType::Global ? transformation*_transformation : _transformation*transformation); } @@ -203,6 +178,30 @@ template inline BasicDualQuaternionTransformation::BasicDualQuaterni */ typedef BasicDualQuaternionTransformation DualQuaternionTransformation; +namespace Implementation { + +template struct Transformation> { + static Math::DualQuaternion fromMatrix(const Math::Matrix4& matrix) { + CORRADE_ASSERT(matrix.isRigidTransformation(), + "SceneGraph::DualQuaternionTransformation: the matrix doesn't represent rigid transformation", {}); + return Math::DualQuaternion::fromMatrix(matrix); + } + + constexpr static Math::Matrix4 toMatrix(const Math::DualQuaternion& transformation) { + return transformation.toMatrix(); + } + + static Math::DualQuaternion compose(const Math::DualQuaternion& parent, const Math::DualQuaternion& child) { + return parent*child; + } + + static Math::DualQuaternion inverted(const Math::DualQuaternion& transformation) { + return transformation.invertedNormalized(); + } +}; + +} + }} #endif diff --git a/src/SceneGraph/MatrixTransformation2D.h b/src/SceneGraph/MatrixTransformation2D.h index f1ddee0bc..3bc5f24db 100644 --- a/src/SceneGraph/MatrixTransformation2D.h +++ b/src/SceneGraph/MatrixTransformation2D.h @@ -45,27 +45,8 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla /** @brief Underlying transformation type */ typedef Math::Matrix3 DataType; - #ifndef DOXYGEN_GENERATING_OUTPUT - constexpr static Math::Matrix3 fromMatrix(const Math::Matrix3& matrix) { - return matrix; - } - - constexpr static Math::Matrix3 toMatrix(const Math::Matrix3& transformation) { - return transformation; - } - - static Math::Matrix3 compose(const Math::Matrix3& parent, const Math::Matrix3& child) { - return parent*child; - } - - static Math::Matrix3 inverted(const Math::Matrix3& transformation) { - return transformation.inverted(); - } - - Math::Matrix3 transformation() const { - return _transformation; - } - #endif + /** @brief Object transformation */ + Math::Matrix3 transformation() const { return _transformation; } /** * @brief Set transformation @@ -90,15 +71,13 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla * @return Reference to self (for method chaining) */ Object>& transform(const Math::Matrix3& transformation, TransformationType type = TransformationType::Global) { - setTransformation(type == TransformationType::Global ? + return setTransformation(type == TransformationType::Global ? transformation*_transformation : _transformation*transformation); - return static_cast>&>(*this); } /** @copydoc AbstractTranslationRotationScaling2D::resetTransformation() */ Object>& resetTransformation() { - setTransformation({}); - return static_cast>&>(*this); + return setTransformation({}); } /** @@ -106,8 +85,7 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla * Same as calling transform() with Matrix3::translation(). */ Object>& translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { - transform(Math::Matrix3::translation(vector), type); - return static_cast>&>(*this); + return transform(Math::Matrix3::translation(vector), type); } /** @@ -115,8 +93,7 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla * Same as calling transform() with Matrix3::rotation(). */ Object>& rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { - transform(Math::Matrix3::rotation(angle), type); - return static_cast>&>(*this); + return transform(Math::Matrix3::rotation(angle), type); } /** @@ -124,8 +101,7 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla * Same as calling transform() with Matrix3::scaling(). */ Object>& scale(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { - transform(Math::Matrix3::scaling(vector), type); - return static_cast>&>(*this); + return transform(Math::Matrix3::scaling(vector), type); } /** @@ -138,8 +114,7 @@ template class BasicMatrixTransformation2D: public AbstractBasicTransla * Same as calling transform() with Matrix3::reflection(). */ Object>& reflect(const Math::Vector2& normal, TransformationType type = TransformationType::Global) { - transform(Math::Matrix3::reflection(normal), type); - return static_cast>&>(*this); + return transform(Math::Matrix3::reflection(normal), type); } /** @@ -184,6 +159,28 @@ template inline BasicMatrixTransformation2D::BasicMatrixTransformati */ typedef BasicMatrixTransformation2D MatrixTransformation2D; +namespace Implementation { + +template struct Transformation> { + constexpr static Math::Matrix3 fromMatrix(const Math::Matrix3& matrix) { + return matrix; + } + + constexpr static Math::Matrix3 toMatrix(const Math::Matrix3& transformation) { + return transformation; + } + + static Math::Matrix3 compose(const Math::Matrix3& parent, const Math::Matrix3& child) { + return parent*child; + } + + static Math::Matrix3 inverted(const Math::Matrix3& transformation) { + return transformation.inverted(); + } +}; + +} + }} #endif diff --git a/src/SceneGraph/MatrixTransformation3D.h b/src/SceneGraph/MatrixTransformation3D.h index 463c6aa1f..742fe3d27 100644 --- a/src/SceneGraph/MatrixTransformation3D.h +++ b/src/SceneGraph/MatrixTransformation3D.h @@ -45,27 +45,8 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla /** @brief Underlying transformation type */ typedef Math::Matrix4 DataType; - #ifndef DOXYGEN_GENERATING_OUTPUT - constexpr static Math::Matrix4 fromMatrix(const Math::Matrix4& matrix) { - return matrix; - } - - constexpr static Math::Matrix4 toMatrix(const Math::Matrix4& transformation) { - return transformation; - } - - static Math::Matrix4 compose(const Math::Matrix4& parent, const Math::Matrix4& child) { - return parent*child; - } - - static Math::Matrix4 inverted(const Math::Matrix4& transformation) { - return transformation.inverted(); - } - - Math::Matrix4 transformation() const { - return _transformation; - } - #endif + /** @brief Object transformation */ + Math::Matrix4 transformation() const { return _transformation; } /** * @brief Set transformation @@ -85,8 +66,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla /** @copydoc AbstractTranslationRotationScaling3D::resetTransformation() */ Object>& resetTransformation() { - setTransformation({}); - return static_cast>&>(*this); + return setTransformation({}); } /** @@ -96,9 +76,8 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * @return Reference to self (for method chaining) */ Object>& transform(const Math::Matrix4& transformation, TransformationType type = TransformationType::Global) { - setTransformation(type == TransformationType::Global ? + return setTransformation(type == TransformationType::Global ? transformation*_transformation : _transformation*transformation); - return static_cast>&>(*this); } /** @@ -106,8 +85,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * Same as calling transform() with Matrix4::translation(). */ Object>& translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { - transform(Math::Matrix4::translation(vector), type); - return static_cast>&>(*this); + return transform(Math::Matrix4::translation(vector), type); } /** @@ -115,8 +93,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * Same as calling transform() with Matrix4::rotation(). */ Object>& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { - transform(Math::Matrix4::rotation(angle, normalizedAxis), type); - return static_cast>&>(*this); + return transform(Math::Matrix4::rotation(angle, normalizedAxis), type); } /** @@ -128,8 +105,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * Same as calling transform() with Matrix4::rotationX(). */ Object>& rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { - transform(Math::Matrix4::rotationX(angle), type); - return static_cast>&>(*this); + return transform(Math::Matrix4::rotationX(angle), type); } /** @@ -141,8 +117,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * Same as calling transform() with Matrix4::rotationY(). */ Object>& rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { - transform(Math::Matrix4::rotationY(angle), type); - return static_cast>&>(*this); + return transform(Math::Matrix4::rotationY(angle), type); } /** @@ -154,8 +129,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * Same as calling transform() with Matrix4::rotationZ(). */ Object>& rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { - transform(Math::Matrix4::rotationZ(angle), type); - return static_cast>&>(*this); + return transform(Math::Matrix4::rotationZ(angle), type); } /** @@ -163,8 +137,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * Same as calling transform() with Matrix4::scaling(). */ Object>& scale(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { - transform(Math::Matrix4::scaling(vector), type); - return static_cast>&>(*this); + return transform(Math::Matrix4::scaling(vector), type); } /** @@ -177,8 +150,7 @@ template class BasicMatrixTransformation3D: public AbstractBasicTransla * Same as calling transform() with Matrix4::reflection(). */ Object>& reflect(const Math::Vector3& normal, TransformationType type = TransformationType::Global) { - transform(Math::Matrix4::reflection(normal), type); - return static_cast>&>(*this); + return transform(Math::Matrix4::reflection(normal), type); } protected: @@ -224,6 +196,28 @@ template inline BasicMatrixTransformation3D::BasicMatrixTransformati */ typedef BasicMatrixTransformation3D MatrixTransformation3D; +namespace Implementation { + +template struct Transformation> { + constexpr static Math::Matrix4 fromMatrix(const Math::Matrix4& matrix) { + return matrix; + } + + constexpr static Math::Matrix4 toMatrix(const Math::Matrix4& transformation) { + return transformation; + } + + static Math::Matrix4 compose(const Math::Matrix4& parent, const Math::Matrix4& child) { + return parent*child; + } + + static Math::Matrix4 inverted(const Math::Matrix4& transformation) { + return transformation.inverted(); + } +}; + +} + }} #endif diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 7343d4a8c..660525905 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -85,6 +85,8 @@ See @ref compilation-speedup-hpp for more information. - @ref MatrixTransformation3D "Object>" - @ref RigidMatrixTransformation2D "Object>" - @ref RigidMatrixTransformation3D "Object>" + - @ref TranslationTransformation2D "Object>" + - @ref TranslationTransformation3D "Object>" @see Scene, AbstractFeature, AbstractTransformation, DebugTools::ObjectRenderer */ @@ -215,7 +217,7 @@ template class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs * @see transformation() */ MatrixType transformationMatrix() const { - return Transformation::toMatrix(Transformation::transformation()); + return Implementation::Transformation::toMatrix(Transformation::transformation()); } /** @@ -224,7 +226,7 @@ template class MAGNUM_SCENEGRAPH_EXPORT Object: public Abs * @see absoluteTransformation() */ MatrixType absoluteTransformationMatrix() const { - return Transformation::toMatrix(absoluteTransformation()); + return Implementation::Transformation::toMatrix(absoluteTransformation()); } /** diff --git a/src/SceneGraph/Object.hpp b/src/SceneGraph/Object.hpp index d16c44e93..578037e88 100644 --- a/src/SceneGraph/Object.hpp +++ b/src/SceneGraph/Object.hpp @@ -92,8 +92,8 @@ template Object& Object::s template Object& Object::setParentKeepTransformation(Object* 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::compose( + Implementation::Transformation::inverted(parent->absoluteTransformation()), absoluteTransformation()); setParent(parent); Transformation::setTransformation(transformation); @@ -102,7 +102,7 @@ template Object& Object::s template typename Transformation::DataType Object::absoluteTransformation() const { if(!parent()) return Transformation::transformation(); - return Transformation::compose(parent()->absoluteTransformation(), Transformation::transformation()); + return Implementation::Transformation::compose(parent()->absoluteTransformation(), Transformation::transformation()); } template void Object::setDirty() { @@ -154,7 +154,7 @@ template void Object::setClean() { objects.pop(); /* Compose transformation and clean object */ - absoluteTransformation = Transformation::compose(absoluteTransformation, o->transformation()); + absoluteTransformation = Implementation::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 auto Object::doTransformationMatr } template auto Object::transformationMatrices(const std::vector*>& objects, const MatrixType& initialTransformationMatrix) const -> std::vector { - std::vector transformations = this->transformations(std::move(objects), Transformation::fromMatrix(initialTransformationMatrix)); + std::vector transformations = this->transformations(std::move(objects), Implementation::Transformation::fromMatrix(initialTransformationMatrix)); std::vector transformationMatrices(transformations.size()); for(std::size_t i = 0; i != objects.size(); ++i) - transformationMatrices[i] = Transformation::toMatrix(transformations[i]); + transformationMatrices[i] = Implementation::Transformation::toMatrix(transformations[i]); return transformationMatrices; } @@ -324,16 +324,16 @@ template typename Transformation::DataType ObjectisScene()); return (jointTransformations[joint] = - Transformation::compose(initialTransformation, jointTransformations[joint])); + Implementation::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::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::compose(parent->transformation(), jointTransformations[joint]); o = parent; } } @@ -406,7 +406,7 @@ template void Object::setClean(const typen if(i->cachedTransformations() & CachedTransformation::Absolute) { if(!(cached & CachedTransformation::Absolute)) { cached |= CachedTransformation::Absolute; - matrix = Transformation::toMatrix(absoluteTransformation); + matrix = Implementation::Transformation::toMatrix(absoluteTransformation); } i->clean(matrix); @@ -417,7 +417,8 @@ template void Object::setClean(const typen if(i->cachedTransformations() & CachedTransformation::InvertedAbsolute) { if(!(cached & CachedTransformation::InvertedAbsolute)) { cached |= CachedTransformation::InvertedAbsolute; - invertedMatrix = Transformation::toMatrix(Transformation::inverted(absoluteTransformation)); + invertedMatrix = Implementation::Transformation::toMatrix( + Implementation::Transformation::inverted(absoluteTransformation)); } i->cleanInverted(invertedMatrix); diff --git a/src/SceneGraph/RigidMatrixTransformation2D.h b/src/SceneGraph/RigidMatrixTransformation2D.h index 86d0677e0..ed169b0ea 100644 --- a/src/SceneGraph/RigidMatrixTransformation2D.h +++ b/src/SceneGraph/RigidMatrixTransformation2D.h @@ -49,43 +49,8 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr /** @brief Underlying transformation type */ typedef Math::Matrix3 DataType; - #ifndef DOXYGEN_GENERATING_OUTPUT - static Math::Matrix3 fromMatrix(const Math::Matrix3& matrix) { - CORRADE_ASSERT(matrix.isRigidTransformation(), - "SceneGraph::RigidMatrixTransformation2D::fromMatrix(): the matrix doesn't represent rigid transformation", {}); - return matrix; - } - - constexpr static Math::Matrix3 toMatrix(const Math::Matrix3& transformation) { - return transformation; - } - - static Math::Matrix3 compose(const Math::Matrix3& parent, const Math::Matrix3& child) { - return parent*child; - } - - static Math::Matrix3 inverted(const Math::Matrix3& transformation) { - return transformation.invertedRigid(); - } - - Math::Matrix3 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>& normalizeRotation() { - setTransformationInternal(Math::Matrix3::from( - Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()), - _transformation.translation())); - return static_cast>&>(*this); - } + /** @brief Object transformation */ + Math::Matrix3 transformation() const { return _transformation; } /** * @brief Set transformation @@ -98,14 +63,25 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr CORRADE_ASSERT(transformation.isRigidTransformation(), "SceneGraph::RigidMatrixTransformation2D::setTransformation(): the matrix doesn't represent rigid transformation", static_cast>&>(*this)); - setTransformationInternal(transformation); - return static_cast>&>(*this); + return setTransformationInternal(transformation); } /** @copydoc AbstractTranslationRotationScaling2D::resetTransformation() */ Object>& resetTransformation() { - setTransformationInternal({}); - return static_cast>&>(*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>& normalizeRotation() { + return setTransformationInternal(Math::Matrix3::from( + Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()), + _transformation.translation())); } /** @@ -121,8 +97,7 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr CORRADE_ASSERT(transformation.isRigidTransformation(), "SceneGraph::RigidMatrixTransformation2D::transform(): the matrix doesn't represent rigid transformation", static_cast>&>(*this)); - transformInternal(transformation, type); - return static_cast>&>(*this); + return transformInternal(transformation, type); } /** @@ -130,8 +105,7 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr * Same as calling transform() with Matrix3::translation(). */ Object>& translate(const Math::Vector2& vector, TransformationType type = TransformationType::Global) { - transformInternal(Math::Matrix3::translation(vector), type); - return static_cast>&>(*this); + return transformInternal(Math::Matrix3::translation(vector), type); } /** @@ -144,8 +118,7 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr * @see normalizeRotation() */ Object>& rotate(Math::Rad angle, TransformationType type = TransformationType::Global) { - transformInternal(Math::Matrix3::rotation(angle), type); - return static_cast>&>(*this); + return transformInternal(Math::Matrix3::rotation(angle), type); } /** @@ -158,8 +131,7 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr * Same as calling transform() with Matrix3::reflection(). */ Object>& reflect(const Math::Vector2& normal, TransformationType type = TransformationType::Global) { - transformInternal(Math::Matrix3::reflection(normal), type); - return static_cast>&>(*this); + return transformInternal(Math::Matrix3::reflection(normal), type); } /** @@ -189,7 +161,7 @@ template class BasicRigidMatrixTransformation2D: public AbstractBasicTr } /* No assertions fired, for internal use */ - void setTransformationInternal(const Math::Matrix3& transformation) { + Object>& setTransformationInternal(const Math::Matrix3& 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 BasicRigidMatrixTransformation2D: public AbstractBasicTr _transformation = transformation; static_cast>*>(this)->setDirty(); } + + return static_cast>&>(*this); } /* No assertions fired, for internal use */ - void transformInternal(const Math::Matrix3& transformation, TransformationType type) { - setTransformation(type == TransformationType::Global ? + Object>& transformInternal(const Math::Matrix3& transformation, TransformationType type) { + return setTransformationInternal(type == TransformationType::Global ? transformation*_transformation : _transformation*transformation); } @@ -217,6 +191,30 @@ template inline BasicRigidMatrixTransformation2D::BasicRigidMatrixTr */ typedef BasicRigidMatrixTransformation2D RigidMatrixTransformation2D; +namespace Implementation { + +template struct Transformation> { + static Math::Matrix3 fromMatrix(const Math::Matrix3& matrix) { + CORRADE_ASSERT(matrix.isRigidTransformation(), + "SceneGraph::RigidMatrixTransformation2D: the matrix doesn't represent rigid transformation", {}); + return matrix; + } + + constexpr static Math::Matrix3 toMatrix(const Math::Matrix3& transformation) { + return transformation; + } + + static Math::Matrix3 compose(const Math::Matrix3& parent, const Math::Matrix3& child) { + return parent*child; + } + + static Math::Matrix3 inverted(const Math::Matrix3& transformation) { + return transformation.invertedRigid(); + } +}; + +} + }} #endif diff --git a/src/SceneGraph/RigidMatrixTransformation3D.h b/src/SceneGraph/RigidMatrixTransformation3D.h index eb5498e31..2fdd6d1cf 100644 --- a/src/SceneGraph/RigidMatrixTransformation3D.h +++ b/src/SceneGraph/RigidMatrixTransformation3D.h @@ -49,43 +49,8 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr /** @brief Underlying transformation type */ typedef Math::Matrix4 DataType; - #ifndef DOXYGEN_GENERATING_OUTPUT - static Math::Matrix4 fromMatrix(const Math::Matrix4& matrix) { - CORRADE_ASSERT(matrix.isRigidTransformation(), - "SceneGraph::RigidMatrixTransformation3D::fromMatrix(): the matrix doesn't represent rigid transformation", {}); - return matrix; - } - - constexpr static Math::Matrix4 toMatrix(const Math::Matrix4& transformation) { - return transformation; - } - - static Math::Matrix4 compose(const Math::Matrix4& parent, const Math::Matrix4& child) { - return parent*child; - } - - static Math::Matrix4 inverted(const Math::Matrix4& transformation) { - return transformation.invertedRigid(); - } - - Math::Matrix4 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>& normalizeRotation() { - setTransformation(Math::Matrix4::from( - Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()), - _transformation.translation())); - return static_cast>&>(*this); - } + /** @brief Object transformation */ + Math::Matrix4 transformation() const { return _transformation; } /** * @brief Set transformation @@ -98,14 +63,25 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr CORRADE_ASSERT(transformation.isRigidTransformation(), "SceneGraph::RigidMatrixTransformation3D::setTransformation(): the matrix doesn't represent rigid transformation", static_cast>&>(*this)); - setTransformationInternal(transformation); - return static_cast>&>(*this); + return setTransformationInternal(transformation); } /** @copydoc AbstractTranslationRotationScaling3D::resetTransformation() */ Object>& resetTransformation() { - setTransformation({}); - return static_cast>&>(*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>& normalizeRotation() { + return setTransformationInternal(Math::Matrix4::from( + Math::Algorithms::gramSchmidtOrthonormalize(_transformation.rotationScaling()), + _transformation.translation())); } /** @@ -121,8 +97,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr CORRADE_ASSERT(transformation.isRigidTransformation(), "SceneGraph::RigidMatrixTransformation3D::transform(): the matrix doesn't represent rigid transformation", static_cast>&>(*this)); - transformInternal(transformation, type); - return static_cast>&>(*this); + return transformInternal(transformation, type); } /** @@ -130,8 +105,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * Same as calling transform() with Matrix4::translation(). */ Object>& translate(const Math::Vector3& vector, TransformationType type = TransformationType::Global) { - transformInternal(Math::Matrix4::translation(vector), type); - return static_cast>&>(*this); + return transformInternal(Math::Matrix4::translation(vector), type); } /** @@ -146,8 +120,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * Vector3::yAxis(), Vector3::zAxis(), normalizeRotation() */ Object>& rotate(Math::Rad angle, const Math::Vector3& normalizedAxis, TransformationType type = TransformationType::Global) { - transformInternal(Math::Matrix4::rotation(angle, normalizedAxis), type); - return static_cast>&>(*this); + return transformInternal(Math::Matrix4::rotation(angle, normalizedAxis), type); } /** @@ -160,8 +133,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @see normalizeRotation() */ Object>& rotateX(Math::Rad angle, TransformationType type = TransformationType::Global) { - transformInternal(Math::Matrix4::rotationX(angle), type); - return static_cast>&>(*this); + return transformInternal(Math::Matrix4::rotationX(angle), type); } /** @@ -174,8 +146,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @see normalizeRotation() */ Object>& rotateY(Math::Rad angle, TransformationType type = TransformationType::Global) { - transformInternal(Math::Matrix4::rotationY(angle), type); - return static_cast>&>(*this); + return transformInternal(Math::Matrix4::rotationY(angle), type); } /** @@ -188,8 +159,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * @see normalizeRotation() */ Object>& rotateZ(Math::Rad angle, TransformationType type = TransformationType::Global) { - transformInternal(Math::Matrix4::rotationZ(angle), type); - return static_cast>&>(*this); + return transformInternal(Math::Matrix4::rotationZ(angle), type); } /** @@ -202,8 +172,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr * Same as calling transform() with Matrix4::reflection(). */ Object>& reflect(const Math::Vector3& normal, TransformationType type = TransformationType::Global) { - transformInternal(Math::Matrix4::reflection(normal), type); - return static_cast>&>(*this); + return transformInternal(Math::Matrix4::reflection(normal), type); } protected: @@ -234,7 +203,7 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr } /* No assertions fired, for internal use */ - void setTransformationInternal(const Math::Matrix4& transformation) { + Object>& setTransformationInternal(const Math::Matrix4& 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? */ @@ -242,11 +211,13 @@ template class BasicRigidMatrixTransformation3D: public AbstractBasicTr _transformation = transformation; static_cast>*>(this)->setDirty(); } + + return static_cast>&>(*this); } /* No assertions fired, for internal use */ - void transformInternal(const Math::Matrix4& transformation, TransformationType type) { - setTransformation(type == TransformationType::Global ? + Object>& transformInternal(const Math::Matrix4& transformation, TransformationType type) { + return setTransformationInternal(type == TransformationType::Global ? transformation*_transformation : _transformation*transformation); } @@ -262,6 +233,30 @@ template inline BasicRigidMatrixTransformation3D::BasicRigidMatrixTr */ typedef BasicRigidMatrixTransformation3D RigidMatrixTransformation3D; +namespace Implementation { + +template struct Transformation> { + static Math::Matrix4 fromMatrix(const Math::Matrix4& matrix) { + CORRADE_ASSERT(matrix.isRigidTransformation(), + "SceneGraph::RigidMatrixTransformation3D: the matrix doesn't represent rigid transformation", {}); + return matrix; + } + + constexpr static Math::Matrix4 toMatrix(const Math::Matrix4& transformation) { + return transformation; + } + + static Math::Matrix4 compose(const Math::Matrix4& parent, const Math::Matrix4& child) { + return parent*child; + } + + static Math::Matrix4 inverted(const Math::Matrix4& transformation) { + return transformation.invertedRigid(); + } +}; + +} + }} #endif diff --git a/src/SceneGraph/SceneGraph.h b/src/SceneGraph/SceneGraph.h index a735fcd05..d39a282e4 100644 --- a/src/SceneGraph/SceneGraph.h +++ b/src/SceneGraph/SceneGraph.h @@ -98,6 +98,17 @@ typedef AbstractTransformation<2, Float> AbstractTransformation2D; typedef AbstractTransformation<3, Float> AbstractTransformation3D; #endif +template class AbstractTranslation; +#ifndef CORRADE_GCC46_COMPATIBILITY +template using AbstractBasicTranslation2D = AbstractTranslation<2, T, TranslationType>; +template using AbstractBasicTranslation3D = AbstractTranslation<3, T, TranslationType>; +typedef AbstractBasicTranslation2D AbstractTranslation2D; +typedef AbstractBasicTranslation3D AbstractTranslation3D; +#else +typedef AbstractTranslation<2, Float> AbstractTranslation2D; +typedef AbstractTranslation<3, Float> AbstractTranslation3D; +#endif + template class AbstractBasicTranslationRotation2D; template class AbstractBasicTranslationRotation3D; typedef AbstractBasicTranslationRotation2D AbstractTranslationRotation2D; @@ -186,6 +197,21 @@ typedef BasicRigidMatrixTransformation3D RigidMatrixTransformation3D; template class Scene; +template class TranslationTransformation; +#ifndef CORRADE_GCC46_COMPATIBILITY +template using BasicTranslationTransformation2D = TranslationTransformation<2, T, TranslationType>; +template using BasicTranslationTransformation3D = TranslationTransformation<3, T, TranslationType>; +typedef BasicTranslationTransformation2D TranslationTransformation2D; +typedef BasicTranslationTransformation3D TranslationTransformation3D; +#else +typedef TranslationTransformation<2, Float> TranslationTransformation2D; +typedef TranslationTransformation<3, Float> TranslationTransformation3D; +#endif + +namespace Implementation { + template struct Transformation; +} + }} #endif diff --git a/src/SceneGraph/Test/CMakeLists.txt b/src/SceneGraph/Test/CMakeLists.txt index 902c2f283..0ba37c03a 100644 --- a/src/SceneGraph/Test/CMakeLists.txt +++ b/src/SceneGraph/Test/CMakeLists.txt @@ -32,9 +32,11 @@ corrade_add_test(SceneGraphObjectTest ObjectTest.cpp LIBRARIES MagnumSceneGraphT corrade_add_test(SceneGraphRigidMatrixTrans___2DTest RigidMatrixTransformation2DTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphRigidMatrixTrans___3DTest RigidMatrixTransformation3DTest.cpp LIBRARIES MagnumSceneGraph) corrade_add_test(SceneGraphSceneTest SceneTest.cpp LIBRARIES MagnumSceneGraph) +corrade_add_test(SceneGraphTranslationTransfo___Test TranslationTransformationTest.cpp LIBRARIES MagnumSceneGraph) set_target_properties(SceneGraphDualComplexTransfo___Test SceneGraphDualQuaternionTran___Test SceneGraphRigidMatrixTrans___2DTest SceneGraphRigidMatrixTrans___3DTest + SceneGraphTranslationTransfo___Test PROPERTIES COMPILE_FLAGS "-DCORRADE_GRACEFUL_ASSERT") diff --git a/src/SceneGraph/Test/DualComplexTransformationTest.cpp b/src/SceneGraph/Test/DualComplexTransformationTest.cpp index 87d222df4..5d7417065 100644 --- a/src/SceneGraph/Test/DualComplexTransformationTest.cpp +++ b/src/SceneGraph/Test/DualComplexTransformationTest.cpp @@ -67,24 +67,24 @@ DualComplexTransformationTest::DualComplexTransformationTest() { void DualComplexTransformationTest::fromMatrix() { Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f}); DualComplex c = DualComplex::rotation(Deg(17.0f))*DualComplex::translation({1.0f, -0.3f}); - CORRADE_COMPARE(DualComplexTransformation::fromMatrix(m), c); + CORRADE_COMPARE(Implementation::Transformation::fromMatrix(m), c); } void DualComplexTransformationTest::toMatrix() { DualComplex c = DualComplex::rotation(Deg(17.0f))*DualComplex::translation({1.0f, -0.3f}); Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f}); - CORRADE_COMPARE(DualComplexTransformation::toMatrix(c), m); + CORRADE_COMPARE(Implementation::Transformation::toMatrix(c), m); } void DualComplexTransformationTest::compose() { DualComplex parent = DualComplex::rotation(Deg(17.0f)); DualComplex child = DualComplex::translation({1.0f, -0.3f}); - CORRADE_COMPARE(DualComplexTransformation::compose(parent, child), parent*child); + CORRADE_COMPARE(Implementation::Transformation::compose(parent, child), parent*child); } void DualComplexTransformationTest::inverted() { DualComplex c = DualComplex::rotation(Deg(17.0f))*DualComplex::translation({1.0f, -0.3f}); - CORRADE_COMPARE(DualComplexTransformation::inverted(c)*c, DualComplex()); + CORRADE_COMPARE(Implementation::Transformation::inverted(c)*c, DualComplex()); } void DualComplexTransformationTest::setTransformation() { diff --git a/src/SceneGraph/Test/DualQuaternionTransformationTest.cpp b/src/SceneGraph/Test/DualQuaternionTransformationTest.cpp index fd48a3ac7..72d5d0f41 100644 --- a/src/SceneGraph/Test/DualQuaternionTransformationTest.cpp +++ b/src/SceneGraph/Test/DualQuaternionTransformationTest.cpp @@ -65,26 +65,31 @@ DualQuaternionTransformationTest::DualQuaternionTransformationTest() { } void DualQuaternionTransformationTest::fromMatrix() { + std::ostringstream o; + Error::setOutput(&o); + Implementation::Transformation::fromMatrix(Matrix4::scaling(Vector3(4.0f))); + CORRADE_COMPARE(o.str(), "SceneGraph::DualQuaternionTransformation: the matrix doesn't represent rigid transformation\n"); + Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f}); DualQuaternion q = DualQuaternion::rotation(Deg(17.0f), Vector3::xAxis())*DualQuaternion::translation({1.0f, -0.3f, 2.3f}); - CORRADE_COMPARE(DualQuaternionTransformation::fromMatrix(m), q); + CORRADE_COMPARE(Implementation::Transformation::fromMatrix(m), q); } void DualQuaternionTransformationTest::toMatrix() { DualQuaternion q = DualQuaternion::rotation(Deg(17.0f), Vector3::xAxis())*DualQuaternion::translation({1.0f, -0.3f, 2.3f}); Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f}); - CORRADE_COMPARE(DualQuaternionTransformation::toMatrix(q), m); + CORRADE_COMPARE(Implementation::Transformation::toMatrix(q), m); } void DualQuaternionTransformationTest::compose() { DualQuaternion parent = DualQuaternion::rotation(Deg(17.0f), Vector3::xAxis()); DualQuaternion child = DualQuaternion::translation({1.0f, -0.3f, 2.3f}); - CORRADE_COMPARE(DualQuaternionTransformation::compose(parent, child), parent*child); + CORRADE_COMPARE(Implementation::Transformation::compose(parent, child), parent*child); } void DualQuaternionTransformationTest::inverted() { DualQuaternion q = DualQuaternion::rotation(Deg(17.0f), Vector3::xAxis())*DualQuaternion::translation({1.0f, -0.3f, 2.3f}); - CORRADE_COMPARE(DualQuaternionTransformation::inverted(q)*q, DualQuaternion()); + CORRADE_COMPARE(Implementation::Transformation::inverted(q)*q, DualQuaternion()); } void DualQuaternionTransformationTest::setTransformation() { diff --git a/src/SceneGraph/Test/MatrixTransformation2DTest.cpp b/src/SceneGraph/Test/MatrixTransformation2DTest.cpp index d997a0f17..b1408956e 100644 --- a/src/SceneGraph/Test/MatrixTransformation2DTest.cpp +++ b/src/SceneGraph/Test/MatrixTransformation2DTest.cpp @@ -67,23 +67,23 @@ MatrixTransformation2DTest::MatrixTransformation2DTest() { void MatrixTransformation2DTest::fromMatrix() { Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f}); - CORRADE_COMPARE(MatrixTransformation2D::fromMatrix(m), m); + CORRADE_COMPARE(Implementation::Transformation::fromMatrix(m), m); } void MatrixTransformation2DTest::toMatrix() { Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f}); - CORRADE_COMPARE(MatrixTransformation2D::toMatrix(m), m); + CORRADE_COMPARE(Implementation::Transformation::toMatrix(m), m); } void MatrixTransformation2DTest::compose() { Matrix3 parent = Matrix3::rotation(Deg(17.0f)); Matrix3 child = Matrix3::translation({1.0f, -0.3f}); - CORRADE_COMPARE(MatrixTransformation2D::compose(parent, child), parent*child); + CORRADE_COMPARE(Implementation::Transformation::compose(parent, child), parent*child); } void MatrixTransformation2DTest::inverted() { Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f}); - CORRADE_COMPARE(MatrixTransformation2D::inverted(m)*m, Matrix3()); + CORRADE_COMPARE(Implementation::Transformation::inverted(m)*m, Matrix3()); } void MatrixTransformation2DTest::setTransformation() { diff --git a/src/SceneGraph/Test/MatrixTransformation3DTest.cpp b/src/SceneGraph/Test/MatrixTransformation3DTest.cpp index ab9f3f97d..66240a318 100644 --- a/src/SceneGraph/Test/MatrixTransformation3DTest.cpp +++ b/src/SceneGraph/Test/MatrixTransformation3DTest.cpp @@ -67,23 +67,23 @@ MatrixTransformation3DTest::MatrixTransformation3DTest() { void MatrixTransformation3DTest::fromMatrix() { Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f})*Matrix4::scaling({2.0f, 1.4f, -2.1f}); - CORRADE_COMPARE(MatrixTransformation3D::fromMatrix(m), m); + CORRADE_COMPARE(Implementation::Transformation::fromMatrix(m), m); } void MatrixTransformation3DTest::toMatrix() { Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f})*Matrix4::scaling({2.0f, 1.4f, -2.1f}); - CORRADE_COMPARE(MatrixTransformation3D::toMatrix(m), m); + CORRADE_COMPARE(Implementation::Transformation::toMatrix(m), m); } void MatrixTransformation3DTest::compose() { Matrix4 parent = Matrix4::rotationX(Deg(17.0f)); Matrix4 child = Matrix4::translation({1.0f, -0.3f, 2.3f}); - CORRADE_COMPARE(MatrixTransformation3D::compose(parent, child), parent*child); + CORRADE_COMPARE(Implementation::Transformation::compose(parent, child), parent*child); } void MatrixTransformation3DTest::inverted() { Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f})*Matrix4::scaling({2.0f, 1.4f, -2.1f}); - CORRADE_COMPARE(MatrixTransformation3D::inverted(m)*m, Matrix4()); + CORRADE_COMPARE(Implementation::Transformation::inverted(m)*m, Matrix4()); } void MatrixTransformation3DTest::setTransformation() { diff --git a/src/SceneGraph/Test/RigidMatrixTransformation2DTest.cpp b/src/SceneGraph/Test/RigidMatrixTransformation2DTest.cpp index b362e97de..f33537c2f 100644 --- a/src/SceneGraph/Test/RigidMatrixTransformation2DTest.cpp +++ b/src/SceneGraph/Test/RigidMatrixTransformation2DTest.cpp @@ -69,27 +69,27 @@ RigidMatrixTransformation2DTest::RigidMatrixTransformation2DTest() { void RigidMatrixTransformation2DTest::fromMatrix() { std::ostringstream o; Error::setOutput(&o); - RigidMatrixTransformation2D::fromMatrix(Matrix3::scaling(Vector2(4.0f))); - CORRADE_COMPARE(o.str(), "SceneGraph::RigidMatrixTransformation2D::fromMatrix(): the matrix doesn't represent rigid transformation\n"); + Implementation::Transformation::fromMatrix(Matrix3::scaling(Vector2(4.0f))); + CORRADE_COMPARE(o.str(), "SceneGraph::RigidMatrixTransformation2D: the matrix doesn't represent rigid transformation\n"); Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f}); - CORRADE_COMPARE(RigidMatrixTransformation2D::fromMatrix(m), m); + CORRADE_COMPARE(Implementation::Transformation::fromMatrix(m), m); } void RigidMatrixTransformation2DTest::toMatrix() { Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f}); - CORRADE_COMPARE(RigidMatrixTransformation2D::toMatrix(m), m); + CORRADE_COMPARE(Implementation::Transformation::toMatrix(m), m); } void RigidMatrixTransformation2DTest::compose() { Matrix3 parent = Matrix3::rotation(Deg(17.0f)); Matrix3 child = Matrix3::translation({1.0f, -0.3f}); - CORRADE_COMPARE(RigidMatrixTransformation2D::compose(parent, child), parent*child); + CORRADE_COMPARE(Implementation::Transformation::compose(parent, child), parent*child); } void RigidMatrixTransformation2DTest::inverted() { Matrix3 m = Matrix3::rotation(Deg(17.0f))*Matrix3::translation({1.0f, -0.3f}); - CORRADE_COMPARE(RigidMatrixTransformation2D::inverted(m)*m, Matrix3()); + CORRADE_COMPARE(Implementation::Transformation::inverted(m)*m, Matrix3()); } void RigidMatrixTransformation2DTest::setTransformation() { diff --git a/src/SceneGraph/Test/RigidMatrixTransformation3DTest.cpp b/src/SceneGraph/Test/RigidMatrixTransformation3DTest.cpp index fd1a464b0..d6cf466a7 100644 --- a/src/SceneGraph/Test/RigidMatrixTransformation3DTest.cpp +++ b/src/SceneGraph/Test/RigidMatrixTransformation3DTest.cpp @@ -69,27 +69,27 @@ RigidMatrixTransformation3DTest::RigidMatrixTransformation3DTest() { void RigidMatrixTransformation3DTest::fromMatrix() { std::ostringstream o; Error::setOutput(&o); - RigidMatrixTransformation3D::fromMatrix(Matrix4::scaling(Vector3(4.0f))); - CORRADE_COMPARE(o.str(), "SceneGraph::RigidMatrixTransformation3D::fromMatrix(): the matrix doesn't represent rigid transformation\n"); + Implementation::Transformation::fromMatrix(Matrix4::scaling(Vector3(4.0f))); + CORRADE_COMPARE(o.str(), "SceneGraph::RigidMatrixTransformation3D: the matrix doesn't represent rigid transformation\n"); Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f}); - CORRADE_COMPARE(RigidMatrixTransformation3D::fromMatrix(m), m); + CORRADE_COMPARE(Implementation::Transformation::fromMatrix(m), m); } void RigidMatrixTransformation3DTest::toMatrix() { Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f}); - CORRADE_COMPARE(RigidMatrixTransformation3D::toMatrix(m), m); + CORRADE_COMPARE(Implementation::Transformation::toMatrix(m), m); } void RigidMatrixTransformation3DTest::compose() { Matrix4 parent = Matrix4::rotationX(Deg(17.0f)); Matrix4 child = Matrix4::translation({1.0f, -0.3f, 2.3f}); - CORRADE_COMPARE(RigidMatrixTransformation3D::compose(parent, child), parent*child); + CORRADE_COMPARE(Implementation::Transformation::compose(parent, child), parent*child); } void RigidMatrixTransformation3DTest::inverted() { Matrix4 m = Matrix4::rotationX(Deg(17.0f))*Matrix4::translation({1.0f, -0.3f, 2.3f}); - CORRADE_COMPARE(RigidMatrixTransformation3D::inverted(m)*m, Matrix4()); + CORRADE_COMPARE(Implementation::Transformation::inverted(m)*m, Matrix4()); } void RigidMatrixTransformation3DTest::setTransformation() { diff --git a/src/SceneGraph/Test/TranslationTransformationTest.cpp b/src/SceneGraph/Test/TranslationTransformationTest.cpp new file mode 100644 index 000000000..ffff1aa74 --- /dev/null +++ b/src/SceneGraph/Test/TranslationTransformationTest.cpp @@ -0,0 +1,146 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + 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 +#include + +#include "SceneGraph/TranslationTransformation.h" +#include "SceneGraph/Scene.h" + +/* For Object2Di */ +#include "SceneGraph/Object.hpp" + +namespace Magnum { namespace SceneGraph { namespace Test { + +typedef Object Object2D; +typedef Scene Scene2D; + +class TranslationTransformationTest: public TestSuite::Tester { + public: + explicit TranslationTransformationTest(); + + void fromMatrix(); + void toMatrix(); + void compose(); + void inverted(); + + void setTransformation(); + void resetTransformation(); + void transform(); + void translate(); + + void integral(); +}; + +TranslationTransformationTest::TranslationTransformationTest() { + addTests({&TranslationTransformationTest::fromMatrix, + &TranslationTransformationTest::toMatrix, + &TranslationTransformationTest::compose, + &TranslationTransformationTest::inverted, + + &TranslationTransformationTest::setTransformation, + &TranslationTransformationTest::resetTransformation, + &TranslationTransformationTest::transform, + &TranslationTransformationTest::translate, + + &TranslationTransformationTest::integral}); +} + +void TranslationTransformationTest::fromMatrix() { + std::ostringstream o; + Error::setOutput(&o); + Implementation::Transformation::fromMatrix(Matrix3::scaling(Vector2(4.0f))); + CORRADE_COMPARE(o.str(), "SceneGraph::TranslationTransformation: the matrix doesn't represent pure translation\n"); + + const Vector2 v(1.0f, -0.3f); + CORRADE_COMPARE(Implementation::Transformation::fromMatrix(Matrix3::translation(v)), v); +} + +void TranslationTransformationTest::toMatrix() { + const Vector2 v(1.0f, -0.3f); + CORRADE_COMPARE(Implementation::Transformation::toMatrix(v), Matrix3::translation(v)); +} + +void TranslationTransformationTest::compose() { + const Vector2 parent(-0.5f, 2.0f); + const Vector2 child(1.0f, -0.3f); + CORRADE_COMPARE(Implementation::Transformation::compose(parent, child), Vector2(0.5f, 1.7f)); +} + +void TranslationTransformationTest::inverted() { + const Vector2 v(1.0f, -0.3f); + CORRADE_COMPARE(Implementation::Transformation::inverted(v), Vector2(-1.0f, 0.3f)); +} + +void TranslationTransformationTest::setTransformation() { + Object2D o; + + /* Dirty after setting transformation */ + o.setClean(); + CORRADE_VERIFY(!o.isDirty()); + o.setTransformation({1.0f, -0.3f}); + CORRADE_VERIFY(o.isDirty()); + CORRADE_COMPARE(o.transformationMatrix(), Matrix3::translation({1.0f, -0.3f})); + + /* Scene cannot be transformed */ + Scene2D s; + s.setClean(); + s.setTransformation({1.0f, -0.3f}); + CORRADE_VERIFY(!s.isDirty()); + CORRADE_COMPARE(s.transformationMatrix(), Matrix3()); +} + +void TranslationTransformationTest::resetTransformation() { + Object2D o; + o.setTransformation({1.0f, -0.3f}); + CORRADE_VERIFY(o.transformationMatrix() != Matrix3()); + o.resetTransformation(); + CORRADE_COMPARE(o.transformationMatrix(), Matrix3()); +} + +void TranslationTransformationTest::transform() { + Object2D o; + o.setTransformation({1.0f, -0.3f}) + .transform({-0.5f, 2.0f}); + CORRADE_COMPARE(o.transformationMatrix(), Matrix3::translation({0.5f, 1.7f})); +} + +void TranslationTransformationTest::translate() { + Object2D o; + o.setTransformation({1.0f, -0.3f}) + .translate({-0.5f, 2.0f}); + CORRADE_COMPARE(o.transformationMatrix(), Matrix3::translation({1.0f, -0.3f})*Matrix3::translation({-0.5f, 2.0f})); +} + +void TranslationTransformationTest::integral() { + typedef Object> Object2Di; + + Object2Di o; + o.translate({3, -7}); + CORRADE_COMPARE(o.transformationMatrix(), Matrix3::translation({3, -7})); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::SceneGraph::Test::TranslationTransformationTest) diff --git a/src/SceneGraph/TranslationTransformation.h b/src/SceneGraph/TranslationTransformation.h new file mode 100644 index 000000000..182078cdf --- /dev/null +++ b/src/SceneGraph/TranslationTransformation.h @@ -0,0 +1,207 @@ +#ifndef Magnum_SceneGraph_TranslationTransformation_h +#define Magnum_SceneGraph_TranslationTransformation_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + 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::TranslationTransformation, alias @ref Magnum::SceneGraph::BasicTranslationTransformation2D, @ref Magnum::SceneGraph::BasicTranslationTransformation3D, typedef @ref Magnum::SceneGraph::TranslationTransformation2D, @ref Magnum::SceneGraph::BasicTranslationTransformation3D + */ + +#include "Math/Matrix3.h" +#include "Math/Matrix4.h" +#include "SceneGraph/AbstractTranslation.h" +#include "SceneGraph/Object.h" + +namespace Magnum { namespace SceneGraph { + +/** +@brief Translation-only transformation + +Uses @ref Math::Vector2 or @ref Math::Vector3 as underlying type. 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. + +Note that translation is commutative, so all @ref TransformationType parameters +have no effect and are included only for compatibility with other +transformation implementations. + +@see @ref BasicTranslationTransformation2D, @ref BasicTranslationTransformation3D, + @ref TranslationTransformation2D, @ref TranslationTransformation3D, + @ref scenegraph +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class TranslationTransformation: public AbstractTranslation { + public: + /** @brief Underlying transformation type */ + typedef typename DimensionTraits::VectorType DataType; + + /** @brief Object transformation */ + typename DimensionTraits::VectorType transformation() const { return _transformation; } + + /** + * @brief Set transformation + * @return Reference to self (for method chaining) + */ + Object>& setTransformation(const typename DimensionTraits::VectorType& 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? */ + if(!static_cast>*>(this)->isScene()) { + _transformation = transformation; + static_cast>*>(this)->setDirty(); + } + + return static_cast>&>(*this); + } + + /** @copydoc AbstractTranslation::resetTransformation() */ + Object>& resetTransformation() { + return setTransformation({}); + } + + /** + * @brief Add transformation + * @param transformation Transformation + * @return Reference to self (for method chaining) + * + * Equivalent to @ref translate(), provided only for compatibility with + * other implementations. + */ + Object>& transform(const typename DimensionTraits::VectorType& transformation, TransformationType = TransformationType::Global) { + return translate(transformation); + } + + /** + * @brief Translate object + * @param vector Translation vector + * @return Reference to self (for method chaining) + * + * @see @ref Vector2::xAxis(), @ref Vector2::yAxis(), @ref Vector3::xAxis(), + * @ref Vector3::yAxis(), @ref Vector3::zAxis() + */ + Object>& translate(const typename DimensionTraits::VectorType& vector, TransformationType = TransformationType::Global) { + _transformation += vector; + return static_cast>&>(*this); + } + + private: + void doResetTransformation() override final { resetTransformation(); } + + void doTranslate(const typename DimensionTraits::VectorType& vector, TransformationType) override final { + translate(vector); + } + + typename DimensionTraits::VectorType _transformation; +}; + +#ifndef CORRADE_GCC46_COMPATIBILITY +/** +@brief Base transformation for two-dimensional scenes supporting translation + +Convenience alternative to %TranslationTransformation<2, T, TranslationType>. +See @ref TranslationTransformation for more information. +@note Not available on GCC < 4.7. Use %TranslationTransformation<2, T, TranslationType> + instead. +@see @ref TranslationTransformation2D, @ref BasicTranslationTransformation3D +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +using BasicTranslationTransformation2D = TranslationTransformation<2, T, TranslationType>; +#endif + +/** +@brief Base transformation for two-dimensional float scenes supporting translation + +@see @ref TranslationTransformation3D +*/ +#ifndef CORRADE_GCC46_COMPATIBILITY +typedef BasicTranslationTransformation2D TranslationTransformation2D; +#else +typedef TranslationTransformation<2, Float> TranslationTransformation2D; +#endif + +#ifndef CORRADE_GCC46_COMPATIBILITY +/** +@brief Base transformation for three-dimensional scenes supporting translation + +Convenience alternative to %TranslationTransformation<3, T, TranslationType>. +See @ref TranslationTransformation for more information. +@note Not available on GCC < 4.7. Use %TranslationTransformation<3, T, TranslationType> + instead. +@see @ref TranslationTransformation3D, @ref BasicTranslationTransformation2D +*/ +#ifdef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +using BasicTranslationTransformation3D = TranslationTransformation<3, T, TranslationType>; +#endif + +/** +@brief Base transformation for three-dimensional float scenes supporting translation + +@see @ref TranslationTransformation2D +*/ +#ifndef CORRADE_GCC46_COMPATIBILITY +typedef BasicTranslationTransformation3D TranslationTransformation3D; +#else +typedef TranslationTransformation<3, Float> TranslationTransformation3D; +#endif + +namespace Implementation { + +template struct Transformation> { + static typename DimensionTraits::VectorType fromMatrix(const typename DimensionTraits::MatrixType& matrix) { + CORRADE_ASSERT((matrix.rotationScaling() == Math::Matrix()), + "SceneGraph::TranslationTransformation: the matrix doesn't represent pure translation", {}); + return typename DimensionTraits::VectorType(matrix.translation()); + } + + constexpr static typename DimensionTraits::MatrixType toMatrix(const typename DimensionTraits::VectorType& transformation) { + return DimensionTraits::MatrixType::translation(typename DimensionTraits::VectorType(transformation)); + } + + static typename DimensionTraits::VectorType compose(const typename DimensionTraits::VectorType& parent, const typename DimensionTraits::VectorType& child) { + return parent+child; + } + + static typename DimensionTraits::VectorType inverted(const typename DimensionTraits::VectorType& transformation) { + return -transformation; + } +}; + +} + +}} + +#endif diff --git a/src/SceneGraph/instantiation.cpp b/src/SceneGraph/instantiation.cpp index 4f589bdbe..8724f4247 100644 --- a/src/SceneGraph/instantiation.cpp +++ b/src/SceneGraph/instantiation.cpp @@ -33,6 +33,7 @@ #include "SceneGraph/Object.hpp" #include "SceneGraph/RigidMatrixTransformation2D.h" #include "SceneGraph/RigidMatrixTransformation3D.h" +#include "SceneGraph/TranslationTransformation.h" namespace Magnum { namespace SceneGraph { @@ -58,6 +59,8 @@ template class MAGNUM_SCENEGRAPH_EXPORT Object>; template class MAGNUM_SCENEGRAPH_EXPORT Object>; template class MAGNUM_SCENEGRAPH_EXPORT Object>; +template class MAGNUM_SCENEGRAPH_EXPORT Object>; +template class MAGNUM_SCENEGRAPH_EXPORT Object>; #endif }} diff --git a/src/Shader.cpp b/src/Shader.cpp index 80ab7e950..4fdf9c5bc 100644 --- a/src/Shader.cpp +++ b/src/Shader.cpp @@ -252,7 +252,7 @@ Int Shader::maxAtomicCounterBuffers(const Type type) { GLint& value = Context::current()->state().shader->maxAtomicCounterBuffers[index]; /* Get the value, if not already cached */ - constexpr static const GLenum what[] = { + constexpr static GLenum what[] = { GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, @@ -287,7 +287,7 @@ Int Shader::maxAtomicCounters(const Type type) { GLint& value = Context::current()->state().shader->maxAtomicCounters[index]; /* Get the value, if not already cached */ - constexpr static const GLenum what[] = { + constexpr static GLenum what[] = { GL_MAX_VERTEX_ATOMIC_COUNTERS, GL_MAX_FRAGMENT_ATOMIC_COUNTERS, GL_MAX_GEOMETRY_ATOMIC_COUNTERS, @@ -322,7 +322,7 @@ Int Shader::maxImageUniforms(const Type type) { GLint& value = Context::current()->state().shader->maxImageUniforms[index]; /* Get the value, if not already cached */ - constexpr static const GLenum what[] = { + constexpr static GLenum what[] = { GL_MAX_VERTEX_IMAGE_UNIFORMS, GL_MAX_FRAGMENT_IMAGE_UNIFORMS, GL_MAX_GEOMETRY_IMAGE_UNIFORMS, @@ -357,7 +357,7 @@ Int Shader::maxShaderStorageBlocks(const Type type) { GLint& value = Context::current()->state().shader->maxShaderStorageBlocks[index]; /* Get the value, if not already cached */ - constexpr static const GLenum what[] = { + constexpr static GLenum what[] = { GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, @@ -393,7 +393,7 @@ Int Shader::maxTextureImageUnits(const Type type) { GLint& value = Context::current()->state().shader->maxTextureImageUnits[index]; /* Get the value, if not already cached */ - constexpr static const GLenum what[] = { + constexpr static GLenum what[] = { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_TEXTURE_IMAGE_UNITS, #ifndef MAGNUM_TARGET_GLES @@ -432,7 +432,7 @@ Int Shader::maxUniformBlocks(const Type type) { GLint& value = Context::current()->state().shader->maxUniformBlocks[index]; /* Get the value, if not already cached */ - constexpr static const GLenum what[] = { + constexpr static GLenum what[] = { GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_BLOCKS, #ifndef MAGNUM_TARGET_GLES @@ -474,7 +474,7 @@ Int Shader::maxUniformComponents(const Type type) { /* Get the value, if not already cached */ #ifndef MAGNUM_TARGET_GLES2 - constexpr static const GLenum what[] = { + constexpr static GLenum what[] = { GL_MAX_VERTEX_UNIFORM_COMPONENTS, GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, #ifndef MAGNUM_TARGET_GLES @@ -488,7 +488,7 @@ Int Shader::maxUniformComponents(const Type type) { glGetIntegerv(what[index], &value); #else /* For ES2 we need to multiply _VECTORS by 4 */ - constexpr static const GLenum what[] = { + constexpr static GLenum what[] = { GL_MAX_VERTEX_UNIFORM_VECTORS, GL_MAX_FRAGMENT_UNIFORM_VECTORS }; @@ -515,7 +515,7 @@ Int Shader::maxCombinedUniformComponents(const Type type) { GLint& value = Context::current()->state().shader->maxCombinedUniformComponents[index]; /* Get the value, if not already cached */ - constexpr static const GLenum what[] = { + constexpr static GLenum what[] = { GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS, GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS, #ifndef MAGNUM_TARGET_GLES diff --git a/src/Shaders/CMakeLists.txt b/src/Shaders/CMakeLists.txt index e1517e356..41b921b8f 100644 --- a/src/Shaders/CMakeLists.txt +++ b/src/Shaders/CMakeLists.txt @@ -56,7 +56,10 @@ if(BUILD_STATIC_PIC) endif() target_link_libraries(MagnumShaders Magnum) -install(TARGETS MagnumShaders DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +install(TARGETS MagnumShaders + RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} + LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} + ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) install(FILES ${MagnumShaders_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Shaders) if(BUILD_TESTS) diff --git a/src/Shaders/Flat.cpp b/src/Shaders/Flat.cpp index 3e1ea3bf5..302cb4161 100644 --- a/src/Shaders/Flat.cpp +++ b/src/Shaders/Flat.cpp @@ -37,7 +37,7 @@ namespace { template<> constexpr const char* vertexShaderName<3>() { return "Flat3D.vert"; } } -template Flat::Flat(): transformationProjectionMatrixUniform(0), colorUniform(1) { +template Flat::Flat(const Flags flags): transformationProjectionMatrixUniform(0), colorUniform(1), _flags(flags) { Utility::Resource rs("MagnumShaders"); /* Weird bug in GCC 4.5 - cannot use initializer list here, although the @@ -49,18 +49,20 @@ template Flat::Flat(): transformationProject #endif Version version = Context::current()->supportedVersion(vs); - Shader frag(version, Shader::Type::Vertex); - frag.addSource(rs.get("compatibility.glsl")) - .addSource(rs.get(vertexShaderName())); - CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); - attachShader(frag); - Shader vert(version, Shader::Type::Fragment); - vert.addSource(rs.get("compatibility.glsl")) + vert.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") + .addSource(rs.get("compatibility.glsl")) .addSource(rs.get("Flat.frag")); CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile()); attachShader(vert); + Shader frag(version, Shader::Type::Vertex); + frag.addSource(flags & Flag::Textured ? "#define TEXTURED\n" : "") + .addSource(rs.get("compatibility.glsl")) + .addSource(rs.get(vertexShaderName())); + CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile()); + attachShader(frag); + #ifndef MAGNUM_TARGET_GLES if(!Context::current()->isExtensionSupported(version)) #else @@ -68,6 +70,7 @@ template Flat::Flat(): transformationProject #endif { bindAttributeLocation(Position::Location, "position"); + if(flags & Flag::Textured) bindAttributeLocation(TextureCoordinates::Location, "textureCoordinates"); } CORRADE_INTERNAL_ASSERT_OUTPUT(link()); @@ -77,7 +80,14 @@ template Flat::Flat(): transformationProject #endif { transformationProjectionMatrixUniform = uniformLocation("transformationProjectionMatrix"); - colorUniform = uniformLocation("color"); + if(!(flags & Flag::Textured)) colorUniform = uniformLocation("color"); + } + + #ifndef MAGNUM_TARGET_GLES + if(flags && !Context::current()->isExtensionSupported(version)) + #endif + { + if(flags & Flag::Textured) setUniform(uniformLocation("textureData"), TextureLayer); } } diff --git a/src/Shaders/Flat.frag b/src/Shaders/Flat.frag index 8f3066029..665ed51d6 100644 --- a/src/Shaders/Flat.frag +++ b/src/Shaders/Flat.frag @@ -24,18 +24,35 @@ #ifndef NEW_GLSL #define fragmentColor gl_FragColor +#define texture texture2D #endif +#ifdef TEXTURED +#ifdef EXPLICIT_TEXTURE_LAYER +layout(binding = 0) uniform sampler2D textureData; +#else +uniform sampler2D textureData; +#endif +#else #ifdef EXPLICIT_UNIFORM_LOCATION layout(location = 1) uniform vec4 color; #else uniform lowp vec4 color; #endif +#endif + +#ifdef TEXTURED +in mediump vec2 interpolatedTextureCoords; +#endif #ifdef NEW_GLSL out lowp vec4 fragmentColor; #endif void main() { + #ifdef TEXTURED + fragmentColor = texture(textureData, interpolatedTextureCoords); + #else fragmentColor = color; + #endif } diff --git a/src/Shaders/Flat.h b/src/Shaders/Flat.h index d8efe6abe..f71da8be3 100644 --- a/src/Shaders/Flat.h +++ b/src/Shaders/Flat.h @@ -38,18 +38,78 @@ namespace Magnum { namespace Shaders { +namespace Implementation { + enum class FlatFlag: UnsignedByte { Textured = 1 << 0 }; + typedef Containers::EnumSet FlatFlags; +} + /** -@brief Flat shader +@brief %Flat shader + +Draws whole mesh with given unshaded color or texture. For colored mesh you +need to provide @ref Position attribute in your triangle mesh and call at least +@ref setTransformationProjectionMatrix() and @ref setColor(). + +If you want to use texture instead of color, you need to provide also +@ref TextureCoordinates attribute. Pass @ref Flag::Textured to constructor and +then at render time bind the texture to its respective layer instead of calling +@ref setColor(). Example: +@code +Shaders::Flat2D shader(Shaders::Flat2D::Flag::Textured); -Draws whole mesh with one color. -@see Flat2D, Flat3D +// ... + +myTexture.bind(Shaders::Flat2D::TextureLayer); +@endcode + +@see @ref Flat2D, @ref Flat3D */ template class MAGNUM_SHADERS_EXPORT Flat: public AbstractShaderProgram { public: /** @brief Vertex position */ typedef Attribute<0, typename DimensionTraits::VectorType> Position; - explicit Flat(); + /** + * @brief Texture coordinates + * + * Used only if @ref Flag::Textured is set. + */ + typedef Attribute<2, Vector2> TextureCoordinates; + + enum: Int { + /** Layer for color texture. Used only if @ref Flag::Textured is set. */ + TextureLayer = 0 + }; + + #ifdef DOXYGEN_GENERATING_OUTPUT + /** + * @brief Shader flag + * + * @see @ref Flags, @ref flags() + */ + enum class Flag: UnsignedByte { + Textured = 1 << 0 /**< The shader uses texture instead of color */ + }; + + /** + * @brief Shader flags + * + * @see @ref flags() + */ + typedef Containers::EnumSet Flags; + #else + typedef Implementation::FlatFlag Flag; + typedef Implementation::FlatFlags Flags; + #endif + + /** + * @brief Constructor + * @param flags Shader flags + */ + explicit Flat(Flags flags = Flags()); + + /** @brief Shader flags */ + Flags flags() const { return _flags; } /** * @brief Set transformation and projection matrix @@ -63,15 +123,16 @@ template class MAGNUM_SHADERS_EXPORT Flat: public Abstra /** * @brief Set color * @return Reference to self (for method chaining) + * + * Has no effect if @ref Flag::Textured is set. */ - Flat& setColor(const Color4& color) { - setUniform(colorUniform, color); - return *this; - } + Flat& setColor(const Color4& color); private: Int transformationProjectionMatrixUniform, colorUniform; + + Flags _flags; }; /** @brief 2D flat shader */ @@ -80,6 +141,13 @@ typedef Flat<2> Flat2D; /** @brief 3D flat shader */ typedef Flat<3> Flat3D; +CORRADE_ENUMSET_OPERATORS(Implementation::FlatFlags) + +template inline Flat& Flat::setColor(const Color4& color) { + if(!(_flags & Flag::Textured)) setUniform(colorUniform, color); + return *this; +} + }} #endif diff --git a/src/Shaders/Flat2D.vert b/src/Shaders/Flat2D.vert index 9e983a978..aa0577bc7 100644 --- a/src/Shaders/Flat2D.vert +++ b/src/Shaders/Flat2D.vert @@ -24,6 +24,7 @@ #ifndef NEW_GLSL #define in attribute +#define out varying #endif #ifdef EXPLICIT_UNIFORM_LOCATION @@ -38,6 +39,20 @@ layout(location = 0) in highp vec2 position; in highp vec2 position; #endif +#ifdef TEXTURED +#ifdef EXPLICIT_ATTRIB_LOCATION +layout(location = 1) in mediump vec2 textureCoords; +#else +in mediump vec2 textureCoords; +#endif +out mediump vec2 interpolatedTextureCoords; +#endif + void main() { gl_Position.xywz = vec4(transformationProjectionMatrix*vec3(position, 1.0), 0.0); + + #ifdef TEXTURED + /* Texture coordinates, if needed */ + interpolatedTextureCoords = textureCoords; + #endif } diff --git a/src/Shaders/Flat3D.vert b/src/Shaders/Flat3D.vert index 2f4b875c5..5ddc90060 100644 --- a/src/Shaders/Flat3D.vert +++ b/src/Shaders/Flat3D.vert @@ -24,6 +24,7 @@ #ifndef NEW_GLSL #define in attribute +#define out varying #endif #ifdef EXPLICIT_UNIFORM_LOCATION @@ -38,6 +39,20 @@ layout(location = 0) in highp vec4 position; in highp vec4 position; #endif +#ifdef TEXTURED +#ifdef EXPLICIT_ATTRIB_LOCATION +layout(location = 1) in mediump vec2 textureCoords; +#else +in mediump vec2 textureCoords; +#endif +out mediump vec2 interpolatedTextureCoords; +#endif + void main() { gl_Position = transformationProjectionMatrix*position; + + #ifdef TEXTURED + /* Texture coordinates, if needed */ + interpolatedTextureCoords = textureCoords; + #endif } diff --git a/src/Shaders/Phong.h b/src/Shaders/Phong.h index 728bca52d..493599586 100644 --- a/src/Shaders/Phong.h +++ b/src/Shaders/Phong.h @@ -39,9 +39,9 @@ namespace Magnum { namespace Shaders { /** @brief Phong shader -Uses ambient, diffuse and specular color or texture. You need to provide -@ref Position and @ref Normal attributes in your triangle mesh and call at -least @ref setTransformationMatrix(), @ref setNormalMatrix(), +Uses ambient, diffuse and specular color or texture. For colored mesh you need +to provide @ref Position and @ref Normal attributes in your triangle mesh and +call at least @ref setTransformationMatrix(), @ref setNormalMatrix(), @ref setProjectionMatrix(), @ref setDiffuseColor() and @ref setLightPosition(). If you want to use texture instead of color, you need to provide also @@ -167,7 +167,7 @@ class MAGNUM_SHADERS_EXPORT Phong: public AbstractShaderProgram { * @brief Set normal matrix * @return Reference to self (for method chaining) */ - Phong& setNormalMatrix(const Math::Matrix<3, Float>& matrix) { + Phong& setNormalMatrix(const Matrix3x3& matrix) { setUniform(normalMatrixUniform, matrix); return *this; } diff --git a/src/Shaders/Test/FlatTest.cpp b/src/Shaders/Test/FlatTest.cpp index 3576beefb..fd376a76c 100644 --- a/src/Shaders/Test/FlatTest.cpp +++ b/src/Shaders/Test/FlatTest.cpp @@ -33,11 +33,15 @@ class FlatTest: public Magnum::Test::AbstractOpenGLTester { void compile2D(); void compile3D(); + void compile2DTextured(); + void compile3DTextured(); }; FlatTest::FlatTest() { addTests({&FlatTest::compile2D, - &FlatTest::compile3D}); + &FlatTest::compile3D, + &FlatTest::compile2DTextured, + &FlatTest::compile3DTextured}); } void FlatTest::compile2D() { @@ -50,6 +54,16 @@ void FlatTest::compile3D() { CORRADE_VERIFY(shader.validate().first); } +void FlatTest::compile2DTextured() { + Shaders::Flat2D shader(Shaders::Flat2D::Flag::Textured); + CORRADE_VERIFY(shader.validate().first); +} + +void FlatTest::compile3DTextured() { + Shaders::Flat3D shader(Shaders::Flat3D::Flag::Textured); + CORRADE_VERIFY(shader.validate().first); +} + }}} CORRADE_TEST_MAIN(Magnum::Shaders::Test::FlatTest) diff --git a/src/Shapes/CMakeLists.txt b/src/Shapes/CMakeLists.txt index 72f85a6ea..992639f60 100644 --- a/src/Shapes/CMakeLists.txt +++ b/src/Shapes/CMakeLists.txt @@ -67,7 +67,10 @@ if(BUILD_STATIC_PIC) endif() target_link_libraries(MagnumShapes Magnum MagnumSceneGraph) -install(TARGETS MagnumShapes DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +install(TARGETS MagnumShapes + RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} + LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} + ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) install(FILES ${MagnumShapes_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Shapes) if(BUILD_TESTS) diff --git a/src/Swizzle.h b/src/Swizzle.h index 2072f7223..ecf717e8a 100644 --- a/src/Swizzle.h +++ b/src/Swizzle.h @@ -25,57 +25,30 @@ */ /** @file /Swizzle.h - * @brief Function Magnum::swizzle() + * @brief Function @ref Magnum::swizzle() + * @deprecated Use @ref Math/Swizzle.h instead. */ #include "Math/Swizzle.h" + +#ifdef MAGNUM_BUILD_DEPRECATED #include "Color.h" namespace Magnum { -namespace Math { namespace Implementation { - template struct Component: public ComponentAtPosition {}; - template struct Component: public ComponentAtPosition {}; - template struct Component: public ComponentAtPosition {}; - template struct Component: public ComponentAtPosition {}; -}} - -namespace Implementation { - template struct TypeForSize { - typedef Math::Vector Type; - }; - template struct TypeForSize<2, T> { typedef Math::Vector2 Type; }; - template struct TypeForSize<3, T> { typedef Math::Vector3 Type; }; - template struct TypeForSize<4, T> { typedef Math::Vector4 Type; }; - template struct TypeForSize<3, BasicColor3> { typedef BasicColor3 Type; }; - template struct TypeForSize<3, BasicColor4> { typedef BasicColor3 Type; }; - template struct TypeForSize<4, BasicColor3> { typedef BasicColor4 Type; }; - template struct TypeForSize<4, BasicColor4> { typedef BasicColor4 Type; }; -} - /** -@brief Swizzle Vector components - -Creates new vector from given components. Example: -@code -Vector4i original(-1, 2, 3, 4); - -auto vec = swizzle<'a', '1', '0', 'r', 'g', 'b'>(original); -// vec == { 4, 1, 0, -1, 2, 3 } -@endcode -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 Math::Vector2, Math::Vector3, Math::Vector4, -Color3 or Color4 specialization is returned. - -@see @ref matrix-vector-component-access, Math::swizzle(), Vector4::xyz(), - Color4::rgb(), Vector4::xy(), Vector3::xy() +@copybrief Math::swizzle() +@deprecated Use @ref Magnum::Math::swizzle() "Math::swizzle()" instead. */ -template constexpr typename Implementation::TypeForSize::Type swizzle(const T& vector) { - return {Math::Implementation::Component::value(vector)...}; -} +#ifdef DOXYGEN_GENERATING_OUTPUT +template constexpr typename Math::Implementation::TypeForSize::Type swizzle(const T& vector); +#else +using Math::swizzle; +#endif } +#else +#error +#endif #endif diff --git a/src/Test/BufferGLTest.cpp b/src/Test/BufferGLTest.cpp index ebd9b1bf5..9ece79fad 100644 --- a/src/Test/BufferGLTest.cpp +++ b/src/Test/BufferGLTest.cpp @@ -22,6 +22,8 @@ DEALINGS IN THE SOFTWARE. */ +#include +#include #include #include "Buffer.h" @@ -82,10 +84,22 @@ void BufferGLTest::construct() { void BufferGLTest::data() { Buffer buffer; + /* Plain array */ constexpr Int data[] = {2, 7, 5, 13, 25}; - buffer.setData(5*4, data, Buffer::Usage::StaticDraw); + buffer.setData({data, 5}, Buffer::Usage::StaticDraw); MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(buffer.size(), 5*4); + /* STL vector */ + std::vector data2{2, 7, 5, 13, 25}; + buffer.setData(data2, Buffer::Usage::StaticDraw); + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(buffer.size(), 5*4); + + /* STL array */ + std::array data3{{2, 7, 5, 13, 25}}; + buffer.setData(data3, Buffer::Usage::StaticDraw); + MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /** @todo How to verify the contents in ES? */ @@ -100,10 +114,22 @@ void BufferGLTest::data() { CORRADE_COMPARE(contents[4], 25); #endif + /* Plain array */ constexpr Int subData[] = {125, 3, 15}; - buffer.setSubData(4, 3*4, subData); + buffer.setSubData(4, {subData, 3}); MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(buffer.size(), 5*4); + /* STL vector */ + std::vector subData2{125, 3, 15}; + buffer.setSubData(4, subData2); + MAGNUM_VERIFY_NO_ERROR(); + CORRADE_COMPARE(buffer.size(), 5*4); + + /* STL array */ + std::array subData3{{125, 3, 15}}; + buffer.setSubData(4, subData3); + MAGNUM_VERIFY_NO_ERROR(); CORRADE_COMPARE(buffer.size(), 5*4); /** @todo How to verify the contents in ES? */ @@ -254,7 +280,7 @@ void BufferGLTest::copy() { buffer1.setData(data, Buffer::Usage::StaticDraw); Buffer buffer2; - buffer2.setData(5, nullptr, Buffer::Usage::StaticDraw); + buffer2.setData({nullptr, 5}, Buffer::Usage::StaticDraw); Buffer::copy(buffer1, buffer2, 1, 2, 3); MAGNUM_VERIFY_NO_ERROR(); diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index 8f10d79ab..f3c741aed 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -33,7 +33,6 @@ corrade_add_test(MeshTest MeshTest.cpp LIBRARIES Magnum) corrade_add_test(RendererTest RendererTest.cpp LIBRARIES Magnum) corrade_add_test(ResourceManagerTest ResourceManagerTest.cpp LIBRARIES MagnumTestLib) corrade_add_test(SamplerTest SamplerTest.cpp LIBRARIES Magnum) -corrade_add_test(SwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib) if(BUILD_GL_TESTS) corrade_add_test(BufferGLTest BufferGLTest.cpp LIBRARIES ${GL_TEST_LIBRARIES}) diff --git a/src/Test/ColorTest.cpp b/src/Test/ColorTest.cpp index 93da6047c..657802f65 100644 --- a/src/Test/ColorTest.cpp +++ b/src/Test/ColorTest.cpp @@ -34,8 +34,6 @@ class ColorTest: public TestSuite::Tester { public: ColorTest(); - void access(); - void fromHue(); void fromSaturation(); void fromValue(); @@ -48,6 +46,7 @@ class ColorTest: public TestSuite::Tester { void hsvOverflow(); void hsvAlpha(); + void swizzleType(); void debug(); void configuration(); }; @@ -56,9 +55,7 @@ typedef Magnum::BasicColor3 Color3ub; typedef Magnum::BasicColor4 Color4ub; ColorTest::ColorTest() { - addTests({&ColorTest::access, - - &ColorTest::fromHue, + addTests({&ColorTest::fromHue, &ColorTest::fromSaturation, &ColorTest::fromValue, @@ -70,34 +67,11 @@ ColorTest::ColorTest() { &ColorTest::hsvOverflow, &ColorTest::hsvAlpha, + &ColorTest::swizzleType, &ColorTest::debug, &ColorTest::configuration}); } -void ColorTest::access() { - Color3ub c3(15, 255, 10); - const Color3ub cc3(15, 255, 10); - - CORRADE_COMPARE(c3.r(), 15); - CORRADE_COMPARE(c3.g(), 255); - CORRADE_COMPARE(c3.b(), 10); - CORRADE_COMPARE(cc3.r(), 15); - CORRADE_COMPARE(cc3.g(), 255); - CORRADE_COMPARE(cc3.b(), 10); - - Color4ub c4(125, 98, 51, 22); - const Color4ub cc4(125, 98, 51, 22); - - CORRADE_COMPARE(c4.r(), 125); - CORRADE_COMPARE(c4.g(), 98); - CORRADE_COMPARE(c4.b(), 51); - CORRADE_COMPARE(c4.a(), 22); - CORRADE_COMPARE(cc4.r(), 125); - CORRADE_COMPARE(cc4.g(), 98); - CORRADE_COMPARE(cc4.b(), 51); - CORRADE_COMPARE(cc4.a(), 22); -} - void ColorTest::fromHue() { CORRADE_COMPARE(Color3ub::fromHSV(Deg(27.0f), 1.0f, 1.0f), Color3ub(255, 114, 0)); CORRADE_COMPARE(Color3ub::fromHSV(Deg(86.0f), 1.0f, 1.0f), Color3ub(144, 255, 0)); @@ -165,6 +139,23 @@ void ColorTest::hsvAlpha() { CORRADE_COMPARE(Color4ub::fromHSV(Deg(230.0f), 0.749f, 0.427f, 23), Color4ub(27, 40, 108, 23)); } +void ColorTest::swizzleType() { + constexpr Color3 origColor3; + constexpr BasicColor4 origColor4; + + constexpr auto a = Math::swizzle<'y', 'z', 'r'>(origColor3); + CORRADE_VERIFY((std::is_same::value)); + + constexpr auto b = Math::swizzle<'y', 'z', 'a'>(origColor4); + CORRADE_VERIFY((std::is_same>::value)); + + constexpr auto c = Math::swizzle<'y', 'z', 'y', 'x'>(origColor3); + CORRADE_VERIFY((std::is_same::value)); + + constexpr auto d = Math::swizzle<'y', 'a', 'y', 'x'>(origColor4); + CORRADE_VERIFY((std::is_same>::value)); +} + void ColorTest::debug() { std::ostringstream o; Debug(&o) << Color3(0.5f, 0.75f, 1.0f); diff --git a/src/Test/SwizzleTest.cpp b/src/Test/SwizzleTest.cpp deleted file mode 100644 index 6ff58281b..000000000 --- a/src/Test/SwizzleTest.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - This file is part of Magnum. - - Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš - - 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 - -#include "Swizzle.h" - -namespace Magnum { namespace Test { - -class SwizzleTest: public TestSuite::Tester { - public: - SwizzleTest(); - - void rgba(); - void type(); - void defaultType(); -}; - -SwizzleTest::SwizzleTest() { - addTests({&SwizzleTest::rgba, - &SwizzleTest::type, - &SwizzleTest::defaultType}); -} - -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::type() { - constexpr Vector4i orig; - constexpr Color3 origColor3; - constexpr BasicColor4 origColor4; - - /* decltype(a) is not const because a is not constexpr under GCC <= 4.5 */ - #ifdef CORRADE_GCC45_COMPATIBILITY - #define const - #endif - - constexpr auto a = swizzle<'y', 'a'>(orig); - CORRADE_VERIFY((std::is_same::value)); - - constexpr auto b = swizzle<'y', 'z', 'a'>(orig); - CORRADE_VERIFY((std::is_same::value)); - - constexpr auto c = swizzle<'y', 'a', 'y', 'x'>(orig); - CORRADE_VERIFY((std::is_same::value)); - - constexpr auto d = swizzle<'y', 'z', 'r'>(origColor3); - CORRADE_VERIFY((std::is_same::value)); - - constexpr auto e = swizzle<'y', 'z', 'a'>(origColor4); - CORRADE_VERIFY((std::is_same>::value)); - - constexpr auto f = swizzle<'y', 'z', 'y', 'x'>(origColor3); - CORRADE_VERIFY((std::is_same::value)); - - constexpr auto g = swizzle<'y', 'a', 'y', 'x'>(origColor4); - CORRADE_VERIFY((std::is_same>::value)); - - #ifdef CORRADE_GCC45_COMPATIBILITY - #undef const - #endif -} - -void SwizzleTest::defaultType() { - constexpr Vector4i orig(1, 2, 3, 4); - - constexpr auto a = swizzle<'b'>(orig); - CORRADE_COMPARE(a, (Math::Vector<1, Int>(3))); - - constexpr auto b = swizzle<'b', 'r', 'a', 'g', 'z', 'y', 'x'>(orig); - CORRADE_COMPARE(b, (Math::Vector<7, Int>(3, 1, 4, 2, 3, 2, 1))); -} - -}} - -CORRADE_TEST_MAIN(Magnum::Test::SwizzleTest) diff --git a/src/Text/CMakeLists.txt b/src/Text/CMakeLists.txt index ddd67fb42..b1176844e 100644 --- a/src/Text/CMakeLists.txt +++ b/src/Text/CMakeLists.txt @@ -45,7 +45,10 @@ if(BUILD_STATIC_PIC) endif() target_link_libraries(MagnumText Magnum MagnumTextureTools) -install(TARGETS MagnumText DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +install(TARGETS MagnumText + RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} + LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} + ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) install(FILES ${MagnumText_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Text) if(BUILD_TESTS) diff --git a/src/Text/TextRenderer.cpp b/src/Text/TextRenderer.cpp index c3e06dd9a..79e707aff 100644 --- a/src/Text/TextRenderer.cpp +++ b/src/Text/TextRenderer.cpp @@ -180,7 +180,7 @@ std::tuple AbstractTextRenderer::render(AbstractFont& font, con indices = new char[indicesSize]; createIndices(indices, layouter->glyphCount()); } - indexBuffer.setData(indicesSize, indices, usage); + indexBuffer.setData({indices, indicesSize}, usage); delete indices; /* Configure mesh except for vertex buffer (depends on dimension count, done @@ -205,7 +205,7 @@ template std::tuple TextRenderer(length); + return &buffer == &_indexBuffer ? _indexBufferData : _vertexBufferData; + #endif } -#ifndef MAGNUM_TARGET_GLES2 +#if !defined(MAGNUM_TARGET_GLES2) || defined(CORRADE_TARGET_EMSCRIPTEN) inline void AbstractTextRenderer::bufferUnmapImplementation(Buffer& buffer) #else void AbstractTextRenderer::bufferUnmapImplementationDefault(Buffer& buffer) #endif { + #ifndef CORRADE_TARGET_EMSCRIPTEN buffer.unmap(); + #else + buffer.setSubData(0, &buffer == &_indexBuffer ? _indexBufferData : _vertexBufferData); + #endif } AbstractTextRenderer::AbstractTextRenderer(AbstractFont& font, const GlyphCache& cache, Float size): _vertexBuffer(Buffer::Target::Array), _indexBuffer(Buffer::Target::ElementArray), font(font), cache(cache), size(size), _capacity(0) { #ifndef MAGNUM_TARGET_GLES MAGNUM_ASSERT_EXTENSION_SUPPORTED(Extensions::GL::ARB::map_buffer_range); - #elif defined(MAGNUM_TARGET_GLES2) + #elif defined(MAGNUM_TARGET_GLES2) && !defined(CORRADE_TARGET_EMSCRIPTEN) if(Context::current()->isExtensionSupported()) { bufferMapImplementation = &AbstractTextRenderer::bufferMapImplementationRange; } else if(Context::current()->isExtensionSupported()) { @@ -278,7 +287,10 @@ void AbstractTextRenderer::reserve(const uint32_t glyphCount, const Buffer::Usag const UnsignedInt indexCount = glyphCount*6; /* Allocate vertex buffer, reset vertex count */ - _vertexBuffer.setData(vertexCount*sizeof(Vertex), nullptr, vertexBufferUsage); + _vertexBuffer.setData({nullptr, vertexCount*sizeof(Vertex)}, vertexBufferUsage); + #ifdef CORRADE_TARGET_EMSCRIPTEN + _vertexBufferData = Containers::Array(vertexCount*sizeof(Vertex)); + #endif _mesh.setVertexCount(0); /* Allocate index buffer, reset index count and reconfigure buffer binding */ @@ -294,7 +306,10 @@ void AbstractTextRenderer::reserve(const uint32_t glyphCount, const Buffer::Usag indexType = Mesh::IndexType::UnsignedInt; indicesSize = indexCount*sizeof(UnsignedInt); } - _indexBuffer.setData(indicesSize, nullptr, indexBufferUsage); + _indexBuffer.setData({nullptr, indicesSize}, indexBufferUsage); + #ifdef CORRADE_TARGET_EMSCRIPTEN + _indexBufferData = Containers::Array(indicesSize); + #endif _mesh.setIndexCount(0) .setIndexBuffer(_indexBuffer, 0, indexType, 0, vertexCount); @@ -359,7 +374,9 @@ void AbstractTextRenderer::render(const std::string& text) { delete layouter; } +#ifndef DOXYGEN_GENERATING_OUTPUT template class MAGNUM_TEXT_EXPORT TextRenderer<2>; template class MAGNUM_TEXT_EXPORT TextRenderer<3>; +#endif }} diff --git a/src/Text/TextRenderer.h b/src/Text/TextRenderer.h index 02c05da66..9cc2f97e4 100644 --- a/src/Text/TextRenderer.h +++ b/src/Text/TextRenderer.h @@ -129,6 +129,9 @@ class MAGNUM_TEXT_EXPORT AbstractTextRenderer { Mesh _mesh; Buffer _vertexBuffer, _indexBuffer; + #ifdef CORRADE_TARGET_EMSCRIPTEN + Containers::Array _vertexBufferData, _indexBufferData; + #endif private: AbstractFont& font; @@ -137,23 +140,33 @@ class MAGNUM_TEXT_EXPORT AbstractTextRenderer { UnsignedInt _capacity; Rectangle _rectangle; - #ifdef MAGNUM_TARGET_GLES2 + #if defined(MAGNUM_TARGET_GLES2) && !defined(CORRADE_TARGET_EMSCRIPTEN) typedef void*(*BufferMapImplementation)(Buffer&, GLsizeiptr); static MAGNUM_TEXT_LOCAL void* bufferMapImplementationFull(Buffer& buffer, GLsizeiptr length); static MAGNUM_TEXT_LOCAL void* bufferMapImplementationSub(Buffer& buffer, GLsizeiptr length); static MAGNUM_TEXT_LOCAL void* bufferMapImplementationRange(Buffer& buffer, GLsizeiptr length); static BufferMapImplementation bufferMapImplementation; #else - static void* bufferMapImplementation(Buffer& buffer, GLsizeiptr length); + #ifndef CORRADE_TARGET_EMSCRIPTEN + static + #else + MAGNUM_TEXT_LOCAL + #endif + void* bufferMapImplementation(Buffer& buffer, GLsizeiptr length); #endif - #ifdef MAGNUM_TARGET_GLES2 + #if defined(MAGNUM_TARGET_GLES2) && !defined(CORRADE_TARGET_EMSCRIPTEN) typedef void(*BufferUnmapImplementation)(Buffer&); static MAGNUM_TEXT_LOCAL void bufferUnmapImplementationDefault(Buffer& buffer); static MAGNUM_TEXT_LOCAL void bufferUnmapImplementationSub(Buffer& buffer); static MAGNUM_TEXT_LOCAL BufferUnmapImplementation bufferUnmapImplementation; #else - static void bufferUnmapImplementation(Buffer& buffer); + #ifndef CORRADE_TARGET_EMSCRIPTEN + static + #else + MAGNUM_TEXT_LOCAL + #endif + void bufferUnmapImplementation(Buffer& buffer); #endif }; @@ -222,6 +235,8 @@ Mutable text rendering requires @extension{ARB,map_buffer_range} on desktop OpenGL (also part of OpenGL ES 3.0). If neither @es_extension{EXT,map_buffer_range} nor @es_extension{CHROMIUM,map_sub} is not available in ES 2.0, at least @es_extension{OES,mapbuffer} must be supported for asynchronous buffer updates. +There is no similar extension in WebGL, thus plain (and slow) buffer updates +are used there. @see TextRenderer2D, TextRenderer3D, Font, Shaders::AbstractVectorShader */ diff --git a/src/TextureFormat.h b/src/TextureFormat.h index 8a9732f71..c5be28182 100644 --- a/src/TextureFormat.h +++ b/src/TextureFormat.h @@ -40,8 +40,8 @@ namespace Magnum { enum class TextureFormat: GLenum { /** * Red component, normalized unsigned, size implementation-dependent. - * @deprecated Prefer to use the exactly specified version of this format, - * e.g. @ref Magnum::TextureFormat "TextureFormat::R8". + * @deprecated_gl Prefer to use the exactly specified version of this + * format, e.g. @ref Magnum::TextureFormat "TextureFormat::R8". * @requires_gl30 %Extension @extension{ARB,texture_rg} * @requires_gles30 %Extension @es_extension{EXT,texture_rg} */ @@ -64,8 +64,8 @@ enum class TextureFormat: 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::TextureFormat "TextureFormat::RG8". + * @deprecated_gl Prefer to use the exactly specified version of this + * format, e.g. @ref Magnum::TextureFormat "TextureFormat::RG8". * @requires_gl30 %Extension @extension{ARB,texture_rg} * @requires_gles30 %Extension @es_extension{EXT,texture_rg} */ @@ -87,8 +87,8 @@ enum class TextureFormat: GLenum { /** * RGB, normalized unsigned, size implementation-dependent. - * @deprecated Prefer to use the exactly specified version of this format, - * e.g. @ref Magnum::TextureFormat "TextureFormat::RGB8". + * @deprecated_gl Prefer to use the exactly specified version of this + * format, e.g. @ref Magnum::TextureFormat "TextureFormat::RGB8". */ RGB = GL_RGB, @@ -104,8 +104,8 @@ enum class TextureFormat: GLenum { /** * RGBA, normalized unsigned, size implementation-dependent. - * @deprecated Prefer to use the exactly specified version of this format, - * e.g. @ref Magnum::TextureFormat "TextureFormat::RGBA8". + * @deprecated_gl Prefer to use the exactly specified version of this + * format, e.g. @ref Magnum::TextureFormat "TextureFormat::RGBA8". */ RGBA = GL_RGBA, @@ -475,7 +475,7 @@ enum class TextureFormat: GLenum { /** * Luminance, normalized unsigned, single value used for all RGB channels. * Size implementation-dependent. - * @deprecated Included for compatibility reasons only, use + * @deprecated_gl Included for compatibility reasons only, use * @ref Magnum::TextureFormat "TextureFormat::R8" instead. * @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use * @ref Magnum::TextureFormat "TextureFormat::R8" instead. @@ -486,7 +486,7 @@ enum class TextureFormat: GLenum { * Floating-point luminance and alpha channel. First value is used for all * RGB channels, second value is used for alpha channel. Size * implementation-dependent. - * @deprecated Included for compatibility reasons only, use + * @deprecated_gl Included for compatibility reasons only, use * @ref Magnum::TextureFormat "TextureFormat::RG8" instead. * @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use * @ref Magnum::TextureFormat "TextureFormat::RG8" instead. @@ -564,8 +564,8 @@ enum class TextureFormat: GLenum { /** * sRGB, normalized unsigned, size implementation-dependent. * @todo is this allowed in core? - * @deprecated Prefer to use the exactly specified version of this format, - * i.e. @ref Magnum::TextureFormat "TextureFormat::SRGB8". + * @deprecated_gl Prefer to use the exactly specified version of this + * format, i.e. @ref Magnum::TextureFormat "TextureFormat::SRGB8". * @requires_es_extension %Extension @es_extension{EXT,sRGB} in OpenGL ES * 2.0, use @ref Magnum::TextureFormat "TextureFormat::SRGB8" in * OpenGL ES 3.0 instead. @@ -639,8 +639,8 @@ enum class TextureFormat: GLenum { /** * sRGBA, normalized unsigned, size implementation-dependent. * @todo is this allowed in core? - * @deprecated Prefer to use the exactly specified version of this format, - * i.e. @ref Magnum::TextureFormat "TextureFormat::SRGB8Alpha8". + * @deprecated_gl Prefer to use the exactly specified version of this + * format, i.e. @ref Magnum::TextureFormat "TextureFormat::SRGB8Alpha8". * @requires_es_extension %Extension @es_extension{EXT,sRGB} in OpenGL ES * 2.0, use @ref Magnum::TextureFormat "TextureFormat::SRGB8Alpha8" in * OpenGL ES 3.0 instead. @@ -751,8 +751,8 @@ enum class TextureFormat: GLenum { /** * Depth component, size implementation-dependent. - * @deprecated Prefer to use exactly specified version of this format, e.g. - * @ref Magnum::TextureFormat "TextureFormat::DepthComponent16". + * @deprecated_gl Prefer to use the exactly specified version of this + * format, e.g. @ref Magnum::TextureFormat "TextureFormat::DepthComponent16". * @requires_gles30 %Extension @es_extension{OES,depth_texture} or * @es_extension{ANGLE,depth_texture} */ @@ -812,8 +812,8 @@ enum class TextureFormat: GLenum { /** * Depth and stencil component, size implementation-dependent. - * @deprecated Prefer to use exactly specified version of this format, e.g. - * @ref Magnum::TextureFormat "TextureFormat::Depth24Stencil8". + * @deprecated_gl Prefer to use exactly specified version of this format, + * e.g. @ref Magnum::TextureFormat "TextureFormat::Depth24Stencil8". * @requires_gles30 %Extension @es_extension{OES,packed_depth_stencil} */ #ifndef MAGNUM_TARGET_GLES2 diff --git a/src/TextureTools/CMakeLists.txt b/src/TextureTools/CMakeLists.txt index f3dc153c0..cf1ba673c 100644 --- a/src/TextureTools/CMakeLists.txt +++ b/src/TextureTools/CMakeLists.txt @@ -61,7 +61,10 @@ if(WITH_DISTANCEFIELDCONVERTER) install(TARGETS magnum-distancefield DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}) endif() -install(TARGETS MagnumTextureTools DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +install(TARGETS MagnumTextureTools + RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR} + LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR} + ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) install(FILES ${MagnumTextureTools_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/TextureTools) if(BUILD_TESTS) diff --git a/src/magnumConfigure.h.cmake b/src/magnumConfigure.h.cmake index 1cb5f49b5..e6b255e1c 100644 --- a/src/magnumConfigure.h.cmake +++ b/src/magnumConfigure.h.cmake @@ -22,6 +22,7 @@ DEALINGS IN THE SOFTWARE. */ +#cmakedefine MAGNUM_BUILD_DEPRECATED #cmakedefine MAGNUM_BUILD_STATIC #cmakedefine MAGNUM_TARGET_GLES #cmakedefine MAGNUM_TARGET_GLES2 diff --git a/toolchains b/toolchains index a941827bf..8e6dbeeb6 160000 --- a/toolchains +++ b/toolchains @@ -1 +1 @@ -Subproject commit a941827bff39e48b85c6d780e08bbc369deb9ea4 +Subproject commit 8e6dbeeb661ad0bd2d678b9f6bfb9e9044eb45f9