In January 2021 we will introduce a 10 GB quota for project repositories. Higher limits for individual projects will be available on request. Please see https://doku.lrz.de/display/PUBLIC/GitLab for more information.

Commit dba5d2aa authored by schultezub's avatar schultezub

#37: further work on improving the DataContainerInspectorWidget debugging...

#37: further work on improving the DataContainerInspectorWidget debugging features, now offering automatic updates, transfer functions and more

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@437 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 9f0c3ac5
......@@ -34,9 +34,11 @@ out vec4 out_Color;
#include "tools/texture2d.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"
uniform Texture2D _texture2d;
uniform Texture3D _texture3d;
uniform TransferFunction1D _transferFunction;
uniform bool _is3d;
uniform int _sliceNumber;
uniform vec4 _color;
......@@ -50,17 +52,29 @@ void main() {
// perform MIP
out_Color = vec4(0.0);
for (float slice = 0.0; slice < 1.0; slice += _texture3d._sizeRCP.z) {
out_Color = max(out_Color, getElement3DNormalized(_texture3d, vec3(ex_TexCoord.xy, slice)));
out_Color = max(out_Color, lookupTF(_transferFunction, getElement3DNormalized(_texture3d, vec3(ex_TexCoord.xy, slice)).a));
}
}
else {
// render the corresponding slice
vec3 coord = vec3(ex_TexCoord.xy, (_sliceNumber + 0.5) / (_texture3d._size.z));
out_Color = getElement3DNormalized(_texture3d, coord);
out_Color = lookupTF(_transferFunction, getElement3DNormalized(_texture3d, coord).a);
}
}
else {
out_Color = getElement2DNormalized(_texture2d, ex_TexCoord.xy);
vec4 texel = getElement2DNormalized(_texture2d, ex_TexCoord.xy);
if (_texture2d._numChannels == 1) {
out_Color = lookupTF(_transferFunction, texel.a);
}
else if (_texture2d._numChannels == 3) {
out_Color = vec4(abs(texel.rgb), 1.0);
}
else if (_texture2d._numChannels == 4) {
out_Color = (abs(texel) - vec4(_transferFunction._intensityDomain.x)) / (_transferFunction._intensityDomain.y - _transferFunction._intensityDomain.x);
}
else {
out_Color = vec4(0.1, 0.6, 1.0, 0.75);
}
}
// mix with fancy checkerboard pattern:
......
......@@ -39,6 +39,7 @@
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/facegeometry.h"
#include "core/tools/job.h"
#include "core/classification/simpletransferfunction.h"
namespace campvis {
......@@ -46,6 +47,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)
, p_transferFunction("TransferFunction", "Transfer Function", new SimpleTransferFunction(64))
, _dataContainer(0)
, _paintShader(0)
, _quad(0)
......@@ -65,6 +67,9 @@ namespace campvis {
std::cerr << "glewInit failed, error: " << glewGetErrorString(err) << std::endl;
exit(EXIT_FAILURE);
}
addProperty(&p_currentSlice);
addProperty(&p_transferFunction);
}
DataContainerInspectorCanvas::~DataContainerInspectorCanvas() {
......@@ -120,7 +125,8 @@ namespace campvis {
tgt::mat4 projection = tgt::mat4::createOrtho(0, size_.x, 0, size_.y, -1, 1);
_paintShader->setUniform("_projectionMatrix", projection);
tgt::TextureUnit unit2d, unit3d;
tgt::TextureUnit tfUnit, unit2d, unit3d;
p_transferFunction.getTF()->bind(_paintShader, tfUnit);
_paintShader->setUniform("_texture2d._texture", unit2d.getUnitNumber());
_paintShader->setUniform("_texture3d._texture", unit3d.getUnitNumber());
......@@ -151,6 +157,7 @@ namespace campvis {
_paintShader->setUniform("_is3d", false);
_paintShader->setUniform("_texture2d._size", tgt::vec2(texture->getDimensions().xy()));
_paintShader->setUniform("_texture2d._sizeRCP", tgt::vec2(1.f) / tgt::vec2(texture->getDimensions().xy()));
_paintShader->setUniform("_texture2d._numChannels", static_cast<int>(texture->getNumChannels()));
}
else {
// clamp current slice to texture size, since this can't be done in event handler:
......@@ -162,6 +169,7 @@ namespace campvis {
_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()));
_paintShader->setUniform("_texture2d._numChannels", static_cast<int>(texture->getNumChannels()));
}
_paintShader->setIgnoreUniformLocationError(false);
......@@ -258,6 +266,7 @@ namespace campvis {
void DataContainerInspectorCanvas::updateTextures() {
_textures.clear();
int maxSlices = 1;
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)) {
......@@ -267,9 +276,14 @@ namespace campvis {
}
else if (const ImageRepresentationGL* imgGL = img->getRepresentation<ImageRepresentationGL>()) {
_textures.push_back(imgGL->getTexture());
maxSlices = std::max(maxSlices, imgGL->getTexture()->getDimensions().z);
}
}
}
if (maxSlices == 1)
maxSlices = -1;
p_currentSlice.setMaxValue(maxSlices);
}
void DataContainerInspectorCanvas::onPropertyChanged(const AbstractProperty* prop) {
......
......@@ -119,6 +119,9 @@ namespace campvis {
*/
virtual void onPropertyChanged(const AbstractProperty* prop);
IntProperty p_currentSlice;
TransferFunctionProperty p_transferFunction; ///< Transfer function
private slots:
/**
* Slot being called when a QtDataHandle has been added to the DataContainer.
......@@ -161,8 +164,6 @@ namespace campvis {
std::map<QString, QtDataHandle> _handles;
std::vector<const tgt::Texture*> _textures;
IntProperty p_currentSlice;
DataContainer* _dataContainer; ///< The DataContainer this widget is inspecting
tbb::mutex _localMutex; ///< Mutex protecting the local members
......
......@@ -48,9 +48,9 @@ namespace campvis {
DataContainerInspectorWidget::DataContainerInspectorWidget(QWidget* parent)
: QWidget(parent)
, _dataContainer(0)
, _selectedDataHandle(0)
, _dctWidget(0)
, _canvas(0)
, _pcWidget(0)
, _mainLayout(0)
, _infoWidget(0)
, _infoWidgetLayout(0)
......@@ -87,32 +87,6 @@ namespace campvis {
return QSize(640, 480);
}
void DataContainerInspectorWidget::onDCTWidgetItemClicked(const QModelIndex& index) {
if (index.isValid()) {
// Yak, this is so ugly - another reason why GUI programming sucks...
QVariant item = index.data(Qt::UserRole);
_selectedDataHandle = item.value<QtDataHandle>();
QModelIndex idxName = index.sibling(index.row(), 0);
_selectedDataHandleName = idxName.data(Qt::DisplayRole).toString();
_selectedIndex = tgt::ivec2(index.row(), index.column());
}
else {
_selectedDataHandle = QtDataHandle(0);
_selectedDataHandleName = "";
_selectedIndex = tgt::ivec2(-1, -1);
}
updateInfoWidget();
}
void DataContainerInspectorWidget::onDCTWidgetDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) {
if (topLeft.row() <= _selectedIndex.x && topLeft.column() <= _selectedIndex.y && bottomRight.row() >= _selectedIndex.x && bottomRight.column() >= _selectedIndex.y) {
onDCTWidgetItemClicked(topLeft.sibling(_selectedIndex.x, _selectedIndex.y));
}
}
void DataContainerInspectorWidget::setupGUI() {
_mainLayout = new QHBoxLayout();
......@@ -144,15 +118,13 @@ namespace campvis {
_canvas = new DataContainerInspectorCanvas(_infoWidget);
_infoWidgetLayout->addWidget(_canvas, 1);
_pcWidget = new PropertyCollectionWidget(_infoWidget);
_pcWidget->updatePropCollection(_canvas);
_infoWidgetLayout->addWidget(_pcWidget);
_mainLayout->addWidget(_infoWidget, 1);
qRegisterMetaType<QtDataHandle>("QtDataHandle");
connect(
_dctWidget, SIGNAL(clicked(const QModelIndex&)),
this, SLOT(onDCTWidgetItemClicked(const QModelIndex&)));
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&)));
......@@ -165,34 +137,47 @@ namespace campvis {
}
void DataContainerInspectorWidget::updateInfoWidget() {
if (_selectedDataHandle.getData() != 0) {
_lblTimestamp->setText("Timestamp: " + QString::number(_selectedDataHandle.getTimestamp()));
_lblName->setText("Name: " + _selectedDataHandleName);
_lblLocalMemoryFootprint->setText("Local Memory Footprint: " + humanizeBytes(_selectedDataHandle.getData()->getLocalMemoryFootprint()));
_lblVideoMemoryFootprint->setText("Video Memory Footprint: " + humanizeBytes(_selectedDataHandle.getData()->getVideoMemoryFootprint()));
}
else {
_lblTimestamp->setText("Timestamp: ");
_lblName->setText("Name: ");
_lblLocalMemoryFootprint->setText("Local Memory Footprint: ");
_lblVideoMemoryFootprint->setText("Video Memory Footprint: ");
// get the selection from the tree widget
const QModelIndexList& indices = _dctWidget->selectionModel()->selectedRows();
std::vector< std::pair<QString, QtDataHandle> > handles;
float _localFootprint = 0.f;
float _videoFootprint = 0.f;
// iterate through the indices of the selection
for (QModelIndexList::const_iterator index = indices.begin(); index != indices.end(); ++index) {
if (! index->isValid())
continue;
// get DataHandle and Handle name
QVariant item = index->data(Qt::UserRole);
QtDataHandle handle = item.value<QtDataHandle>();
QModelIndex idxName = index->sibling(index->row(), 0);
// only consider non-empty DataHandles
if (handle.getData() != 0) {
handles.push_back(std::make_pair(idxName.data(Qt::DisplayRole).toString(), handle));
_localFootprint += handle.getData()->getLocalMemoryFootprint();
_videoFootprint += handle.getData()->getVideoMemoryFootprint();
}
}
// 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;
// update labels
if (handles.size() == 1) {
_lblName->setText("Name: " + handles.front().first);
_lblTimestamp->setText("Timestamp: " + QString::number(handles.front().second.getTimestamp()));
QVariant item = index->data(Qt::UserRole);
QModelIndex idxName = index->sibling(index->row(), 0);
_canvas->p_transferFunction.getTF()->setImageHandle(handles.front().second);
}
else {
_lblName->setText(QString::number(handles.size()) + " DataHandles selected");
_lblTimestamp->setText("Timestamp: n/a");
handles.push_back(std::make_pair(idxName.data(Qt::DisplayRole).toString(), item.value<QtDataHandle>()));
}
_canvas->p_transferFunction.getTF()->setImageHandle(0);
}
_lblLocalMemoryFootprint->setText("Local Memory Footprint: " + humanizeBytes(_localFootprint));
_lblVideoMemoryFootprint->setText("Video Memory Footprint: " + humanizeBytes(_videoFootprint));
// update DataHandles for the DataContainerInspectorCanvas
_canvas->setDataHandles(handles);
}
......
......@@ -38,6 +38,7 @@
#include "application/gui/qtdatahandle.h"
#include "application/gui/datacontainerinspectorcanvas.h"
#include "application/gui/properties/propertycollectionwidget.h"
#include "core/tools/opengljobprocessor.h"
#include <QLabel>
......@@ -109,18 +110,6 @@ namespace campvis {
void dataContainerChanged(const QString&, QtDataHandle);
private slots:
/**
* Slot to be called by the DataContainerTreeWidget when the selected item changes.
* \param index Index of the selected item
*/
void onDCTWidgetItemClicked(const QModelIndex& index);
/**
* Slot to be called by the DataContainerTreeWidget when the data has changed.
* \param topLeft
* \param bottomRight
*/
void onDCTWidgetDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
/**
* Slot to be called when the selection in the DataContainerTreeWidget has changed.
......@@ -148,14 +137,10 @@ namespace campvis {
QString humanizeBytes(size_t numBytes) const;
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
PropertyCollectionWidget* _pcWidget;
QHBoxLayout* _mainLayout; ///< Layout for this widget
QWidget* _infoWidget; ///< Widget showing the information about the selected QtDataHandle
......
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