mirror of https://github.com/mosra/magnum.git
Browse Source
Visualizes object position, rotation and size. Common usage as with ShapeRenderer, common documentation extended and moved to new `debug-tools` page.pull/7/head
8 changed files with 354 additions and 3 deletions
@ -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<DebugTools::ObjectRendererOptions>("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. |
||||
|
||||
*/ |
||||
} |
||||
@ -0,0 +1,178 @@
|
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
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<std::uint8_t> 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<Point2D, 8> positions; |
||||
static const std::array<Color3<>, 8> colors; |
||||
static const std::array<std::uint8_t, 12> indices; |
||||
}; |
||||
|
||||
const std::array<Point2D, 8> 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<Color3<>, 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<std::uint8_t, 12> 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<Point3D, 12> positions; |
||||
static const std::array<Color3<>, 12> colors; |
||||
static const std::array<uint8_t, 18> indices; |
||||
}; |
||||
|
||||
const std::array<Point3D, 12> 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<Color3<>, 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<std::uint8_t, 18> 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<std::uint8_t dimensions> ObjectRenderer<dimensions>::ObjectRenderer(SceneGraph::AbstractObject<dimensions>* object, ResourceKey options, SceneGraph::DrawableGroup<dimensions>* drawables): SceneGraph::Drawable<dimensions>(object, drawables), options(ResourceManager::instance()->get<ObjectRendererOptions>(options)) { |
||||
/* Shader */ |
||||
shader = ResourceManager::instance()->get<AbstractShaderProgram, Shaders::VertexColorShader<dimensions>>(Renderer<dimensions>::shader()); |
||||
if(!shader) ResourceManager::instance()->set<AbstractShaderProgram>(shader.key(), |
||||
new Shaders::VertexColorShader<dimensions>, ResourceDataState::Final, ResourcePolicy::Resident); |
||||
|
||||
/* Mesh and vertex buffer */ |
||||
mesh = ResourceManager::instance()->get<Mesh>(Renderer<dimensions>::mesh()); |
||||
vertexBuffer = ResourceManager::instance()->get<Buffer>(Renderer<dimensions>::vertexBuffer()); |
||||
indexBuffer = ResourceManager::instance()->get<Buffer>(Renderer<dimensions>::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<dimensions>::positions, Renderer<dimensions>::colors); |
||||
ResourceManager::instance()->set(this->vertexBuffer.key(), vertexBuffer, ResourceDataState::Final, ResourcePolicy::Manual); |
||||
|
||||
indexBuffer->setData(Renderer<dimensions>::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<dimensions>::Position(), typename Shaders::VertexColorShader<dimensions>::Color()) |
||||
->setIndexCount(Renderer<dimensions>::indices.size()) |
||||
->setIndexType(Type::UnsignedByte) |
||||
->setIndexBuffer(indexBuffer); |
||||
ResourceManager::instance()->set<Mesh>(this->mesh.key(), mesh, ResourceDataState::Final, ResourcePolicy::Manual); |
||||
} |
||||
|
||||
template<std::uint8_t dimensions> void ObjectRenderer<dimensions>::draw(const typename DimensionTraits<dimensions>::MatrixType& transformationMatrix, SceneGraph::AbstractCamera<dimensions>* camera) { |
||||
shader->setTransformationProjectionMatrix(camera->projectionMatrix()*transformationMatrix*DimensionTraits<dimensions>::MatrixType::scaling(typename DimensionTraits<dimensions>::VectorType(options->size()))) |
||||
->use(); |
||||
|
||||
mesh->draw(); |
||||
} |
||||
|
||||
template class ObjectRenderer<2>; |
||||
template class ObjectRenderer<3>; |
||||
|
||||
}} |
||||
@ -0,0 +1,107 @@
|
||||
#ifndef Magnum_DebugTools_ObjectRenderer_h |
||||
#define Magnum_DebugTools_ObjectRenderer_h |
||||
/*
|
||||
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
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<DebugTools::ObjectRendererOptions>("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<std::uint8_t dimensions> class MAGNUM_DEBUGTOOLS_EXPORT ObjectRenderer: public SceneGraph::Drawable<dimensions> { |
||||
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<dimensions>* object, ResourceKey options = ResourceKey(), SceneGraph::DrawableGroup<dimensions>* drawables = nullptr); |
||||
|
||||
protected: |
||||
/** @todoc Remove GLfloat when Doxygen properly treats this as override */ |
||||
void draw(const typename DimensionTraits<dimensions, GLfloat>::MatrixType& transformationMatrix, SceneGraph::AbstractCamera<dimensions, GLfloat>* camera) override; |
||||
|
||||
private: |
||||
Resource<ObjectRendererOptions> options; |
||||
Resource<AbstractShaderProgram, Shaders::VertexColorShader<dimensions>> shader; |
||||
Resource<Mesh> mesh; |
||||
Resource<Buffer> vertexBuffer, indexBuffer; |
||||
}; |
||||
|
||||
/** @brief Two-dimensional object renderer */ |
||||
typedef ObjectRenderer<2> ObjectRenderer2D; |
||||
|
||||
/** @brief Three-dimensional object renderer */ |
||||
typedef ObjectRenderer<3> ObjectRenderer3D; |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
Loading…
Reference in new issue