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