From 51f2478b1ef3f635387d0185eb6c7fa15e485fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 Aug 2012 13:19:27 +0200 Subject: [PATCH 01/78] More precise double Math constants. Double has 15-17 significant decimal digits precision, extended the constant to have 15 decimal digits. On the other hand, float has only 6-9 digits, so there is no need to have more than 9. Added just-to-be-sure test for sqrt* constants. --- src/Math/Math.h | 12 ++++++------ src/Math/Test/MathTest.cpp | 11 ++++++++++- src/Math/Test/MathTest.h | 1 + 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/Math/Math.h b/src/Math/Math.h index cfd22d08a..4f6d641a2 100644 --- a/src/Math/Math.h +++ b/src/Math/Math.h @@ -50,14 +50,14 @@ template struct Constants { #ifndef DOXYGEN_GENERATING_OUTPUT template<> struct Constants { - static inline constexpr double pi() { return 3.14159265359; } - static inline constexpr double sqrt2() { return 1.41421356237; } - static inline constexpr double sqrt3() { return 1.73205080757; } + static inline constexpr double pi() { return 3.141592653589793; } + static inline constexpr double sqrt2() { return 1.414213562373095; } + static inline constexpr double sqrt3() { return 1.732050807568877; } }; template<> struct Constants { - static inline constexpr float pi() { return 3.14159265359f; } - static inline constexpr float sqrt2() { return 1.41421356237f; } - static inline constexpr float sqrt3() { return 1.73205080757f; } + static inline constexpr float pi() { return 3.141592654f; } + static inline constexpr float sqrt2() { return 1.414213562f; } + static inline constexpr float sqrt3() { return 1.732050808f; } }; namespace Implementation { diff --git a/src/Math/Test/MathTest.cpp b/src/Math/Test/MathTest.cpp index db4d29676..9d76e9535 100644 --- a/src/Math/Test/MathTest.cpp +++ b/src/Math/Test/MathTest.cpp @@ -24,13 +24,22 @@ CORRADE_TEST_MAIN(Magnum::Math::Test::MathTest) namespace Magnum { namespace Math { namespace Test { MathTest::MathTest() { - addTests(&MathTest::degrad, + addTests(&MathTest::constants, + &MathTest::degrad, &MathTest::normalize, &MathTest::denormalize, &MathTest::pow, &MathTest::log); } +void MathTest::constants() { + CORRADE_COMPARE(Math::pow<2>(Constants::sqrt2()), 2.0f); + CORRADE_COMPARE(Math::pow<2>(Constants::sqrt3()), 3.0f); + + CORRADE_COMPARE(Math::pow<2>(Constants::sqrt2()), 2.0); + CORRADE_COMPARE(Math::pow<2>(Constants::sqrt3()), 3.0); +} + void MathTest::degrad() { CORRADE_COMPARE(deg(90.0), Constants::pi()/2); CORRADE_COMPARE(deg(90.0f), Constants::pi()/2); diff --git a/src/Math/Test/MathTest.h b/src/Math/Test/MathTest.h index b6dcba0c8..3bb32c5ea 100644 --- a/src/Math/Test/MathTest.h +++ b/src/Math/Test/MathTest.h @@ -23,6 +23,7 @@ class MathTest: public Corrade::TestSuite::Tester { public: MathTest(); + void constants(); void degrad(); void normalize(); void denormalize(); From d9dff2c04687644ac91ba133a8a46f82be73bc9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 Aug 2012 14:31:41 +0200 Subject: [PATCH 02/78] Clarified required version and extension for R/RG textures. --- src/AbstractTexture.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index cae04f499..680fc144c 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -122,12 +122,14 @@ class MAGNUM_EXPORT AbstractTexture { /** * Red component only. Green and blue are set to `0`, alpha is set * to `1`. + * @requires_gl30 Extension @extension{ARB,texture_rg} */ Red, /** * Red and green component. Blue is set to `0`, alpha is set to * `1`. + * @requires_gl30 Extension @extension{ARB,texture_rg} */ RedGreen, @@ -241,7 +243,7 @@ class MAGNUM_EXPORT AbstractTexture { * One-component (red channel), unsigned normalized, probably * 8bit. * @requires_gl - * @requires_gl30 (no extension providing this functionality) + * @requires_gl30 Extension @extension{ARB,texture_rg} */ Red = GL_RED, @@ -249,7 +251,7 @@ class MAGNUM_EXPORT AbstractTexture { * Two-component (red and green channel), unsigned normalized, * each component probably 8bit, 16bit total. * @requires_gl - * @requires_gl30 (no extension providing this functionality) + * @requires_gl30 Extension @extension{ARB,texture_rg} */ RedGreen = GL_RG, #endif @@ -365,12 +367,14 @@ class MAGNUM_EXPORT AbstractTexture { /** * Compressed red channel, unsigned normalized. * @requires_gl + * @requires_gl30 Extension @extension{ARB,texture_rg} */ CompressedRed = GL_COMPRESSED_RED, /** * Compressed red and green channel, unsigned normalized. * @requires_gl + * @requires_gl30 Extension @extension{ARB,texture_rg} */ CompressedRedGreen = GL_COMPRESSED_RG, From cbdff680529bb32d796b1ebef3491a1b81f5f83c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 Aug 2012 14:45:33 +0200 Subject: [PATCH 03/78] Clarified signed normalized texture types, formatting fixes. Signed normalization results in [-1.0, 1.0], NOT [0.0, 1.0]. --- src/AbstractTexture.h | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index 680fc144c..2e1856e6f 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -147,85 +147,75 @@ class MAGNUM_EXPORT AbstractTexture { enum class ComponentType { /** * (Non-normalized) unsigned byte - * * @requires_gl30 Extension @extension{EXT,texture_integer} */ UnsignedByte, /** * (Non-normalized) byte - * * @requires_gl30 Extension @extension{EXT,texture_integer} */ Byte, /** * (Non-normalized) unsigned short - * * @requires_gl30 Extension @extension{EXT,texture_integer} */ UnsignedShort, /** * (Non-normalized) short - * * @requires_gl30 Extension @extension{EXT,texture_integer} */ Short, /** * (Non-normalized) unsigned integer - * * @requires_gl30 Extension @extension{EXT,texture_integer} */ UnsignedInt, /** * (Non-normalized) integer - * * @requires_gl30 Extension @extension{EXT,texture_integer} */ Int, /** * Half float (16 bit) - * * @requires_gl30 Extension @extension{ARB,texture_float} */ Half, /** * Float (32 bit) - * * @requires_gl30 Extension @extension{ARB,texture_float} */ Float, /** - * Normalized unsigned byte, i.e. values from range - * @f$ [0; 255] @f$ are converted to range @f$ [0.0; 1.0] @f$. + * Normalized unsigned byte, i.e. values from range @f$ [0; 255] @f$ + * are converted to range @f$ [0.0; 1.0] @f$. */ NormalizedUnsignedByte, /** - * Normalized byte, i.e. values from range - * @f$ [-128; 127] @f$ are converted to range @f$ [0.0; 1.0] @f$. - * - * @requires_gl31 (no extension providing this functionality) + * Normalized signed byte, i.e. values from range @f$ [-128; 127] @f$ + * are converted to range @f$ [-1.0; 1.0] @f$. + * @requires_gl31 Extension @extension{EXT,texture_snorm} */ NormalizedByte, /** - * Normalized unsigned short, i.e. values from range - * @f$ [0; 65536] @f$ are converted to range @f$ [0.0; 1.0] @f$. + * Normalized unsigned short, i.e. values from range @f$ [0; 65536] @f$ + * are converted to range @f$ [0.0; 1.0] @f$. */ NormalizedUnsignedShort, /** - * Normalized short, i.e. values from range - * @f$ [-32768; 32767] @f$ are converted to range @f$ [0.0; 1.0] @f$. - * - * @requires_gl31 (no extension providing this functionality) + * Normalized signed short, i.e. values from range @f$ [-32768; 32767] @f$ + * are converted to range @f$ [-1.0; 1.0] @f$. + * @requires_gl31 Extension @extension{EXT,texture_snorm} */ NormalizedShort }; From eeca90c17cffce75fe4e2453ded866ade6578761 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 Aug 2012 14:47:30 +0200 Subject: [PATCH 04/78] Added @todos. --- src/AbstractImage.h | 1 + src/Color.h | 2 ++ src/Math/Math.h | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/src/AbstractImage.h b/src/AbstractImage.h index 3dea087db..815371bfe 100644 --- a/src/AbstractImage.h +++ b/src/AbstractImage.h @@ -44,6 +44,7 @@ class MAGNUM_EXPORT AbstractImage { */ /** @brief Color components */ + /** @todo Support *_INTEGER types */ enum class Components: GLenum { #ifndef MAGNUM_TARGET_GLES /** diff --git a/src/Color.h b/src/Color.h index 7dd384a1f..abfafa345 100644 --- a/src/Color.h +++ b/src/Color.h @@ -140,6 +140,8 @@ is always in range in range @f$ [0.0, 360.0] @f$, saturation and value in range @f$ [0.0, 1.0] @f$. @see Color4 + +@todo Signed normalization to [-1.0, 1.0] like in OpenGL? */ template class Color3: public Math::Vector3 { public: diff --git a/src/Math/Math.h b/src/Math/Math.h index 4f6d641a2..21191b360 100644 --- a/src/Math/Math.h +++ b/src/Math/Math.h @@ -104,6 +104,8 @@ float a = normalize('\127'); // b = 1.0f float b = normalize('\127'); @endcode + +@todo Signed normalization to [-1.0, 1.0] like in OpenGL? */ template inline constexpr typename std::enable_if::value && std::is_integral::value, FloatingPoint>::type normalize(Integral value) { return (FloatingPoint(value)-FloatingPoint(std::numeric_limits::min()))/ @@ -118,6 +120,8 @@ integral type. @note For best precision, `FloatingPoint` type should be always larger that resulting `Integral` type (e.g. `double` to `int`, `long double` to `long long`). + +@todo Signed normalization to [-1.0, 1.0] like in OpenGL? */ template inline constexpr typename std::enable_if::value && std::is_integral::value, Integral>::type denormalize(FloatingPoint value) { return std::numeric_limits::min() + From 0177ec8b5dfc9f0cc54f2b5e1887ea28108a767f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 Aug 2012 15:17:13 +0200 Subject: [PATCH 05/78] Moved swizzle() functions to root namespace. They aren't much useful in Math namespace and here it allows to handle also Color3/Color4 types. Moreover all RGBA component names were removed from Math namespace, so it would be inconsistent to have them there only in swizzle() functions. --- src/CMakeLists.txt | 1 + src/Math/CMakeLists.txt | 1 - src/Math/Test/CMakeLists.txt | 2 -- src/{Math => }/Swizzle.h | 34 +++++++++++++++++------------ src/Test/CMakeLists.txt | 1 + src/{Math => }/Test/SwizzleTest.cpp | 17 ++++++++++++--- src/{Math => }/Test/SwizzleTest.h | 8 +++---- 7 files changed, 40 insertions(+), 24 deletions(-) rename src/{Math => }/Swizzle.h (74%) rename src/{Math => }/Test/SwizzleTest.cpp (74%) rename src/{Math => }/Test/SwizzleTest.h (86%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd2fe4927..a3639825c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -56,6 +56,7 @@ set(Magnum_HEADERS Scene.h Shader.h SizeTraits.h + Swizzle.h Texture.h TypeTraits.h diff --git a/src/Math/CMakeLists.txt b/src/Math/CMakeLists.txt index d12a6a16c..a0cc17b69 100644 --- a/src/Math/CMakeLists.txt +++ b/src/Math/CMakeLists.txt @@ -6,7 +6,6 @@ set(MagnumMath_HEADERS Matrix.h Matrix3.h Matrix4.h - Swizzle.h Vector.h Vector2.h Vector3.h diff --git a/src/Math/Test/CMakeLists.txt b/src/Math/Test/CMakeLists.txt index f71db4d9a..b77ac8e4c 100644 --- a/src/Math/Test/CMakeLists.txt +++ b/src/Math/Test/CMakeLists.txt @@ -6,8 +6,6 @@ corrade_add_test2(MathVector2Test Vector2Test.cpp) corrade_add_test2(MathVector3Test Vector3Test.cpp) corrade_add_test2(MathVector4Test Vector4Test.cpp) -corrade_add_test2(MathSwizzleTest SwizzleTest.cpp) - corrade_add_test2(MathMatrixTest MatrixTest.cpp) corrade_add_test2(MathMatrix3Test Matrix3Test.cpp) corrade_add_test2(MathMatrix4Test Matrix4Test.cpp) diff --git a/src/Math/Swizzle.h b/src/Swizzle.h similarity index 74% rename from src/Math/Swizzle.h rename to src/Swizzle.h index e964948a6..84af4858b 100644 --- a/src/Math/Swizzle.h +++ b/src/Swizzle.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Math_Swizzle_h -#define Magnum_Math_Swizzle_h +#ifndef Magnum_Swizzle_h +#define Magnum_Swizzle_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -19,12 +19,15 @@ * @brief Function Magnum::Math::swizzle() */ -#include "Vector4.h" +#include "Color.h" -namespace Magnum { namespace Math { +namespace Magnum { #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { + using Math::Implementation::Sequence; + using Math::Implementation::GenerateSequence; + template struct GetPosition { static_assert(size > position, "Swizzle parameter out of range of base vector"); @@ -42,12 +45,15 @@ namespace Implementation { template struct GetComponent: public GetPosition {}; template struct TypeForSize { - typedef Vector Type; + typedef Math::Vector Type; }; - - template struct TypeForSize<2, T> { typedef Vector2 Type; }; - template struct TypeForSize<3, T> { typedef Vector3 Type; }; - template struct TypeForSize<4, T> { typedef Vector4 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, Color3> { typedef Color3 Type; }; + template struct TypeForSize<3, Color4> { typedef Color3 Type; }; + template struct TypeForSize<4, Color3> { typedef Color4 Type; }; + template struct TypeForSize<4, Color4> { typedef Color4 Type; }; inline constexpr size_t getPosition(size_t size, size_t position) { return size > position ? position : throw; @@ -65,7 +71,7 @@ namespace Implementation { throw; } - template inline constexpr Vector swizzleFrom(Sequence, const Vector& vector, const char(&components)[sizeof...(sequence)+1]) { + template inline constexpr Math::Vector swizzleFrom(Sequence, const Math::Vector& vector, const char(&components)[sizeof...(sequence)+1]) { return {vector[getComponent(components[sequence])]...}; } } @@ -93,8 +99,8 @@ instead of at runtime. @see Vector4::xyz(), Vector4::rgb(), Vector4::xy(), Vector3::xy() */ -template inline constexpr typename Implementation::TypeForSize::Type swizzle(const Vector& vector) { - return {vector[Implementation::GetComponent::value()]...}; +template inline constexpr typename Implementation::TypeForSize::Type swizzle(const T& vector) { + return {vector[Implementation::GetComponent::value()]...}; } /** @@ -119,10 +125,10 @@ evaluated at compile time, but at runtime. @see Vector4::xyz(), Vector4::rgb(), Vector4::xy(), Vector3::xy() */ -template inline constexpr typename Implementation::TypeForSize::Type swizzle(const Vector& vector, const char(&components)[newSize]) { +template inline constexpr typename Implementation::TypeForSize::Type swizzle(const T& vector, const char(&components)[newSize]) { return Implementation::swizzleFrom(typename Implementation::GenerateSequence::Type(), vector, components); } -}} +} #endif diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index 6c20f9a69..67650069a 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -3,3 +3,4 @@ corrade_add_test2(CameraTest CameraTest.cpp LIBRARIES Magnum) corrade_add_test2(SceneTest SceneTest.cpp LIBRARIES Magnum) corrade_add_test2(ColorTest ColorTest.cpp) +corrade_add_test2(SwizzleTest SwizzleTest.cpp) diff --git a/src/Math/Test/SwizzleTest.cpp b/src/Test/SwizzleTest.cpp similarity index 74% rename from src/Math/Test/SwizzleTest.cpp rename to src/Test/SwizzleTest.cpp index 52f590ae8..299603280 100644 --- a/src/Math/Test/SwizzleTest.cpp +++ b/src/Test/SwizzleTest.cpp @@ -19,9 +19,9 @@ using namespace std; -CORRADE_TEST_MAIN(Magnum::Math::Test::SwizzleTest) +CORRADE_TEST_MAIN(Magnum::Test::SwizzleTest) -namespace Magnum { namespace Math { namespace Test { +namespace Magnum { namespace Test { typedef Math::Vector2 Vector2; typedef Math::Vector3 Vector3; @@ -66,6 +66,17 @@ void SwizzleTest::type() { CORRADE_VERIFY((is_same::value)); CORRADE_VERIFY((is_same(orig)), Vector4>::value)); CORRADE_VERIFY((is_same::value)); + + Color3 origColor3; + Color4 origColor4; + CORRADE_VERIFY((is_same(origColor3)), Color3>::value)); + CORRADE_VERIFY((is_same(origColor4)), Color3>::value)); + CORRADE_VERIFY((is_same>::value)); + CORRADE_VERIFY((is_same>::value)); + CORRADE_VERIFY((is_same(origColor3)), Color4>::value)); + CORRADE_VERIFY((is_same(origColor4)), Color4>::value)); + CORRADE_VERIFY((is_same>::value)); + CORRADE_VERIFY((is_same>::value)); } void SwizzleTest::defaultType() { @@ -76,4 +87,4 @@ void SwizzleTest::defaultType() { CORRADE_COMPARE(swizzle(orig, "bragzyx"), Vector<7>(3, 1, 4, 2, 3, 2, 1)); } -}}} +}} diff --git a/src/Math/Test/SwizzleTest.h b/src/Test/SwizzleTest.h similarity index 86% rename from src/Math/Test/SwizzleTest.h rename to src/Test/SwizzleTest.h index a08dfdd17..b43180be0 100644 --- a/src/Math/Test/SwizzleTest.h +++ b/src/Test/SwizzleTest.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Math_Test_SwizzleTest_h -#define Magnum_Math_Test_SwizzleTest_h +#ifndef Magnum_Test_SwizzleTest_h +#define Magnum_Test_SwizzleTest_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -17,7 +17,7 @@ #include -namespace Magnum { namespace Math { namespace Test { +namespace Magnum { namespace Test { class SwizzleTest: public Corrade::TestSuite::Tester { public: @@ -30,6 +30,6 @@ class SwizzleTest: public Corrade::TestSuite::Tester { void defaultType(); }; -}}} +}} #endif From 80cd503bbd3109ed78fe46dec5b6857ff148d543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 Aug 2012 19:44:49 +0200 Subject: [PATCH 06/78] Reorganized Framebuffer class and grouped its members. Also marked everything related to blitting as unsupported in OpenGL ES 2.0. --- src/Framebuffer.h | 438 ++++++++++++++++++++++++---------------------- 1 file changed, 229 insertions(+), 209 deletions(-) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 27ee0cb85..69827bb49 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -42,6 +42,8 @@ class MAGNUM_EXPORT Framebuffer { Framebuffer& operator=(Framebuffer&& other) = delete; public: + /** @{ @name Framebuffer features */ + /** * @brief Features * @@ -66,6 +68,21 @@ class MAGNUM_EXPORT Framebuffer { FaceCulling = GL_CULL_FACE /**< Back face culling */ }; + /** @brief Set feature */ + static void setFeature(Feature feature, bool enabled); + + /** + * @brief Set viewport size + * + * Call when window size changes. + * @see Camera::setViewport() + */ + static void setViewport(const Math::Vector2& position, const Math::Vector2& size); + + /*@}*/ + + /** @{ @name Clearing the framebuffer */ + /** * @brief Mask for clearing * @@ -79,6 +96,61 @@ class MAGNUM_EXPORT Framebuffer { typedef Corrade::Utility::Set ClearMask; /**< @brief Mask for clearing */ + /** + * @brief Clear framebuffer + * + * Clears color buffer, depth and stencil buffer in currently active + * framebuffer. If depth or stencil test is not enabled, it doesn't + * clear these buffers. + * + * @see setFeature(), clear(ClearMask) + */ + inline static void clear() { glClear(static_cast(clearMask)); } + + /** + * @brief Clear specified buffers in framebuffer + * + * @see clear() + */ + inline static void clear(ClearMask mask) { glClear(static_cast(mask)); } + + /** + * @brief Set clear color + * + * Initial value is `{0.0f, 0.0f, 0.0f, 1.0f}`. + */ + inline static void setClearColor(const Color4& color) { + glClearColor(color.r(), color.g(), color.b(), color.a()); + } + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Set clear depth + * + * Initial value is `1.0`. + * @requires_gl See setClearDepth(GLfloat), which is supported in OpenGL ES. + */ + inline static void setClearDepth(GLdouble depth) { glClearDepth(depth); } + #endif + + /** + * @overload + * + * @requires_gl41 Extension @extension{ARB,ES2_compatibility} + */ + inline static void setClearDepth(GLfloat depth) { glClearDepthf(depth); } + + /** + * @brief Set clear stencil + * + * Initial value is `0`. + */ + inline static void setClearStencil(GLint stencil) { glClearStencil(stencil); } + + /*@}*/ + + /** @{ @name Framebuffer creation and binding */ + /** * @brief %Framebuffer target * @@ -142,119 +214,38 @@ class MAGNUM_EXPORT Framebuffer { #endif /** - * @brief Attachment for depth/stencil part of fragment shader output + * @brief Constructor * - * @see attachRenderbuffer(Target, DepthStencilAttachment, Renderbuffer*), - * attachTexture1D(Target, DepthStencilAttachment, Texture1D*, GLint), - * attachTexture2D(Target, DepthStencilAttachment, Texture2D*, GLint), - * attachCubeMapTexture(Target, DepthStencilAttachment, CubeMapTexture*, CubeMapTexture::Coordinate, GLint), - * attachTexture3D(Target, DepthStencilAttachment, Texture3D*, GLint) + * Generates new OpenGL framebuffer. * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ - enum class DepthStencilAttachment: GLenum { - Depth = GL_DEPTH_ATTACHMENT, /**< Depth output only. */ - - Stencil = GL_STENCIL_ATTACHMENT /**< Stencil output only. */ - - #ifndef MAGNUM_TARGET_GLES - , - /** - * Both depth and stencil output. - */ - DepthStencil = GL_DEPTH_STENCIL_ATTACHMENT - #endif - }; + inline Framebuffer() { glGenFramebuffers(1, &framebuffer); } /** - * @brief Output mask for blitting + * @brief Destructor * - * Specifies which data are copied when performing blit operation - * using blit(). - * @see BlitMask - * @requires_gl30 Extension @extension{EXT,framebuffer_object} - */ - enum class Blit: GLbitfield { - Color = GL_COLOR_BUFFER_BIT, /**< Color */ - Depth = GL_DEPTH_BUFFER_BIT, /**< Depth value */ - Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil value */ - }; - - /** - * @brief Output mask for blitting + * Deletes associated OpenGL framebuffer. * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ - typedef Corrade::Utility::Set BlitMask; - - /** @brief Set feature */ - static void setFeature(Feature feature, bool enabled); + inline ~Framebuffer() { glDeleteFramebuffers(1, &framebuffer); } /** - * @brief Set clear color + * @brief Bind default framebuffer to given target + * @param target %Target * - * Initial value is `{0.0f, 0.0f, 0.0f, 1.0f}`. + * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ - inline static void setClearColor(const Color4& color) { - glClearColor(color.r(), color.g(), color.b(), color.a()); + inline static void bindDefault(Target target) { + glBindFramebuffer(static_cast(target), 0); } /** - * @brief Clear framebuffer - * - * Clears color buffer, depth and stencil buffer in currently active - * framebuffer. If depth or stencil test is not enabled, it doesn't - * clear these buffers. - * - * @see setFeature(), clear(ClearMask) - */ - inline static void clear() { glClear(static_cast(clearMask)); } - - /** - * @brief Clear specified buffers in framebuffer - * - * @see clear() - */ - inline static void clear(ClearMask mask) { glClear(static_cast(mask)); } - - #ifndef MAGNUM_TARGET_GLES - /** - * @brief Set clear depth - * - * Initial value is `1.0`. - * @requires_gl See setClearDepth(GLfloat), which is supported in OpenGL ES. - */ - inline static void setClearDepth(GLdouble depth) { glClearDepth(depth); } - #endif - - /** - * @overload - * - * @requires_gl41 Extension @extension{ARB,ES2_compatibility} - */ - inline static void setClearDepth(GLfloat depth) { glClearDepthf(depth); } - - /** - * @brief Set clear stencil - * - * Initial value is `0`. - */ - inline static void setClearStencil(GLint stencil) { glClearStencil(stencil); } - - /** - * @brief Set viewport size - * - * Call when window size changes. - * @see Camera::setViewport() - */ - static void setViewport(const Math::Vector2& position, const Math::Vector2& size); - - /** - * @brief Bind default framebuffer to given target - * @param target %Target + * @brief Bind framebuffer * * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ - inline static void bindDefault(Target target) { - glBindFramebuffer(static_cast(target), 0); + inline void bind(Target target) { + glBindFramebuffer(static_cast(target), framebuffer); } #ifndef MAGNUM_TARGET_GLES @@ -274,120 +265,6 @@ class MAGNUM_EXPORT Framebuffer { */ static void mapDefaultForDraw(std::initializer_list attachments); - /** - * @brief Map given attachment of default framebuffer for reading - * @param attachment Default attachment - * - * Each used attachment should have either renderbuffer or texture - * attached to work properly. - * @see mapForRead(), mapDefaultForDraw() - * @requires_gl - * @requires_gl30 Extension @extension{EXT,framebuffer_object} - */ - inline static void mapDefaultForRead(DefaultReadAttachment attachment) { - bindDefault(Target::Read); - glReadBuffer(static_cast(attachment)); - } - #endif - - #ifndef MAGNUM_TARGET_GLES - /** - * @brief Copy block of pixels from read to draw framebuffer - * @param bottomLeft Bottom left coordinates of source rectangle - * @param topRight Top right coordinates of source rectangle - * @param destinationBottomLeft Bottom left coordinates of destination rectangle - * @param destinationTopRight Top right coordinates of destination - * rectangle - * @param blitMask Blit mask - * @param filter Interpolation applied if the image is - * stretched - * - * See mapForRead() / mapDefaultForRead() and mapForDraw() / - * mapDefaultForDraw() for binding particular framebuffer for reading - * and drawing. If multiple attachments are specified in mapForDraw() - * / mapDefaultForDraw(), the data are written to each of them. - * @requires_gl - * @requires_gl30 Extension @extension{EXT,framebuffer_blit} - */ - inline static void blit(const Math::Vector2& bottomLeft, const Math::Vector2& topRight, const Math::Vector2& destinationBottomLeft, const Math::Vector2& destinationTopRight, BlitMask blitMask, AbstractTexture::Filter filter) { - glBlitFramebuffer(bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), destinationBottomLeft.x(), destinationBottomLeft.y(), destinationTopRight.x(), destinationTopRight.y(), static_cast(blitMask), static_cast(filter)); - } - - /** - * @brief Copy block of pixels from read to draw framebuffer - * @param bottomLeft Bottom left coordinates of source and - * destination rectangle - * @param topRight Top right coordinates of source and - * destination rectangle - * @param blitMask Blit mask - * - * Convenience function when source rectangle is the same as - * destination rectangle. As the image is copied pixel-by-pixel, - * no interpolation is needed and thus - * AbstractTexture::Filter::NearestNeighbor filtering is used by - * default. - * @requires_gl - * @requires_gl30 Extension @extension{EXT,framebuffer_blit} - */ - inline static void blit(const Math::Vector2& bottomLeft, const Math::Vector2& topRight, BlitMask blitMask) { - glBlitFramebuffer(bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), static_cast(blitMask), static_cast(AbstractTexture::Filter::NearestNeighbor)); - } - #endif - - /** - * @brief Read block of pixels from framebuffer to image - * @param offset Offset in the framebuffer - * @param dimensions Image dimensions - * @param components Color components - * @param type Data type - * @param image %Image where to put the data - * - * @requires_gl30 Extension @extension{EXT,framebuffer_object} - */ - static void read(const Math::Vector2& offset, const Math::Vector2& dimensions, AbstractImage::Components components, AbstractImage::ComponentType type, Image2D* image); - - #ifndef MAGNUM_TARGET_GLES - /** - * @brief Read block of pixels from framebuffer to buffered image - * @param offset Offset in the framebuffer - * @param dimensions Image dimensions - * @param components Color components - * @param type Data type - * @param image Buffered image where to put the data - * @param usage %Buffer usage - * - * @requires_gl - * @requires_gl30 Extension @extension{EXT,framebuffer_object} - */ - static void read(const Math::Vector2& offset, const Math::Vector2& dimensions, AbstractImage::Components components, AbstractImage::ComponentType type, BufferedImage2D* image, Buffer::Usage usage); - #endif - - /** - * @brief Constructor - * - * Generates new OpenGL framebuffer. - * @requires_gl30 Extension @extension{EXT,framebuffer_object} - */ - inline Framebuffer() { glGenFramebuffers(1, &framebuffer); } - - /** - * @brief Destructor - * - * Deletes associated OpenGL framebuffer. - * @requires_gl30 Extension @extension{EXT,framebuffer_object} - */ - inline ~Framebuffer() { glDeleteFramebuffers(1, &framebuffer); } - - /** - * @brief Bind framebuffer - * - * @requires_gl30 Extension @extension{EXT,framebuffer_object} - */ - inline void bind(Target target) { - glBindFramebuffer(static_cast(target), framebuffer); - } - - #ifndef MAGNUM_TARGET_GLES /** * @brief Map given color attachments of current framebuffer for drawing * @param colorAttachments Color attachment IDs. If any value is -1, @@ -404,6 +281,21 @@ class MAGNUM_EXPORT Framebuffer { */ void mapForDraw(std::initializer_list colorAttachments); + /** + * @brief Map given attachment of default framebuffer for reading + * @param attachment Default attachment + * + * Each used attachment should have either renderbuffer or texture + * attached to work properly. + * @see mapForRead(), mapDefaultForDraw() + * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} + */ + inline static void mapDefaultForRead(DefaultReadAttachment attachment) { + bindDefault(Target::Read); + glReadBuffer(static_cast(attachment)); + } + /** * @brief Map given color attachment of current framebuffer for reading * @param colorAttachment Color attachment ID @@ -420,6 +312,34 @@ class MAGNUM_EXPORT Framebuffer { } #endif + /*@}*/ + + /** @{ @name Attaching textures and renderbuffers */ + + /** + * @brief Attachment for depth/stencil part of fragment shader output + * + * @see attachRenderbuffer(Target, DepthStencilAttachment, Renderbuffer*), + * attachTexture1D(Target, DepthStencilAttachment, Texture1D*, GLint), + * attachTexture2D(Target, DepthStencilAttachment, Texture2D*, GLint), + * attachCubeMapTexture(Target, DepthStencilAttachment, CubeMapTexture*, CubeMapTexture::Coordinate, GLint), + * attachTexture3D(Target, DepthStencilAttachment, Texture3D*, GLint) + * @requires_gl30 Extension @extension{EXT,framebuffer_object} + */ + enum class DepthStencilAttachment: GLenum { + Depth = GL_DEPTH_ATTACHMENT, /**< Depth output only. */ + + Stencil = GL_STENCIL_ATTACHMENT /**< Stencil output only. */ + + #ifndef MAGNUM_TARGET_GLES + , + /** + * Both depth and stencil output. + */ + DepthStencil = GL_DEPTH_STENCIL_ATTACHMENT + #endif + }; + /** * @brief Attach renderbuffer to given framebuffer depth/stencil attachment * @param target %Target @@ -592,6 +512,106 @@ class MAGNUM_EXPORT Framebuffer { } #endif + /*@}*/ + + /** @{ @name Framebuffer blitting and reading */ + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Output mask for blitting + * + * Specifies which data are copied when performing blit operation + * using blit(). + * @see BlitMask + * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} + */ + enum class Blit: GLbitfield { + Color = GL_COLOR_BUFFER_BIT, /**< Color */ + Depth = GL_DEPTH_BUFFER_BIT, /**< Depth value */ + Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil value */ + }; + + /** + * @brief Output mask for blitting + * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} + */ + typedef Corrade::Utility::Set BlitMask; + + /** + * @brief Copy block of pixels from read to draw framebuffer + * @param bottomLeft Bottom left coordinates of source rectangle + * @param topRight Top right coordinates of source rectangle + * @param destinationBottomLeft Bottom left coordinates of destination rectangle + * @param destinationTopRight Top right coordinates of destination + * rectangle + * @param blitMask Blit mask + * @param filter Interpolation applied if the image is + * stretched + * + * See mapForRead() / mapDefaultForRead() and mapForDraw() / + * mapDefaultForDraw() for binding particular framebuffer for reading + * and drawing. If multiple attachments are specified in mapForDraw() + * / mapDefaultForDraw(), the data are written to each of them. + * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_blit} + */ + inline static void blit(const Math::Vector2& bottomLeft, const Math::Vector2& topRight, const Math::Vector2& destinationBottomLeft, const Math::Vector2& destinationTopRight, BlitMask blitMask, AbstractTexture::Filter filter) { + glBlitFramebuffer(bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), destinationBottomLeft.x(), destinationBottomLeft.y(), destinationTopRight.x(), destinationTopRight.y(), static_cast(blitMask), static_cast(filter)); + } + + /** + * @brief Copy block of pixels from read to draw framebuffer + * @param bottomLeft Bottom left coordinates of source and + * destination rectangle + * @param topRight Top right coordinates of source and + * destination rectangle + * @param blitMask Blit mask + * + * Convenience function when source rectangle is the same as + * destination rectangle. As the image is copied pixel-by-pixel, + * no interpolation is needed and thus + * AbstractTexture::Filter::NearestNeighbor filtering is used by + * default. + * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_blit} + */ + inline static void blit(const Math::Vector2& bottomLeft, const Math::Vector2& topRight, BlitMask blitMask) { + glBlitFramebuffer(bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), bottomLeft.x(), bottomLeft.y(), topRight.x(), topRight.y(), static_cast(blitMask), static_cast(AbstractTexture::Filter::NearestNeighbor)); + } + #endif + + /** + * @brief Read block of pixels from framebuffer to image + * @param offset Offset in the framebuffer + * @param dimensions Image dimensions + * @param components Color components + * @param type Data type + * @param image %Image where to put the data + * + * @requires_gl30 Extension @extension{EXT,framebuffer_object} + */ + static void read(const Math::Vector2& offset, const Math::Vector2& dimensions, AbstractImage::Components components, AbstractImage::ComponentType type, Image2D* image); + + #ifndef MAGNUM_TARGET_GLES + /** + * @brief Read block of pixels from framebuffer to buffered image + * @param offset Offset in the framebuffer + * @param dimensions Image dimensions + * @param components Color components + * @param type Data type + * @param image Buffered image where to put the data + * @param usage %Buffer usage + * + * @requires_gl + * @requires_gl30 Extension @extension{EXT,framebuffer_object} + */ + static void read(const Math::Vector2& offset, const Math::Vector2& dimensions, AbstractImage::Components components, AbstractImage::ComponentType type, BufferedImage2D* image, Buffer::Usage usage); + #endif + + /*@}*/ + private: static ClearMask clearMask; From cd8b309ce8acf569ccdc315f7c9fa8d14c442baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 Aug 2012 19:57:14 +0200 Subject: [PATCH 07/78] Added @todo. --- src/Framebuffer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 69827bb49..e0ebbce3e 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -111,6 +111,7 @@ class MAGNUM_EXPORT Framebuffer { * @brief Clear specified buffers in framebuffer * * @see clear() + * @todo Clearing only given draw buffer */ inline static void clear(ClearMask mask) { glClear(static_cast(mask)); } From ae843eb595a5c65e057fc7f09cdba964c91c19dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 Aug 2012 19:57:54 +0200 Subject: [PATCH 08/78] Added set*Mask() functions to Framebuffer. --- src/Framebuffer.h | 53 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index e0ebbce3e..f666687dc 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -150,6 +150,59 @@ class MAGNUM_EXPORT Framebuffer { /*@}*/ + /** @{ @name Masking writes */ + + /** + * @brief Affected face for stencil mask + * + * @see setStencilMask(StencilMaskFace, GLuint) + */ + enum class StencilMaskFace: GLenum { + Front = GL_FRONT, /**< Front-facing polygons */ + Back = GL_BACK, /**< Back-facing polygons */ + FrontAndBack = GL_FRONT_AND_BACK /**< Front- and back-facing polygons */ + }; + + /** + * @brief Mask color writes + * + * Set to `false` to disallow writing to given color channel. + * @todo Masking only given draw buffer + */ + inline static void setColorMask(GLboolean allowRed, GLboolean allowGreen, GLboolean allowBlue, GLboolean allowAlpha) { + glColorMask(allowRed, allowGreen, allowBlue, allowAlpha); + } + + /** + * @brief Mask depth writes + * + * Set to `false` to disallow writing to depth buffer. + */ + inline static void setDepthMask(GLboolean allow) { + glDepthMask(allow); + } + + /** + * @brief Mask stencil writes + * + * Set given bit to `0` to disallow writing stencil value to it. + */ + inline static void setStencilMask(GLuint allowBits) { + glStencilMask(allowBits); + } + + /** + * @brief Mask stencil writes + * + * Set given bit to `0` to disallow writing stencil value for given + * faces to it. + */ + inline static void setStencilMask(StencilMaskFace face, GLuint allowBits) { + glStencilMaskSeparate(static_cast(face), allowBits); + } + + /*@}*/ + /** @{ @name Framebuffer creation and binding */ /** From 5ea1f104e824ffe54a188056ee1fca049772f187 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 Aug 2012 19:59:18 +0200 Subject: [PATCH 09/78] Blending is not only alpha blending. --- src/Framebuffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index f666687dc..bf5f1fa71 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -51,7 +51,7 @@ class MAGNUM_EXPORT Framebuffer { * @see setFeature() */ enum class Feature: GLenum { - AlphaBlending = GL_BLEND, /**< Alpha blending */ + Blending = GL_BLEND, /**< Blending */ #ifndef MAGNUM_TARGET_GLES /** From 129b7f23a75f55ec9da0f0315d3ef7979154559b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 Aug 2012 22:46:46 +0200 Subject: [PATCH 10/78] Fixed typos (substract -> subtract). --- doc/building.dox | 2 +- src/Math/Test/VectorTest.cpp | 4 ++-- src/Math/Test/VectorTest.h | 2 +- src/Math/Vector.h | 4 ++-- src/Physics/ShapeGroup.h | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/building.dox b/doc/building.dox index 5f85874d8..5153bf4b4 100644 --- a/doc/building.dox +++ b/doc/building.dox @@ -15,7 +15,7 @@ Minimal set of tools and libraries required for building is: which are tested to support everything needed: **GCC** >= 4.6 and **Clang** >= 3.1. - **CMake** >= 2.8.8 (needed for `OBJECT` library target) -- **OpenGL** headers, on Linux most probably shipped with Mesa or +- **OpenGL** headers, on Linux most probably shipped with Mesa, or **OpenGL ES 2** headers, if targeting OpenGL ES (see below). - **GLEW** - OpenGL extension wrangler - **Corrade** - Plugin management and utility library. You can get it at diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index 327c2cb49..41bd037ec 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/src/Math/Test/VectorTest.cpp @@ -36,7 +36,7 @@ VectorTest::VectorTest() { &VectorTest::copy, &VectorTest::dot, &VectorTest::multiplyDivide, - &VectorTest::addSubstract, + &VectorTest::addSubtract, &VectorTest::dotSelf, &VectorTest::length, &VectorTest::normalized, @@ -103,7 +103,7 @@ void VectorTest::multiplyDivide() { CORRADE_COMPARE(multipliedChar/-1.5f, vecChar); } -void VectorTest::addSubstract() { +void VectorTest::addSubtract() { Vector4 a(0.5f, -7.5f, 9.0f, -11.0f); Vector4 b(-0.5, 1.0f, 0.0f, 7.5f); Vector4 expected(0.0f, -6.5f, 9.0f, -3.5f); diff --git a/src/Math/Test/VectorTest.h b/src/Math/Test/VectorTest.h index 662865119..bbf02d783 100644 --- a/src/Math/Test/VectorTest.h +++ b/src/Math/Test/VectorTest.h @@ -28,7 +28,7 @@ class VectorTest: public Corrade::TestSuite::Tester { void copy(); void dot(); void multiplyDivide(); - void addSubstract(); + void addSubtract(); void dotSelf(); void length(); void normalized(); diff --git a/src/Math/Vector.h b/src/Math/Vector.h index bfdb1681f..9e7800cdd 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -218,13 +218,13 @@ template class Vector { return *this; } - /** @brief Substract two vectors */ + /** @brief Subtract two vectors */ inline Vector operator-(const Vector& other) const { return Vector(*this)-=other; } /** - * @brief Substract and assign vector + * @brief Subtract and assign vector * * More efficient than operator-(), because it does the computation * in-place. diff --git a/src/Physics/ShapeGroup.h b/src/Physics/ShapeGroup.h index 2e1174c82..074474719 100644 --- a/src/Physics/ShapeGroup.h +++ b/src/Physics/ShapeGroup.h @@ -31,7 +31,7 @@ namespace Magnum { namespace Physics { /** @brief Collider group with defined set operation -Result of union, intersection, substraction or XOR of two collider objects. +Result of union, intersection, subtraction or XOR of two collider objects. See @ref collision-detection for brief introduction. */ class PHYSICS_EXPORT ShapeGroup: public AbstractShape { From ee55d8425ccfd74a2299848a17a7755354c1caf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 14 Aug 2012 00:14:22 +0200 Subject: [PATCH 11/78] Added AbstractShaderProgram::bindFragmentDataLocationIndexed(). --- src/AbstractShaderProgram.cpp | 5 +++++ src/AbstractShaderProgram.h | 38 +++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/AbstractShaderProgram.cpp b/src/AbstractShaderProgram.cpp index 4fd606973..47ea3eeb4 100644 --- a/src/AbstractShaderProgram.cpp +++ b/src/AbstractShaderProgram.cpp @@ -50,6 +50,11 @@ void AbstractShaderProgram::bindFragmentDataLocation(GLuint location, const std: glBindFragDataLocation(program, location, name.c_str()); } +void AbstractShaderProgram::bindFragmentDataLocationIndexed(GLuint location, GLuint index, const std::string& name) { + CORRADE_ASSERT(state == Initialized, "AbstractShaderProgram: fragment data location cannot be bound after linking.", ); + + glBindFragDataLocationIndexed(program, location, index, name.c_str()); +} #endif void AbstractShaderProgram::link() { diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index d15c2aeb9..d08447345 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -39,6 +39,8 @@ typedef Attribute<0, Vector4> Vertex; typedef Attribute<1, Vector3> Normal; typedef Attribute<2, Vector2> TextureCoords; @endcode + @todoc Output attribute location (for bindFragmentDataLocationIndexed(), + referenced also from Framebuffer::mapDefaultForDraw() / Framebuffer::mapForDraw()) - **Layers for texture uniforms** to which the textures will be bound before rendering, for example: @code @@ -82,18 +84,27 @@ layout(location = 0) in vec4 vertex; layout(location = 1) in vec3 normal; layout(location = 2) in vec2 textureCoords; @endcode +Similarly for ouput attributes, you can also specify blend equation color +index for them (see Framebuffer::BlendFunction for more information about +using color input index): +@code +layout(location = 0, index = 0) out vec4 color; +layout(location = 1, index = 1) out vec4 ambient; +@endcode @requires_gl (for explicit input attribute location instead of using bindAttributeLocation()) @requires_gl (for explicit output attribute location or using - bindFragmentDataLocation()) + bindFragmentDataLocation() / bindFragmentDataLocationIndexed()) @requires_gl30 Extension @extension{EXT,gpu_shader4} (for using bindFragmentDataLocation()) +@requires_gl33 Extension @extension{ARB,blend_func_extended} (for using + bindFragmentDataLocationIndexed()) @requires_gl33 Extension @extension{ARB,explicit_attrib_location} (for explicit attribute location instead of using bindAttributeLocation()) If you don't have the required extension, you can use functions bindAttributeLocation() -and bindFragmentDataLocation() between attaching of shaders and linking the -program: +and bindFragmentDataLocation() / bindFragmentDataLocationIndexed() between +attaching the shaders and linking the program: @code // Shaders attached... @@ -101,6 +112,9 @@ bindAttributeLocation(Vertex::Location, "vertex"); bindAttributeLocation(Normal::Location, "normal"); bindAttributeLocation(TextureCoords::Location, "textureCoords"); +bindFragmentDataLocationIndexed(0, 0, "color"); +bindFragmentDataLocationIndexed(1, 1, "ambient"); + // Link... @endcode @@ -249,16 +263,32 @@ class MAGNUM_EXPORT AbstractShaderProgram { #ifndef MAGNUM_TARGET_GLES /** - * @brief Bind fragment data to given location + * @brief Bind fragment data to given location and color input index * @param location Location * @param name Fragment output variable name + * @param index Blend equation color input index (`0` or `1`) * + * Binds fragment data to location which is used later for framebuffer + * operations. See also Framebuffer::BlendFunction for more + * information about using color input index. + * @requires_gl + * @requires_gl33 Extension @extension{ARB,blend_func_extended} * @note This function should be called after attachShader() calls and * before link(). * @deprecated 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. + */ + void bindFragmentDataLocationIndexed(GLuint location, GLuint index, const std::string& name); + + /** + * @brief Bind fragment data to given location and first color input index + * @param location Location + * @param name Fragment output variable name + * + * The same as bindFragmentDataLocationIndexed(), but with `index` set + * to `0`. * @requires_gl * @requires_gl30 Extension @extension{EXT,gpu_shader4} */ From a491d54ed5dd0f5c9c24ec3d2ffad46723f8f350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 14 Aug 2012 00:15:01 +0200 Subject: [PATCH 12/78] Added blend operations to Framebuffer. --- src/Framebuffer.h | 210 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 209 insertions(+), 1 deletion(-) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index bf5f1fa71..4a0f29e43 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -51,7 +51,11 @@ class MAGNUM_EXPORT Framebuffer { * @see setFeature() */ enum class Feature: GLenum { - Blending = GL_BLEND, /**< Blending */ + /** + * Blending + * @see setBlendEquation(), setBlendFunction(), setBlendColor() + */ + Blending = GL_BLEND, #ifndef MAGNUM_TARGET_GLES /** @@ -203,6 +207,210 @@ class MAGNUM_EXPORT Framebuffer { /*@}*/ + /** @{ @name Blending + * @todo Blending for given draw buffer + */ + + /** + * @brief Blend equation + * + * @see setBlendEquation() + */ + enum class BlendEquation: GLenum { + Add = GL_FUNC_ADD, /**< `source + destination` */ + Subtract = GL_FUNC_SUBTRACT, /**< `source - destination` */ + ReverseSubtract = GL_FUNC_REVERSE_SUBTRACT, /**< `destination - source` */ + Min = GL_MIN, /**< `min(source, destination)` */ + Max = GL_MAX /**< `max(source, destination)` */ + }; + + /** + * @brief Blend function + * + * @see setBlendFunction() + */ + enum class BlendFunction: GLenum { + /** Zero (@f$ RGB = (0.0, 0.0, 0.0); A = 0.0 @f$) */ + Zero = GL_ZERO, + + /** One (@f$ RGB = (1.0, 1.0, 1.0); A = 1.0 @f$) */ + One = GL_ONE, + + /** + * Constant color (@f$ RGB = (R_c, G_c, B_c); A = A_c @f$) + * + * @see setBlendColor() + */ + ConstantColor = GL_CONSTANT_COLOR, + + /** + * One minus constant color (@f$ RGB = (1.0 - R_c, 1.0 - G_c, 1.0 - B_c); A = 1.0 - A_c @f$) + * + * @see setBlendColor() + */ + OneMinusConstantColor = GL_ONE_MINUS_CONSTANT_COLOR, + + /** + * Constant alpha (@f$ RGB = (A_c, A_c, A_c); A = A_c @f$) + * + * @see setBlendColor() + */ + ConstantAlpha = GL_CONSTANT_ALPHA, + + /** + * One minus constant alpha (@f$ RGB = (1.0 - A_c, 1.0 - A_c, 1.0 - A_c); A = 1.0 - A_c @f$) + * + * @see setBlendColor() + */ + OneMinusConstantAlpha = GL_ONE_MINUS_CONSTANT_ALPHA, + + /** Source color (@f$ RGB = (R_{s0}, G_{s0}, B_{s0}); A = A_{s0} @f$) */ + SourceColor = GL_SRC_COLOR, + + #ifndef MAGNUM_TARGET_GLES + /** + * Second source color (@f$ RGB = (R_{s1}, G_{s1}, B_{s1}); A = A_{s1} @f$) + * + * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() + * @requires_gl + * @requires_gl33 Extension @extension{ARB,blend_func_extended} + */ + SecondSourceColor = GL_SRC1_COLOR, + #endif + + /** + * One minus source color (@f$ RGB = (1.0 - R_{s0}, 1.0 - G_{s0}, 1.0 - B_{s0}); A = 1.0 - A_{s0} @f$) + */ + OneMinusSourceColor = GL_ONE_MINUS_SRC_COLOR, + + #ifndef MAGNUM_TARGET_GLES + /** + * One minus second source color (@f$ RGB = (1.0 - R_{s1}, 1.0 - G_{s1}, 1.0 - B_{s1}); A = 1.0 - A_{s1} @f$) + * + * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() + * @requires_gl + * @requires_gl33 Extension @extension{ARB,blend_func_extended} + */ + OneMinusSecondSourceColor = GL_ONE_MINUS_SRC1_COLOR, + #endif + + /** Source alpha (@f$ RGB = (A_{s0}, A_{s0}, A_{s0}); A = A_{s0} @f$) */ + SourceAlpha = GL_SRC_ALPHA, + + /** + * Saturate source alpha (@f$ RGB = (f, f, f); A = 1.0; f = min(A_s, 1.0 - A_d) @f$) + * + * Can be used only in source parameter of setBlendFunction(). + */ + SourceAlphaSaturate = GL_SRC_ALPHA_SATURATE, + + #ifndef MAGNUM_TARGET_GLES + /** + * Second source alpha (@f$ RGB = (A_{s1}, A_{s1}, A_{s1}); A = A_{s1} @f$) + * + * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() + * @requires_gl + * @requires_gl33 Extension @extension{ARB,blend_func_extended} + */ + SecondSourceAlpha = GL_SRC1_ALPHA, + #endif + + /** + * One minus source alpha (@f$ RGB = (1.0 - A_{s0}, 1.0 - A_{s0}, 1.0 - A_{s0}); A = 1.0 - A_{s0} @f$) + */ + OneMinusSourceAlpha = GL_ONE_MINUS_SRC_ALPHA, + + #ifndef MAGNUM_TARGET_GLES + /** + * One minus second source alpha (@f$ RGB = (1.0 - A_{s1}, 1.0 - A_{s1}, 1.0 - A_{s1}); A = 1.0 - A_{s1} @f$) + * + * @see AbstractShaderProgram::bindFragmentDataLocationIndexed() + * @requires_gl + * @requires_gl33 Extension @extension{ARB,blend_func_extended} + */ + OneMinusSecondSourceAlpha = GL_ONE_MINUS_SRC1_ALPHA, + #endif + + /** Destination color (@f$ RGB = (R_d, G_d, B_d); A = A_d @f$) */ + DestinationColor = GL_DST_COLOR, + + /** + * One minus source color (@f$ RGB = (1.0 - R_d, 1.0 - G_d, 1.0 - B_d); A = 1.0 - A_d @f$) + */ + OneMinusDestinationColor = GL_ONE_MINUS_DST_COLOR, + + /** Destination alpha (@f$ RGB = (A_d, A_d, A_d); A = A_d @f$) */ + DestinationAlpha = GL_DST_ALPHA, + + /** + * One minus source alpha (@f$ RGB = (1.0 - A_d, 1.0 - A_d, 1.0 - A_d); A = 1.0 - A_d @f$) + */ + OneMinusDestinationAlpha = GL_ONE_MINUS_DST_ALPHA + }; + + /** + * @brief Set blend equation + * + * How to combine source color (pixel value) with destination color + * (framebuffer). Initial value is `BlendEquation::Add`. + * @attention You have to enable blending with setFeature() first. + * @see setBlendEquation(BlendEquation, BlendEquation) + */ + inline static void setBlendEquation(BlendEquation equation) { + glBlendEquation(static_cast(equation)); + } + + /** + * @brief Set blend equation separately for RGB and alpha components + * + * See setBlendEquation(BlendEquation) for more information. + * @attention You have to enable blending with setFeature() first. + */ + inline static void setBlendEquation(BlendEquation rgb, BlendEquation alpha) { + glBlendEquationSeparate(static_cast(rgb), static_cast(alpha)); + } + + /** + * @brief Set blend function + * @param source How the source blending factor is computed + * from pixel value. Initial value is `BlendFunction::One`. + * @param destination How the destination blending factor is + * computed from framebuffer. Initial value is + * `BlendFunction::Zero`. + * + * @attention You have to enable blending with setFeature() first. + * @see setBlendFunction(BlendFunction, BlendFunction, BlendFunction, BlendFunction) + */ + inline static void setBlendFunction(BlendFunction source, BlendFunction destination) { + glBlendFunc(static_cast(source), static_cast(destination)); + } + + /** + * @brief Set blend function separately for RGB and alpha components + * + * See setBlendFunction(BlendFunction, BlendFunction) for more information. + * @attention You have to enable blending with setFeature() first. + */ + inline static void setBlendFunction(BlendFunction sourceRgb, BlendFunction destinationRgb, BlendFunction sourceAlpha, BlendFunction destinationAlpha) { + glBlendFuncSeparate(static_cast(sourceRgb), static_cast(destinationRgb), static_cast(sourceAlpha), static_cast(destinationAlpha)); + } + + /** + * @brief Set blend color + * + * Sets constant color used in setBlendFunction() by + * `BlendFunction::ConstantColor`, + * `BlendFunction::OneMinusConstantColor`, + * `BlendFunction::ConstantAlpha` and + * `BlendFunction::OneMinusConstantAlpha`. + * @attention You have to enable blending with setFeature() first. + */ + inline static void setBlendColor(const Color4& color) { + glBlendColor(color.r(), color.g(), color.b(), color.a()); + } + + /*@}*/ + /** @{ @name Framebuffer creation and binding */ /** From 8084e283637863e576fd852a7485f08325bc0040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 14 Aug 2012 00:15:35 +0200 Subject: [PATCH 13/78] Doc++ --- src/AbstractShaderProgram.h | 4 ++-- src/Framebuffer.h | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index d08447345..6b53cd6b6 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -250,8 +250,8 @@ class MAGNUM_EXPORT AbstractShaderProgram { * @param location Location * @param name Attribute name * - * Binds attribute to location which is be used later for binding - * vertex buffers. Preferred usage is to + * Binds attribute to location which is used later for binding vertex + * buffers. * @note This function should be called after attachShader() calls and * before link(). * @deprecated Preferred usage is to specify attribute location diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 4a0f29e43..4861a240d 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -190,6 +190,7 @@ class MAGNUM_EXPORT Framebuffer { * @brief Mask stencil writes * * Set given bit to `0` to disallow writing stencil value to it. + * @see setStencilMask(StencilMaskFace, GLuint) */ inline static void setStencilMask(GLuint allowBits) { glStencilMask(allowBits); @@ -200,6 +201,7 @@ class MAGNUM_EXPORT Framebuffer { * * Set given bit to `0` to disallow writing stencil value for given * faces to it. + * @see setStencilMask(GLuint) */ inline static void setStencilMask(StencilMaskFace face, GLuint allowBits) { glStencilMaskSeparate(static_cast(face), allowBits); @@ -847,7 +849,7 @@ class MAGNUM_EXPORT Framebuffer { /** * @brief Read block of pixels from framebuffer to image * @param offset Offset in the framebuffer - * @param dimensions Image dimensions + * @param dimensions %Image dimensions * @param components Color components * @param type Data type * @param image %Image where to put the data @@ -860,7 +862,7 @@ class MAGNUM_EXPORT Framebuffer { /** * @brief Read block of pixels from framebuffer to buffered image * @param offset Offset in the framebuffer - * @param dimensions Image dimensions + * @param dimensions %Image dimensions * @param components Color components * @param type Data type * @param image Buffered image where to put the data From 3597eb5ddaba18fad403765af7fc0e7c38782454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 14 Aug 2012 00:34:22 +0200 Subject: [PATCH 14/78] Added scissor test to Framebuffer. --- src/Framebuffer.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 4861a240d..254a13c23 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -30,10 +30,12 @@ namespace Magnum { /** @ingroup textures +@nosubgrouping @brief %Framebuffer Provides operations with framebuffers (configuring, clearing, blitting...) and creation and attaching of named framebuffers. +@todo @extension{ARB,viewport_array} */ class MAGNUM_EXPORT Framebuffer { Framebuffer(const Framebuffer& other) = delete; @@ -66,6 +68,11 @@ class MAGNUM_EXPORT Framebuffer { DepthClamp = GL_DEPTH_CLAMP, #endif + /** + * Scissor test + * @see setScissor() + */ + ScissorTest = GL_SCISSOR_TEST, DepthTest = GL_DEPTH_TEST, /**< Depth test */ StencilTest = GL_STENCIL_TEST, /**< Stencil test */ Dithering = GL_DITHER, /**< Dithering (enabled by default) */ @@ -154,6 +161,22 @@ class MAGNUM_EXPORT Framebuffer { /*@}*/ + /** @{ @name Scissor operations */ + + /** + * @brief Set scissor rectangle + * @param bottomLeft Bottom left corner. Initial value is `(0, 0)`. + * @param size Scissor rectangle size. Initial value is + * size of the window when the context is first attached to a + * window. + * @attention You have to enable scissoring with setFeature() first. + */ + inline static void setScissor(const Math::Vector2& bottomLeft, const Math::Vector2& size) { + glScissor(bottomLeft.x(), bottomLeft.y(), size.x(), size.y()); + } + + /*@}*/ + /** @{ @name Masking writes */ /** @@ -210,6 +233,7 @@ class MAGNUM_EXPORT Framebuffer { /*@}*/ /** @{ @name Blending + * You have to enable blending with setFeature() first. * @todo Blending for given draw buffer */ From 433b43906deef3b2b5599ac85d27215806e8672a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 14 Aug 2012 00:57:34 +0200 Subject: [PATCH 15/78] Added logical operation to Framebuffer. --- src/Framebuffer.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 254a13c23..d330498ee 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -59,6 +59,12 @@ class MAGNUM_EXPORT Framebuffer { */ Blending = GL_BLEND, + /** + * Logical operation + * @see setLogicOperation() + */ + LogicOperation = GL_COLOR_LOGIC_OP, + #ifndef MAGNUM_TARGET_GLES /** * Depth clamping. If enabled, ignores near and far clipping plane. @@ -437,6 +443,43 @@ class MAGNUM_EXPORT Framebuffer { /*@}*/ + /** @{ @name Logical operation */ + + /** + * @brief Logical operation + * + * @see setLogicOperation() + */ + enum class LogicOperation: GLenum { + Clear = GL_CLEAR, /**< `0` */ + Set = GL_SET, /**< `1` */ + Copy = GL_COPY, /**< `source` */ + CopyInverted = GL_COPY_INVERTED,/**< `~source` */ + Noop = GL_NOOP, /**< `destination` */ + Invert = GL_INVERT, /**< `~destination` */ + And = GL_AND, /**< `source & destination` */ + AndReverse = GL_AND_REVERSE, /**< `source & ~destination` */ + AndInverted = GL_AND_INVERTED, /**< `~source & destination` */ + Nand = GL_NAND, /**< `~(source & destination)` */ + Or = GL_OR, /**< `source | destination` */ + OrReverse = GL_OR_REVERSE, /**< `source | ~destination` */ + OrInverted = GL_OR_INVERTED, /**< `~source | destination` */ + Nor = GL_NOR, /**< `~(source | destination)` */ + Xor = GL_XOR, /**< `source ^ destination` */ + Equivalence = GL_EQUIV /**< `~(source ^ destination)` */ + }; + + /** + * @brief Set logical operation + * + * @attention You have to enable logical operation with setFeature() first. + */ + inline static void setLogicOperation(LogicOperation operation) { + glLogicOp(static_cast(operation)); + } + + /*@}*/ + /** @{ @name Framebuffer creation and binding */ /** From 6407600c068595e209e582fd9c8e3055ed4cfded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 14 Aug 2012 01:45:34 +0200 Subject: [PATCH 16/78] Added stencil operations to Framebuffer. --- src/Framebuffer.h | 152 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 137 insertions(+), 15 deletions(-) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index d330498ee..b1d66bff4 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -183,23 +183,144 @@ class MAGNUM_EXPORT Framebuffer { /*@}*/ - /** @{ @name Masking writes */ + /** @{ @name Stencil operations */ /** - * @brief Affected face for stencil mask + * @brief Affected polygon facing for stencil operations and masks * - * @see setStencilMask(StencilMaskFace, GLuint) + * @see setStencilFunction(PolygonFacing, StencilFunction, GLint, GLuint), + * setStencilOperation(PolygonFacing, StencilOperation, StencilOperation, StencilOperation), + * setStencilMask(PolygonFacing, GLuint) */ - enum class StencilMaskFace: GLenum { + enum class PolygonFacing: GLenum { Front = GL_FRONT, /**< Front-facing polygons */ Back = GL_BACK, /**< Back-facing polygons */ FrontAndBack = GL_FRONT_AND_BACK /**< Front- and back-facing polygons */ }; + /** + * @brief Stencil function + * + * @see setStencilFunction() + */ + enum class StencilFunction: GLenum { + Never = GL_NEVER, /**< Never pass stencil test. */ + Always = GL_ALWAYS, /**< Always pass stencil test. */ + Less = GL_LESS, /**< Pass when reference value is less than buffer value. */ + LessOrEqual = GL_LEQUAL, /**< Pass when reference value is less than or equal to buffer value. */ + Equal = GL_EQUAL, /**< Pass when reference value is equal to buffer value. */ + NotEqual = GL_NOTEQUAL, /**< Pass when reference value is not equal to buffer value. */ + GreaterOrEqual = GL_GEQUAL, /**< Pass when reference value is greater than or equal to buffer value. */ + Greater = GL_GREATER /**< Pass when reference value is greater than buffer value. */ + }; + + /** + * @brief Stencil operation + * + * @see setStencilOperation() + */ + enum class StencilOperation: GLenum { + Keep = GL_KEEP, /**< Keep the current value. */ + Zero = GL_ZERO, /**< Set the stencil buffer value to `0`. */ + + /** + * Set the stencil value to reference value specified by + * setStencilFunction(). + */ + Replace = GL_REPLACE, + + /** + * Increment the current stencil buffer value, clamp to maximum + * possible value on overflow. + */ + Increment = GL_INCR, + + /** + * Increment the current stencil buffer value, wrap to zero on + * overflow. + */ + IncrementWrap = GL_INCR_WRAP, + + /** + * Increment the current stencil buffer value, clamp to minimum + * possible value on underflow. + */ + Decrement = GL_DECR, + + /** + * Decrement the current stencil buffer value, wrap to maximum + * possible value on underflow. + */ + DecrementWrap = GL_DECR_WRAP, + + /** + * Bitwise invert the current stencil buffer value. + */ + Invert = GL_INVERT + }; + + /** + * @brief Set stencil function + * @param facing Affected polygon facing + * @param function Stencil function. Initial value is + * `StencilFunction::Always`. + * @param referenceValue Reference value. Initial value is `0`. + * @param mask Mask for both reference and buffer value. + * Initial value is all `1`s. + * + * @attention You have to enable stencil test with setFeature() first. + * @see setStencilFunction(StencilFunction, GLint, GLuint) + */ + inline static void setStencilFunction(PolygonFacing facing, StencilFunction function, GLint referenceValue, GLuint mask) { + glStencilFuncSeparate(static_cast(facing), static_cast(function), referenceValue, mask); + } + + /** + * @brief Set stencil function + * + * The same as setStencilFunction(PolygonFacing, StencilFunction, GLint, GLuint) + * with `facing` set to `PolygonFacing::FrontAndBack`. + */ + inline static void setStencilFunction(StencilFunction function, GLint referenceValue, GLuint mask) { + glStencilFunc(static_cast(function), referenceValue, mask); + } + + /** + * @brief Set stencil operation + * @param facing Affected polygon facing + * @param stencilFail Action when stencil test fails + * @param depthFail Action when stencil test passes, but depth + * test fails + * @param depthPass Action when both stencil and depth test + * pass + * + * Initial value for all fields is `StencilOperation::Keep`. + * @attention You have to enable stencil test with setFeature() first. + * @see setStencilOperation(StencilOperation, StencilOperation, StencilOperation) + */ + inline static void setStencilOperation(PolygonFacing facing, StencilOperation stencilFail, StencilOperation depthFail, StencilOperation depthPass) { + glStencilOpSeparate(static_cast(facing), static_cast(stencilFail), static_cast(depthFail), static_cast(depthPass)); + } + + /** + * @brief Set stencil operation + * + * The same as setStencilOperation(PolygonFacing, StencilOperation, StencilOperation, StencilOperation) + * with `facing` set to `PolygonFacing::FrontAndBack`. + */ + inline static void setStencilOperation(StencilOperation stencilFail, StencilOperation depthFail, StencilOperation depthPass) { + glStencilOp(static_cast(stencilFail), static_cast(depthFail), static_cast(depthPass)); + } + + /*@}*/ + + /** @{ @name Masking writes */ + /** * @brief Mask color writes * - * Set to `false` to disallow writing to given color channel. + * Set to `false` to disallow writing to given color channel. Initial + * values are all `true`. * @todo Masking only given draw buffer */ inline static void setColorMask(GLboolean allowRed, GLboolean allowGreen, GLboolean allowBlue, GLboolean allowAlpha) { @@ -209,7 +330,8 @@ class MAGNUM_EXPORT Framebuffer { /** * @brief Mask depth writes * - * Set to `false` to disallow writing to depth buffer. + * Set to `false` to disallow writing to depth buffer. Initial value + * is `true`. */ inline static void setDepthMask(GLboolean allow) { glDepthMask(allow); @@ -218,22 +340,22 @@ class MAGNUM_EXPORT Framebuffer { /** * @brief Mask stencil writes * - * Set given bit to `0` to disallow writing stencil value to it. - * @see setStencilMask(StencilMaskFace, GLuint) + * Set given bit to `0` to disallow writing stencil value for given + * faces to it. Initial value is all `1`s. + * @see setStencilMask(GLuint) */ - inline static void setStencilMask(GLuint allowBits) { - glStencilMask(allowBits); + inline static void setStencilMask(PolygonFacing facing, GLuint allowBits) { + glStencilMaskSeparate(static_cast(facing), allowBits); } /** * @brief Mask stencil writes * - * Set given bit to `0` to disallow writing stencil value for given - * faces to it. - * @see setStencilMask(GLuint) + * The same as setStencilMask(PolygonFacing, GLuint) with `facing` set + * to `PolygonFacing::FrontAndBack`. */ - inline static void setStencilMask(StencilMaskFace face, GLuint allowBits) { - glStencilMaskSeparate(static_cast(face), allowBits); + inline static void setStencilMask(GLuint allowBits) { + glStencilMask(allowBits); } /*@}*/ From 4d1538c0a9e3c5ea5cfae54595d51a3092ee17e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 14 Aug 2012 01:59:14 +0200 Subject: [PATCH 17/78] Added depth function to Framebuffer. --- src/Framebuffer.h | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index b1d66bff4..2f2bba667 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -204,8 +204,8 @@ class MAGNUM_EXPORT Framebuffer { * @see setStencilFunction() */ enum class StencilFunction: GLenum { - Never = GL_NEVER, /**< Never pass stencil test. */ - Always = GL_ALWAYS, /**< Always pass stencil test. */ + Never = GL_NEVER, /**< Never pass the test. */ + Always = GL_ALWAYS, /**< Always pass the test. */ Less = GL_LESS, /**< Pass when reference value is less than buffer value. */ LessOrEqual = GL_LEQUAL, /**< Pass when reference value is less than or equal to buffer value. */ Equal = GL_EQUAL, /**< Pass when reference value is equal to buffer value. */ @@ -314,6 +314,27 @@ class MAGNUM_EXPORT Framebuffer { /*@}*/ + /** @{ @name Depth testing */ + + /** + * @brief Depth function + * + * @see setDepthFunction() + */ + typedef StencilFunction DepthFunction; + + /** + * @brief Set depth function + * + * Initial value is `DepthFunction::Less`. + * @attention You have to enable depth test with setFeature() first. + */ + inline static void setDepthFunction(DepthFunction function) { + glDepthFunc(static_cast(function)); + } + + /*@}*/ + /** @{ @name Masking writes */ /** From 6baf9581aa0331236f0dfa1362f970ac3ac7afbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 14 Aug 2012 02:00:13 +0200 Subject: [PATCH 18/78] Doc++ --- src/Framebuffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 2f2bba667..149583b54 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -797,7 +797,7 @@ class MAGNUM_EXPORT Framebuffer { * attachTexture1D(Target, DepthStencilAttachment, Texture1D*, GLint), * attachTexture2D(Target, DepthStencilAttachment, Texture2D*, GLint), * attachCubeMapTexture(Target, DepthStencilAttachment, CubeMapTexture*, CubeMapTexture::Coordinate, GLint), - * attachTexture3D(Target, DepthStencilAttachment, Texture3D*, GLint) + * attachTexture3D(Target, DepthStencilAttachment, Texture3D*, GLint, GLint) * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ enum class DepthStencilAttachment: GLenum { From 88d988c7159ea54666161f4c6459970c18d0dfd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 16 Aug 2012 15:57:54 +0200 Subject: [PATCH 19/78] Added Type and Size members to Matrix. --- src/Math/Matrix.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index a3e2609fe..1afc00846 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -41,6 +41,9 @@ template class Matrix { friend class Matrix; /* for ij() */ public: + const static size_t Size = size; /**< @brief %Matrix size */ + typedef T Type; /**< @brief %Matrix data type */ + /** * @brief %Matrix from array * @return Reference to the data as if it was Matrix, thus doesn't From dc6f29bf085c01ebb0a3d9c67403b4244085d1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 15 Aug 2012 16:04:32 +0200 Subject: [PATCH 20/78] Removed old cruft from documentation. --- src/Camera.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Camera.h b/src/Camera.h index 833993e96..3cecda517 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -49,7 +49,7 @@ class MAGNUM_EXPORT Camera: public Object { * @param parent Parent object * * Sets orthographic projection to the default OpenGL cube (range - * @f$ [-1; 1] @f$ in all directions) and clear color to black. + * @f$ [-1; 1] @f$ in all directions). * @see setOrthographic(), setPerspective() */ Camera(Object* parent = nullptr); From fec65aa6f5a0b2a264ae065f8e45d4bed5809a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 16 Aug 2012 17:51:19 +0200 Subject: [PATCH 21/78] Ability to construct Vector from another of different type. --- src/Math/Test/VectorTest.cpp | 11 +++++++++++ src/Math/Test/VectorTest.h | 1 + src/Math/Vector.h | 25 +++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index 41bd037ec..eb9c09d87 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/src/Math/Test/VectorTest.cpp @@ -28,10 +28,12 @@ using namespace Corrade::Utility; namespace Magnum { namespace Math { namespace Test { typedef Vector<4, float> Vector4; +typedef Vector<4, int> Vector4i; typedef Vector<3, float> Vector3; VectorTest::VectorTest() { addTests(&VectorTest::construct, + &VectorTest::constructFrom, &VectorTest::data, &VectorTest::copy, &VectorTest::dot, @@ -56,6 +58,15 @@ void VectorTest::construct() { CORRADE_COMPARE(Vector4::from(data), Vector4(1.0f, 2.0f, 3.0f, 4.0f)); } +void VectorTest::constructFrom() { + Vector4 floatingPoint(1.3f, 2.7f, -15.0f, 7.0f); + Vector4 floatingPointRounded(1.0f, 2.0f, -15.0f, 7.0f); + Vector4i integral(1, 2, -15, 7); + + CORRADE_COMPARE(Vector4i::from(floatingPoint), integral); + CORRADE_COMPARE(Vector4::from(integral), floatingPointRounded); +} + void VectorTest::data() { Vector4 v; v[2] = 1.5f; diff --git a/src/Math/Test/VectorTest.h b/src/Math/Test/VectorTest.h index bbf02d783..29404c289 100644 --- a/src/Math/Test/VectorTest.h +++ b/src/Math/Test/VectorTest.h @@ -24,6 +24,7 @@ class VectorTest: public Corrade::TestSuite::Tester { VectorTest(); void construct(); + void constructFrom(); void data(); void copy(); void dot(); diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 9e7800cdd..e24ac6659 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -27,6 +27,8 @@ namespace Magnum { namespace Math { +template class Vector; + #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { template struct Sequence {}; @@ -38,6 +40,11 @@ namespace Implementation { template struct GenerateSequence<0, sequence...> { typedef Sequence Type; }; + + /* Implementation for Vector::from(const Vector&) */ + template inline constexpr Math::Vector vectorFrom(Sequence, const Math::Vector& vector) { + return {T(vector[sequence])...}; + } } #endif @@ -65,6 +72,21 @@ template class Vector { return *reinterpret_cast*>(data); } + /** + * @brief %Vector from another of different type + * + * Performs only default casting on the values, no rounding or + * anything else. Example usage: + * @code + * Vector<4, float> floatingPoint(1.3f, 2.7f, -15.0f, 7.0f); + * Vector<4, int> integral(Vector<4, int>::from(floatingPoint)); + * // integral == {1, 2, -15, 7} + * @endcode + */ + template inline constexpr static Vector from(const Vector& other) { + return Implementation::vectorFrom(typename Implementation::GenerateSequence::Type(), other); + } + /** * @brief Dot product * @@ -338,6 +360,9 @@ template Corrade::Utility::Debug operator<<(Corrade::Utili } \ inline constexpr static const Type& from(const T* data) { \ return *reinterpret_cast*>(data); \ + } \ + template inline constexpr static Type from(const Vector& other) { \ + return Vector::from(other); \ } \ \ inline Type& operator=(const Type& other) { \ From 26d70e0eaef1343c823b3da0c9b8753cd4d25ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 16 Aug 2012 17:52:54 +0200 Subject: [PATCH 22/78] Added move constructor and move assignment to Mesh. --- src/Mesh.cpp | 25 ++++++++++++++++++++++++- src/Mesh.h | 12 +++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 5bfe0567c..edd0f44bc 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -20,7 +20,16 @@ using namespace std; namespace Magnum { -Mesh::~Mesh() { +Mesh::Mesh(Mesh&& other): + #ifndef MAGNUM_TARGET_GLES + vao(other.vao), + #endif + _primitive(other._primitive), _vertexCount(other._vertexCount), finalized(other.finalized), _buffers(other._buffers), _attributes(other._attributes) +{ + other.vao = 0; +} + +void Mesh::destroy() { for(auto& it: _buffers) delete it.first; @@ -29,6 +38,20 @@ Mesh::~Mesh() { #endif } +Mesh& Mesh::operator=(Mesh&& other) { + destroy(); + + vao = other.vao; + _primitive = other._primitive; + _vertexCount = other._vertexCount; + finalized = other.finalized; + _buffers = other._buffers; + _attributes = other._attributes; + other.vao = 0; + + return *this; +} + Buffer* Mesh::addBuffer(BufferType interleaved) { Buffer* buffer = new Buffer(Buffer::Target::Array); _buffers.insert(make_pair(buffer, make_pair(interleaved, vector()))); diff --git a/src/Mesh.h b/src/Mesh.h index 7985bdd68..10956f569 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -48,9 +48,7 @@ VAOs are used for desktop OpenGL (not in OpenGL ES). */ class MAGNUM_EXPORT Mesh { Mesh(const Mesh& other) = delete; - Mesh(Mesh&& other) = delete; Mesh& operator=(const Mesh& other) = delete; - Mesh& operator=(Mesh&& other) = delete; public: #ifndef MAGNUM_TARGET_GLES @@ -208,12 +206,18 @@ class MAGNUM_EXPORT Mesh { #endif } + /** @brief Move constructor */ + Mesh(Mesh&& other); + /** * @brief Destructor * * Deletes all associated buffers. */ - virtual ~Mesh(); + inline virtual ~Mesh() { destroy(); } + + /** @brief Move assignment */ + Mesh& operator=(Mesh&& other); /** * @brief Whether the mesh is finalized @@ -340,6 +344,8 @@ class MAGNUM_EXPORT Mesh { std::set _attributes; MAGNUM_EXPORT void bindAttribute(Buffer* buffer, GLuint attribute, GLint size, Type type); + + void destroy(); }; } From 125a0fa9d15afa10c839a80116399c757d38edf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 02:02:55 +0200 Subject: [PATCH 23/78] Doc++ --- src/Math/Vector.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Math/Vector.h b/src/Math/Vector.h index e24ac6659..009adc3c3 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -186,16 +186,17 @@ template class Vector { * Note that corresponding operator with swapped type order * (multiplying number with vector) is not available, because it would * cause ambiguity in some cases. + * @see operator*=(U) */ template inline Vector operator*(U number) const { return Vector(*this)*=number; } /** - * @brief Multiply and assign vector + * @brief Multiply vector and assign * - * More efficient than operator*(), because it does the computation - * in-place. + * More efficient than operator*(U) const, because it does the + * computation in-place. */ template Vector& operator*=(U number) { for(size_t i = 0; i != size; ++i) @@ -204,16 +205,20 @@ template class Vector { return *this; } - /** @brief Divide vector */ + /** + * @brief Divide vector + * + * @see operator/=(U) + */ template inline Vector operator/(U number) const { return Vector(*this)/=number; } /** - * @brief Divide and assign vector + * @brief Divide vector and assign * - * More efficient than operator/(), because it does the computation - * in-place. + * More efficient than operator/(U) const, because it does the + * computation in-place. */ template Vector& operator/=(U number) { for(size_t i = 0; i != size; ++i) From a4c80d18ed500d1edce8c842f1f50396a56b4b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 02:03:43 +0200 Subject: [PATCH 24/78] Added component-wise multiplication and division to Vector. --- src/Math/Test/VectorTest.cpp | 10 +++++++ src/Math/Test/VectorTest.h | 1 + src/Math/Vector.h | 58 ++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index eb9c09d87..822355090 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/src/Math/Test/VectorTest.cpp @@ -38,6 +38,7 @@ VectorTest::VectorTest() { &VectorTest::copy, &VectorTest::dot, &VectorTest::multiplyDivide, + &VectorTest::multiplyDivideComponentWise, &VectorTest::addSubtract, &VectorTest::dotSelf, &VectorTest::length, @@ -114,6 +115,15 @@ void VectorTest::multiplyDivide() { CORRADE_COMPARE(multipliedChar/-1.5f, vecChar); } +void VectorTest::multiplyDivideComponentWise() { + Vector4 vec(1.0f, 2.0f, 3.0f, 4.0f); + Vector4 multiplier(7.0f, -4.0f, -1.5f, 1.0f); + Vector4 multiplied(7.0f, -8.0f, -4.5f, 4.0f); + + CORRADE_COMPARE(vec*multiplier, multiplied); + CORRADE_COMPARE(multiplied/multiplier, vec); +} + void VectorTest::addSubtract() { Vector4 a(0.5f, -7.5f, 9.0f, -11.0f); Vector4 b(-0.5, 1.0f, 0.0f, 7.5f); diff --git a/src/Math/Test/VectorTest.h b/src/Math/Test/VectorTest.h index 29404c289..75a9d3cc7 100644 --- a/src/Math/Test/VectorTest.h +++ b/src/Math/Test/VectorTest.h @@ -29,6 +29,7 @@ class VectorTest: public Corrade::TestSuite::Tester { void copy(); void dot(); void multiplyDivide(); + void multiplyDivideComponentWise(); void addSubtract(); void dotSelf(); void length(); diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 009adc3c3..88adce375 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -205,6 +205,28 @@ template class Vector { return *this; } + /** + * @brief Multiply vector component-wise + * + * @see operator*=(const Vector&) + */ + Vector operator*(const Vector& other) const { + return Vector(*this)*=other; + } + + /** + * @brief Multiply vector component-wise and assign + * + * More efficient than operator*(const Vector&) const, + * because it does the computation in-place. + */ + Vector& operator*=(const Vector& other) { + for(size_t i = 0; i != size; ++i) + (*this)[i] *= other[i]; + + return *this; + } + /** * @brief Divide vector * @@ -227,6 +249,28 @@ template class Vector { return *this; } + /** + * @brief Divide vector component-wise + * + * @see operator/=(const Vector&) + */ + Vector operator/(const Vector& other) const { + return Vector(*this)/=other; + } + + /** + * @brief Divide vector component-wise and assign + * + * More efficient than operator/(const Vector&) const, + * because it does the computation in-place. + */ + Vector& operator/=(const Vector& other) { + for(size_t i = 0; i != size; ++i) + (*this)[i] /= other[i]; + + return *this; + } + /** @brief Add two vectors */ inline Vector operator+(const Vector& other) const { return Vector(*this)+=other; @@ -382,12 +426,26 @@ template Corrade::Utility::Debug operator<<(Corrade::Utili Vector::operator*=(number); \ return *this; \ } \ + inline Type operator*(const Vector& other) const { \ + return Vector::operator*(other); \ + } \ + inline Type& operator*=(const Vector& other) { \ + Vector::operator*=(other); \ + return *this; \ + } \ template inline Type operator/(U number) const { \ return Vector::operator/(number); \ } \ template inline Type& operator/=(U number) { \ Vector::operator/=(number); \ return *this; \ + } \ + inline Type operator/(const Vector& other) const { \ + return Vector::operator/(other); \ + } \ + inline Type& operator/=(const Vector& other) { \ + Vector::operator/=(other); \ + return *this; \ } \ \ inline Type operator+(const Vector& other) const { \ From 5157abc439659f0a15a9a0f9b0acd468c75a8517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 02:16:49 +0200 Subject: [PATCH 25/78] Disabled original Vector div/mult for non-arithmetic types. --- src/Math/Vector.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 88adce375..c4569f485 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -188,7 +188,11 @@ template class Vector { * cause ambiguity in some cases. * @see operator*=(U) */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template inline typename std::enable_if::value, Vector>::type operator*(U number) const { + #else template inline Vector operator*(U number) const { + #endif return Vector(*this)*=number; } @@ -198,7 +202,11 @@ template class Vector { * More efficient than operator*(U) const, because it does the * computation in-place. */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template typename std::enable_if::value, Vector&>::type operator*=(U number) { + #else template Vector& operator*=(U number) { + #endif for(size_t i = 0; i != size; ++i) (*this)[i] *= number; @@ -232,7 +240,11 @@ template class Vector { * * @see operator/=(U) */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template inline typename std::enable_if::value, Vector>::type operator/(U number) const { + #else template inline Vector operator/(U number) const { + #endif return Vector(*this)/=number; } @@ -242,7 +254,11 @@ template class Vector { * More efficient than operator/(U) const, because it does the * computation in-place. */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template typename std::enable_if::value, Vector&>::type operator/=(U number) { + #else template Vector& operator/=(U number) { + #endif for(size_t i = 0; i != size; ++i) (*this)[i] /= number; From 0e081388065253642a4a6d182e8d834bcccb4b14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 11:26:51 +0200 Subject: [PATCH 26/78] Added number*Vector and number/Vector operators. --- src/Math/Test/VectorTest.cpp | 8 ++++++ src/Math/Vector.h | 51 ++++++++++++++++++++++++++++++++---- src/Math/Vector2.h | 2 ++ src/Math/Vector3.h | 2 ++ src/Math/Vector4.h | 2 ++ 5 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index 822355090..93f14bef3 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/src/Math/Test/VectorTest.cpp @@ -107,12 +107,20 @@ void VectorTest::multiplyDivide() { Vector4 multiplied(-1.5f, -3.0f, -4.5f, -6.0f); CORRADE_COMPARE(vec*-1.5f, multiplied); + CORRADE_COMPARE(-1.5f*vec, multiplied); CORRADE_COMPARE(multiplied/-1.5f, vec); Math::Vector<1, char> vecChar(32); Math::Vector<1, char> multipliedChar(-48); CORRADE_COMPARE(vecChar*-1.5f, multipliedChar); CORRADE_COMPARE(multipliedChar/-1.5f, vecChar); + CORRADE_COMPARE(-1.5f*vecChar, multipliedChar); + + /* Divide vector with number and inverse */ + Vector4 divisor(1.0f, 2.0f, -4.0f, 8.0f); + Vector4 result(1.0f, 0.5f, -0.25f, 0.125f); + CORRADE_COMPARE(1.0f/divisor, result); + CORRADE_COMPARE(-1550.0f/multipliedChar, vecChar); } void VectorTest::multiplyDivideComponentWise() { diff --git a/src/Math/Vector.h b/src/Math/Vector.h index c4569f485..6121ab144 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -183,10 +183,7 @@ template class Vector { /** * @brief Multiply vector * - * Note that corresponding operator with swapped type order - * (multiplying number with vector) is not available, because it would - * cause ambiguity in some cases. - * @see operator*=(U) + * @see operator*=(U), operator*(U, const Vector&) */ #ifndef DOXYGEN_GENERATING_OUTPUT template inline typename std::enable_if::value, Vector>::type operator*(U number) const { @@ -238,7 +235,7 @@ template class Vector { /** * @brief Divide vector * - * @see operator/=(U) + * @see operator/=(U), operator/(U, const Vector&) */ #ifndef DOXYGEN_GENERATING_OUTPUT template inline typename std::enable_if::value, Vector>::type operator/(U number) const { @@ -405,6 +402,42 @@ template class Vector { T _data[size]; }; +/** @relates Vector +@brief Multiply number with vector + +@see Vector::operator*(U) const +*/ +#ifndef DOXYGEN_GENERATING_OUTPUT +template inline typename std::enable_if::value, Vector>::type operator*(U number, const Vector& vector) { +#else +template inline Vector operator*(U number, const Vector& vector) { +#endif + return vector*number; +} + +/** @relates Vector +@brief Divide vector with number and invert + +Example: +@code +Vector<4, float> vec(1.0f, 2.0f, -4.0f, 8.0f); +Vector<4, float> another = 1.0f/vec; // {1.0f, 0.5f, -0.25f, 0.128f} +@endcode +@see Vector::operator/(U) const +*/ +#ifndef DOXYGEN_GENERATING_OUTPUT +template typename std::enable_if::value, Vector>::type operator/(U number, const Vector& vector) { +#else +template Vector operator/(U number, const Vector& vector) { +#endif + Vector out; + + for(size_t i = 0; i != size; ++i) + out[i] = number/vector[i]; + + return out; +} + /** @debugoperator{Vector} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector& value) { debug << "Vector("; @@ -481,6 +514,14 @@ template Corrade::Utility::Debug operator<<(Corrade::Utili \ inline Type operator-() const { return Vector::operator-(); } \ inline Type normalized() const { return Vector::normalized(); } + +#define MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Type, size) \ + template inline Type operator*(U number, const Type& vector) { \ + return number*Vector(vector); \ + } \ + template inline Type operator/(U number, const Type& vector) { \ + return number/Vector(vector); \ + } #endif }} diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 5920261c4..262fe58c8 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -48,6 +48,8 @@ template class Vector2: public Vector<2, T> { MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector2, 2) }; +MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Vector2, 2) + /** @debugoperator{Vector2} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector2& value) { return debug << static_cast&>(value); diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index d70e6dc08..29edd6df7 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -92,6 +92,8 @@ template class Vector3: public Vector<3, T> { MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector3, 3) }; +MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Vector3, 3) + /** @debugoperator{Vector3} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector3& value) { return debug << static_cast&>(value); diff --git a/src/Math/Vector4.h b/src/Math/Vector4.h index 32d4f3c51..88fb0f5d8 100644 --- a/src/Math/Vector4.h +++ b/src/Math/Vector4.h @@ -86,6 +86,8 @@ template class Vector4: public Vector<4, T> { MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector4, 4) }; +MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Vector4, 4) + /** @debugoperator{Vector4} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector4& value) { return debug << static_cast&>(value); From 8dbae4f09ca74fbd6e235da7d4beeebab82e5c2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 11:27:25 +0200 Subject: [PATCH 27/78] Added @todo. --- src/Math/Vector.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 6121ab144..29413e124 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -49,6 +49,7 @@ namespace Implementation { #endif /** @brief %Vector */ +/** @todo Constexprize all for loops */ template class Vector { static_assert(size != 0, "Vector cannot have zero elements"); From 9d750179cdfafc97bd63724a1356ef804721d88d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 10:58:05 +0200 Subject: [PATCH 28/78] Swapped template parameters in Vector/Matrix debug operator. Forgotten in cc1f9c60c9f63213f1de1a3b4ba0e62a2be65c7c, swapped them to make things consistent. --- src/Math/Matrix.h | 2 +- src/Math/Vector.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index 1afc00846..d1ca9b4a2 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -256,7 +256,7 @@ template class Matrix { }; /** @debugoperator{Matrix} */ -template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Matrix& value) { +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Matrix& value) { debug << "Matrix("; debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false); for(size_t row = 0; row != size; ++row) { diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 29413e124..a2714007c 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -440,7 +440,7 @@ template Vector operator/(U number, cons } /** @debugoperator{Vector} */ -template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector& value) { +template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector& value) { debug << "Vector("; debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false); for(size_t i = 0; i != size; ++i) { From 3744d247d2be63ecf9a4cb1b1edbaeb8e3c251ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 11:51:54 +0200 Subject: [PATCH 29/78] Adapted to Corrade changes. --- src/Framebuffer.h | 6 +++--- src/Trade/AbstractImporter.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 149583b54..7e6b16772 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -19,7 +19,7 @@ * @brief Class Magnum::Framebuffer */ -#include +#include #include "BufferedImage.h" #include "CubeMapTexture.h" @@ -111,7 +111,7 @@ class MAGNUM_EXPORT Framebuffer { Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil value */ }; - typedef Corrade::Utility::Set ClearMask; /**< @brief Mask for clearing */ + typedef Corrade::Containers::Set ClearMask; /**< @brief Mask for clearing */ /** * @brief Clear framebuffer @@ -1011,7 +1011,7 @@ class MAGNUM_EXPORT Framebuffer { * @requires_gl * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ - typedef Corrade::Utility::Set BlitMask; + typedef Corrade::Containers::Set BlitMask; /** * @brief Copy block of pixels from read to draw framebuffer diff --git a/src/Trade/AbstractImporter.h b/src/Trade/AbstractImporter.h index 03f3d0729..f978f6e94 100644 --- a/src/Trade/AbstractImporter.h +++ b/src/Trade/AbstractImporter.h @@ -19,7 +19,7 @@ * @brief Class Magnum::Trade::AbstractImporter */ -#include +#include #include #include "ImageData.h" @@ -65,7 +65,7 @@ class MAGNUM_EXPORT AbstractImporter: public Corrade::PluginManager::Plugin { }; /** @brief Set of features supported by this importer */ - typedef Corrade::Utility::Set Features; + typedef Corrade::Containers::Set Features; /** @brief Constructor */ inline AbstractImporter(Corrade::PluginManager::AbstractPluginManager* manager = nullptr, const std::string& plugin = ""): Plugin(manager, plugin) {} From e3ee7b487bad8e2dd12f6ae609deb8764e1f07de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 14 Aug 2012 03:42:43 +0200 Subject: [PATCH 30/78] Moved Object, Scene and Light to separate SceneGraph library. --- CMakeLists.txt | 2 + doc/mainpage.dox | 4 +- doc/namespaces.dox | 13 ++++++- modules/FindMagnum.cmake | 6 +++ src/CMakeLists.txt | 20 +++------- src/SceneGraph/CMakeLists.txt | 42 +++++++++++++++++++++ src/{ => SceneGraph}/Camera.cpp | 4 +- src/{ => SceneGraph}/Camera.h | 14 +++---- src/{ => SceneGraph}/Light.cpp | 4 +- src/{ => SceneGraph}/Light.h | 12 +++--- src/{ => SceneGraph}/Object.cpp | 5 ++- src/{ => SceneGraph}/Object.h | 15 ++++---- src/{ => SceneGraph}/Scene.h | 12 +++--- src/SceneGraph/Test/CMakeLists.txt | 3 ++ src/{ => SceneGraph}/Test/CameraTest.cpp | 9 ++--- src/{ => SceneGraph}/Test/CameraTest.h | 8 ++-- src/{ => SceneGraph}/Test/ObjectTest.cpp | 10 ++--- src/{ => SceneGraph}/Test/ObjectTest.h | 10 ++--- src/{ => SceneGraph}/Test/SceneTest.cpp | 8 ++-- src/{ => SceneGraph}/Test/SceneTest.h | 8 ++-- src/SceneGraph/magnumSceneGraphVisibility.h | 30 +++++++++++++++ src/Test/CMakeLists.txt | 4 -- 22 files changed, 162 insertions(+), 81 deletions(-) create mode 100644 src/SceneGraph/CMakeLists.txt rename src/{ => SceneGraph}/Camera.cpp (98%) rename src/{ => SceneGraph}/Camera.h (94%) rename src/{ => SceneGraph}/Light.cpp (94%) rename src/{ => SceneGraph}/Light.h (86%) rename src/{ => SceneGraph}/Object.cpp (98%) rename src/{ => SceneGraph}/Object.h (97%) rename src/{ => SceneGraph}/Scene.h (86%) create mode 100644 src/SceneGraph/Test/CMakeLists.txt rename src/{ => SceneGraph}/Test/CameraTest.cpp (90%) rename src/{ => SceneGraph}/Test/CameraTest.h (83%) rename src/{ => SceneGraph}/Test/ObjectTest.cpp (97%) rename src/{ => SceneGraph}/Test/ObjectTest.h (88%) rename src/{ => SceneGraph}/Test/SceneTest.cpp (89%) rename src/{ => SceneGraph}/Test/SceneTest.h (83%) create mode 100644 src/SceneGraph/magnumSceneGraphVisibility.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a95d0d81..990245bcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,7 @@ option(WITH_EVERYTHING "Build everything (doesn't include contexts)" ON) option(WITH_MESHTOOLS "Build MeshTools library" OFF) option(WITH_PHYSICS "Build Physics library" OFF) option(WITH_PRIMITIVES "Builf Primitives library" OFF) +option(WITH_SCENEGRAPH "Build SceneGraph library" OFF) option(WITH_SHADERS "Build Shaders library" OFF) cmake_dependent_option(WITH_EGLCONTEXT "Build EglContext library" OFF "TARGET_GLES" OFF) @@ -23,6 +24,7 @@ if(WITH_EVERYTHING) set(WITH_MESHTOOLS ON) set(WITH_PHYSICS ON) set(WITH_PRIMITIVES ON) + set(WITH_SCENEGRAPH ON) set(WITH_SHADERS ON) endif() diff --git a/doc/mainpage.dox b/doc/mainpage.dox index 3e369b994..8071252ee 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -6,8 +6,8 @@ Features: - Easy-to-use templated @ref Math "mathematical library" for matrix/vector calculations and @ref Math::Geometry "geometry". -- Hierarchical @ref Object "scene graph" which supports transformation caching - for better performance, classes for convenient usage of +- Hierarchical @ref SceneGraph "scene graph" which supports transformation + caching for better performance, classes for convenient usage of @ref AbstractShaderProgram "shaders", @ref Buffer "buffers" and @ref AbstractTexture "textures". Access to @ref Framebuffer "framebuffer" and @ref AbstractQuery "occlusion queries". diff --git a/doc/namespaces.dox b/doc/namespaces.dox index 1905ab375..5f9427928 100644 --- a/doc/namespaces.dox +++ b/doc/namespaces.dox @@ -7,8 +7,7 @@ /** @namespace Magnum @brief Root namespace -Contains classes needed for building meshes, setting up and rendering the -scene. +Contains classes for interacting with OpenGL. */ /** @dir Contexts @@ -58,6 +57,16 @@ Tools for generating, optimizing and cleaning meshes. Basic primitives for testing purposes. */ +/** @dir SceneGraph + * @brief Namespace Magnum::SceneGraph + */ +/** +@namespace Magnum::SceneGraph +@brief %Scene graph library + +Setting up and rendering the scene. +*/ + /** @dir Shaders * @brief Namespace Magnum::Shaders */ diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 09a41585c..778b7b77d 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -18,6 +18,7 @@ # MeshTools - MeshTools library # Physics - Physics library # Primitives - Library with stock geometric primitives (static) +# SceneGraph - Scene graph library # Shaders - Library with stock shaders # EglContext - EGL context (depends on EGL and X11 libraries) # GlutContext - GLUT context (depends on GLUT library) @@ -137,6 +138,11 @@ foreach(component ${Magnum_FIND_COMPONENTS}) set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES Cube.h) endif() + # Scene graph library + if(${component} STREQUAL SceneGraph) + set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES Scene.h) + endif() + # Shaders library if(${component} STREQUAL Shaders) set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES PhongShader.h) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a3639825c..5673b8e00 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,10 +19,8 @@ set(Magnum_SRCS AbstractTexture.cpp AbstractShaderProgram.cpp BufferedTexture.cpp - Camera.cpp Framebuffer.cpp IndexedMesh.cpp - Light.cpp Mesh.cpp Query.cpp Renderbuffer.cpp @@ -39,7 +37,6 @@ set(Magnum_HEADERS BufferedImage.h BufferedTexture.h Buffer.h - Camera.h Color.h CubeMapTextureArray.h CubeMapTexture.h @@ -47,13 +44,10 @@ set(Magnum_HEADERS Image.h ImageWrapper.h IndexedMesh.h - Light.h Magnum.h Mesh.h - Object.h Query.h Renderbuffer.h - Scene.h Shader.h SizeTraits.h Swizzle.h @@ -68,10 +62,6 @@ set(MagnumMath_SRCS Math/Math.cpp) add_library(MagnumMathObjects OBJECT ${MagnumMath_SRCS}) -# Files compiled with different flags for main library and unit test library -set(Magnum_GracefulAssert_SRCS - Object.cpp) - # Set shared library flags for the objects, as they will be part of shared lib # TODO: fix when CMake sets target_EXPORTS for OBJECT targets as well set_target_properties(MagnumObjects MagnumMathObjects PROPERTIES COMPILE_FLAGS "-DMagnumObjects_EXPORTS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") @@ -79,8 +69,7 @@ set_target_properties(MagnumObjects MagnumMathObjects PROPERTIES COMPILE_FLAGS " # Main library add_library(Magnum SHARED $ - $ - ${Magnum_GracefulAssert_SRCS}) + $) target_link_libraries(Magnum ${CORRADE_UTILITY_LIBRARY} ${CORRADE_PLUGINMANAGER_LIBRARY}) if(NOT TARGET_GLES) target_link_libraries(Magnum ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARY}) @@ -110,6 +99,10 @@ if(WITH_PRIMITIVES) add_subdirectory(Primitives) endif() +if(WITH_SCENEGRAPH) + add_subdirectory(SceneGraph) +endif() + if(WITH_SHADERS) add_subdirectory(Shaders) endif() @@ -119,8 +112,7 @@ if(BUILD_TESTS) # Library with graceful assert for testing add_library(MagnumTestLib SHARED - $ - ${Magnum_GracefulAssert_SRCS}) + $) set_target_properties(MagnumTestLib PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) target_link_libraries(MagnumTestLib ${CORRADE_UTILITY_LIBRARY} ${CORRADE_PLUGINMANAGER_LIBRARY}) if(NOT TARGET_GLES) diff --git a/src/SceneGraph/CMakeLists.txt b/src/SceneGraph/CMakeLists.txt new file mode 100644 index 000000000..dd8f5bee3 --- /dev/null +++ b/src/SceneGraph/CMakeLists.txt @@ -0,0 +1,42 @@ +# Files shared between main library and unit test library +set(MagnumSceneGraph_SRCS + Camera.cpp + Light.cpp) +set(MagnumSceneGraph_HEADERS + Camera.h + Light.h + Object.h + Scene.h + + magnumSceneGraphVisibility.h) +add_library(MagnumSceneGraphObjects OBJECT ${MagnumSceneGraph_SRCS}) + +# Files compiled with different flags for main library and unit test library +set(MagnumSceneGraph_GracefulAssert_SRCS + Object.cpp) + +# Set shared library flags for the objects, as they will be part of shared lib +# TODO: fix when CMake sets target_EXPORTS for OBJECT targets as well +set_target_properties(MagnumSceneGraphObjects PROPERTIES COMPILE_FLAGS "-DMagnumSceneGraphObjects_EXPORTS ${CMAKE_SHARED_LIBRARY_CXX_FLAGS}") + +# SceneGraph library +add_library(MagnumSceneGraph SHARED + $ + ${MagnumSceneGraph_GracefulAssert_SRCS}) +target_link_libraries(MagnumSceneGraph Magnum) + +install(TARGETS MagnumSceneGraph DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +install(FILES ${MagnumSceneGraph_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/SceneGraph) + +if(BUILD_TESTS) + enable_testing() + + # Library with graceful assert for testing + add_library(MagnumSceneGraphTestLib SHARED + $ + ${MagnumSceneGraph_GracefulAssert_SRCS}) + set_target_properties(MagnumSceneGraphTestLib PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT) + target_link_libraries(MagnumSceneGraphTestLib Magnum) + + add_subdirectory(Test) +endif() diff --git a/src/Camera.cpp b/src/SceneGraph/Camera.cpp similarity index 98% rename from src/Camera.cpp rename to src/SceneGraph/Camera.cpp index f15454a27..d05ff63f1 100644 --- a/src/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -19,7 +19,7 @@ using namespace std; -namespace Magnum { +namespace Magnum { namespace SceneGraph { Camera::Camera(Object* parent): Object(parent), _aspectRatioPolicy(AspectRatioPolicy::Extend) {} @@ -122,4 +122,4 @@ void Camera::drawChildren(Object* object, const Matrix4& transformationMatrix) { } } -} +}} diff --git a/src/Camera.h b/src/SceneGraph/Camera.h similarity index 94% rename from src/Camera.h rename to src/SceneGraph/Camera.h index 3cecda517..47be24edb 100644 --- a/src/Camera.h +++ b/src/SceneGraph/Camera.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Camera_h -#define Magnum_Camera_h +#ifndef Magnum_SceneGraph_Camera_h +#define Magnum_SceneGraph_Camera_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -16,7 +16,7 @@ */ /** @file - * @brief Class Magnum::Camera + * @brief Class Magnum::SceneGraph::Camera */ #include "Object.h" @@ -26,12 +26,12 @@ #undef far #endif -namespace Magnum { +namespace Magnum { namespace SceneGraph { /** @ingroup scene @brief %Camera object */ -class MAGNUM_EXPORT Camera: public Object { +class SCENEGRAPH_EXPORT Camera: public Object { public: /** * @brief Aspect ratio policy @@ -148,9 +148,9 @@ class MAGNUM_EXPORT Camera: public Object { Math::Vector2 _viewport; AspectRatioPolicy _aspectRatioPolicy; - MAGNUM_LOCAL void fixAspectRatio(); + SCENEGRAPH_LOCAL void fixAspectRatio(); }; -} +}} #endif diff --git a/src/Light.cpp b/src/SceneGraph/Light.cpp similarity index 94% rename from src/Light.cpp rename to src/SceneGraph/Light.cpp index 9c12bfff2..9b5eb5860 100644 --- a/src/Light.cpp +++ b/src/SceneGraph/Light.cpp @@ -15,7 +15,7 @@ #include "Light.h" -namespace Magnum { +namespace Magnum { namespace SceneGraph { void Light::clean(const Matrix4& absoluteTransformation) { Object::clean(absoluteTransformation); @@ -23,4 +23,4 @@ void Light::clean(const Matrix4& absoluteTransformation) { _position = absoluteTransformation[3]; } -} +}} diff --git a/src/Light.h b/src/SceneGraph/Light.h similarity index 86% rename from src/Light.h rename to src/SceneGraph/Light.h index 1675753f4..8a902b699 100644 --- a/src/Light.h +++ b/src/SceneGraph/Light.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Light_h -#define Magnum_Light_h +#ifndef Magnum_SceneGraph_Light_h +#define Magnum_SceneGraph_Light_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -16,19 +16,19 @@ */ /** @file - * @brief Class Magnum::Light + * @brief Class Magnum::SceneGraph::Light */ #include "Object.h" -namespace Magnum { +namespace Magnum { namespace SceneGraph { /** @ingroup scene * @brief Basic light object * * Provides cached light position. */ -class MAGNUM_EXPORT Light: public Object { +class SCENEGRAPH_EXPORT Light: public Object { public: /** * @brief Constructor @@ -54,6 +54,6 @@ class MAGNUM_EXPORT Light: public Object { Vector4 _position; }; -} +}} #endif diff --git a/src/Object.cpp b/src/SceneGraph/Object.cpp similarity index 98% rename from src/Object.cpp rename to src/SceneGraph/Object.cpp index 66614f7ed..5ee2d06a6 100644 --- a/src/Object.cpp +++ b/src/SceneGraph/Object.cpp @@ -16,12 +16,13 @@ #include "Object.h" #include + #include "Scene.h" #include "Camera.h" using namespace std; -namespace Magnum { +namespace Magnum { namespace SceneGraph { Object* Object::setParent(Object* parent) { /* Skip if nothing to do or this is scene */ @@ -149,4 +150,4 @@ void Object::setClean() { } } -} +}} diff --git a/src/Object.h b/src/SceneGraph/Object.h similarity index 97% rename from src/Object.h rename to src/SceneGraph/Object.h index d4df67530..66280e729 100644 --- a/src/Object.h +++ b/src/SceneGraph/Object.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Object_h -#define Magnum_Object_h +#ifndef Magnum_SceneGraph_Object_h +#define Magnum_SceneGraph_Object_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -16,14 +16,16 @@ */ /** @file - * @brief Class Magnum::Object + * @brief Class Magnum::SceneGraph::Object */ #include #include "Magnum.h" -namespace Magnum { +#include "magnumSceneGraphVisibility.h" + +namespace Magnum { namespace SceneGraph { class Scene; class Camera; @@ -44,7 +46,7 @@ class Camera; * @todo Transform transformation when changing parent, so the object stays in * place. */ -class MAGNUM_EXPORT Object { +class SCENEGRAPH_EXPORT Object { Object(const Object& other) = delete; Object(Object&& other) = delete; Object& operator=(const Object& other) = delete; @@ -268,7 +270,6 @@ class MAGNUM_EXPORT Object { inline void Object::draw(const Matrix4&, Camera*) {} inline void Object::clean(const Matrix4&) { dirty = false; } - -} +}} #endif diff --git a/src/Scene.h b/src/SceneGraph/Scene.h similarity index 86% rename from src/Scene.h rename to src/SceneGraph/Scene.h index 076e6f4ef..13b504ee4 100644 --- a/src/Scene.h +++ b/src/SceneGraph/Scene.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Scene_h -#define Magnum_Scene_h +#ifndef Magnum_SceneGraph_Scene_h +#define Magnum_SceneGraph_Scene_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -16,17 +16,17 @@ */ /** @file - * @brief Class Magnum::Scene + * @brief Class Magnum::SceneGraph::Scene */ #include "Object.h" -namespace Magnum { +namespace Magnum { namespace SceneGraph { /** @ingroup scene @brief %Scene */ -class MAGNUM_EXPORT Scene: public Object { +class SCENEGRAPH_EXPORT Scene: public Object { public: /** @brief Constructor */ inline Scene() { _parent = this; } @@ -42,6 +42,6 @@ class MAGNUM_EXPORT Scene: public Object { inline void draw(const Magnum::Matrix4&, Camera*) {} }; -} +}} #endif diff --git a/src/SceneGraph/Test/CMakeLists.txt b/src/SceneGraph/Test/CMakeLists.txt new file mode 100644 index 000000000..e0db0910d --- /dev/null +++ b/src/SceneGraph/Test/CMakeLists.txt @@ -0,0 +1,3 @@ +corrade_add_test2(SceneGraphObjectTest ObjectTest.cpp LIBRARIES MagnumSceneGraphTestLib) +corrade_add_test2(SceneGraphCameraTest CameraTest.cpp LIBRARIES MagnumSceneGraph) +corrade_add_test2(SceneGraphSceneTest SceneTest.cpp LIBRARIES MagnumSceneGraph) diff --git a/src/Test/CameraTest.cpp b/src/SceneGraph/Test/CameraTest.cpp similarity index 90% rename from src/Test/CameraTest.cpp rename to src/SceneGraph/Test/CameraTest.cpp index 4211d0235..508705b43 100644 --- a/src/Test/CameraTest.cpp +++ b/src/SceneGraph/Test/CameraTest.cpp @@ -15,12 +15,11 @@ #include "CameraTest.h" -#include "Camera.h" -#include "Scene.h" +#include "SceneGraph/Camera.h" -CORRADE_TEST_MAIN(Magnum::Test::CameraTest) +CORRADE_TEST_MAIN(Magnum::SceneGraph::Test::CameraTest) -namespace Magnum { namespace Test { +namespace Magnum { namespace SceneGraph { namespace Test { CameraTest::CameraTest() { addTests(&CameraTest::orthographic, @@ -51,4 +50,4 @@ void CameraTest::perspective() { CORRADE_COMPARE(camera.projectionMatrix(), a); } -}} +}}} diff --git a/src/Test/CameraTest.h b/src/SceneGraph/Test/CameraTest.h similarity index 83% rename from src/Test/CameraTest.h rename to src/SceneGraph/Test/CameraTest.h index 9f5424647..ec9a699b0 100644 --- a/src/Test/CameraTest.h +++ b/src/SceneGraph/Test/CameraTest.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Test_CameraTest_h -#define Magnum_Test_CameraTest_h +#ifndef Magnum_SceneGraph_Test_CameraTest_h +#define Magnum_SceneGraph_Test_CameraTest_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -17,7 +17,7 @@ #include -namespace Magnum { namespace Test { +namespace Magnum { namespace SceneGraph { namespace Test { class CameraTest: public Corrade::TestSuite::Tester { public: @@ -27,6 +27,6 @@ class CameraTest: public Corrade::TestSuite::Tester { void perspective(); }; -}} +}}} #endif diff --git a/src/Test/ObjectTest.cpp b/src/SceneGraph/Test/ObjectTest.cpp similarity index 97% rename from src/Test/ObjectTest.cpp rename to src/SceneGraph/Test/ObjectTest.cpp index 9e9f30a72..5a4f22a6e 100644 --- a/src/Test/ObjectTest.cpp +++ b/src/SceneGraph/Test/ObjectTest.cpp @@ -14,16 +14,16 @@ */ #include "ObjectTest.h" -#include "Scene.h" -#include "Camera.h" +#include "SceneGraph/Camera.h" +#include "SceneGraph/Scene.h" #include using namespace std; -CORRADE_TEST_MAIN(Magnum::Test::ObjectTest) +CORRADE_TEST_MAIN(Magnum::SceneGraph::Test::ObjectTest) -namespace Magnum { namespace Test { +namespace Magnum { namespace SceneGraph { namespace Test { ObjectTest::ObjectTest() { addTests(&ObjectTest::parenting, @@ -195,4 +195,4 @@ void ObjectTest::dirty() { CORRADE_VERIFY(childThree->isDirty()); } -}} +}}} diff --git a/src/Test/ObjectTest.h b/src/SceneGraph/Test/ObjectTest.h similarity index 88% rename from src/Test/ObjectTest.h rename to src/SceneGraph/Test/ObjectTest.h index da48eabab..8505bd59e 100644 --- a/src/Test/ObjectTest.h +++ b/src/SceneGraph/Test/ObjectTest.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Test_ObjectTest_h -#define Magnum_Test_ObjectTest_h +#ifndef Magnum_SceneGraph_Test_ObjectTest_h +#define Magnum_SceneGraph_Test_ObjectTest_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -17,9 +17,9 @@ #include -#include "Object.h" +#include "SceneGraph/Object.h" -namespace Magnum { namespace Test { +namespace Magnum { namespace SceneGraph { namespace Test { class ObjectTest: public Corrade::TestSuite::Tester { public: @@ -46,6 +46,6 @@ class ObjectTest: public Corrade::TestSuite::Tester { }; }; -}} +}}} #endif diff --git a/src/Test/SceneTest.cpp b/src/SceneGraph/Test/SceneTest.cpp similarity index 89% rename from src/Test/SceneTest.cpp rename to src/SceneGraph/Test/SceneTest.cpp index ac05d18e8..132c09e0b 100644 --- a/src/Test/SceneTest.cpp +++ b/src/SceneGraph/Test/SceneTest.cpp @@ -15,11 +15,11 @@ #include "SceneTest.h" -#include "Scene.h" +#include "SceneGraph/Scene.h" -CORRADE_TEST_MAIN(Magnum::Test::SceneTest) +CORRADE_TEST_MAIN(Magnum::SceneGraph::Test::SceneTest) -namespace Magnum { namespace Test { +namespace Magnum { namespace SceneGraph { namespace Test { SceneTest::SceneTest() { addTests(&SceneTest::transformation, @@ -48,4 +48,4 @@ void SceneTest::parent() { CORRADE_VERIFY(object.children().empty()); } -}} +}}} diff --git a/src/Test/SceneTest.h b/src/SceneGraph/Test/SceneTest.h similarity index 83% rename from src/Test/SceneTest.h rename to src/SceneGraph/Test/SceneTest.h index 77af6179d..6d1af5c9b 100644 --- a/src/Test/SceneTest.h +++ b/src/SceneGraph/Test/SceneTest.h @@ -1,5 +1,5 @@ -#ifndef Magnum_Test_SceneTest_h -#define Magnum_Test_SceneTest_h +#ifndef Magnum_SceneGraph_Test_SceneTest_h +#define Magnum_SceneGraph_Test_SceneTest_h /* Copyright © 2010, 2011, 2012 Vladimír Vondruš @@ -17,7 +17,7 @@ #include -namespace Magnum { namespace Test { +namespace Magnum { namespace SceneGraph { namespace Test { class SceneTest: public Corrade::TestSuite::Tester { public: @@ -27,6 +27,6 @@ class SceneTest: public Corrade::TestSuite::Tester { void parent(); }; -}} +}}} #endif diff --git a/src/SceneGraph/magnumSceneGraphVisibility.h b/src/SceneGraph/magnumSceneGraphVisibility.h new file mode 100644 index 000000000..2e1c2e758 --- /dev/null +++ b/src/SceneGraph/magnumSceneGraphVisibility.h @@ -0,0 +1,30 @@ +#ifndef Magnum_SceneGraph_magnumSceneGraphVisibility_h +#define Magnum_SceneGraph_magnumSceneGraphVisibility_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. +*/ + +#ifdef _WIN32 + #if defined(MagnumSceneGraph_EXPORTS) || defined(MagnumSceneGraphObjects_EXPORTS) + #define SCENEGRAPH_EXPORT __declspec(dllexport) + #else + #define SCENEGRAPH_EXPORT __declspec(dllimport) + #endif + #define SCENEGRAPH_LOCAL +#else + #define SCENEGRAPH_EXPORT __attribute__ ((visibility ("default"))) + #define SCENEGRAPH_LOCAL __attribute__ ((visibility ("hidden"))) +#endif + +#endif diff --git a/src/Test/CMakeLists.txt b/src/Test/CMakeLists.txt index 67650069a..f86d239e8 100644 --- a/src/Test/CMakeLists.txt +++ b/src/Test/CMakeLists.txt @@ -1,6 +1,2 @@ -corrade_add_test2(ObjectTest ObjectTest.cpp LIBRARIES MagnumTestLib) -corrade_add_test2(CameraTest CameraTest.cpp LIBRARIES Magnum) -corrade_add_test2(SceneTest SceneTest.cpp LIBRARIES Magnum) - corrade_add_test2(ColorTest ColorTest.cpp) corrade_add_test2(SwizzleTest SwizzleTest.cpp) From c451b223928aba8d7c397b13f9b781a92fb4caae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 14 Aug 2012 03:49:11 +0200 Subject: [PATCH 31/78] Revert "Documentation: organizing the classes into "modules"." It only caused another maintenance burden and was confusing to users. Now when scene graph is in SceneGraph namespace there is no need for another grouping. Namespaces are (and should be) sufficient. This reverts commit 79945ab6fce4bf0b53faab1d2f694f4cd934d562. Conflicts: src/BufferedImage.h src/BufferedTexture.h src/Framebuffer.h src/Query.h src/SceneGraph/Scene.h --- doc/groups.dox | 29 ---------------------------- doc/mainpage.dox | 5 ----- doc/namespaces.dox | 9 +++------ src/AbstractImage.h | 2 +- src/AbstractShaderProgram.h | 2 +- src/AbstractTexture.h | 2 +- src/Buffer.h | 2 +- src/BufferedImage.h | 6 ------ src/BufferedTexture.h | 2 +- src/CubeMapTexture.h | 2 +- src/CubeMapTextureArray.h | 2 +- src/Framebuffer.h | 3 +-- src/Image.h | 6 ------ src/ImageWrapper.h | 6 ------ src/IndexedMesh.h | 2 +- src/Math/MathTypeTraits.h | 2 +- src/Mesh.h | 2 +- src/MeshTools/Clean.h | 2 +- src/MeshTools/CombineIndexedArrays.h | 2 +- src/MeshTools/CompressIndices.h | 6 ------ src/MeshTools/FlipNormals.h | 6 ------ src/MeshTools/GenerateFlatNormals.h | 2 +- src/MeshTools/Interleave.h | 6 ------ src/MeshTools/Subdivide.h | 2 +- src/MeshTools/Tipsify.h | 2 +- src/Primitives/Capsule.h | 2 +- src/Primitives/Cube.h | 4 +--- src/Primitives/Icosphere.h | 4 ++-- src/Primitives/Plane.h | 2 +- src/Primitives/UVSphere.h | 4 +--- src/Query.h | 5 ----- src/Renderbuffer.h | 2 +- src/SceneGraph/Camera.h | 2 +- src/SceneGraph/Light.h | 2 +- src/SceneGraph/Object.h | 2 +- src/SceneGraph/Scene.h | 4 +--- src/Shader.h | 2 +- src/Shaders/PhongShader.h | 2 +- src/SizeTraits.h | 6 ------ src/Texture.h | 6 ------ src/TypeTraits.h | 6 ------ 41 files changed, 32 insertions(+), 135 deletions(-) delete mode 100644 doc/groups.dox diff --git a/doc/groups.dox b/doc/groups.dox deleted file mode 100644 index 22e833e4b..000000000 --- a/doc/groups.dox +++ /dev/null @@ -1,29 +0,0 @@ -namespace Magnum { - -/** @page modules */ - -/** -@defgroup scene Scene graph -@brief %Scene hierarchy, cameras, lights and other objects -*/ - -/** -@defgroup mesh Meshes -@brief Creating, modifying and rendering meshes -*/ - -/** -@defgroup rendering Rendering -@brief %Shader, buffer and mesh management, render queries -*/ - -/** @ingroup rendering -@defgroup textures Textures -@brief Access to OpenGL textures, image data wrappers and framebuffer operations -*/ - -/** -@defgroup utility Utility -@brief Various supporting utility classes -*/ -} diff --git a/doc/mainpage.dox b/doc/mainpage.dox index 8071252ee..093bcf0ce 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -50,11 +50,6 @@ in step-by-step tutorial. Then you can dig deeper and try @ref example-index "other examples", read about fundamental principles in the documentation or start experimenting on your own! -@subsection module-overview Module overview - -Classes in %Magnum are grouped into a few modules for a better orientation. -Check the @ref modules "module index" for more information about all classes. - @subsection getting-started-hacking Hacking Magnum If you want to hack on this engine, if you spotted a bug, need an feature or diff --git a/doc/namespaces.dox b/doc/namespaces.dox index 5f9427928..63587bca1 100644 --- a/doc/namespaces.dox +++ b/doc/namespaces.dox @@ -40,8 +40,7 @@ Functions for computing intersections, distances, areas and volumes. /** @dir MeshTools * @brief Namespace Magnum::MeshTools */ -/** @ingroup mesh -@namespace Magnum::MeshTools +/** @namespace Magnum::MeshTools @brief %Mesh tools Tools for generating, optimizing and cleaning meshes. @@ -50,8 +49,7 @@ Tools for generating, optimizing and cleaning meshes. /** @dir Primitives * @brief Namespace Magnum::Primitives */ -/** @ingroup mesh -@namespace Magnum::Primitives +/** @namespace Magnum::Primitives @brief Primitive library Basic primitives for testing purposes. @@ -70,8 +68,7 @@ Setting up and rendering the scene. /** @dir Shaders * @brief Namespace Magnum::Shaders */ -/** @ingroup rendering -@namespace Magnum::Shaders +/** @namespace Magnum::Shaders @brief Sample shaders Collection of shaders for testing purposes. diff --git a/src/AbstractImage.h b/src/AbstractImage.h index 815371bfe..1a86e4313 100644 --- a/src/AbstractImage.h +++ b/src/AbstractImage.h @@ -23,7 +23,7 @@ namespace Magnum { -/** @ingroup textures +/** @brief Non-templated base for one-, two- or three-dimensional images See Image, BufferedImage, Trade::ImageData documentation for more information. diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index 6b53cd6b6..827d238de 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -25,7 +25,7 @@ namespace Magnum { -/** @ingroup rendering +/** @brief Base class for shaders @section AbstractShaderProgram-subclassing Subclassing workflow diff --git a/src/AbstractTexture.h b/src/AbstractTexture.h index 2e1856e6f..5dd213d17 100644 --- a/src/AbstractTexture.h +++ b/src/AbstractTexture.h @@ -24,7 +24,7 @@ namespace Magnum { -/** @ingroup textures +/** @brief Base for textures @attention Don't forget to call @ref Texture::setWrapping() "setWrapping()", diff --git a/src/Buffer.h b/src/Buffer.h index 940dcaae5..2b7655b9c 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -23,7 +23,7 @@ namespace Magnum { -/** @ingroup rendering +/** @brief Class for managing buffers @todo Support for buffer copying (OpenGL 3.1, @extension{ARB,copy_buffer}) diff --git a/src/BufferedImage.h b/src/BufferedImage.h index c8efa5181..5b91723c5 100644 --- a/src/BufferedImage.h +++ b/src/BufferedImage.h @@ -26,10 +26,6 @@ namespace Magnum { #ifndef MAGNUM_TARGET_GLES -/** @addtogroup textures - * @{ - */ - /** @brief %Buffered image @@ -116,8 +112,6 @@ typedef BufferedImage<2> BufferedImage2D; /** @brief Three-dimensional buffered image */ typedef BufferedImage<3> BufferedImage3D; - -/*@}*/ #endif } diff --git a/src/BufferedTexture.h b/src/BufferedTexture.h index fca8f74fc..12f2b05c0 100644 --- a/src/BufferedTexture.h +++ b/src/BufferedTexture.h @@ -25,7 +25,7 @@ namespace Magnum { #ifndef MAGNUM_TARGET_GLES -/** @ingroup textures +/** @brief Buffered texture This texture is, unlike classic textures such as Texture or CubeMapTexture, diff --git a/src/CubeMapTexture.h b/src/CubeMapTexture.h index 7a8edbdfa..44ae71fce 100644 --- a/src/CubeMapTexture.h +++ b/src/CubeMapTexture.h @@ -23,7 +23,7 @@ namespace Magnum { -/** @ingroup textures +/** @brief Cube map texture %Texture used mainly for environemnt maps. See AbstractTexture documentation diff --git a/src/CubeMapTextureArray.h b/src/CubeMapTextureArray.h index 22d7e1cde..0a1f0ebca 100644 --- a/src/CubeMapTextureArray.h +++ b/src/CubeMapTextureArray.h @@ -23,7 +23,7 @@ namespace Magnum { -/** @ingroup textures +/** @brief Cube map texture array For information about usage, see CubeMapTexture documentation. diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 7e6b16772..b6e98c34b 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -29,8 +29,7 @@ namespace Magnum { -/** @ingroup textures -@nosubgrouping +/** @nosubgrouping @brief %Framebuffer Provides operations with framebuffers (configuring, clearing, blitting...) and diff --git a/src/Image.h b/src/Image.h index 61dcf30a0..7a595786f 100644 --- a/src/Image.h +++ b/src/Image.h @@ -24,10 +24,6 @@ namespace Magnum { -/** @addtogroup textures - * @{ - */ - /** @brief %Image @@ -128,8 +124,6 @@ typedef Image<2> Image2D; /** @brief Three-dimensional image */ typedef Image<3> Image3D; -/*@}*/ - } #endif diff --git a/src/ImageWrapper.h b/src/ImageWrapper.h index fef9a13c0..b4dc0e4e6 100644 --- a/src/ImageWrapper.h +++ b/src/ImageWrapper.h @@ -24,10 +24,6 @@ namespace Magnum { -/** @addtogroup textures - * @{ - */ - /** @brief %Image wrapper @@ -113,8 +109,6 @@ typedef ImageWrapper<2> ImageWrapper2D; /** @brief Three-dimensional image wrapper */ typedef ImageWrapper<3> ImageWrapper3D; -/*@}*/ - } #endif diff --git a/src/IndexedMesh.h b/src/IndexedMesh.h index a400d7f55..7250357b2 100644 --- a/src/IndexedMesh.h +++ b/src/IndexedMesh.h @@ -24,7 +24,7 @@ namespace Magnum { -/** @ingroup rendering mesh +/** * @brief Indexed mesh */ class MAGNUM_EXPORT IndexedMesh: public Mesh { diff --git a/src/Math/MathTypeTraits.h b/src/Math/MathTypeTraits.h index 3208711d0..fb97bb8b6 100644 --- a/src/Math/MathTypeTraits.h +++ b/src/Math/MathTypeTraits.h @@ -33,7 +33,7 @@ namespace Magnum { namespace Math { -/** @ingroup utility +/** @brief Traits class for numeric types Traits classes are usable for detecting type features at compile time without diff --git a/src/Mesh.h b/src/Mesh.h index 10956f569..e75567d8b 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -30,7 +30,7 @@ namespace Magnum { class Buffer; -/** @ingroup rendering mesh +/** @brief Base class for managing non-indexed meshes VAOs are used for desktop OpenGL (not in OpenGL ES). diff --git a/src/MeshTools/Clean.h b/src/MeshTools/Clean.h index a0b4ccade..7f5247d07 100644 --- a/src/MeshTools/Clean.h +++ b/src/MeshTools/Clean.h @@ -119,7 +119,7 @@ template class Clean { } #endif -/** @ingroup mesh +/** @brief %Clean the mesh @tparam Vertex Vertex data type @tparam vertexSize How many initial vertex fields are important (for diff --git a/src/MeshTools/CombineIndexedArrays.h b/src/MeshTools/CombineIndexedArrays.h index d3b272e8d..612e8fce3 100644 --- a/src/MeshTools/CombineIndexedArrays.h +++ b/src/MeshTools/CombineIndexedArrays.h @@ -89,7 +89,7 @@ class CombineIndexedArrays { } #endif -/** @ingroup mesh +/** @brief Combine indexed arrays @param[in,out] indexedArrays Index and attribute arrays @return Array with resulting indices diff --git a/src/MeshTools/CompressIndices.h b/src/MeshTools/CompressIndices.h index bbfe171c9..4a6b2ac48 100644 --- a/src/MeshTools/CompressIndices.h +++ b/src/MeshTools/CompressIndices.h @@ -73,10 +73,6 @@ class CompressIndices { } #endif -/** @addtogroup mesh - * @{ - */ - /** @brief Compress vertex indices @param indices Index array @@ -119,8 +115,6 @@ inline void compressIndices(IndexedMesh* mesh, Buffer::Usage usage, const std::v return Implementation::CompressIndices{indices}(mesh, usage); } -/*@}*/ - }} #endif diff --git a/src/MeshTools/FlipNormals.h b/src/MeshTools/FlipNormals.h index 2c5be2216..191177945 100644 --- a/src/MeshTools/FlipNormals.h +++ b/src/MeshTools/FlipNormals.h @@ -24,10 +24,6 @@ namespace Magnum { namespace MeshTools { -/** @addtogroup mesh - * @{ - */ - /** @brief Flip face winding @@ -61,8 +57,6 @@ inline void flipNormals(std::vector& indices, std::vector flipNormals(normals); } -/*@}*/ - }} #endif diff --git a/src/MeshTools/GenerateFlatNormals.h b/src/MeshTools/GenerateFlatNormals.h index 1af39d95e..a5dfcbb9b 100644 --- a/src/MeshTools/GenerateFlatNormals.h +++ b/src/MeshTools/GenerateFlatNormals.h @@ -26,7 +26,7 @@ namespace Magnum { namespace MeshTools { -/** @ingroup mesh +/** @brief Generate flat normals @param indices Array of triangle face indexes @param vertices Vertex array diff --git a/src/MeshTools/Interleave.h b/src/MeshTools/Interleave.h index aa1de8558..3c7408e52 100644 --- a/src/MeshTools/Interleave.h +++ b/src/MeshTools/Interleave.h @@ -96,10 +96,6 @@ class Interleave { } #endif -/** @addtogroup mesh - * @{ - */ - /** @brief %Interleave vertex attributes @param attribute First attribute array @@ -157,8 +153,6 @@ template inline void interleave(Mesh* mesh, Buffer* buffer, Buffer:: return Implementation::Interleave()(mesh, buffer, usage, attributes...); } -/*@}*/ - }} #endif diff --git a/src/MeshTools/Subdivide.h b/src/MeshTools/Subdivide.h index 7dad9a0b7..ab2c27dc8 100644 --- a/src/MeshTools/Subdivide.h +++ b/src/MeshTools/Subdivide.h @@ -84,7 +84,7 @@ template class Subdivide { } #endif -/** @ingroup mesh +/** @brief %Subdivide the mesh @tparam Vertex Vertex data type @tparam Interpolator See `interpolator` function parameter diff --git a/src/MeshTools/Tipsify.h b/src/MeshTools/Tipsify.h index 58e2425e8..d43f4e926 100644 --- a/src/MeshTools/Tipsify.h +++ b/src/MeshTools/Tipsify.h @@ -51,7 +51,7 @@ class MESHTOOLS_EXPORT Tipsify { } #endif -/** @ingroup mesh +/** @brief %Tipsify the mesh @param[in,out] indices Indices array to operate on @param[in] vertexCount Vertex count diff --git a/src/Primitives/Capsule.h b/src/Primitives/Capsule.h index 79c715231..3923beba1 100644 --- a/src/Primitives/Capsule.h +++ b/src/Primitives/Capsule.h @@ -23,7 +23,7 @@ namespace Magnum { namespace Primitives { -/** @ingroup mesh +/** @brief %Capsule primitive Cylinder along Y axis with hemispheres instead of caps. diff --git a/src/Primitives/Cube.h b/src/Primitives/Cube.h index 0a7864b91..bacc1829c 100644 --- a/src/Primitives/Cube.h +++ b/src/Primitives/Cube.h @@ -23,9 +23,7 @@ namespace Magnum { namespace Primitives { -/** @ingroup mesh -@brief %Cube primitive -*/ +/** @brief %Cube primitive */ class Cube: public Trade::MeshData { public: /** @brief Constructor */ diff --git a/src/Primitives/Icosphere.h b/src/Primitives/Icosphere.h index 7ce808846..5cd011e03 100644 --- a/src/Primitives/Icosphere.h +++ b/src/Primitives/Icosphere.h @@ -27,7 +27,7 @@ namespace Magnum { namespace Primitives { template class Icosphere; -/** @ingroup mesh +/** @brief %Icosphere primitive with zero subdivisions @todo Use own computed (and more precise) icosahedron data, not these stolen @@ -39,7 +39,7 @@ template<> class Icosphere<0>: public Trade::MeshData { Icosphere(); }; -/** @ingroup mesh +/** * @brief %Icosphere primitive * @tparam subdivisions Number of subdivisions */ diff --git a/src/Primitives/Plane.h b/src/Primitives/Plane.h index dffe9ce4e..d21eee942 100644 --- a/src/Primitives/Plane.h +++ b/src/Primitives/Plane.h @@ -23,7 +23,7 @@ namespace Magnum { namespace Primitives { -/** @ingroup mesh +/** @brief %Plane primitive 2x2 plane with normals in positive Z direction. diff --git a/src/Primitives/UVSphere.h b/src/Primitives/UVSphere.h index 6f50caee4..4e6be3b63 100644 --- a/src/Primitives/UVSphere.h +++ b/src/Primitives/UVSphere.h @@ -23,9 +23,7 @@ namespace Magnum { namespace Primitives { -/** @ingroup mesh -@brief UV Sphere primitive -*/ +/** @brief UV Sphere primitive */ class UVSphere: public Capsule { public: /** diff --git a/src/Query.h b/src/Query.h index 38d4d1cf1..32413b2bf 100644 --- a/src/Query.h +++ b/src/Query.h @@ -24,10 +24,6 @@ namespace Magnum { #ifndef MAGNUM_TARGET_GLES -/** @addtogroup rendering - * @{ - */ - /** @brief Base class for queries @@ -301,7 +297,6 @@ class TimeQuery: public AbstractQuery { } }; -/*@}*/ #endif } diff --git a/src/Renderbuffer.h b/src/Renderbuffer.h index 3a9d14145..35854aba3 100644 --- a/src/Renderbuffer.h +++ b/src/Renderbuffer.h @@ -23,7 +23,7 @@ namespace Magnum { -/** @ingroup textures +/** @brief %Renderbuffer Attachable to Framebuffer as render target. diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index 47be24edb..308a0d99a 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -28,7 +28,7 @@ namespace Magnum { namespace SceneGraph { -/** @ingroup scene +/** @brief %Camera object */ class SCENEGRAPH_EXPORT Camera: public Object { diff --git a/src/SceneGraph/Light.h b/src/SceneGraph/Light.h index 8a902b699..57ae9e083 100644 --- a/src/SceneGraph/Light.h +++ b/src/SceneGraph/Light.h @@ -23,7 +23,7 @@ namespace Magnum { namespace SceneGraph { -/** @ingroup scene +/** * @brief Basic light object * * Provides cached light position. diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 66280e729..5ddb2c2f3 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -40,7 +40,7 @@ class Camera; not needed) */ -/** @ingroup scene +/** * @brief Base for all positioned objects * * @todo Transform transformation when changing parent, so the object stays in diff --git a/src/SceneGraph/Scene.h b/src/SceneGraph/Scene.h index 13b504ee4..63cedc905 100644 --- a/src/SceneGraph/Scene.h +++ b/src/SceneGraph/Scene.h @@ -23,9 +23,7 @@ namespace Magnum { namespace SceneGraph { -/** @ingroup scene -@brief %Scene -*/ +/** @brief %Scene */ class SCENEGRAPH_EXPORT Scene: public Object { public: /** @brief Constructor */ diff --git a/src/Shader.h b/src/Shader.h index 4b5639604..cdb19b456 100644 --- a/src/Shader.h +++ b/src/Shader.h @@ -26,7 +26,7 @@ namespace Magnum { -/** @ingroup rendering +/** * @brief %Shader * * Allows loading and compiling the shader from file or directly from source diff --git a/src/Shaders/PhongShader.h b/src/Shaders/PhongShader.h index 119676cc4..ceb79af6b 100644 --- a/src/Shaders/PhongShader.h +++ b/src/Shaders/PhongShader.h @@ -24,7 +24,7 @@ namespace Magnum { namespace Shaders { -/** @ingroup rendering +/** @brief Phong shader @requires_gl33 The shader is written in GLSL 3.3, although it should be trivial diff --git a/src/SizeTraits.h b/src/SizeTraits.h index dfa19ec28..5b156c576 100644 --- a/src/SizeTraits.h +++ b/src/SizeTraits.h @@ -23,10 +23,6 @@ namespace Magnum { -/** @addtogroup utility - * @{ - */ - /** @brief Traits class providing suitable types for given data sizes @tparam byte Highest byte needed (counting from zero) @@ -175,8 +171,6 @@ template struct Log { }; #endif -/*@}*/ - } #endif diff --git a/src/Texture.h b/src/Texture.h index b36bfa049..7bb9e33b3 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -23,10 +23,6 @@ namespace Magnum { -/** @addtogroup textures - * @{ - */ - /** @brief %Texture @@ -189,8 +185,6 @@ typedef Texture<2> Texture2D; typedef Texture<3> Texture3D; #endif -/*@}*/ - } #endif diff --git a/src/TypeTraits.h b/src/TypeTraits.h index 31dd42f93..3e95eec12 100644 --- a/src/TypeTraits.h +++ b/src/TypeTraits.h @@ -23,10 +23,6 @@ namespace Magnum { -/** @addtogroup utility - * @{ - */ - /** @brief Traits class for plain OpenGL types @@ -148,8 +144,6 @@ struct MAGNUM_EXPORT TypeInfo { /** @todo Other texture types, referenced in glTexImage2D function manual */ /** @todo Using Vector3 for textures? */ -/*@}*/ - #ifndef DOXYGEN_GENERATING_OUTPUT template<> struct TypeOf { typedef GLubyte Type; }; template<> struct TypeOf { typedef GLbyte Type; }; From 810c06509a48493f4bd3579484b069f6bb7b684b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 15 Aug 2012 18:57:12 +0200 Subject: [PATCH 32/78] SceneGraph: modifications to allow 2D implementation in future. --- src/SceneGraph/Camera.cpp | 129 +++++++++++++++------------- src/SceneGraph/Camera.h | 133 +++++++++++++++++++---------- src/SceneGraph/Light.h | 4 +- src/SceneGraph/Object.cpp | 54 ++++++------ src/SceneGraph/Object.h | 127 +++++++++++++++------------ src/SceneGraph/Scene.h | 23 +++-- src/SceneGraph/Test/CameraTest.cpp | 4 +- src/SceneGraph/Test/ObjectTest.cpp | 44 +++++----- src/SceneGraph/Test/ObjectTest.h | 6 +- src/SceneGraph/Test/SceneTest.cpp | 10 +-- 10 files changed, 303 insertions(+), 231 deletions(-) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp index d05ff63f1..ad3b794fe 100644 --- a/src/SceneGraph/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -21,9 +21,72 @@ using namespace std; namespace Magnum { namespace SceneGraph { -Camera::Camera(Object* parent): Object(parent), _aspectRatioPolicy(AspectRatioPolicy::Extend) {} +#ifndef DOXYGEN_GENERATING_OUTPUT +namespace Implementation { -void Camera::setOrthographic(GLfloat size, GLfloat near, GLfloat far) { +Matrix4 Camera<3>::fixAspectRatio(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport) { + /* Don't divide by zero */ + if(viewport.x() == 0 || viewport.y() == 0) + return Matrix4(); + + /* Extend on larger side = scale larger side down */ + if(aspectRatioPolicy == AspectRatioPolicy::Extend) + return ((viewport.x() > viewport.y()) ? + Matrix4::scaling({GLfloat(viewport.y())/viewport.x(), 1, 1}) : + Matrix4::scaling({1, GLfloat(viewport.x())/viewport.y(), 1}) + ); + + /* Clip on smaller side = scale smaller side up */ + if(aspectRatioPolicy == AspectRatioPolicy::Clip) + return ((viewport.x() > viewport.y()) ? + Matrix4::scaling({1, GLfloat(viewport.x())/viewport.y(), 1}) : + Matrix4::scaling({GLfloat(viewport.y())/viewport.x(), 1, 1}) + ); + + /* Don't preserve anything */ + return Matrix4(); +} + +} +#endif + +template Camera::Camera(ObjectType* parent): ObjectType(parent), _aspectRatioPolicy(AspectRatioPolicy::Extend) {} + +template void Camera::setViewport(const Math::Vector2& size) { + Framebuffer::setViewport({0, 0}, size); + + _viewport = size; + fixAspectRatio(); +} + +template void Camera::clean(const MatrixType& absoluteTransformation) { + ObjectType::clean(absoluteTransformation); + + _cameraMatrix = absoluteTransformation.inverted(); +} + +template void Camera::draw() { + SceneType* s = this->scene(); + CORRADE_ASSERT(s, "Camera: cannot draw without camera attached to scene", ); + + Framebuffer::clear(); + + /* Recursively draw child objects */ + drawChildren(s, cameraMatrix()); +} + +template void Camera::drawChildren(ObjectType* object, const MatrixType& transformationMatrix) { + for(typename set::const_iterator it = object->children().begin(); it != object->children().end(); ++it) { + /* Transformation matrix for the object */ + MatrixType matrix = transformationMatrix*(*it)->transformation(); + + /* Draw the object and its children */ + (*it)->draw(matrix, static_cast(this)); + drawChildren(*it, matrix); + } +} + +void Camera3D::setOrthographic(GLfloat size, GLfloat near, GLfloat far) { _near = near; _far = far; @@ -38,7 +101,7 @@ void Camera::setOrthographic(GLfloat size, GLfloat near, GLfloat far) { fixAspectRatio(); } -void Camera::setPerspective(GLfloat fov, GLfloat near, GLfloat far) { +void Camera3D::setPerspective(GLfloat fov, GLfloat near, GLfloat far) { _near = near; _far = far; @@ -63,63 +126,7 @@ void Camera::setPerspective(GLfloat fov, GLfloat near, GLfloat far) { fixAspectRatio(); } -void Camera::setViewport(const Math::Vector2& size) { - Framebuffer::setViewport({0, 0}, size); - - _viewport = size; - fixAspectRatio(); -} - -void Camera::clean(const Matrix4& absoluteTransformation) { - Object::clean(absoluteTransformation); - - _cameraMatrix = absoluteTransformation.inverted(); -} - -void Camera::fixAspectRatio() { - /* Don't divide by zero */ - if(_viewport.x() == 0 || _viewport.y() == 0) { - _projectionMatrix = rawProjectionMatrix; - return; - } - - /* Extend on larger side = scale larger side down */ - if(_aspectRatioPolicy == AspectRatioPolicy::Extend) { - _projectionMatrix = ((_viewport.x() > _viewport.y()) ? - Matrix4::scaling({GLfloat(_viewport.y())/_viewport.x(), 1, 1}) : - Matrix4::scaling({1, GLfloat(_viewport.x())/_viewport.y(), 1}) - )*rawProjectionMatrix; - - /* Clip on smaller side = scale smaller side up */ - } else if(_aspectRatioPolicy == AspectRatioPolicy::Clip) { - _projectionMatrix = ((_viewport.x() > _viewport.y()) ? - Matrix4::scaling({1, GLfloat(_viewport.x())/_viewport.y(), 1}) : - Matrix4::scaling({GLfloat(_viewport.y())/_viewport.x(), 1, 1}) - )*rawProjectionMatrix; - - /* Don't preserve anything */ - } else _projectionMatrix = rawProjectionMatrix; -} - -void Camera::draw() { - Scene* s = scene(); - CORRADE_ASSERT(s, "Camera: cannot draw without camera attached to scene", ); - - Framebuffer::clear(); - - /* Recursively draw child objects */ - drawChildren(s, cameraMatrix()); -} - -void Camera::drawChildren(Object* object, const Matrix4& transformationMatrix) { - for(set::const_iterator it = object->children().begin(); it != object->children().end(); ++it) { - /* Transformation matrix for the object */ - Matrix4 matrix = transformationMatrix*(*it)->transformation(); - - /* Draw the object and its children */ - (*it)->draw(matrix, this); - drawChildren(*it, matrix); - } -} +/* Explicitly instantiate the templates */ +template class Camera; }} diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index 308a0d99a..d1a8674f8 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -28,31 +28,38 @@ namespace Magnum { namespace SceneGraph { +#ifndef DOXYGEN_GENERATING_OUTPUT +namespace Implementation { + enum class AspectRatioPolicy { + NotPreserved, Extend, Clip + }; + + template class Camera {}; +} +#endif + /** @brief %Camera object */ -class SCENEGRAPH_EXPORT Camera: public Object { +template class SCENEGRAPH_EXPORT Camera: public ObjectType { public: /** * @brief Aspect ratio policy * * @see aspectRatioPolicy(), setAspectRatioPolicy() */ + #ifndef DOXYGEN_GENERATING_OUTPUT + typedef Implementation::AspectRatioPolicy AspectRatioPolicy; + #else enum class AspectRatioPolicy { NotPreserved, /**< Don't preserve aspect ratio */ Extend, /**< Extend on larger side of view */ Clip /**< Clip on smaller side of view */ }; + #endif - /** - * @brief Constructor - * @param parent Parent object - * - * Sets orthographic projection to the default OpenGL cube (range - * @f$ [-1; 1] @f$ in all directions). - * @see setOrthographic(), setPerspective() - */ - Camera(Object* parent = nullptr); + /** @copydoc Object::Object */ + Camera(ObjectType* parent = nullptr); /** @brief Aspect ratio policy */ inline AspectRatioPolicy aspectRatioPolicy() const { return _aspectRatioPolicy; } @@ -60,39 +67,14 @@ class SCENEGRAPH_EXPORT Camera: public Object { /** @brief Set aspect ratio policy */ void setAspectRatioPolicy(AspectRatioPolicy policy) { _aspectRatioPolicy = policy; } - /** - * @brief Set orthographic projection - * @param size Size of (square) view - * @param near Near clipping plane - * @param far Far clipping plane - * - * The volume of given size will be scaled down to range - * @f$ [-1; 1] @f$ on all directions. - */ - void setOrthographic(GLfloat size, GLfloat near, GLfloat far); - - /** - * @brief Set perspective projection - * @param fov Field of view angle - * @param near Near clipping plane - * @param far Far clipping plane - */ - void setPerspective(GLfloat fov, GLfloat near, GLfloat far); - - /** @brief Near clipping plane */ - inline GLfloat near() const { return _near; } - - /** @brief Far clipping plane */ - inline GLfloat far() const { return _far; } - /** * @brief Camera matrix * * Camera matrix describes world position relative to the camera and is * applied as first. */ - inline Matrix4 cameraMatrix() { - setClean(); + inline MatrixType cameraMatrix() { + this->setClean(); return _cameraMatrix; } @@ -102,7 +84,7 @@ class SCENEGRAPH_EXPORT Camera: public Object { * Projection matrix handles e.g. perspective distortion and is applied * as last. */ - inline Matrix4 projectionMatrix() const { return _projectionMatrix; } + inline MatrixType projectionMatrix() const { return _projectionMatrix; } /** @brief Viewport size */ inline Math::Vector2 viewport() const { return _viewport; } @@ -124,31 +106,88 @@ class SCENEGRAPH_EXPORT Camera: public Object { */ virtual void draw(); - using Object::draw; /* Don't hide Object's draw() */ + using ObjectType::draw; /* Don't hide Object's draw() */ protected: /** * Recalculates camera matrix. */ - void clean(const Matrix4& absoluteTransformation); + void clean(const MatrixType& absoluteTransformation); /** * @brief Draw object children * * Recursively draws all children of the object. */ - void drawChildren(Object* object, const Matrix4& transformationMatrix); + void drawChildren(ObjectType* object, const MatrixType& transformationMatrix); + + #ifndef DOXYGEN_GENERATING_OUTPUT + inline void fixAspectRatio() { + _projectionMatrix = Implementation::Camera::fixAspectRatio(_aspectRatioPolicy, _viewport)*rawProjectionMatrix; + } + + MatrixType rawProjectionMatrix; + AspectRatioPolicy _aspectRatioPolicy; + #endif private: - Matrix4 rawProjectionMatrix; - Matrix4 _projectionMatrix; - Matrix4 _cameraMatrix; - GLfloat _near, _far; + MatrixType _projectionMatrix; + MatrixType _cameraMatrix; Math::Vector2 _viewport; - AspectRatioPolicy _aspectRatioPolicy; +}; + +#ifndef DOXYGEN_GENERATING_OUTPUT +/* These templates are instantiated in source file */ +extern template class SCENEGRAPH_EXPORT Camera; + +namespace Implementation { + template<> class Camera<3> { + public: + static Matrix4 fixAspectRatio(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport); + }; +} +#endif + +/** @brief %Camera for three-dimensional scenes */ +class SCENEGRAPH_EXPORT Camera3D: public Camera { + public: + /** + * @brief Constructor + * @param parent Parent object + * + * Sets orthographic projection to the default OpenGL cube (range @f$ [-1; 1] @f$ in all directions). + * @see setOrthographic(), setPerspective() + */ + inline Camera3D(Object3D* parent = nullptr): Camera(parent), _near(0.0), _far(0.0) {} + + /** + * @brief Set orthographic projection + * @param size Size of (square) view + * @param near Near clipping plane + * @param far Far clipping plane + * + * The volume of given size will be scaled down to range @f$ [-1; 1] @f$ + * on all directions. + */ + void setOrthographic(GLfloat size, GLfloat near, GLfloat far); + + /** + * @brief Set perspective projection + * @param fov Field of view angle + * @param near Near clipping plane + * @param far Far clipping plane + */ + void setPerspective(GLfloat fov, GLfloat near, GLfloat far); - SCENEGRAPH_LOCAL void fixAspectRatio(); + /** @brief Near clipping plane */ + inline GLfloat near() const { return _near; } + + /** @brief Far clipping plane */ + inline GLfloat far() const { return _far; } + + private: + GLfloat _near, _far; }; }} diff --git a/src/SceneGraph/Light.h b/src/SceneGraph/Light.h index 57ae9e083..3e604f584 100644 --- a/src/SceneGraph/Light.h +++ b/src/SceneGraph/Light.h @@ -28,13 +28,13 @@ namespace Magnum { namespace SceneGraph { * * Provides cached light position. */ -class SCENEGRAPH_EXPORT Light: public Object { +class SCENEGRAPH_EXPORT Light: public Object3D { public: /** * @brief Constructor * @param parent Parent object */ - inline Light(Object* parent = nullptr): Object(parent) {} + inline Light(Object3D* parent = nullptr): Object3D(parent) {} /** * @brief Light position relative to root object (scene) diff --git a/src/SceneGraph/Object.cpp b/src/SceneGraph/Object.cpp index 5ee2d06a6..386cf86e9 100644 --- a/src/SceneGraph/Object.cpp +++ b/src/SceneGraph/Object.cpp @@ -21,44 +21,45 @@ #include "Camera.h" using namespace std; +using namespace Magnum::Math; namespace Magnum { namespace SceneGraph { -Object* Object::setParent(Object* parent) { +template ObjectType* Object::setParent(ObjectType* parent) { /* Skip if nothing to do or this is scene */ - if(_parent == parent || _parent == this) return this; + if(_parent == parent || _parent == this) return static_cast(this); /* Add the object to children list of new parent */ if(parent != nullptr) { /* Only Fry can be his own grandfather */ - Object* p = parent; + ObjectType* p = parent; while(p != nullptr && p->parent() != p) { - if(p == this) return this; + if(p == this) return static_cast(this); p = p->parent(); } - parent->_children.insert(this); + parent->_children.insert(static_cast(this)); } /* Remove the object from old parent children list */ if(_parent != nullptr) - _parent->_children.erase(this); + _parent->_children.erase(static_cast(this)); /* Set new parent */ _parent = parent; setDirty(); - return this; + return static_cast(this); } -Matrix4 Object::absoluteTransformation(Camera* camera) { +template MatrixType Object::absoluteTransformation(CameraType* camera) { /* Shortcut for absolute transformation of camera relative to itself */ - if(camera == this) return Matrix4(); + if(camera == this) return MatrixType(); - Matrix4 t = _transformation; + MatrixType t = _transformation; - Object* p = parent(); + ObjectType* p = parent(); while(p != nullptr) { t = p->transformation()*t; @@ -80,7 +81,7 @@ Matrix4 Object::absoluteTransformation(Camera* camera) { return t; } -Object::~Object() { +template Object::~Object() { /* Remove the object from parent's children */ setParent(nullptr); @@ -89,44 +90,44 @@ Object::~Object() { delete *_children.begin(); } -Scene* Object::scene() { +template SceneType* Object::scene() { /* Goes up the family tree until it finds object which is parent of itself (that's the scene) */ - Object* p = parent(); + ObjectType* p = parent(); while(p != nullptr) { - if(p->parent() == p) return static_cast(p); + if(p->parent() == p) return static_cast(p); p = p->parent(); } return nullptr; } -Object* Object::setTransformation(const Matrix4& transformation) { - if(_parent == this) return this; +template ObjectType* Object::setTransformation(const MatrixType& transformation) { + if(_parent == this) return static_cast(this); _transformation = transformation; setDirty(); - return this; + return static_cast(this); } -void Object::setDirty() { +template void Object::setDirty() { /* The object (and all its children) are already dirty, nothing to do */ if(dirty) return; dirty = true; /* Make all children dirty */ - for(set::iterator it = _children.begin(); it != _children.end(); ++it) + for(typename set::iterator it = _children.begin(); it != _children.end(); ++it) (*it)->setDirty(); } -void Object::setClean() { +template void Object::setClean() { /* The object (and all its parents) are already clean, nothing to do */ if(!dirty) return; /* Collect all parents */ - stack objects; - Object* p = this; + stack objects; + ObjectType* p = static_cast(this); for(;;) { objects.push(p); @@ -138,9 +139,9 @@ void Object::setClean() { } /* Call setClean(const Matrix4&) for every parent and also this object */ - Object* o = objects.top(); + ObjectType* o = objects.top(); objects.pop(); - Matrix4 absoluteTransformation = o->absoluteTransformation(); + MatrixType absoluteTransformation = o->absoluteTransformation(); o->clean(absoluteTransformation); while(!objects.empty()) { o = objects.top(); @@ -150,4 +151,7 @@ void Object::setClean() { } } +/* Explicitly instantiate the templates */ +template class Object; + }} diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 5ddb2c2f3..b86f48d20 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -27,8 +27,7 @@ namespace Magnum { namespace SceneGraph { -class Scene; -class Camera; +template class Scene; /** @todo User-specified Object implementation: @@ -46,13 +45,15 @@ class Camera; * @todo Transform transformation when changing parent, so the object stays in * place. */ -class SCENEGRAPH_EXPORT Object { - Object(const Object& other) = delete; - Object(Object&& other) = delete; - Object& operator=(const Object& other) = delete; - Object& operator=(Object&& other) = delete; +template class SCENEGRAPH_EXPORT Object { + #ifndef DOXYGEN_GENERATING_OUTPUT + Object(const Object& other) = delete; + Object(Object&& other) = delete; + Object& operator=(const Object& other) = delete; + Object& operator=(Object&& other) = delete; + #endif - friend class Scene; + friend class Scene; public: /** @@ -61,7 +62,7 @@ class SCENEGRAPH_EXPORT Object { * * Sets all transformations to their default values. */ - inline Object(Object* parent = nullptr): _parent(nullptr), dirty(true) { + inline Object(ObjectType* parent = nullptr): _parent(nullptr), dirty(true) { setParent(parent); } @@ -79,16 +80,16 @@ class SCENEGRAPH_EXPORT Object { * @brief %Scene * @return If the object is not assigned to any scene, returns nullptr. */ - Scene* scene(); + SceneType* scene(); /** @brief Parent object */ - inline Object* parent() { return _parent; } + inline ObjectType* parent() { return _parent; } /** @brief Child objects */ - inline const std::set& children() { return _children; } + inline const std::set& children() { return _children; } /** @brief Set parent object */ - Object* setParent(Object* parent); + ObjectType* setParent(ObjectType* parent); /*@}*/ @@ -108,7 +109,7 @@ class SCENEGRAPH_EXPORT Object { }; /** @brief Transformation */ - inline Matrix4 transformation() const { + inline MatrixType transformation() const { return _transformation; } @@ -123,50 +124,20 @@ class SCENEGRAPH_EXPORT Object { * objects every time it is asked, unless this function is * reimplemented in a different way. */ - virtual Matrix4 absoluteTransformation(Camera* camera = nullptr); + virtual MatrixType absoluteTransformation(CameraType* camera = nullptr); /** @brief Set transformation */ - Object* setTransformation(const Matrix4& transformation); + ObjectType* setTransformation(const MatrixType& transformation); /** * @brief Multiply transformation * @param transformation Transformation * @param type Transformation type */ - inline Object* multiplyTransformation(const Matrix4& transformation, Transformation type = Transformation::Global) { + inline ObjectType* multiplyTransformation(const MatrixType& transformation, Transformation type = Transformation::Global) { setTransformation(type == Transformation::Global ? transformation*_transformation : _transformation*transformation); - return this; - } - - /** - * @brief Translate object - * - * Same as calling multiplyTransformation() with Matrix4::translation(). - */ - inline Object* translate(Vector3 vec, Transformation type = Transformation::Global) { - multiplyTransformation(Matrix4::translation(vec), type); - return this; - } - - /** - * @brief Scale object - * - * Same as calling multiplyTransformation() with Matrix4::scaling(). - */ - inline Object* scale(Vector3 vec, Transformation type = Transformation::Global) { - multiplyTransformation(Matrix4::scaling(vec), type); - return this; - } - - /** - * @brief Rotate object - * - * Same as calling multiplyTransformation() with Matrix4::rotation(). - */ - inline Object* rotate(GLfloat angle, Vector3 vec, Transformation type = Transformation::Global) { - multiplyTransformation(Matrix4::rotation(angle, vec), type); - return this; + return static_cast(this); } /*@}*/ @@ -180,7 +151,7 @@ class SCENEGRAPH_EXPORT Object { * * Default implementation does nothing. */ - virtual void draw(const Matrix4& transformationMatrix, Camera* camera); + virtual void draw(const MatrixType& transformationMatrix, CameraType* camera); /** @{ @name Caching helpers * @@ -255,20 +226,66 @@ class SCENEGRAPH_EXPORT Object { * } * @endcode */ - virtual void clean(const Matrix4& absoluteTransformation); + virtual void clean(const MatrixType& absoluteTransformation); /*@}*/ private: - Object* _parent; - std::set _children; - Matrix4 _transformation; + ObjectType* _parent; + std::set _children; + MatrixType _transformation; bool dirty; }; /* Implementations for inline functions with unused parameters */ -inline void Object::draw(const Matrix4&, Camera*) {} -inline void Object::clean(const Matrix4&) { dirty = false; } +template inline void Object::draw(const MatrixType&, CameraType*) {} +template inline void Object::clean(const MatrixType&) { dirty = false; } + +class Camera3D; +class Object3D; +typedef Scene Scene3D; + +#ifndef DOXYGEN_GENERATING_OUTPUT +/* These templates are instantiated in source file */ +extern template class SCENEGRAPH_EXPORT Object; +#endif + +/** @brief Three-dimensional object */ +class SCENEGRAPH_EXPORT Object3D: public Object { + public: + /** @copydoc Object::Object */ + inline Object3D(Object3D* parent = nullptr): Object(parent) {} + + /** + * @brief Translate object + * + * Same as calling multiplyTransformation() with Matrix4::translation(). + */ + inline Object3D* translate(const Vector3& vec, Transformation type = Transformation::Global) { + multiplyTransformation(Matrix4::translation(vec), type); + return this; + } + + /** + * @brief Scale object + * + * Same as calling multiplyTransformation() with Matrix4::scaling(). + */ + inline Object3D* scale(const Vector3& vec, Transformation type = Transformation::Global) { + multiplyTransformation(Matrix4::scaling(vec), type); + return this; + } + + /** + * @brief Rotate object + * + * Same as calling multiplyTransformation() with Matrix4::rotation(). + */ + inline Object3D* rotate(GLfloat angle, const Vector3& vec, Transformation type = Transformation::Global) { + multiplyTransformation(Matrix4::rotation(angle, vec), type); + return this; + } +}; }} diff --git a/src/SceneGraph/Scene.h b/src/SceneGraph/Scene.h index 63cedc905..35b36e501 100644 --- a/src/SceneGraph/Scene.h +++ b/src/SceneGraph/Scene.h @@ -24,22 +24,27 @@ namespace Magnum { namespace SceneGraph { /** @brief %Scene */ -class SCENEGRAPH_EXPORT Scene: public Object { +template class SCENEGRAPH_EXPORT Scene: public ObjectType { public: /** @brief Constructor */ - inline Scene() { _parent = this; } + inline Scene() { this->_parent = this; } - void setParent(Object* parent) = delete; - void setTransformation(const Matrix4& transformation) = delete; - void multiplyTransformation(const Matrix4& transformation, Transformation type = Transformation::Global) = delete; - void translate(Vector3 vec, Transformation type = Transformation::Global) = delete; - void scale(Vector3 vec, Transformation type = Transformation::Global) = delete; - void rotate(GLfloat angle, Vector3 vec, Transformation type = Transformation::Global) = delete; + #ifndef DOXYGEN_GENERATING_OUTPUT + void setParent(ObjectType* parent) = delete; + void setTransformation(const MatrixType& transformation) = delete; + void multiplyTransformation(const MatrixType& transformation, typename ObjectType::Transformation type = ObjectType::Transformation::Global) = delete; + void translate(const VectorType& vec, typename ObjectType::Transformation type = ObjectType::Transformation::Global) = delete; + void scale(const VectorType& vec, typename ObjectType::Transformation type = ObjectType::Transformation::Global) = delete; + void rotate(GLfloat angle, const VectorType& vec, typename ObjectType::Transformation type = ObjectType::Transformation::Global) = delete; + #endif private: - inline void draw(const Magnum::Matrix4&, Camera*) {} + inline void draw(const MatrixType&, CameraType*) {} }; +/** @brief Three-dimensional scene */ +typedef Scene Scene3D; + }} #endif diff --git a/src/SceneGraph/Test/CameraTest.cpp b/src/SceneGraph/Test/CameraTest.cpp index 508705b43..53e4cbe42 100644 --- a/src/SceneGraph/Test/CameraTest.cpp +++ b/src/SceneGraph/Test/CameraTest.cpp @@ -27,7 +27,7 @@ CameraTest::CameraTest() { } void CameraTest::orthographic() { - Camera camera; + Camera3D camera; camera.setOrthographic(5, 1, 9); Matrix4 a(0.4f, 0.0f, 0.0f, 0.0f, @@ -39,7 +39,7 @@ void CameraTest::orthographic() { } void CameraTest::perspective() { - Camera camera; + Camera3D camera; camera.setPerspective(deg(27.0f), 32.0f, 100); Matrix4 a(4.1652994f, 0.0f, 0.0f, 0.0f, diff --git a/src/SceneGraph/Test/ObjectTest.cpp b/src/SceneGraph/Test/ObjectTest.cpp index 5a4f22a6e..06248e097 100644 --- a/src/SceneGraph/Test/ObjectTest.cpp +++ b/src/SceneGraph/Test/ObjectTest.cpp @@ -35,10 +35,10 @@ ObjectTest::ObjectTest() { } void ObjectTest::parenting() { - Object root; + Object3D root; - Object* childOne = new Object(&root); - Object* childTwo = new Object(&root); + Object3D* childOne = new Object3D(&root); + Object3D* childTwo = new Object3D(&root); CORRADE_VERIFY(childOne->parent() == &root); CORRADE_COMPARE(root.children().size(), 2); @@ -62,8 +62,8 @@ void ObjectTest::parenting() { } void ObjectTest::transformation() { - Object o; - Object o2; + Object3D o; + Object3D o2; o.setTransformation(Matrix4::translation(Vector3::xAxis(1.0f))); o2.translate(Vector3::xAxis(1.0f)); @@ -74,8 +74,8 @@ void ObjectTest::transformation() { Matrix4::translation(Vector3::xAxis(1.0f))); CORRADE_COMPARE(o2.transformation(), o.transformation()); - o.multiplyTransformation(Matrix4::scaling(Vector3(2.0f)), Object::Transformation::Local); - o2.scale(Vector3(2.0f), Object::Transformation::Local); + o.multiplyTransformation(Matrix4::scaling(Vector3(2.0f)), Object3D::Transformation::Local); + o2.scale(Vector3(2.0f), Object3D::Transformation::Local); CORRADE_COMPARE(o.transformation(), Matrix4::rotation(deg(35.0f), Vector3::zAxis())* Matrix4::translation(Vector3::xAxis(1.0f))* Matrix4::scaling(Vector3(2.0f))); @@ -86,56 +86,56 @@ void ObjectTest::absoluteTransformationWrongCamera() { stringstream ss; Error::setOutput(&ss); - Scene s; - Object o(&s); + Scene3D s; + Object3D o(&s); o.translate(Vector3::yAxis()); - Camera c; + Camera3D c; CORRADE_COMPARE(o.absoluteTransformation(&c), Matrix4::translation(Vector3::yAxis())); CORRADE_COMPARE(ss.str(), "Object::absoluteTransformation(): the camera is not part of the same scene as object!\n"); ss.str(""); - Object o2; + Object3D o2; o2.translate(Vector3::xAxis()); CORRADE_COMPARE(o2.absoluteTransformation(&c), Matrix4::translation(Vector3::xAxis())); CORRADE_COMPARE(ss.str(), "Object::absoluteTransformation(): the object is not part of camera scene!\n"); } void ObjectTest::absoluteTransformation() { - Scene s; - Camera c(&s); + Scene3D s; + Camera3D c(&s); c.translate(Vector3::zAxis(2.0f)); CORRADE_COMPARE(s.absoluteTransformation(), Matrix4()); CORRADE_COMPARE(c.absoluteTransformation(&c), Matrix4()); - Object o(&s); + Object3D o(&s); o.scale(Vector3(2.0f)); - Object o2(&o); + Object3D o2(&o); o.rotate(deg(90.0f), Vector3::yAxis()); CORRADE_COMPARE(o2.absoluteTransformation(), Matrix4::scaling(Vector3(2.0f))*Matrix4::rotation(deg(90.0f), Vector3::yAxis())); CORRADE_COMPARE(o2.absoluteTransformation(&c), (Matrix4::translation(Vector3::zAxis(2.0f)).inverted())*Matrix4::scaling(Vector3(2.0f))*Matrix4::rotation(deg(90.0f), Vector3::yAxis())); - Object o3; + Object3D o3; o3.translate({1.0f, 2.0f, 3.0f}); CORRADE_COMPARE(o3.absoluteTransformation(), Matrix4::translation({1.0f, 2.0f, 3.0f})); } void ObjectTest::scene() { - Scene scene; + Scene3D scene; - Object* childOne = new Object(&scene); - Object* childTwo = new Object(childOne); + Object3D* childOne = new Object3D(&scene); + Object3D* childTwo = new Object3D(childOne); - Object orphan; - Object* childOfOrphan = new Object(&orphan); + Object3D orphan; + Object3D* childOfOrphan = new Object3D(&orphan); CORRADE_VERIFY(childTwo->scene() == &scene); CORRADE_VERIFY(childOfOrphan->scene() == nullptr); } void ObjectTest::dirty() { - Scene scene; + Scene3D scene; CleaningObject* childOne = new CleaningObject(&scene); childOne->scale(Vector3(2.0f)); diff --git a/src/SceneGraph/Test/ObjectTest.h b/src/SceneGraph/Test/ObjectTest.h index 8505bd59e..01149310f 100644 --- a/src/SceneGraph/Test/ObjectTest.h +++ b/src/SceneGraph/Test/ObjectTest.h @@ -33,12 +33,12 @@ class ObjectTest: public Corrade::TestSuite::Tester { void dirty(); private: - class CleaningObject: public Object { + class CleaningObject: public Object3D { public: - CleaningObject(Object* parent = nullptr): Object(parent) {} + CleaningObject(Object3D* parent = nullptr): Object3D(parent) {} inline void clean(const Matrix4& absoluteTransformation) { - Object::clean(absoluteTransformation); + Object3D::clean(absoluteTransformation); cleanedAbsoluteTransformation = absoluteTransformation; } diff --git a/src/SceneGraph/Test/SceneTest.cpp b/src/SceneGraph/Test/SceneTest.cpp index 132c09e0b..e2df35aa1 100644 --- a/src/SceneGraph/Test/SceneTest.cpp +++ b/src/SceneGraph/Test/SceneTest.cpp @@ -27,21 +27,21 @@ SceneTest::SceneTest() { } void SceneTest::transformation() { - Scene scene; + Scene3D scene; - Object* scenePointer = &scene; + Object3D* scenePointer = &scene; scenePointer->setTransformation(Matrix4::translation({1.0f, 1.0f, 1.0f})); CORRADE_COMPARE(scene.transformation(), Matrix4()); } void SceneTest::parent() { - Scene scene; + Scene3D scene; CORRADE_VERIFY(scene.parent() == &scene); /* Scene parent cannot be changed */ - Object* scenePointer = &scene; - Object object; + Object3D* scenePointer = &scene; + Object3D object; scenePointer->setParent(&object); CORRADE_VERIFY(scene.parent() == &scene); CORRADE_VERIFY(scene.children().empty()); From f6d1aa7bc949154dc0682f899b583bc1089adfae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 16 Aug 2012 15:29:07 +0200 Subject: [PATCH 33/78] SceneGraph: Test for Implementation::Camera<3>::fixAspectRatio(). --- src/SceneGraph/Camera.h | 4 +++- src/SceneGraph/Test/CameraTest.cpp | 30 +++++++++++++++++++++++++++++- src/SceneGraph/Test/CameraTest.h | 1 + 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index d1a8674f8..b5fa51e51 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -137,12 +137,14 @@ template _viewport; }; +/** @todo Export implementation symbols only for tests */ + #ifndef DOXYGEN_GENERATING_OUTPUT /* These templates are instantiated in source file */ extern template class SCENEGRAPH_EXPORT Camera; namespace Implementation { - template<> class Camera<3> { + template<> class SCENEGRAPH_EXPORT Camera<3> { public: static Matrix4 fixAspectRatio(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport); }; diff --git a/src/SceneGraph/Test/CameraTest.cpp b/src/SceneGraph/Test/CameraTest.cpp index 53e4cbe42..496dd2de3 100644 --- a/src/SceneGraph/Test/CameraTest.cpp +++ b/src/SceneGraph/Test/CameraTest.cpp @@ -22,10 +22,38 @@ CORRADE_TEST_MAIN(Magnum::SceneGraph::Test::CameraTest) namespace Magnum { namespace SceneGraph { namespace Test { CameraTest::CameraTest() { - addTests(&CameraTest::orthographic, + addTests(&CameraTest::fixAspectRatio, + &CameraTest::orthographic, &CameraTest::perspective); } +void CameraTest::fixAspectRatio() { + /* Division by zero */ + Math::Vector2 sizeZeroY(400, 0); + Math::Vector2 sizeZeroX(0, 300); + CORRADE_COMPARE(Implementation::Camera<3>::fixAspectRatio(Implementation::AspectRatioPolicy::Clip, sizeZeroY), Matrix4()); + CORRADE_COMPARE(Implementation::Camera<3>::fixAspectRatio(Implementation::AspectRatioPolicy::Extend, sizeZeroX), Matrix4()); + + Math::Vector2 size(400, 300); + + /* Not preserved */ + CORRADE_COMPARE(Implementation::Camera<3>::fixAspectRatio(Implementation::AspectRatioPolicy::NotPreserved, size), Matrix4()); + + /* Clip */ + Matrix4 expectedClip(1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 4.0f/3.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + CORRADE_COMPARE(Implementation::Camera<3>::fixAspectRatio(Implementation::AspectRatioPolicy::Clip, size), expectedClip); + + /* Extend */ + Matrix4 expectedExtend(3.0f/4.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + CORRADE_COMPARE(Implementation::Camera<3>::fixAspectRatio(Implementation::AspectRatioPolicy::Extend, size), expectedExtend); +} + void CameraTest::orthographic() { Camera3D camera; camera.setOrthographic(5, 1, 9); diff --git a/src/SceneGraph/Test/CameraTest.h b/src/SceneGraph/Test/CameraTest.h index ec9a699b0..f460c241f 100644 --- a/src/SceneGraph/Test/CameraTest.h +++ b/src/SceneGraph/Test/CameraTest.h @@ -23,6 +23,7 @@ class CameraTest: public Corrade::TestSuite::Tester { public: CameraTest(); + void fixAspectRatio(); void orthographic(); void perspective(); }; From 27bbf23dff8a58fff45010de514e0c4f882e18e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 16 Aug 2012 15:38:14 +0200 Subject: [PATCH 34/78] SceneGraph: Simplified Implementation::Camera<3>::fixAspectRatio(). --- src/SceneGraph/Camera.cpp | 35 ++++++++++++------------------ src/SceneGraph/Camera.h | 17 ++++++++++----- src/SceneGraph/Test/CameraTest.cpp | 10 ++++----- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp index ad3b794fe..32fba23f8 100644 --- a/src/SceneGraph/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -24,29 +24,22 @@ namespace Magnum { namespace SceneGraph { #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { -Matrix4 Camera<3>::fixAspectRatio(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport) { - /* Don't divide by zero */ - if(viewport.x() == 0 || viewport.y() == 0) - return Matrix4(); - - /* Extend on larger side = scale larger side down */ - if(aspectRatioPolicy == AspectRatioPolicy::Extend) - return ((viewport.x() > viewport.y()) ? - Matrix4::scaling({GLfloat(viewport.y())/viewport.x(), 1, 1}) : - Matrix4::scaling({1, GLfloat(viewport.x())/viewport.y(), 1}) - ); - - /* Clip on smaller side = scale smaller side up */ - if(aspectRatioPolicy == AspectRatioPolicy::Clip) - return ((viewport.x() > viewport.y()) ? - Matrix4::scaling({1, GLfloat(viewport.x())/viewport.y(), 1}) : - Matrix4::scaling({GLfloat(viewport.y())/viewport.x(), 1, 1}) - ); - - /* Don't preserve anything */ - return Matrix4(); +template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport) { + /* Don't divide by zero / don't preserve anything */ + if(viewport.x() == 0 || viewport.y() == 0 || aspectRatioPolicy == AspectRatioPolicy::NotPreserved) + return MatrixType(); + + /* Extend on larger side = scale larger side down + Clip on smaller side = scale smaller side up */ + return Camera::aspectRatioScale( + (viewport.x() > viewport.y()) == (aspectRatioPolicy == AspectRatioPolicy::Extend) ? + Vector2(GLfloat(viewport.y())/viewport.x(), 1.0f) : + Vector2(1.0f, GLfloat(viewport.x())/viewport.y())); } +/* Explicitly instantiate the templates */ +template Matrix4 aspectRatioFix(AspectRatioPolicy, const Math::Vector2&); + } #endif diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index b5fa51e51..96f71cef4 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -28,6 +28,8 @@ namespace Magnum { namespace SceneGraph { +/** @todo Export implementation symbols only for tests */ + #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { enum class AspectRatioPolicy { @@ -35,6 +37,11 @@ namespace Implementation { }; template class Camera {}; + + template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport); + + /* These templates are instantiated in source file */ + extern template SCENEGRAPH_EXPORT Matrix4 aspectRatioFix(AspectRatioPolicy, const Math::Vector2&); } #endif @@ -123,7 +130,7 @@ template::fixAspectRatio(_aspectRatioPolicy, _viewport)*rawProjectionMatrix; + _projectionMatrix = Implementation::aspectRatioFix(_aspectRatioPolicy, _viewport)*rawProjectionMatrix; } MatrixType rawProjectionMatrix; @@ -137,16 +144,16 @@ template _viewport; }; -/** @todo Export implementation symbols only for tests */ - #ifndef DOXYGEN_GENERATING_OUTPUT /* These templates are instantiated in source file */ extern template class SCENEGRAPH_EXPORT Camera; namespace Implementation { - template<> class SCENEGRAPH_EXPORT Camera<3> { + template<> class Camera<3> { public: - static Matrix4 fixAspectRatio(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport); + inline constexpr static Matrix4 aspectRatioScale(const Vector2& scale) { + return Matrix4::scaling({scale.x(), scale.y(), 1.0f}); + } }; } #endif diff --git a/src/SceneGraph/Test/CameraTest.cpp b/src/SceneGraph/Test/CameraTest.cpp index 496dd2de3..2a72ac5a9 100644 --- a/src/SceneGraph/Test/CameraTest.cpp +++ b/src/SceneGraph/Test/CameraTest.cpp @@ -31,27 +31,27 @@ void CameraTest::fixAspectRatio() { /* Division by zero */ Math::Vector2 sizeZeroY(400, 0); Math::Vector2 sizeZeroX(0, 300); - CORRADE_COMPARE(Implementation::Camera<3>::fixAspectRatio(Implementation::AspectRatioPolicy::Clip, sizeZeroY), Matrix4()); - CORRADE_COMPARE(Implementation::Camera<3>::fixAspectRatio(Implementation::AspectRatioPolicy::Extend, sizeZeroX), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, sizeZeroY), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, sizeZeroX), Matrix4()); Math::Vector2 size(400, 300); /* Not preserved */ - CORRADE_COMPARE(Implementation::Camera<3>::fixAspectRatio(Implementation::AspectRatioPolicy::NotPreserved, size), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::NotPreserved, size), Matrix4()); /* Clip */ Matrix4 expectedClip(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.0f/3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); - CORRADE_COMPARE(Implementation::Camera<3>::fixAspectRatio(Implementation::AspectRatioPolicy::Clip, size), expectedClip); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, size), expectedClip); /* Extend */ Matrix4 expectedExtend(3.0f/4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); - CORRADE_COMPARE(Implementation::Camera<3>::fixAspectRatio(Implementation::AspectRatioPolicy::Extend, size), expectedExtend); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, size), expectedExtend); } void CameraTest::orthographic() { From c6e14dd348eb82c80240f9340b75c2aad0e6c0bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 02:42:34 +0200 Subject: [PATCH 35/78] SceneGraph: Initial support for projections with aspect ratio != 1:1. Orthographic projection done, perspective projection needs total rework, leaving it for later. --- src/SceneGraph/Camera.cpp | 23 +++++++++-------- src/SceneGraph/Camera.h | 13 ++++++---- src/SceneGraph/Test/CameraTest.cpp | 40 ++++++++++++++++++++++++------ 3 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp index 32fba23f8..5726e9596 100644 --- a/src/SceneGraph/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -24,26 +24,28 @@ namespace Magnum { namespace SceneGraph { #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { -template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport) { +template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2& viewport) { /* Don't divide by zero / don't preserve anything */ - if(viewport.x() == 0 || viewport.y() == 0 || aspectRatioPolicy == AspectRatioPolicy::NotPreserved) + if(projectionAspectRatio.x() == 0 || projectionAspectRatio.y() == 0 || viewport.x() == 0 || viewport.y() == 0 || aspectRatioPolicy == AspectRatioPolicy::NotPreserved) return MatrixType(); + Vector2 relativeAspectRatio = Vector2::from(viewport)/projectionAspectRatio; + /* Extend on larger side = scale larger side down Clip on smaller side = scale smaller side up */ return Camera::aspectRatioScale( - (viewport.x() > viewport.y()) == (aspectRatioPolicy == AspectRatioPolicy::Extend) ? - Vector2(GLfloat(viewport.y())/viewport.x(), 1.0f) : - Vector2(1.0f, GLfloat(viewport.x())/viewport.y())); + (relativeAspectRatio.x() > relativeAspectRatio.y()) == (aspectRatioPolicy == AspectRatioPolicy::Extend) ? + Vector2(relativeAspectRatio.y()/relativeAspectRatio.x(), 1.0f) : + Vector2(1.0f, relativeAspectRatio.x()/relativeAspectRatio.y())); } /* Explicitly instantiate the templates */ -template Matrix4 aspectRatioFix(AspectRatioPolicy, const Math::Vector2&); +template Matrix4 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); } #endif -template Camera::Camera(ObjectType* parent): ObjectType(parent), _aspectRatioPolicy(AspectRatioPolicy::Extend) {} +template Camera::Camera(ObjectType* parent): ObjectType(parent), projectionAspectRatio(1.0f), _aspectRatioPolicy(AspectRatioPolicy::Extend) {} template void Camera::setViewport(const Math::Vector2& size) { Framebuffer::setViewport({0, 0}, size); @@ -79,18 +81,18 @@ template class Camera {}; - template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Math::Vector2& viewport); + template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2& viewport); /* These templates are instantiated in source file */ - extern template SCENEGRAPH_EXPORT Matrix4 aspectRatioFix(AspectRatioPolicy, const Math::Vector2&); + extern template SCENEGRAPH_EXPORT Matrix4 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); } #endif @@ -130,9 +130,10 @@ template(_aspectRatioPolicy, _viewport)*rawProjectionMatrix; + _projectionMatrix = Implementation::aspectRatioFix(_aspectRatioPolicy, projectionAspectRatio, _viewport)*rawProjectionMatrix; } + Vector2 projectionAspectRatio; MatrixType rawProjectionMatrix; AspectRatioPolicy _aspectRatioPolicy; #endif @@ -172,20 +173,22 @@ class SCENEGRAPH_EXPORT Camera3D: public Camera size(400, 300); + /* Division by zero */ + Vector2 projectionSizeZeroY(2, 0); + Vector2 projectionSizeZeroX(0, 2); Math::Vector2 sizeZeroY(400, 0); Math::Vector2 sizeZeroX(0, 300); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, sizeZeroY), Matrix4()); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, sizeZeroX), Matrix4()); - - Math::Vector2 size(400, 300); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSizeZeroX, size), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSizeZeroY, size), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSize, sizeZeroY), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, projectionSize, sizeZeroX), Matrix4()); /* Not preserved */ - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::NotPreserved, size), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::NotPreserved, projectionSize, size), Matrix4()); /* Clip */ Matrix4 expectedClip(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.0f/3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, size), expectedClip); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, Vector2(2.0f), size), expectedClip); + Matrix4 expectedClipRectangle(1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 2.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSize, size), expectedClipRectangle); /* Extend */ Matrix4 expectedExtend(3.0f/4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, size), expectedExtend); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, Vector2(2.0f), size), expectedExtend); + Matrix4 expectedExtendRectangle(0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, projectionSize, size), expectedExtendRectangle); } void CameraTest::orthographic() { Camera3D camera; - camera.setOrthographic(5, 1, 9); + camera.setOrthographic(Vector2(5), 1, 9); Matrix4 a(0.4f, 0.0f, 0.0f, 0.0f, 0.0f, 0.4f, 0.0f, 0.0f, @@ -64,6 +79,15 @@ void CameraTest::orthographic() { 0.0f, 0.0f, -1.25f, 1.0f); CORRADE_COMPARE(camera.projectionMatrix(), a); + + camera.setOrthographic(Vector2(5.0f, 4.0f), 1, 9); + + Matrix4 rectangle(0.4f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, -0.25f, 0.0f, + 0.0f, 0.0f, -1.25f, 1.0f); + + CORRADE_COMPARE(camera.projectionMatrix(), rectangle); } void CameraTest::perspective() { From d43e18a741f07cdc6e68b475b9a2dbaede108799 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 16 Aug 2012 15:39:01 +0200 Subject: [PATCH 36/78] Initial support for 2D scene graph. --- src/SceneGraph/Camera.cpp | 10 ++++++++++ src/SceneGraph/Camera.h | 29 +++++++++++++++++++++++++++ src/SceneGraph/Object.cpp | 1 + src/SceneGraph/Object.h | 41 +++++++++++++++++++++++++++++++++++++++ src/SceneGraph/Scene.h | 3 +++ 5 files changed, 84 insertions(+) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp index 5726e9596..5ab0c81b8 100644 --- a/src/SceneGraph/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -40,6 +40,7 @@ template MatrixType aspectRatioFix(AspectRatioPolicy aspectRat } /* Explicitly instantiate the templates */ +template Matrix3 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); template Matrix4 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); } @@ -81,6 +82,14 @@ template; template class Camera; }} diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index 36a4c8d06..cf6ba0c4b 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -147,9 +147,16 @@ template; extern template class SCENEGRAPH_EXPORT Camera; namespace Implementation { + template<> class Camera<2> { + public: + inline constexpr static Matrix3 aspectRatioScale(const Vector2& scale) { + return Matrix3::scaling({scale.x(), scale.y()}); + } + }; template<> class Camera<3> { public: inline constexpr static Matrix4 aspectRatioScale(const Vector2& scale) { @@ -159,6 +166,28 @@ namespace Implementation { } #endif +/** @brief %Camera for two-dimensional scenes */ +class SCENEGRAPH_EXPORT Camera2D: public Camera { + public: + /** + * @brief Constructor + * @param parent Parent object + * + * Sets orthographic projection to the default OpenGL cube (range @f$ [-1; 1] @f$ in all directions). + * @see setOrthographic() + */ + inline Camera2D(Object2D* parent = nullptr): Camera(parent) {} + + /** + * @brief Set projection + * @param size Size of the view + * + * The area of given size will be scaled down to range @f$ [-1; 1] @f$ + * on all directions. + */ + void setProjection(const Vector2& size); +}; + /** @brief %Camera for three-dimensional scenes */ class SCENEGRAPH_EXPORT Camera3D: public Camera { public: diff --git a/src/SceneGraph/Object.cpp b/src/SceneGraph/Object.cpp index 386cf86e9..f74602bb1 100644 --- a/src/SceneGraph/Object.cpp +++ b/src/SceneGraph/Object.cpp @@ -152,6 +152,7 @@ template; template class Object; }} diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index b86f48d20..691baf688 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -241,15 +241,56 @@ template inline void Object::draw(const MatrixType&, CameraType*) {} template inline void Object::clean(const MatrixType&) { dirty = false; } +class Camera2D; class Camera3D; +class Object2D; class Object3D; +typedef Scene Scene2D; typedef Scene Scene3D; #ifndef DOXYGEN_GENERATING_OUTPUT /* These templates are instantiated in source file */ +extern template class SCENEGRAPH_EXPORT Object; extern template class SCENEGRAPH_EXPORT Object; #endif +/** @brief Two-dimensional object */ +class SCENEGRAPH_EXPORT Object2D: public Object { + public: + /** @copydoc Object::Object */ + inline Object2D(Object2D* parent = nullptr): Object(parent) {} + + /** + * @brief Translate object + * + * Same as calling multiplyTransformation() with Matrix3::translation(). + */ + inline Object2D* translate(const Vector2& vec, Transformation type = Transformation::Global) { + multiplyTransformation(Matrix3::translation(vec), type); + return this; + } + + /** + * @brief Scale object + * + * Same as calling multiplyTransformation() with Matrix3::scaling(). + */ + inline Object2D* scale(const Vector2& vec, Transformation type = Transformation::Global) { + multiplyTransformation(Matrix3::scaling(vec), type); + return this; + } + + /** + * @brief Rotate object + * + * Same as calling multiplyTransformation() with Matrix3::rotation(). + */ + inline Object2D* rotate(GLfloat angle, Transformation type = Transformation::Global) { + multiplyTransformation(Matrix3::rotation(angle), type); + return this; + } +}; + /** @brief Three-dimensional object */ class SCENEGRAPH_EXPORT Object3D: public Object { public: diff --git a/src/SceneGraph/Scene.h b/src/SceneGraph/Scene.h index 35b36e501..73e3793f0 100644 --- a/src/SceneGraph/Scene.h +++ b/src/SceneGraph/Scene.h @@ -42,6 +42,9 @@ template inline void draw(const MatrixType&, CameraType*) {} }; +/** @brief Two-dimensional scene */ +typedef Scene Scene2D; + /** @brief Three-dimensional scene */ typedef Scene Scene3D; From af8b01da88a15150af93466bef550f3118cf03b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 00:54:36 +0200 Subject: [PATCH 37/78] SceneGraph: default Camera aspect ratio policy is to not preserve. I thought and believed it was like that since forever, but I was wrong. --- src/SceneGraph/Camera.cpp | 2 +- src/SceneGraph/Camera.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp index 5ab0c81b8..46db61799 100644 --- a/src/SceneGraph/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -46,7 +46,7 @@ template Matrix4 aspectRatioFix(AspectRatioPolicy, const Vector2&, cons } #endif -template Camera::Camera(ObjectType* parent): ObjectType(parent), projectionAspectRatio(1.0f), _aspectRatioPolicy(AspectRatioPolicy::Extend) {} +template Camera::Camera(ObjectType* parent): ObjectType(parent), projectionAspectRatio(1.0f), _aspectRatioPolicy(AspectRatioPolicy::NotPreserved) {} template void Camera::setViewport(const Math::Vector2& size) { Framebuffer::setViewport({0, 0}, size); diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index cf6ba0c4b..003845250 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -59,7 +59,7 @@ template Date: Fri, 17 Aug 2012 21:55:03 +0200 Subject: [PATCH 38/78] SceneGraph: removed fugly hack for detecting scene. Previously the scene was its own parent, which was good sometimes back then, but it became so ugly and complicated hack ("my friend has access to my privates"-style) that it needed to be replaced with something less ugly. Now there is an function isScene() which is overloaded in Scene. Yes, it's possible to overload it anywhere else, but you better shouldn't even think about it. --- src/SceneGraph/Object.cpp | 15 ++++++++------- src/SceneGraph/Object.h | 8 ++++---- src/SceneGraph/Scene.h | 3 +-- src/SceneGraph/Test/SceneTest.cpp | 5 ++--- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/SceneGraph/Object.cpp b/src/SceneGraph/Object.cpp index f74602bb1..d0b56a1f6 100644 --- a/src/SceneGraph/Object.cpp +++ b/src/SceneGraph/Object.cpp @@ -27,14 +27,14 @@ namespace Magnum { namespace SceneGraph { template ObjectType* Object::setParent(ObjectType* parent) { /* Skip if nothing to do or this is scene */ - if(_parent == parent || _parent == this) return static_cast(this); + if(_parent == parent || isScene()) return static_cast(this); /* Add the object to children list of new parent */ if(parent != nullptr) { /* Only Fry can be his own grandfather */ ObjectType* p = parent; - while(p != nullptr && p->parent() != p) { + while(p != nullptr) { if(p == this) return static_cast(this); p = p->parent(); } @@ -64,7 +64,7 @@ templatetransformation()*t; /* We got to the scene, multiply with camera matrix */ - if(p->parent() == p) { + if(p->isScene()) { if(camera) { CORRADE_ASSERT(camera->scene() == scene(), "Object::absoluteTransformation(): the camera is not part of the same scene as object!", t); t = camera->cameraMatrix()*t; @@ -95,7 +95,7 @@ templateparent() == p) return static_cast(p); + if(p->isScene()) return static_cast(p); p = p->parent(); } @@ -103,7 +103,8 @@ template ObjectType* Object::setTransformation(const MatrixType& transformation) { - if(_parent == this) return static_cast(this); + /* Setting transformation is forbidden for the scene */ + if(isScene()) return static_cast(this); _transformation = transformation; setDirty(); @@ -131,8 +132,8 @@ templateparent() == nullptr || p->parent() == p || !p->parent()->isDirty()) + /* Stop on root object / clean object */ + if(p->parent() == nullptr || !p->parent()->isDirty()) break; p = p->parent(); diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 691baf688..6a1ccd02d 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -27,8 +27,6 @@ namespace Magnum { namespace SceneGraph { -template class Scene; - /** @todo User-specified Object implementation: - for front-to-back sorting, LoD changes etc. @@ -53,8 +51,6 @@ template& operator=(Object&& other) = delete; #endif - friend class Scene; - public: /** * @brief Constructor @@ -76,6 +72,9 @@ template class Scene; typedef Scene Scene2D; typedef Scene Scene3D; diff --git a/src/SceneGraph/Scene.h b/src/SceneGraph/Scene.h index 73e3793f0..58cc94fd1 100644 --- a/src/SceneGraph/Scene.h +++ b/src/SceneGraph/Scene.h @@ -26,8 +26,7 @@ namespace Magnum { namespace SceneGraph { /** @brief %Scene */ template class SCENEGRAPH_EXPORT Scene: public ObjectType { public: - /** @brief Constructor */ - inline Scene() { this->_parent = this; } + inline bool isScene() const { return true; } #ifndef DOXYGEN_GENERATING_OUTPUT void setParent(ObjectType* parent) = delete; diff --git a/src/SceneGraph/Test/SceneTest.cpp b/src/SceneGraph/Test/SceneTest.cpp index e2df35aa1..a3f859aa6 100644 --- a/src/SceneGraph/Test/SceneTest.cpp +++ b/src/SceneGraph/Test/SceneTest.cpp @@ -36,14 +36,13 @@ void SceneTest::transformation() { void SceneTest::parent() { Scene3D scene; - - CORRADE_VERIFY(scene.parent() == &scene); + CORRADE_VERIFY(scene.isScene()); /* Scene parent cannot be changed */ Object3D* scenePointer = &scene; Object3D object; scenePointer->setParent(&object); - CORRADE_VERIFY(scene.parent() == &scene); + CORRADE_VERIFY(scene.parent() == nullptr); CORRADE_VERIFY(scene.children().empty()); CORRADE_VERIFY(object.children().empty()); } From aa80ac55eeea6150ff922e18fc1533b25f4eb0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 21:57:59 +0200 Subject: [PATCH 39/78] SceneGraph: Added @todos for some Object weirdness. --- src/SceneGraph/Object.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SceneGraph/Object.cpp b/src/SceneGraph/Object.cpp index d0b56a1f6..c3831644b 100644 --- a/src/SceneGraph/Object.cpp +++ b/src/SceneGraph/Object.cpp @@ -35,6 +35,7 @@ template(this); p = p->parent(); } @@ -104,6 +105,7 @@ template ObjectType* Object::setTransformation(const MatrixType& transformation) { /* Setting transformation is forbidden for the scene */ + /** @todo Assert for this? */ if(isScene()) return static_cast(this); _transformation = transformation; From 58abfdeeeef74b371d7c88073aca98c42721e580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 22:08:40 +0200 Subject: [PATCH 40/78] SceneGraph: Using linked list from Corrade instead of std::set. Resulting (debug) executables are ~100 kB smaller, all operations which were previously logarithmic are now done in constant time and the whole implementation is a lot simpler. --- src/SceneGraph/Camera.cpp | 8 +++--- src/SceneGraph/Object.cpp | 42 ++++++++++-------------------- src/SceneGraph/Object.h | 30 ++++++++++++++------- src/SceneGraph/Test/ObjectTest.cpp | 11 +++++--- src/SceneGraph/Test/SceneTest.cpp | 4 +-- 5 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp index 46db61799..6f1101bcf 100644 --- a/src/SceneGraph/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -72,13 +72,13 @@ template void Camera::drawChildren(ObjectType* object, const MatrixType& transformationMatrix) { - for(typename set::const_iterator it = object->children().begin(); it != object->children().end(); ++it) { + for(ObjectType* i = object->firstChild(); i; i = i->nextSibling()) { /* Transformation matrix for the object */ - MatrixType matrix = transformationMatrix*(*it)->transformation(); + MatrixType matrix = transformationMatrix*i->transformation(); /* Draw the object and its children */ - (*it)->draw(matrix, static_cast(this)); - drawChildren(*it, matrix); + i->draw(matrix, static_cast(this)); + drawChildren(i, matrix); } } diff --git a/src/SceneGraph/Object.cpp b/src/SceneGraph/Object.cpp index c3831644b..f3de86b1c 100644 --- a/src/SceneGraph/Object.cpp +++ b/src/SceneGraph/Object.cpp @@ -27,28 +27,23 @@ namespace Magnum { namespace SceneGraph { template ObjectType* Object::setParent(ObjectType* parent) { /* Skip if nothing to do or this is scene */ - if(_parent == parent || isScene()) return static_cast(this); + if(this->parent() == parent || isScene()) return static_cast(this); - /* Add the object to children list of new parent */ - if(parent != nullptr) { - - /* Only Fry can be his own grandfather */ - ObjectType* p = parent; - while(p != nullptr) { - /** @todo Assert for this */ - if(p == this) return static_cast(this); - p = p->parent(); - } - - parent->_children.insert(static_cast(this)); + /* Only Fry can be his own grandfather */ + ObjectType* p = parent; + while(p) { + /** @todo Assert for this */ + if(p == this) return static_cast(this); + p = p->parent(); } /* Remove the object from old parent children list */ - if(_parent != nullptr) - _parent->_children.erase(static_cast(this)); + if(this->parent()) + this->parent()->cut(static_cast(this)); - /* Set new parent */ - _parent = parent; + /* Add the object to list of new parent */ + if(parent) + parent->insert(static_cast(this)); setDirty(); return static_cast(this); @@ -82,15 +77,6 @@ template Object::~Object() { - /* Remove the object from parent's children */ - setParent(nullptr); - - /* Delete all children */ - while(!_children.empty()) - delete *_children.begin(); -} - template SceneType* Object::scene() { /* Goes up the family tree until it finds object which is parent of itself (that's the scene) */ @@ -120,8 +106,8 @@ template::iterator it = _children.begin(); it != _children.end(); ++it) - (*it)->setDirty(); + for(ObjectType* i = firstChild(); i; i = i->nextSibling()) + i->setDirty(); } template void Object::setClean() { diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 6a1ccd02d..de69e990a 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -19,7 +19,7 @@ * @brief Class Magnum::SceneGraph::Object */ -#include +#include #include "Magnum.h" @@ -43,7 +43,7 @@ namespace Magnum { namespace SceneGraph { * @todo Transform transformation when changing parent, so the object stays in * place. */ -template class SCENEGRAPH_EXPORT Object { +template class SCENEGRAPH_EXPORT Object: public Corrade::Containers::DoubleLinkedList, public Corrade::Containers::DoubleLinkedListItem { #ifndef DOXYGEN_GENERATING_OUTPUT Object(const Object& other) = delete; Object(Object&& other) = delete; @@ -58,7 +58,7 @@ template::list(); } - /** @brief Child objects */ - inline const std::set& children() { return _children; } + /** @brief Previous sibling object or `nullptr`, if this is first object */ + inline ObjectType* previousSibling() { return Corrade::Containers::DoubleLinkedListItem::previous(); } + + /** @brief Next sibling object or `nullptr`, if this is last object */ + inline ObjectType* nextSibling() { return Corrade::Containers::DoubleLinkedListItem::next(); } + + /** @brief Whether this object has children */ + inline bool hasChildren() const { return !Corrade::Containers::DoubleLinkedList::isEmpty(); } + + /** @brief First child object or `nullptr`, if this object has no children */ + inline ObjectType* firstChild() { return Corrade::Containers::DoubleLinkedList::first(); } + + /** @brief Last child object or `nullptr`, if this object has no children */ + inline ObjectType* lastChild() { return Corrade::Containers::DoubleLinkedList::last(); } /** @brief Set parent object */ ObjectType* setParent(ObjectType* parent); @@ -230,8 +242,6 @@ template _children; MatrixType _transformation; bool dirty; }; diff --git a/src/SceneGraph/Test/ObjectTest.cpp b/src/SceneGraph/Test/ObjectTest.cpp index 06248e097..77f5a7afa 100644 --- a/src/SceneGraph/Test/ObjectTest.cpp +++ b/src/SceneGraph/Test/ObjectTest.cpp @@ -41,7 +41,10 @@ void ObjectTest::parenting() { Object3D* childTwo = new Object3D(&root); CORRADE_VERIFY(childOne->parent() == &root); - CORRADE_COMPARE(root.children().size(), 2); + CORRADE_VERIFY(childTwo->parent() == &root); + CORRADE_VERIFY(root.firstChild() == childOne); + CORRADE_VERIFY(root.lastChild() == childTwo); + CORRADE_VERIFY(root.firstChild()->nextSibling() == root.lastChild()); /* A object cannot be parent of itself */ childOne->setParent(childOne); @@ -53,12 +56,12 @@ void ObjectTest::parenting() { /* Reparent to another */ childTwo->setParent(childOne); - CORRADE_VERIFY(root.children().size() == 1 && *root.children().begin() == childOne); - CORRADE_VERIFY(childOne->children().size() == 1 && *childOne->children().begin() == childTwo); + CORRADE_VERIFY(root.firstChild() == childOne && root.firstChild()->nextSibling() == nullptr); + CORRADE_VERIFY(childOne->firstChild() == childTwo && childOne->firstChild()->nextSibling() == nullptr); /* Delete child */ delete childTwo; - CORRADE_VERIFY(childOne->children().empty()); + CORRADE_VERIFY(!childOne->hasChildren()); } void ObjectTest::transformation() { diff --git a/src/SceneGraph/Test/SceneTest.cpp b/src/SceneGraph/Test/SceneTest.cpp index a3f859aa6..65bff5daa 100644 --- a/src/SceneGraph/Test/SceneTest.cpp +++ b/src/SceneGraph/Test/SceneTest.cpp @@ -43,8 +43,8 @@ void SceneTest::parent() { Object3D object; scenePointer->setParent(&object); CORRADE_VERIFY(scene.parent() == nullptr); - CORRADE_VERIFY(scene.children().empty()); - CORRADE_VERIFY(object.children().empty()); + CORRADE_VERIFY(!scene.hasChildren()); + CORRADE_VERIFY(!object.hasChildren()); } }}} From 881f07ec7688c8244b2c5e272e954018d460af0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 17 Aug 2012 23:38:52 +0200 Subject: [PATCH 41/78] Added Object2D::move() to manage 2D stacking order. --- src/SceneGraph/Object.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index de69e990a..23c3e2a37 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -299,6 +299,16 @@ class SCENEGRAPH_EXPORT Object2D: public ObjectCorrade::Containers::DoubleLinkedList::move(this, under); + return this; + } }; /** @brief Three-dimensional object */ From 85de3109a9566f9af1db1260315bf6b8ffe533fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 18 Aug 2012 09:57:58 +0200 Subject: [PATCH 42/78] Adapted to Corrade changes. --- src/Framebuffer.h | 6 +++--- src/SceneGraph/Object.h | 18 +++++++++--------- src/Trade/AbstractImporter.h | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index b6e98c34b..b7eca5f0d 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -19,7 +19,7 @@ * @brief Class Magnum::Framebuffer */ -#include +#include #include "BufferedImage.h" #include "CubeMapTexture.h" @@ -110,7 +110,7 @@ class MAGNUM_EXPORT Framebuffer { Stencil = GL_STENCIL_BUFFER_BIT /**< Stencil value */ }; - typedef Corrade::Containers::Set ClearMask; /**< @brief Mask for clearing */ + typedef Corrade::Containers::EnumSet ClearMask; /**< @brief Mask for clearing */ /** * @brief Clear framebuffer @@ -1010,7 +1010,7 @@ class MAGNUM_EXPORT Framebuffer { * @requires_gl * @requires_gl30 Extension @extension{EXT,framebuffer_object} */ - typedef Corrade::Containers::Set BlitMask; + typedef Corrade::Containers::EnumSet BlitMask; /** * @brief Copy block of pixels from read to draw framebuffer diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 23c3e2a37..3f7d18803 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -19,7 +19,7 @@ * @brief Class Magnum::SceneGraph::Object */ -#include +#include #include "Magnum.h" @@ -43,7 +43,7 @@ namespace Magnum { namespace SceneGraph { * @todo Transform transformation when changing parent, so the object stays in * place. */ -template class SCENEGRAPH_EXPORT Object: public Corrade::Containers::DoubleLinkedList, public Corrade::Containers::DoubleLinkedListItem { +template class SCENEGRAPH_EXPORT Object: public Corrade::Containers::LinkedList, public Corrade::Containers::LinkedListItem { #ifndef DOXYGEN_GENERATING_OUTPUT Object(const Object& other) = delete; Object(Object&& other) = delete; @@ -82,22 +82,22 @@ template::list(); } + inline ObjectType* parent() { return Corrade::Containers::LinkedListItem::list(); } /** @brief Previous sibling object or `nullptr`, if this is first object */ - inline ObjectType* previousSibling() { return Corrade::Containers::DoubleLinkedListItem::previous(); } + inline ObjectType* previousSibling() { return Corrade::Containers::LinkedListItem::previous(); } /** @brief Next sibling object or `nullptr`, if this is last object */ - inline ObjectType* nextSibling() { return Corrade::Containers::DoubleLinkedListItem::next(); } + inline ObjectType* nextSibling() { return Corrade::Containers::LinkedListItem::next(); } /** @brief Whether this object has children */ - inline bool hasChildren() const { return !Corrade::Containers::DoubleLinkedList::isEmpty(); } + inline bool hasChildren() const { return !Corrade::Containers::LinkedList::isEmpty(); } /** @brief First child object or `nullptr`, if this object has no children */ - inline ObjectType* firstChild() { return Corrade::Containers::DoubleLinkedList::first(); } + inline ObjectType* firstChild() { return Corrade::Containers::LinkedList::first(); } /** @brief Last child object or `nullptr`, if this object has no children */ - inline ObjectType* lastChild() { return Corrade::Containers::DoubleLinkedList::last(); } + inline ObjectType* lastChild() { return Corrade::Containers::LinkedList::last(); } /** @brief Set parent object */ ObjectType* setParent(ObjectType* parent); @@ -306,7 +306,7 @@ class SCENEGRAPH_EXPORT Object2D: public ObjectCorrade::Containers::DoubleLinkedList::move(this, under); + list()->Corrade::Containers::LinkedList::move(this, under); return this; } }; diff --git a/src/Trade/AbstractImporter.h b/src/Trade/AbstractImporter.h index f978f6e94..0258b2b32 100644 --- a/src/Trade/AbstractImporter.h +++ b/src/Trade/AbstractImporter.h @@ -19,7 +19,7 @@ * @brief Class Magnum::Trade::AbstractImporter */ -#include +#include #include #include "ImageData.h" @@ -65,7 +65,7 @@ class MAGNUM_EXPORT AbstractImporter: public Corrade::PluginManager::Plugin { }; /** @brief Set of features supported by this importer */ - typedef Corrade::Containers::Set Features; + typedef Corrade::Containers::EnumSet Features; /** @brief Constructor */ inline AbstractImporter(Corrade::PluginManager::AbstractPluginManager* manager = nullptr, const std::string& plugin = ""): Plugin(manager, plugin) {} From 3298c5181a98aa2a9ac1be81d4d3e86890c4e8ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 18 Aug 2012 10:14:02 +0200 Subject: [PATCH 43/78] SceneGraph: Hiding LinkedList/LinkedListItem methods in Object. All of them have appropriate aliases, so it's not needed to expose both in public interface. --- src/SceneGraph/Object.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 3f7d18803..01ce166b7 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -242,6 +242,19 @@ template::first; + using Corrade::Containers::LinkedList::last; + using Corrade::Containers::LinkedList::isEmpty; + using Corrade::Containers::LinkedList::insert; + using Corrade::Containers::LinkedList::cut; + using Corrade::Containers::LinkedList::move; + using Corrade::Containers::LinkedList::erase; + using Corrade::Containers::LinkedList::clear; + using Corrade::Containers::LinkedListItem::list; + using Corrade::Containers::LinkedListItem::previous; + using Corrade::Containers::LinkedListItem::next; + MatrixType _transformation; bool dirty; }; @@ -306,7 +319,7 @@ class SCENEGRAPH_EXPORT Object2D: public ObjectCorrade::Containers::LinkedList::move(this, under); + parent()->Corrade::Containers::LinkedList::move(this, under); return this; } }; From 61cac0f1b30a1c05a1a4aadbb30be92638a69bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 18 Aug 2012 10:35:24 +0200 Subject: [PATCH 44/78] Renamed EglContext to XEglContext. X11 window and event handling will be used also elsewhere for desktop OpenGL, reflect its presence in the class name. --- CMakeLists.txt | 2 +- modules/FindMagnum.cmake | 4 ++-- src/Contexts/CMakeLists.txt | 12 +++++------ .../{EglContext.cpp => XEglContext.cpp} | 10 +++++----- src/Contexts/{EglContext.h => XEglContext.h} | 20 +++++++++---------- 5 files changed, 24 insertions(+), 24 deletions(-) rename src/Contexts/{EglContext.cpp => XEglContext.cpp} (95%) rename src/Contexts/{EglContext.h => XEglContext.h} (91%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 990245bcc..240f12297 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,7 +14,7 @@ option(WITH_PRIMITIVES "Builf Primitives library" OFF) option(WITH_SCENEGRAPH "Build SceneGraph library" OFF) option(WITH_SHADERS "Build Shaders library" OFF) -cmake_dependent_option(WITH_EGLCONTEXT "Build EglContext library" OFF "TARGET_GLES" OFF) +cmake_dependent_option(WITH_XEGLCONTEXT "Build XEglContext library" OFF "TARGET_GLES" OFF) cmake_dependent_option(WITH_GLUTCONTEXT "Build GlutContext library" OFF "NOT TARGET_GLES" OFF) option(WITH_SDL2CONTEXT "Build Sdl2Context library" OFF) diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 778b7b77d..4b1aa91e0 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -20,7 +20,7 @@ # Primitives - Library with stock geometric primitives (static) # SceneGraph - Scene graph library # Shaders - Library with stock shaders -# EglContext - EGL context (depends on EGL and X11 libraries) +# XEglContext - X/EGL context (depends on EGL and X11 libraries) # GlutContext - GLUT context (depends on GLUT library) # Sdl2Context - SDL2 context (depends on SDL2 library) # Example usage with specifying additional components is: @@ -112,7 +112,7 @@ foreach(component ${Magnum_FIND_COMPONENTS}) endif() # X/EGL context dependencies - if(${component} STREQUAL EglContext) + if(${component} STREQUAL XEglContext) find_package(EGL) find_package(X11) if(EGL_FOUND AND X11_FOUND) diff --git a/src/Contexts/CMakeLists.txt b/src/Contexts/CMakeLists.txt index 9adde18b6..e65a8ecee 100644 --- a/src/Contexts/CMakeLists.txt +++ b/src/Contexts/CMakeLists.txt @@ -26,16 +26,16 @@ if(WITH_SDL2CONTEXT) endif() # X/EGL context -if(WITH_EGLCONTEXT) +if(WITH_XEGLCONTEXT) find_package(EGL) find_package(X11) if(EGL_FOUND AND X11_FOUND) - add_library(MagnumEglContext STATIC EglContext.cpp) + add_library(MagnumXEglContext STATIC XEglContext.cpp) # X11 macros are a mess, disable warnings for C-style casts - set_target_properties(MagnumEglContext PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") - install(FILES EglContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) - install(TARGETS MagnumEglContext DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) + set_target_properties(MagnumXEglContext PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") + install(FILES XEglContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) + install(TARGETS MagnumXEglContext DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) else() - message(FATAL_ERROR "EGL or X11 libraries, required by EglContext, were not found. Set WITH_EGLCONTEXT to OFF to skip building it.") + message(FATAL_ERROR "EGL or X11 libraries, required by XEglContext, were not found. Set WITH_XEGLCONTEXT to OFF to skip building it.") endif() endif() diff --git a/src/Contexts/EglContext.cpp b/src/Contexts/XEglContext.cpp similarity index 95% rename from src/Contexts/EglContext.cpp rename to src/Contexts/XEglContext.cpp index b05890ab8..6486d8588 100644 --- a/src/Contexts/EglContext.cpp +++ b/src/Contexts/XEglContext.cpp @@ -13,7 +13,7 @@ GNU Lesser General Public License version 3 for more details. */ -#include "EglContext.h" +#include "XEglContext.h" #define None 0L // redef Xlib nonsense @@ -24,7 +24,7 @@ using namespace std; namespace Magnum { namespace Contexts { -EglContext::EglContext(int&, char**, const string& title, const Math::Vector2& size): viewportSize(size) { +XEglContext::XEglContext(int&, char**, const string& title, const Math::Vector2& size): viewportSize(size) { /* Get default X display and root window, init EGL */ xDisplay = XOpenDisplay(0); display = eglGetDisplay(xDisplay); @@ -116,13 +116,13 @@ EglContext::EglContext(int&, char**, const string& title, const Math::Vector2 @@ -16,7 +16,7 @@ */ /** @file - * @brief Class Magnum::Contexts::EglContext + * @brief Class Magnum::Contexts::XEglContext */ #include "Magnum.h" @@ -40,7 +40,7 @@ namespace Magnum { namespace Contexts { Supports keyboard and mouse handling. */ -class EglContext: public AbstractContext { +class XEglContext: public AbstractContext { public: /** * @brief Constructor @@ -51,14 +51,14 @@ class EglContext: public AbstractContext { * * Creates window with double-buffered OpenGL ES 2 context. */ - EglContext(int& argc, char** argv, const std::string& title = "Magnum X/EGL context", const Math::Vector2& size = Math::Vector2(800, 600)); + XEglContext(int& argc, char** argv, const std::string& title = "Magnum X/EGL context", const Math::Vector2& size = Math::Vector2(800, 600)); /** * @brief Destructor * * Deletes context and destroys the window. */ - ~EglContext(); + ~XEglContext(); int exec(); @@ -218,10 +218,10 @@ class EglContext: public AbstractContext { Math::Vector2 viewportSize; }; -inline void EglContext::keyPressEvent(EglContext::Key, const Math::Vector2&) {} -inline void EglContext::keyReleaseEvent(EglContext::Key, const Math::Vector2&) {} -inline void EglContext::mousePressEvent(EglContext::MouseButton, const Math::Vector2&) {} -inline void EglContext::mouseReleaseEvent(EglContext::MouseButton, const Math::Vector2&) {} +inline void XEglContext::keyPressEvent(XEglContext::Key, const Math::Vector2&) {} +inline void XEglContext::keyReleaseEvent(XEglContext::Key, const Math::Vector2&) {} +inline void XEglContext::mousePressEvent(XEglContext::MouseButton, const Math::Vector2&) {} +inline void XEglContext::mouseReleaseEvent(XEglContext::MouseButton, const Math::Vector2&) {} }} From db105839c5caa827fa40629edf74fec1a44a3a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 18 Aug 2012 15:51:17 +0200 Subject: [PATCH 45/78] Doc++ --- src/BufferedImage.h | 2 +- src/Image.h | 2 +- src/SceneGraph/Camera.h | 2 +- src/SceneGraph/Object.h | 2 +- src/SceneGraph/Scene.h | 4 +++- src/Swizzle.h | 6 +++--- src/Texture.h | 2 +- 7 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/BufferedImage.h b/src/BufferedImage.h index 5b91723c5..5489716df 100644 --- a/src/BufferedImage.h +++ b/src/BufferedImage.h @@ -16,7 +16,7 @@ */ /** @file - * @brief Class Magnum::BufferedImage + * @brief Class Magnum::BufferedImage, typedef Magnum::BufferedImage1D, Magnum::BufferedImage2D, Magnum::BufferedImage3D */ #include "AbstractImage.h" diff --git a/src/Image.h b/src/Image.h index 7a595786f..64557ea23 100644 --- a/src/Image.h +++ b/src/Image.h @@ -16,7 +16,7 @@ */ /** @file - * @brief Class Magnum::Image + * @brief Class Magnum::Image, typedef Magnum::Image1D, Magnum::Image2D, Magnum::Image3D */ #include "AbstractImage.h" diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index 003845250..64ed68d37 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -16,7 +16,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::Camera + * @brief Class Magnum::SceneGraph::Camera, Magnum::SceneGraph::Camera2D, Magnum::SceneGraph::Camera3D */ #include "Object.h" diff --git a/src/SceneGraph/Object.h b/src/SceneGraph/Object.h index 01ce166b7..b6a0d3861 100644 --- a/src/SceneGraph/Object.h +++ b/src/SceneGraph/Object.h @@ -16,7 +16,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::Object + * @brief Class Magnum::SceneGraph::Object, Magnum::SceneGraph::Object2D, Magnum::SceneGraph::Object3D */ #include diff --git a/src/SceneGraph/Scene.h b/src/SceneGraph/Scene.h index 58cc94fd1..2fd2e6fe9 100644 --- a/src/SceneGraph/Scene.h +++ b/src/SceneGraph/Scene.h @@ -16,7 +16,7 @@ */ /** @file - * @brief Class Magnum::SceneGraph::Scene + * @brief Class Magnum::SceneGraph::Scene, typedef Magnum::SceneGraph::Scene2D, Magnum::SceneGraph::Scene3D */ #include "Object.h" @@ -26,8 +26,10 @@ namespace Magnum { namespace SceneGraph { /** @brief %Scene */ template class SCENEGRAPH_EXPORT Scene: public ObjectType { public: + /** @copydoc Object::isScene() */ inline bool isScene() const { return true; } + /** @todo Some deleted functions belong only to Scene2D, some only to Scene3D - what to do? */ #ifndef DOXYGEN_GENERATING_OUTPUT void setParent(ObjectType* parent) = delete; void setTransformation(const MatrixType& transformation) = delete; diff --git a/src/Swizzle.h b/src/Swizzle.h index 84af4858b..22239225b 100644 --- a/src/Swizzle.h +++ b/src/Swizzle.h @@ -16,7 +16,7 @@ */ /** @file - * @brief Function Magnum::Math::swizzle() + * @brief Functions Magnum::swizzle(const T&), Magnum::swizzle(const T&, const char(&)[]) */ #include "Color.h" @@ -93,7 +93,7 @@ two, three or four-component, corresponding Vector2, Vector3 or Vector4 specialization is returned. @attention This function is less convenient to write than -swizzle(const Vector&, const char(&)[newSize]), but the evaluation of +swizzle(const T&, const char(&)[newSize]), but the evaluation of the swizzling operation is guaranteed to be always done at compile time instead of at runtime. @@ -119,7 +119,7 @@ two, three or four-component, corresponding Vector2, Vector3 or Vector4 specialization is returned. @attention This function is more convenient to write than -swizzle(const Vector&), but unless the result is marked with +swizzle(const T&), but unless the result is marked with `constexpr`, the evaluation of the swizzling operation probably won't be evaluated at compile time, but at runtime. diff --git a/src/Texture.h b/src/Texture.h index 7bb9e33b3..d31d2039b 100644 --- a/src/Texture.h +++ b/src/Texture.h @@ -16,7 +16,7 @@ */ /** @file - * @brief Class Magnum::Texture + * @brief Class Magnum::Texture, typedef Magnum::Texture1D, Magnum::Texture2D, Magnum::Texture3D */ #include "AbstractTexture.h" From 68872b03cf874a98f15586afa5d17f8535102194 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 7 Aug 2012 15:01:26 +0200 Subject: [PATCH 46/78] Added @requires_{gl43,gles30,es_extension} Doxygen aliases. --- Doxyfile | 8 ++++++-- doc/required-extensions.dox | 6 ++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Doxyfile b/Doxyfile index 40f5bcd66..fdfd9b5e7 100644 --- a/Doxyfile +++ b/Doxyfile @@ -206,8 +206,12 @@ ALIASES = \ "requires_gl40=@xrefitem requires-gl40 \"Requires OpenGL 4.0\" \"Functionality requiring OpenGL 4.0\"" \ "requires_gl41=@xrefitem requires-gl41 \"Requires OpenGL 4.1\" \"Functionality requiring OpenGL 4.1\"" \ "requires_gl42=@xrefitem requires-gl42 \"Requires OpenGL 4.2\" \"Functionality requiring OpenGL 4.2\"" \ - "requires_extension=@xrefitem requires-extension \"Requires extension\" \"Functionality requiring specific OpenGL extension\"" \ - "extension{2}=\1_\2" + "requires_gl43=@xrefitem requires-gl43 \"Requires OpenGL 4.3\" \"Functionality requiring OpenGL 4.3\"" \ + "requires_extension=@xrefitem requires-extension \"Requires OpenGL extension\" \"Functionality requiring specific OpenGL extension\"" \ + "extension{2}=\1_\2" \ + "requires_gles30=@xrefitem requires-gles30 \"Requires OpenGL ES 3.0\" \"Functionality requiring OpenGL ES 3.0\"" \ + "requires_es_extension=@xrefitem requires-es-extension \"Requires OpenGL ES extension\" \"Functionality requiring specific OpenGL ES extension\"" \ + "es_extension{2}=\1_\2" # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding diff --git a/doc/required-extensions.dox b/doc/required-extensions.dox index c35629ca5..443109d1a 100644 --- a/doc/required-extensions.dox +++ b/doc/required-extensions.dox @@ -20,7 +20,10 @@ supported on Intel GPUs even if they are capable of OpenGL 2.1 only). - @subpage requires-gl40 - @subpage requires-gl41 - @subpage requires-gl42 +- @subpage requires-gl43 - @subpage requires-extension +- @subpage requires-gles30 +- @subpage requires-es-extension @page requires-gl Functionality requiring desktop OpenGL (not available on OpenGL ES) @page requires-gl30 Functionality requiring OpenGL 3.0 @@ -30,6 +33,9 @@ supported on Intel GPUs even if they are capable of OpenGL 2.1 only). @page requires-gl40 Functionality requiring OpenGL 4.0 @page requires-gl41 Functionality requiring OpenGL 4.1 @page requires-gl42 Functionality requiring OpenGL 4.2 +@page requires-gl43 Functionality requiring OpenGL 4.3 @page requires-extension Functionality requiring specific OpenGL extension +@page requires-gles30 Functionality requiring OpenGL ES 3.0 +@page requires-es-extension Functionality requiring specific OpenGL ES extension */ From a87141b250db68f9c6040bbe068e0b3107842248 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 7 Aug 2012 15:27:41 +0200 Subject: [PATCH 47/78] Mention required version/extension in shader code. --- src/AbstractShaderProgram.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/AbstractShaderProgram.h b/src/AbstractShaderProgram.h index 827d238de..f50d20040 100644 --- a/src/AbstractShaderProgram.h +++ b/src/AbstractShaderProgram.h @@ -80,6 +80,8 @@ The preferred workflow is to specify attribute location for vertex shader input attributes and fragment shader output attributes explicitly in the shader code, e.g.: @code +#version 330 +// or #extension GL_ARB_explicit_attrib_location: enable layout(location = 0) in vec4 vertex; layout(location = 1) in vec3 normal; layout(location = 2) in vec2 textureCoords; @@ -122,6 +124,8 @@ bindFragmentDataLocationIndexed(1, 1, "ambient"); The preferred workflow is to specify texture layers directly in the shader code, e.g.: @code +#version 420 +// or #extension GL_ARB_shading_language_420pack: enable layout(binding = 0) uniform sampler2D diffuseTexture; layout(binding = 1) uniform sampler2D specularTexture; @endcode From 57b064a2ef714b9baeb4a236510495e839b1541f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Tue, 7 Aug 2012 15:54:36 +0200 Subject: [PATCH 48/78] Pixel pack buffer isn't available on ES2 either. --- src/Buffer.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Buffer.h b/src/Buffer.h index 2b7655b9c..c76260f3e 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -69,7 +69,10 @@ class Buffer { */ PixelUnpack = GL_PIXEL_UNPACK_BUFFER, - /** Target for pixel pack operations. */ + /** + * Target for pixel pack operations. + * @requires_gl + */ PixelPack = GL_PIXEL_PACK_BUFFER, /** From a46b51b11f945abf0fcf464466a5abc049627710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 18 Aug 2012 16:06:47 +0200 Subject: [PATCH 49/78] Updated for OpenGL ES 2 support. --- src/Framebuffer.h | 28 ++++++++++++++++++++++++---- src/Mesh.cpp | 7 +++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/Framebuffer.h b/src/Framebuffer.h index b7eca5f0d..4df94c9bf 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -58,13 +58,14 @@ class MAGNUM_EXPORT Framebuffer { */ Blending = GL_BLEND, + #ifndef MAGNUM_TARGET_GLES /** * Logical operation * @see setLogicOperation() + * @requires_gl Logic operations on framebuffer are in desktop OpenGL only. */ LogicOperation = GL_COLOR_LOGIC_OP, - #ifndef MAGNUM_TARGET_GLES /** * Depth clamping. If enabled, ignores near and far clipping plane. * @requires_gl @@ -393,9 +394,24 @@ class MAGNUM_EXPORT Framebuffer { enum class BlendEquation: GLenum { Add = GL_FUNC_ADD, /**< `source + destination` */ Subtract = GL_FUNC_SUBTRACT, /**< `source - destination` */ - ReverseSubtract = GL_FUNC_REVERSE_SUBTRACT, /**< `destination - source` */ - Min = GL_MIN, /**< `min(source, destination)` */ - Max = GL_MAX /**< `max(source, destination)` */ + ReverseSubtract = GL_FUNC_REVERSE_SUBTRACT /**< `destination - source` */ + + #ifndef MAGNUM_TARGET_GLES + /** @todo Enable for ES3 when the headers are available */ + , + + /** + * `min(source, destination)` + * @requires_gles30 Extension @es_extension{EXT,blend_minmax} + */ + Min = GL_MIN, + + /** + * `max(source, destination)` + * @requires_gles30 Extension @es_extension{EXT,blend_minmax} + */ + Max = GL_MAX + #endif }; /** @@ -585,12 +601,14 @@ class MAGNUM_EXPORT Framebuffer { /*@}*/ + #ifndef MAGNUM_TARGET_GLES /** @{ @name Logical operation */ /** * @brief Logical operation * * @see setLogicOperation() + * @requires_gl */ enum class LogicOperation: GLenum { Clear = GL_CLEAR, /**< `0` */ @@ -615,12 +633,14 @@ class MAGNUM_EXPORT Framebuffer { * @brief Set logical operation * * @attention You have to enable logical operation with setFeature() first. + * @requires_gl Logic operations on framebuffer are in desktop OpenGL only. */ inline static void setLogicOperation(LogicOperation operation) { glLogicOp(static_cast(operation)); } /*@}*/ + #endif /** @{ @name Framebuffer creation and binding */ diff --git a/src/Mesh.cpp b/src/Mesh.cpp index edd0f44bc..93d789c0c 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -26,7 +26,9 @@ Mesh::Mesh(Mesh&& other): #endif _primitive(other._primitive), _vertexCount(other._vertexCount), finalized(other.finalized), _buffers(other._buffers), _attributes(other._attributes) { + #ifndef MAGNUM_TARGET_GLES other.vao = 0; + #endif } void Mesh::destroy() { @@ -41,13 +43,18 @@ void Mesh::destroy() { Mesh& Mesh::operator=(Mesh&& other) { destroy(); + #ifndef MAGNUM_TARGET_GLES vao = other.vao; + #endif _primitive = other._primitive; _vertexCount = other._vertexCount; finalized = other.finalized; _buffers = other._buffers; _attributes = other._attributes; + + #ifndef MAGNUM_TARGET_GLES other.vao = 0; + #endif return *this; } From 442c9629aef4ffda92800d02a334b35938724650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 18 Aug 2012 22:00:33 +0200 Subject: [PATCH 50/78] Code reorganization. --- src/Contexts/XEglContext.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Contexts/XEglContext.cpp b/src/Contexts/XEglContext.cpp index 6486d8588..8fbd47fec 100644 --- a/src/Contexts/XEglContext.cpp +++ b/src/Contexts/XEglContext.cpp @@ -34,8 +34,6 @@ XEglContext::XEglContext(int&, char**, const string& title, const Math::Vector2< #else eglBindAPI(EGL_OPENGL_ES_API); #endif - int screenNumber = DefaultScreen(xDisplay); - Window root = RootWindow(xDisplay, screenNumber); /* Choose EGL config */ static const EGLint attribs[] = { @@ -73,6 +71,7 @@ XEglContext::XEglContext(int&, char**, const string& title, const Math::Vector2< } /* Create X Window */ + Window root = RootWindow(xDisplay, DefaultScreen(display)); XSetWindowAttributes attr; attr.background_pixel = 0; attr.border_pixel = 0; From 0f579efe854566371b7f732661296e7ef9bf4d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 18 Aug 2012 22:52:22 +0200 Subject: [PATCH 51/78] Undef some more Xlib nonsense. --- src/Contexts/XEglContext.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Contexts/XEglContext.h b/src/Contexts/XEglContext.h index e39fabe19..496ce7c63 100644 --- a/src/Contexts/XEglContext.h +++ b/src/Contexts/XEglContext.h @@ -22,9 +22,9 @@ #include "Magnum.h" #include -#ifdef None // undef Xlib nonsense to avoid conflicts +/* undef Xlib nonsense to avoid conflicts */ #undef None -#endif +#undef Always #ifndef SUPPORT_X11 #define SUPPORT_X11 // OpenGL ES on BeagleBoard needs this (?) From e372a716369c661f070dda3fa538e7b05f5e699f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 18 Aug 2012 22:56:25 +0200 Subject: [PATCH 52/78] Decoupled EGL interface from XEglContext. New class EglInterface now handles only EGL, AbstractXContext is able to take any OpenGL interface sublassed from AbstractGlInterface. --- src/Contexts/AbstractGlInterface.h | 53 ++++ .../{XEglContext.cpp => AbstractXContext.cpp} | 105 +++----- src/Contexts/AbstractXContext.h | 227 ++++++++++++++++++ src/Contexts/CMakeLists.txt | 41 +++- src/Contexts/EglInterface.cpp | 86 +++++++ src/Contexts/EglInterface.h | 71 ++++++ src/Contexts/XEglContext.h | 191 +-------------- 7 files changed, 502 insertions(+), 272 deletions(-) create mode 100644 src/Contexts/AbstractGlInterface.h rename src/Contexts/{XEglContext.cpp => AbstractXContext.cpp} (50%) create mode 100644 src/Contexts/AbstractXContext.h create mode 100644 src/Contexts/EglInterface.cpp create mode 100644 src/Contexts/EglInterface.h diff --git a/src/Contexts/AbstractGlInterface.h b/src/Contexts/AbstractGlInterface.h new file mode 100644 index 000000000..629eb1dc3 --- /dev/null +++ b/src/Contexts/AbstractGlInterface.h @@ -0,0 +1,53 @@ +#ifndef Magnum_Contexts_AbstractGlInterface_h +#define Magnum_Contexts_AbstractGlInterface_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::Contexts::AbstractGlInterface + */ + +namespace Magnum { namespace Contexts { + +/** @brief Base for OpenGL interfaces */ +template class AbstractGlInterface { + public: + /** + * @brief Get visual ID + * + * Initializes the interface on given display and returns visual ID. + */ + virtual VisualId getVisualId(Display nativeDisplay) = 0; + + /** + * @brief Destructor + * + * Finalizes and closes the interface. + */ + virtual ~AbstractGlInterface() {} + + /** @brief Create context */ + virtual void createContext(Window nativeWindow) = 0; + + /** @brief Make the context current */ + virtual void makeCurrent() = 0; + + /** @brief Swap buffers */ + virtual void swapBuffers() = 0; +}; + +}} + +#endif diff --git a/src/Contexts/XEglContext.cpp b/src/Contexts/AbstractXContext.cpp similarity index 50% rename from src/Contexts/XEglContext.cpp rename to src/Contexts/AbstractXContext.cpp index 8fbd47fec..5195b5387 100644 --- a/src/Contexts/XEglContext.cpp +++ b/src/Contexts/AbstractXContext.cpp @@ -13,7 +13,7 @@ GNU Lesser General Public License version 3 for more details. */ -#include "XEglContext.h" +#include "AbstractXContext.h" #define None 0L // redef Xlib nonsense @@ -24,117 +24,70 @@ using namespace std; namespace Magnum { namespace Contexts { -XEglContext::XEglContext(int&, char**, const string& title, const Math::Vector2& size): viewportSize(size) { - /* Get default X display and root window, init EGL */ - xDisplay = XOpenDisplay(0); - display = eglGetDisplay(xDisplay); - eglInitialize(display, 0, 0); - #ifndef MAGNUM_TARGET_GLES - eglBindAPI(EGL_OPENGL_API); - #else - eglBindAPI(EGL_OPENGL_ES_API); - #endif +AbstractXContext::AbstractXContext(AbstractGlInterface* glInterface, int&, char**, const string& title, const Math::Vector2& size): glInterface(glInterface), viewportSize(size) { + /* Get default X display */ + display = XOpenDisplay(0); - /* Choose EGL config */ - static const EGLint attribs[] = { - EGL_RED_SIZE, 1, - EGL_GREEN_SIZE, 1, - EGL_BLUE_SIZE, 1, - EGL_DEPTH_SIZE, 1, - #ifndef MAGNUM_TARGET_GLES - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, - #else - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - #endif - EGL_NONE - }; - EGLConfig config; - EGLint configCount; - if(!eglChooseConfig(display, attribs, &config, 1, &configCount)) { - Error() << "Cannot get EGL visual config"; - exit(1); - } + /* Get visual ID */ + VisualID visualId = glInterface->getVisualId(display); - /* Get X visual */ - EGLint visualId; - if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visualId)) { - Error() << "Cannot get native visual ID"; - exit(1); - } + /* Get visual info */ XVisualInfo *visInfo, visTemplate; int visualCount; visTemplate.visualid = visualId; - visInfo = XGetVisualInfo(xDisplay, VisualIDMask, &visTemplate, &visualCount); + visInfo = XGetVisualInfo(display, VisualIDMask, &visTemplate, &visualCount); if(!visInfo) { Error() << "Cannot get X visual"; exit(1); } /* Create X Window */ - Window root = RootWindow(xDisplay, DefaultScreen(display)); + Window root = RootWindow(display, DefaultScreen(display)); XSetWindowAttributes attr; attr.background_pixel = 0; attr.border_pixel = 0; - attr.colormap = XCreateColormap(xDisplay, root, visInfo->visual, AllocNone); + attr.colormap = XCreateColormap(display, root, visInfo->visual, AllocNone); attr.event_mask = 0; unsigned long mask = CWBackPixel|CWBorderPixel|CWColormap|CWEventMask; - xWindow = XCreateWindow(xDisplay, root, 20, 20, size.x(), size.y(), 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr); - XSetStandardProperties(xDisplay, xWindow, title.c_str(), 0, None, 0, 0, 0); + window = XCreateWindow(display, root, 20, 20, size.x(), size.y(), 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr); + XSetStandardProperties(display, window, title.c_str(), 0, None, 0, 0, 0); XFree(visInfo); /* Be notified about closing the window */ - deleteWindow = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True); - XSetWMProtocols(xDisplay, xWindow, &deleteWindow, 1); - - /* Create context and window surface */ - static const EGLint contextAttributes[] = { - #ifdef MAGNUM_TARGET_GLES - EGL_CONTEXT_CLIENT_VERSION, 2, - #endif - EGL_NONE - }; - context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes); - if(!context) { - Error() << "Cannot create EGL context"; - exit(1); - } - surface = eglCreateWindowSurface(display, config, xWindow, NULL); - if(!surface) { - Error() << "Cannot create window surface"; - exit(1); - } + deleteWindow = XInternAtom(display, "WM_DELETE_WINDOW", True); + XSetWMProtocols(display, window, &deleteWindow, 1); + + /* Create context */ + glInterface->createContext(window); /* Capture exposure, keyboard and mouse button events */ - XSelectInput(xDisplay, xWindow, INPUT_MASK); + XSelectInput(display, window, INPUT_MASK); /* Set OpenGL context as current */ - eglMakeCurrent(display, surface, surface, context); + glInterface->makeCurrent(); - /** @bug Fixme: GLEW initialization fails (thinks that the context is not created) */ #ifndef MAGNUM_TARGET_GLES /* Init GLEW */ GLenum err = glewInit(); if(err != GLEW_OK) { - Error() << "XEglContext: cannot initialize GLEW:" << glewGetErrorString(err); + Error() << "AbstractXContext: cannot initialize GLEW:" << glewGetErrorString(err); exit(1); } #endif } -XEglContext::~XEglContext() { - /* Shut down EGL */ - eglDestroyContext(display, context); - eglDestroySurface(display, surface); - eglTerminate(display); +AbstractXContext::~AbstractXContext() { + /* Shut down the interface */ + delete glInterface; /* Shut down X */ - XDestroyWindow(xDisplay, xWindow); - XCloseDisplay(xDisplay); + XDestroyWindow(display, window); + XCloseDisplay(display); } -int XEglContext::exec() { +int AbstractXContext::exec() { /* Show window */ - XMapWindow(xDisplay, xWindow); + XMapWindow(display, window); /* Call viewportEvent for the first time */ viewportEvent(viewportSize); @@ -143,12 +96,12 @@ int XEglContext::exec() { XEvent event; /* Closed window */ - if(XCheckTypedWindowEvent(xDisplay, xWindow, ClientMessage, &event) && + if(XCheckTypedWindowEvent(display, window, ClientMessage, &event) && Atom(event.xclient.data.l[0]) == deleteWindow) { return 0; } - while(XCheckWindowEvent(xDisplay, xWindow, INPUT_MASK, &event)) { + while(XCheckWindowEvent(display, window, INPUT_MASK, &event)) { switch(event.type) { /* Window resizing */ case ConfigureNotify: { diff --git a/src/Contexts/AbstractXContext.h b/src/Contexts/AbstractXContext.h new file mode 100644 index 000000000..971240d98 --- /dev/null +++ b/src/Contexts/AbstractXContext.h @@ -0,0 +1,227 @@ +#ifndef Magnum_Contexts_AbstractXContext_h +#define Magnum_Contexts_AbstractXContext_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::Contexts::AbstractXContext + */ + +#include "Magnum.h" + +#include +#include +/* undef Xlib nonsense to avoid conflicts */ +#undef None +#undef Always + +#include "AbstractContext.h" +#include "AbstractGlInterface.h" + +namespace Magnum { namespace Contexts { + +/** +@brief Base for X11-based contexts + +Supports keyboard and mouse handling. + +@note Not meant to be used directly, see subclasses. +*/ +class AbstractXContext: public AbstractContext { + public: + /** + * @brief Constructor + * @param glInterface Interface to OpenGL + * @param argc Count of arguments of `main()` function + * @param argv Arguments of `main()` function + * @param title Window title + * @param size Window size + * + * Creates window with double-buffered OpenGL ES 2 context. + */ + AbstractXContext(AbstractGlInterface* glInterface, int& argc, char** argv, const std::string& title = "Magnum X/EGL context", const Math::Vector2& size = Math::Vector2(800, 600)); + + /** + * @brief Destructor + * + * Deletes context and destroys the window. + */ + virtual ~AbstractXContext() = 0; + + int exec(); + + /** @{ @name Drawing functions */ + + protected: + /** @copydoc GlutContext::viewportEvent() */ + virtual void viewportEvent(const Math::Vector2& size) = 0; + + /** @copydoc GlutContext::drawEvent() */ + virtual void drawEvent() = 0; + + /** @copydoc GlutContext::swapBuffers() */ + inline void swapBuffers() { glInterface->swapBuffers(); } + + /** @todo implement */ + inline void redraw() {} + + /*@}*/ + + /** @{ @name Keyboard handling */ + + public: + /** @brief Key */ + enum class Key: KeySym { + Up = XK_Up, /**< Up arrow */ + Down = XK_Down, /**< Down arrow */ + Left = XK_Left, /**< Left arrow */ + Right = XK_Right, /**< Right arrow */ + F1 = XK_F1, /**< F1 */ + F2 = XK_F2, /**< F2 */ + F3 = XK_F3, /**< F3 */ + F4 = XK_F4, /**< F4 */ + F5 = XK_F5, /**< F5 */ + F6 = XK_F6, /**< F6 */ + F7 = XK_F7, /**< F7 */ + F8 = XK_F8, /**< F8 */ + F9 = XK_F9, /**< F9 */ + F10 = XK_F10, /**< F10 */ + F11 = XK_F11, /**< F11 */ + F12 = XK_F12, /**< F12 */ + Home = XK_Home, /**< Home */ + End = XK_End, /**< End */ + PageUp = XK_Page_Up, /**< Page up */ + PageDown = XK_Page_Down, /**< Page down */ + + Space = XK_space, /**< Space */ + Comma = XK_comma, /**< Comma */ + Period = XK_period, /**< Period */ + Minus = XK_minus, /**< Minus */ + Plus = XK_plus, /**< Plus */ + Slash = XK_slash, /**< Slash */ + Percent = XK_percent, /**< Percent */ + Equal = XK_equal, /**< Equal */ + + Zero = XK_0, /**< Zero */ + One = XK_1, /**< One */ + Two = XK_2, /**< Two */ + Three = XK_3, /**< Three */ + Four = XK_4, /**< Four */ + Five = XK_5, /**< Five */ + Six = XK_6, /**< Six */ + Seven = XK_7, /**< Seven */ + Eight = XK_8, /**< Eight */ + Nine = XK_9, /**< Nine */ + + A = XK_a, /**< Small letter A */ + B = XK_b, /**< Small letter B */ + C = XK_c, /**< Small letter C */ + D = XK_d, /**< Small letter D */ + E = XK_e, /**< Small letter E */ + F = XK_f, /**< Small letter F */ + G = XK_g, /**< Small letter G */ + H = XK_h, /**< Small letter H */ + I = XK_i, /**< Small letter I */ + J = XK_j, /**< Small letter J */ + K = XK_k, /**< Small letter K */ + L = XK_l, /**< Small letter L */ + M = XK_m, /**< Small letter M */ + N = XK_n, /**< Small letter N */ + O = XK_o, /**< Small letter O */ + P = XK_p, /**< Small letter P */ + Q = XK_q, /**< Small letter Q */ + R = XK_r, /**< Small letter R */ + S = XK_s, /**< Small letter S */ + T = XK_t, /**< Small letter T */ + U = XK_u, /**< Small letter U */ + V = XK_v, /**< Small letter V */ + W = XK_w, /**< Small letter W */ + X = XK_x, /**< Small letter X */ + Y = XK_y, /**< Small letter Y */ + Z = XK_z /**< Small letter Z */ + }; + + protected: + /** + * @brief Key press event + * @param key Key pressed + * @param position Cursor position + * + * Called when an key is pressed. Default implementation does nothing. + */ + virtual void keyPressEvent(Key key, const Math::Vector2& position); + + /** + * @brief Key press event + * @param key Key released + * @param position Cursor position + * + * Called when an key is released. Default implementation does nothing. + */ + virtual void keyReleaseEvent(Key key, const Math::Vector2& position); + + /*@}*/ + + /** @{ @name Mouse handling */ + + public: + /** @brief Mouse button */ + enum class MouseButton: unsigned int { + Left = Button1, /**< Left button */ + Middle = Button2, /**< Middle button */ + Right = Button3, /**< Right button */ + WheelUp = Button4, /**< Wheel up */ + WheelDown = Button5 /**< Wheel down */ + }; + + protected: + /** + * @brief Mouse press event + * + * Called when mouse button is pressed. Default implementation does + * nothing. + */ + virtual void mousePressEvent(MouseButton button, const Math::Vector2& position); + + /** + * @brief Mouse release event + * + * Called when mouse button is released. Default implementation does + * nothing. + */ + virtual void mouseReleaseEvent(MouseButton button, const Math::Vector2& position); + + /*@}*/ + + private: + Display* display; + Window window; + Atom deleteWindow; + + AbstractGlInterface* glInterface; + + /** @todo Get this from the created window */ + Math::Vector2 viewportSize; +}; + +inline void AbstractXContext::keyPressEvent(AbstractXContext::Key, const Math::Vector2&) {} +inline void AbstractXContext::keyReleaseEvent(AbstractXContext::Key, const Math::Vector2&) {} +inline void AbstractXContext::mousePressEvent(AbstractXContext::MouseButton, const Math::Vector2&) {} +inline void AbstractXContext::mouseReleaseEvent(AbstractXContext::MouseButton, const Math::Vector2&) {} + + +}} + +#endif diff --git a/src/Contexts/CMakeLists.txt b/src/Contexts/CMakeLists.txt index e65a8ecee..dee2f25e6 100644 --- a/src/Contexts/CMakeLists.txt +++ b/src/Contexts/CMakeLists.txt @@ -1,4 +1,7 @@ -install(FILES AbstractContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) +set(MagnumContexts_HEADERS + AbstractContext.h + AbstractGlInterface.h) +install(FILES ${MagnumContexts_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) # GLUT context if(WITH_GLUTCONTEXT) @@ -27,15 +30,33 @@ endif() # X/EGL context if(WITH_XEGLCONTEXT) - find_package(EGL) + set(NEED_ABSTRACTXCONTEXT 1) + set(NEED_EGLINTERFACE 1) + add_library(MagnumXEglContext STATIC $ $) + install(FILES XEglContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) + install(TARGETS MagnumXEglContext DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +endif() + +# Abstract X context +if(NEED_ABSTRACTXCONTEXT) find_package(X11) - if(EGL_FOUND AND X11_FOUND) - add_library(MagnumXEglContext STATIC XEglContext.cpp) - # X11 macros are a mess, disable warnings for C-style casts - set_target_properties(MagnumXEglContext PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") - install(FILES XEglContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) - install(TARGETS MagnumXEglContext DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) - else() - message(FATAL_ERROR "EGL or X11 libraries, required by XEglContext, were not found. Set WITH_XEGLCONTEXT to OFF to skip building it.") + if(NOT X11_FOUND) + message(FATAL_ERROR "X11 library, required by some contexts, was not found. Set WITH_*X*CONTEXT to OFF to skip building them.") + endif() + add_library(MagnumAbstractXContext OBJECT AbstractXContext.cpp) + # X11 macros are a mess, disable warnings for C-style casts + set_target_properties(MagnumAbstractXContext PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") + install(FILES AbstractXContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) +endif() + +# EGL interface +if(NEED_EGLINTERFACE) + find_package(EGL) + if(NOT EGL_FOUND) + message(FATAL_ERROR "EGL library, required by some contexts, was not found. Set WITH_*EGL*CONTEXT to OFF to skip building them.") endif() + add_library(MagnumEglInterface OBJECT EglInterface.cpp) + # X11 macros are a mess, disable warnings for C-style casts + set_target_properties(MagnumEglInterface PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") + install(FILES EglInterface.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) endif() diff --git a/src/Contexts/EglInterface.cpp b/src/Contexts/EglInterface.cpp new file mode 100644 index 000000000..609f37322 --- /dev/null +++ b/src/Contexts/EglInterface.cpp @@ -0,0 +1,86 @@ +/* + 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 "EglInterface.h" + +namespace Magnum { namespace Contexts { + +EglInterface::~EglInterface() { + eglDestroyContext(display, context); + eglDestroySurface(display, surface); + eglTerminate(display); +} + +VisualId EglInterface::getVisualId(EGLNativeDisplayType nativeDisplay) { + /* Initialize */ + display = eglGetDisplay(nativeDisplay); + eglInitialize(display, 0, 0); + #ifndef MAGNUM_TARGET_GLES + eglBindAPI(EGL_OPENGL_API); + #else + eglBindAPI(EGL_OPENGL_ES_API); + #endif + + /* Choose EGL config */ + static const EGLint attribs[] = { + EGL_RED_SIZE, 1, + EGL_GREEN_SIZE, 1, + EGL_BLUE_SIZE, 1, + EGL_DEPTH_SIZE, 1, + #ifndef MAGNUM_TARGET_GLES + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, + #else + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + #endif + EGL_NONE + }; + EGLint configCount; + if(!eglChooseConfig(display, attribs, &config, 1, &configCount)) { + Error() << "Cannot get EGL visual config"; + exit(1); + } + + /* Get visual ID */ + EGLint visualId; + if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &visualId)) { + Error() << "Cannot get native visual ID"; + exit(1); + } + + return visualId; +} + +void EglInterface::createContext(EGLNativeWindowType window) { + static const EGLint contextAttributes[] = { + #ifdef MAGNUM_TARGET_GLES + EGL_CONTEXT_CLIENT_VERSION, 2, + #endif + EGL_NONE + }; + context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttributes); + if(!context) { + Error() << "Cannot create EGL context"; + exit(1); + } + surface = eglCreateWindowSurface(display, config, window, NULL); + if(!surface) { + Error() << "Cannot create window surface"; + exit(1); + } + + /** @bug Fixme: On desktop OpenGL and Mesa EGL implementation OpenGL version is 1.0, which is wrong */ +} + +}} diff --git a/src/Contexts/EglInterface.h b/src/Contexts/EglInterface.h new file mode 100644 index 000000000..671d6df18 --- /dev/null +++ b/src/Contexts/EglInterface.h @@ -0,0 +1,71 @@ +#ifndef Magnum_Contexts_EglInterface_h +#define Magnum_Contexts_EglInterface_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::Contexts::EglInterface + */ + +#include "Magnum.h" + +#ifndef SUPPORT_X11 +#define SUPPORT_X11 // OpenGL ES on BeagleBoard needs this (?) +#endif +#include + +#include "AbstractGlInterface.h" + +namespace Magnum { namespace Contexts { + +#ifndef DOXYGEN_GENERATING_OUTPUT +/* EGL returns visual ID as int, but Xorg expects long unsigned int */ +#ifdef __unix__ +typedef VisualID VisualId; +#else +typedef EGLInt VisualId; +#endif +#endif + +/** +@brief EGL interface + +Used in XEglContext. +*/ +class EglInterface: public AbstractGlInterface { + public: + ~EglInterface(); + + VisualId getVisualId(EGLNativeDisplayType nativeDisplay); + void createContext(EGLNativeWindowType nativeWindow); + + inline void makeCurrent() { + eglMakeCurrent(display, surface, surface, context); + } + + inline void swapBuffers() { + eglSwapBuffers(display, surface); + } + + private: + EGLDisplay display; + EGLConfig config; + EGLSurface surface; + EGLContext context; +}; + +}} + +#endif diff --git a/src/Contexts/XEglContext.h b/src/Contexts/XEglContext.h index 496ce7c63..fb368c1db 100644 --- a/src/Contexts/XEglContext.h +++ b/src/Contexts/XEglContext.h @@ -19,28 +19,17 @@ * @brief Class Magnum::Contexts::XEglContext */ -#include "Magnum.h" - -#include -/* undef Xlib nonsense to avoid conflicts */ -#undef None -#undef Always - -#ifndef SUPPORT_X11 -#define SUPPORT_X11 // OpenGL ES on BeagleBoard needs this (?) -#endif -#include - -#include "AbstractContext.h" +#include "AbstractXContext.h" +#include "EglInterface.h" namespace Magnum { namespace Contexts { /** @brief X/EGL context -Supports keyboard and mouse handling. +Uses EglInterface. */ -class XEglContext: public AbstractContext { +class XEglContext: public AbstractXContext { public: /** * @brief Constructor @@ -51,179 +40,9 @@ class XEglContext: public AbstractContext { * * Creates window with double-buffered OpenGL ES 2 context. */ - XEglContext(int& argc, char** argv, const std::string& title = "Magnum X/EGL context", const Math::Vector2& size = Math::Vector2(800, 600)); - - /** - * @brief Destructor - * - * Deletes context and destroys the window. - */ - ~XEglContext(); - - int exec(); - - /** @{ @name Drawing functions */ - - protected: - /** @copydoc GlutContext::viewportEvent() */ - virtual void viewportEvent(const Math::Vector2& size) = 0; - - /** @copydoc GlutContext::drawEvent() */ - virtual void drawEvent() = 0; - - /** @copydoc GlutContext::swapBuffers() */ - inline void swapBuffers() { eglSwapBuffers(display, surface); } - - /** @todo implement */ - inline void redraw() {} - - /*@}*/ - - /** @{ @name Keyboard handling */ - - public: - /** @brief Key */ - enum class Key: KeySym { - Up = XK_Up, /**< Up arrow */ - Down = XK_Down, /**< Down arrow */ - Left = XK_Left, /**< Left arrow */ - Right = XK_Right, /**< Right arrow */ - F1 = XK_F1, /**< F1 */ - F2 = XK_F2, /**< F2 */ - F3 = XK_F3, /**< F3 */ - F4 = XK_F4, /**< F4 */ - F5 = XK_F5, /**< F5 */ - F6 = XK_F6, /**< F6 */ - F7 = XK_F7, /**< F7 */ - F8 = XK_F8, /**< F8 */ - F9 = XK_F9, /**< F9 */ - F10 = XK_F10, /**< F10 */ - F11 = XK_F11, /**< F11 */ - F12 = XK_F12, /**< F12 */ - Home = XK_Home, /**< Home */ - End = XK_End, /**< End */ - PageUp = XK_Page_Up, /**< Page up */ - PageDown = XK_Page_Down, /**< Page down */ - - Space = XK_space, /**< Space */ - Comma = XK_comma, /**< Comma */ - Period = XK_period, /**< Period */ - Minus = XK_minus, /**< Minus */ - Plus = XK_plus, /**< Plus */ - Slash = XK_slash, /**< Slash */ - Percent = XK_percent, /**< Percent */ - Equal = XK_equal, /**< Equal */ - - Zero = XK_0, /**< Zero */ - One = XK_1, /**< One */ - Two = XK_2, /**< Two */ - Three = XK_3, /**< Three */ - Four = XK_4, /**< Four */ - Five = XK_5, /**< Five */ - Six = XK_6, /**< Six */ - Seven = XK_7, /**< Seven */ - Eight = XK_8, /**< Eight */ - Nine = XK_9, /**< Nine */ - - A = XK_a, /**< Small letter A */ - B = XK_b, /**< Small letter B */ - C = XK_c, /**< Small letter C */ - D = XK_d, /**< Small letter D */ - E = XK_e, /**< Small letter E */ - F = XK_f, /**< Small letter F */ - G = XK_g, /**< Small letter G */ - H = XK_h, /**< Small letter H */ - I = XK_i, /**< Small letter I */ - J = XK_j, /**< Small letter J */ - K = XK_k, /**< Small letter K */ - L = XK_l, /**< Small letter L */ - M = XK_m, /**< Small letter M */ - N = XK_n, /**< Small letter N */ - O = XK_o, /**< Small letter O */ - P = XK_p, /**< Small letter P */ - Q = XK_q, /**< Small letter Q */ - R = XK_r, /**< Small letter R */ - S = XK_s, /**< Small letter S */ - T = XK_t, /**< Small letter T */ - U = XK_u, /**< Small letter U */ - V = XK_v, /**< Small letter V */ - W = XK_w, /**< Small letter W */ - X = XK_x, /**< Small letter X */ - Y = XK_y, /**< Small letter Y */ - Z = XK_z /**< Small letter Z */ - }; - - protected: - /** - * @brief Key press event - * @param key Key pressed - * @param position Cursor position - * - * Called when an key is pressed. Default implementation does nothing. - */ - virtual void keyPressEvent(Key key, const Math::Vector2& position); - - /** - * @brief Key press event - * @param key Key released - * @param position Cursor position - * - * Called when an key is released. Default implementation does nothing. - */ - virtual void keyReleaseEvent(Key key, const Math::Vector2& position); - - /*@}*/ - - /** @{ @name Mouse handling */ - - public: - /** @brief Mouse button */ - enum class MouseButton: unsigned int { - Left = Button1, /**< Left button */ - Middle = Button2, /**< Middle button */ - Right = Button3, /**< Right button */ - WheelUp = Button4, /**< Wheel up */ - WheelDown = Button5 /**< Wheel down */ - }; - - protected: - /** - * @brief Mouse press event - * - * Called when mouse button is pressed. Default implementation does - * nothing. - */ - virtual void mousePressEvent(MouseButton button, const Math::Vector2& position); - - /** - * @brief Mouse release event - * - * Called when mouse button is released. Default implementation does - * nothing. - */ - virtual void mouseReleaseEvent(MouseButton button, const Math::Vector2& position); - - /*@}*/ - - private: - Display* xDisplay; - Window xWindow; - Atom deleteWindow; - - EGLDisplay display; - EGLSurface surface; - EGLContext context; - - /** @todo Get this from the created window */ - Math::Vector2 viewportSize; + inline XEglContext(int& argc, char** argv, const std::string& title = "Magnum X/EGL context", const Math::Vector2& size = Math::Vector2(800, 600)): AbstractXContext(new EglInterface, argc, argv, title, size) {} }; -inline void XEglContext::keyPressEvent(XEglContext::Key, const Math::Vector2&) {} -inline void XEglContext::keyReleaseEvent(XEglContext::Key, const Math::Vector2&) {} -inline void XEglContext::mousePressEvent(XEglContext::MouseButton, const Math::Vector2&) {} -inline void XEglContext::mouseReleaseEvent(XEglContext::MouseButton, const Math::Vector2&) {} - - }} #endif From a3bc29a0005a181084b140c9c1655870e15700c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 01:48:35 +0200 Subject: [PATCH 53/78] Separate class for extension wrangler initialization. --- src/Contexts/AbstractGlInterface.h | 11 +++++++++ src/Contexts/AbstractXContext.cpp | 12 +++------ src/Contexts/CMakeLists.txt | 19 ++++++++++++--- src/Contexts/ExtensionWrangler.cpp | 37 ++++++++++++++++++++++++++++ src/Contexts/ExtensionWrangler.h | 39 ++++++++++++++++++++++++++++++ src/Contexts/GlutContext.cpp | 9 +++---- src/Contexts/Sdl2Context.cpp | 12 ++------- 7 files changed, 111 insertions(+), 28 deletions(-) create mode 100644 src/Contexts/ExtensionWrangler.cpp create mode 100644 src/Contexts/ExtensionWrangler.h diff --git a/src/Contexts/AbstractGlInterface.h b/src/Contexts/AbstractGlInterface.h index 629eb1dc3..3f6d14ef6 100644 --- a/src/Contexts/AbstractGlInterface.h +++ b/src/Contexts/AbstractGlInterface.h @@ -19,6 +19,8 @@ * @brief Class Magnum::Contexts::AbstractGlInterface */ +#include "ExtensionWrangler.h" + namespace Magnum { namespace Contexts { /** @brief Base for OpenGL interfaces */ @@ -41,6 +43,15 @@ template class AbstractGlInterface /** @brief Create context */ virtual void createContext(Window nativeWindow) = 0; + /** + * @brief Whether to enable experimental extension wrangler features + * + * Default is to disable. + */ + virtual inline ExtensionWrangler::ExperimentalFeatures experimentalExtensionWranglerFeatures() const { + return ExtensionWrangler::ExperimentalFeatures::Disable; + } + /** @brief Make the context current */ virtual void makeCurrent() = 0; diff --git a/src/Contexts/AbstractXContext.cpp b/src/Contexts/AbstractXContext.cpp index 5195b5387..103dcabbc 100644 --- a/src/Contexts/AbstractXContext.cpp +++ b/src/Contexts/AbstractXContext.cpp @@ -15,6 +15,8 @@ #include "AbstractXContext.h" +#include "ExtensionWrangler.h" + #define None 0L // redef Xlib nonsense /* Mask for X events */ @@ -66,14 +68,8 @@ AbstractXContext::AbstractXContext(AbstractGlInterfacemakeCurrent(); - #ifndef MAGNUM_TARGET_GLES - /* Init GLEW */ - GLenum err = glewInit(); - if(err != GLEW_OK) { - Error() << "AbstractXContext: cannot initialize GLEW:" << glewGetErrorString(err); - exit(1); - } - #endif + /* Initialize extension wrangler */ + ExtensionWrangler::initialize(glInterface->experimentalExtensionWranglerFeatures()); } AbstractXContext::~AbstractXContext() { diff --git a/src/Contexts/CMakeLists.txt b/src/Contexts/CMakeLists.txt index dee2f25e6..bc1aa130c 100644 --- a/src/Contexts/CMakeLists.txt +++ b/src/Contexts/CMakeLists.txt @@ -1,13 +1,19 @@ +# Extension wrangler +add_library(MagnumContextsExtensionWrangler OBJECT ExtensionWrangler.cpp) + set(MagnumContexts_HEADERS AbstractContext.h - AbstractGlInterface.h) + AbstractGlInterface.h + ExtensionWrangler.h) install(FILES ${MagnumContexts_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) # GLUT context if(WITH_GLUTCONTEXT) find_package(GLUT) if(GLUT_FOUND) - add_library(MagnumGlutContext STATIC GlutContext.cpp) + add_library(MagnumGlutContext STATIC + GlutContext.cpp + $) install(FILES GlutContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) install(TARGETS MagnumGlutContext DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) else() @@ -20,7 +26,9 @@ if(WITH_SDL2CONTEXT) find_package(SDL2) if(SDL2_FOUND) include_directories(${SDL2_INCLUDE_DIR}) - add_library(MagnumSdl2Context STATIC Sdl2Context.cpp) + add_library(MagnumSdl2Context STATIC + Sdl2Context.cpp + $) install(FILES Sdl2Context.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) install(TARGETS MagnumSdl2Context DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) else() @@ -32,7 +40,10 @@ endif() if(WITH_XEGLCONTEXT) set(NEED_ABSTRACTXCONTEXT 1) set(NEED_EGLINTERFACE 1) - add_library(MagnumXEglContext STATIC $ $) + add_library(MagnumXEglContext STATIC + $ + $ + $) install(FILES XEglContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) install(TARGETS MagnumXEglContext DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) endif() diff --git a/src/Contexts/ExtensionWrangler.cpp b/src/Contexts/ExtensionWrangler.cpp new file mode 100644 index 000000000..4515624bd --- /dev/null +++ b/src/Contexts/ExtensionWrangler.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 "ExtensionWrangler.h" + +#include "Magnum.h" + +namespace Magnum { namespace Contexts { + +void ExtensionWrangler::initialize(ExperimentalFeatures experimentalFeatures) { + #ifndef MAGNUM_TARGET_GLES + /* Enable experimental features */ + if(experimentalFeatures == ExperimentalFeatures::Enable) + glewExperimental = true; + + /* Init GLEW */ + GLenum err = glewInit(); + if(err != GLEW_OK) { + Error() << "ExtensionWrangler: cannot initialize GLEW:" << glewGetErrorString(err); + exit(1); + } + #endif +} + +}} diff --git a/src/Contexts/ExtensionWrangler.h b/src/Contexts/ExtensionWrangler.h new file mode 100644 index 000000000..04dba65d3 --- /dev/null +++ b/src/Contexts/ExtensionWrangler.h @@ -0,0 +1,39 @@ +#ifndef Magnum_Contexts_ExtensionWrangler_h +#define Magnum_Contexts_ExtensionWrangler_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::Contexts::ExtensionWrangler + */ + +namespace Magnum { namespace Contexts { + +/** @brief Extension wrangler interface */ +class ExtensionWrangler { + public: + /** @brief Whether to enable or disable experimental features */ + enum class ExperimentalFeatures { + Disable, + Enable + }; + + /** @brief Initialize extension wrangler */ + static void initialize(ExperimentalFeatures experimentalFeatures = ExperimentalFeatures::Disable); +}; + +}} + +#endif diff --git a/src/Contexts/GlutContext.cpp b/src/Contexts/GlutContext.cpp index a3d210e31..01307482d 100644 --- a/src/Contexts/GlutContext.cpp +++ b/src/Contexts/GlutContext.cpp @@ -15,6 +15,8 @@ #include "GlutContext.h" +#include "ExtensionWrangler.h" + namespace Magnum { namespace Contexts { GlutContext* GlutContext::instance = nullptr; @@ -35,12 +37,7 @@ GlutContext::GlutContext(int& argc, char** argv, const std::string& title, const glutMotionFunc(staticMouseMotionEvent); glutDisplayFunc(staticDrawEvent); - /* Init GLEW */ - GLenum err = glewInit(); - if(err != GLEW_OK) { - Error() << "GlutContext: cannot initialize GLEW:" << glewGetErrorString(err); - exit(1); - } + ExtensionWrangler::initialize(); } }} diff --git a/src/Contexts/Sdl2Context.cpp b/src/Contexts/Sdl2Context.cpp index 472b9fc95..074fe3edd 100644 --- a/src/Contexts/Sdl2Context.cpp +++ b/src/Contexts/Sdl2Context.cpp @@ -14,6 +14,7 @@ */ #include "Sdl2Context.h" +#include "ExtensionWrangler.h" namespace Magnum { namespace Contexts { @@ -40,18 +41,9 @@ Sdl2Context::Sdl2Context(int, char**, const std::string& name, const Math::Vecto context = SDL_GL_CreateContext(window); - #ifndef MAGNUM_TARGET_GLES /* This must be enabled, otherwise (on my NVidia) it crashes when creating VAO. WTF. */ - glewExperimental = true; - - /* Init GLEW */ - GLenum err = glewInit(); - if(err != GLEW_OK) { - Error() << "Sdl2Context: cannot initialize GLEW:" << glewGetErrorString(err); - exit(1); - } - #endif + ExtensionWrangler::initialize(ExtensionWrangler::ExperimentalFeatures::Enable); /* Push resize event, so viewportEvent() is called at startup */ SDL_Event* sizeEvent = new SDL_Event; From 31e4e8d95ed3259947cef4255a497d3b64b00e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 02:03:19 +0200 Subject: [PATCH 54/78] Added GLX context. --- CMakeLists.txt | 1 + modules/FindMagnum.cmake | 11 +++++ src/Contexts/CMakeLists.txt | 20 ++++++++ src/Contexts/GlxContext.h | 49 +++++++++++++++++++ src/Contexts/GlxInterface.cpp | 90 +++++++++++++++++++++++++++++++++++ src/Contexts/GlxInterface.h | 66 +++++++++++++++++++++++++ 6 files changed, 237 insertions(+) create mode 100644 src/Contexts/GlxContext.h create mode 100644 src/Contexts/GlxInterface.cpp create mode 100644 src/Contexts/GlxInterface.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 240f12297..53bc48175 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ option(WITH_PRIMITIVES "Builf Primitives library" OFF) option(WITH_SCENEGRAPH "Build SceneGraph library" OFF) option(WITH_SHADERS "Build Shaders library" OFF) +option(WITH_GLXCONTEXT "Build GlxContext library" OFF) cmake_dependent_option(WITH_XEGLCONTEXT "Build XEglContext library" OFF "TARGET_GLES" OFF) cmake_dependent_option(WITH_GLUTCONTEXT "Build GlutContext library" OFF "NOT TARGET_GLES" OFF) option(WITH_SDL2CONTEXT "Build Sdl2Context library" OFF) diff --git a/modules/FindMagnum.cmake b/modules/FindMagnum.cmake index 4b1aa91e0..fada6ad10 100644 --- a/modules/FindMagnum.cmake +++ b/modules/FindMagnum.cmake @@ -20,6 +20,7 @@ # Primitives - Library with stock geometric primitives (static) # SceneGraph - Scene graph library # Shaders - Library with stock shaders +# GlxContext - GLX context (depends on X11 libraries) # XEglContext - X/EGL context (depends on EGL and X11 libraries) # GlutContext - GLUT context (depends on GLUT library) # Sdl2Context - SDL2 context (depends on SDL2 library) @@ -111,6 +112,16 @@ foreach(component ${Magnum_FIND_COMPONENTS}) endif() endif() + # GLX context dependencies + if(${component} STREQUAL GlxContext) + find_package(X11) + if(X11_FOUND) + set(_MAGNUM_${_COMPONENT}_LIBRARIES ${X11_LIBRARIES}) + else() + unset(MAGNUM_${_COMPONENT}_LIBRARY) + endif() + endif() + # X/EGL context dependencies if(${component} STREQUAL XEglContext) find_package(EGL) diff --git a/src/Contexts/CMakeLists.txt b/src/Contexts/CMakeLists.txt index bc1aa130c..7d5cd8fe0 100644 --- a/src/Contexts/CMakeLists.txt +++ b/src/Contexts/CMakeLists.txt @@ -36,6 +36,18 @@ if(WITH_SDL2CONTEXT) endif() endif() +# GLX context +if(WITH_GLXCONTEXT) + set(NEED_ABSTRACTXCONTEXT 1) + set(NEED_GLXINTERFACE 1) + add_library(MagnumGlxContext STATIC + $ + $ + $) + install(FILES GlxContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) + install(TARGETS MagnumGlxContext DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}) +endif() + # X/EGL context if(WITH_XEGLCONTEXT) set(NEED_ABSTRACTXCONTEXT 1) @@ -60,6 +72,14 @@ if(NEED_ABSTRACTXCONTEXT) install(FILES AbstractXContext.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) endif() +# GLX interface +if(NEED_GLXINTERFACE) + add_library(MagnumGlxInterface OBJECT GlxInterface.cpp) + # X11 macros are a mess, disable warnings for C-style casts + set_target_properties(MagnumGlxInterface PROPERTIES COMPILE_FLAGS "-Wno-old-style-cast") + install(FILES GlxInterface.h DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/Contexts) +endif() + # EGL interface if(NEED_EGLINTERFACE) find_package(EGL) diff --git a/src/Contexts/GlxContext.h b/src/Contexts/GlxContext.h new file mode 100644 index 000000000..a11b503c7 --- /dev/null +++ b/src/Contexts/GlxContext.h @@ -0,0 +1,49 @@ +#ifndef Magnum_Contexts_GlxContext_h +#define Magnum_Contexts_GlxContext_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::Contexts::GlxContext + */ + +#include "AbstractXContext.h" +#include "GlxInterface.h" + +namespace Magnum { namespace Contexts { + +/** +@brief GLX context + +Uses GlxInterface. +*/ +class GlxContext: public AbstractXContext { + public: + /** + * @brief Constructor + * @param argc Count of arguments of `main()` function + * @param argv Arguments of `main()` function + * @param title Window title + * @param size Window size + * + * Creates window with double-buffered OpenGL 3.3 core context or + * OpenGL ES 2.0 context, if targetting OpenGL ES. + */ + inline GlxContext(int& argc, char** argv, const std::string& title = "Magnum GLX context", const Math::Vector2& size = Math::Vector2(800, 600)): AbstractXContext(new GlxInterface, argc, argv, title, size) {} +}; + +}} + +#endif diff --git a/src/Contexts/GlxInterface.cpp b/src/Contexts/GlxInterface.cpp new file mode 100644 index 000000000..a8fb92680 --- /dev/null +++ b/src/Contexts/GlxInterface.cpp @@ -0,0 +1,90 @@ +/* + 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 "GlxInterface.h" + +#include + +namespace Magnum { namespace Contexts { + +VisualID GlxInterface::getVisualId(Display* nativeDisplay) { + display = nativeDisplay; + + /* Check version */ + int major, minor; + glXQueryVersion(nativeDisplay, &major, &minor); + if(major == 1 && minor < 4) { + Error() << "GlxInterface: GLX version 1.4 or greater is required."; + exit(1); + } + + /* Choose config */ + int configCount = 0; + static const int attributes[] = { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_X_RENDERABLE, True, + GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_DOUBLEBUFFER, True, + GLX_RED_SIZE, 8, + GLX_GREEN_SIZE, 8, + GLX_BLUE_SIZE, 8, + 0 + }; + configs = glXChooseFBConfig(nativeDisplay, DefaultScreen(nativeDisplay), attributes, &configCount); + if(!configCount) { + Error() << "GlxInterface: no supported framebuffer configuration found."; + exit(1); + } + + /* Get visual ID */ + XVisualInfo* info = glXGetVisualFromFBConfig(display, configs[0]); + VisualID visualId = info->visualid; + XFree(info); + + return visualId; +} + +void GlxInterface::createContext(Window nativeWindow) { + window = nativeWindow; + + GLint attributes[] = { + #ifndef MAGNUM_TARGET_GLES + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 3, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + #else + GLX_CONTEXT_MAJOR_VERSION_ARB, 2, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT, + #endif + 0 + }; + + /** @todo Use some extension wrangler for this, not GLEW, as it apparently needs context to create context, yo dawg wtf. */ + PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); + context = glXCreateContextAttribsARB(display, configs[0], 0, True, attributes); + XFree(configs); + if(!context) { + Error() << "GlxInterface: cannot create context."; + exit(1); + } +} + +GlxInterface::~GlxInterface() { + glXMakeCurrent(display, None, nullptr); + glXDestroyContext(display, context); +} + +}} diff --git a/src/Contexts/GlxInterface.h b/src/Contexts/GlxInterface.h new file mode 100644 index 000000000..e9f3177d8 --- /dev/null +++ b/src/Contexts/GlxInterface.h @@ -0,0 +1,66 @@ +#ifndef Magnum_Contexts_EglInterface_h +#define Magnum_Contexts_EglInterface_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::Contexts::GlxInterface + */ + +#include "Magnum.h" +#include + +#include "AbstractGlInterface.h" + +namespace Magnum { namespace Contexts { + +/** +@brief GLX interface + +Creates OpenGL 3.3 core context or OpenGL ES 2.0 context, if targetting +OpenGL ES. + +Used in GlxContext. +*/ +class GlxInterface: public AbstractGlInterface { + public: + ~GlxInterface(); + + VisualID getVisualId(Display* nativeDisplay); + void createContext(Window nativeWindow); + + /* This must be enabled, otherwise (on my NVidia) it crashes when creating VAO. WTF. */ + inline ExtensionWrangler::ExperimentalFeatures experimentalExtensionWranglerFeatures() const { + return ExtensionWrangler::ExperimentalFeatures::Enable; + } + + inline void makeCurrent() { + glXMakeCurrent(display, window, context); + } + + inline void swapBuffers() { + glXSwapBuffers(display, window); + } + + private: + Display* display; + Window window; + GLXFBConfig* configs; + GLXContext context; +}; + +}} + +#endif From 436c07a706298aff89faead6a08684540f33582e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 11:09:25 +0200 Subject: [PATCH 55/78] Removed done @todo. --- src/Contexts/AbstractXContext.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Contexts/AbstractXContext.cpp b/src/Contexts/AbstractXContext.cpp index 103dcabbc..e125604c7 100644 --- a/src/Contexts/AbstractXContext.cpp +++ b/src/Contexts/AbstractXContext.cpp @@ -124,7 +124,6 @@ int AbstractXContext::exec() { } } - /** @todo Handle at least window closing and resizing */ drawEvent(); } From 070c5ba7062febed095fb8e7e7d52551252c8762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 11:12:47 +0200 Subject: [PATCH 56/78] Sdl2Context: calling redraw() in drawEvent() didn't have any effect. --- src/Contexts/Sdl2Context.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Contexts/Sdl2Context.cpp b/src/Contexts/Sdl2Context.cpp index 074fe3edd..91f21c36c 100644 --- a/src/Contexts/Sdl2Context.cpp +++ b/src/Contexts/Sdl2Context.cpp @@ -101,8 +101,8 @@ int Sdl2Context::exec() { } if(_redraw) { - drawEvent(); _redraw = false; + drawEvent(); } else Corrade::Utility::sleep(5); } From 0ca0f03f1cd598d3c48f1a879e24a434b53df20e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 11:13:47 +0200 Subject: [PATCH 57/78] Implemented AbstractXContext::redraw(). --- src/Contexts/AbstractXContext.cpp | 8 ++++++-- src/Contexts/AbstractXContext.h | 6 ++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Contexts/AbstractXContext.cpp b/src/Contexts/AbstractXContext.cpp index e125604c7..c73d8ecdd 100644 --- a/src/Contexts/AbstractXContext.cpp +++ b/src/Contexts/AbstractXContext.cpp @@ -26,7 +26,7 @@ using namespace std; namespace Magnum { namespace Contexts { -AbstractXContext::AbstractXContext(AbstractGlInterface* glInterface, int&, char**, const string& title, const Math::Vector2& size): glInterface(glInterface), viewportSize(size) { +AbstractXContext::AbstractXContext(AbstractGlInterface* glInterface, int&, char**, const string& title, const Math::Vector2& size): glInterface(glInterface), viewportSize(size), _redraw(true) { /* Get default X display */ display = XOpenDisplay(0); @@ -105,6 +105,7 @@ int AbstractXContext::exec() { if(size != viewportSize) { viewportSize = size; viewportEvent(size); + _redraw = true; } } break; @@ -124,7 +125,10 @@ int AbstractXContext::exec() { } } - drawEvent(); + if(_redraw) { + _redraw = false; + drawEvent(); + } else Corrade::Utility::sleep(5); } return 0; diff --git a/src/Contexts/AbstractXContext.h b/src/Contexts/AbstractXContext.h index 971240d98..c8cca51fb 100644 --- a/src/Contexts/AbstractXContext.h +++ b/src/Contexts/AbstractXContext.h @@ -74,8 +74,8 @@ class AbstractXContext: public AbstractContext { /** @copydoc GlutContext::swapBuffers() */ inline void swapBuffers() { glInterface->swapBuffers(); } - /** @todo implement */ - inline void redraw() {} + /** @copydoc GlutContext::redraw() */ + inline void redraw() { _redraw = true; } /*@}*/ @@ -214,6 +214,8 @@ class AbstractXContext: public AbstractContext { /** @todo Get this from the created window */ Math::Vector2 viewportSize; + + bool _redraw; }; inline void AbstractXContext::keyPressEvent(AbstractXContext::Key, const Math::Vector2&) {} From 4a207c6556a20470444dafded6186b4ae9e0a579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 11:38:15 +0200 Subject: [PATCH 58/78] Simplified camera projection matrix creation. It doesn't need to be decomposed in many matrix multiplications which still fail to go properly together. --- src/SceneGraph/Camera.cpp | 37 ++++++++++++++++--------------------- src/SceneGraph/Camera.h | 2 +- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp index 6f1101bcf..3585ae8dc 100644 --- a/src/SceneGraph/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -94,12 +94,15 @@ void Camera3D::setOrthographic(const Vector2& size, GLfloat near, GLfloat far) { _near = near; _far = far; - /* Scale the volume down so it fits in (-1, 1) in all directions */ - GLfloat zScale = 2/(far-near); - rawProjectionMatrix = Matrix4::scaling({2.0f/size, -zScale}); + Vector2 xyScale = 2.0f/size; + GLfloat zScale = 2.0f/(near-far); - /* Move the volume on z into (-1, 1) range */ - rawProjectionMatrix = Matrix4::translation(Vector3::zAxis(-1-near*zScale))*rawProjectionMatrix; + rawProjectionMatrix = Matrix4( + xyScale.x(), 0.0f, 0.0f, 0.0f, + 0.0f, xyScale.y(), 0.0f, 0.0f, + 0.0f, 0.0f, zScale, 0.0f, + 0.0f, 0.0f, near*zScale-1, 1.0f + ); projectionAspectRatio = size; fixAspectRatio(); @@ -109,23 +112,15 @@ void Camera3D::setPerspective(GLfloat fov, GLfloat near, GLfloat far) { _near = near; _far = far; - /* First move the volume on z in (-1, 1) range */ - rawProjectionMatrix = Matrix4::translation(Vector3::zAxis(2*far*near/(far+near))); - - /* Then apply magic perspective matrix (with reversed Z) */ - static const Matrix4 a(1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, -1.0f, -1.0f, - 0.0f, 0.0f, 0.0f, 0.0f); - rawProjectionMatrix = a*rawProjectionMatrix; - - /* Then scale the volume down so it fits in (-1, 1) in all directions */ - GLfloat xyScale = 1/tan(fov/2); - GLfloat zScale = 1+2*near/(far-near); - rawProjectionMatrix = Matrix4::scaling({xyScale, xyScale, zScale})*rawProjectionMatrix; + GLfloat xyScale = 1.0f/tan(fov/2); + GLfloat zScale = 1.0f/(near-far); - /* And... another magic */ - rawProjectionMatrix[3][3] = 0; + rawProjectionMatrix = Matrix4( + xyScale, 0.0f, 0.0f, 0.0f, + 0.0f, xyScale, 0.0f, 0.0f, + 0.0f, 0.0f, (far+near)*zScale, -1.0f, + 0.0f, 0.0f, (2*far*near)*zScale, 0.0f + ); projectionAspectRatio = Vector2(xyScale); fixAspectRatio(); diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index 64ed68d37..6378014de 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -198,7 +198,7 @@ class SCENEGRAPH_EXPORT Camera3D: public Camera Date: Sun, 19 Aug 2012 12:53:36 +0200 Subject: [PATCH 59/78] Doc++, code cleanup. --- src/Contexts/AbstractXContext.h | 27 +++++++++++++++++++-------- src/Contexts/GlutContext.h | 32 +++++++++++++++++++++++--------- src/Contexts/Sdl2Context.h | 9 ++++++--- 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/Contexts/AbstractXContext.h b/src/Contexts/AbstractXContext.h index c8cca51fb..4e7d13fb6 100644 --- a/src/Contexts/AbstractXContext.h +++ b/src/Contexts/AbstractXContext.h @@ -32,7 +32,7 @@ namespace Magnum { namespace Contexts { -/** +/** @nosubgrouping @brief Base for X11-based contexts Supports keyboard and mouse handling. @@ -82,7 +82,11 @@ class AbstractXContext: public AbstractContext { /** @{ @name Keyboard handling */ public: - /** @brief Key */ + /** + * @brief Key + * + * @see keyPressEvent(), keyReleaseEvent() + */ enum class Key: KeySym { Up = XK_Up, /**< Up arrow */ Down = XK_Down, /**< Down arrow */ @@ -177,7 +181,11 @@ class AbstractXContext: public AbstractContext { /** @{ @name Mouse handling */ public: - /** @brief Mouse button */ + /** + * @brief Mouse button + * + * @see mousePressEvent(), mouseReleaseEvent() + */ enum class MouseButton: unsigned int { Left = Button1, /**< Left button */ Middle = Button2, /**< Middle button */ @@ -189,6 +197,8 @@ class AbstractXContext: public AbstractContext { protected: /** * @brief Mouse press event + * @param button Button pressed + * @param position Cursor position * * Called when mouse button is pressed. Default implementation does * nothing. @@ -197,6 +207,8 @@ class AbstractXContext: public AbstractContext { /** * @brief Mouse release event + * @param button Button released + * @param position Cursor position * * Called when mouse button is released. Default implementation does * nothing. @@ -218,11 +230,10 @@ class AbstractXContext: public AbstractContext { bool _redraw; }; -inline void AbstractXContext::keyPressEvent(AbstractXContext::Key, const Math::Vector2&) {} -inline void AbstractXContext::keyReleaseEvent(AbstractXContext::Key, const Math::Vector2&) {} -inline void AbstractXContext::mousePressEvent(AbstractXContext::MouseButton, const Math::Vector2&) {} -inline void AbstractXContext::mouseReleaseEvent(AbstractXContext::MouseButton, const Math::Vector2&) {} - +inline void AbstractXContext::keyPressEvent(Key, const Math::Vector2&) {} +inline void AbstractXContext::keyReleaseEvent(Key, const Math::Vector2&) {} +inline void AbstractXContext::mousePressEvent(MouseButton, const Math::Vector2&) {} +inline void AbstractXContext::mouseReleaseEvent(MouseButton, const Math::Vector2&) {} }} diff --git a/src/Contexts/GlutContext.h b/src/Contexts/GlutContext.h index 17a3c921c..73e32569f 100644 --- a/src/Contexts/GlutContext.h +++ b/src/Contexts/GlutContext.h @@ -60,7 +60,8 @@ class GlutContext: public AbstractContext { * @brief Viewport event * * Called when viewport size changes. You should pass the new size to - * Camera::viewport() function of your camera. + * Framebuffer::setViewport() or SceneGraph::Camera::setViewport(), + * if using scene graph. */ virtual void viewportEvent(const Math::Vector2& size) = 0; @@ -68,8 +69,9 @@ class GlutContext: public AbstractContext { * @brief Draw event * * Here implement your drawing functions, such as calling - * Camera::draw(). After drawing is finished, call swapBuffers(). If - * you want to draw immediately again, call also redraw(). + * SceneGraph::Camera::draw(). After drawing is finished, call + * swapBuffers(). If you want to draw immediately again, call also + * redraw(). */ virtual void drawEvent() = 0; @@ -97,7 +99,11 @@ class GlutContext: public AbstractContext { /** @{ @name Keyboard handling */ public: - /** @brief Key */ + /** + * @brief Key + * + * @see keyPressEvent() + */ enum class Key: int { Up = GLUT_KEY_UP, /**< Up arrow */ Down = GLUT_KEY_DOWN, /**< Down arrow */ @@ -136,7 +142,11 @@ class GlutContext: public AbstractContext { /** @{ @name Mouse handling */ public: - /** @brief Mouse button */ + /** + * @brief Mouse button + * + * @see mousePressEvent(), mouseReleaseEvent() + */ enum class MouseButton: int { Left = GLUT_LEFT_BUTTON, /**< Left button */ Middle = GLUT_MIDDLE_BUTTON, /**< Middle button */ @@ -145,7 +155,11 @@ class GlutContext: public AbstractContext { WheelDown = 4 /**< Wheel down */ }; - /** @brief Mouse cursor */ + /** + * @brief Mouse cursor + * + * @see setMouseCursor() + */ enum class MouseCursor: int { Default = GLUT_CURSOR_INHERIT, /**< Default cursor provided by parent window */ None = GLUT_CURSOR_NONE /**< No cursor */ @@ -231,9 +245,9 @@ class GlutContext: public AbstractContext { }; /* Implementations for inline functions with unused parameters */ -inline void GlutContext::keyPressEvent(GlutContext::Key, const Math::Vector2&) {} -inline void GlutContext::mousePressEvent(GlutContext::MouseButton, const Math::Vector2&) {} -inline void GlutContext::mouseReleaseEvent(GlutContext::MouseButton, const Math::Vector2&) {} +inline void GlutContext::keyPressEvent(Key, const Math::Vector2&) {} +inline void GlutContext::mousePressEvent(MouseButton, const Math::Vector2&) {} +inline void GlutContext::mouseReleaseEvent(MouseButton, const Math::Vector2&) {} inline void GlutContext::mouseMotionEvent(const Math::Vector2&) {} }} diff --git a/src/Contexts/Sdl2Context.h b/src/Contexts/Sdl2Context.h index fb4b00a22..da4024055 100644 --- a/src/Contexts/Sdl2Context.h +++ b/src/Contexts/Sdl2Context.h @@ -79,6 +79,7 @@ class Sdl2Context: public AbstractContext { public: /** * @brief Key + * * @see keyPressEvent(), keyReleaseEvent() */ enum class Key: SDL_Keycode { @@ -111,6 +112,7 @@ class Sdl2Context: public AbstractContext { public: /** * @brief Mouse button + * * @see mouseEvent() */ enum class MouseButton: Uint8 { @@ -121,6 +123,7 @@ class Sdl2Context: public AbstractContext { /** * @brief Mouse state + * * @see mouseEvent() */ enum class MouseState: Uint8 { @@ -169,9 +172,9 @@ class Sdl2Context: public AbstractContext { }; /* Implementations for inline functions with unused parameters */ -inline void Sdl2Context::keyPressEvent(Sdl2Context::Key, Uint8) {} -inline void Sdl2Context::keyReleaseEvent(Sdl2Context::Key) {} -inline void Sdl2Context::mouseEvent(Sdl2Context::MouseButton, Sdl2Context::MouseState, const Math::Vector2&) {} +inline void Sdl2Context::keyPressEvent(Key, Uint8) {} +inline void Sdl2Context::keyReleaseEvent(Key) {} +inline void Sdl2Context::mouseEvent(MouseButton, MouseState, const Math::Vector2&) {} inline void Sdl2Context::mouseWheelEvent(const Math::Vector2&) {} inline void Sdl2Context::mouseMotionEvent(const Math::Vector2&, const Math::Vector2&) {} From 9d63f35279a26ee94270351c7d2dd9af4318949e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 12:58:05 +0200 Subject: [PATCH 60/78] Sdl2Context: split mouseEvent to mousePressEvent and mouseReleaseEvent. Preserving consistency with GlutContext and *XContext. --- src/Contexts/Sdl2Context.cpp | 6 +++--- src/Contexts/Sdl2Context.h | 26 ++++++++++++++++++-------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/Contexts/Sdl2Context.cpp b/src/Contexts/Sdl2Context.cpp index 91f21c36c..f55fa6125 100644 --- a/src/Contexts/Sdl2Context.cpp +++ b/src/Contexts/Sdl2Context.cpp @@ -83,10 +83,10 @@ int Sdl2Context::exec() { keyReleaseEvent(static_cast(event.key.keysym.sym)); break; case SDL_MOUSEBUTTONDOWN: + mousePressEvent(static_cast(event.button.button), {event.button.x, event.button.y}); + break; case SDL_MOUSEBUTTONUP: - mouseEvent(static_cast(event.button.button), - static_cast(event.button.state), - {event.button.x, event.button.y}); + mouseReleaseEvent(static_cast(event.button.button), {event.button.x, event.button.y}); break; case SDL_MOUSEWHEEL: mouseWheelEvent({event.wheel.x, event.wheel.y}); diff --git a/src/Contexts/Sdl2Context.h b/src/Contexts/Sdl2Context.h index da4024055..112b434b8 100644 --- a/src/Contexts/Sdl2Context.h +++ b/src/Contexts/Sdl2Context.h @@ -133,15 +133,24 @@ class Sdl2Context: public AbstractContext { protected: /** - * @brief Mouse event - * @param button Mouse button - * @param state Mouse state - * @param position Mouse position relative to the window + * @brief Mouse press event + * @param button Button pressed + * @param position Cursor position * - * Called when mouse button is pressed or released. Default - * implementation does nothing. + * Called when mouse button is pressed. Default implementation does + * nothing. + */ + virtual void mousePressEvent(MouseButton button, const Math::Vector2& position); + + /** + * @brief Mouse release event + * @param button Button released + * @param position Cursor position + * + * Called when mouse button is released. Default implementation does + * nothing. */ - virtual void mouseEvent(MouseButton button, MouseState state, const Math::Vector2& position); + virtual void mouseReleaseEvent(MouseButton button, const Math::Vector2& position); /** * @brief Mouse wheel event @@ -174,7 +183,8 @@ class Sdl2Context: public AbstractContext { /* Implementations for inline functions with unused parameters */ inline void Sdl2Context::keyPressEvent(Key, Uint8) {} inline void Sdl2Context::keyReleaseEvent(Key) {} -inline void Sdl2Context::mouseEvent(MouseButton, MouseState, const Math::Vector2&) {} +inline void Sdl2Context::mousePressEvent(MouseButton, const Math::Vector2&) {} +inline void Sdl2Context::mouseReleaseEvent(MouseButton, const Math::Vector2&) {} inline void Sdl2Context::mouseWheelEvent(const Math::Vector2&) {} inline void Sdl2Context::mouseMotionEvent(const Math::Vector2&, const Math::Vector2&) {} From fa50c8fe784a48166378571c0628fa2930786cc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 12:59:01 +0200 Subject: [PATCH 61/78] AbstractXContext: store viewport size in the right vector type. --- src/Contexts/AbstractXContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Contexts/AbstractXContext.cpp b/src/Contexts/AbstractXContext.cpp index c73d8ecdd..ab7b3bf1a 100644 --- a/src/Contexts/AbstractXContext.cpp +++ b/src/Contexts/AbstractXContext.cpp @@ -101,7 +101,7 @@ int AbstractXContext::exec() { switch(event.type) { /* Window resizing */ case ConfigureNotify: { - Math::Vector2 size(event.xconfigure.width, event.xconfigure.height); + Math::Vector2 size(event.xconfigure.width, event.xconfigure.height); if(size != viewportSize) { viewportSize = size; viewportEvent(size); From 8f3abe9dadf8fa1c630684d0724620c893d996d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 12:59:58 +0200 Subject: [PATCH 62/78] AbstractXContext: added modifiers to key and mouse events. --- src/Contexts/AbstractXContext.cpp | 8 +++--- src/Contexts/AbstractXContext.h | 43 +++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/Contexts/AbstractXContext.cpp b/src/Contexts/AbstractXContext.cpp index ab7b3bf1a..ffc4e10f5 100644 --- a/src/Contexts/AbstractXContext.cpp +++ b/src/Contexts/AbstractXContext.cpp @@ -111,16 +111,16 @@ int AbstractXContext::exec() { /* Key/mouse events */ case KeyPress: - keyPressEvent(static_cast(XLookupKeysym(&event.xkey, 0)), {event.xkey.x, event.xkey.y}); + keyPressEvent(static_cast(XLookupKeysym(&event.xkey, 0)), static_cast(event.xkey.state), {event.xkey.x, event.xkey.y}); break; case KeyRelease: - keyReleaseEvent(static_cast(XLookupKeysym(&event.xkey, 0)), {event.xkey.x, event.xkey.y}); + keyReleaseEvent(static_cast(XLookupKeysym(&event.xkey, 0)), static_cast(event.xkey.state), {event.xkey.x, event.xkey.y}); break; case ButtonPress: - mousePressEvent(static_cast(event.xbutton.button), {event.xbutton.x, event.xbutton.y}); + mousePressEvent(static_cast(event.xbutton.button), static_cast(event.xkey.state), {event.xbutton.x, event.xbutton.y}); break; case ButtonRelease: - mouseReleaseEvent(static_cast(event.xbutton.button), {event.xbutton.x, event.xbutton.y}); + mouseReleaseEvent(static_cast(event.xbutton.button), static_cast(event.xkey.state), {event.xbutton.x, event.xbutton.y}); break; } } diff --git a/src/Contexts/AbstractXContext.h b/src/Contexts/AbstractXContext.h index 4e7d13fb6..3f30bee54 100644 --- a/src/Contexts/AbstractXContext.h +++ b/src/Contexts/AbstractXContext.h @@ -27,6 +27,8 @@ #undef None #undef Always +#include + #include "AbstractContext.h" #include "AbstractGlInterface.h" @@ -82,6 +84,27 @@ class AbstractXContext: public AbstractContext { /** @{ @name Keyboard handling */ public: + /** + * @brief %Modifier + * + * @see Modifiers, keyPressEvent(), keyReleaseEvent() + */ + enum class Modifier: unsigned int { + Shift = ShiftMask, /**< Shift */ + CapsLock = LockMask, /**< Caps lock */ + Ctrl = ControlMask, /**< Ctrl */ + Alt = Mod1Mask, /**< Alt */ + NumLock = Mod2Mask, /**< Num lock */ + AltGr = Mod5Mask /**< AltGr */ + }; + + /** + * @brief Set of modifiers + * + * @see keyPressEvent(), keyReleaseEvent() + */ + typedef Corrade::Containers::EnumSet Modifiers; + /** * @brief Key * @@ -161,20 +184,22 @@ class AbstractXContext: public AbstractContext { /** * @brief Key press event * @param key Key pressed + * @param modifiers Active modifiers * @param position Cursor position * * Called when an key is pressed. Default implementation does nothing. */ - virtual void keyPressEvent(Key key, const Math::Vector2& position); + virtual void keyPressEvent(Key key, Modifiers modifiers, const Math::Vector2& position); /** * @brief Key press event * @param key Key released + * @param modifiers Active modifiers * @param position Cursor position * * Called when an key is released. Default implementation does nothing. */ - virtual void keyReleaseEvent(Key key, const Math::Vector2& position); + virtual void keyReleaseEvent(Key key, Modifiers modifiers, const Math::Vector2& position); /*@}*/ @@ -198,22 +223,24 @@ class AbstractXContext: public AbstractContext { /** * @brief Mouse press event * @param button Button pressed + * @param modifiers Active modifiers * @param position Cursor position * * Called when mouse button is pressed. Default implementation does * nothing. */ - virtual void mousePressEvent(MouseButton button, const Math::Vector2& position); + virtual void mousePressEvent(MouseButton button, Modifiers modifiers, const Math::Vector2& position); /** * @brief Mouse release event * @param button Button released + * @param modifiers Active modifiers * @param position Cursor position * * Called when mouse button is released. Default implementation does * nothing. */ - virtual void mouseReleaseEvent(MouseButton button, const Math::Vector2& position); + virtual void mouseReleaseEvent(MouseButton button, Modifiers modifiers, const Math::Vector2& position); /*@}*/ @@ -230,10 +257,10 @@ class AbstractXContext: public AbstractContext { bool _redraw; }; -inline void AbstractXContext::keyPressEvent(Key, const Math::Vector2&) {} -inline void AbstractXContext::keyReleaseEvent(Key, const Math::Vector2&) {} -inline void AbstractXContext::mousePressEvent(MouseButton, const Math::Vector2&) {} -inline void AbstractXContext::mouseReleaseEvent(MouseButton, const Math::Vector2&) {} +inline void AbstractXContext::keyPressEvent(Key, Modifiers, const Math::Vector2&) {} +inline void AbstractXContext::keyReleaseEvent(Key, Modifiers, const Math::Vector2&) {} +inline void AbstractXContext::mousePressEvent(MouseButton, Modifiers, const Math::Vector2&) {} +inline void AbstractXContext::mouseReleaseEvent(MouseButton, Modifiers, const Math::Vector2&) {} }} From 1a6037ff5dabd002115b4499993cb871623f4063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 19 Aug 2012 21:23:06 +0200 Subject: [PATCH 63/78] Adapted to Corrade changes, added operators for enum sets. --- src/Contexts/AbstractXContext.h | 3 +++ src/Framebuffer.h | 3 +++ src/Trade/AbstractImporter.h | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Contexts/AbstractXContext.h b/src/Contexts/AbstractXContext.h index 3f30bee54..4bfd3eee6 100644 --- a/src/Contexts/AbstractXContext.h +++ b/src/Contexts/AbstractXContext.h @@ -257,6 +257,9 @@ class AbstractXContext: public AbstractContext { bool _redraw; }; +CORRADE_ENUMSET_OPERATORS(AbstractXContext::Modifiers) + +/* Implementations for inline functions with unused parameters */ inline void AbstractXContext::keyPressEvent(Key, Modifiers, const Math::Vector2&) {} inline void AbstractXContext::keyReleaseEvent(Key, Modifiers, const Math::Vector2&) {} inline void AbstractXContext::mousePressEvent(MouseButton, Modifiers, const Math::Vector2&) {} diff --git a/src/Framebuffer.h b/src/Framebuffer.h index 4df94c9bf..427dcca32 100644 --- a/src/Framebuffer.h +++ b/src/Framebuffer.h @@ -1111,6 +1111,9 @@ class MAGNUM_EXPORT Framebuffer { GLuint framebuffer; }; +CORRADE_ENUMSET_OPERATORS(Framebuffer::ClearMask) +CORRADE_ENUMSET_OPERATORS(Framebuffer::BlitMask) + } #endif diff --git a/src/Trade/AbstractImporter.h b/src/Trade/AbstractImporter.h index 0258b2b32..2b7ed2528 100644 --- a/src/Trade/AbstractImporter.h +++ b/src/Trade/AbstractImporter.h @@ -310,7 +310,7 @@ class MAGNUM_EXPORT AbstractImporter: public Corrade::PluginManager::Plugin { /*@}*/ }; -SET_OPERATORS(AbstractImporter::Features) +CORRADE_ENUMSET_OPERATORS(AbstractImporter::Features) /* Implementations for inline functions with unused parameters */ inline int AbstractImporter::sceneForName(const std::string&) { return -1; } From c83de594c20defdda0c9537ee327d45aae7d13a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 09:47:16 +0200 Subject: [PATCH 64/78] AbstractXContext: ability to exit from main loop, added Esc key. --- src/Contexts/AbstractXContext.cpp | 12 ++++++------ src/Contexts/AbstractXContext.h | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/Contexts/AbstractXContext.cpp b/src/Contexts/AbstractXContext.cpp index ffc4e10f5..26e108771 100644 --- a/src/Contexts/AbstractXContext.cpp +++ b/src/Contexts/AbstractXContext.cpp @@ -26,7 +26,7 @@ using namespace std; namespace Magnum { namespace Contexts { -AbstractXContext::AbstractXContext(AbstractGlInterface* glInterface, int&, char**, const string& title, const Math::Vector2& size): glInterface(glInterface), viewportSize(size), _redraw(true) { +AbstractXContext::AbstractXContext(AbstractGlInterface* glInterface, int&, char**, const string& title, const Math::Vector2& size): glInterface(glInterface), viewportSize(size), flags(Flag::Redraw) { /* Get default X display */ display = XOpenDisplay(0); @@ -40,7 +40,7 @@ AbstractXContext::AbstractXContext(AbstractGlInterfaceswapBuffers(); } /** @copydoc GlutContext::redraw() */ - inline void redraw() { _redraw = true; } + inline void redraw() { flags |= Flag::Redraw; } /*@}*/ @@ -111,6 +114,8 @@ class AbstractXContext: public AbstractContext { * @see keyPressEvent(), keyReleaseEvent() */ enum class Key: KeySym { + Esc = XK_Escape, /**< Escape */ + Up = XK_Up, /**< Up arrow */ Down = XK_Down, /**< Down arrow */ Left = XK_Left, /**< Left arrow */ @@ -245,6 +250,14 @@ class AbstractXContext: public AbstractContext { /*@}*/ private: + enum class Flag: unsigned int { + Redraw = 1 << 0, + Exit = 1 << 1 + }; + + typedef Corrade::Containers::EnumSet Flags; + CORRADE_ENUMSET_FRIEND_OPERATORS(Flags) + Display* display; Window window; Atom deleteWindow; @@ -254,10 +267,11 @@ class AbstractXContext: public AbstractContext { /** @todo Get this from the created window */ Math::Vector2 viewportSize; - bool _redraw; + Flags flags; }; CORRADE_ENUMSET_OPERATORS(AbstractXContext::Modifiers) +CORRADE_ENUMSET_OPERATORS(AbstractXContext::Flags) /* Implementations for inline functions with unused parameters */ inline void AbstractXContext::keyPressEvent(Key, Modifiers, const Math::Vector2&) {} From f35a71a974872ac47eee3313c97e8707a85adf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 10:26:21 +0200 Subject: [PATCH 65/78] Doc++ --- src/Contexts/AbstractXContext.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Contexts/AbstractXContext.h b/src/Contexts/AbstractXContext.h index 58e9d2875..59fa93bf5 100644 --- a/src/Contexts/AbstractXContext.h +++ b/src/Contexts/AbstractXContext.h @@ -90,7 +90,8 @@ class AbstractXContext: public AbstractContext { /** * @brief %Modifier * - * @see Modifiers, keyPressEvent(), keyReleaseEvent() + * @see Modifiers, keyPressEvent(), keyReleaseEvent(), + * mousePressEvent(), mouseReleaseEvent() */ enum class Modifier: unsigned int { Shift = ShiftMask, /**< Shift */ From dd5635a3aba237c8a304a90a08030296586f93f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 10:28:01 +0200 Subject: [PATCH 66/78] AbstractXContext: added support for mouse motion event. --- src/Contexts/AbstractXContext.cpp | 7 ++++++- src/Contexts/AbstractXContext.h | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Contexts/AbstractXContext.cpp b/src/Contexts/AbstractXContext.cpp index 26e108771..9c0747aaf 100644 --- a/src/Contexts/AbstractXContext.cpp +++ b/src/Contexts/AbstractXContext.cpp @@ -20,7 +20,7 @@ #define None 0L // redef Xlib nonsense /* Mask for X events */ -#define INPUT_MASK KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|StructureNotifyMask +#define INPUT_MASK KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|StructureNotifyMask using namespace std; @@ -122,6 +122,11 @@ int AbstractXContext::exec() { case ButtonRelease: mouseReleaseEvent(static_cast(event.xbutton.button), static_cast(event.xkey.state), {event.xbutton.x, event.xbutton.y}); break; + + /* Mouse move events */ + case MotionNotify: + mouseMotionEvent(static_cast(event.xmotion.state), {event.xmotion.x, event.xmotion.y}); + break; } } diff --git a/src/Contexts/AbstractXContext.h b/src/Contexts/AbstractXContext.h index 59fa93bf5..620a777ac 100644 --- a/src/Contexts/AbstractXContext.h +++ b/src/Contexts/AbstractXContext.h @@ -91,7 +91,7 @@ class AbstractXContext: public AbstractContext { * @brief %Modifier * * @see Modifiers, keyPressEvent(), keyReleaseEvent(), - * mousePressEvent(), mouseReleaseEvent() + * mousePressEvent(), mouseReleaseEvent(), mouseMotionEvent() */ enum class Modifier: unsigned int { Shift = ShiftMask, /**< Shift */ @@ -99,7 +99,11 @@ class AbstractXContext: public AbstractContext { Ctrl = ControlMask, /**< Ctrl */ Alt = Mod1Mask, /**< Alt */ NumLock = Mod2Mask, /**< Num lock */ - AltGr = Mod5Mask /**< AltGr */ + AltGr = Mod5Mask, /**< AltGr */ + + LeftButton = Button1Mask, /**< Left mouse button */ + MiddleButton = Button2Mask, /**< Middle mouse button */ + RightButton = Button3Mask /**< Right mouse button */ }; /** @@ -248,6 +252,15 @@ class AbstractXContext: public AbstractContext { */ virtual void mouseReleaseEvent(MouseButton button, Modifiers modifiers, const Math::Vector2& position); + /** + * @brief Mouse motion event + * @param modifiers Active modifiers + * @param position Cursor position + * + * Called when mouse is moved. + */ + virtual void mouseMotionEvent(Modifiers modifiers, const Math::Vector2& position); + /*@}*/ private: @@ -279,6 +292,7 @@ inline void AbstractXContext::keyPressEvent(Key, Modifiers, const Math::Vector2< inline void AbstractXContext::keyReleaseEvent(Key, Modifiers, const Math::Vector2&) {} inline void AbstractXContext::mousePressEvent(MouseButton, Modifiers, const Math::Vector2&) {} inline void AbstractXContext::mouseReleaseEvent(MouseButton, Modifiers, const Math::Vector2&) {} +inline void AbstractXContext::mouseMotionEvent(Modifiers, const Math::Vector2&) {} }} From 8a5e7abd30021418d6a86328080eb0a5e18ef506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 11:57:19 +0200 Subject: [PATCH 67/78] SceneGraph: added tests for 2D projection and default projections. --- src/SceneGraph/Test/CameraTest.cpp | 31 ++++++++++++++++++++++++++++-- src/SceneGraph/Test/CameraTest.h | 3 +++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/SceneGraph/Test/CameraTest.cpp b/src/SceneGraph/Test/CameraTest.cpp index d2c514b09..9d89a0365 100644 --- a/src/SceneGraph/Test/CameraTest.cpp +++ b/src/SceneGraph/Test/CameraTest.cpp @@ -23,6 +23,9 @@ namespace Magnum { namespace SceneGraph { namespace Test { CameraTest::CameraTest() { addTests(&CameraTest::fixAspectRatio, + &CameraTest::defaultProjection2D, + &CameraTest::defaultProjection3D, + &CameraTest::projection2D, &CameraTest::orthographic, &CameraTest::perspective); } @@ -69,9 +72,32 @@ void CameraTest::fixAspectRatio() { CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, projectionSize, size), expectedExtendRectangle); } +void CameraTest::defaultProjection2D() { + Camera2D camera; + CORRADE_COMPARE(camera.projectionMatrix(), Matrix3()); +} + +void CameraTest::defaultProjection3D() { + Camera3D camera; + CORRADE_COMPARE(camera.projectionMatrix(), Matrix4()); +} + +void CameraTest::projection2D() { + Vector2 projectionSize(4.0f, 3.0f); + Camera2D camera; + camera.setProjection(projectionSize); + + Matrix3 a(2.0f/4.0f, 0.0f, 0.0f, + 0.0f, 2.0f/3.0f, 0.0f, + 0.0f, 0.0f, 1.0f); + + CORRADE_COMPARE(camera.projectionMatrix(), a); +} + void CameraTest::orthographic() { + Vector2 projectionSize(5); Camera3D camera; - camera.setOrthographic(Vector2(5), 1, 9); + camera.setOrthographic(projectionSize, 1, 9); Matrix4 a(0.4f, 0.0f, 0.0f, 0.0f, 0.0f, 0.4f, 0.0f, 0.0f, @@ -80,7 +106,8 @@ void CameraTest::orthographic() { CORRADE_COMPARE(camera.projectionMatrix(), a); - camera.setOrthographic(Vector2(5.0f, 4.0f), 1, 9); + Vector2 projectionSizeRectangle(5.0f, 4.0f); + camera.setOrthographic(projectionSizeRectangle, 1, 9); Matrix4 rectangle(0.4f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, diff --git a/src/SceneGraph/Test/CameraTest.h b/src/SceneGraph/Test/CameraTest.h index f460c241f..2bf0e93b5 100644 --- a/src/SceneGraph/Test/CameraTest.h +++ b/src/SceneGraph/Test/CameraTest.h @@ -24,6 +24,9 @@ class CameraTest: public Corrade::TestSuite::Tester { CameraTest(); void fixAspectRatio(); + void defaultProjection2D(); + void defaultProjection3D(); + void projection2D(); void orthographic(); void perspective(); }; From e1641fb5c1b8cdef8bd45b625184bc34b3ea65d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 11:57:53 +0200 Subject: [PATCH 68/78] Doc++ --- src/SceneGraph/Camera.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp index 3585ae8dc..63967f990 100644 --- a/src/SceneGraph/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -112,7 +112,7 @@ void Camera3D::setPerspective(GLfloat fov, GLfloat near, GLfloat far) { _near = near; _far = far; - GLfloat xyScale = 1.0f/tan(fov/2); + GLfloat xyScale = 1.0f/tan(fov/2); /* == near/size */ GLfloat zScale = 1.0f/(near-far); rawProjectionMatrix = Matrix4( From 31ead0e35dbde2a01950516bd0f08d5fd8ad2e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 12:10:44 +0200 Subject: [PATCH 69/78] SceneGraph: added forgotten extern template. --- src/SceneGraph/Camera.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index 6378014de..1c3a59e85 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -41,6 +41,7 @@ namespace Implementation { template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2& viewport); /* These templates are instantiated in source file */ + extern template SCENEGRAPH_EXPORT Matrix3 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); extern template SCENEGRAPH_EXPORT Matrix4 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); } #endif From 236e0abc582f652d3a886711fe119551721dbccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 12:13:41 +0200 Subject: [PATCH 70/78] Camera: computing projection scale directly from projection matrix. Storing scale as independent (and inverted) value and updating it separately from projection matrix is just plain wrong. --- src/SceneGraph/Camera.cpp | 11 ++++------- src/SceneGraph/Camera.h | 5 ++--- src/SceneGraph/Test/CameraTest.cpp | 24 ++++++++++++------------ 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp index 63967f990..f6896667b 100644 --- a/src/SceneGraph/Camera.cpp +++ b/src/SceneGraph/Camera.cpp @@ -24,12 +24,12 @@ namespace Magnum { namespace SceneGraph { #ifndef DOXYGEN_GENERATING_OUTPUT namespace Implementation { -template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2& viewport) { +template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionScale, const Math::Vector2& viewport) { /* Don't divide by zero / don't preserve anything */ - if(projectionAspectRatio.x() == 0 || projectionAspectRatio.y() == 0 || viewport.x() == 0 || viewport.y() == 0 || aspectRatioPolicy == AspectRatioPolicy::NotPreserved) + if(projectionScale.x() == 0 || projectionScale.y() == 0 || viewport.x() == 0 || viewport.y() == 0 || aspectRatioPolicy == AspectRatioPolicy::NotPreserved) return MatrixType(); - Vector2 relativeAspectRatio = Vector2::from(viewport)/projectionAspectRatio; + Vector2 relativeAspectRatio = Vector2::from(viewport)*projectionScale; /* Extend on larger side = scale larger side down Clip on smaller side = scale smaller side up */ @@ -46,7 +46,7 @@ template Matrix4 aspectRatioFix(AspectRatioPolicy, const Vector2&, cons } #endif -template Camera::Camera(ObjectType* parent): ObjectType(parent), projectionAspectRatio(1.0f), _aspectRatioPolicy(AspectRatioPolicy::NotPreserved) {} +template Camera::Camera(ObjectType* parent): ObjectType(parent), _aspectRatioPolicy(AspectRatioPolicy::NotPreserved) {} template void Camera::setViewport(const Math::Vector2& size) { Framebuffer::setViewport({0, 0}, size); @@ -86,7 +86,6 @@ void Camera2D::setProjection(const Vector2& size) { /* Scale the volume down so it fits in (-1, 1) in all directions */ rawProjectionMatrix = Matrix3::scaling(2.0f/size); - projectionAspectRatio = size; fixAspectRatio(); } @@ -104,7 +103,6 @@ void Camera3D::setOrthographic(const Vector2& size, GLfloat near, GLfloat far) { 0.0f, 0.0f, near*zScale-1, 1.0f ); - projectionAspectRatio = size; fixAspectRatio(); } @@ -122,7 +120,6 @@ void Camera3D::setPerspective(GLfloat fov, GLfloat near, GLfloat far) { 0.0f, 0.0f, (2*far*near)*zScale, 0.0f ); - projectionAspectRatio = Vector2(xyScale); fixAspectRatio(); } diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index 1c3a59e85..b1a735cf7 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -38,7 +38,7 @@ namespace Implementation { template class Camera {}; - template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionAspectRatio, const Math::Vector2& viewport); + template MatrixType aspectRatioFix(AspectRatioPolicy aspectRatioPolicy, const Vector2& projectionScale, const Math::Vector2& viewport); /* These templates are instantiated in source file */ extern template SCENEGRAPH_EXPORT Matrix3 aspectRatioFix(AspectRatioPolicy, const Vector2&, const Math::Vector2&); @@ -131,10 +131,9 @@ template(_aspectRatioPolicy, projectionAspectRatio, _viewport)*rawProjectionMatrix; + _projectionMatrix = Implementation::aspectRatioFix(_aspectRatioPolicy, {rawProjectionMatrix[0].x(), rawProjectionMatrix[1].y()}, _viewport)*rawProjectionMatrix; } - Vector2 projectionAspectRatio; MatrixType rawProjectionMatrix; AspectRatioPolicy _aspectRatioPolicy; #endif diff --git a/src/SceneGraph/Test/CameraTest.cpp b/src/SceneGraph/Test/CameraTest.cpp index 9d89a0365..d02aefda9 100644 --- a/src/SceneGraph/Test/CameraTest.cpp +++ b/src/SceneGraph/Test/CameraTest.cpp @@ -31,45 +31,45 @@ CameraTest::CameraTest() { } void CameraTest::fixAspectRatio() { - Vector2 projectionSize(2, 3); + Vector2 projectionScale(0.5f, 1.0f/3.0f); Math::Vector2 size(400, 300); /* Division by zero */ - Vector2 projectionSizeZeroY(2, 0); - Vector2 projectionSizeZeroX(0, 2); + Vector2 projectionScaleZeroY(0.5f, 0.0f); + Vector2 projectionScaleZeroX(0.0f, 0.5f); Math::Vector2 sizeZeroY(400, 0); Math::Vector2 sizeZeroX(0, 300); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSizeZeroX, size), Matrix4()); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSizeZeroY, size), Matrix4()); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSize, sizeZeroY), Matrix4()); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, projectionSize, sizeZeroX), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionScaleZeroX, size), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionScaleZeroY, size), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionScale, sizeZeroY), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, projectionScale, sizeZeroX), Matrix4()); /* Not preserved */ - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::NotPreserved, projectionSize, size), Matrix4()); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::NotPreserved, projectionScale, size), Matrix4()); /* Clip */ Matrix4 expectedClip(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.0f/3.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, Vector2(2.0f), size), expectedClip); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, Vector2(0.5f), size), expectedClip); Matrix4 expectedClipRectangle(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionSize, size), expectedClipRectangle); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Clip, projectionScale, size), expectedClipRectangle); /* Extend */ Matrix4 expectedExtend(3.0f/4.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, Vector2(2.0f), size), expectedExtend); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, Vector2(0.5f), size), expectedExtend); Matrix4 expectedExtendRectangle(0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); - CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, projectionSize, size), expectedExtendRectangle); + CORRADE_COMPARE(Implementation::aspectRatioFix(Implementation::AspectRatioPolicy::Extend, projectionScale, size), expectedExtendRectangle); } void CameraTest::defaultProjection2D() { From 924e4f82cef8c6ac93a7adc671546f1249c437d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 12:19:43 +0200 Subject: [PATCH 71/78] Camera: added function to retrieve size of XY projection plane. --- src/SceneGraph/Camera.h | 11 +++++++++++ src/SceneGraph/Test/CameraTest.cpp | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/src/SceneGraph/Camera.h b/src/SceneGraph/Camera.h index b1a735cf7..76faa6c45 100644 --- a/src/SceneGraph/Camera.h +++ b/src/SceneGraph/Camera.h @@ -91,9 +91,20 @@ template viewport() const { return _viewport; } diff --git a/src/SceneGraph/Test/CameraTest.cpp b/src/SceneGraph/Test/CameraTest.cpp index d02aefda9..40dbcfa32 100644 --- a/src/SceneGraph/Test/CameraTest.cpp +++ b/src/SceneGraph/Test/CameraTest.cpp @@ -75,11 +75,13 @@ void CameraTest::fixAspectRatio() { void CameraTest::defaultProjection2D() { Camera2D camera; CORRADE_COMPARE(camera.projectionMatrix(), Matrix3()); + CORRADE_COMPARE(camera.projectionSize(), Vector2(2.0f)); } void CameraTest::defaultProjection3D() { Camera3D camera; CORRADE_COMPARE(camera.projectionMatrix(), Matrix4()); + CORRADE_COMPARE(camera.projectionSize(), Vector2(2.0f)); } void CameraTest::projection2D() { @@ -92,6 +94,7 @@ void CameraTest::projection2D() { 0.0f, 0.0f, 1.0f); CORRADE_COMPARE(camera.projectionMatrix(), a); + CORRADE_COMPARE(camera.projectionSize(), projectionSize); } void CameraTest::orthographic() { @@ -105,6 +108,7 @@ void CameraTest::orthographic() { 0.0f, 0.0f, -1.25f, 1.0f); CORRADE_COMPARE(camera.projectionMatrix(), a); + CORRADE_COMPARE(camera.projectionSize(), projectionSize); Vector2 projectionSizeRectangle(5.0f, 4.0f); camera.setOrthographic(projectionSizeRectangle, 1, 9); @@ -115,6 +119,7 @@ void CameraTest::orthographic() { 0.0f, 0.0f, -1.25f, 1.0f); CORRADE_COMPARE(camera.projectionMatrix(), rectangle); + CORRADE_COMPARE(camera.projectionSize(), projectionSizeRectangle); } void CameraTest::perspective() { @@ -127,6 +132,7 @@ void CameraTest::perspective() { 0.0f, 0.0f, -94.1176452f, 0.0f); CORRADE_COMPARE(camera.projectionMatrix(), a); + CORRADE_COMPARE(camera.projectionSize(), Vector2(0.48015756f)); } }}} From b8750d3702aa79689256cefc8a338aadcecc4c56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 13:22:25 +0200 Subject: [PATCH 72/78] Added Vector2::*Axis(), similar to those in Vector3. --- src/Math/Test/Vector2Test.cpp | 6 ++++++ src/Math/Test/Vector2Test.h | 1 + src/Math/Test/Vector3Test.cpp | 4 ++-- src/Math/Test/Vector3Test.h | 2 +- src/Math/Vector2.h | 6 ++++++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/Math/Test/Vector2Test.cpp b/src/Math/Test/Vector2Test.cpp index 636f19c72..35999b7f2 100644 --- a/src/Math/Test/Vector2Test.cpp +++ b/src/Math/Test/Vector2Test.cpp @@ -30,6 +30,7 @@ typedef Math::Vector2 Vector2; Vector2Test::Vector2Test() { addTests(&Vector2Test::construct, + &Vector2Test::axes, &Vector2Test::debug); } @@ -37,6 +38,11 @@ void Vector2Test::construct() { CORRADE_COMPARE(Vector2(1, 2), (Vector<2, float>(1.0f, 2.0f))); } +void Vector2Test::axes() { + CORRADE_COMPARE(Vector2::xAxis(5.0f), Vector2(5.0f, 0.0f)); + CORRADE_COMPARE(Vector2::yAxis(6.0f), Vector2(0.0f, 6.0f)); +} + void Vector2Test::debug() { ostringstream o; Debug(&o) << Vector2(0.5f, 15.0f); diff --git a/src/Math/Test/Vector2Test.h b/src/Math/Test/Vector2Test.h index 39515fbf9..ef91cf151 100644 --- a/src/Math/Test/Vector2Test.h +++ b/src/Math/Test/Vector2Test.h @@ -24,6 +24,7 @@ class Vector2Test: public Corrade::TestSuite::Tester { Vector2Test(); void construct(); + void axes(); void debug(); }; diff --git a/src/Math/Test/Vector3Test.cpp b/src/Math/Test/Vector3Test.cpp index 6df8a84e7..1a84a2012 100644 --- a/src/Math/Test/Vector3Test.cpp +++ b/src/Math/Test/Vector3Test.cpp @@ -32,7 +32,7 @@ typedef Math::Vector2 Vector2; Vector3Test::Vector3Test() { addTests(&Vector3Test::construct, &Vector3Test::cross, - &Vector3Test::axis, + &Vector3Test::axes, &Vector3Test::twoComponent, &Vector3Test::debug); } @@ -49,7 +49,7 @@ void Vector3Test::cross() { CORRADE_COMPARE(Vector3::cross(a, b), Vector3(-10, -3, 7)); } -void Vector3Test::axis() { +void Vector3Test::axes() { CORRADE_COMPARE(Vector3::xAxis(5.0f), Vector3(5.0f, 0.0f, 0.0f)); CORRADE_COMPARE(Vector3::yAxis(6.0f), Vector3(0.0f, 6.0f, 0.0f)); CORRADE_COMPARE(Vector3::zAxis(7.0f), Vector3(0.0f, 0.0f, 7.0f)); diff --git a/src/Math/Test/Vector3Test.h b/src/Math/Test/Vector3Test.h index 73de924e9..4d817dc07 100644 --- a/src/Math/Test/Vector3Test.h +++ b/src/Math/Test/Vector3Test.h @@ -25,7 +25,7 @@ class Vector3Test: public Corrade::TestSuite::Tester { void construct(); void cross(); - void axis(); + void axes(); void twoComponent(); void debug(); diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 262fe58c8..8bd0e6f35 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -26,6 +26,12 @@ namespace Magnum { namespace Math { /** @brief Two-component vector */ template class Vector2: public Vector<2, T> { public: + /** @brief %Vector in direction of X axis */ + inline constexpr static Vector2 xAxis(T length = T(1)) { return Vector2(length, T()); } + + /** @brief %Vector in direction of Y axis */ + inline constexpr static Vector2 yAxis(T length = T(1)) { return Vector2(T(), length); } + /** @copydoc Vector::Vector(T) */ inline constexpr explicit Vector2(T value = T()): Vector<2, T>(value, value) {} From d96cb96d606a06358bcc82efe64170a53f33d10c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 13:40:49 +0200 Subject: [PATCH 73/78] Documented convenience functions on vectors and angles. --- src/Math/Math.h | 16 +++++++++++----- src/Math/Matrix3.h | 4 ++-- src/Math/Matrix4.h | 4 ++-- src/Math/Vector2.h | 16 ++++++++++++++-- src/Math/Vector3.h | 23 ++++++++++++++++++++--- 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/Math/Math.h b/src/Math/Math.h index 21191b360..aa9d77723 100644 --- a/src/Math/Math.h +++ b/src/Math/Math.h @@ -130,17 +130,23 @@ template inline constexpr typename std::ena } /** - * @brief Angle in degrees - * - * Function to make angle entering less error-prone. Converts the value to - * radians at compile time. For example `deg(180.0f)` is converted to `3.14f`. +@brief Angle in degrees + +Function to make angle entering less error-prone. Converts the value to +radians at compile time. For example `deg(180.0f)` is converted to `3.14f`. + +Usable for entering e.g. rotation: +@code +Matrix4::rotation(deg(30.0f), Vector3::yAxis()); +@endcode +@see rad() */ template inline constexpr T deg(T value) { return value*Constants::pi()/180; } /** * @brief Angle in radians * - * See also deg(). + * See deg() for more information. */ template inline constexpr T rad(T value) { return value; } diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index 1dec2c7f3..190aa9832 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -36,7 +36,7 @@ template class Matrix3: public Matrix<3, T> { * @brief 2D translation matrix * @param vec Translation vector * - * @see Matrix4::translation() + * @see Matrix4::translation(), Vector2::xAxis(), Vector2::yAxis() */ inline constexpr static Matrix3 translation(const Vector2& vec) { return Matrix3( /* Column-major! */ @@ -64,7 +64,7 @@ template class Matrix3: public Matrix<3, T> { * @brief 3D rotation matrix * @param angle Rotation angle (counterclockwise, in radians) * - * @see Matrix4::rotation() + * @see Matrix4::rotation(), deg(), rad() */ static Matrix3 rotation(T angle) { return Matrix3( /* Column-major! */ diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index fcecef081..172c05f70 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -38,7 +38,7 @@ template class Matrix4: public Matrix<4, T> { * @brief 3D translation matrix * @param vec Translation vector * - * @see Matrix3::translation() + * @see Matrix3::translation(), Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis() */ inline constexpr static Matrix4 translation(const Vector3& vec) { return Matrix4( /* Column-major! */ @@ -69,7 +69,7 @@ template class Matrix4: public Matrix<4, T> { * @param angle Rotation angle (counterclockwise, in radians) * @param vec Rotation vector * - * @see Matrix3::rotation() + * @see Matrix3::rotation(), Vector3::xAxis(), Vector3::yAxis(), Vector3::zAxis(), deg(), rad() * @todo optimize - Assume the vectors are normalized? */ static Matrix4 rotation(T angle, const Vector3& vec) { diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 8bd0e6f35..0caa28b5b 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -26,10 +26,22 @@ namespace Magnum { namespace Math { /** @brief Two-component vector */ template class Vector2: public Vector<2, T> { public: - /** @brief %Vector in direction of X axis */ + /** + * @brief %Vector in direction of X axis + * + * Usable for translation in given axis, for example: + * @code + * Matrix3::translation(Vector2::xAxis(5.0f)); // same as Matrix3::translation({5.0f, 0.0f}); + * @endcode + * @see yAxis() + */ inline constexpr static Vector2 xAxis(T length = T(1)) { return Vector2(length, T()); } - /** @brief %Vector in direction of Y axis */ + /** + * @brief %Vector in direction of Y axis + * + * See xAxis() for more information. + */ inline constexpr static Vector2 yAxis(T length = T(1)) { return Vector2(T(), length); } /** @copydoc Vector::Vector(T) */ diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index 29edd6df7..13c495332 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -26,13 +26,30 @@ namespace Magnum { namespace Math { /** @brief Three-component vector */ template class Vector3: public Vector<3, T> { public: - /** @brief %Vector in direction of X axis */ + /** + * @brief %Vector in direction of X axis + * + * Usable for translation or rotation along given axis, for example: + * @code + * Matrix4::translation(Vector3::xAxis(5.0f)); // same as Matrix4::translation({5.0f, 0.0f, 0.0f}); + * Matrix4::rotation(deg(30.0f), Vector3::xAxis()); // same as Matrix::rotation(deg(30.0f), {1.0f, 0.0f, 0.0f}); + * @endcode + * @see yAxis(), zAxis() + */ inline constexpr static Vector3 xAxis(T length = T(1)) { return Vector3(length, T(), T()); } - /** @brief %Vector in direction of Y axis */ + /** + * @brief %Vector in direction of Y axis + * + * See xAxis() for more information. + */ inline constexpr static Vector3 yAxis(T length = T(1)) { return Vector3(T(), length, T()); } - /** @brief %Vector in direction of Z axis */ + /** + * @brief %Vector in direction of Z axis + * + * See xAxis() for more information. + */ inline constexpr static Vector3 zAxis(T length = T(1)) { return Vector3(T(), T(), length); } /** From a5b8afa122a6c91adefa8c001fa4bcb06574358b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 13:55:59 +0200 Subject: [PATCH 74/78] Added Vector2::*Scale() and Vector3::*Scale(). Complements to *Axis for scaling. --- src/Math/Matrix3.h | 2 +- src/Math/Matrix4.h | 2 +- src/Math/Test/Vector2Test.cpp | 6 ++++++ src/Math/Test/Vector2Test.h | 1 + src/Math/Test/Vector3Test.cpp | 7 +++++++ src/Math/Test/Vector3Test.h | 1 + src/Math/Vector2.h | 22 +++++++++++++++++++++- src/Math/Vector3.h | 31 ++++++++++++++++++++++++++++++- 8 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index 190aa9832..7ee74c4a7 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -50,7 +50,7 @@ template class Matrix3: public Matrix<3, T> { * @brief 2D scaling matrix * @param vec Scaling vector * - * @see Matrix4::scaling() + * @see Matrix4::scaling(), Vector2::xScale(), Vector2::yScale() */ inline constexpr static Matrix3 scaling(const Vector2& vec) { return Matrix3( /* Column-major! */ diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index 172c05f70..602dfd98a 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -53,7 +53,7 @@ template class Matrix4: public Matrix<4, T> { * @brief 3D scaling matrix * @param vec Scaling vector * - * @see Matrix3::scaling() + * @see Matrix3::scaling(), Vector3::xScale(), Vector3::yScale(), Vector3::zScale() */ inline constexpr static Matrix4 scaling(const Vector3& vec) { return Matrix4( /* Column-major! */ diff --git a/src/Math/Test/Vector2Test.cpp b/src/Math/Test/Vector2Test.cpp index 35999b7f2..a3a6e9753 100644 --- a/src/Math/Test/Vector2Test.cpp +++ b/src/Math/Test/Vector2Test.cpp @@ -31,6 +31,7 @@ typedef Math::Vector2 Vector2; Vector2Test::Vector2Test() { addTests(&Vector2Test::construct, &Vector2Test::axes, + &Vector2Test::scales, &Vector2Test::debug); } @@ -43,6 +44,11 @@ void Vector2Test::axes() { CORRADE_COMPARE(Vector2::yAxis(6.0f), Vector2(0.0f, 6.0f)); } +void Vector2Test::scales() { + CORRADE_COMPARE(Vector2::xScale(-5.0f), Vector2(-5.0f, 1.0f)); + CORRADE_COMPARE(Vector2::yScale(-0.2f), Vector2(1.0f, -0.2f)); +} + void Vector2Test::debug() { ostringstream o; Debug(&o) << Vector2(0.5f, 15.0f); diff --git a/src/Math/Test/Vector2Test.h b/src/Math/Test/Vector2Test.h index ef91cf151..128f271be 100644 --- a/src/Math/Test/Vector2Test.h +++ b/src/Math/Test/Vector2Test.h @@ -25,6 +25,7 @@ class Vector2Test: public Corrade::TestSuite::Tester { void construct(); void axes(); + void scales(); void debug(); }; diff --git a/src/Math/Test/Vector3Test.cpp b/src/Math/Test/Vector3Test.cpp index 1a84a2012..1ea4ad574 100644 --- a/src/Math/Test/Vector3Test.cpp +++ b/src/Math/Test/Vector3Test.cpp @@ -33,6 +33,7 @@ Vector3Test::Vector3Test() { addTests(&Vector3Test::construct, &Vector3Test::cross, &Vector3Test::axes, + &Vector3Test::scales, &Vector3Test::twoComponent, &Vector3Test::debug); } @@ -55,6 +56,12 @@ void Vector3Test::axes() { CORRADE_COMPARE(Vector3::zAxis(7.0f), Vector3(0.0f, 0.0f, 7.0f)); } +void Vector3Test::scales() { + CORRADE_COMPARE(Vector3::xScale(-5.0f), Vector3(-5.0f, 1.0f, 1.0f)); + CORRADE_COMPARE(Vector3::yScale(-0.2f), Vector3(1.0f, -0.2f, 1.0f)); + CORRADE_COMPARE(Vector3::zScale(71.0f), Vector3(1.0f, 1.0f, 71.0f)); +} + void Vector3Test::twoComponent() { CORRADE_COMPARE(Vector3(1.0f, 2.0f, 3.0f).xy(), Vector2(1.0f, 2.0f)); } diff --git a/src/Math/Test/Vector3Test.h b/src/Math/Test/Vector3Test.h index 4d817dc07..247c63e0d 100644 --- a/src/Math/Test/Vector3Test.h +++ b/src/Math/Test/Vector3Test.h @@ -26,6 +26,7 @@ class Vector3Test: public Corrade::TestSuite::Tester { void construct(); void cross(); void axes(); + void scales(); void twoComponent(); void debug(); diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 0caa28b5b..8c81dce48 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -33,7 +33,7 @@ template class Vector2: public Vector<2, T> { * @code * Matrix3::translation(Vector2::xAxis(5.0f)); // same as Matrix3::translation({5.0f, 0.0f}); * @endcode - * @see yAxis() + * @see yAxis(), xScale() */ inline constexpr static Vector2 xAxis(T length = T(1)) { return Vector2(length, T()); } @@ -41,9 +41,29 @@ template class Vector2: public Vector<2, T> { * @brief %Vector in direction of Y axis * * See xAxis() for more information. + * @see yScale() */ inline constexpr static Vector2 yAxis(T length = T(1)) { return Vector2(T(), length); } + /** + * @brief Scaling vector in direction of X axis + * + * Usable for scaling along given direction, for example: + * @code + * Matrix3::scaling(Vector2::xScale(-2.0f)); // same as Matrix3::scaling({-2.0f, 1.0f}); + * @endcode + * @see yScale(), xAxis() + */ + inline constexpr static Vector2 xScale(T scale) { return Vector2(scale, T(1)); } + + /** + * @brief Scaling vector in direction of Y axis + * + * See xScale() for more information. + * @see yAxis() + */ + inline constexpr static Vector2 yScale(T scale) { return Vector2(T(1), scale); } + /** @copydoc Vector::Vector(T) */ inline constexpr explicit Vector2(T value = T()): Vector<2, T>(value, value) {} diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index 13c495332..2510c1f2e 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -34,7 +34,7 @@ template class Vector3: public Vector<3, T> { * Matrix4::translation(Vector3::xAxis(5.0f)); // same as Matrix4::translation({5.0f, 0.0f, 0.0f}); * Matrix4::rotation(deg(30.0f), Vector3::xAxis()); // same as Matrix::rotation(deg(30.0f), {1.0f, 0.0f, 0.0f}); * @endcode - * @see yAxis(), zAxis() + * @see yAxis(), zAxis(), xScale() */ inline constexpr static Vector3 xAxis(T length = T(1)) { return Vector3(length, T(), T()); } @@ -42,6 +42,7 @@ template class Vector3: public Vector<3, T> { * @brief %Vector in direction of Y axis * * See xAxis() for more information. + * @see yScale() */ inline constexpr static Vector3 yAxis(T length = T(1)) { return Vector3(T(), length, T()); } @@ -49,9 +50,37 @@ template class Vector3: public Vector<3, T> { * @brief %Vector in direction of Z axis * * See xAxis() for more information. + * @see zScale() */ inline constexpr static Vector3 zAxis(T length = T(1)) { return Vector3(T(), T(), length); } + /** + * @brief Scaling vector in direction of X axis + * + * Usable for scaling along given direction, for example: + * @code + * Matrix4::scaling(Vector3::xScale(-2.0f)); // same as Matrix4::scaling({-2.0f, 1.0f, 1.0f}); + * @endcode + * @see yScale(), zScale(), xAxis() + */ + inline constexpr static Vector3 xScale(T scale) { return Vector3(scale, T(1), T(1)); } + + /** + * @brief Scaling vector in direction of Y axis + * + * See xScale() for more information. + * @see yAxis() + */ + inline constexpr static Vector3 yScale(T scale) { return Vector3(T(1), scale, T(1)); } + + /** + * @brief Scaling vector in direction of Z axis + * + * See xScale() for more information. + * @see zAxis() + */ + inline constexpr static Vector3 zScale(T scale) { return Vector3(T(1), T(1), scale); } + /** * @brief Cross product * From 2b62cc401294ffec79f778b74bbdff6be74bfa7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 16:22:28 +0200 Subject: [PATCH 75/78] Prefer to use (col, row) instead of [col][row] on matrices. They should be in theory both compiled to the same code, but in practice [][] sometimes fails during optimization. --- src/Math/Matrix.h | 36 +++++++++++++++++++++++------------- src/Math/Test/MatrixTest.cpp | 13 +++++++------ 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index d1ca9b4a2..4e08c1903 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -125,7 +125,12 @@ template class Matrix { inline T* data() { return _data; } inline constexpr const T* data() const { return _data; } /**< @overload */ - /** @brief %Matrix column */ + /** + * @brief %Matrix column + * + * For accessing individual elements prefer to use operator(), as it + * is guaranteed to not involve unnecessary conversions. + */ inline Vector& operator[](size_t col) { return Vector::from(_data+col*size); } @@ -134,6 +139,20 @@ template class Matrix { return Vector::from(_data+col*size); } + /** + * @brief Element on given position + * + * Prefer this instead of using `[][]`. + * @see operator[] + */ + inline T& operator()(size_t col, size_t row) { + return _data[col*size+row]; + } + /** @overload */ + inline constexpr const T& operator()(size_t col, size_t row) const { + return _data[col*size+row]; + } + /** @brief Equality operator */ inline bool operator==(const Matrix& other) const { for(size_t i = 0; i != size*size; ++i) @@ -243,15 +262,6 @@ template class Matrix { return Matrix(first, next...); } - /* Used internally instead of [][], because GCC does some heavy - optimalization in release mode which breaks it */ - inline T& operator()(size_t col, size_t row) { - return _data[col*size+row]; - } - inline constexpr const T& operator()(size_t col, size_t row) const { - return _data[col*size+row]; - } - T _data[size*size]; }; @@ -318,7 +328,7 @@ template class MatrixDeterminant { T out(0); for(size_t col = 0; col != size; ++col) - out += ((col & 1) ? -1 : 1)*m[col][0]*m.ij(col, 0).determinant(); + out += ((col & 1) ? -1 : 1)*m(col, 0)*m.ij(col, 0).determinant(); return out; } @@ -328,7 +338,7 @@ template class MatrixDeterminant<2, T> { public: /** @brief Functor */ inline constexpr T operator()(const Matrix<2, T>& m) { - return m[0][0]*m[1][1] - m[1][0]*m[0][1]; + return m(0, 0)*m(1, 1) - m(1, 0)*m(0, 1); } }; @@ -336,7 +346,7 @@ template class MatrixDeterminant<1, T> { public: /** @brief Functor */ inline constexpr T operator()(const Matrix<1, T>& m) { - return m[0][0]; + return m(0, 0); } }; diff --git a/src/Math/Test/MatrixTest.cpp b/src/Math/Test/MatrixTest.cpp index 8514f8779..2452a78b7 100644 --- a/src/Math/Test/MatrixTest.cpp +++ b/src/Math/Test/MatrixTest.cpp @@ -124,9 +124,10 @@ void MatrixTest::data() { m[3] = vector; m[2][1] = 1.0f; - m[1][2] = 1.5f; + m(1, 2) = 1.5f; - CORRADE_COMPARE(m[2][1], 1.0f); + CORRADE_COMPARE(m(2, 1), 1.0f); + CORRADE_COMPARE(m[1][2], 1.5f); CORRADE_COMPARE(m[3], vector); Matrix4 expected( @@ -142,20 +143,20 @@ void MatrixTest::data() { void MatrixTest::copy() { Matrix4 m1(Matrix4::Zero); - m1[2][3] = 1.0f; + m1(2, 3) = 1.0f; /* Copy */ Matrix4 m2(m1); Matrix4 m3; - m3[0][0] = 1.0f; /* this line is here so it's not optimized to Matrix4 m3(m1) */ + m3(0, 0) = 1.0f; /* this line is here so it's not optimized to Matrix4 m3(m1) */ m3 = m1; /* Change original */ - m1[3][2] = 1.0f; + m1(3, 2) = 1.0f; /* Verify the copy is the same as original */ Matrix4 original(Matrix4::Zero); - original[2][3] = 1.0f; + original(2, 3) = 1.0f; CORRADE_COMPARE(m2, original); CORRADE_COMPARE(m3, original); From 1ade64ca6b2107be603127d7b2c9503bb88227b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 17:50:03 +0200 Subject: [PATCH 76/78] New crossreferenced @debugoperator alias. --- Doxyfile | 2 +- src/Color.h | 4 ++-- src/Math/Matrix.h | 2 +- src/Math/Matrix3.h | 2 +- src/Math/Matrix4.h | 2 +- src/Math/Vector.h | 2 +- src/Math/Vector2.h | 2 +- src/Math/Vector3.h | 2 +- src/Math/Vector4.h | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Doxyfile b/Doxyfile index fdfd9b5e7..8c6c050e4 100644 --- a/Doxyfile +++ b/Doxyfile @@ -195,7 +195,7 @@ TAB_SIZE = 8 # You can put \n's in the value part of an alias to insert newlines. ALIASES = \ - "debugoperator{1}=@relates \1\n@brief Debug output operator" \ + "debugoperator{1}=@relates \1\n@brief Debug output operator @xrefitem debugoperators \"Debug output operator\" \"Debug output operators for custom types\" Allows printing \1 with Corrade::Utility::Debug and friends." \ "collisionoperator{2}=@relates \1\n@brief Collision of %\1 and %\2\n@see \2::operator%(const \1&) const" \ "todoc=@xrefitem todoc \"Documentation todo\" \"Documentation-related todo list\"" \ "requires_gl=@xrefitem requires-gl \"Requires desktop OpenGL\" \"Functionality requiring desktop OpenGL (not available on OpenGL ES)\" Not available on OpenGL ES." \ diff --git a/src/Color.h b/src/Color.h index abfafa345..626e3adb8 100644 --- a/src/Color.h +++ b/src/Color.h @@ -396,12 +396,12 @@ template class Color4: public Math::Vector4 { } }; -/** @debugoperator{Color3} */ +/** @debugoperator{Magnum::Color3} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Color3& value) { return debug << static_cast&>(value); } -/** @debugoperator{Color4} */ +/** @debugoperator{Magnum::Color4} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Color4& value) { return debug << static_cast&>(value); } diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index 4e08c1903..4cb2a60c7 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -265,7 +265,7 @@ template class Matrix { T _data[size*size]; }; -/** @debugoperator{Matrix} */ +/** @debugoperator{Magnum::Math::Matrix} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Matrix& value) { debug << "Matrix("; debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false); diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index 7ee74c4a7..35b121f6d 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -97,7 +97,7 @@ template class Matrix3: public Matrix<3, T> { MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Matrix3, Vector3, 3) }; -/** @debugoperator{Matrix3} */ +/** @debugoperator{Magnum::Math::Matrix3} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Matrix3& value) { return debug << static_cast&>(value); } diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index 602dfd98a..a7e8912a7 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -146,7 +146,7 @@ template class Matrix4: public Matrix<4, T> { MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Matrix4, Vector4, 4) }; -/** @debugoperator{Matrix4} */ +/** @debugoperator{Magnum::Math::Matrix4} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Matrix4& value) { return debug << static_cast&>(value); } diff --git a/src/Math/Vector.h b/src/Math/Vector.h index a2714007c..eede07b42 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -439,7 +439,7 @@ template Vector operator/(U number, cons return out; } -/** @debugoperator{Vector} */ +/** @debugoperator{Magnum::Math::Vector} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector& value) { debug << "Vector("; debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false); diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 8c81dce48..3dde7c5a1 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -88,7 +88,7 @@ template class Vector2: public Vector<2, T> { MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Vector2, 2) -/** @debugoperator{Vector2} */ +/** @debugoperator{Magnum::Math::Vector2} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector2& value) { return debug << static_cast&>(value); } diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index 2510c1f2e..9beae4e77 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -140,7 +140,7 @@ template class Vector3: public Vector<3, T> { MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Vector3, 3) -/** @debugoperator{Vector3} */ +/** @debugoperator{Magnum::Math::Vector3} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector3& value) { return debug << static_cast&>(value); } diff --git a/src/Math/Vector4.h b/src/Math/Vector4.h index 88fb0f5d8..a33752b8d 100644 --- a/src/Math/Vector4.h +++ b/src/Math/Vector4.h @@ -88,7 +88,7 @@ template class Vector4: public Vector<4, T> { MAGNUM_VECTOR_SUBCLASS_OPERATOR_IMPLEMENTATION(Vector4, 4) -/** @debugoperator{Vector4} */ +/** @debugoperator{Magnum::Math::Vector4} */ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Magnum::Math::Vector4& value) { return debug << static_cast&>(value); } From d5d4215a458e45479128a2c6a713c841bedba744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 17:51:38 +0200 Subject: [PATCH 77/78] Color: test for debug operators. --- src/Test/ColorTest.cpp | 17 ++++++++++++++++- src/Test/ColorTest.h | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Test/ColorTest.cpp b/src/Test/ColorTest.cpp index a500ffee4..3c3334ccd 100644 --- a/src/Test/ColorTest.cpp +++ b/src/Test/ColorTest.cpp @@ -21,11 +21,14 @@ using namespace std; CORRADE_TEST_MAIN(Magnum::Test::ColorTest) +using namespace Corrade::Utility; + namespace Magnum { namespace Test { typedef Magnum::Color3 Color3; typedef Magnum::Color4 Color4; typedef Magnum::Color3 Color3f; +typedef Magnum::Color4 Color4f; ColorTest::ColorTest() { addTests(&ColorTest::fromDenormalized, @@ -41,7 +44,9 @@ ColorTest::ColorTest() { &ColorTest::hsv, &ColorTest::hsvOverflow, - &ColorTest::hsvAlpha); + &ColorTest::hsvAlpha, + + &ColorTest::debug); } void ColorTest::fromDenormalized() { @@ -118,4 +123,14 @@ void ColorTest::hsvAlpha() { CORRADE_COMPARE(Color4::fromHSV(230.0f, 0.749f, 0.427f, 23), Color4(27, 41, 109, 23)); } +void ColorTest::debug() { + ostringstream o; + Debug(&o) << Color3f(0.5f, 0.75f, 1.0f); + CORRADE_COMPARE(o.str(), "Vector(0.5, 0.75, 1)\n"); + + o.str(""); + Debug(&o) << Color4f(0.5f, 0.75f, 0.0f, 1.0f); + CORRADE_COMPARE(o.str(), "Vector(0.5, 0.75, 0, 1)\n"); +} + }} diff --git a/src/Test/ColorTest.h b/src/Test/ColorTest.h index 068e36da6..a1ee2a727 100644 --- a/src/Test/ColorTest.h +++ b/src/Test/ColorTest.h @@ -37,6 +37,8 @@ class ColorTest: public Corrade::TestSuite::Tester { void hsv(); void hsvOverflow(); void hsvAlpha(); + + void debug(); }; }} From 0e74c3847dcc0f18072c48d3cf6381cc4df696a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 20 Aug 2012 18:04:10 +0200 Subject: [PATCH 78/78] Support for storing matrices and vectors in configuration. --- Doxyfile | 2 ++ doc/coding-style.dox | 4 +-- src/Color.h | 8 ++++++ src/Math/Matrix.h | 46 ++++++++++++++++++++++++++++++++--- src/Math/Matrix3.h | 6 +++++ src/Math/Matrix4.h | 6 +++++ src/Math/Test/Matrix3Test.cpp | 14 ++++++++++- src/Math/Test/Matrix3Test.h | 2 ++ src/Math/Test/Matrix4Test.cpp | 15 +++++++++++- src/Math/Test/Matrix4Test.h | 1 + src/Math/Test/MatrixTest.cpp | 15 +++++++++++- src/Math/Test/MatrixTest.h | 1 + src/Math/Test/Vector2Test.cpp | 10 +++++++- src/Math/Test/Vector2Test.h | 2 ++ src/Math/Test/Vector3Test.cpp | 10 +++++++- src/Math/Test/Vector3Test.h | 1 + src/Math/Test/Vector4Test.cpp | 10 +++++++- src/Math/Test/Vector4Test.h | 1 + src/Math/Test/VectorTest.cpp | 10 +++++++- src/Math/Test/VectorTest.h | 1 + src/Math/Vector.h | 42 ++++++++++++++++++++++++++++++-- src/Math/Vector2.h | 11 ++++++++- src/Math/Vector3.h | 11 ++++++++- src/Math/Vector4.h | 11 ++++++++- src/Test/ColorTest.cpp | 15 +++++++++++- src/Test/ColorTest.h | 1 + 26 files changed, 237 insertions(+), 19 deletions(-) diff --git a/Doxyfile b/Doxyfile index 8c6c050e4..a9b8a684f 100644 --- a/Doxyfile +++ b/Doxyfile @@ -196,6 +196,8 @@ TAB_SIZE = 8 ALIASES = \ "debugoperator{1}=@relates \1\n@brief Debug output operator @xrefitem debugoperators \"Debug output operator\" \"Debug output operators for custom types\" Allows printing \1 with Corrade::Utility::Debug and friends." \ + "configurationvalueref{1}=@see @ref configurationvalues \"Corrade::Utility::ConfigurationValue<\1>\"" \ + "configurationvalue{1}=@brief %Configuration value parser and writer @xrefitem configurationvalues \"Configuration value parser and writer\" \"Configuration value parsers and writers for custom types\" Allows parsing and writing \1 from and to Corrade::Utility::Configuration." \ "collisionoperator{2}=@relates \1\n@brief Collision of %\1 and %\2\n@see \2::operator%(const \1&) const" \ "todoc=@xrefitem todoc \"Documentation todo\" \"Documentation-related todo list\"" \ "requires_gl=@xrefitem requires-gl \"Requires desktop OpenGL\" \"Functionality requiring desktop OpenGL (not available on OpenGL ES)\" Not available on OpenGL ES." \ diff --git a/doc/coding-style.dox b/doc/coding-style.dox index acab6dc81..09fbdcb80 100644 --- a/doc/coding-style.dox +++ b/doc/coding-style.dox @@ -33,8 +33,8 @@ removing redundant prefixes) is encouraged. @subsection documentation-commands Special documentation commands -Additionally to @c \@todoc and @c \@debugoperator (same as in Corrade), these -are defined: +Additionally to @c \@todoc, @c \@debugoperator @c \@configurationvalue and +@c \@configurationvalueref (same as in Corrade), these are defined: @subsubsection documentation-commands-collisionoperator Physics collision operators diff --git a/src/Color.h b/src/Color.h index 626e3adb8..c95e010a3 100644 --- a/src/Color.h +++ b/src/Color.h @@ -408,4 +408,12 @@ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug deb } +namespace Corrade { namespace Utility { + /** @configurationvalue{Magnum::Color3} */ + template struct ConfigurationValue>: public ConfigurationValue> {}; + + /** @configurationvalue{Magnum::Color4} */ + template struct ConfigurationValue>: public ConfigurationValue> {}; +}} + #endif diff --git a/src/Math/Matrix.h b/src/Math/Matrix.h index 4cb2a60c7..263185396 100644 --- a/src/Math/Matrix.h +++ b/src/Math/Matrix.h @@ -30,10 +30,11 @@ namespace Implementation { #endif /** - * @brief %Matrix - * - * @todo @c PERFORMANCE - loop unrolling for Matrix<3, T> and Matrix<4, T> - * @todo first col, then row (cache adjacency) +@brief %Matrix + +@configurationvalueref{Magnum::Math::Matrix} +@todo @c PERFORMANCE - loop unrolling for Matrix<3, T> and Matrix<4, T> +@todo first col, then row (cache adjacency) */ template class Matrix { static_assert(size != 0, "Matrix cannot have zero elements"); @@ -355,4 +356,41 @@ template class MatrixDeterminant<1, T> { }} +namespace Corrade { namespace Utility { + +/** @configurationvalue{Magnum::Math::Matrix} */ +template struct ConfigurationValue> { + /** @brief Writes elements separated with spaces */ + static std::string toString(const Magnum::Math::Matrix& value, int flags = 0) { + std::string output; + + for(size_t row = 0; row != size; ++row) { + for(size_t col = 0; col != size; ++col) { + if(!output.empty()) output += ' '; + output += ConfigurationValue::toString(value(col, row), flags); + } + } + + return output; + } + + /** @brief Reads elements separated with whitespace */ + static Magnum::Math::Matrix fromString(const std::string& stringValue, int flags = 0) { + Magnum::Math::Matrix result(Magnum::Math::Matrix::Zero); + std::istringstream in(stringValue); + + for(size_t row = 0; row != size; ++row) { + for(size_t col = 0; col != size; ++col) { + std::string num; + in >> num; + result(col, row) = ConfigurationValue::fromString(num, flags); + } + } + + return result; + } +}; + +}} + #endif diff --git a/src/Math/Matrix3.h b/src/Math/Matrix3.h index 35b121f6d..1cf5640b8 100644 --- a/src/Math/Matrix3.h +++ b/src/Math/Matrix3.h @@ -29,6 +29,7 @@ namespace Magnum { namespace Math { Provides functions for transformations in 2D. See also Matrix4 for 3D transformations. +@configurationvalueref{Magnum::Math::Matrix3} */ template class Matrix3: public Matrix<3, T> { public: @@ -104,4 +105,9 @@ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug deb }} +namespace Corrade { namespace Utility { + /** @configurationvalue{Magnum::Math::Matrix3} */ + template struct ConfigurationValue>: public ConfigurationValue> {}; +}} + #endif diff --git a/src/Math/Matrix4.h b/src/Math/Matrix4.h index a7e8912a7..c4b0f3935 100644 --- a/src/Math/Matrix4.h +++ b/src/Math/Matrix4.h @@ -29,6 +29,7 @@ namespace Magnum { namespace Math { Provides functions for transformations in 3D. See also Matrix3 for 2D transformations. +@configurationvalueref{Magnum::Math::Matrix4} @todo Shearing @todo Reflection */ @@ -153,4 +154,9 @@ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug deb }} +namespace Corrade { namespace Utility { + /** @configurationvalue{Magnum::Math::Matrix4} */ + template struct ConfigurationValue>: public ConfigurationValue> {}; +}} + #endif diff --git a/src/Math/Test/Matrix3Test.cpp b/src/Math/Test/Matrix3Test.cpp index dc01cb2f2..840e75c92 100644 --- a/src/Math/Test/Matrix3Test.cpp +++ b/src/Math/Test/Matrix3Test.cpp @@ -34,7 +34,8 @@ Matrix3Test::Matrix3Test() { &Matrix3Test::translation, &Matrix3Test::scaling, &Matrix3Test::rotation, - &Matrix3Test::debug); + &Matrix3Test::debug, + &Matrix3Test::configuration); } void Matrix3Test::constructIdentity() { @@ -103,4 +104,15 @@ void Matrix3Test::debug() { " 8, 7, 8)\n"); } +void Matrix3Test::configuration() { + Matrix3 m( + 5.0f, 8.0f, 4.0f, + 4.0f, 7.0f, 3.125f, + 4.0f, 5.0f, 9.55f + ); + string value("5 4 4 8 7 5 4 3.125 9.55"); + CORRADE_COMPARE(ConfigurationValue::toString(m), value); + CORRADE_COMPARE(ConfigurationValue::fromString(value), m); +} + }}} diff --git a/src/Math/Test/Matrix3Test.h b/src/Math/Test/Matrix3Test.h index 27544cd0e..2402fbc93 100644 --- a/src/Math/Test/Matrix3Test.h +++ b/src/Math/Test/Matrix3Test.h @@ -28,7 +28,9 @@ class Matrix3Test: public Corrade::TestSuite::Tester { void translation(); void scaling(); void rotation(); + void debug(); + void configuration(); }; }}} diff --git a/src/Math/Test/Matrix4Test.cpp b/src/Math/Test/Matrix4Test.cpp index 0d9b813cb..9cc253cc6 100644 --- a/src/Math/Test/Matrix4Test.cpp +++ b/src/Math/Test/Matrix4Test.cpp @@ -37,7 +37,8 @@ Matrix4Test::Matrix4Test() { &Matrix4Test::rotation, &Matrix4Test::rotationScalingPart, &Matrix4Test::rotationPart, - &Matrix4Test::debug); + &Matrix4Test::debug, + &Matrix4Test::configuration); } void Matrix4Test::constructIdentity() { @@ -144,4 +145,16 @@ void Matrix4Test::debug() { " 4, 3, 0, 9)\n"); } +void Matrix4Test::configuration() { + Matrix4 m( + 3.0f, 5.0f, 8.0f, 4.0f, + 4.0f, 4.0f, 7.0f, 3.125f, + 7.0f, -1.0f, 8.0f, 0.0f, + 9.0f, 4.0f, 5.0f, 9.55f + ); + string value("3 4 7 9 5 4 -1 4 8 7 8 5 4 3.125 0 9.55"); + CORRADE_COMPARE(ConfigurationValue::toString(m), value); + CORRADE_COMPARE(ConfigurationValue::fromString(value), m); +} + }}} diff --git a/src/Math/Test/Matrix4Test.h b/src/Math/Test/Matrix4Test.h index 5138e3a3a..a49cfddb1 100644 --- a/src/Math/Test/Matrix4Test.h +++ b/src/Math/Test/Matrix4Test.h @@ -32,6 +32,7 @@ class Matrix4Test: public Corrade::TestSuite::Tester { void rotationPart(); void debug(); + void configuration(); }; }}} diff --git a/src/Math/Test/MatrixTest.cpp b/src/Math/Test/MatrixTest.cpp index 2452a78b7..d9e986c85 100644 --- a/src/Math/Test/MatrixTest.cpp +++ b/src/Math/Test/MatrixTest.cpp @@ -44,7 +44,8 @@ MatrixTest::MatrixTest() { &MatrixTest::ij, &MatrixTest::determinant, &MatrixTest::inverted, - &MatrixTest::debug); + &MatrixTest::debug, + &MatrixTest::configuration); } void MatrixTest::construct() { @@ -308,4 +309,16 @@ void MatrixTest::debug() { " 0, 0, 0, 1)\n"); } +void MatrixTest::configuration() { + Matrix4 m( + 3.0f, 5.0f, 8.0f, 4.0f, + 4.0f, 4.0f, 7.0f, 3.125f, + 7.0f, -1.0f, 8.0f, 0.0f, + 9.0f, 4.0f, 5.0f, 9.55f + ); + string value("3 4 7 9 5 4 -1 4 8 7 8 5 4 3.125 0 9.55"); + CORRADE_COMPARE(ConfigurationValue::toString(m), value); + CORRADE_COMPARE(ConfigurationValue::fromString(value), m); +} + }}} diff --git a/src/Math/Test/MatrixTest.h b/src/Math/Test/MatrixTest.h index 704c95ff3..bb4eab650 100644 --- a/src/Math/Test/MatrixTest.h +++ b/src/Math/Test/MatrixTest.h @@ -38,6 +38,7 @@ class MatrixTest: public Corrade::TestSuite::Tester { void inverted(); void debug(); + void configuration(); }; }}} diff --git a/src/Math/Test/Vector2Test.cpp b/src/Math/Test/Vector2Test.cpp index a3a6e9753..a60a253d7 100644 --- a/src/Math/Test/Vector2Test.cpp +++ b/src/Math/Test/Vector2Test.cpp @@ -32,7 +32,8 @@ Vector2Test::Vector2Test() { addTests(&Vector2Test::construct, &Vector2Test::axes, &Vector2Test::scales, - &Vector2Test::debug); + &Vector2Test::debug, + &Vector2Test::configuration); } void Vector2Test::construct() { @@ -55,4 +56,11 @@ void Vector2Test::debug() { CORRADE_COMPARE(o.str(), "Vector(0.5, 15)\n"); } +void Vector2Test::configuration() { + Vector2 vec(3.125f, 9.0f); + string value("3.125 9"); + CORRADE_COMPARE(ConfigurationValue::toString(vec), value); + CORRADE_COMPARE(ConfigurationValue::fromString(value), vec); +} + }}} diff --git a/src/Math/Test/Vector2Test.h b/src/Math/Test/Vector2Test.h index 128f271be..48bcc1b9f 100644 --- a/src/Math/Test/Vector2Test.h +++ b/src/Math/Test/Vector2Test.h @@ -26,7 +26,9 @@ class Vector2Test: public Corrade::TestSuite::Tester { void construct(); void axes(); void scales(); + void debug(); + void configuration(); }; }}} diff --git a/src/Math/Test/Vector3Test.cpp b/src/Math/Test/Vector3Test.cpp index 1ea4ad574..710c60cd0 100644 --- a/src/Math/Test/Vector3Test.cpp +++ b/src/Math/Test/Vector3Test.cpp @@ -35,7 +35,8 @@ Vector3Test::Vector3Test() { &Vector3Test::axes, &Vector3Test::scales, &Vector3Test::twoComponent, - &Vector3Test::debug); + &Vector3Test::debug, + &Vector3Test::configuration); } void Vector3Test::construct() { @@ -72,4 +73,11 @@ void Vector3Test::debug() { CORRADE_COMPARE(o.str(), "Vector(0.5, 15, 1)\n"); } +void Vector3Test::configuration() { + Vector3 vec(3.0f, 3.125f, 9.55f); + string value("3 3.125 9.55"); + CORRADE_COMPARE(ConfigurationValue::toString(vec), value); + CORRADE_COMPARE(ConfigurationValue::fromString(value), vec); +} + }}} diff --git a/src/Math/Test/Vector3Test.h b/src/Math/Test/Vector3Test.h index 247c63e0d..1542c6a06 100644 --- a/src/Math/Test/Vector3Test.h +++ b/src/Math/Test/Vector3Test.h @@ -30,6 +30,7 @@ class Vector3Test: public Corrade::TestSuite::Tester { void twoComponent(); void debug(); + void configuration(); }; }}} diff --git a/src/Math/Test/Vector4Test.cpp b/src/Math/Test/Vector4Test.cpp index 57a0b9b7d..b8765b65b 100644 --- a/src/Math/Test/Vector4Test.cpp +++ b/src/Math/Test/Vector4Test.cpp @@ -34,7 +34,8 @@ Vector4Test::Vector4Test() { addTests(&Vector4Test::construct, &Vector4Test::threeComponent, &Vector4Test::twoComponent, - &Vector4Test::debug); + &Vector4Test::debug, + &Vector4Test::configuration); } void Vector4Test::construct() { @@ -57,4 +58,11 @@ void Vector4Test::debug() { CORRADE_COMPARE(o.str(), "Vector(0.5, 15, 1, 1)\n"); } +void Vector4Test::configuration() { + Vector4 vec(3.0f, 3.125f, 9.0f, 9.55f); + string value("3 3.125 9 9.55"); + CORRADE_COMPARE(ConfigurationValue::toString(vec), value); + CORRADE_COMPARE(ConfigurationValue::fromString(value), vec); +} + }}} diff --git a/src/Math/Test/Vector4Test.h b/src/Math/Test/Vector4Test.h index d31df492a..e06ce248a 100644 --- a/src/Math/Test/Vector4Test.h +++ b/src/Math/Test/Vector4Test.h @@ -28,6 +28,7 @@ class Vector4Test: public Corrade::TestSuite::Tester { void twoComponent(); void debug(); + void configuration(); }; }}} diff --git a/src/Math/Test/VectorTest.cpp b/src/Math/Test/VectorTest.cpp index 93f14bef3..cbafca1c9 100644 --- a/src/Math/Test/VectorTest.cpp +++ b/src/Math/Test/VectorTest.cpp @@ -49,7 +49,8 @@ VectorTest::VectorTest() { &VectorTest::max, &VectorTest::angle, &VectorTest::negative, - &VectorTest::debug); + &VectorTest::debug, + &VectorTest::configuration); } void VectorTest::construct() { @@ -194,4 +195,11 @@ void VectorTest::debug() { CORRADE_COMPARE(o.str(), "a Vector(0, 0, 0, 0) b Vector(0, 0, 0, 0)\n"); } +void VectorTest::configuration() { + Vector4 vec(3.0f, 3.125f, 9.0f, 9.55f); + string value("3 3.125 9 9.55"); + CORRADE_COMPARE(ConfigurationValue::toString(vec), value); + CORRADE_COMPARE(ConfigurationValue::fromString(value), vec); +} + }}} diff --git a/src/Math/Test/VectorTest.h b/src/Math/Test/VectorTest.h index 75a9d3cc7..cde0cafa9 100644 --- a/src/Math/Test/VectorTest.h +++ b/src/Math/Test/VectorTest.h @@ -42,6 +42,7 @@ class VectorTest: public Corrade::TestSuite::Tester { void negative(); void debug(); + void configuration(); }; }}} diff --git a/src/Math/Vector.h b/src/Math/Vector.h index eede07b42..c6344ac0b 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "MathTypeTraits.h" @@ -48,8 +49,12 @@ namespace Implementation { } #endif -/** @brief %Vector */ -/** @todo Constexprize all for loops */ +/** +@brief %Vector + +@configurationvalueref{Magnum::Math::Vector} +@todo Constexprize all for loops +*/ template class Vector { static_assert(size != 0, "Vector cannot have zero elements"); @@ -527,4 +532,37 @@ template Corrade::Utility::Debug operator<<(Corrade::Utili }} +namespace Corrade { namespace Utility { + +/** @configurationvalue{Magnum::Math::Vector} */ +template struct ConfigurationValue> { + /** @brief Writes elements separated with spaces */ + static std::string toString(const Magnum::Math::Vector& value, int flags = 0) { + std::string output; + + for(size_t pos = 0; pos != size; ++pos) { + if(!output.empty()) output += ' '; + output += ConfigurationValue::toString(value[pos], flags); + } + + return output; + } + + /** @brief Reads elements separated with whitespace */ + static Magnum::Math::Vector fromString(const std::string& stringValue, int flags = 0) { + Magnum::Math::Vector result; + std::istringstream in(stringValue); + + std::string num; + for(size_t pos = 0; pos != size; ++pos) { + in >> num; + result[pos] = ConfigurationValue::fromString(num, flags); + } + + return result; + } +}; + +}} + #endif diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 3dde7c5a1..68d19cb33 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -23,7 +23,11 @@ namespace Magnum { namespace Math { -/** @brief Two-component vector */ +/** +@brief Two-component vector + +@configurationvalueref{Magnum::Math::Vector2} +*/ template class Vector2: public Vector<2, T> { public: /** @@ -95,4 +99,9 @@ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug deb }} +namespace Corrade { namespace Utility { + /** @configurationvalue{Magnum::Math::Vector2} */ + template struct ConfigurationValue>: public ConfigurationValue> {}; +}} + #endif diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index 9beae4e77..212e79ac4 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -23,7 +23,11 @@ namespace Magnum { namespace Math { -/** @brief Three-component vector */ +/** +@brief Three-component vector + +@configurationvalueref{Magnum::Math::Vector3} +*/ template class Vector3: public Vector<3, T> { public: /** @@ -147,4 +151,9 @@ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug deb }} +namespace Corrade { namespace Utility { + /** @configurationvalue{Magnum::Math::Vector3} */ + template struct ConfigurationValue>: public ConfigurationValue> {}; +}} + #endif diff --git a/src/Math/Vector4.h b/src/Math/Vector4.h index a33752b8d..303361921 100644 --- a/src/Math/Vector4.h +++ b/src/Math/Vector4.h @@ -23,7 +23,11 @@ namespace Magnum { namespace Math { -/** @brief Four-component vector */ +/** +@brief Four-component vector + +@configurationvalueref{Magnum::Math::Vector4} +*/ template class Vector4: public Vector<4, T> { public: /** @@ -95,4 +99,9 @@ template Corrade::Utility::Debug operator<<(Corrade::Utility::Debug deb }} +namespace Corrade { namespace Utility { + /** @configurationvalue{Magnum::Math::Vector4} */ + template struct ConfigurationValue>: public ConfigurationValue> {}; +}} + #endif diff --git a/src/Test/ColorTest.cpp b/src/Test/ColorTest.cpp index 3c3334ccd..7813b5f06 100644 --- a/src/Test/ColorTest.cpp +++ b/src/Test/ColorTest.cpp @@ -46,7 +46,8 @@ ColorTest::ColorTest() { &ColorTest::hsvOverflow, &ColorTest::hsvAlpha, - &ColorTest::debug); + &ColorTest::debug, + &ColorTest::configuration); } void ColorTest::fromDenormalized() { @@ -133,4 +134,16 @@ void ColorTest::debug() { CORRADE_COMPARE(o.str(), "Vector(0.5, 0.75, 0, 1)\n"); } +void ColorTest::configuration() { + Color3f color3(0.5f, 0.75f, 1.0f); + string value3("0.5 0.75 1"); + CORRADE_COMPARE(ConfigurationValue::toString(color3), value3); + CORRADE_COMPARE(ConfigurationValue::fromString(value3), color3); + + Color4f color4(0.5f, 0.75f, 0.0f, 1.0f); + string value4("0.5 0.75 0 1"); + CORRADE_COMPARE(ConfigurationValue::toString(color4), value4); + CORRADE_COMPARE(ConfigurationValue::fromString(value4), color4); +} + }} diff --git a/src/Test/ColorTest.h b/src/Test/ColorTest.h index a1ee2a727..47b18101d 100644 --- a/src/Test/ColorTest.h +++ b/src/Test/ColorTest.h @@ -39,6 +39,7 @@ class ColorTest: public Corrade::TestSuite::Tester { void hsvAlpha(); void debug(); + void configuration(); }; }}