Commit 5ea6ef24 authored by schultezub's avatar schultezub
Browse files

various design revisions:

 * Moved paint() method out of VisualizationPipeline back to TumVisPainter
 * started using signals/slots instead of simple observer implementation

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@193 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 29c1c9cb
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "tgt/qt/qtapplication.h" #include "tgt/qt/qtapplication.h"
#include "tgt/qt/qtcanvas.h" #include "tgt/qt/qtcanvas.h"
#include "tbb/include/tbb/task_scheduler_init.h"
#include "tumvispainter.h" #include "tumvispainter.h"
#include "modules/pipelines/slicevis.h" #include "modules/pipelines/slicevis.h"
...@@ -22,6 +24,7 @@ int main(int argc, char** argv) { ...@@ -22,6 +24,7 @@ int main(int argc, char** argv) {
tgt::QtCanvas* canvas = new tgt::QtCanvas("TUMVis"); tgt::QtCanvas* canvas = new tgt::QtCanvas("TUMVis");
SliceVis* sliceVis = 0; SliceVis* sliceVis = 0;
tbb::task_scheduler_init init;
app->addCanvas(canvas); app->addCanvas(canvas);
app->init(); app->init();
LogMgr.getConsoleLog()->addCat("", true); LogMgr.getConsoleLog()->addCat("", true);
...@@ -36,13 +39,13 @@ int main(int argc, char** argv) { ...@@ -36,13 +39,13 @@ int main(int argc, char** argv) {
tgt::Camera camera; tgt::Camera camera;
canvas->setCamera(&camera); canvas->setCamera(&camera);
TumVisPainter* painter;
try { try {
sliceVis = new SliceVis(canvas); sliceVis = new SliceVis();
canvas->setPainter(sliceVis); painter = new TumVisPainter(canvas, sliceVis);
// TumVisPainter painter(canvas); canvas->setPainter(painter);
// canvas->setPainter(&painter); sliceVis->init();
} }
catch (tgt::Exception& e) { catch (tgt::Exception& e) {
LERRORC("main.cpp", "Encountered tgt::Exception: " << e.what()); LERRORC("main.cpp", "Encountered tgt::Exception: " << e.what());
...@@ -53,6 +56,7 @@ int main(int argc, char** argv) { ...@@ -53,6 +56,7 @@ int main(int argc, char** argv) {
app->run(); app->run();
delete painter;
delete sliceVis; delete sliceVis;
delete canvas; delete canvas;
delete app; delete app;
......
#include "tumvispainter.h" #include "tumvispainter.h"
#include "tgt/assert.h" #include "tgt/assert.h"
#include "tgt/camera.h" #include "tgt/camera.h"
#include "tgt/quadrenderer.h"
#include "tgt/quadric.h" #include "tgt/quadric.h"
#include "core/datastructures/imagedatarendertarget.h"
namespace TUMVis { namespace TUMVis {
const std::string TumVisPainter::loggerCat_ = "TUMVis.core.TumVisPainter"; const std::string TumVisPainter::loggerCat_ = "TUMVis.core.TumVisPainter";
TumVisPainter::TumVisPainter(tgt::GLCanvas* canvas) TumVisPainter::TumVisPainter(tgt::GLCanvas* canvas, VisualizationPipeline* pipeline)
: tgt::Painter(canvas) : tgt::Painter(canvas)
, _pipeline(0)
, _dirty(0)
, _currentlyRendering(false)
, _copyShader(0)
{ {
tgtAssert(getCanvas() != 0, "The given canvas must not be 0!"); tgtAssert(getCanvas() != 0, "The given canvas must not be 0!");
setPipeline(pipeline);
} }
void TumVisPainter::paint() { void TumVisPainter::paint() {
// Put TUMVis rendering pipeline evaluation inside if (getCanvas() == 0)
return;
{
tbb::mutex::scoped_lock lock(_localMutex);
_currentlyRendering = true;
_dirty = false;
}
// get OpenGL focus and setup context
getCanvas()->getGLFocus();
const tgt::ivec2 size = getCanvas()->getSize();
glViewport(0, 0, size.x, size.y);
// try get Data
const ImageDataRenderTarget* image = _pipeline->getRenderTarget();
if (image != 0) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Some Dummy rendering: // activate shader
_copyShader->activate();
_copyShader->setIgnoreUniformLocationError(true);
_copyShader->setUniform("_viewportSize", size);
_copyShader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(size));
_copyShader->setIgnoreUniformLocationError(false);
// bind input textures
tgt::TextureUnit colorUnit, depthUnit;
image->bind(_copyShader, colorUnit, depthUnit);
LGL_ERROR;
// execute the shader
tgt::QuadRenderer::renderQuad();
_copyShader->deactivate();
LGL_ERROR;
}
else {
// TODO: render some nifty error texture
// so long, we do some dummy rendering
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
getCamera()->setPosition(tgt::vec3(0.f,0.f,2.f));
getCamera()->look(); getCamera()->look();
glColor3f(1.f, 0.f, 0.f); glColor3f(1.f, 0.f, 0.f);
tgt::Sphere sphere(.5f, 64, 32); tgt::Sphere sphere(.5f, 64, 32);
sphere.render(); sphere.render();
/*
// render error texture
if (!errorTex_) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
return;
}
glClear(GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
errorTex_->bind();
errorTex_->enable();
glColor3f(1.f, 1.f, 1.f);
renderQuad();
errorTex_->disable();*/
}
LGL_ERROR;
{
tbb::mutex::scoped_lock lock(_localMutex);
_currentlyRendering = false;
}
if (_dirty)
getCanvas()->repaint();
} }
void TumVisPainter::sizeChanged(const tgt::ivec2& size) { void TumVisPainter::sizeChanged(const tgt::ivec2& size) {
if (getCanvas()) { if (getCanvas()) {
getCanvas()->getGLFocus(); getCanvas()->getGLFocus();
} }
glViewport(0, 0, size.x, size.y); _pipeline->setRenderTargetSize(size);
getCamera()->setRatio((float) size.x/size.y);
} }
void TumVisPainter::init() { void TumVisPainter::init() {
if (getCanvas()) { try {
getCanvas()->getGLFocus(); // TODO: Remove hardcoded paths, and use ShdrMgr.addPath() at some central location
_copyShader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "core/glsl/copyimage.frag", "", false);
}
catch (tgt::Exception& e) {
LERRORC("main.cpp", "Encountered tgt::Exception: " << e.what());
} }
else {
LWARNING("initialize(): No canvas");
} }
glEnable(GL_DEPTH_TEST); void TumVisPainter::setPipeline(VisualizationPipeline* pipeline) {
glShadeModel(GL_SMOOTH); tgtAssert(pipeline != 0, "The given pipeline must not be 0.");
glEnable(GL_COLOR_MATERIAL); if (_pipeline != 0) {
glEnable(GL_LIGHTING); _pipeline->s_renderTargetChanged.disconnect(this);
glEnable(GL_LIGHT0); if (getCanvas()->getEventHandler() != 0)
getCanvas()->getEventHandler()->removeListener(_pipeline);
getCamera()->setPosition(tgt::vec3(0.f,0.f,2.f)); }
/*
_pipeline = pipeline;
_pipeline->s_renderTargetChanged.connect(this, &TumVisPainter::onPipelineInvalidated);
_pipeline->setRenderTargetSize(getCanvas()->getSize());
if (getCanvas()->getEventHandler() != 0)
getCanvas()->getEventHandler()->addListenerToFront(_pipeline);
}
glEnable(GL_DEPTH_TEST); void TumVisPainter::onPipelineInvalidated() {
glDepthFunc(GL_LESS); if (! _currentlyRendering)
glDisable(GL_CULL_FACE); getCanvas()->repaint();
glCullFace(GL_BACK);*/ else {
tbb::mutex::scoped_lock lock(_localMutex);
_dirty = true;
} }
}
} }
\ No newline at end of file
#include "sigslot/sigslot.h"
#include "tbb/include/tbb/mutex.h"
#include "tgt/logmanager.h" #include "tgt/logmanager.h"
#include "tgt/glcanvas.h" #include "tgt/glcanvas.h"
#include "tgt/painter.h" #include "tgt/painter.h"
#include "tgt/event/eventhandler.h" #include "tgt/event/eventhandler.h"
#include "core/pipeline/visualizationpipeline.h"
namespace tgt {
class Shader;
}
namespace TUMVis { namespace TUMVis {
/** /**
...@@ -10,18 +18,26 @@ namespace TUMVis { ...@@ -10,18 +18,26 @@ namespace TUMVis {
* *
* \todo * \todo
*/ */
class TumVisPainter : public tgt::Painter { class TumVisPainter : public tgt::Painter, public sigslot::has_slots<> {
public: public:
TumVisPainter(tgt::GLCanvas* canvas); TumVisPainter(tgt::GLCanvas* canvas, VisualizationPipeline* pipeline);
virtual void paint(); virtual void paint();
virtual void sizeChanged(const tgt::ivec2& size); virtual void sizeChanged(const tgt::ivec2& size);
virtual void init(); virtual void init();
void setPipeline(VisualizationPipeline* pipeline);
void onPipelineInvalidated();
private: private:
static const std::string loggerCat_; static const std::string loggerCat_;
float _size; VisualizationPipeline* _pipeline;
bool _dirty;
bool _currentlyRendering;
tgt::Shader* _copyShader; ///< Shader for copying the render target to the framebuffer.
tbb::mutex _localMutex;
}; };
} }
...@@ -16,12 +16,13 @@ namespace TUMVis { ...@@ -16,12 +16,13 @@ namespace TUMVis {
} }
const DataHandle* DataContainer::addData(const std::string& name, AbstractData* data) { const DataHandle* DataContainer::addData(const std::string& name, AbstractData* data) {
DataHandle* dh = new DataHandle(this, data); DataHandle* dh = new DataHandle(data);
addDataHandle(name, dh); addDataHandle(name, dh);
return dh; return dh;
} }
void DataContainer::addDataHandle(const std::string& name, const DataHandle* dh) { void DataContainer::addDataHandle(const std::string& name, const DataHandle* dh) {
{
tbb::spin_mutex::scoped_lock lock(_localMutex); tbb::spin_mutex::scoped_lock lock(_localMutex);
std::map<std::string, const DataHandle*>::iterator it = _handles.lower_bound(name); std::map<std::string, const DataHandle*>::iterator it = _handles.lower_bound(name);
if (it != _handles.end() && it->first == name) { if (it != _handles.end() && it->first == name) {
...@@ -31,7 +32,9 @@ namespace TUMVis { ...@@ -31,7 +32,9 @@ namespace TUMVis {
else { else {
_handles.insert(it, std::make_pair(name, dh)); _handles.insert(it, std::make_pair(name, dh));
} }
}
DataHandle::addOwner(dh, this); DataHandle::addOwner(dh, this);
s_dataAdded(name, dh);
} }
bool DataContainer::hasData(const std::string& name) const { bool DataContainer::hasData(const std::string& name) const {
......
#ifndef DATACONTAINER_H__ #ifndef DATACONTAINER_H__
#define DATACONTAINER_H__ #define DATACONTAINER_H__
#include "sigslot/sigslot.h"
#include "tbb/include/tbb/spin_mutex.h" #include "tbb/include/tbb/spin_mutex.h"
#include "core/datastructures/abstractdata.h" #include "core/datastructures/abstractdata.h"
#include "core/datastructures/datahandle.h" #include "core/datastructures/datahandle.h"
#include "core/tools/observer.h"
#include <string> #include <string>
#include <map> #include <map>
namespace TUMVis { namespace TUMVis {
/** /**
* A DataContainer manages instances of AbstractData and offers access to them via string identifiers (names/keys). * A DataContainer manages instances of AbstractData and offers access to them via string identifiers (names/keys).
* Therefore, it stores them in DataHandles which take ownership of the AbstractData instance. Hence, * Therefore, it stores them in DataHandles which take ownership of the AbstractData instance. Hence,
...@@ -41,7 +42,7 @@ namespace TUMVis { ...@@ -41,7 +42,7 @@ namespace TUMVis {
/** /**
* Adds the given AbstractData instance \a data, accessible by the key \name, to this DataContainer. * Adds the given AbstractData instance \a data, accessible by the key \name, to this DataContainer.
* In doing so, the DataContainer (respectively the created DataHandle) takes ownership of \a data * In doing so, the DataContainer (respectively the created DataHandle) takes ownership of \a data
* and will manage its lifetime. So don't even dare to delete \a data yourself! * and will manage its lifetime. So don't even think about deleting \a data yourself!
* *
* \param name Key for accessing the DataHandle within this DataContainer * \param name Key for accessing the DataHandle within this DataContainer
* \param data DataHandle to add. * \param data DataHandle to add.
...@@ -86,6 +87,9 @@ namespace TUMVis { ...@@ -86,6 +87,9 @@ namespace TUMVis {
template<typename T> template<typename T>
inline const T* getTypedData(const std::string& name) const; inline const T* getTypedData(const std::string& name) const;
sigslot::signal2<const std::string&, const DataHandle*> s_dataAdded;
private: private:
std::map<std::string, const DataHandle*> _handles; std::map<std::string, const DataHandle*> _handles;
mutable tbb::spin_mutex _localMutex; mutable tbb::spin_mutex _localMutex;
......
...@@ -6,9 +6,10 @@ namespace TUMVis { ...@@ -6,9 +6,10 @@ namespace TUMVis {
const std::string DataHandle::loggerCat_ = "TUMVis.core.datastructures.DataHandle"; const std::string DataHandle::loggerCat_ = "TUMVis.core.datastructures.DataHandle";
DataHandle::DataHandle(const DataContainer* owner, AbstractData* data) DataHandle::DataHandle(AbstractData* data, const DataContainer* owner /*= 0*/)
: _data(data) : _data(data)
{ {
if (owner != 0)
addOwner(this, owner); addOwner(this, owner);
} }
......
...@@ -53,13 +53,13 @@ namespace TUMVis { ...@@ -53,13 +53,13 @@ namespace TUMVis {
private: private:
/** /**
* Creates a new DataHandle for \a data and takes its ownership in terms of lifetime management. * Creates a new DataHandle for \a data and takes its ownership in terms of lifetime management.
* The DataContainer \a owner will automatically be added to the set of owners of this DataHandle, so * If \a owner != 0, it will automatically be added to the set of owners of this DataHandle, so
* it is NOT needed to call DataHandle::addOwner(). * in this case it is NOT needed to call DataHandle::addOwner().
* *
* \param owner Initial owner of this DataHandle (usually the DataContainer creating the handle)
* \param data AbstractData instance to manage * \param data AbstractData instance to manage
* \param owner Initial owner of this DataHandle, may be 0.
*/ */
DataHandle(const DataContainer* owner, AbstractData* data); DataHandle(AbstractData* data, const DataContainer* owner = 0);
/** /**
* DO NOT USE - it is private on purpose! * DO NOT USE - it is private on purpose!
......
...@@ -27,4 +27,15 @@ namespace TUMVis { ...@@ -27,4 +27,15 @@ namespace TUMVis {
} }
} }
void AbstractPipeline::onNotify(const ProcessorObserverArgs& poa) {
// tbb::spin_mutex::scoped_lock lock(_localMutex);
// _invalidationLevel.setLevel(InvalidationLevel::INVALID_RESULT);
execute();
}
const DataContainer& AbstractPipeline::getDataContainer() const {
return _data;
}
} }
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
#define ABSTRACTPIPELINE_H__ #define ABSTRACTPIPELINE_H__
#include "tgt/logmanager.h" #include "tgt/logmanager.h"
#include "tbb/include/tbb/spin_mutex.h"
#include "core/tools/observer.h"
#include "core/tools/invalidationlevel.h"
#include "core/datastructures/datacontainer.h" #include "core/datastructures/datacontainer.h"
#include "core/pipeline/abstractprocessor.h" #include "core/pipeline/abstractprocessor.h"
#include "core/properties/propertycollection.h" #include "core/properties/propertycollection.h"
...@@ -14,7 +17,7 @@ namespace TUMVis { ...@@ -14,7 +17,7 @@ namespace TUMVis {
* Abstract base class for TUMVis Pipelines. * Abstract base class for TUMVis Pipelines.
* *
*/ */
class AbstractPipeline { class AbstractPipeline : public GenericObserver<ProcessorObserverArgs> {
public: public:
/** /**
* Creates a AbstractPipeline. * Creates a AbstractPipeline.
...@@ -40,16 +43,33 @@ namespace TUMVis { ...@@ -40,16 +43,33 @@ namespace TUMVis {
virtual void execute() = 0; virtual void execute() = 0;
/** /**
* Returns the PropertyCollection of this processor. * Returns the PropertyCollection of this pipeline.
* \return _properties * \return _properties
*/ */
PropertyCollection& getPropertyCollection(); PropertyCollection& getPropertyCollection();
/**
* Returns the DataContainer of this pipeline
* \return _data
*/
const DataContainer& getDataContainer() const;
/**
* Gets called when one of the observed processors changed and thus notifies its observers.
* The default behaviour is just to set the invalidation level to invalid.
* \sa GenericObserver::onNotify, AbstractProcessor
* \param poa ProcessorObserverArgs ObserverArgument struct containing the emitting processor and its InvalidationLevel
*/
virtual void onNotify(const ProcessorObserverArgs& poa);
protected: protected:
DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline DataContainer _data; ///< DataContainer containing local working set of data for this Pipeline
std::vector<AbstractProcessor*> _processors; ///< List of all processors of this pipeline std::vector<AbstractProcessor*> _processors; ///< List of all processors of this pipeline
PropertyCollection _properties; ///< PropertyCollection of this pipeline, put in here all properties you want to be publicly accessible PropertyCollection _properties; ///< PropertyCollection of this pipeline, put in here all properties you want to be publicly accessible
InvalidationLevel _invalidationLevel; ///< current invalidation level
tbb::spin_mutex _localMutex; ///< mutex for altering local members
static const std::string loggerCat_; static const std::string loggerCat_;
}; };
......
...@@ -7,21 +7,22 @@ ...@@ -7,21 +7,22 @@
namespace TUMVis { namespace TUMVis {
const std::string VisualizationPipeline::loggerCat_ = "TUMVis.core.datastructures.VisualizationPipeline"; const std::string VisualizationPipeline::loggerCat_ = "TUMVis.core.datastructures.VisualizationPipeline";
VisualizationPipeline::VisualizationPipeline(tgt::GLCanvas* canvas /*= 0*/) VisualizationPipeline::VisualizationPipeline()
: AbstractPipeline() : AbstractPipeline()
, _canvas(0) , tgt::EventListener()
, _canvasSize("canvasSize", "Canvas Size", tgt::ivec2(128, 128)) , _renderTargetSize("canvasSize", "Canvas Size", tgt::ivec2(128, 128))
, _renderTargetID("renderTargetID", "Render Target ID", "VisualizationPipeline.renderTarget") , _renderTargetID("renderTargetID", "Render Target ID", "VisualizationPipeline.renderTarget")
{ {
setCanvas(canvas); _data.s_dataAdded.connect(this, &VisualizationPipeline::onDataContainerDataAdded);
} }
VisualizationPipeline::~VisualizationPipeline() { VisualizationPipeline::~VisualizationPipeline() {
_data.s_dataAdded.disconnect(this);
} }
void VisualizationPipeline::onEvent(tgt::Event* e) { void VisualizationPipeline::onEvent(tgt::Event* e) {
// cycle through event handlers, ask each one if it handles the event and if so, execute it. // cycle through event handlers, ask each one if it handles the event and if so, execute it.
for (std::vector<AbstractEventHandler*>::iterator it = _eventHandlers.begin(); it != _eventHandlers.end() && !e->isAccepted(); ++it) { for (std::vector<AbstractEventHandler*>::iterator it = _eventHandlers.begin(); it != _eventHandlers.end() && e->isAccepted(); ++it) {
if ((*it)->accept(e)) { if ((*it)->accept(e)) {
(*it)->execute(e); (*it)->execute(e);
} }
...@@ -32,107 +33,30 @@ namespace TUMVis { ...@@ -32,107 +33,30 @@ namespace TUMVis {
} }
} }
void VisualizationPipeline::setCanvas(tgt::GLCanvas* canvas) {
if (_canvas != 0 && _canvas->getEventHandler() != 0) {
_canvas->getEventHandler()->removeListener(this);
}
_canvas = canvas;
_canvasSize.setValue(_canvas->getSize());