11.3.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 9f0c3ac5 authored by schultezub's avatar schultezub

#37: further work on improving the DataContainerInspectorWidget

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@436 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 9de33c78
......@@ -45,6 +45,7 @@ namespace campvis {
DataContainerInspectorCanvas::DataContainerInspectorCanvas(QWidget* parent /*= 0*/)
: tgt::QtThreadedCanvas("DataContainer Inspector", tgt::ivec2(640, 480), tgt::GLCanvas::RGBA_BUFFER, parent, true)
, p_currentSlice("CurrentSlice", "Slice", -1, -1, -1)
, _dataContainer(0)
, _paintShader(0)
, _quad(0)
......@@ -93,93 +94,25 @@ namespace campvis {
delete _quad;
}
void DataContainerInspectorCanvas::setDataContainer(DataContainer* dataContainer) {
if (_dataContainer != 0) {
_dataContainer->s_dataAdded.disconnect(this);
}
{
tbb::mutex::scoped_lock lock(_localMutex);
_dataContainer = dataContainer;
if (_dataContainer != 0) {
_handles = _dataContainer->getHandlesCopy();
}
}
if (_dataContainer != 0) {
_dataContainer->s_dataAdded.connect(this, &DataContainerInspectorCanvas::onDataContainerDataAdded);
}
invalidate();
}
QSize DataContainerInspectorCanvas::sizeHint() const {
return QSize(640, 480);
}
void DataContainerInspectorCanvas::onDataContainerDataAdded(const std::string& name, const DataHandle& dh) {
{
tbb::mutex::scoped_lock lock(_localMutex);
// check whether DataHandle is already existing
std::map<std::string, DataHandle>::iterator lb = _handles.lower_bound(name);
if (lb == _handles.end() || lb->first != name) {
// not existant -> insert
_handles.insert(std::make_pair(name, DataHandle(dh)));
}
else {
// existant -> replace
lb->second = DataHandle(dh);
}
}
invalidate();
}
void DataContainerInspectorCanvas::paint() {
tbb::mutex::scoped_lock lock(_localMutex);
std::vector<const tgt::Texture*> textures;
for (std::map<std::string, DataHandle>::iterator it = _handles.begin(); it != _handles.end(); ++it) {
if (const ImageData* img = dynamic_cast<const ImageData*>(it->second.getData())) {
if (const ImageRepresentationRenderTarget* imgRT = img->getRepresentation<ImageRepresentationRenderTarget>(false)) {
for (size_t i = 0; i < imgRT->getNumColorTextures(); ++i)
textures.push_back(imgRT->getColorTexture(i));
textures.push_back(imgRT->getDepthTexture());
}
else if (const ImageRepresentationGL* imgGL = img->getRepresentation<ImageRepresentationGL>()) {
textures.push_back(imgGL->getTexture());
}
}
}
if (_textures.empty())
return;
glPushAttrib(GL_ALL_ATTRIB_BITS);
glViewport(0, 0, size_.x, size_.y);
glClearColor(0.7f, 0.7f, 0.7f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
LGL_ERROR;
if (textures.empty()) {
glPopAttrib();
return;
}
// update window title
int memsize = 0;
for (size_t i = 0; i < textures.size(); ++i) {
memsize += textures[i]->getSizeOnGPU();
}
memsize /= 1024 * 1024;
/*QString title = tr("DataContainer Inspector: %1 Textures (%2 mb)").arg(textures.size()).arg(memsize);
if (parentWidget() && parentWidget()->parentWidget())
parentWidget()->parentWidget()->setWindowTitle(title);
else
setWindowTitle(title);*/
// update layout dimensions
_numTiles.x = ceil(sqrt(static_cast<float>(textures.size())));
_numTiles.y = ceil(static_cast<float>(textures.size()) / _numTiles.x);
_numTiles.x = ceil(sqrt(static_cast<float>(_textures.size())));
_numTiles.y = ceil(static_cast<float>(_textures.size()) / _numTiles.x);
_quadSize = size_ / _numTiles;
_paintShader->activate();
......@@ -191,25 +124,16 @@ namespace campvis {
_paintShader->setUniform("_texture2d._texture", unit2d.getUnitNumber());
_paintShader->setUniform("_texture3d._texture", unit3d.getUnitNumber());
if (_renderFullscreen) {
if(_selectedTexture >= 0 && _selectedTexture < (int)textures.size()) {
tgt::mat4 scaleMatrix = tgt::mat4::createScale(tgt::vec3(size_, 1.f));
_paintShader->setUniform("_modelMatrix", scaleMatrix);
paintTexture2D(textures[_selectedTexture], unit2d, unit3d);
}
}
else {
for (int y = 0; y < _numTiles.y; ++y) {
for (int x = 0; x < _numTiles.x; ++x) {
int index = (_numTiles.x * y) + x;
if (index >= static_cast<int>(textures.size()))
break;
tgt::mat4 scaleMatrix = tgt::mat4::createScale(tgt::vec3(_quadSize, 1.f));
tgt::mat4 translation = tgt::mat4::createTranslation(tgt::vec3(_quadSize.x * x, _quadSize.y * y, 0.f));
_paintShader->setUniform("_modelMatrix", translation * scaleMatrix);
paintTexture2D(textures[index], unit2d, unit3d);
}
for (int y = 0; y < _numTiles.y; ++y) {
for (int x = 0; x < _numTiles.x; ++x) {
int index = (_numTiles.x * y) + x;
if (index >= static_cast<int>(_textures.size()))
break;
tgt::mat4 scaleMatrix = tgt::mat4::createScale(tgt::vec3(_quadSize, 1.f));
tgt::mat4 translation = tgt::mat4::createTranslation(tgt::vec3(_quadSize.x * x, _quadSize.y * y, 0.f));
_paintShader->setUniform("_modelMatrix", translation * scaleMatrix);
paintTexture(_textures[index], unit2d, unit3d);
}
}
......@@ -218,7 +142,7 @@ namespace campvis {
glPopAttrib();
}
void DataContainerInspectorCanvas::paintTexture2D(const tgt::Texture* texture, const tgt::TextureUnit& unit2d, const tgt::TextureUnit& unit3d) {
void DataContainerInspectorCanvas::paintTexture(const tgt::Texture* texture, const tgt::TextureUnit& unit2d, const tgt::TextureUnit& unit3d) {
_paintShader->setIgnoreUniformLocationError(true);
if (texture->getDimensions().z == 1) {
......@@ -235,7 +159,7 @@ namespace campvis {
unit3d.activate();
texture->bind();
_paintShader->setUniform("_is3d", true);
_paintShader->setUniform("_sliceNumber", _currentSlice);
_paintShader->setUniform("_sliceNumber", p_currentSlice.getValue());
_paintShader->setUniform("_texture3d._size", tgt::vec3(texture->getDimensions()));
_paintShader->setUniform("_texture3d._sizeRCP", tgt::vec3(1.f) / tgt::vec3(texture->getDimensions()));
}
......@@ -299,4 +223,58 @@ namespace campvis {
}
}
void DataContainerInspectorCanvas::onDataContainerChanged(const QString& key, QtDataHandle dh) {
{
tbb::mutex::scoped_lock lock(_localMutex);
// check whether DataHandle is already existing
std::map<QString, QtDataHandle>::iterator lb = _handles.lower_bound(key);
if (lb == _handles.end() || lb->first != key) {
// not existant -> do nothing
}
else {
// existant -> replace
lb->second = QtDataHandle(dh);
// update _textures array
updateTextures();
}
}
invalidate();
}
void DataContainerInspectorCanvas::setDataHandles(const std::vector< std::pair<QString, QtDataHandle> >& handles) {
{
tbb::mutex::scoped_lock lock(_localMutex);
_handles.clear();
for (std::vector< std::pair<QString, QtDataHandle> >::const_iterator it = handles.begin(); it != handles.end(); ++it)
_handles.insert(*it);
updateTextures();
}
invalidate();
}
void DataContainerInspectorCanvas::updateTextures() {
_textures.clear();
for (std::map<QString, QtDataHandle>::iterator it = _handles.begin(); it != _handles.end(); ++it) {
if (const ImageData* img = dynamic_cast<const ImageData*>(it->second.getData())) {
if (const ImageRepresentationRenderTarget* imgRT = img->getRepresentation<ImageRepresentationRenderTarget>(false)) {
for (size_t i = 0; i < imgRT->getNumColorTextures(); ++i)
_textures.push_back(imgRT->getColorTexture(i));
_textures.push_back(imgRT->getDepthTexture());
}
else if (const ImageRepresentationGL* imgGL = img->getRepresentation<ImageRepresentationGL>()) {
_textures.push_back(imgGL->getTexture());
}
}
}
}
void DataContainerInspectorCanvas::onPropertyChanged(const AbstractProperty* prop) {
HasPropertyCollection::onPropertyChanged(prop);
invalidate();
}
}
\ No newline at end of file
......@@ -38,6 +38,11 @@
#include "tgt/qt/qtthreadedcanvas.h"
#include "tbb/include/tbb/mutex.h"
#include "application/gui/qtdatahandle.h"
#include "core/properties/propertycollection.h"
#include "core/properties/numericproperty.h"
#include "core/properties/transferfunctionproperty.h"
#include "core/tools/opengljobprocessor.h"
namespace tgt {
......@@ -53,7 +58,7 @@ namespace campvis {
class DataHandle;
class FaceGeometry;
class DataContainerInspectorCanvas : public tgt::QtThreadedCanvas, tgt::Painter, public tgt::EventListener, public sigslot::has_slots<> {
class DataContainerInspectorCanvas : public tgt::QtThreadedCanvas, tgt::Painter, public tgt::EventListener, public HasPropertyCollection {
Q_OBJECT;
public:
......@@ -80,11 +85,7 @@ namespace campvis {
*/
void deinit();
/**
* Set the DataContainer this widget is inspecting.
* \param dataContainer The DataContainer this widget shall inspect, may be 0.
*/
void setDataContainer(DataContainer* dataContainer);
void setDataHandles(const std::vector< std::pair<QString, QtDataHandle> >& handles);
/**
* Size hint for the default window size
......@@ -111,8 +112,20 @@ namespace campvis {
* \param e Mouse event arguments
*/
virtual void wheelEvent(tgt::MouseEvent* e);
/**
* Slot getting called when one of the observed properties changed and notifies its observers.
* \param prop Property that emitted the signal
*/
virtual void onPropertyChanged(const AbstractProperty* prop);
private slots:
/**
* Slot being called when a QtDataHandle has been added to the DataContainer.
* \param key Name of the QtDataHandle
* \param dh The added QtDataHandle
*/
void onDataContainerChanged(const QString& key, QtDataHandle dh);
protected:
/**
......@@ -123,6 +136,12 @@ namespace campvis {
*/
void onDataContainerDataAdded(const std::string& name, const DataHandle& dh);
/**
* Updates the textures vector.
* \note Only call with acquired lock!!
*/
void updateTextures();
/**
* To be called when the canvas is invalidated, issues new paint job.
*/
......@@ -133,15 +152,19 @@ namespace campvis {
* Binds the texture to the shader, sets the uniforms and renders the quad.
* \param texture The texture to render.
*/
void paintTexture2D(const tgt::Texture* texture, const tgt::TextureUnit& unit2d, const tgt::TextureUnit& unit3d);
void paintTexture(const tgt::Texture* texture, const tgt::TextureUnit& unit2d, const tgt::TextureUnit& unit3d);
/**
* Creates the quad used for rendering the textures.
*/
void createQuad();
std::map<QString, QtDataHandle> _handles;
std::vector<const tgt::Texture*> _textures;
IntProperty p_currentSlice;
DataContainer* _dataContainer; ///< The DataContainer this widget is inspecting
std::map<std::string, DataHandle> _handles; ///< Local copy of the DataHandles to inspect
tbb::mutex _localMutex; ///< Mutex protecting the local members
tgt::Shader* _paintShader; ///< GLSL shader for rendering the textures
......
......@@ -47,9 +47,6 @@ namespace campvis {
DataContainerInspectorWidget::DataContainerInspectorWidget(QWidget* parent)
: QWidget(parent)
, _quad(0)
, _paintShader(0)
, _currentSlice(-1)
, _dataContainer(0)
, _selectedDataHandle(0)
, _dctWidget(0)
......@@ -74,10 +71,8 @@ namespace campvis {
_dataContainer = dataContainer;
_dctWidget->update(dataContainer);
updateInfoWidget();
if (_canvas != 0)
_canvas->setDataContainer(_dataContainer);
if (_dataContainer != 0) {
_dataContainer->s_dataAdded.connect(this, &DataContainerInspectorWidget::onDataContainerDataAdded);
}
......@@ -125,6 +120,8 @@ namespace campvis {
setLayout(_mainLayout);
_dctWidget = new DataContainerTreeWidget(this);
_dctWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
_dctWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
_mainLayout->addWidget(_dctWidget);
_infoWidget = new QWidget(this);
......@@ -156,6 +153,12 @@ namespace campvis {
connect(
_dctWidget->getTreeModel(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(onDCTWidgetDataChanged(const QModelIndex&, const QModelIndex&)));
connect(
_dctWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
this, SLOT(onDCTWidgetSelectionModelSelectionChanged(const QItemSelection&, const QItemSelection&)));
connect(
this, SIGNAL(dataContainerChanged(const QString&, QtDataHandle)),
_canvas, SLOT(onDataContainerChanged(const QString&, QtDataHandle)));
connect(
this, SIGNAL(dataContainerChanged(const QString&, QtDataHandle)),
_dctWidget->getTreeModel(), SLOT(onDataContainerChanged(const QString&, QtDataHandle)));
......@@ -174,6 +177,23 @@ namespace campvis {
_lblLocalMemoryFootprint->setText("Local Memory Footprint: ");
_lblVideoMemoryFootprint->setText("Video Memory Footprint: ");
}
// update DataHandles for the DataContainerInspectorCanvas
const QItemSelection& selectedItems = _dctWidget->selectionModel()->selection();
std::vector< std::pair<QString, QtDataHandle> > handles;
for (QItemSelection::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) {
const QModelIndexList& indices = it->indexes();
for (QModelIndexList::const_iterator index = indices.begin(); index != indices.end(); ++index) {
if (! index->isValid())
continue;
QVariant item = index->data(Qt::UserRole);
QModelIndex idxName = index->sibling(index->row(), 0);
handles.push_back(std::make_pair(idxName.data(Qt::DisplayRole).toString(), item.value<QtDataHandle>()));
}
}
_canvas->setDataHandles(handles);
}
QString DataContainerInspectorWidget::humanizeBytes(size_t numBytes) const {
......@@ -203,4 +223,8 @@ namespace campvis {
_canvas->deinit();
}
void DataContainerInspectorWidget::onDCTWidgetSelectionModelSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
updateInfoWidget();
}
}
\ No newline at end of file
......@@ -34,6 +34,7 @@
#include "tgt/painter.h"
#include "tgt/qt/qtcontextmanager.h"
#include "tgt/qt/qtthreadedcanvas.h"
#include "tbb/include/tbb/mutex.h"
#include "application/gui/qtdatahandle.h"
#include "application/gui/datacontainerinspectorcanvas.h"
......@@ -46,6 +47,7 @@
#include <QString>
class QModelIndex;
class QItemSelection;
namespace tgt {
class Texture;
......@@ -120,6 +122,13 @@ namespace campvis {
*/
void onDCTWidgetDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
/**
* Slot to be called when the selection in the DataContainerTreeWidget has changed.
* \param selected selected items
* \param deselected deselected items
*/
void onDCTWidgetSelectionModelSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
protected:
/**
* Setup the GUI stuff
......@@ -138,15 +147,13 @@ namespace campvis {
*/
QString humanizeBytes(size_t numBytes) const;
tgt::Shader* _paintShader;
FaceGeometry* _quad; ///< Quad used for rendering
int _currentSlice; ///< current slice if rendering a 3D image fullscreen, render MIP if negative
DataContainer* _dataContainer; ///< The DataContainer this widget is inspecting
QtDataHandle _selectedDataHandle; ///< The currently selected QtDataHandle
QString _selectedDataHandleName; ///< The name of the currently selected QtDataHandle
tgt::ivec2 _selectedIndex; ///< row/column of selected item
tbb::mutex _localMutex;
DataContainerTreeWidget* _dctWidget; ///< The TreeWidget showing the DataHandles in _dataContainer
DataContainerInspectorCanvas* _canvas; ///< The OpenGL canvas for rendering the DataContainer's contents
......
......@@ -171,17 +171,13 @@ namespace campvis {
delete _intensityHistogram;
_intensityHistogram = 0;
if (_imageHandle.getData() != 0) {
const ImageData* id = dynamic_cast<const ImageData*>(_imageHandle.getData());
if (id != 0) {
if(const ImageRepresentationLocal* idl = id->getRepresentation<ImageRepresentationLocal>()) {
float mins = _intensityDomain.x;
float maxs = _intensityDomain.y;
size_t numBuckets = std::min(WeaklyTypedPointer::numBytes(idl->getWeaklyTypedPointer()._baseType) << 8, 512U);
_intensityHistogram = new IntensityHistogramType(&mins, &maxs, &numBuckets);
tbb::parallel_for(tbb::blocked_range<size_t>(0, idl->getNumElements()), IntensityHistogramGenerator(idl, _intensityHistogram));
}
}
ImageRepresentationLocal::ScopedRepresentation repLocal(_imageHandle);
if (repLocal != 0) {
float mins = _intensityDomain.x;
float maxs = _intensityDomain.y;
size_t numBuckets = std::min(WeaklyTypedPointer::numBytes(repLocal->getWeaklyTypedPointer()._baseType) << 8, 512U);
_intensityHistogram = new IntensityHistogramType(&mins, &maxs, &numBuckets);
tbb::parallel_for(tbb::blocked_range<size_t>(0, repLocal->getNumElements()), IntensityHistogramGenerator(repLocal, _intensityHistogram));
}
_dirtyHistogram = false;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment