From 7a12cbe8b140b19f0b9daf16fd73f36d6a2dc98a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Wed, 3 Apr 2013 22:19:37 +0200 Subject: [PATCH 01/21] DebugTools: use proper sphere parameters in ShapeRenderer. --- src/DebugTools/Implementation/SphereRenderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DebugTools/Implementation/SphereRenderer.cpp b/src/DebugTools/Implementation/SphereRenderer.cpp index 67a367c3a..60b27c880 100644 --- a/src/DebugTools/Implementation/SphereRenderer.cpp +++ b/src/DebugTools/Implementation/SphereRenderer.cpp @@ -41,8 +41,8 @@ template SphereRenderer::SphereRenderer(Phys template void SphereRenderer::draw(Resource& options, const typename DimensionTraits::MatrixType& projectionMatrix) { this->shader->setTransformationProjectionMatrix(projectionMatrix* - DimensionTraits::MatrixType::translation(sphere.position())* - DimensionTraits::MatrixType::scaling(typename DimensionTraits::VectorType(sphere.radius()))) + DimensionTraits::MatrixType::translation(sphere.transformedPosition())* + DimensionTraits::MatrixType::scaling(typename DimensionTraits::VectorType(sphere.transformedRadius()))) ->setColor(options->color()) ->use(); this->mesh->draw(); From daffbdce0cfc251145e8032cd176b0185dbcd5d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 4 Apr 2013 15:18:16 +0200 Subject: [PATCH 02/21] Platform: some const fascism. --- src/Platform/NaClApplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Platform/NaClApplication.cpp b/src/Platform/NaClApplication.cpp index 4b82e6e6f..88d9804b7 100644 --- a/src/Platform/NaClApplication.cpp +++ b/src/Platform/NaClApplication.cpp @@ -45,7 +45,7 @@ void NaClApplication::createContext(NaClApplication::Configuration* configuratio viewportSize = configuration->size(); - std::int32_t attributes[] = { + const std::int32_t attributes[] = { PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24, PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8, From df5630225d4cc57456259a06f8653c85f770b05b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 4 Apr 2013 15:19:45 +0200 Subject: [PATCH 03/21] Platform: minor code cleanup in Sdl2Application. * Explicitly set multisample attributes in all cases (so the attributes are always properly set when creating another context). * Do both assign and test in `if` statement. --- src/Platform/Sdl2Application.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Platform/Sdl2Application.cpp b/src/Platform/Sdl2Application.cpp index d5f9a1850..4040a356e 100644 --- a/src/Platform/Sdl2Application.cpp +++ b/src/Platform/Sdl2Application.cpp @@ -70,15 +70,14 @@ void Sdl2Application::createContext(Configuration* configuration) { SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); /* Multisampling */ - if(configuration->sampleCount()) { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configuration->sampleCount()); - } - - window = SDL_CreateWindow(configuration->title().c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - configuration->size().x(), configuration->size().y(), SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN); - if(!window) { - Error() << "Cannot create window."; + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, configuration->sampleCount() > 1 ? 1 : 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configuration->sampleCount()); + + if(!(window = SDL_CreateWindow(configuration->title().c_str(), + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + configuration->size().x(), configuration->size().y(), + SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN))) { + Error() << "Platform::Sdl2Application::tryCreateContext(): cannot create window"; std::exit(2); } From bda6202d42123e54d4ed13c44ec44e03fec4fa19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 4 Apr 2013 15:23:31 +0200 Subject: [PATCH 04/21] Platform: ability to negotiate context in {Glut,NaCl,Sdl2}Application. --- doc/platform.dox | 24 ++++++++++++++++++++++++ src/Platform/GlutApplication.cpp | 17 +++++++++++++---- src/Platform/GlutApplication.h | 19 ++++++++++++++++--- src/Platform/NaClApplication.cpp | 27 ++++++++++++++++++--------- src/Platform/NaClApplication.h | 3 +++ src/Platform/Sdl2Application.cpp | 27 ++++++++++++++++++++++----- src/Platform/Sdl2Application.h | 5 +++++ 7 files changed, 101 insertions(+), 21 deletions(-) diff --git a/doc/platform.dox b/doc/platform.dox index 3f82bb0db..f6a4b16cd 100644 --- a/doc/platform.dox +++ b/doc/platform.dox @@ -169,5 +169,29 @@ MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication( } @endcode +The configuration passed to constructor and @ref GlutApplication::createContext() "createContext()" +is automaticall deleted afterwards and if the context creation fails, the +application exits. However, it is also possible to negotiate the context using +@ref GlutApplication::tryCreateContext() "tryCreateContext()". The major +difference is that this function returns `false` instead of exiting and it +doesn't delete the configuration afterwards so you can reuse it. You can for +example try enabling MSAA and if the context creation fails, fall back to +no-AA rendering: +@code +MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(argc, argv, nullptr) { + // ... + + auto conf = new Configuration; + conf->setTitle("My Application") + ->setSampleCount(16); + + if(!tryCreateContext(conf)) + createContext(conf->setSampleCount(0)); + else delete conf; + + // ... +} +@endcode + */ }} diff --git a/src/Platform/GlutApplication.cpp b/src/Platform/GlutApplication.cpp index 38741a3fb..705264312 100644 --- a/src/Platform/GlutApplication.cpp +++ b/src/Platform/GlutApplication.cpp @@ -47,12 +47,20 @@ void GlutApplication::initialize(int& argc, char** argv) { /* Init GLUT */ glutInit(&argc, argv); + glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION); } void GlutApplication::createContext(Configuration* configuration) { - CORRADE_ASSERT(!c, "GlutApplication::createContext(): context already created", ); + if(!tryCreateContext(configuration)) { + Error() << "Platform::GlutApplication::createContext(): cannot create context"; + delete configuration; + std::exit(1); - glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION); + } else delete configuration; +} + +bool GlutApplication::tryCreateContext(Configuration* configuration) { + CORRADE_ASSERT(!c, "Platform::GlutApplication::tryCreateContext(): context already created", false); unsigned int flags = GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL; @@ -61,7 +69,8 @@ void GlutApplication::createContext(Configuration* configuration) { glutInitDisplayMode(flags); glutInitWindowSize(configuration->size().x(), configuration->size().y()); - glutCreateWindow(configuration->title().c_str()); + if(!glutCreateWindow(configuration->title().c_str())) + return false; glutReshapeFunc(staticViewportEvent); glutSpecialFunc(staticKeyEvent); glutMouseFunc(staticMouseEvent); @@ -71,7 +80,7 @@ void GlutApplication::createContext(Configuration* configuration) { ExtensionWrangler::initialize(); c = new Context; - delete configuration; + return true; } GlutApplication::~GlutApplication() { diff --git a/src/Platform/GlutApplication.h b/src/Platform/GlutApplication.h index ce141930b..4987ccf60 100644 --- a/src/Platform/GlutApplication.h +++ b/src/Platform/GlutApplication.h @@ -81,7 +81,8 @@ class GlutApplication { * @param arguments Application arguments * * Creates application with default configuration. See Configuration - * for more information. + * for more information. The program exits if the context cannot be + * created, see tryCreateContext() for an alternative. */ explicit GlutApplication(const Arguments& arguments); @@ -92,7 +93,8 @@ class GlutApplication { * * The @p configuration is deleted afterwards. If `nullptr` is passed * as @p configuration, the context is not created and must be created - * with createContext(). + * with createContext(). The program exits if the context cannot be + * created, see tryCreateContext() for an alternative. */ explicit GlutApplication(const Arguments& arguments, Configuration* configuration); @@ -112,10 +114,21 @@ class GlutApplication { * @brief Create context with given configuration * * The @p configuration is deleted afterwards. Must be called if and - * only if the context wasn't created by the constructor itself. + * only if the context wasn't created by the constructor itself. The + * program exits if the context cannot be created, see tryCreateContext() + * for an alternative. */ void createContext(Configuration* configuration); + /** + * @brief Try to create context with given configuration + * + * Unlike createContext() the @p configuration is *not* deleted + * afterwards. Returns `false` if the context cannot be created, `true` + * otherwise. + */ + bool tryCreateContext(Configuration* configuration); + /** @{ @name Drawing functions */ /** diff --git a/src/Platform/NaClApplication.cpp b/src/Platform/NaClApplication.cpp index 88d9804b7..504d6d750 100644 --- a/src/Platform/NaClApplication.cpp +++ b/src/Platform/NaClApplication.cpp @@ -36,12 +36,21 @@ NaClApplication::NaClApplication(const Arguments& arguments): Instance(arguments createContext(new Configuration); } -NaClApplication::NaClApplication(const Arguments& arguments, Configuration* configuration): Instance(arguments), Graphics3DClient(this), MouseLock(this), c(nullptr) { +NaClApplication::NaClApplication(const Arguments& arguments, Configuration* configuration): Instance(arguments), Graphics3DClient(this), MouseLock(this), graphics(nullptr), fullscreen(nullptr), c(nullptr) { if(configuration) createContext(configuration); } -void NaClApplication::createContext(NaClApplication::Configuration* configuration) { - CORRADE_ASSERT(!c, "NaClApplication::createContext(): context already created", ); +void NaClApplication::createContext(Configuration* configuration) { + if(!tryCreateContext(configuration)) { + Error() << "Platform::NaClApplication::createContext(): cannot create context"; + delete configuration; + std::exit(1); + + } else delete configuration; +} + +bool NaClApplication::tryCreateContext(Configuration* configuration) { + CORRADE_ASSERT(!c, "Platform::NaClApplication::tryCreateContext(): context already created", false); viewportSize = configuration->size(); @@ -58,11 +67,12 @@ void NaClApplication::createContext(NaClApplication::Configuration* configuratio graphics = new pp::Graphics3D(this, attributes); if(graphics->is_null()) { - Error() << "Platform::NaClApplication::NaClApplication(): cannot create graphics"; - std::exit(1); + delete graphics; + graphics = nullptr; + return false; } if(!BindGraphics(*graphics)) { - Error() << "Platform::NaClApplication::NaClApplication(): cannot bind graphics"; + Error() << "Platform::NaClApplication::tryCreateContext(): cannot bind graphics"; std::exit(1); } @@ -70,8 +80,6 @@ void NaClApplication::createContext(NaClApplication::Configuration* configuratio glSetCurrentContextPPAPI(graphics->pp_resource()); - c = new Context; - /* Enable input handling for mouse and keyboard */ RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE|PP_INPUTEVENT_CLASS_WHEEL); RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); @@ -79,7 +87,8 @@ void NaClApplication::createContext(NaClApplication::Configuration* configuratio /* Make sure viewportEvent() is called for first time */ flags |= Flag::ViewportUpdated; - delete configuration; + c = new Context; + return true; } NaClApplication::~NaClApplication() { diff --git a/src/Platform/NaClApplication.h b/src/Platform/NaClApplication.h index 46419c989..ac7e119f2 100644 --- a/src/Platform/NaClApplication.h +++ b/src/Platform/NaClApplication.h @@ -121,6 +121,9 @@ class NaClApplication: public pp::Instance, public pp::Graphics3DClient, public /** @copydoc GlutApplication::createContext() */ void createContext(Configuration* configuration); + /** @copydoc GlutApplication::tryCreateContext() */ + bool tryCreateContext(Configuration* configuration); + /** @{ @name Drawing functions */ /** @copydoc GlutApplication::viewportEvent() */ diff --git a/src/Platform/Sdl2Application.cpp b/src/Platform/Sdl2Application.cpp index 4040a356e..89c0cf290 100644 --- a/src/Platform/Sdl2Application.cpp +++ b/src/Platform/Sdl2Application.cpp @@ -50,20 +50,33 @@ Sdl2Application::InputEvent::Modifiers fixedModifiers(Uint16 mod) { } Sdl2Application::Sdl2Application(const Arguments&): context(nullptr), flags(Flag::Redraw) { + initialize(); createContext(new Configuration); } Sdl2Application::Sdl2Application(const Arguments&, Configuration* configuration): context(nullptr), flags(Flag::Redraw) { + initialize(); if(configuration) createContext(configuration); } -void Sdl2Application::createContext(Configuration* configuration) { - CORRADE_ASSERT(!context, "Sdl2Application::createContext(): context already created", ); - +void Sdl2Application::initialize() { if(SDL_Init(SDL_INIT_VIDEO) < 0) { Error() << "Cannot initialize SDL."; std::exit(1); } +} + +void Sdl2Application::createContext(Configuration* configuration) { + if(!tryCreateContext(configuration)) { + Error() << "Platform::Sdl2Application::createContext(): cannot create context:" << SDL_GetError(); + delete configuration; + std::exit(1); + + } else delete configuration; +} + +bool Sdl2Application::tryCreateContext(Configuration* configuration) { + CORRADE_ASSERT(!context, "Platform::Sdl2Application::tryCreateContext(): context already created", false); /* Enable double buffering and 24bt depth buffer */ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -81,7 +94,11 @@ void Sdl2Application::createContext(Configuration* configuration) { std::exit(2); } - context = SDL_GL_CreateContext(window); + if(!(context = SDL_GL_CreateContext(window))) { + SDL_DestroyWindow(window); + window = nullptr; + return false; + } /* This must be enabled, otherwise (on my NVidia) it crashes when creating VAO. WTF. */ @@ -96,7 +113,7 @@ void Sdl2Application::createContext(Configuration* configuration) { SDL_PushEvent(sizeEvent); c = new Context; - delete configuration; + return true; } Sdl2Application::~Sdl2Application() { diff --git a/src/Platform/Sdl2Application.h b/src/Platform/Sdl2Application.h index fb9a5f0e7..ed901ec56 100644 --- a/src/Platform/Sdl2Application.h +++ b/src/Platform/Sdl2Application.h @@ -95,6 +95,9 @@ class Sdl2Application { /** @copydoc GlutApplication::createContext() */ void createContext(Configuration* configuration); + /** @copydoc GlutApplication::tryCreateContext() */ + bool tryCreateContext(Configuration* configuration); + /** @{ @name Drawing functions */ /** @copydoc GlutApplication::viewportEvent() */ @@ -167,6 +170,8 @@ class Sdl2Application { typedef Corrade::Containers::EnumSet Flags; CORRADE_ENUMSET_FRIEND_OPERATORS(Flags) + void initialize(); + SDL_Window* window; SDL_GLContext context; From b0883f8d6ba769ff6bb7549fecc7317ec6b9cf84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 4 Apr 2013 15:42:33 +0200 Subject: [PATCH 05/21] Doc++ --- src/Math/Functions.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Math/Functions.h b/src/Math/Functions.h index 42ab8991d..f5af1e56a 100644 --- a/src/Math/Functions.h +++ b/src/Math/Functions.h @@ -164,8 +164,7 @@ template Vector max(const Vector& a /** @brief Sign -Returns `1.0` if @f$ x > 0 @f$, `0.0` if @f$ @p x = 0 @f$ and `-1.0` if -@f$ x < 0 @f$. +Returns `1` if @p x > 0, `0` if @p x = 0 and `-1` if @p x < 0. */ #ifdef DOXYGEN_GENERATING_OUTPUT template inline T sign(const T scalar); From 78ab75c72e5fc2e2b981c94da62dc195bf15b76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 4 Apr 2013 15:44:05 +0200 Subject: [PATCH 06/21] Explicitly mention supported platforms in README and documentation. --- README.md | 15 ++++++++++++--- doc/mainpage.dox | 14 +++++++++++--- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fdb1f940f..b74a24b74 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Magnum is 2D/3D graphics engine written in C++11 and OpenGL 3 Core Profile. +Magnum is 2D/3D graphics engine written in C++11 and modern OpenGL. DESIGN GOALS ============ @@ -34,6 +34,17 @@ DESIGN GOALS done on top of pre-made skeleton classes, support for file formats is done using plugins and platform support is done by writing simple wrapper class. +SUPPORTED PLATFORMS +=================== + +* **OpenGL** 2.1 through 4.3, core profile functionality and modern + extensions +* **OpenGL ES** 2.0, 3.0 and extensions to match desktop OpenGL functionality +* **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through + GLUT or SDL2 toolkit) +* **Windows** (through GLUT or SDL2 toolkit) +* **Google Chrome Native Client** (natively using PPAPI) + FEATURES ======== @@ -46,8 +57,6 @@ FEATURES * Extensible scene graph which can be modified for each specific usage. * Plugin-based data exchange framework, tools for manipulating meshes, textures and images. -* Integration with various windowing toolkits and also ability to create - windowless contexts. * Pre-made shaders, primitives and other tools for easy prototyping and debugging. diff --git a/doc/mainpage.dox b/doc/mainpage.dox index cc5e6df15..acc1cec27 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -25,7 +25,7 @@ namespace Magnum { /** @mainpage -%Magnum is 2D/3D graphics engine written in C++11 and OpenGL 3 Core Profile. +%Magnum is 2D/3D graphics engine written in C++11 and modern OpenGL. @section mainpage-design-goals Design goals @@ -60,6 +60,16 @@ namespace Magnum { done on top of pre-made skeleton classes, support for file formats is done using plugins and platform support is done by writing simple wrapper class. +@section mainpage-platforms Supported platforms + +- **OpenGL** 2.1 through 4.3, core profile functionality and modern + extensions +- **OpenGL ES** 2.0, 3.0 and extensions to match desktop OpenGL functionality +- **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through + GLUT or SDL2 toolkit) +- **Windows** (through GLUT or SDL2 toolkit) +- **Google Chrome Native Client** (natively using PPAPI) + @section mainpage-features Features - Vector and matrix library with implementation of complex numbers, @@ -69,8 +79,6 @@ namespace Magnum { - Extensible scene graph which can be modified for each specific usage. - Plugin-based data exchange framework, tools for manipulating meshes, textures and images. -- Integration with various windowing toolkits and also ability to create - windowless contexts. Ported to OpenGL ES and various platforms. - Pre-made shaders, primitives and other tools for easy prototyping and debugging. From 5c89c89ff8295f347425d12d0283bd4f806d2c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 4 Apr 2013 16:22:04 +0200 Subject: [PATCH 07/21] Platform: added window flags to Sdl2Application. Making resizable window the default to be consistent with GLUT and others. --- src/Platform/Sdl2Application.cpp | 8 +++++-- src/Platform/Sdl2Application.h | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/Platform/Sdl2Application.cpp b/src/Platform/Sdl2Application.cpp index 89c0cf290..d5e5b3855 100644 --- a/src/Platform/Sdl2Application.cpp +++ b/src/Platform/Sdl2Application.cpp @@ -86,10 +86,14 @@ bool Sdl2Application::tryCreateContext(Configuration* configuration) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, configuration->sampleCount() > 1 ? 1 : 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, configuration->sampleCount()); + /* Flags: if not hidden, set as shown */ + Uint32 flags(configuration->flags()); + if(!(configuration->flags() & Configuration::Flag::Hidden)) flags |= SDL_WINDOW_SHOWN; + if(!(window = SDL_CreateWindow(configuration->title().c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, configuration->size().x(), configuration->size().y(), - SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN))) { + SDL_WINDOW_OPENGL|flags))) { Error() << "Platform::Sdl2Application::tryCreateContext(): cannot create window"; std::exit(2); } @@ -183,7 +187,7 @@ void Sdl2Application::setMouseLocked(bool enabled) { SDL_SetRelativeMouseMode(enabled ? SDL_TRUE : SDL_FALSE); } -Sdl2Application::Configuration::Configuration(): _title("Magnum SDL2 Application"), _size(800, 600), _sampleCount(0) {} +Sdl2Application::Configuration::Configuration(): _title("Magnum SDL2 Application"), _size(800, 600), _flags(Flag::Resizable), _sampleCount(0) {} Sdl2Application::Configuration::~Configuration() = default; Sdl2Application::InputEvent::Modifiers Sdl2Application::MouseEvent::modifiers() { diff --git a/src/Platform/Sdl2Application.h b/src/Platform/Sdl2Application.h index ed901ec56..5ed06ed7a 100644 --- a/src/Platform/Sdl2Application.h +++ b/src/Platform/Sdl2Application.h @@ -196,6 +196,29 @@ class Sdl2Application::Configuration { Configuration& operator=(Configuration&&) = delete; public: + /** + * @brief Window flag + * + * @see Flags, setFlags() + */ + enum class Flag: Uint32 { + Resizable = SDL_WINDOW_RESIZABLE, /**< Resizable window */ + Fullscreen = SDL_WINDOW_FULLSCREEN, /**< Fullscreen window */ + Hidden = SDL_WINDOW_HIDDEN, /**< Hidden window */ + Maximized = SDL_WINDOW_MAXIMIZED, /**< Maximized window */ + Minimized = SDL_WINDOW_MINIMIZED, /**< Minimized window */ + MouseLocked = SDL_WINDOW_INPUT_GRABBED /**< Window with mouse locked */ + }; + + /** + * @brief Window flags + * + * @see setFlags() + */ + typedef Corrade::Containers::EnumSet Flags; + explicit Configuration(); ~Configuration(); @@ -227,6 +250,20 @@ class Sdl2Application::Configuration { return this; } + /** @brief Window flags */ + inline Flags flags() const { return _flags; } + + /** + * @brief Set window flags + * @return Pointer to self (for method chaining) + * + * Default is @ref Flag "Flag::Resizable". + */ + inline Configuration* setFlags(const Flags flags) { + _flags = flags; + return this; + } + /** @brief Sample count */ inline Int sampleCount() const { return _sampleCount; } @@ -245,9 +282,12 @@ class Sdl2Application::Configuration { private: std::string _title; Vector2i _size; + Flags _flags; Int _sampleCount; }; +CORRADE_ENUMSET_OPERATORS(Sdl2Application::Configuration::Flags) + /** @brief Base for input events From 0cd98456dad98148b761ffc90c2644f203db8373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 4 Apr 2013 21:54:02 +0200 Subject: [PATCH 08/21] Math: Added Vector2::cross(). --- src/Math/Test/Vector2Test.cpp | 13 ++++++++++++- src/Math/Test/Vector3Test.cpp | 6 +++--- src/Math/Vector2.h | 14 ++++++++++++++ src/Math/Vector3.h | 8 ++++---- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/Math/Test/Vector2Test.cpp b/src/Math/Test/Vector2Test.cpp index ec05fab05..24ede0935 100644 --- a/src/Math/Test/Vector2Test.cpp +++ b/src/Math/Test/Vector2Test.cpp @@ -26,7 +26,7 @@ #include #include -#include "Math/Vector2.h" +#include "Math/Vector3.h" struct Vec2 { float x, y; @@ -63,6 +63,7 @@ class Vector2Test: public Corrade::TestSuite::Tester { void convert(); void access(); + void cross(); void axes(); void scales(); @@ -70,6 +71,7 @@ class Vector2Test: public Corrade::TestSuite::Tester { void configuration(); }; +typedef Math::Vector3 Vector3i; typedef Math::Vector2 Vector2; typedef Math::Vector2 Vector2i; @@ -83,6 +85,7 @@ Vector2Test::Vector2Test() { &Vector2Test::convert, &Vector2Test::access, + &Vector2Test::cross, &Vector2Test::axes, &Vector2Test::scales, @@ -162,6 +165,14 @@ void Vector2Test::access() { CORRADE_COMPARE(y, -2.0f); } +void Vector2Test::cross() { + Vector2i a(1, -1); + Vector2i b(4, 3); + + CORRADE_COMPARE(Vector2i::cross(a, b), 7); + CORRADE_COMPARE(Vector3i::cross({a, 0}, {b, 0}), Vector3i(0, 0, Vector2i::cross(a, b))); +} + void Vector2Test::axes() { constexpr Vector2 x = Vector2::xAxis(5.0f); constexpr Vector2 y = Vector2::yAxis(6.0f); diff --git a/src/Math/Test/Vector3Test.cpp b/src/Math/Test/Vector3Test.cpp index 649cd1851..586bc4e9a 100644 --- a/src/Math/Test/Vector3Test.cpp +++ b/src/Math/Test/Vector3Test.cpp @@ -180,10 +180,10 @@ void Vector3Test::access() { } void Vector3Test::cross() { - Vector3 a(1, -1, 1); - Vector3 b(4, 3, 7); + Vector3i a(1, -1, 1); + Vector3i b(4, 3, 7); - CORRADE_COMPARE(Vector3::cross(a, b), Vector3(-10, -3, 7)); + CORRADE_COMPARE(Vector3i::cross(a, b), Vector3i(-10, -3, 7)); } void Vector3Test::axes() { diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index 148174cfb..b19624d6f 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -80,6 +80,20 @@ template class Vector2: public Vector<2, T> { */ inline constexpr static Vector2 yScale(T scale) { return Vector2(T(1), scale); } + /** + * @brief 2D cross product + * + * 2D version of cross product, equivalent to calling Vector3::cross() + * with Z coordinate set to `0` and extracting only Z coordinate from + * the result (X and Y coordinates are always zero). + * @f[ + * \boldsymbol a \times \boldsymbol b = a_xb_y - a_yb_x + * @f] + */ + inline static T cross(const Vector2& a, const Vector2& b) { + return a.x()*b.y() - a.y()*b.x(); + } + /** @copydoc Vector::Vector() */ inline constexpr /*implicit*/ Vector2() {} diff --git a/src/Math/Vector3.h b/src/Math/Vector3.h index cbab75330..933d11591 100644 --- a/src/Math/Vector3.h +++ b/src/Math/Vector3.h @@ -102,12 +102,12 @@ template class Vector3: public Vector<3, T> { * @brief Cross product * * @f[ - * \boldsymbol a \times \boldsymbol b = - * \begin{pmatrix} c_0 \\ c_1 \\ c_2 \end{pmatrix} = - * \begin{pmatrix}a_1b_2 - a_2b_1 \\ a_2b_0 - a_0b_2 \\ a_0b_1 - a_1b_0 \end{pmatrix} + * \boldsymbol a \times \boldsymbol b = + * \begin{pmatrix}a_yb_z - a_zb_y \\ a_zb_y - a_xb_z \\ a_xb_y - a_yb_x \end{pmatrix} * @f] + * @see Vector2::cross() */ - inline constexpr static Vector3 cross(const Vector3& a, const Vector3& b) { + inline static Vector3 cross(const Vector3& a, const Vector3& b) { return swizzle<'y', 'z', 'x'>(a)*swizzle<'z', 'x', 'y'>(b) - swizzle<'z', 'x', 'y'>(a)*swizzle<'y', 'z', 'x'>(b); } From b885a49d8006394d858288ee852083013a6ef77e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 4 Apr 2013 21:57:15 +0200 Subject: [PATCH 09/21] Mention support of both `glibc` and `newlib` NaCl toolchains. --- README.md | 3 ++- doc/mainpage.dox | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b74a24b74..8aa48981c 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,8 @@ SUPPORTED PLATFORMS * **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through GLUT or SDL2 toolkit) * **Windows** (through GLUT or SDL2 toolkit) -* **Google Chrome Native Client** (natively using PPAPI) +* **Google Chrome Native Client** (natively using PPAPI, both `newlib` + and `glibc` toolchains are supported) FEATURES ======== diff --git a/doc/mainpage.dox b/doc/mainpage.dox index acc1cec27..660d85cf6 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -68,7 +68,8 @@ namespace Magnum { - **Linux** and embedded Linux (natively using GLX/EGL and Xlib or through GLUT or SDL2 toolkit) - **Windows** (through GLUT or SDL2 toolkit) -- **Google Chrome Native Client** (natively using PPAPI) +- **Google Chrome Native Client** (natively using PPAPI, both `newlib` + and `glibc` toolchains are supported) @section mainpage-features Features From 8d5f6037c7c327acbce0cee0e5a81a50c6930198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 5 Apr 2013 15:46:48 +0200 Subject: [PATCH 10/21] Doc++ --- src/Timeline.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Timeline.h b/src/Timeline.h index a74efe154..807ce0672 100644 --- a/src/Timeline.h +++ b/src/Timeline.h @@ -57,10 +57,9 @@ performed, after everything is properly initialized. In your draw event implementation don't forget to call nextFrame() after buffer swap. You can use previousFrameDuration() to compute animation speed. -Example usage (in e.g. @ref Platform::GlutApplication "GlutApplication" -subclass): +Example usage: @code -MyApplication::MyApplication(...): Platform::GlutApplication(...) { +MyApplication::MyApplication(const Parameters& parameters): Platform::Application(parameters) { // Initialization ... timeline.setMinimalFrameTime(1/120.0f); // 120 FPS at max From c4073c08745fe16dc7a06d4e25c2b9243a147ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 5 Apr 2013 17:07:25 +0200 Subject: [PATCH 11/21] Primitives: added 2D/3D Line primitive. No shit. This is usable mainly if some common code expects the mesh wrapped in MeshData and thus it is better to just have this tiny class instead of doing it manually. --- src/Primitives/CMakeLists.txt | 2 ++ src/Primitives/Line.cpp | 45 +++++++++++++++++++++++ src/Primitives/Line.h | 67 +++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 src/Primitives/Line.cpp create mode 100644 src/Primitives/Line.h diff --git a/src/Primitives/CMakeLists.txt b/src/Primitives/CMakeLists.txt index 6c44f1c81..9675469aa 100644 --- a/src/Primitives/CMakeLists.txt +++ b/src/Primitives/CMakeLists.txt @@ -29,6 +29,7 @@ set(MagnumPrimitives_SRCS Cube.cpp Cylinder.cpp Icosphere.cpp + Line.cpp Plane.cpp Square.cpp UVSphere.cpp) @@ -40,6 +41,7 @@ set(MagnumPrimitives_HEADERS Cube.h Cylinder.h Icosphere.h + Line.h Plane.h Square.h UVSphere.h diff --git a/src/Primitives/Line.cpp b/src/Primitives/Line.cpp new file mode 100644 index 000000000..53926a9f6 --- /dev/null +++ b/src/Primitives/Line.cpp @@ -0,0 +1,45 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "Line.h" + +#include "Math/Vector3.h" +#include "Trade/MeshData2D.h" +#include "Trade/MeshData3D.h" + +namespace Magnum { namespace Primitives { + +Trade::MeshData2D Line2D::wireframe() { + return Trade::MeshData2D(Mesh::Primitive::Lines, nullptr, {new std::vector{ + {0.0f, 0.0f}, {1.0f, 0.0f} + }}, {}); +} + +Trade::MeshData3D Line3D::wireframe() { + return Trade::MeshData3D(Mesh::Primitive::Lines, nullptr, {new std::vector{ + {0.0f, 0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, + }}, {}, {}); +} + +}} diff --git a/src/Primitives/Line.h b/src/Primitives/Line.h new file mode 100644 index 000000000..59a0d7a6c --- /dev/null +++ b/src/Primitives/Line.h @@ -0,0 +1,67 @@ +#ifndef Magnum_Primitives_Line_h +#define Magnum_Primitives_Line_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +/** @file + * @brief Class Magnum::Primitives::Line2D, Magnum::Primitives::Line3D + */ + +#include "Trade/Trade.h" + +#include "Primitives/magnumPrimitivesVisibility.h" + +namespace Magnum { namespace Primitives { + +/** +@brief 2D line primitive + +Unit-size line in direction of positive X axis. Non-indexed +@ref Mesh::Primitive "Lines". +*/ +class MAGNUM_PRIMITIVES_EXPORT Line2D { + public: + /** @brief Wireframe line */ + static Trade::MeshData2D wireframe(); + + Line2D() = delete; +}; + +/** +@brief 3D line primitive + +Unit-size line in direction of positive X axis. Non-indexed +@ref Mesh::Primitive "Lines". +*/ +class MAGNUM_PRIMITIVES_EXPORT Line3D { + public: + /** @brief Wireframe line */ + static Trade::MeshData3D wireframe(); + + Line3D() = delete; +}; + +}} + +#endif From 45cbf1669f6ec859c2e15504bab5e85079ddd807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 5 Apr 2013 17:19:06 +0200 Subject: [PATCH 12/21] DebugTools: 2D and 3D LineSegment support in ShapeRenderer. --- src/DebugTools/CMakeLists.txt | 1 + .../Implementation/LineSegmentRenderer.cpp | 68 +++++++++++++++++++ .../Implementation/LineSegmentRenderer.h | 47 +++++++++++++ .../LineSegmentRendererTransformation.h | 39 +++++++++++ src/DebugTools/ShapeRenderer.cpp | 8 +++ src/DebugTools/Test/CMakeLists.txt | 1 + .../Test/LineSegmentRendererTest.cpp | 67 ++++++++++++++++++ 7 files changed, 231 insertions(+) create mode 100644 src/DebugTools/Implementation/LineSegmentRenderer.cpp create mode 100644 src/DebugTools/Implementation/LineSegmentRenderer.h create mode 100644 src/DebugTools/Implementation/LineSegmentRendererTransformation.h create mode 100644 src/DebugTools/Test/LineSegmentRendererTest.cpp diff --git a/src/DebugTools/CMakeLists.txt b/src/DebugTools/CMakeLists.txt index a80d6e435..bbad443ce 100644 --- a/src/DebugTools/CMakeLists.txt +++ b/src/DebugTools/CMakeLists.txt @@ -33,6 +33,7 @@ set(MagnumDebugTools_SRCS Implementation/AbstractShapeRenderer.cpp Implementation/AxisAlignedBoxRenderer.cpp Implementation/BoxRenderer.cpp + Implementation/LineSegmentRenderer.cpp Implementation/PointRenderer.cpp Implementation/SphereRenderer.cpp) diff --git a/src/DebugTools/Implementation/LineSegmentRenderer.cpp b/src/DebugTools/Implementation/LineSegmentRenderer.cpp new file mode 100644 index 000000000..c9a0240c8 --- /dev/null +++ b/src/DebugTools/Implementation/LineSegmentRenderer.cpp @@ -0,0 +1,68 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "LineSegmentRenderer.h" + +#include "Mesh.h" +#include "DebugTools/ShapeRenderer.h" +#include "Physics/Line.h" +#include "Primitives/Line.h" +#include "Shaders/FlatShader.h" +#include "Trade/MeshData2D.h" +#include "Trade/MeshData3D.h" + +#include "DebugTools/Implementation/LineSegmentRendererTransformation.h" + +namespace Magnum { namespace DebugTools { namespace Implementation { + +namespace { + template ResourceKey meshKey(); + template<> inline ResourceKey meshKey<2>() { return ResourceKey("line2d"); } + template<> inline ResourceKey meshKey<3>() { return ResourceKey("line3d"); } + + template ResourceKey vertexBufferKey(); + template<> inline ResourceKey vertexBufferKey<2>() { return ResourceKey("line2d-vertices"); } + template<> inline ResourceKey vertexBufferKey<3>() { return ResourceKey("line3d-vertices"); } + + template typename MeshData::Type meshData(); + template<> inline Trade::MeshData2D meshData<2>() { return Primitives::Line2D::wireframe(); } + template<> inline Trade::MeshData3D meshData<3>() { return Primitives::Line3D::wireframe(); } +} + +template LineSegmentRenderer::LineSegmentRenderer(Physics::Line& line): AbstractShapeRenderer(meshKey(), vertexBufferKey(), {}), line(line) { + if(!this->mesh) this->createResources(meshData()); +} + +template void LineSegmentRenderer::draw(Resource& options, const typename DimensionTraits::MatrixType& projectionMatrix) { + this->shader->setTransformationProjectionMatrix(projectionMatrix* + Implementation::lineSegmentRendererTransformation(line.transformedA(), line.transformedB())) + ->setColor(options->color()) + ->use(); + this->mesh->draw(); +} + +template class LineSegmentRenderer<2>; +template class LineSegmentRenderer<3>; + +}}} diff --git a/src/DebugTools/Implementation/LineSegmentRenderer.h b/src/DebugTools/Implementation/LineSegmentRenderer.h new file mode 100644 index 000000000..a67208825 --- /dev/null +++ b/src/DebugTools/Implementation/LineSegmentRenderer.h @@ -0,0 +1,47 @@ +#ifndef Magnum_DebugTools_Implementation_LineSegmentRenderer_h +#define Magnum_DebugTools_Implementation_LineSegmentRenderer_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "AbstractShapeRenderer.h" + +#include "Physics/Physics.h" + +#include "corradeCompatibility.h" + +namespace Magnum { namespace DebugTools { namespace Implementation { + +template class LineSegmentRenderer: public AbstractShapeRenderer { + public: + LineSegmentRenderer(Physics::Line& line); + + void draw(Resource& options, const typename DimensionTraits::MatrixType& projectionMatrix) override; + + private: + Physics::Line& line; +}; + +}}} + +#endif diff --git a/src/DebugTools/Implementation/LineSegmentRendererTransformation.h b/src/DebugTools/Implementation/LineSegmentRendererTransformation.h new file mode 100644 index 000000000..fc94a1bfe --- /dev/null +++ b/src/DebugTools/Implementation/LineSegmentRendererTransformation.h @@ -0,0 +1,39 @@ +#ifndef Magnum_DebugTools_Implementation_LineSegmentRendererTransformation_h +#define Magnum_DebugTools_Implementation_LineSegmentRendererTransformation_h +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "DimensionTraits.h" + +namespace Magnum { namespace DebugTools { namespace Implementation { + +template typename DimensionTraits::MatrixType lineSegmentRendererTransformation(const typename DimensionTraits::VectorType& a, const typename DimensionTraits::VectorType& b) { + auto transformation = DimensionTraits::MatrixType::translation(a); + transformation.right() = b - a; + return transformation; +} + +}}} + +#endif diff --git a/src/DebugTools/ShapeRenderer.cpp b/src/DebugTools/ShapeRenderer.cpp index 38fbd46ce..060bfffcc 100644 --- a/src/DebugTools/ShapeRenderer.cpp +++ b/src/DebugTools/ShapeRenderer.cpp @@ -29,6 +29,7 @@ #include "Physics/AxisAlignedBox.h" #include "Physics/Box.h" #include "Physics/ObjectShape.h" +#include "Physics/LineSegment.h" #include "Physics/Point.h" #include "Physics/ShapeGroup.h" #include "Physics/Sphere.h" @@ -36,6 +37,7 @@ #include "Implementation/AxisAlignedBoxRenderer.h" #include "Implementation/BoxRenderer.h" +#include "Implementation/LineSegmentRenderer.h" #include "Implementation/PointRenderer.h" #include "Implementation/SphereRenderer.h" @@ -52,6 +54,9 @@ template<> void createDebugMesh(ShapeRenderer<2>* renderer, Physics::AbstractSha case Physics::AbstractShape2D::Type::Box: renderer->renderers.push_back(new Implementation::BoxRenderer<2>(*static_cast(shape))); break; + case Physics::AbstractShape2D::Type::LineSegment: + renderer->renderers.push_back(new Implementation::LineSegmentRenderer<2>(*static_cast(shape))); + break; case Physics::AbstractShape2D::Type::Point: renderer->renderers.push_back(new Implementation::PointRenderer<2>(*static_cast(shape))); break; @@ -76,6 +81,9 @@ template<> void createDebugMesh(ShapeRenderer<3>* renderer, Physics::AbstractSha case Physics::AbstractShape3D::Type::Box: renderer->renderers.push_back(new Implementation::BoxRenderer<3>(*static_cast(shape))); break; + case Physics::AbstractShape3D::Type::LineSegment: + renderer->renderers.push_back(new Implementation::LineSegmentRenderer<3>(*static_cast(shape))); + break; case Physics::AbstractShape3D::Type::Point: renderer->renderers.push_back(new Implementation::PointRenderer<3>(*static_cast(shape))); break; diff --git a/src/DebugTools/Test/CMakeLists.txt b/src/DebugTools/Test/CMakeLists.txt index 00f3ccf65..1e945d0c0 100644 --- a/src/DebugTools/Test/CMakeLists.txt +++ b/src/DebugTools/Test/CMakeLists.txt @@ -23,3 +23,4 @@ # corrade_add_test(DebugToolsForceRendererTest ForceRendererTest.cpp LIBRARIES MagnumMathTestLib) +corrade_add_test(DebugToolsLineSegmentRendererTest LineSegmentRendererTest.cpp LIBRARIES MagnumMathTestLib) diff --git a/src/DebugTools/Test/LineSegmentRendererTest.cpp b/src/DebugTools/Test/LineSegmentRendererTest.cpp new file mode 100644 index 000000000..5e0a056bc --- /dev/null +++ b/src/DebugTools/Test/LineSegmentRendererTest.cpp @@ -0,0 +1,67 @@ +/* + This file is part of Magnum. + + Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include + +#include "Math/Matrix3.h" +#include "Math/Matrix4.h" +#include "Magnum.h" +#include "DebugTools/Implementation/LineSegmentRendererTransformation.h" + +namespace Magnum { namespace DebugTools { namespace Test { + +class LineSegmentRendererTest: public Corrade::TestSuite::Tester { + public: + explicit LineSegmentRendererTest(); + + void line2D(); + void line3D(); +}; + +LineSegmentRendererTest::LineSegmentRendererTest() { + addTests({&LineSegmentRendererTest::line2D, + &LineSegmentRendererTest::line3D}); +} + +void LineSegmentRendererTest::line2D() { + const Vector2 a(-2.0f, 3.0f); + const Vector2 b(3.4f, -1.5f); + const Matrix3 matrix = Implementation::lineSegmentRendererTransformation<2>(a, b); + + CORRADE_COMPARE(matrix.transformPoint({0.0f, 0.0f}), a); + CORRADE_COMPARE(matrix.transformPoint({1.0f, 0.0f}), b); +} + +void LineSegmentRendererTest::line3D() { + const Vector3 a(-2.0f, 3.0f, 1.5f); + const Vector3 b(3.4f, -1.5f, 0.5f); + const Matrix4 matrix = Implementation::lineSegmentRendererTransformation<3>(a, b); + + CORRADE_COMPARE(matrix.transformPoint({0.0f, 0.0f, 0.0f}), a); + CORRADE_COMPARE(matrix.transformPoint({1.0f, 0.0f, 0.0f}), b); +} + +}}} + +CORRADE_TEST_MAIN(Magnum::DebugTools::Test::LineSegmentRendererTest) From b7aeccad4cb54b93f4a687c406c708f20e4925d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Fri, 5 Apr 2013 17:28:54 +0200 Subject: [PATCH 13/21] Clang compilation fixes. --- src/Math/Geometry/Rectangle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Math/Geometry/Rectangle.h b/src/Math/Geometry/Rectangle.h index ccf8ac019..6211bd8b7 100644 --- a/src/Math/Geometry/Rectangle.h +++ b/src/Math/Geometry/Rectangle.h @@ -60,7 +60,7 @@ template class Rectangle { * * Construct zero-area rectangle positioned at origin. */ - inline constexpr Rectangle() = default; + inline constexpr Rectangle() {} /** @brief Construct rectangle from two corners */ inline constexpr Rectangle(const Vector2& bottomLeft, const Vector2& topRight): _bottomLeft(bottomLeft), _topRight(topRight) {} From fe0f5dc43809d8e17846cec68dad30277f0a1af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Apr 2013 00:03:29 +0200 Subject: [PATCH 14/21] Use `nullptr` instead of `0`. --- src/Platform/AbstractXApplication.cpp | 4 ++-- src/Platform/GlxContextHandler.cpp | 2 +- src/Platform/WindowlessGlxApplication.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Platform/AbstractXApplication.cpp b/src/Platform/AbstractXApplication.cpp index 153429d13..f7a00bd71 100644 --- a/src/Platform/AbstractXApplication.cpp +++ b/src/Platform/AbstractXApplication.cpp @@ -50,7 +50,7 @@ void AbstractXApplication::createContext(AbstractXApplication::Configuration* co viewportSize = configuration->size(); /* Get default X display */ - display = XOpenDisplay(0); + display = XOpenDisplay(nullptr); /* Get visual ID */ VisualID visualId = contextHandler->getVisualId(display); @@ -74,7 +74,7 @@ void AbstractXApplication::createContext(AbstractXApplication::Configuration* co attr.event_mask = 0; unsigned long mask = CWBackPixel|CWBorderPixel|CWColormap|CWEventMask; window = XCreateWindow(display, root, 20, 20, configuration->size().x(), configuration->size().y(), 0, visInfo->depth, InputOutput, visInfo->visual, mask, &attr); - XSetStandardProperties(display, window, configuration->title().c_str(), 0, None, 0, 0, 0); + XSetStandardProperties(display, window, configuration->title().c_str(), nullptr, None, nullptr, 0, nullptr); XFree(visInfo); /* Be notified about closing the window */ diff --git a/src/Platform/GlxContextHandler.cpp b/src/Platform/GlxContextHandler.cpp index f39cd2db4..9e7506424 100644 --- a/src/Platform/GlxContextHandler.cpp +++ b/src/Platform/GlxContextHandler.cpp @@ -84,7 +84,7 @@ void GlxContextHandler::createContext(Window nativeWindow) { /** @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); + context = glXCreateContextAttribsARB(display, configs[0], nullptr, True, attributes); XFree(configs); if(!context) { Error() << "GlxContextHandler: cannot create context."; diff --git a/src/Platform/WindowlessGlxApplication.cpp b/src/Platform/WindowlessGlxApplication.cpp index 39f934f60..2d7c017b8 100644 --- a/src/Platform/WindowlessGlxApplication.cpp +++ b/src/Platform/WindowlessGlxApplication.cpp @@ -74,7 +74,7 @@ void WindowlessGlxApplication::createContext(Configuration* configuration) { /** @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, contextAttributes); + context = glXCreateContextAttribsARB(display, configs[0], nullptr, True, contextAttributes); if(!context) { Error() << "WindowlessGlxApplication: cannot create context."; std::exit(1); From bba3755da13497ed714bb2ce2720d019b151d2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Apr 2013 00:44:44 +0200 Subject: [PATCH 15/21] GCC 4.8 compilation fixes. --- src/Math/Algorithms/Svd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Math/Algorithms/Svd.h b/src/Math/Algorithms/Svd.h index 51ef991ae..8249e0bbb 100644 --- a/src/Math/Algorithms/Svd.h +++ b/src/Math/Algorithms/Svd.h @@ -49,7 +49,7 @@ template T pythagoras(T a, T b) { return absb*std::sqrt(T(1) + Math::pow<2>(absa/absb)); } -template T smallestDelta(); +template constexpr T smallestDelta(); template<> inline constexpr Float smallestDelta() { return 1.0e-32; } #ifndef MAGNUM_TARGET_GLES template<> inline constexpr Double smallestDelta() { return 1.0e-64; } From 82ca09a4ed4ab242676596a4da323385942b82ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Apr 2013 18:53:19 +0200 Subject: [PATCH 16/21] Minor documentation fixes. It's not needed to have empty `()` after class name in this type of expressions: (new Object()) ->setFoo(a) ->setBar(b); --- doc/debug-tools.dox | 2 +- doc/platform.dox | 4 ++-- src/DebugTools/ForceRenderer.h | 5 ++--- src/DebugTools/ObjectRenderer.h | 4 ++-- src/DebugTools/ShapeRenderer.h | 4 ++-- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/doc/debug-tools.dox b/doc/debug-tools.dox index 916df7408..afbed3e3e 100644 --- a/doc/debug-tools.dox +++ b/doc/debug-tools.dox @@ -63,7 +63,7 @@ SceneGraph::DrawableGroup3D debugDrawables; // Create renderer options which will be referenced later by "my" resource key DebugTools::ResourceManager::instance()->set("my", - (new DebugTools::ObjectRendererOptions())->setSize(0.3f)); + (new DebugTools::ObjectRendererOptions)->setSize(0.3f)); // Create debug renderer for given object, use "my" options for it. The // renderer is automatically added to the object features and also to diff --git a/doc/platform.dox b/doc/platform.dox index f6a4b16cd..525355321 100644 --- a/doc/platform.dox +++ b/doc/platform.dox @@ -147,7 +147,7 @@ window size 800x600 pixels). If you want something else, you can pass constructor. Using method chaining it can be done conveniently like this: @code MyApplication::MyApplication(int& argc, char** argv): - Platform::GlutApplication(argc, argv, (new Configuration()) + Platform::GlutApplication(argc, argv, (new Configuration) ->setTitle("My Application")->setSize({800, 600}) { // ... } @@ -161,7 +161,7 @@ instead of Configuration instance and then specify it later with MyApplication::MyApplication(int& argc, char** argv): Platform::GlutApplication(argc, argv, nullptr) { // ... - createContext((new Configuration()) + createContext((new Configuration) ->setTitle("My Application") ->setSize(size)); diff --git a/src/DebugTools/ForceRenderer.h b/src/DebugTools/ForceRenderer.h index d9494a212..79e521ab4 100644 --- a/src/DebugTools/ForceRenderer.h +++ b/src/DebugTools/ForceRenderer.h @@ -90,9 +90,8 @@ See @ref debug-tools-renderers for more information. Example code: @code // Create some options -DebugTools::ResourceManager::instance()->set("my", (new DebugTools::ForceRendererOptions() - ->setScale(5.0f) - ->setColor(Color3<>::fromHSV(120.0_degf, 1.0f, 0.7f))); +DebugTools::ResourceManager::instance()->set("my", (new DebugTools::ForceRendererOptions) + ->setScale(5.0f)->setColor(Color3<>::fromHSV(120.0_degf, 1.0f, 0.7f))); // Create debug renderer for given object, use "my" options for it Object3D* object; diff --git a/src/DebugTools/ObjectRenderer.h b/src/DebugTools/ObjectRenderer.h index e1c86cab8..cbafafd98 100644 --- a/src/DebugTools/ObjectRenderer.h +++ b/src/DebugTools/ObjectRenderer.h @@ -74,8 +74,8 @@ Visualizes object position, rotation and scale using colored axes. See Example code: @code // Create some options -DebugTools::ResourceManager::instance()->set("my", - (new DebugTools::ObjectRendererOptions())->setSize(0.3f)); +DebugTools::ResourceManager::instance()->set("my", (new DebugTools::ObjectRendererOptions) + ->setSize(0.3f)); // Create debug renderer for given object, use "my" options for it Object3D* object; diff --git a/src/DebugTools/ShapeRenderer.h b/src/DebugTools/ShapeRenderer.h index 5a73819d3..e1af8bf93 100644 --- a/src/DebugTools/ShapeRenderer.h +++ b/src/DebugTools/ShapeRenderer.h @@ -104,8 +104,8 @@ Visualizes collision shapes using wireframe primitives. See Example code: @code // Create some options -DebugTools::ResourceManager::instance()->set("red", - (new DebugTools::ShapeRendererOptions())->setColor({1.0f, 0.0f, 0.0f})); +DebugTools::ResourceManager::instance()->set("red", (new DebugTools::ShapeRendererOptions) + ->setColor({1.0f, 0.0f, 0.0f})); // Create debug renderer for given shape, use "red" options for it Physics::ObjectShape2D* shape; From e69693e87feb94a7a27c1eea0f5e67a2d96ae601 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Apr 2013 18:54:53 +0200 Subject: [PATCH 17/21] Use `std::` prefix everywhere. --- src/Platform/AbstractXApplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Platform/AbstractXApplication.cpp b/src/Platform/AbstractXApplication.cpp index f7a00bd71..80e6e7215 100644 --- a/src/Platform/AbstractXApplication.cpp +++ b/src/Platform/AbstractXApplication.cpp @@ -62,7 +62,7 @@ void AbstractXApplication::createContext(AbstractXApplication::Configuration* co visInfo = XGetVisualInfo(display, VisualIDMask, &visTemplate, &visualCount); if(!visInfo) { Error() << "Cannot get X visual"; - ::exit(1); + std::exit(1); } /* Create X Window */ From d85c15bca90935e53f8a8f62d35d561a0a1a3933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Apr 2013 18:56:19 +0200 Subject: [PATCH 18/21] SceneGraph: this was fixed in 59a3a7029df0524d93fe5015113c668356da93ed. --- src/SceneGraph/Object.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/SceneGraph/Object.hpp b/src/SceneGraph/Object.hpp index 1a7a48d5a..5855813ef 100644 --- a/src/SceneGraph/Object.hpp +++ b/src/SceneGraph/Object.hpp @@ -180,8 +180,6 @@ template std::vector Ob /* Remember object count for later */ std::size_t objectCount = objects.size(); - /** @bug What if there is one objects twice in the list */ - /* Mark all original objects as joints and create initial list of joints from them */ for(std::size_t i = 0; i != objects.size(); ++i) { From 9ecb8b5b8d29b400b39c371f1631f5e75108b2eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Apr 2013 19:21:01 +0200 Subject: [PATCH 19/21] SceneGraph: fully test also Object::setClean() for list of objects. The test fails (it doesn't clean parent objects). --- src/SceneGraph/Test/ObjectTest.cpp | 62 ++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/SceneGraph/Test/ObjectTest.cpp b/src/SceneGraph/Test/ObjectTest.cpp index 51f1187f2..a54acdd43 100644 --- a/src/SceneGraph/Test/ObjectTest.cpp +++ b/src/SceneGraph/Test/ObjectTest.cpp @@ -42,7 +42,8 @@ class ObjectTest: public Corrade::TestSuite::Tester { void transformationsOrphan(); void transformationsDuplicate(); void setClean(); - void bulkSetClean(); + void setCleanListHierarchy(); + void setCleanListBulk(); }; typedef SceneGraph::Object> Object3D; @@ -71,7 +72,8 @@ ObjectTest::ObjectTest() { &ObjectTest::transformationsOrphan, &ObjectTest::transformationsDuplicate, &ObjectTest::setClean, - &ObjectTest::bulkSetClean}); + &ObjectTest::setCleanListHierarchy, + &ObjectTest::setCleanListBulk}); } void ObjectTest::parenting() { @@ -305,10 +307,13 @@ void ObjectTest::setClean() { /* If the object itself is already clean, it shouldn't clean it again */ childOne->cleanedAbsoluteTransformation = Matrix4(Matrix4::Zero); + CORRADE_VERIFY(!childOne->isDirty()); childOne->setClean(); CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero)); /* If any object in the hierarchy is already clean, it shouldn't clean it again */ + CORRADE_VERIFY(!childOne->isDirty()); + CORRADE_VERIFY(childTwo->isDirty()); childTwo->setClean(); CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero)); @@ -332,7 +337,58 @@ void ObjectTest::setClean() { CORRADE_VERIFY(childThree->isDirty()); } -void ObjectTest::bulkSetClean() { +void ObjectTest::setCleanListHierarchy() { + Scene3D scene; + + class CachingFeature: public AbstractFeature<3> { + public: + CachingFeature(AbstractObject<3>* object): AbstractFeature<3>(object) { + setCachedTransformations(CachedTransformation::Absolute); + } + + Matrix4 cleanedAbsoluteTransformation; + + void clean(const Matrix4& absoluteTransformation) override { + cleanedAbsoluteTransformation = absoluteTransformation; + } + }; + + CachingObject* childOne = new CachingObject(&scene); + childOne->scale(Vector3(2.0f)); + + CachingObject* childTwo = new CachingObject(childOne); + childTwo->translate(Vector3::xAxis(1.0f)); + CachingFeature* childTwoFeature = new CachingFeature(childTwo); + + CachingObject* childThree = new CachingObject(childTwo); + childThree->rotate(Deg(90.0f), Vector3::yAxis()); + + /* Clean the object and all its dirty parents (but not children) */ + Scene3D::setClean(std::vector{childTwo}); + CORRADE_VERIFY(!scene.isDirty()); + CORRADE_VERIFY(!childOne->isDirty()); + CORRADE_VERIFY(!childTwo->isDirty()); + CORRADE_VERIFY(childThree->isDirty()); + + /* Verify the right matrices were passed */ + CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, childOne->absoluteTransformationMatrix()); + CORRADE_COMPARE(childTwo->cleanedAbsoluteTransformation, childTwo->absoluteTransformationMatrix()); + CORRADE_COMPARE(childTwoFeature->cleanedAbsoluteTransformation, childTwo->absoluteTransformationMatrix()); + + /* If the object itself is already clean, it shouldn't clean it again */ + childOne->cleanedAbsoluteTransformation = Matrix4(Matrix4::Zero); + CORRADE_VERIFY(!childOne->isDirty()); + Scene3D::setClean(std::vector{childOne}); + CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero)); + + /* If any object in the hierarchy is already clean, it shouldn't clean it again */ + CORRADE_VERIFY(!childOne->isDirty()); + childTwo->setDirty(); + Scene3D::setClean(std::vector{childTwo}); + CORRADE_COMPARE(childOne->cleanedAbsoluteTransformation, Matrix4(Matrix4::Zero)); +} + +void ObjectTest::setCleanListBulk() { /* Verify it doesn't crash when passed empty list */ Object3D::setClean(std::vector()); From 218a4c142c84b0d3443619855a00889a3181916b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Apr 2013 19:48:48 +0200 Subject: [PATCH 20/21] SceneGraph: fixed Object::setClean(). Now also all non-clean parent objects are cleaned. --- src/SceneGraph/Object.hpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/SceneGraph/Object.hpp b/src/SceneGraph/Object.hpp index 5855813ef..15b659aab 100644 --- a/src/SceneGraph/Object.hpp +++ b/src/SceneGraph/Object.hpp @@ -321,6 +321,22 @@ template void Object::setClean(std::vector /* No dirty objects left, done */ if(objects.empty()) return; + /* Add non-clean parents to the list. Mark each added object as visited, so + they aren't added more than once */ + for(std::size_t end = objects.size(), i = 0; i != end; ++i) { + Object* o = objects[i]; + o->flags |= Flag::Visited; + + Object* parent = o->parent(); + while(parent && !(parent->flags & Flag::Visited) && parent->isDirty()) { + objects.push_back(parent); + parent = parent->parent(); + } + } + + /* Cleanup all marks */ + for(auto o: objects) o->flags &= ~Flag::Visited; + /* Compute absolute transformations */ Scene* scene = objects[0]->scene(); CORRADE_ASSERT(scene, "Object::setClean(): objects must be part of some scene", ); From 49154f30c446cf5a92b2a85a1536ff8b338a9d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 6 Apr 2013 20:49:31 +0200 Subject: [PATCH 21/21] Math: added Vector2::perpendicular(). Also updated and crosslinked related documentation. --- src/Math/Test/Vector2Test.cpp | 9 +++++++++ src/Math/Vector.h | 7 +++++-- src/Math/Vector2.h | 10 ++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/Math/Test/Vector2Test.cpp b/src/Math/Test/Vector2Test.cpp index 24ede0935..0d8aa7691 100644 --- a/src/Math/Test/Vector2Test.cpp +++ b/src/Math/Test/Vector2Test.cpp @@ -66,6 +66,7 @@ class Vector2Test: public Corrade::TestSuite::Tester { void cross(); void axes(); void scales(); + void perpendicular(); void debug(); void configuration(); @@ -88,6 +89,7 @@ Vector2Test::Vector2Test() { &Vector2Test::cross, &Vector2Test::axes, &Vector2Test::scales, + &Vector2Test::perpendicular, &Vector2Test::debug, &Vector2Test::configuration}); @@ -187,6 +189,13 @@ void Vector2Test::scales() { CORRADE_COMPARE(y, Vector2(1.0f, -0.2f)); } +void Vector2Test::perpendicular() { + const Vector2 a(0.5f, -15.0f); + CORRADE_COMPARE(a.perpendicular(), Vector2(15.0f, 0.5f)); + CORRADE_COMPARE(Vector2::dot(a.perpendicular(), a), 0.0f); + CORRADE_COMPARE(Vector2::xAxis().perpendicular(), Vector2::yAxis()); +} + void Vector2Test::debug() { std::ostringstream o; Debug(&o) << Vector2(0.5f, 15.0f); diff --git a/src/Math/Vector.h b/src/Math/Vector.h index 8d07e9ab5..e49f1700b 100644 --- a/src/Math/Vector.h +++ b/src/Math/Vector.h @@ -84,10 +84,12 @@ template class Vector { /** * @brief Dot product * - * @f[ + * Returns `0` if two vectors are orthogonal, `1` if two *normalized* + * vectors are parallel and `-1` if two *normalized* vectors are + * antiparallel. @f[ * \boldsymbol a \cdot \boldsymbol b = \sum_{i=0}^{n-1} \boldsymbol a_i \boldsymbol b_i * @f] - * @see dot() const + * @see dot() const, operator-(), Vector2::perpendicular() */ inline static T dot(const Vector& a, const Vector& b) { return (a*b).sum(); @@ -270,6 +272,7 @@ template class Vector { * The computation is done in-place. @f[ * \boldsymbol a_i = -\boldsymbol a_i * @f] + * @see Vector2::perpendicular() */ Vector operator-() const { Vector out; diff --git a/src/Math/Vector2.h b/src/Math/Vector2.h index b19624d6f..4e7b17c00 100644 --- a/src/Math/Vector2.h +++ b/src/Math/Vector2.h @@ -123,6 +123,16 @@ template class Vector2: public Vector<2, T> { inline T& y() { return (*this)[1]; } /**< @brief Y component */ inline constexpr T y() const { return (*this)[1]; } /**< @overload */ + /** + * @brief Perpendicular vector + * + * Returns vector rotated 90° counterclockwise. @f[ + * \boldsymbol v_\perp = \begin{pmatrix} -v_y \\ v_x \end{pmatrix} + * @f] + * @see dot(const Vector&, const Vector&), operator-() const + */ + inline Vector2 perpendicular() const { return {-y(), x()}; } + MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(Vector2, 2) };