Commit fad91715 authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Merge branch 'development' of /mnt/bigone/git/repositories/berge/campvis

parents e2fcc506 1c50f447
......@@ -28,24 +28,6 @@
// ================================================================================================
#include "application/campvisapplication.h"
#include "modules/advancedusvis/pipelines/advancedusvis.h"
#include "modules/advancedusvis/pipelines/cmbatchgeneration.h"
#include "modules/vis/pipelines/ixpvdemo.h"
#include "modules/vis/pipelines/dvrvis.h"
#include "modules/vis/pipelines/volumerendererdemo.h"
#include "modules/vis/pipelines/volumeexplorerdemo.h"
#include "modules/vis/pipelines/slicevis.h"
#ifdef HAS_KISSCL
#include "modules/opencl/pipelines/openclpipeline.h"
#endif
#ifdef CAMPVIS_HAS_MODULE_SCR_MSK
#include "modules/scr_msk/pipelines/uscompounding.h"
#endif
#ifdef CAMPVIS_HAS_MODULE_COLUMBIA
#include "modules/columbia/pipelines/columbia1.h"
#endif
#ifdef Q_WS_X11
#include <X11/Xlib.h>
......@@ -66,27 +48,6 @@ int main(int argc, char** argv) {
#endif
CampVisApplication app(argc, argv);
//app.addVisualizationPipeline("Advanced Ultrasound Visualization", new AdvancedUsVis());
//app.addVisualizationPipeline("Confidence Map Generation", new CmBatchGeneration());
// app.addVisualizationPipeline("IXPV", new IxpvDemo());
//app.addVisualizationPipeline("SliceVis", new SliceVis());
app.addVisualizationPipeline("DVRVis", new DVRVis());
//app.addVisualizationPipeline("VolumeRendererDemo", new VolumeRendererDemo());
app.addVisualizationPipeline("VolumeExplorerDemo", new VolumeExplorerDemo());
#ifdef HAS_KISSCL
//app.addVisualizationPipeline("DVR with OpenCL", new OpenCLPipeline());
#endif
#ifdef CAMPVIS_HAS_MODULE_SCR_MSK
//app.addVisualizationPipeline("US Compounding", new UsCompounding());
#endif
#ifdef CAMPVIS_HAS_MODULE_COLUMBIA
//app.addVisualizationPipeline("Columbia", new Columbia1());
#endif
app.init();
int toReturn = app.run();
app.deinit();
......
......@@ -47,9 +47,10 @@
#include "application/gui/mainwindow.h"
#include "core/tools/opengljobprocessor.h"
#include "core/tools/simplejobprocessor.h"
#include "core/tools/stringutils.h"
#include "core/tools/quadrenderer.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/visualizationpipeline.h"
#include "modules/pipelinefactory.h"
namespace campvis {
......@@ -78,17 +79,29 @@ namespace campvis {
tgtAssert(_initialized == false, "Destructing initialized CampVisApplication, deinitialize first!");
// delete everything in the right order:
for (std::vector< std::pair<VisualizationPipeline*, TumVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
delete it->second;
}
for (std::vector<AbstractPipeline*>::iterator it = _pipelines.begin(); it != _pipelines.end(); ++it) {
delete *it;
}
for (std::vector<DataContainer*>::iterator it = _dataContainers.begin(); it != _dataContainers.end(); ++it) {
delete *it;
}
}
void CampVisApplication::init() {
tgtAssert(_initialized == false, "Tried to initialize CampVisApplication twice.");
// parse argument list and create pipelines
QStringList pipelinesToAdd = this->arguments();
for (int i = 1; i < pipelinesToAdd.size(); ++i) {
DataContainer* dc = createAndAddDataContainer("DataContainer #" + StringUtils::toString(_dataContainers.size() + 1));
AbstractPipeline* p = PipelineFactory::getRef().createPipeline(pipelinesToAdd[i].toStdString(), dc);
if (p != 0)
addPipeline(pipelinesToAdd[i].toStdString(), p);
}
// Init TGT
tgt::InitFeature::Features featureset = tgt::InitFeature::ALL;
tgt::init(featureset);
......@@ -167,7 +180,7 @@ namespace campvis {
}
// Now init painters:
for (std::vector< std::pair<VisualizationPipeline*, TumVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
it->second->init();
}
......@@ -190,7 +203,7 @@ namespace campvis {
}
// Now deinit painters:
for (std::vector< std::pair<VisualizationPipeline*, TumVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
for (std::vector< std::pair<AbstractPipeline*, CampVisPainter*> >::iterator it = _visualizations.begin(); it != _visualizations.end(); ++it) {
it->second->deinit();
}
......@@ -235,33 +248,57 @@ namespace campvis {
return toReturn;
}
void CampVisApplication::addPipeline(AbstractPipeline* pipeline) {
tgtAssert(_initialized == false, "Adding pipelines after initialization is currently not supported.");
void CampVisApplication::addPipeline(const std::string& name, AbstractPipeline* pipeline) {
tgtAssert(pipeline != 0, "Pipeline must not be 0.");
_pipelines.push_back(pipeline);
// if CAMPVis is already fully initialized, we need to temporarily shut down its
// OpenGL job processor, since we need to create a new context.
if (_initialized) {
GLJobProc.pause();
{
tgt::QtThreadedCanvas* canvas = CtxtMgr.createContext(name, "CAMPVis", tgt::ivec2(512, 512));
tgt::GLContextScopedLock lock(canvas->getContext());
addPipelineImpl(canvas, name, pipeline);
}
GLJobProc.resume();
}
else {
tgt::QtThreadedCanvas* canvas = CtxtMgr.createContext(name, "CAMPVis", tgt::ivec2(512, 512));
addPipelineImpl(canvas, name, pipeline);
}
s_PipelinesChanged();
}
void CampVisApplication::addVisualizationPipeline(const std::string& name, VisualizationPipeline* vp) {
tgtAssert(_initialized == false, "Adding pipelines after initialization is currently not supported.");
tgtAssert(vp != 0, "Pipeline must not be 0.");
// create canvas and painter for the VisPipeline and connect all together
tgt::QtThreadedCanvas* canvas = CtxtMgr.createContext(name, "CAMPVis", tgt::ivec2(512, 512));
void CampVisApplication::addPipelineImpl(tgt::QtThreadedCanvas* canvas, const std::string& name, AbstractPipeline* pipeline) {
// create canvas and painter for the pipeline and connect all together
GLJobProc.registerContext(canvas);
_mainWindow->addVisualizationPipelineWidget(name, canvas);
canvas->init();
TumVisPainter* painter = new TumVisPainter(canvas, vp);
CampVisPainter* painter = new CampVisPainter(canvas, pipeline);
canvas->setPainter(painter, false);
pipeline->setCanvas(canvas);
_visualizations.push_back(std::make_pair(vp, painter));
_visualizations.push_back(std::make_pair(pipeline, painter));
_pipelines.push_back(pipeline);
vp->setCanvas(canvas);
addPipeline(vp);
if (_initialized) {
LGL_ERROR;
pipeline->init();
LGL_ERROR;
painter->init();
LGL_ERROR;
}
CtxtMgr.releaseCurrentContext();
_mainWindow->addVisualizationPipelineWidget(name, canvas);
// enable pipeline and invalidate all processors
pipeline->setEnabled(true);
for (std::vector<AbstractProcessor*>::const_iterator it = pipeline->getProcessors().begin(); it != pipeline->getProcessors().end(); ++it) {
(*it)->invalidate(AbstractProcessor::INVALID_RESULT);
}
}
void CampVisApplication::registerDockWidget(Qt::DockWidgetArea area, QDockWidget* dock) {
......@@ -270,4 +307,12 @@ namespace campvis {
_mainWindow->addDockWidget(area, dock);
}
DataContainer* CampVisApplication::createAndAddDataContainer(const std::string& name) {
DataContainer* dc = new DataContainer(name);
_dataContainers.push_back(dc);
s_DataContainersChanged();
return dc;
}
}
......@@ -38,6 +38,8 @@
#include <utility>
#include <vector>
#include "core/datastructures/datacontainer.h"
namespace tgt {
class QtThreadedCanvas;
}
......@@ -45,8 +47,7 @@ namespace tgt {
namespace campvis {
class AbstractPipeline;
class MainWindow;
class TumVisPainter;
class VisualizationPipeline;
class CampVisPainter;
/**
* The CampVisApplication class wraps Pipelines, Evaluators and Painters all together and takes
......@@ -89,25 +90,14 @@ namespace campvis {
void deinit();
/**
* Adds a pipeline which doesn't need visualization (OpenGL) support.
* Each pipeline will automatically get its own evaluator.
*
* \note If you want to add a pipeline that needs a valid OpenGL context, use
* addVisualizationPipeline() instead.
* \param pipeline Pipeline to add, must not need OpenGL support.
*/
void addPipeline(AbstractPipeline* pipeline);
/**
* Adds a visualization pipeline (i.e. a pipeline that needs a OpenGL context).
* For each added pipeline, an OpenGL context will be created (for the evaluation
* and rendering).
* Adds a pipeline to this CAMPVis application.
* Each pipeline will automatically get its own OpenGL context, the corresponding CampvisPainter
* and all necessary connections will be created.
*
* \note You do \b not need to call addPipeline.
* \param name Name of the OpenGL context to create for the pipeline.
* \param vp VisualizationPipeline to add.
* \param vp AbstractPipeline to add.
*/
void addVisualizationPipeline(const std::string& name, VisualizationPipeline* vp);
void addPipeline(const std::string& name, AbstractPipeline* pipeline);
/**
* Adds a dock widget to the main window.
......@@ -125,14 +115,30 @@ namespace campvis {
*/
int run();
/**
* Creates a new DataContainer with the given name.
* \param name Name of the new DataContainer
* \return The newly created DataContainer
*/
DataContainer* createAndAddDataContainer(const std::string& name);
/// Signal emitted when the collection of pipelines has changed.
sigslot::signal0<> s_PipelinesChanged;
/// Signal emitted when the collection of DataContainers has changed.
sigslot::signal0<> s_DataContainersChanged;
private:
/// All pipelines (incuding VisualizationPipelines)
void addPipelineImpl(tgt::QtThreadedCanvas* canvas, const std::string& name, AbstractPipeline* pipeline);
/// All pipelines
std::vector<AbstractPipeline*> _pipelines;
/// All visualisations (i.e. VisualizationPipelines with their corresponding painters/canvases)
std::vector< std::pair<VisualizationPipeline*, TumVisPainter*> > _visualizations;
/// All visualisations (i.e. Pipelines with their corresponding painters/canvases)
std::vector< std::pair<AbstractPipeline*, CampVisPainter*> > _visualizations;
/// All DataContainers
std::vector<DataContainer*> _dataContainers;
/// A local OpenGL context used for initialization
tgt::QtThreadedCanvas* _localContext;
......
......@@ -41,15 +41,15 @@
#include "core/datastructures/imagedata.h"
#include "core/datastructures/renderdata.h"
#include "core/pipeline/visualizationpipeline.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/tools/job.h"
#include "core/tools/opengljobprocessor.h"
#include "core/tools/quadrenderer.h"
namespace campvis {
const std::string TumVisPainter::loggerCat_ = "CAMPVis.core.TumVisPainter";
const std::string CampVisPainter::loggerCat_ = "CAMPVis.core.CampVisPainter";
TumVisPainter::TumVisPainter(tgt::GLCanvas* canvas, VisualizationPipeline* pipeline)
CampVisPainter::CampVisPainter(tgt::GLCanvas* canvas, AbstractPipeline* pipeline)
: Runnable()
, tgt::Painter(canvas)
, _pipeline(0)
......@@ -60,11 +60,11 @@ namespace campvis {
setPipeline(pipeline);
}
TumVisPainter::~TumVisPainter() {
CampVisPainter::~CampVisPainter() {
}
void TumVisPainter::stop() {
void CampVisPainter::stop() {
// we need to execute run() one more time to ensure correct release of the OpenGL context
_stopExecution = true;
_renderCondition.notify_all();
......@@ -72,7 +72,7 @@ namespace campvis {
Runnable::stop();
}
void TumVisPainter::run() {
void CampVisPainter::run() {
std::unique_lock<tbb::mutex> lock(CtxtMgr.getGlMutex());
while (! _stopExecution) {
......@@ -89,7 +89,7 @@ namespace campvis {
CtxtMgr.releaseCurrentContext();
}
void TumVisPainter::paint() {
void CampVisPainter::paint() {
if (getCanvas() == 0)
return;
......@@ -97,7 +97,7 @@ namespace campvis {
glViewport(0, 0, size.x, size.y);
// try get Data
DataContainer::ScopedTypedData<RenderData> rd(_pipeline->getDataContainer(), _pipeline->getRenderTargetID());
ScopedTypedData<RenderData> rd(_pipeline->getDataContainer(), _pipeline->getRenderTargetID());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (rd != 0) {
// activate shader
......@@ -150,11 +150,11 @@ namespace campvis {
getCanvas()->swap();
}
void TumVisPainter::sizeChanged(const tgt::ivec2& size) {
void CampVisPainter::sizeChanged(const tgt::ivec2& size) {
_pipeline->setRenderTargetSize(size);
}
void TumVisPainter::init() {
void CampVisPainter::init() {
try {
// TODO: Remove hardcoded paths, and use ShdrMgr.addPath() at some central location
_copyShader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "core/glsl/copyimage.frag", "", false);
......@@ -164,7 +164,7 @@ namespace campvis {
}
}
void TumVisPainter::deinit() {
void CampVisPainter::deinit() {
ShdrMgr.dispose(_copyShader);
if (_pipeline != 0) {
......@@ -175,7 +175,7 @@ namespace campvis {
}
}
void TumVisPainter::setPipeline(VisualizationPipeline* pipeline) {
void CampVisPainter::setPipeline(AbstractPipeline* pipeline) {
tgtAssert(pipeline != 0, "The given pipeline must not be 0.");
if (_pipeline != 0) {
_pipeline->s_renderTargetChanged.disconnect(this);
......@@ -184,21 +184,21 @@ namespace campvis {
}
_pipeline = pipeline;
_pipeline->s_renderTargetChanged.connect(this, &TumVisPainter::onRenderTargetChanged);
_pipeline->s_renderTargetChanged.connect(this, &CampVisPainter::onRenderTargetChanged);
_pipeline->setRenderTargetSize(getCanvas()->getSize());
if (getCanvas()->getEventHandler() != 0)
getCanvas()->getEventHandler()->addEventListenerToFront(_pipeline);
}
void TumVisPainter::repaint() {
GLJobProc.enqueueJob(getCanvas(), makeJobOnHeap(this, &TumVisPainter::paint), OpenGLJobProcessor::PaintJob);
void CampVisPainter::repaint() {
GLJobProc.enqueueJob(getCanvas(), makeJobOnHeap(this, &CampVisPainter::paint), OpenGLJobProcessor::PaintJob);
}
void TumVisPainter::onRenderTargetChanged() {
void CampVisPainter::onRenderTargetChanged() {
repaint();
}
void TumVisPainter::setCanvas(tgt::GLCanvas* canvas) {
void CampVisPainter::setCanvas(tgt::GLCanvas* canvas) {
tgtAssert(dynamic_cast<tgt::QtThreadedCanvas*>(canvas) != 0, "Canvas must be of type QtThreadedCanvas!");
Painter::setCanvas(canvas);
}
......
......@@ -44,30 +44,30 @@ namespace tgt {
}
namespace campvis {
class VisualizationPipeline;
class AbstractPipeline;
/**
* Painter class for CAMPVis, rendering the render target of a VisualizationPipeline.
* Painter class for CAMPVis, rendering the render target of an AbstractPipeline.
* This painter implements Runnable, hence, it runs in its own thread and the associated canvas
* must be of type QtThreadedCanvas.
* Rendering is implemented using condidional wait - hence the canvas is only updated when
* \a pipeline emits the s_RenderTargetChanged signal.
*
* \sa Runnable, VisualizationPipeline
* \sa Runnable, AbstractPipeline
*/
class TumVisPainter : public Runnable, public tgt::Painter, public sigslot::has_slots<> {
class CampVisPainter : public Runnable, public tgt::Painter, public sigslot::has_slots<> {
public:
/**
* Creates a new TumVisPainter rendering the render target of \a pipeline on \a canvas.
* Creates a new CampVisPainter rendering the render target of \a pipeline on \a canvas.
* \param canvas Canvas to render on
* \param pipeline Pipeline to render
*/
TumVisPainter(tgt::GLCanvas* canvas, VisualizationPipeline* pipeline);
CampVisPainter(tgt::GLCanvas* canvas, AbstractPipeline* pipeline);
/**
* Destructor, stops and waits for the rendering thread if it's still running.
*/
virtual ~TumVisPainter();
virtual ~CampVisPainter();
/// \see Runnable::stop
void stop();
......@@ -106,7 +106,7 @@ namespace campvis {
* Pipeline with the render target to render.
* \param pipeline Pipeline to render
*/
void setPipeline(VisualizationPipeline* pipeline);
void setPipeline(AbstractPipeline* pipeline);
/**
* Slot being notified when the pipeline's render target changed.
......@@ -121,7 +121,7 @@ namespace campvis {
static const std::string loggerCat_;
VisualizationPipeline* _pipeline; ///< Pipeline to render
AbstractPipeline* _pipeline; ///< Pipeline to render
tgt::Shader* _copyShader; ///< Shader for copying the render target to the framebuffer.
tbb::atomic<bool> _dirty; ///< Flag whether render result is dirty and needs to be rerendered.
std::condition_variable _renderCondition; ///< conditional wait condition for rendering
......
......@@ -66,7 +66,7 @@ namespace campvis {
* Creates a new DataContainerInspectorCanvas.
* \param parent Parent Qt widget, may be 0 (default)
*/
DataContainerInspectorCanvas(QWidget* parent = 0);
explicit DataContainerInspectorCanvas(QWidget* parent = 0);
/**
* Destructor.
......
......@@ -71,7 +71,7 @@ namespace campvis {
* Creates a new DataContainerInspectorWidget.
* \param parent Parent Qt widget, may be 0 (default)
*/
DataContainerInspectorWidget(QWidget* parent = 0);
explicit DataContainerInspectorWidget(QWidget* parent = 0);
/**
* Destructor.
......
......@@ -49,7 +49,7 @@ namespace campvis {
*/
class DataContainerTreeRootItem : public TreeItem {
public:
DataContainerTreeRootItem(TreeItem* parent = 0);
explicit DataContainerTreeRootItem(TreeItem* parent = 0);
virtual ~DataContainerTreeRootItem();
/// \see TreeItem::getData()
......@@ -98,7 +98,7 @@ namespace campvis {
Q_OBJECT
public:
DataContainerTreeModel(QObject *parent = 0);
explicit DataContainerTreeModel(QObject *parent = 0);
~DataContainerTreeModel();
void setData(const DataContainer* dataContainer);
......@@ -147,7 +147,7 @@ namespace campvis {
* Creates a new DataContainerTreeWidget.
* \param parent Parent widget
*/
DataContainerTreeWidget(QWidget* parent = 0);
explicit DataContainerTreeWidget(QWidget* parent = 0);
/**
* Destructor
......
......@@ -48,7 +48,7 @@ namespace campvis {
*
* \param parent the QTextEdit to install the LogHighlighter on
*/
LogHighlighter(QTextEdit* parent);
explicit LogHighlighter(QTextEdit* parent);
/**
* Destructor.
......
......@@ -58,7 +58,7 @@ namespace campvis {
* Creates a new DataContainerInspectorWidget.
* \param parent Parent Qt widget, may be 0 (default)
*/
LogViewerWidget(QWidget* parent = 0);
explicit LogViewerWidget(QWidget* parent = 0);
/**
* Destructor.
......
......@@ -35,18 +35,25 @@
#include "application/gui/datacontainerinspectorcanvas.h"
#include "application/gui/qtdatahandle.h"
#include "application/gui/visualizationpipelinewrapper.h"
#include "core/datastructures/datacontainer.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/abstractprocessor.h"
#include "core/tools/stringutils.h"
#include "modules/pipelinefactory.h"
#include <QMdiSubWindow>
#include <QScrollBar>
namespace campvis {
MainWindow::MainWindow(CampVisApplication* application)
: QMainWindow()
, _application(application)
, _mdiArea(0)
, _containerWidget(0)
, _cbPipelineFactory(0)
, _btnPipelineFactory(0)
, _pipelineWidget(0)
, _propCollectionWidget(0)
, _dcInspectorWidget(0)
......@@ -55,6 +62,7 @@ namespace campvis {
, _btnShowDataContainerInspector(0)
, _selectedPipeline(0)
, _selectedProcessor(0)
, _selectedDataContainer(0)
, _logViewer(0)
{
tgtAssert(_application != 0, "Application must not be 0.");
......@@ -64,6 +72,7 @@ namespace campvis {
MainWindow::~MainWindow() {
_application->s_PipelinesChanged.disconnect(this);
_application->s_DataContainersChanged.disconnect(this);
delete _dcInspectorWidget;
}
......@@ -81,9 +90,24 @@ namespace campvis {
_mdiArea->tileSubWindows();
setCentralWidget(_mdiArea);
_containerWidget = new QWidget(this);
QGridLayout* _cwLayout = new QGridLayout(_containerWidget);
_cbPipelineFactory = new QComboBox(_containerWidget);
std::vector<std::string> registeredPipelines = PipelineFactory::getRef().getRegisteredPipelines();
for (std::vector<std::string>::const_iterator it = registeredPipelines.begin(); it != registeredPipelines.end(); ++it)
_cbPipelineFactory->addItem(QString::fromStdString(*it));
_cwLayout->addWidget(_cbPipelineFactory, 0, 0);
_btnPipelineFactory = new QPushButton("Add Pipeline", _containerWidget);
_cwLayout->addWidget(_btnPipelineFactory, 0, 1);
_pipelineWidget = new PipelineTreeWidget();
_pipelineWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
ui.pipelineTreeDock->setWidget(_pipelineWidget);
_containerWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
_cwLayout->addWidget(_pipelineWidget, 1, 0, 1, 2);
_containerWidget->setLayout(_cwLayout);
ui.pipelineTreeDock->setWidget(_containerWidget);
_pipelinePropertiesScrollArea = new QScrollArea();
_pipelinePropertiesScrollArea->setWidgetResizable(true);
......@@ -115,8 +139,8 @@ namespace campvis {
_dcInspectorWidget = new DataContainerInspectorWidget();
connect(
this, SIGNAL(updatePipelineWidget(const std::vector<AbstractPipeline*>&)),
_pipelineWidget, SLOT(update(const std::vector<AbstractPipeline*>&)));
this, SIGNAL(updatePipelineWidget(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)),
_pipelineWidget, SLOT(update(const std::vector<DataContainer*>&, const std::vector<AbstractPipeline*>&)));
connect(
_pipelineWidget, SIGNAL(clicked(const QModelIndex&)),
this, SLOT(onPipelineWidgetItemClicked(const QModelIndex&)));
......@@ -129,7 +153,12 @@ namespace campvis {
connect(
_btnShowDataContainerInspector, SIGNAL(clicked()),
this, SLOT(onBtnShowDataContainerInspectorClicked()));
connect(
_btnPipelineFactory, SIGNAL(clicked()),
this, SLOT(onBtnPipelineFactoryClicked()));
_application->s_PipelinesChanged.connect(this, &MainWindow::onPipelinesChanged);
_application->s_DataContainersChanged.connect(this, &MainWindow::onDataContainersChanged);
}
bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
......@@ -142,38 +171,51 @@ namespace campvis {
}