diff --git a/doc/debug-tools.dox b/doc/debug-tools.dox new file mode 100644 index 000000000..97e439783 --- /dev/null +++ b/doc/debug-tools.dox @@ -0,0 +1,56 @@ +namespace Magnum { +/** @page debug-tools Debugging helpers + +@brief Convenience classes to help you during development. + +@tableofcontents + +DebugTools library provides various helper classes to help you with +prototyping and debugging applications without the need to write too much +common code. They probably have no usage in production code, but can be useful +in development. + +@section debug-tools-renderers Debug renderers + +%Debug renderers provide a way to visualize objects and object features in +@ref scenegraph "scene graph" without the need to mess around with meshes and +shaders. They are implemented as object features, so you can attach any number +of them to any object. + +Basic usage involves instancing DebugTools::ResourceManager and keeping it for +for the whole lifetime of debug renderers. Next you need some SceneGraph::DrawableGroup +instance. You can use the same group as for the rest of your scene, but +preferrably use dedicated one for debug renderers, so you can easily enable or +disable debug rendering. + +Next step is to create configuration for your debug renderers and create +particular debug renderer. The configuration is managed using the resource +manager - you create configuration instance, add it to the manager and then +reference it using particular resource key. This way you can easily share the +same options with more renderers. If no options are specified or resource with +given key doesn't exist, default fallback is used. + +Example usage: visualizing object position, rotation and scaling using +DebugTools::ObjectRenderer: +@code +// Global instance of debug resource manager, drawable group for the renderers +DebugTools::ResourceManager manager; +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), + ResourceDataState::Final, ResourcePolicy::Persistent); + +// Create debug renderer for given object, use "my" options for it. The +// renderer is automatically added to the object features and also to +// specified drawable group. +Object3D* object; +new DebugTools::ObjectRenderer2D(object, "my", debugDrawables); +@endcode + +See DebugTools::ObjectRenderer and DebugTools::ShapeRenderer for more +information. + +*/ +} diff --git a/doc/features.dox b/doc/features.dox index 339e66824..3a0084de2 100644 --- a/doc/features.dox +++ b/doc/features.dox @@ -5,5 +5,6 @@ namespace Magnum { - @subpage matrix-vector - @copybrief matrix-vector - @subpage scenegraph - @copybrief scenegraph - @subpage collision-detection - @copybrief collision-detection +- @subpage debug-tools - @copybrief debug-tools */ } diff --git a/src/DebugTools/CMakeLists.txt b/src/DebugTools/CMakeLists.txt index 25bd0dfeb..3f828e7dd 100644 --- a/src/DebugTools/CMakeLists.txt +++ b/src/DebugTools/CMakeLists.txt @@ -1,4 +1,5 @@ set(MagnumDebugTools_SRCS + ObjectRenderer.cpp Profiler.cpp ResourceManager.cpp ShapeRenderer.cpp @@ -10,6 +11,7 @@ set(MagnumDebugTools_SRCS set(MagnumDebugTools_HEADERS DebugTools.h + ObjectRenderer.h Profiler.h ResourceManager.h ShapeRenderer.h diff --git a/src/DebugTools/DebugTools.h b/src/DebugTools/DebugTools.h index 529a3194a..d1aeff182 100644 --- a/src/DebugTools/DebugTools.h +++ b/src/DebugTools/DebugTools.h @@ -23,6 +23,11 @@ namespace Magnum { namespace DebugTools { +template class ObjectRenderer; +typedef ObjectRenderer<2> ObjectRenderer2D; +typedef ObjectRenderer<3> ObjectRenderer3D; +class ObjectRendererOptions; + class Profiler; class ResourceManager; diff --git a/src/DebugTools/ObjectRenderer.cpp b/src/DebugTools/ObjectRenderer.cpp new file mode 100644 index 000000000..3632f65a8 --- /dev/null +++ b/src/DebugTools/ObjectRenderer.cpp @@ -0,0 +1,178 @@ +/* + 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 "ObjectRenderer.h" + +#include "Buffer.h" +#include "IndexedMesh.h" +#include "DebugTools/ResourceManager.h" +#include "MeshTools/Interleave.h" +#include "SceneGraph/AbstractCamera.h" +#include "Shaders/VertexColorShader.h" + +namespace Magnum { namespace DebugTools { + +namespace { + +template struct Renderer; + +template<> struct Renderer<2> { + inline static ResourceKey shader() { return {"VertexColorShader2D"}; } + inline static ResourceKey vertexBuffer() { return {"object2d-vertices"}; } + inline static ResourceKey indexBuffer() { return {"object2d-indices"}; } + inline static ResourceKey mesh() { return {"object2d"}; } + + static const std::array positions; + static const std::array, 8> colors; + static const std::array indices; +}; + +const std::array Renderer<2>::positions{{ + { 0.0f, 0.0f}, + { 1.0f, 0.0f}, /* X axis */ + { 0.9f, 0.1f}, + { 0.9f, -0.1f}, + + { 0.0f, 0.0f}, + { 0.0f, 1.0f}, /* Y axis */ + { 0.1f, 0.9f}, + {-0.1f, 0.9f} +}}; + +const std::array, 8> Renderer<2>::colors{{ + {1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, /* X axis */ + {1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, /* Y axis */ + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, +}}; + +const std::array Renderer<2>::indices{{ + 0, 1, + 1, 2, /* X axis */ + 1, 3, + + 4, 5, + 5, 6, /* Y axis */ + 5, 7 +}}; + +template<> struct Renderer<3> { + inline static ResourceKey shader() { return {"VertexColorShader3D"}; } + inline static ResourceKey vertexBuffer() { return {"object3d-vertices"}; } + inline static ResourceKey indexBuffer() { return {"object3d-indices"}; } + inline static ResourceKey mesh() { return {"object3d"}; } + + static const std::array positions; + static const std::array, 12> colors; + static const std::array indices; +}; + +const std::array Renderer<3>::positions{{ + { 0.0f, 0.0f, 0.0f}, + { 1.0f, 0.0f, 0.0f}, /* X axis */ + { 0.9f, 0.1f, 0.0f}, + { 0.9f, -0.1f, 0.0f}, + + { 0.0f, 0.0f, 0.0f}, + { 0.0f, 1.0f, 0.0f}, /* Y axis */ + { 0.1f, 0.9f, 0.0f}, + {-0.1f, 0.9f, 0.0f}, + + { 0.0f, 0.0f, 0.0f}, + { 0.0f, 0.0f, 1.0f}, /* Z axis */ + { 0.1f, 0.0f, 0.9f}, + {-0.1f, 0.0f, 0.9f} +}}; + +const std::array, 12> Renderer<3>::colors{{ + {1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, /* X axis */ + {1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f}, + + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, /* Y axis */ + {0.0f, 1.0f, 0.0f}, + {0.0f, 1.0f, 0.0f}, + + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f}, /* Z axis */ + {0.0f, 0.0f, 1.0f}, + {0.0f, 0.0f, 1.0f} +}}; + +const std::array Renderer<3>::indices{{ + 0, 1, + 1, 2, /* X axis */ + 1, 3, + + 4, 5, + 5, 6, /* Y axis */ + 5, 7, + + 8, 9, + 9, 10, /* Z axis */ + 9, 11 +}}; + +} + +template ObjectRenderer::ObjectRenderer(SceneGraph::AbstractObject* object, ResourceKey options, SceneGraph::DrawableGroup* drawables): SceneGraph::Drawable(object, drawables), options(ResourceManager::instance()->get(options)) { + /* Shader */ + shader = ResourceManager::instance()->get>(Renderer::shader()); + if(!shader) ResourceManager::instance()->set(shader.key(), + new Shaders::VertexColorShader, ResourceDataState::Final, ResourcePolicy::Resident); + + /* Mesh and vertex buffer */ + mesh = ResourceManager::instance()->get(Renderer::mesh()); + vertexBuffer = ResourceManager::instance()->get(Renderer::vertexBuffer()); + indexBuffer = ResourceManager::instance()->get(Renderer::indexBuffer()); + if(mesh) return; + + /* Create the mesh */ + Buffer* vertexBuffer = new Buffer(Buffer::Target::Array); + Buffer* indexBuffer = new Buffer(Buffer::Target::ElementArray); + IndexedMesh* mesh = new IndexedMesh; + + MeshTools::interleave(mesh, vertexBuffer, Buffer::Usage::StaticDraw, Renderer::positions, Renderer::colors); + ResourceManager::instance()->set(this->vertexBuffer.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); + + indexBuffer->setData(Renderer::indices, Buffer::Usage::StaticDraw); + ResourceManager::instance()->set(this->indexBuffer.key(), indexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); + + mesh->setPrimitive(Mesh::Primitive::Lines) + ->addInterleavedVertexBuffer(vertexBuffer, 0, typename Shaders::VertexColorShader::Position(), typename Shaders::VertexColorShader::Color()) + ->setIndexCount(Renderer::indices.size()) + ->setIndexType(Type::UnsignedByte) + ->setIndexBuffer(indexBuffer); + ResourceManager::instance()->set(this->mesh.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual); +} + +template void ObjectRenderer::draw(const typename DimensionTraits::MatrixType& transformationMatrix, SceneGraph::AbstractCamera* camera) { + shader->setTransformationProjectionMatrix(camera->projectionMatrix()*transformationMatrix*DimensionTraits::MatrixType::scaling(typename DimensionTraits::VectorType(options->size()))) + ->use(); + + mesh->draw(); +} + +template class ObjectRenderer<2>; +template class ObjectRenderer<3>; + +}} diff --git a/src/DebugTools/ObjectRenderer.h b/src/DebugTools/ObjectRenderer.h new file mode 100644 index 000000000..b94f42025 --- /dev/null +++ b/src/DebugTools/ObjectRenderer.h @@ -0,0 +1,107 @@ +#ifndef Magnum_DebugTools_ObjectRenderer_h +#define Magnum_DebugTools_ObjectRenderer_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License version 3 for more details. +*/ + +#include "Resource.h" +#include "SceneGraph/Drawable.h" +#include "Shaders/Shaders.h" + +#include "magnumDebugToolsVisibility.h" + +namespace Magnum { namespace DebugTools { + +/** +@brief Object renderer options + +See ObjectRenderer documentation for more information. +*/ +class ObjectRendererOptions { + public: + inline constexpr ObjectRendererOptions(): _size(1.0f) {} + + /** @brief Size of the rendered axes */ + inline constexpr GLfloat size() const { return _size; } + + /** + * @brief Set size of the rendered axes + * @return Pointer to self (for method chaining) + * + * Default is `1.0f`. + */ + inline ObjectRendererOptions* setSize(GLfloat size) { + _size = size; + return this; + } + + private: + GLfloat _size; +}; + +/** +@brief Object renderer + +Visualizes object position, rotation and scale using colored axes. + +@section ObjectRenderer-usage Basic usage + +Example code: +@code +// Create some options +DebugTools::ResourceManager::instance()->set("my", + (new DebugTools::ObjectRendererOptions())->setSize(0.3f), + ResourceDataState::Final, ResourcePolicy::Persistent); + +// Create debug renderer for given object, use "my" options for it +Object3D* object; +new DebugTools::ObjectRenderer2D(object, "my", debugDrawables); +@endcode + +@see ObjectRenderer2D, ObjectRenderer3D +*/ +template class MAGNUM_DEBUGTOOLS_EXPORT ObjectRenderer: public SceneGraph::Drawable { + public: + /** + * @brief Constructor + * @param object Object for which to create debug renderer + * @param options Options resource key. See + * @ref ObjectRenderer-usage "class documentation" for more + * information. + * @param drawables Drawable group + * + * The renderer is automatically added to object's features. + */ + explicit ObjectRenderer(SceneGraph::AbstractObject* object, ResourceKey options = ResourceKey(), SceneGraph::DrawableGroup* drawables = nullptr); + + protected: + /** @todoc Remove GLfloat when Doxygen properly treats this as override */ + void draw(const typename DimensionTraits::MatrixType& transformationMatrix, SceneGraph::AbstractCamera* camera) override; + + private: + Resource options; + Resource> shader; + Resource mesh; + Resource vertexBuffer, indexBuffer; +}; + +/** @brief Two-dimensional object renderer */ +typedef ObjectRenderer<2> ObjectRenderer2D; + +/** @brief Three-dimensional object renderer */ +typedef ObjectRenderer<3> ObjectRenderer3D; + +}} + +#endif diff --git a/src/DebugTools/ResourceManager.cpp b/src/DebugTools/ResourceManager.cpp index 3c75732e9..fccdd75b3 100644 --- a/src/DebugTools/ResourceManager.cpp +++ b/src/DebugTools/ResourceManager.cpp @@ -19,15 +19,17 @@ #include "Buffer.h" #include "Mesh.h" +#include "DebugTools/ObjectRenderer.h" #include "DebugTools/ShapeRenderer.h" namespace Magnum { -template class ResourceManager; +template class ResourceManager; namespace DebugTools { ResourceManager::ResourceManager() { + setFallback(new ObjectRendererOptions); setFallback(new ShapeRendererOptions); } diff --git a/src/DebugTools/ResourceManager.h b/src/DebugTools/ResourceManager.h index 98ca34956..3e90d8526 100644 --- a/src/DebugTools/ResourceManager.h +++ b/src/DebugTools/ResourceManager.h @@ -34,7 +34,7 @@ namespace Magnum { -extern template ResourceManager MAGNUM_DEBUGTOOLS_EXPORT *& ResourceManager::internalInstance(); +extern template ResourceManager MAGNUM_DEBUGTOOLS_EXPORT *& ResourceManager::internalInstance(); namespace DebugTools { @@ -43,7 +43,7 @@ namespace DebugTools { Stores various data used by debug renderers. */ -class MAGNUM_DEBUGTOOLS_EXPORT ResourceManager: public Magnum::ResourceManager { +class MAGNUM_DEBUGTOOLS_EXPORT ResourceManager: public Magnum::ResourceManager { public: explicit ResourceManager(); ~ResourceManager();