diff --git a/doc/compilation-speedup.dox b/doc/compilation-speedup.dox index b14647277..c1a0802f6 100644 --- a/doc/compilation-speedup.dox +++ b/doc/compilation-speedup.dox @@ -14,6 +14,11 @@ floating-point vectors and matrices like @ref Vector3 and @ref Matrix4, but to actually use any of them, you have to include the respective header, e.g. Math/Vector3.h. +You are encouraged to use forward declarations also in your code. However, for +some types it can be too cumbersome -- e.g. too many template parameters, +typedefs etc. In this case a header with forward declarations is usually +available: see SceneGraph/SceneGraph.h for example. + @section compilation-speedup-templates Templates Many things in %Magnum are templated to allow handling of various types and @@ -33,17 +38,18 @@ Template implementation files have `*.hpp` extension (hinting that they are something between `*.h` and `*.cpp` files). Template implementation file can be included along the header itself and it -will just work, but it doesn't positively affect compilation time. If you are -using one template specialization on many places, template implementation -files give you the ability to explicitly instantiate the template in some -source file. Then you can include only the header everywhere else and leave -the rest on the linker. +will just work, but it will negatively affect compilation time. If you are +using one template specialization in many places, the compiler performs +compilation of the same template specialization many times. Template +implementation files give you the ability to explicitly instantiate the +template only once in some dedicated source file. Then you can include just +the header everywhere else and leave the rest on the linker. Templated classes which have implementation files state in their documentation all common specializations that are already compiled in the libraries. So, -unless the templated class is too generic (ResourceManager for example) or you -need something special, you don't have to mess with Object implementation -files at all. See Color3 or SceneGraph::Object for an example. +unless the templated class is too generic or you need something special, you +don't have to mess with template implementation files at all. See +SceneGraph::Object or SceneGraph::AbstractCamera for an example. Sometimes you however need to use your own specialization and that's why template implementation files are included in the library. For example we want @@ -61,8 +67,8 @@ using namespace Magnum::SceneGraph; template class Object>; @endcode All other files using the same object specialization now need to include only -SceneGraph/Object.h header and if we compile our `Object.cpp` together with -the rest, the Object specialization will be compiled only once. +SceneGraph/Object.h header. Thus the Object specialization will be compiled +only once in our `Object.cpp` file, saving precious compilation time. @subsection compilation-speedup-extern-templates Extern templates diff --git a/doc/scenegraph.dox b/doc/scenegraph.dox index 4adbf419f..3ea52abf2 100644 --- a/doc/scenegraph.dox +++ b/doc/scenegraph.dox @@ -24,6 +24,11 @@ Transformation handles object position, rotation etc. and its basic property is dimension count (2D or 3D) and underlying floating-point type (by default `float`s are used everywhere, but you can use `double`s too). +@note All classes in SceneGraph have `GLfloat` as default underlying + floating-point type, which means that you can omit that template parameter + and write just %AbstractObject<2> or %MatrixTransformation3D<> + instead of %AbstractObject<2, GLfloat> and %MatrixTransformation3D<GLfloat>. + %Scene graph has implementation of transformations in both 2D and 3D, using either matrices or combination of position and rotation. Each implementation has its own advantages and disadvantages -- for example when using matrices diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index b768ea334..7f85beeaf 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -28,6 +28,8 @@ #include "magnumVisibility.h" +/** @todo early asserts (no bool returns?) */ + namespace Magnum { namespace Math { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6492fb4a0..2f1eadbb6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -98,7 +98,9 @@ endif() # Files shared between main library and math unit test library set(MagnumMath_SRCS - Math/Math.cpp) + Math/Math.cpp + Math/RectangularMatrix.cpp + Math/Vector.cpp) if(NOT CMAKE_NO_OBJECT_TARGET) add_library(MagnumMathObjects OBJECT ${MagnumMath_SRCS}) endif() @@ -167,13 +169,21 @@ if(BUILD_TESTS) # Library with graceful assert for testing if(NOT CMAKE_NO_OBJECT_TARGET) + add_library(MagnumMathTestLib SHARED + $) + add_library(MagnumTestLib SHARED - $) + $ + $) else() + add_library(MagnumMathTestLib SHARED + ${MagnumMath_SRCS}) + add_library(MagnumTestLib SHARED - ${Magnum_SRCS}) + ${Magnum_SRCS} + ${MagnumMath_SRCS}) endif() - set_target_properties(MagnumTestLib PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) + set_target_properties(MagnumTestLib MagnumMathTestLib PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) target_link_libraries(MagnumTestLib ${Magnum_LIBS}) add_subdirectory(Test) diff --git a/src/Color.h b/src/Color.h index c24866b9d..044fc3579 100644 --- a/src/Color.h +++ b/src/Color.h @@ -143,6 +143,8 @@ range @f$ [0.0, 1.0] @f$. @todo Signed normalization to [-1.0, 1.0] like in OpenGL? */ +/* Not using template specialization because some internal functions are + impossible to explicitly instantiate */ template class Color3: public Math::Vector3 { public: /** @brief Corresponding floating-point type for HSV computation */ @@ -287,6 +289,8 @@ MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Color3, 3) See Color3 for more information. */ +/* Not using template specialization because some internal functions are + impossible to explicitly instantiate */ template class Color4: public Math::Vector4 { public: /** @copydoc Color3::FloatingPointType */ diff --git a/src/Math/Algorithms/Test/CMakeLists.txt b/src/Math/Algorithms/Test/CMakeLists.txt index 8ebf44bc1..41e1779f2 100644 --- a/src/Math/Algorithms/Test/CMakeLists.txt +++ b/src/Math/Algorithms/Test/CMakeLists.txt @@ -1 +1 @@ -corrade_add_test2(MathAlgorithmsGaussJordanTest GaussJordanTest.cpp) +corrade_add_test2(MathAlgorithmsGaussJordanTest GaussJordanTest.cpp LIBRARIES MagnumMathTestLib) diff --git a/src/Math/RectangularMatrix.cpp b/src/Math/RectangularMatrix.cpp new file mode 100644 index 000000000..73b56677d --- /dev/null +++ b/src/Math/RectangularMatrix.cpp @@ -0,0 +1,106 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "RectangularMatrix.h" + +namespace Magnum { namespace Math { + +#ifndef DOXYGEN_GENERATING_OUTPUT +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 2, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 3, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 4, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 2, int>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 3, int>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 4, int>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 2, unsigned int>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 3, unsigned int>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 4, unsigned int>&); +#ifndef MAGNUM_TARGET_GLES +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 2, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 3, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<1, 4, double>&); +#endif + +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<2, 2, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<3, 3, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<4, 4, float>&); +#ifndef MAGNUM_TARGET_GLES +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<2, 2, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<3, 3, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<4, 4, double>&); +#endif + +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<2, 3, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<3, 2, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<2, 4, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<4, 2, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<3, 4, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<4, 3, float>&); +#ifndef MAGNUM_TARGET_GLES +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<2, 3, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<3, 2, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<2, 4, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<4, 2, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<3, 4, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::RectangularMatrix<4, 3, double>&); +#endif +#endif + +}} + +namespace Corrade { namespace Utility { + +#ifndef DOXYGEN_GENERATING_OUTPUT +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +#ifndef MAGNUM_TARGET_GLES +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +#endif + +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +#ifndef MAGNUM_TARGET_GLES +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +#endif + +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +#ifndef MAGNUM_TARGET_GLES +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +template struct ConfigurationValue>; +#endif +#endif + +}} diff --git a/src/Math/RectangularMatrix.h b/src/Math/RectangularMatrix.h index 8d917e19b..2dd862b2b 100644 --- a/src/Math/RectangularMatrix.h +++ b/src/Math/RectangularMatrix.h @@ -26,6 +26,8 @@ #include "MathTypeTraits.h" +#include "magnumVisibility.h" + namespace Magnum { namespace Math { /** @todo Properly test all constexpr */ @@ -400,6 +402,51 @@ template Corrade::Utility::Debug op return debug; } +/* Explicit instantiation for types used in OpenGL */ +#ifndef DOXYGEN_GENERATING_OUTPUT +/* Vectors */ +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 2, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 3, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 4, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 2, int>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 3, int>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 4, int>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 2, unsigned int>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 3, unsigned int>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 4, unsigned int>&); +#ifndef MAGNUM_TARGET_GLES +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 2, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 3, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<1, 4, double>&); +#endif + +/* Square matrices */ +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<2, 2, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<3, 3, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<4, 4, float>&); +#ifndef MAGNUM_TARGET_GLES +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<2, 2, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<3, 3, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<4, 4, double>&); +#endif + +/* Rectangular matrices */ +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<2, 3, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<3, 2, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<2, 4, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<4, 2, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<3, 4, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<4, 3, float>&); +#ifndef MAGNUM_TARGET_GLES +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<2, 3, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<3, 2, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<2, 4, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<4, 2, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<3, 4, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const RectangularMatrix<4, 3, double>&); +#endif +#endif + #ifndef DOXYGEN_GENERATING_OUTPUT #define MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(cols, rows, ...) \ inline constexpr static __VA_ARGS__& from(T* data) { \ @@ -491,6 +538,50 @@ template struct ConfigurationValue< } }; +#ifndef DOXYGEN_GENERATING_OUTPUT +/* Vectors */ +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +#ifndef MAGNUM_TARGET_GLES +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +#endif + +/* Square matrices */ +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +#ifndef MAGNUM_TARGET_GLES +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +#endif + +/* Rectangular matrices */ +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +#ifndef MAGNUM_TARGET_GLES +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +extern template struct MAGNUM_EXPORT ConfigurationValue>; +#endif +#endif + }} /* Include also Vector, so the definition is complete */ diff --git a/src/Math/Test/CMakeLists.txt b/src/Math/Test/CMakeLists.txt index a7f583747..c641a04a5 100644 --- a/src/Math/Test/CMakeLists.txt +++ b/src/Math/Test/CMakeLists.txt @@ -1,24 +1,19 @@ corrade_add_test2(MathConstantsTest ConstantsTest.cpp) -if(NOT CMAKE_NO_OBJECT_TARGET) - set(MathTest_SRCS MathTest.cpp $) -else() - set(MathTest_SRCS MathTest.cpp ${MagnumMath_SRCS}) -endif() -corrade_add_test2(MathTest ${MathTest_SRCS}) +corrade_add_test2(MathTest MathTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test2(MathMathTypeTraitsTest MathTypeTraitsTest.cpp) -corrade_add_test2(MathRectangularMatrixTest RectangularMatrixTest.cpp) +corrade_add_test2(MathRectangularMatrixTest RectangularMatrixTest.cpp LIBRARIES MagnumMathTestLib) -corrade_add_test2(MathVectorTest VectorTest.cpp) -corrade_add_test2(MathVector2Test Vector2Test.cpp) -corrade_add_test2(MathVector3Test Vector3Test.cpp) -corrade_add_test2(MathVector4Test Vector4Test.cpp) +corrade_add_test2(MathVectorTest VectorTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test2(MathVector2Test Vector2Test.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test2(MathVector3Test Vector3Test.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test2(MathVector4Test Vector4Test.cpp LIBRARIES MagnumMathTestLib) -corrade_add_test2(MathPoint2DTest Point2DTest.cpp) -corrade_add_test2(MathPoint3DTest Point3DTest.cpp) +corrade_add_test2(MathPoint2DTest Point2DTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test2(MathPoint3DTest Point3DTest.cpp LIBRARIES MagnumMathTestLib) -corrade_add_test2(MathMatrixTest MatrixTest.cpp) -corrade_add_test2(MathMatrix3Test Matrix3Test.cpp) -corrade_add_test2(MathMatrix4Test Matrix4Test.cpp) +corrade_add_test2(MathMatrixTest MatrixTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test2(MathMatrix3Test Matrix3Test.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test2(MathMatrix4Test Matrix4Test.cpp LIBRARIES MagnumMathTestLib) set_target_properties(MathVectorTest MathMatrix4Test PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) diff --git a/src/Math/Vector.cpp b/src/Math/Vector.cpp new file mode 100644 index 000000000..0004c854e --- /dev/null +++ b/src/Math/Vector.cpp @@ -0,0 +1,37 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "Vector.h" + +namespace Magnum { namespace Math { + +#ifndef DOXYGEN_GENERATING_OUTPUT +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<2, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<3, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<4, float>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<2, int>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<3, int>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<4, int>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<2, unsigned int>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<3, unsigned int>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<4, unsigned int>&); +#ifndef MAGNUM_TARGET_GLES +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<2, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<3, double>&); +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug, const Magnum::Math::Vector<4, double>&); +#endif +#endif + +}} diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 57f2509d6..a0304c49d 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -254,6 +254,24 @@ template Corrade::Utility::Debug operator<<(Corrade:: return debug; } +/* Explicit instantiation for types used in OpenGL */ +#ifndef DOXYGEN_GENERATING_OUTPUT +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<2, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<3, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<4, float>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<2, int>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<3, int>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<4, int>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<2, unsigned int>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<3, unsigned int>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<4, unsigned int>&); +#ifndef MAGNUM_TARGET_GLES +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<2, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<3, double>&); +extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utility::Debug, const Vector<4, double>&); +#endif +#endif + #ifndef DOXYGEN_GENERATING_OUTPUT #define MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Type, size) \ inline constexpr static Type& from(T* data) { \ diff --git a/src/Physics/Box.h b/src/Physics/Box.h index d92ab64ab..81959172e 100644 --- a/src/Physics/Box.h +++ b/src/Physics/Box.h @@ -30,6 +30,7 @@ namespace Magnum { namespace Physics { /** @brief Unit-size box with assigned transformation matrix +@todo Use quat + position + size instead? @see Box2D, Box3D */ template class PHYSICS_EXPORT Box: public AbstractShape { diff --git a/src/Physics/CMakeLists.txt b/src/Physics/CMakeLists.txt index fdfde2722..e3eec9146 100644 --- a/src/Physics/CMakeLists.txt +++ b/src/Physics/CMakeLists.txt @@ -3,20 +3,30 @@ set(MagnumPhysics_SRCS AxisAlignedBox.cpp Box.cpp Capsule.cpp + DebugDrawResourceManager.cpp Line.cpp Plane.cpp Point.cpp + ObjectShape.cpp + ObjectShapeGroup.cpp ShapeGroup.cpp - Sphere.cpp) + Sphere.cpp + + Implementation/AbstractDebugRenderer.cpp + Implementation/BoxRenderer.cpp) + set(MagnumPhysics_HEADERS AbstractShape.h AxisAlignedBox.h Box.h Capsule.h + DebugDrawResourceManager.h Line.h LineSegment.h Plane.h Point.h + ObjectShape.h + ObjectShapeGroup.h ShapeGroup.h Sphere.h diff --git a/src/Physics/DebugDrawResourceManager.cpp b/src/Physics/DebugDrawResourceManager.cpp index f048a5816..c2f35c2f3 100644 --- a/src/Physics/DebugDrawResourceManager.cpp +++ b/src/Physics/DebugDrawResourceManager.cpp @@ -18,13 +18,14 @@ #include "AbstractShaderProgram.h" #include "Buffer.h" #include "Mesh.h" +#include "ResourceManager.h" #include "Shaders/FlatShader.h" #include "AbstractShape.h" #include "Box.h" -#include "ShapedObject.h" +#include "ObjectShape.h" #include "ShapeGroup.h" -#include "Implementation/AbstractDebugRenderer.h" #include "Implementation/BoxRenderer.h" +#include "Implementation/DebugRenderer.h" namespace Magnum { @@ -32,24 +33,33 @@ template class ResourceManager SceneGraph::Drawable* DebugDrawResourceManager::createDebugRenderer(ObjectShape* shape, ResourceKey options) { + Implementation::DebugRenderer* renderer = new Implementation::DebugRenderer(shape->object(), instance()->get(options)); + createDebugMesh(renderer, shape->shape()); + return renderer; } -SceneGraph::Object2D* DebugDrawResourceManager::createDebugMesh(SceneGraph::Object2D* parent, AbstractShape2D* shape, ResourceKey options) { +template SceneGraph::Drawable<2>* DebugDrawResourceManager::createDebugRenderer(ObjectShape<2>* shape, ResourceKey options); +template SceneGraph::Drawable<3>* DebugDrawResourceManager::createDebugRenderer(ObjectShape<3>* shape, ResourceKey options); + +void DebugDrawResourceManager::createDebugMesh(Implementation::DebugRenderer<2>* renderer, AbstractShape2D* shape) { switch(shape->type()) { case AbstractShape2D::Type::Box: - return new Implementation::BoxRenderer<2>(*static_cast(shape), options, parent); + renderer->addRenderer(new Implementation::BoxRenderer<2>(*static_cast(shape))); + break; case AbstractShape2D::Type::ShapeGroup: { - if(!parent) parent = new SceneGraph::Object2D; ShapeGroup2D* group = static_cast(shape); - if(group->first()) createDebugMesh(parent, group->first(), options); - if(group->second()) createDebugMesh(parent, group->second(), options); - return parent; - } default: return nullptr; + if(group->first()) createDebugMesh(renderer, group->first()); + if(group->second()) createDebugMesh(renderer, group->second()); + break; + } + default: + Warning() << "Physics::DebugDrawResourceManager::createDebugRenderer(): type" << shape->type() << "not implemented"; } } +void DebugDrawResourceManager::createDebugMesh(Implementation::DebugRenderer<3>*, AbstractShape3D*) {} + DebugDrawResourceManager::DebugDrawResourceManager() { setFallback(new Options); set("shader2d", new Shaders::FlatShader<2>, ResourceDataState::Final, ResourcePolicy::Resident); diff --git a/src/Physics/DebugDrawResourceManager.h b/src/Physics/DebugDrawResourceManager.h index db22e4221..618b594eb 100644 --- a/src/Physics/DebugDrawResourceManager.h +++ b/src/Physics/DebugDrawResourceManager.h @@ -22,6 +22,7 @@ #include "Magnum.h" #include "Color.h" #include "ResourceManager.h" +#include "SceneGraph/SceneGraph.h" #include "magnumPhysicsVisibility.h" @@ -36,27 +37,20 @@ namespace Physics { namespace Implementation { struct Options { Color3 color; }; - template class AbstractDebugRenderer; + template class DebugRenderer; }} - -#ifndef WIN32 -extern template class PHYSICS_EXPORT ResourceManager; -#endif #endif -/** @todo fix extern template multiple definition linker errors in mingw32-gcc */ - -namespace SceneGraph { - class Object2D; - class Object3D; -} - namespace Physics { template class AbstractShape; typedef AbstractShape<2> AbstractShape2D; typedef AbstractShape<3> AbstractShape3D; +template class ObjectShape; +typedef ObjectShape<2> ObjectShape2D; +typedef ObjectShape<3> ObjectShape3D; + /** @brief %Resource manager for physics debug draw @@ -64,14 +58,18 @@ Can create objects which draw object collision shape for debugging purposes. @section DebugDrawResourceManager-usage Basic usage The manager must be instanced for the whole lifetime of debug draw objects. -To create debug draw objects, call createDebugRenderer() and add the resulting -object to the scene. You can specify options via Options struct - add it to +To create debug renderers, call createDebugRenderer() and add the resulting +drawable to some group. You can specify options via Options struct - add it to the manager and then create debug renderer with the same options key. This way -you can easily share the same options with more objects. If no options for +you can easily share the same options with more renderers. If no options for given key exist, default is used. Example code: @code +// Group of drawables,preferrably dedicated for debug renderers, so you can +// easily enable or disable debug draw +DrawableGroup2D group; + // Instance the manager at first DebugDrawResourceManager manager; @@ -81,11 +79,10 @@ auto o = new DebugDrawResourceManager::Options { }; manager->set("red", o, ResourceDataState::Final, ResourcePolicy::Persistent); -// Add debug draw object for given shape, use "red" options for it, don't -// forget to add it to the scene -ShapedObject2D* object; -DebugDrawResourceManager::createDebugRenderer(object->shape(), "red") - ->setParent(object); +// Create debug renderer for given shape, use "red" options for it. Don't +// forget to add it to some drawable group. +ObjectShape2D* shape; +group.add(DebugDrawResourceManager::createDebugRenderer(shape, "red")); @endcode */ class PHYSICS_EXPORT DebugDrawResourceManager: public ResourceManager { @@ -106,17 +103,17 @@ class PHYSICS_EXPORT DebugDrawResourceManager: public ResourceManager static SceneGraph::Drawable* createDebugRenderer(ObjectShape* shape, ResourceKey options = ResourceKey()); DebugDrawResourceManager(); - ~DebugDrawResourceManager(); private: - static SceneGraph::Object2D* createDebugMesh(SceneGraph::Object2D* parent, AbstractShape2D* shape, ResourceKey options); + static void createDebugMesh(Implementation::DebugRenderer<2>* renderer, AbstractShape2D* shape); + static void createDebugMesh(Implementation::DebugRenderer<3>* renderer, AbstractShape3D* shape); }; }} diff --git a/src/Physics/Implementation/AbstractDebugRenderer.cpp b/src/Physics/Implementation/AbstractDebugRenderer.cpp index 63235f8bb..dbd41dcd7 100644 --- a/src/Physics/Implementation/AbstractDebugRenderer.cpp +++ b/src/Physics/Implementation/AbstractDebugRenderer.cpp @@ -22,7 +22,9 @@ namespace Magnum { namespace Physics { namespace Implementation { -template AbstractDebugRenderer::AbstractDebugRenderer(ResourceKey shader, ResourceKey mesh, ResourceKey options, typename SceneGraph::AbstractObject::ObjectType* parent): SceneGraph::AbstractObject::ObjectType(parent), shader(DebugDrawResourceManager::instance()->get>(shader)), mesh(DebugDrawResourceManager::instance()->get(mesh)), options(DebugDrawResourceManager::instance()->get(options)) {} +template AbstractDebugRenderer::AbstractDebugRenderer(ResourceKey shader, ResourceKey mesh): shader(DebugDrawResourceManager::instance()->get>(shader)), mesh(DebugDrawResourceManager::instance()->get(mesh)) {} + +template AbstractDebugRenderer::~AbstractDebugRenderer() {} template class AbstractDebugRenderer<2>; template class AbstractDebugRenderer<3>; diff --git a/src/Physics/Implementation/AbstractDebugRenderer.h b/src/Physics/Implementation/AbstractDebugRenderer.h index ed236b60d..0b3af89c2 100644 --- a/src/Physics/Implementation/AbstractDebugRenderer.h +++ b/src/Physics/Implementation/AbstractDebugRenderer.h @@ -15,9 +15,9 @@ GNU Lesser General Public License version 3 for more details. */ -#include "Color.h" +#include "DimensionTraits.h" #include "ResourceManager.h" -#include "SceneGraph/Camera.h" +#include "SceneGraph/SceneGraph.h" namespace Magnum { @@ -32,19 +32,19 @@ namespace Physics { namespace Implementation { struct Options; -template class AbstractDebugRenderer: public SceneGraph::AbstractObject::ObjectType { +template class AbstractDebugRenderer { public: - AbstractDebugRenderer(ResourceKey shader, ResourceKey mesh, ResourceKey options, typename SceneGraph::AbstractObject::ObjectType* parent); + AbstractDebugRenderer(ResourceKey shader, ResourceKey mesh); + + virtual ~AbstractDebugRenderer(); + + virtual void draw(Resource& options, const typename DimensionTraits::MatrixType& transformationMatrix, SceneGraph::AbstractCamera* camera) = 0; protected: Resource> shader; Resource mesh; - Resource options; }; -extern template class AbstractDebugRenderer<2>; -extern template class AbstractDebugRenderer<3>; - }}} #endif diff --git a/src/Physics/Implementation/BoxRenderer.cpp b/src/Physics/Implementation/BoxRenderer.cpp index 31b609e73..a6cc9d4ca 100644 --- a/src/Physics/Implementation/BoxRenderer.cpp +++ b/src/Physics/Implementation/BoxRenderer.cpp @@ -20,6 +20,7 @@ #include "Physics/DebugDrawResourceManager.h" #include "Primitives/Cube.h" #include "Primitives/Square.h" +#include "SceneGraph/AbstractCamera.h" #include "Shaders/FlatShader.h" namespace Magnum { namespace Physics { namespace Implementation { @@ -28,8 +29,8 @@ namespace { template struct BoxMesh {}; template<> struct BoxMesh<2> { - constexpr static ResourceKey shader() { return {"shader2d"}; } - constexpr static ResourceKey key() { return {"box2d"}; } + static ResourceKey shader() { return {"shader2d"}; } + static ResourceKey key() { return {"box2d"}; } static Mesh* mesh(Buffer* buffer) { Primitives::Square square; @@ -42,8 +43,8 @@ namespace { }; template<> struct BoxMesh<3> { - constexpr static ResourceKey shader() { return {"shader3d"}; } - constexpr static ResourceKey key() { return {"box3d"}; } + static ResourceKey shader() { return {"shader3d"}; } + static ResourceKey key() { return {"box3d"}; } static Mesh* mesh(Buffer* buffer) { Primitives::Cube cube; @@ -56,16 +57,16 @@ namespace { }; } -template BoxRenderer::BoxRenderer(Box& box, ResourceKey options, typename SceneGraph::AbstractObject::ObjectType* parent): AbstractDebugRenderer(BoxMesh::shader(), BoxMesh::key(), options, parent), buffer(DebugDrawResourceManager::instance()->get(BoxMesh::key())), box(box) { +template BoxRenderer::BoxRenderer(Box& box): AbstractDebugRenderer(BoxMesh::shader(), BoxMesh::key()), buffer(DebugDrawResourceManager::instance()->get(BoxMesh::key())), box(box) { if(!this->mesh) { DebugDrawResourceManager::instance()->set(this->buffer.key(), new Buffer, ResourceDataState::Final, ResourcePolicy::Manual); DebugDrawResourceManager::instance()->set(this->mesh.key(), BoxMesh::mesh(buffer), ResourceDataState::Final, ResourcePolicy::Manual); } } -template void BoxRenderer::draw(const typename DimensionTraits::MatrixType&, typename SceneGraph::AbstractObject::CameraType* camera) { - this->shader->setTransformationProjection(camera->projectionMatrix()*box.transformedTransformation()) - ->setColor(this->options->color) +template void BoxRenderer::draw(Resource& options, const typename DimensionTraits::MatrixType&, typename SceneGraph::AbstractCamera* camera) { + this->shader->setTransformationProjection(camera->projectionMatrix()*camera->cameraMatrix()*box.transformedTransformation()) + ->setColor(options->color) ->use(); this->mesh->draw(); } diff --git a/src/Physics/Implementation/BoxRenderer.h b/src/Physics/Implementation/BoxRenderer.h index a04683ee4..d563c7c63 100644 --- a/src/Physics/Implementation/BoxRenderer.h +++ b/src/Physics/Implementation/BoxRenderer.h @@ -17,6 +17,8 @@ #include "AbstractDebugRenderer.h" +#include "magnumCompatibility.h" + namespace Magnum { class Buffer; @@ -29,18 +31,15 @@ namespace Implementation { template class BoxRenderer: public AbstractDebugRenderer { public: - BoxRenderer(Box& box, ResourceKey options, typename SceneGraph::AbstractObject::ObjectType* parent); + BoxRenderer(Box& box); - void draw(const typename DimensionTraits::MatrixType& transformation, typename SceneGraph::AbstractObject::CameraType* camera); + void draw(Resource& options, const typename DimensionTraits::MatrixType& transformation, typename SceneGraph::AbstractCamera* camera) override; private: Resource buffer; Box& box; }; -extern template class BoxRenderer<2>; -extern template class BoxRenderer<3>; - }}} #endif diff --git a/src/Physics/Implementation/DebugRenderer.h b/src/Physics/Implementation/DebugRenderer.h new file mode 100644 index 000000000..fdb19e268 --- /dev/null +++ b/src/Physics/Implementation/DebugRenderer.h @@ -0,0 +1,58 @@ +#ifndef Magnum_Physics_Implementation_DebugRenderer_h +#define Magnum_Physics_Implementation_DebugRenderer_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "ResourceManager.h" +#include "SceneGraph/Drawable.h" +#include "AbstractDebugRenderer.h" + +namespace Magnum { + +class AbstractShaderProgram; +class Mesh; + +namespace Shaders { + template class FlatShader; +} + +namespace Physics { namespace Implementation { + +struct Options; + +template class DebugRenderer: public SceneGraph::Drawable { + public: + DebugRenderer(SceneGraph::AbstractObject* object, Resource&& options): SceneGraph::Drawable(object), options(options) {} + + inline ~DebugRenderer() { + for(auto i: renderers) delete i; + } + + inline void addRenderer(AbstractDebugRenderer* renderer) { + renderers.push_back(renderer); + } + + inline void draw(const typename DimensionTraits::MatrixType& transformationMatrix, SceneGraph::AbstractCamera* camera) override { + for(auto i: renderers) i->draw(options, transformationMatrix, camera); + } + + private: + Resource options; + std::vector*> renderers; +}; + +}}} + +#endif diff --git a/src/Physics/ObjectShape.cpp b/src/Physics/ObjectShape.cpp new file mode 100644 index 000000000..4ce8e4ce7 --- /dev/null +++ b/src/Physics/ObjectShape.cpp @@ -0,0 +1,46 @@ +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "ObjectShape.h" + +#include + +#include "AbstractShape.h" +#include "ObjectShapeGroup.h" + +using namespace std; + +namespace Magnum { namespace Physics { + +template ObjectShape::ObjectShape(SceneGraph::AbstractObject* object, ObjectShapeGroup* group): SceneGraph::AbstractGroupedFeature>(object, group), _shape(nullptr) { + this->setCachedTransformations(SceneGraph::AbstractFeature::CachedTransformation::Absolute); +} + +template ObjectShape::~ObjectShape() { + delete _shape; +} + +template void ObjectShape::markDirty() { + group()->setDirty(); +} + +template void ObjectShape::clean(const typename DimensionTraits::MatrixType& absoluteTransformation) { + if(_shape) _shape->applyTransformation(absoluteTransformation); +} + +template class ObjectShape<2>; +template class ObjectShape<3>; + +}} diff --git a/src/Physics/ObjectShape.h b/src/Physics/ObjectShape.h new file mode 100644 index 000000000..1a651a8ee --- /dev/null +++ b/src/Physics/ObjectShape.h @@ -0,0 +1,98 @@ +#ifndef Magnum_Physics_ObjectShape_h +#define Magnum_Physics_ObjectShape_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Physics::ObjectShape + */ + +#include "SceneGraph/AbstractGroupedFeature.h" +#include "ObjectShapeGroup.h" + +#include "magnumPhysicsVisibility.h" + +namespace Magnum { namespace Physics { + +template class ObjectShapeGroup; +template class AbstractShape; + +/** +@brief Object shape + +Adds shape for collision detection to object. +@see ObjectShape2D, ObjectShape3D +*/ +template class PHYSICS_EXPORT ObjectShape: public SceneGraph::AbstractGroupedFeature> { + public: + /** + * @brief Constructor + * @param object Object holding this feature + * @param group Group this shape belongs to + * + * Creates empty object shape. + * @see setShape() + */ + ObjectShape(SceneGraph::AbstractObject* object, ObjectShapeGroup* group = nullptr); + + /** + * @brief Destructor + * + * Deletes associated shape. + */ + ~ObjectShape(); + + /** @brief Shape */ + inline AbstractShape* shape() { return _shape; } + inline const AbstractShape* shape() const { return _shape; } /**< @overload */ + + /** + * @brief Set shape + * @return Pointer to self (for method chaining) + */ + inline ObjectShape* setShape(AbstractShape* shape) { + _shape = shape; + this->object()->setDirty(); + return this; + } + + inline ObjectShapeGroup* group() { + return static_cast*>(SceneGraph::AbstractGroupedFeature>::group()); + } + + inline const ObjectShapeGroup* group() const { + return static_cast*>(SceneGraph::AbstractGroupedFeature>::group()); + } + + protected: + /** Marks also the group as dirty */ + void markDirty() override; + + /** Applies transformation to associated shape. */ + void clean(const typename DimensionTraits::MatrixType& absoluteTransformation) override; + + private: + AbstractShape* _shape; +}; + +/** @brief Two-dimensional object shape */ +typedef ObjectShape<2> ObjectShape2D; + +/** @brief Three-dimensional object shape */ +typedef ObjectShape<3> ObjectShape3D; + +}} + +#endif diff --git a/src/Physics/ShapedObjectGroup.cpp b/src/Physics/ObjectShapeGroup.cpp similarity index 56% rename from src/Physics/ShapedObjectGroup.cpp rename to src/Physics/ObjectShapeGroup.cpp index 1dedcfe87..013bf4d78 100644 --- a/src/Physics/ShapedObjectGroup.cpp +++ b/src/Physics/ObjectShapeGroup.cpp @@ -13,20 +13,26 @@ GNU Lesser General Public License version 3 for more details. */ -#include "ShapedObjectGroup.h" +#include "ObjectShapeGroup.h" -#include "ShapedObject.h" +#include "ObjectShape.h" namespace Magnum { namespace Physics { -template void ShapedObjectGroup::setClean() { - for(auto it = objects.begin(); it != objects.end(); ++it) - if((*it)->isDirty()) (*it)->setClean(); +template void ObjectShapeGroup::setClean() { + /* Clean all objects */ + if(!this->isEmpty()) { + std::vector*> objects(this->size()); + for(std::size_t i = 0; i != this->size(); ++i) + objects[i] = (*this)[i]->object(); + + objects[0]->setClean(objects); + } dirty = false; } -template class ShapedObjectGroup<2>; -template class ShapedObjectGroup<3>; +template class ObjectShapeGroup<2>; +template class ObjectShapeGroup<3>; }} diff --git a/src/Physics/ShapedObjectGroup.h b/src/Physics/ObjectShapeGroup.h similarity index 63% rename from src/Physics/ShapedObjectGroup.h rename to src/Physics/ObjectShapeGroup.h index 5ebe7c37c..93eb61659 100644 --- a/src/Physics/ShapedObjectGroup.h +++ b/src/Physics/ObjectShapeGroup.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Physics_ShapedObjectGroup_h -#define Magnum_Physics_ShapedObjectGroup_h +#ifndef Magnum_Physics_ObjectShapeGroup_h +#define Magnum_Physics_ObjectShapeGroup_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -16,28 +16,28 @@ */ /** @file - * @brief Class Magnum::Physics::ShapedObjectGroup + * @brief Class Magnum::Physics::ObjectShapeGroup */ #include #include +#include "SceneGraph/FeatureGroup.h" + #include "magnumPhysicsVisibility.h" namespace Magnum { namespace Physics { -template class ShapedObject; +template class ObjectShape; /** -@brief Group of shaped objects +@brief Group of object shapes + -@ref ShapedObject "ShapedObject*D" instances are added to the group by -specifying it in the constructor. When the group is deleted, all objects -belogning to it are deleted too. -@see ShapedObjectGroup2D, ShapedObjectGroup3D +@see ObjectShapeGroup2D, ObjectShapeGroup3D */ -template class PHYSICS_EXPORT ShapedObjectGroup { - friend class ShapedObject; +template class PHYSICS_EXPORT ObjectShapeGroup: public SceneGraph::FeatureGroup> { + friend class ObjectShape; public: /** @@ -45,17 +45,7 @@ template class PHYSICS_EXPORT ShapedObjectGroup { * * Marks the group as dirty. */ - inline ShapedObjectGroup(): dirty(true) {} - - /** - * @brief Destructor - * - * Deletes all objects belogning to the group. - */ - inline virtual ~ShapedObjectGroup() { - for(auto it = objects.begin(); it != objects.end(); ++it) - delete *it; - } + inline ObjectShapeGroup(): dirty(true) {} /** * @brief Whether the group is dirty @@ -83,15 +73,14 @@ template class PHYSICS_EXPORT ShapedObjectGroup { void setClean(); private: - std::vector*> objects; bool dirty; }; /** @brief Group of two-dimensional shaped objects */ -typedef ShapedObjectGroup<2> ShapedObjectGroup2D; +typedef ObjectShapeGroup<2> ObjectShapeGroup2D; /** @brief Group of three-dimensional shaped objects */ -typedef ShapedObjectGroup<3> ShapedObjectGroup3D; +typedef ObjectShapeGroup<3> ObjectShapeGroup3D; }} diff --git a/src/Physics/ShapedObject.cpp b/src/Physics/ShapedObject.cpp deleted file mode 100644 index fb92ede11..000000000 --- a/src/Physics/ShapedObject.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - Copyright © 2010, 2011, 2012 Vladimír Vondruš - - This file is part of Magnum. - - Magnum is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License version 3 - only, as published by the Free Software Foundation. - - Magnum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License version 3 for more details. -*/ - -#include "ShapedObject.h" - -#include - -#include "AbstractShape.h" -#include "ShapedObjectGroup.h" - -using namespace std; - -namespace Magnum { namespace Physics { - -template ShapedObject::ShapedObject(ShapedObjectGroup* group, typename SceneGraph::AbstractObject::ObjectType* parent): SceneGraph::AbstractObject::ObjectType(parent), group(group), _shape(nullptr) { - group->objects.push_back(this); -} - -template ShapedObject::~ShapedObject() { - group->objects.erase(find(group->objects.begin(), group->objects.end(), this)); - delete _shape; -} - -template void ShapedObject::setDirty() { - SceneGraph::AbstractObject::ObjectType::setDirty(); - - group->setDirty(); -} - -template void ShapedObject::clean(const typename DimensionTraits::MatrixType& absoluteTransformation) { - SceneGraph::AbstractObject::ObjectType::clean(absoluteTransformation); - - if(_shape) _shape->applyTransformation(absoluteTransformation); -} - -template class ShapedObject<2>; -template class ShapedObject<3>; - -}} diff --git a/src/Physics/ShapedObject.h b/src/Physics/ShapedObject.h deleted file mode 100644 index b9763270f..000000000 --- a/src/Physics/ShapedObject.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef Magnum_Physics_ShapedObject_h -#define Magnum_Physics_ShapedObject_h -/* - Copyright © 2010, 2011, 2012 Vladimír Vondruš - - This file is part of Magnum. - - Magnum is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License version 3 - only, as published by the Free Software Foundation. - - Magnum is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License version 3 for more details. -*/ - -/** @file - * @brief Class Magnum::Physics::ShapedObject - */ - -#include "SceneGraph/Object.h" - -#include "magnumPhysicsVisibility.h" - -namespace Magnum { namespace Physics { - -template class ShapedObjectGroup; -template class AbstractShape; - -/** -@brief Object with assigned shape - -@see ShapedObject2D, ShapedObject3D -*/ -template class PHYSICS_EXPORT ShapedObject: public SceneGraph::AbstractObject::ObjectType { - public: - /** - * @brief Constructor - * @param group Group this shaped object belongs to - * @param parent Parent object - * - * Creates object with no shape. - * @see setShape() - */ - ShapedObject(ShapedObjectGroup* group, typename SceneGraph::AbstractObject::ObjectType* parent = nullptr); - - /** - * @brief Destructor - * - * Deletes associated shape. - */ - ~ShapedObject(); - - /** @brief Object shape */ - inline AbstractShape* shape() { return _shape; } - inline const AbstractShape* shape() const { return _shape; } /**< @overload */ - - /** - * @brief Set object shape - * @return Pointer to self (for method chaining) - */ - inline ShapedObject* setShape(AbstractShape* shape) { - _shape = shape; - setDirty(); - return this; - } - - /** - * @copybrief SceneGraph::AbstractObject::setDirty() - * - * Marks shaped object group as dirty. - */ - void setDirty(); - - protected: - /** - * @copybrief SceneGraph::AbstractObject::clean() - * - * Applies transformation to associated shape. - */ - void clean(const typename DimensionTraits::MatrixType& absoluteTransformation); - - private: - ShapedObjectGroup* group; - AbstractShape* _shape; -}; - -/** @brief Two-dimensional shaped object */ -typedef ShapedObject<2> ShapedObject2D; - -/** @brief Three-dimensional shaped object */ -typedef ShapedObject<3> ShapedObject3D; - -}} - -#endif diff --git a/src/Physics/Test/CMakeLists.txt b/src/Physics/Test/CMakeLists.txt index 5bb96fb4a..5c6c5f2a5 100644 --- a/src/Physics/Test/CMakeLists.txt +++ b/src/Physics/Test/CMakeLists.txt @@ -7,3 +7,5 @@ corrade_add_test2(PhysicsPlaneTest PlaneTest.cpp LIBRARIES MagnumPhysics) corrade_add_test2(PhysicsPointTest PointTest.cpp LIBRARIES MagnumPhysics) corrade_add_test2(PhysicsShapeGroupTest ShapeGroupTest.cpp LIBRARIES MagnumPhysics) corrade_add_test2(PhysicsSphereTest SphereTest.cpp LIBRARIES MagnumPhysics) + +corrade_add_test2(PhysicsObjectShapeTest ObjectShapeTest.cpp LIBRARIES MagnumPhysics) diff --git a/src/Physics/Test/ShapedObjectTest.cpp b/src/Physics/Test/ObjectShapeTest.cpp similarity index 58% rename from src/Physics/Test/ShapedObjectTest.cpp rename to src/Physics/Test/ObjectShapeTest.cpp index fec1e3c5a..dd5b438bd 100644 --- a/src/Physics/Test/ShapedObjectTest.cpp +++ b/src/Physics/Test/ObjectShapeTest.cpp @@ -13,23 +13,36 @@ GNU Lesser General Public License version 3 for more details. */ -#include "ShapedObjectTest.h" +#include "ObjectShapeTest.h" -#include "Physics/ShapedObjectGroup.h" -#include "Physics/ShapedObject.h" +#include "Physics/ObjectShapeGroup.h" +#include "Physics/ObjectShape.h" +#include "Physics/Point.h" +#include "SceneGraph/MatrixTransformation3D.h" +#include "SceneGraph/Scene.h" -CORRADE_TEST_MAIN(Magnum::Physics::Test::ShapedObjectTest) +CORRADE_TEST_MAIN(Magnum::Physics::Test::ObjectShapeTest) namespace Magnum { namespace Physics { namespace Test { -ShapedObjectTest::ShapedObjectTest() { - addTests(&ShapedObjectTest::clean); +typedef SceneGraph::Scene> Scene3D; +typedef SceneGraph::Object> Object3D; + +ObjectShapeTest::ObjectShapeTest() { + addTests(&ObjectShapeTest::clean); } -void ShapedObjectTest::clean() { - ShapedObjectGroup3D group; +void ObjectShapeTest::clean() { + Scene3D scene; + ObjectShapeGroup3D group; + + Object3D a(&scene); + ObjectShape3D* shape = new ObjectShape3D(&a, &group); + shape->setShape(new Physics::Point3D({1.0f, -2.0f, 3.0f})); + a.scale(Vector3(-2.0f)); - ShapedObject3D a(&group), b(&group); + Object3D b(&scene); + new ObjectShape3D(&b, &group); /* Everything is dirty at the beginning */ CORRADE_VERIFY(group.isDirty()); @@ -42,6 +55,10 @@ void ShapedObjectTest::clean() { CORRADE_VERIFY(!a.isDirty()); CORRADE_VERIFY(b.isDirty()); + /* Verify that the feature was actually cleaned */ + CORRADE_COMPARE(static_cast(shape->shape())->transformedPosition(), + Vector3(-2.0f, 4.0f, -6.0f)); + /* Setting group clean will clean whole group */ a.setDirty(); group.setClean(); diff --git a/src/Physics/Test/ShapedObjectTest.h b/src/Physics/Test/ObjectShapeTest.h similarity index 78% rename from src/Physics/Test/ShapedObjectTest.h rename to src/Physics/Test/ObjectShapeTest.h index 81f49e406..65d051da1 100644 --- a/src/Physics/Test/ShapedObjectTest.h +++ b/src/Physics/Test/ObjectShapeTest.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Physics_Test_ShapedObjectTest_h -#define Magnum_Physics_Test_ShapedObjectTest_h +#ifndef Magnum_Physics_Test_ObjectShapeTest_h +#define Magnum_Physics_Test_ObjectShapeTest_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -19,9 +19,9 @@ namespace Magnum { namespace Physics { namespace Test { -class ShapedObjectTest: public Corrade::TestSuite::Tester { +class ObjectShapeTest: public Corrade::TestSuite::Tester { public: - ShapedObjectTest(); + ObjectShapeTest(); void clean(); }; diff --git a/src/ResourceManager.h b/src/ResourceManager.h index edbbe4db0..0d0a3538d 100644 --- a/src/ResourceManager.h +++ b/src/ResourceManager.h @@ -142,12 +142,12 @@ namespace Implementation { } #endif - Data(Data&& other): data(other.data), state(other.state), policy(other.policy), referenceCount(other.referenceCount) { + inline Data(Data&& other): data(other.data), state(other.state), policy(other.policy), referenceCount(other.referenceCount) { other.data = nullptr; other.referenceCount = 0; } - ~Data() { + inline ~Data() { CORRADE_ASSERT(referenceCount == 0, "ResourceManager: cannot destruct it while data are still referenced", ); delete data; } @@ -398,6 +398,8 @@ template class Resource { Provides storage for arbitrary set of types, accessible globally using instance(). +@section ResourceManager-usage Usage + Each resource is referenced from Resource class. For optimizing performance, each resource can be set as mutable or final. Mutable resources can be modified by the manager and thus each %Resource instance asks the manager for @@ -453,6 +455,9 @@ cube->draw(); - Destroying resource references and deleting manager instance when nothing references the resources anymore. */ +/* Due to too much work involved with explicit template instantiation (all + Resource combinations, all ResourceManagerData...), this class doesn't have + template implementation file. */ template class ResourceManager: protected Implementation::ResourceManagerData... { public: /** @brief Global instance */ @@ -566,7 +571,7 @@ template class ResourceManager: protected Implementation::Resour }; /** @debugoperator{Magnum::ResourceKey} */ -template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const ResourceKey& value) { +template inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const ResourceKey& value) { return debug << static_cast&>(value); } diff --git a/src/SceneGraph/AbstractCamera.h b/src/SceneGraph/AbstractCamera.h index 48c7890d2..64707a78e 100644 --- a/src/SceneGraph/AbstractCamera.h +++ b/src/SceneGraph/AbstractCamera.h @@ -27,14 +27,6 @@ namespace Magnum { namespace SceneGraph { -template class Drawable; -template class FeatureGroup; -#ifndef MAGNUM_GCC46_COMPATIBILITY -template using DrawableGroup = FeatureGroup, T>; -#else -template class DrawableGroup; -#endif - /** @relates AbstractCamera @brief Camera aspect ratio policy @@ -72,7 +64,12 @@ file to avoid linker errors. See also relevant sections in @see Drawable, DrawableGroup, AbstractCamera2D, AbstractCamera3D */ -template class SCENEGRAPH_EXPORT AbstractCamera: public AbstractFeature { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class SCENEGRAPH_EXPORT AbstractCamera: public AbstractFeature { public: /** * @brief Constructor @@ -200,12 +197,6 @@ template using AbstractCamera3D = AbstractCamera<3, T>; typedef AbstractCamera<3, T = GLfloat> AbstractCamera3D; #endif -/* Make implementers' life easier */ -#ifndef MAGNUM_GCC46_COMPATIBILITY -template using DrawableGroup2D = DrawableGroup<2, T>; -template using DrawableGroup3D = DrawableGroup<3, T>; -#endif - }} #endif diff --git a/src/SceneGraph/AbstractFeature.h b/src/SceneGraph/AbstractFeature.h index 34e3feffd..f48b88034 100644 --- a/src/SceneGraph/AbstractFeature.h +++ b/src/SceneGraph/AbstractFeature.h @@ -45,6 +45,9 @@ namespace Implementation { Contained in Object, takes care of transformation caching. See @ref scenegraph for introduction. +Uses Corrade::Containers::LinkedList for accessing holder object and sibling +features. + @section AbstractFeature-subclassing Subclassing Feature is templated on dimension count and underlying transformation type, so @@ -114,10 +117,11 @@ which is automatically extracted from the pointer in our constructor. @see AbstractFeature2D, AbstractFeature3D */ +#ifndef DOXYGEN_GENERATING_OUTPUT +template class AbstractFeature: private Corrade::Containers::LinkedListItem, AbstractObject> +#else template class AbstractFeature - #ifndef DOXYGEN_GENERATING_OUTPUT - : private Corrade::Containers::LinkedListItem, AbstractObject> - #endif +#endif { friend class Corrade::Containers::LinkedList>; friend class Corrade::Containers::LinkedListItem, AbstractObject>; diff --git a/src/SceneGraph/AbstractGroupedFeature.h b/src/SceneGraph/AbstractGroupedFeature.h index 8e17a39d2..c88379183 100644 --- a/src/SceneGraph/AbstractGroupedFeature.h +++ b/src/SceneGraph/AbstractGroupedFeature.h @@ -47,7 +47,12 @@ typedef SceneGraph::FeatureGroup3D DrawableGroup; @see AbstractGroupedFeature2D, AbstractGroupedFeature3D, FeatureGroup, FeatureGroup2D, FeatureGroup3D */ -template class AbstractGroupedFeature: public AbstractFeature { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class AbstractGroupedFeature: public AbstractFeature { friend class FeatureGroup; public: @@ -123,12 +128,6 @@ template using AbstractGroupedFeature3D = Abst typedef AbstractGroupedFeature<3, Derived, T = GLfloat> AbstractGroupedFeature3D; #endif -/* Make implementers' life easier */ -#ifndef MAGNUM_GCC46_COMPATIBILITY -template using FeatureGroup2D = FeatureGroup<2, Feature, T>; -template using FeatureGroup3D = FeatureGroup<3, Feature, T>; -#endif - }} #endif diff --git a/src/SceneGraph/AbstractObject.h b/src/SceneGraph/AbstractObject.h index 63d962981..82b7514aa 100644 --- a/src/SceneGraph/AbstractObject.h +++ b/src/SceneGraph/AbstractObject.h @@ -22,14 +22,12 @@ #include #include "DimensionTraits.h" -#include "Magnum.h" +#include "SceneGraph.h" #include "magnumCompatibility.h" namespace Magnum { namespace SceneGraph { -template class AbstractFeature; - /** @brief Base for objects @@ -37,12 +35,15 @@ Provides minimal interface for features, not depending on object transformation implementation. This class is not directly instantiatable, use Object subclass instead. See also @ref scenegraph for more information. +Uses Corrade::Containers::LinkedList for storing features. + @see AbstractObject2D, AbstractObject3D */ +#ifndef DOXYGEN_GENERATING_OUTPUT +template class AbstractObject: private Corrade::Containers::LinkedList> +#else template class AbstractObject - #ifndef DOXYGEN_GENERATING_OUTPUT - : private Corrade::Containers::LinkedList> - #endif +#endif { friend class Corrade::Containers::LinkedList>; friend class Corrade::Containers::LinkedListItem, AbstractObject>; @@ -150,10 +151,24 @@ template class AbstractObject * on all object features which have caching enabled and recursively * calls setClean() on every parent which is not already clean. If the * object is already clean, the function does nothing. + * + * See also setClean(const std::vector& objects), which cleans given + * set of objects more efficiently than when calling setClean() on + * each object individually. * @see @ref scenegraph-caching, setDirty(), isDirty() */ virtual void setClean() = 0; + /** + * @brief Clean absolute transformations of given set of objects + * + * Only dirty objects in the list are cleaned. + * @warning This function cannot check if all objects are of the same + * Object type, use typesafe Object::setClean(const std::vector& objects) when + * possible. + */ + virtual void setClean(const std::vector*>& objects) const = 0; + /*@}*/ }; diff --git a/src/SceneGraph/AbstractTransformation.h b/src/SceneGraph/AbstractTransformation.h index a2c73d818..31dc26409 100644 --- a/src/SceneGraph/AbstractTransformation.h +++ b/src/SceneGraph/AbstractTransformation.h @@ -21,13 +21,11 @@ #include -#include "Magnum.h" #include "DimensionTraits.h" +#include "SceneGraph.h" namespace Magnum { namespace SceneGraph { -template class Object; - /** @brief Base for transformations @@ -43,7 +41,12 @@ When sublassing, you have to: @see AbstractTransformation2D, AbstractTransformation3D */ -template class AbstractTransformation { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class AbstractTransformation { public: /** @brief Underlying floating-point type */ typedef T Type; @@ -60,6 +63,13 @@ template class AbstractTransformatio * 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 * diff --git a/src/SceneGraph/AbstractTranslationRotation2D.h b/src/SceneGraph/AbstractTranslationRotation2D.h index 22d407b14..e06566397 100644 --- a/src/SceneGraph/AbstractTranslationRotation2D.h +++ b/src/SceneGraph/AbstractTranslationRotation2D.h @@ -28,7 +28,12 @@ namespace Magnum { namespace SceneGraph { @see AbstractTranslationRotation3D */ -template class AbstractTranslationRotation2D: public AbstractTransformation<2, T> { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class AbstractTranslationRotation2D: public AbstractTransformation<2, T> { public: /** * @brief Translate object diff --git a/src/SceneGraph/AbstractTranslationRotation3D.h b/src/SceneGraph/AbstractTranslationRotation3D.h index 4bc174a59..1175b8af2 100644 --- a/src/SceneGraph/AbstractTranslationRotation3D.h +++ b/src/SceneGraph/AbstractTranslationRotation3D.h @@ -29,7 +29,12 @@ namespace Magnum { namespace SceneGraph { @see AbstractTranslationRotation2D */ -template class AbstractTranslationRotation3D: public AbstractTransformation<3, T> { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class AbstractTranslationRotation3D: public AbstractTransformation<3, T> { public: /** * @brief Translate object diff --git a/src/SceneGraph/AbstractTranslationRotationScaling2D.h b/src/SceneGraph/AbstractTranslationRotationScaling2D.h index 6d5d3f66d..26da23b36 100644 --- a/src/SceneGraph/AbstractTranslationRotationScaling2D.h +++ b/src/SceneGraph/AbstractTranslationRotationScaling2D.h @@ -28,7 +28,12 @@ namespace Magnum { namespace SceneGraph { @see AbstractTranslationRotationScaling2D */ -template class AbstractTranslationRotationScaling2D: public AbstractTranslationRotation2D { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class AbstractTranslationRotationScaling2D: public AbstractTranslationRotation2D { public: /** * @brief Scale object diff --git a/src/SceneGraph/AbstractTranslationRotationScaling3D.h b/src/SceneGraph/AbstractTranslationRotationScaling3D.h index c4c880ae5..ab4ffd4f6 100644 --- a/src/SceneGraph/AbstractTranslationRotationScaling3D.h +++ b/src/SceneGraph/AbstractTranslationRotationScaling3D.h @@ -28,7 +28,12 @@ namespace Magnum { namespace SceneGraph { @see AbstractTranslationRotationScaling2D */ -template class AbstractTranslationRotationScaling3D: public AbstractTranslationRotation3D { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class AbstractTranslationRotationScaling3D: public AbstractTranslationRotation3D { public: /** * @brief Scale object diff --git a/src/SceneGraph/CMakeLists.txt b/src/SceneGraph/CMakeLists.txt index 753944943..1cd0780fd 100644 --- a/src/SceneGraph/CMakeLists.txt +++ b/src/SceneGraph/CMakeLists.txt @@ -22,6 +22,7 @@ set(MagnumSceneGraph_HEADERS Object.h Object.hpp Scene.h + SceneGraph.h magnumSceneGraphVisibility.h) add_library(MagnumSceneGraphObjects OBJECT ${MagnumSceneGraph_SRCS}) diff --git a/src/SceneGraph/Camera2D.h b/src/SceneGraph/Camera2D.h index 9f9845797..c38e9d052 100644 --- a/src/SceneGraph/Camera2D.h +++ b/src/SceneGraph/Camera2D.h @@ -38,7 +38,12 @@ avoid linker errors. See @ref compilation-speedup-hpp for more information. @see Camera3D, Drawable, DrawableGroup */ -template class SCENEGRAPH_EXPORT Camera2D: public AbstractCamera<2, T> { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class SCENEGRAPH_EXPORT Camera2D: public AbstractCamera<2, T> { public: /** * @brief Constructor diff --git a/src/SceneGraph/Camera3D.h b/src/SceneGraph/Camera3D.h index c34e8ecb2..4c6056fc5 100644 --- a/src/SceneGraph/Camera3D.h +++ b/src/SceneGraph/Camera3D.h @@ -43,7 +43,12 @@ avoid linker errors. See @ref compilation-speedup-hpp for more information. @see Camera2D, Drawable, DrawableGroup */ -template class SCENEGRAPH_EXPORT Camera3D: public AbstractCamera<3, T> { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class SCENEGRAPH_EXPORT Camera3D: public AbstractCamera<3, T> { public: /** * @brief Constructor diff --git a/src/SceneGraph/Drawable.h b/src/SceneGraph/Drawable.h index 5493fe819..983d48716 100644 --- a/src/SceneGraph/Drawable.h +++ b/src/SceneGraph/Drawable.h @@ -23,14 +23,6 @@ namespace Magnum { namespace SceneGraph { -template class AbstractCamera; -template class Drawable; -#ifndef MAGNUM_GCC46_COMPATIBILITY -template using DrawableGroup = FeatureGroup, T>; -#else -template class DrawableGroup; -#endif - /** @brief %Drawable @@ -85,7 +77,12 @@ void MyApplication::drawEvent() { @see Drawable2D, Drawable3D, DrawableGroup2D, DrawableGroup3D */ -template class Drawable: public AbstractGroupedFeature, T> { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class Drawable: public AbstractGroupedFeature, T> { public: /** @copydoc AbstractGroupedFeature::AbstractGroupedFeature() */ inline Drawable(AbstractObject* object, DrawableGroup* group = nullptr): AbstractGroupedFeature, T>(object, group) {} @@ -145,7 +142,12 @@ See Drawable for more information. #if !defined(MAGNUM_GCC46_COMPATIBILITY) && !defined(DOXYGEN_GENERATING_OUTPUT) template using DrawableGroup = FeatureGroup, T>; #else -template class DrawableGroup: public FeatureGroup, T> {}; +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class DrawableGroup: public FeatureGroup, T> {}; #endif /** @@ -182,12 +184,6 @@ template using DrawableGroup3D = DrawableGroup<3, T>; typedef DrawableGroup<3, T = GLfloat> DrawableGroup3D; #endif -/* Make implementers' life easier */ -#ifndef MAGNUM_GCC46_COMPATIBILITY -template using AbstractCamera2D = AbstractCamera<2, T>; -template using AbstractCamera3D = AbstractCamera<3, T>; -#endif - }} #endif diff --git a/src/SceneGraph/FeatureGroup.h b/src/SceneGraph/FeatureGroup.h index b3506821e..279be4dcf 100644 --- a/src/SceneGraph/FeatureGroup.h +++ b/src/SceneGraph/FeatureGroup.h @@ -19,24 +19,26 @@ * @brief Class Magnum::SceneGraph::FeatureGroup, alias Magnum::SceneGraph::FeatureGroup2D, Magnum::SceneGraph::FeatureGroup3D */ -#include #include #include #include -#include "Magnum.h" +#include "SceneGraph.h" namespace Magnum { namespace SceneGraph { -template class AbstractGroupedFeature; - /** @brief Group of features See AbstractGroupedFeature for more information. @see FeatureGroup2D, FeatureGroup3D */ -template class FeatureGroup { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class FeatureGroup { friend class AbstractGroupedFeature; public: diff --git a/src/SceneGraph/MatrixTransformation2D.h b/src/SceneGraph/MatrixTransformation2D.h index b25ea2e1f..e60dc18a6 100644 --- a/src/SceneGraph/MatrixTransformation2D.h +++ b/src/SceneGraph/MatrixTransformation2D.h @@ -30,7 +30,12 @@ namespace Magnum { namespace SceneGraph { @see MatrixTransformation3D */ -template class MatrixTransformation2D: public AbstractTranslationRotationScaling2D { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class MatrixTransformation2D: public AbstractTranslationRotationScaling2D { public: /** @brief Transformation matrix type */ typedef typename DimensionTraits<2, T>::MatrixType DataType; @@ -64,7 +69,7 @@ template class MatrixTransformation2D: public AbstractTransla MatrixTransformation2D* setTransformation(const Math::Matrix3& transformation) { /* Setting transformation is forbidden for the scene */ /** @todo Assert for this? */ - /** @todo Do this in some common code? */ + /** @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(); diff --git a/src/SceneGraph/MatrixTransformation3D.h b/src/SceneGraph/MatrixTransformation3D.h index dff09d723..763acbcc3 100644 --- a/src/SceneGraph/MatrixTransformation3D.h +++ b/src/SceneGraph/MatrixTransformation3D.h @@ -30,7 +30,12 @@ namespace Magnum { namespace SceneGraph { @see MatrixTransformation2D */ -template class MatrixTransformation3D: public AbstractTranslationRotationScaling3D { +#ifndef DOXYGEN_GENERATING_OUTPUT +template +#else +template +#endif +class MatrixTransformation3D: public AbstractTranslationRotationScaling3D { public: /** @brief Transformation matrix type */ typedef typename DimensionTraits<3, T>::MatrixType DataType; @@ -64,7 +69,7 @@ template class MatrixTransformation3D: public AbstractTransla MatrixTransformation3D* setTransformation(const Math::Matrix4& transformation) { /* Setting transformation is forbidden for the scene */ /** @todo Assert for this? */ - /** @todo Do this in some common code? */ + /** @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(); diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 94ac66e63..005ea1687 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -28,8 +28,6 @@ namespace Magnum { namespace SceneGraph { -template class Scene; - #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { enum class ObjectFlag: std::uint8_t { @@ -48,8 +46,10 @@ namespace Implementation { @brief %Object Base of scene graph. Contains specific transformation implementation, takes -care of parent/children relationships and contains features. See -@ref scenegraph for introduction. +care of parent/children relationship and contains features. See @ref scenegraph +for introduction. + +Uses Corrade::Containers::LinkedList for parent/children relationship. @section Object-explicit-specializations Explicit template specializations @@ -78,6 +78,15 @@ template class Object: public AbstractObject*> objects); + /** * @brief Constructor * @param parent Parent object @@ -213,6 +222,10 @@ template class Object: public AbstractObject*>& jointObjects, std::vector& jointTransformations, const std::size_t joint, const typename Transformation::DataType& initialTransformation) const; + void setClean(const std::vector*>& objects) const override; + + void setClean(const typename Transformation::DataType& absoluteTransformation); + typedef Implementation::ObjectFlag Flag; typedef Implementation::ObjectFlags Flags; std::uint16_t counter; diff --git a/src/SceneGraph/Object.hpp b/src/SceneGraph/Object.hpp index e8c62022b..e39253aeb 100644 --- a/src/SceneGraph/Object.hpp +++ b/src/SceneGraph/Object.hpp @@ -21,6 +21,7 @@ #include "Object.h" +#include #include #include "Scene.h" @@ -123,42 +124,9 @@ template void Object::setClean() { Object* o = objects.top(); objects.pop(); - /* Compose transformations */ + /* Compose transformation and clean object */ absoluteTransformation = Transformation::compose(absoluteTransformation, o->transformation()); - - /* "Lazy storage" for transformation matrix and inverted transformation matrix */ - typedef typename AbstractFeature::CachedTransformation CachedTransformation; - typename AbstractFeature::CachedTransformations cached; - typename DimensionTraits::MatrixType - matrix, invertedMatrix; - - /* Clean all features */ - for(AbstractFeature* i = o->firstFeature(); i; i = i->nextFeature()) { - /* Cached absolute transformation, compute it if it wasn't - computed already */ - if(i->cachedTransformations() & CachedTransformation::Absolute) { - if(!(cached & CachedTransformation::Absolute)) { - cached |= CachedTransformation::Absolute; - matrix = Transformation::toMatrix(absoluteTransformation); - } - - i->clean(matrix); - } - - /* Cached inverse absolute transformation, compute it if it wasn't - computed already */ - if(i->cachedTransformations() & CachedTransformation::InvertedAbsolute) { - if(!(cached & CachedTransformation::InvertedAbsolute)) { - cached |= CachedTransformation::InvertedAbsolute; - invertedMatrix = Transformation::toMatrix(Transformation::inverted(absoluteTransformation)); - } - - i->cleanInverted(invertedMatrix); - } - } - - /* Mark object as clean */ - o->flags &= ~Flag::Dirty; + o->setClean(absoluteTransformation); } } @@ -286,6 +254,69 @@ template typename Transformation::DataType Object void Object::setClean(const std::vector*>& objects) const { + std::vector*> castObjects(objects.size()); + for(std::size_t i = 0; i != objects.size(); ++i) + /** @todo Ensure this doesn't crash, somehow */ + castObjects[i] = static_cast*>(objects[i]); + + setClean(std::move(castObjects)); +} + +template void Object::setClean(std::vector*> objects) { + /* Remove all clean objects from the list */ + auto firstClean = std::remove_if(objects.begin(), objects.end(), [](Object* o) { return !o->isDirty(); }); + objects.erase(firstClean, objects.end()); + + /* No dirty objects left, done */ + if(objects.empty()) return; + + /* Compute absolute transformations */ + Scene* scene = objects[0]->scene(); + CORRADE_ASSERT(scene, "Object::setClean(): objects must be part of some scene", ); + std::vector transformations(scene->transformations(objects)); + + /* Go through all objects and clean them */ + for(std::size_t i = 0; i != objects.size(); ++i) + objects[i]->setClean(transformations[i]); +} + +template void Object::setClean(const typename Transformation::DataType& absoluteTransformation) { + /* "Lazy storage" for transformation matrix and inverted transformation matrix */ + typedef typename AbstractFeature::CachedTransformation CachedTransformation; + typename AbstractFeature::CachedTransformations cached; + typename DimensionTraits::MatrixType + matrix, invertedMatrix; + + /* Clean all features */ + for(AbstractFeature* i = this->firstFeature(); i; i = i->nextFeature()) { + /* Cached absolute transformation, compute it if it wasn't + computed already */ + if(i->cachedTransformations() & CachedTransformation::Absolute) { + if(!(cached & CachedTransformation::Absolute)) { + cached |= CachedTransformation::Absolute; + matrix = Transformation::toMatrix(absoluteTransformation); + } + + i->clean(matrix); + } + + /* Cached inverse absolute transformation, compute it if it wasn't + computed already */ + if(i->cachedTransformations() & CachedTransformation::InvertedAbsolute) { + if(!(cached & CachedTransformation::InvertedAbsolute)) { + cached |= CachedTransformation::InvertedAbsolute; + invertedMatrix = Transformation::toMatrix(Transformation::inverted(absoluteTransformation)); + } + + i->cleanInverted(invertedMatrix); + } + } + + /* Mark object as clean */ + flags &= ~Flag::Dirty; +} + }} #endif diff --git a/src/SceneGraph/SceneGraph.h b/src/SceneGraph/SceneGraph.h new file mode 100644 index 000000000..1f0845df0 --- /dev/null +++ b/src/SceneGraph/SceneGraph.h @@ -0,0 +1,94 @@ +#ifndef Magnum_SceneGraph_SceneGraph_h +#define Magnum_SceneGraph_SceneGraph_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Forward declarations for Magnum::SceneGraph namespace + */ + +#include + +#include "Magnum.h" + +namespace Magnum { namespace SceneGraph { + +template class AbstractCamera; +#ifndef MAGNUM_GCC46_COMPATIBILITY +template using AbstractCamera2D = AbstractCamera<2, T>; +template using AbstractCamera3D = AbstractCamera<3, T>; +#endif + +template class AbstractFeature; +#ifndef MAGNUM_GCC46_COMPATIBILITY +template using AbstractFeature2D = AbstractFeature<2, T>; +template using AbstractFeature3D = AbstractFeature<3, T>; +#endif + +template class AbstractGroupedFeature; +#ifndef MAGNUM_GCC46_COMPATIBILITY +template using AbstractGroupedFeature2D = AbstractGroupedFeature<2, Derived, T>; +template using AbstractGroupedFeature3D = AbstractGroupedFeature<3, Derived, T>; +#endif + +template class AbstractObject; +#ifndef MAGNUM_GCC46_COMPATIBILITY +template using AbstractObject2D = AbstractObject<2, T>; +template using AbstractObject3D = AbstractObject<3, T>; +#endif + +template class AbstractTransformation; +#ifndef MAGNUM_GCC46_COMPATIBILITY +template using AbstractTransformation2D = AbstractTransformation<2, T>; +template using AbstractTransformation3D = AbstractTransformation<3, T>; +#endif + +template class AbstractTranslationRotation2D; +template class AbstractTranslationRotation3D; +template class AbstractTranslationRotationScaling2D; +template class AbstractTranslationRotationScaling3D; + +template class Camera2D; +template class Camera3D; + +template class Drawable; +#ifndef MAGNUM_GCC46_COMPATIBILITY +template using Drawable2D = Drawable<2, T>; +template using Drawable3D = Drawable<3, T>; +#endif + +template class FeatureGroup; +#ifndef MAGNUM_GCC46_COMPATIBILITY +template using FeatureGroup2D = FeatureGroup<2, Feature, T>; +template using FeatureGroup3D = FeatureGroup<3, Feature, T>; +#endif + +#ifndef MAGNUM_GCC46_COMPATIBILITY +template using DrawableGroup = FeatureGroup, T>; +template using DrawableGroup2D = DrawableGroup<2, T>; +template using DrawableGroup3D = DrawableGroup<3, T>; +#else +template class DrawableGroup; +#endif + +template class MatrixTransformation2D; +template class MatrixTransformation3D; + +template class Object; +template class Scene; + +}} + +#endif diff --git a/src/SceneGraph/Test/ObjectTest.cpp b/src/SceneGraph/Test/ObjectTest.cpp index bba87ffe8..376f859b3 100644 --- a/src/SceneGraph/Test/ObjectTest.cpp +++ b/src/SceneGraph/Test/ObjectTest.cpp @@ -30,12 +30,27 @@ namespace Magnum { namespace SceneGraph { namespace Test { typedef SceneGraph::Object> Object3D; typedef SceneGraph::Scene> Scene3D; +class CachingObject: public Object3D, AbstractFeature<3, GLfloat> { + public: + inline CachingObject(Object3D* parent = nullptr): Object3D(parent), AbstractFeature<3, GLfloat>(this) { + setCachedTransformations(CachedTransformation::Absolute); + } + + Matrix4 cleanedAbsoluteTransformation; + + protected: + void clean(const Matrix4& absoluteTransformation) override { + cleanedAbsoluteTransformation = absoluteTransformation; + } +}; + ObjectTest::ObjectTest() { addTests(&ObjectTest::parenting, &ObjectTest::scene, &ObjectTest::absoluteTransformation, &ObjectTest::transformations, - &ObjectTest::caching); + &ObjectTest::setClean, + &ObjectTest::bulkSetClean); } void ObjectTest::parenting() { @@ -105,6 +120,9 @@ void ObjectTest::transformations() { Matrix4 initial = Matrix4::rotationX(deg(90.0f)).inverted(); + /* Empty list */ + CORRADE_COMPARE(s.transformations(vector(), initial), vector()); + /* Scene alone */ CORRADE_COMPARE(s.transformations({&s}, initial), vector{initial}); @@ -168,7 +186,7 @@ void ObjectTest::transformations() { CORRADE_COMPARE(o.str(), "SceneGraph::Object::transformations(): the objects are not part of the same tree\n"); } -void ObjectTest::caching() { +void ObjectTest::setClean() { Scene3D scene; class CachingFeature: public AbstractFeature<3, GLfloat> { @@ -197,20 +215,6 @@ void ObjectTest::caching() { } }; - class CachingObject: public Object3D, AbstractFeature<3, GLfloat> { - public: - inline CachingObject(Object3D* parent = nullptr): Object3D(parent), AbstractFeature<3, GLfloat>(this) { - setCachedTransformations(CachedTransformation::Absolute); - } - - Matrix4 cleanedAbsoluteTransformation; - - protected: - void clean(const Matrix4& absoluteTransformation) override { - cleanedAbsoluteTransformation = absoluteTransformation; - } - }; - CachingObject* childOne = new CachingObject(&scene); childOne->scale(Vector3(2.0f)); @@ -277,4 +281,36 @@ void ObjectTest::caching() { CORRADE_VERIFY(childThree->isDirty()); } +void ObjectTest::bulkSetClean() { + /* Verify it doesn't crash when passed empty list */ + Object3D::setClean(vector()); + + Scene3D scene; + Object3D a(&scene); + Object3D b(&scene); + b.setClean(); + Object3D c(&scene); + c.translate(Vector3::zAxis(3.0f)); + CachingObject d(&c); + d.scale(Vector3(-2.0f)); + Object3D e(&scene); + vector cleanAll{&a, &b, &c, &d, &e}; + + /* All objects should be cleaned */ + CORRADE_VERIFY(a.isDirty()); + CORRADE_VERIFY(!b.isDirty()); + CORRADE_VERIFY(c.isDirty()); + CORRADE_VERIFY(d.isDirty()); + CORRADE_VERIFY(e.isDirty()); + Object3D::setClean(cleanAll); + CORRADE_VERIFY(!a.isDirty()); + CORRADE_VERIFY(!b.isDirty()); + CORRADE_VERIFY(!c.isDirty()); + CORRADE_VERIFY(!d.isDirty()); + CORRADE_VERIFY(!e.isDirty()); + + /* Verify that right transformation was passed */ + CORRADE_COMPARE(d.cleanedAbsoluteTransformation, Matrix4::translation(Vector3::zAxis(3.0f))*Matrix4::scaling(Vector3(-2.0f))); +} + }}} diff --git a/src/SceneGraph/Test/ObjectTest.h b/src/SceneGraph/Test/ObjectTest.h index f0e44b5c7..7a04a1bd5 100644 --- a/src/SceneGraph/Test/ObjectTest.h +++ b/src/SceneGraph/Test/ObjectTest.h @@ -27,7 +27,8 @@ class ObjectTest: public Corrade::TestSuite::Tester { void scene(); void absoluteTransformation(); void transformations(); - void caching(); + void setClean(); + void bulkSetClean(); }; }}} diff --git a/src/Shaders/FlatShader2D.frag b/src/Shaders/FlatShader2D.frag index 44051058d..82c2d5a95 100644 --- a/src/Shaders/FlatShader2D.frag +++ b/src/Shaders/FlatShader2D.frag @@ -4,7 +4,7 @@ uniform lowp vec3 color; -#ifndef NEW_GLSL +#ifdef NEW_GLSL out lowp vec4 fragmentColor; #endif diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index 87e9f71e2..2a2c2ebc8 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -1,5 +1,5 @@ -corrade_add_test2(ColorTest ColorTest.cpp) +corrade_add_test2(ColorTest ColorTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test2(ResourceManagerTest ResourceManagerTest.cpp) -corrade_add_test2(SwizzleTest SwizzleTest.cpp) +corrade_add_test2(SwizzleTest SwizzleTest.cpp LIBRARIES MagnumMathTestLib) set_target_properties(ResourceManagerTest PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)