The name of the initial branch for new projects is now "main" instead of "master". Existing projects remain unchanged. More information: https://doku.lrz.de/display/PUBLIC/GitLab

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

Added implementation for IEEE SciVis 14 submission on "Predicate-based...

Added implementation for IEEE SciVis 14 submission on "Predicate-based Focus-and-Context Visualization for 3D Ultrasound" (Schulte zu Berge et al.) to advancedusvis module:
* Introducing AbstractPointPredicate base for point predicates and various derived classes
* Introducing PointPredicateHistogram, its corresponding PointPredicateHistogramProperty and the PointPredicateHistogramPropertyWidget
* Introducing PointPredicateEvaluator, PointPredicateRaycaster, PointPredicateVolumeExplorer and ScanlineDistributionComputation processors
* Added demo/reference pipeline implementations for the four data sets from the paper: Achilles tendon, shoulder and two carotid arteries
parent 76156663
......@@ -3,18 +3,27 @@
IF(ModuleEnabled)
# Source files:
FILE(GLOB ThisModSources RELATIVE ${ModulesDir}
modules/advancedusvis/datastructures/*.cpp
modules/advancedusvis/pipelines/*.cpp
modules/advancedusvis/processors/*.cpp
modules/advancedusvis/properties/*.cpp
)
# Header files (including GLSL files so that they'll appear in VS projects)
FILE(GLOB ThisModHeaders RELATIVE ${ModulesDir}
modules/advancedusvis/datastructures/*.frag
modules/advancedusvis/glsl/*.frag
modules/advancedusvis/glsl/*.vert
modules/advancedusvis/pipelines/*.h
modules/advancedusvis/processors/*.h
modules/advancedusvis/properties/*.h
)
# campvis-application files
FILE(GLOB ThisModApplicationSources RELATIVE ${ModulesDir} modules/advancedusvis/widgets/*.cpp)
FILE(GLOB ThisModApplicationHeaders RELATIVE ${ModulesDir} modules/advancedusvis/widgets/*.h)
FILE(GLOB ThisModApplicationToBeMocced RELATIVE ${ModulesDir} modules/advancedusvis/widgets/*.h)
SET(ThisModShaderDirectories "modules/advancedusvis/glsl")
SET(ThisModDependencies vis io preprocessing)
ENDIF(ModuleEnabled)
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "pointpredicate.h"
#include "tgt/shadermanager.h"
#include "core/tools/stringutils.h"
namespace campvis {
AbstractPointPredicate::AbstractPointPredicate(const std::string& inputVariable, const std::string& name, const std::string& title, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: MetaProperty(name, title, invalidationLevel)
, p_enable("Enable", "Enable Predicate", true)
, p_importance("Importance", "Importance", 1.f, 0.f, 5.f, .1f, 1)
, p_color("Color", "Predicate-Specific Color", tgt::vec2(0.f), tgt::vec2(0.f), tgt::vec2(1.f), tgt::vec2(.01f, .1f), tgt::ivec2(2, 1))
, p_intensityHack("IntensityHack", "Intensity Hack", 0.f, 0.f, 1.f, 1)
, _inputVariable(inputVariable)
, _importanceUniformName("_vpImportance" + _name)
, _colorUniformName("_vpColor" + _name)
, _intensityHackUniformName("_vpIntensityHack" + _name)
{
tgtAssert(inputVariable.find_first_of(" \t\r\n") == std::string::npos, "Input variable must not contain whitespace!");
tgtAssert(name.find_first_of(" \t\r\n") == std::string::npos, "Predicate name must not contain whitespace!");
p_enable.setVisible(false);
p_importance.setVisible(false);
p_color.setVisible(false);
p_intensityHack.setVisible(false);
addProperty(&p_enable);
addProperty(&p_importance);
addProperty(&p_color);
addProperty(&p_intensityHack);
}
AbstractPointPredicate::~AbstractPointPredicate() {
}
std::string AbstractPointPredicate::getGlslHeader() const {
std::string toReturn;
toReturn += "uniform float " + _importanceUniformName + ";\n";
toReturn += "uniform float " + _intensityHackUniformName + ";\n";
toReturn += "uniform vec2 " + _colorUniformName + ";\n";
return toReturn;
}
void AbstractPointPredicate::setupShader(tgt::Shader* shader) const {
shader->setUniform(_importanceUniformName, p_importance.getValue());
shader->setUniform(_colorUniformName, p_color.getValue());
shader->setUniform(_intensityHackUniformName, p_intensityHack.getValue());
}
const std::string& AbstractPointPredicate::getImportanceUniformName() const {
return _importanceUniformName;
}
const std::string& AbstractPointPredicate::getColorUniformName() const {
return _colorUniformName;
}
const std::string& AbstractPointPredicate::getIntensityHackUniformName() const {
return _intensityHackUniformName;
}
bool AbstractPointPredicate::isEnabled() const {
return p_enable.getValue();
}
const std::string& AbstractPointPredicate::getInputVariable() const {
return _inputVariable;
}
void AbstractPointPredicate::onPropertyChanged(const AbstractProperty* prop) {
if (prop == &p_enable) {
if (p_enable.getValue()) {
for (size_t i = 0; i < _properties.size(); ++i) {
_properties[i]->setVisible(true);
}
}
else {
for (size_t i = 0; i < _properties.size(); ++i) {
if (_properties[i] != &p_enable)
_properties[i]->setVisible(false);
}
}
s_enabledChanged();
}
else {
s_configurationChanged();
}
MetaProperty::onPropertyChanged(prop);
}
// ================================================================================================
AndCombinedPointPredicate::AndCombinedPointPredicate(const std::string& name, const std::string& title, const std::vector<AbstractPointPredicate*>& predicates)
: AbstractPointPredicate("", name, title)
, _predicates(predicates)
{
for (size_t i = 0; i < _predicates.size(); ++i) {
addProperty(_predicates[i]);
}
}
AndCombinedPointPredicate::~AndCombinedPointPredicate() {
for (size_t i = 0; i < _predicates.size(); ++i)
delete _predicates[i];
}
std::string AndCombinedPointPredicate::getGlslHeader() const {
std::string toReturn = AbstractPointPredicate::getGlslHeader();
for (size_t i = 0; i < _predicates.size(); ++i)
toReturn += _predicates[i]->getGlslHeader();
return toReturn;
}
std::string AndCombinedPointPredicate::getPredicateEvaluationGlslString() const {
std::string toReturn = "(" + _predicates.front()->getPredicateEvaluationGlslString();
for (size_t i = 1; i < _predicates.size(); ++i)
toReturn += " && " + _predicates[i]->getPredicateEvaluationGlslString();
toReturn += ")";
return toReturn;
}
void AndCombinedPointPredicate::setupShader(tgt::Shader* shader) const {
for (size_t i = 0; i < _predicates.size(); ++i)
_predicates[i]->setupShader(shader);
AbstractPointPredicate::setupShader(shader);
}
// ================================================================================================
RangePointPredicate::RangePointPredicate(const std::string& inputVariable, const std::string& name, const std::string& title, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: AbstractPointPredicate(inputVariable, name, title, invalidationLevel)
, p_range("Range", "Range", tgt::vec2(0.f, 1.f), tgt::vec2(0.f), tgt::vec2(1.f), tgt::vec2(.01f), tgt::ivec2(2))
, _rangeUniformName("_vpRange" + _name)
{
addProperty(&p_range);
}
RangePointPredicate::~RangePointPredicate() {
}
std::string RangePointPredicate::getGlslHeader() const {
std::string toReturn = AbstractPointPredicate::getGlslHeader();
toReturn += "uniform vec2 " + _rangeUniformName + ";\n";
return toReturn;
}
std::string RangePointPredicate::getPredicateEvaluationGlslString() const {
return "(" + _inputVariable + " >= " + _rangeUniformName + ".x && " + _inputVariable + " <= " + _rangeUniformName + ".y)";
}
void RangePointPredicate::setupShader(tgt::Shader* shader) const {
AbstractPointPredicate::setupShader(shader);
shader->setUniform(_rangeUniformName, p_range.getValue());
}
// ================================================================================================
LabelBitPointPredicate::LabelBitPointPredicate(const std::string& inputVariable, const std::string& name, const std::string& title, int invalidationLevel /*= AbstractProcessor::INVALID_RESULT*/)
: AbstractPointPredicate(inputVariable, name, title, invalidationLevel)
, p_bit("Bit", "Bit in Label Image", 0, 0, 16)
, _bitUniformName("_vpBit" + _name)
{
addProperty(&p_bit);
}
LabelBitPointPredicate::~LabelBitPointPredicate() {
}
std::string LabelBitPointPredicate::getGlslHeader() const {
std::string toReturn = AbstractPointPredicate::getGlslHeader();
toReturn += "uniform int " + _bitUniformName + ";\n";
return toReturn;
}
std::string LabelBitPointPredicate::getPredicateEvaluationGlslString() const {
return "(bitfieldExtract(" + _inputVariable + ", " + _bitUniformName + ", 1) != 0U)";
}
void LabelBitPointPredicate::setupShader(tgt::Shader* shader) const {
AbstractPointPredicate::setupShader(shader);
shader->setUniform(_bitUniformName, p_bit.getValue());
}
}
\ No newline at end of file
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#ifndef POINTPREDICATE_H__
#define POINTPREDICATE_H__
#include "core/properties/floatingpointproperty.h"
#include "core/properties/genericproperty.h"
#include "core/properties/metaproperty.h"
#include <string>
namespace tgt {
class Shader;
}
namespace campvis {
class AbstractPointPredicate : public MetaProperty {
public:
AbstractPointPredicate(const std::string& inputVariable, const std::string& name, const std::string& title, int invalidationLevel = AbstractProcessor::INVALID_RESULT);
virtual ~AbstractPointPredicate();
/**
* Returns the GLSL header needed to apply this voxel predicate (i.e. uniforms etc.)
* \return The needed GLSL header for this voxel predicate.
*/
virtual std::string getGlslHeader() const;
/**
* Returns the GLSL string to evaluate the predicate.
* \return The GLSL string to evaluate the predicate.
*/
virtual std::string getPredicateEvaluationGlslString() const = 0;
/**
* Sets up the given shader for this voxel predicate (i.e. sets the uniforms)
* \param shader Shader to set up.
*/
virtual void setupShader(tgt::Shader* shader) const;
/**
* Returns the GLSL uniform name of this predicate's importance value.
* \return _importanceUniformName
*/
const std::string& getImportanceUniformName() const;
/**
* Returns the GLSL uniform name of this predicate's color value.
* \return _colorUniformName
*/
const std::string& getColorUniformName() const;
/**
* Returns the GLSL uniform name of this predicate's color value.
* \return _colorUniformName
*/
const std::string& getIntensityHackUniformName() const;
/**
* Returns, whether this predicate is enabled.
* \return p_enable.getValue()
*/
bool isEnabled() const;
/**
* Returns the input variable
* \return _inputVariable
*/
const std::string& getInputVariable() const;
/// Signal emitted when this predicate's configuration (importance, color, ...) has changed
sigslot::signal0<> s_configurationChanged;
/// Signal emitted when this predicate's enabled state has changed
sigslot::signal0<> s_enabledChanged;
BoolProperty p_enable;
FloatProperty p_importance;
Vec2Property p_color;
FloatProperty p_intensityHack;
protected:
/**
* Callback when one of the predicate's properties has changed, issues the
* corresponding changed signal to the outside.
* \param prop Property that has changed
*/
virtual void onPropertyChanged(const AbstractProperty* prop);
std::string _inputVariable;
const std::string _importanceUniformName;
const std::string _colorUniformName;
const std::string _intensityHackUniformName;
};
// ================================================================================================
class AndCombinedPointPredicate : public AbstractPointPredicate {
public:
AndCombinedPointPredicate(const std::string& name, const std::string& title, const std::vector<AbstractPointPredicate*>& predicates);
virtual ~AndCombinedPointPredicate();
virtual std::string getGlslHeader() const;
virtual std::string getPredicateEvaluationGlslString() const;
virtual void setupShader(tgt::Shader* shader) const;
protected:
std::vector<AbstractPointPredicate*> _predicates;
};
// ================================================================================================
class RangePointPredicate : public AbstractPointPredicate {
public:
RangePointPredicate(const std::string& inputVariable, const std::string& name, const std::string& title, int invalidationLevel = AbstractProcessor::INVALID_RESULT);
virtual ~RangePointPredicate();
virtual std::string getGlslHeader() const;
virtual std::string getPredicateEvaluationGlslString() const;
virtual void setupShader(tgt::Shader* shader) const;
Vec2Property p_range;
protected:
const std::string _rangeUniformName;
};
// ================================================================================================
class LabelBitPointPredicate : public AbstractPointPredicate {
public:
LabelBitPointPredicate(const std::string& inputVariable, const std::string& name, const std::string& title, int invalidationLevel = AbstractProcessor::INVALID_RESULT);
virtual ~LabelBitPointPredicate();
virtual std::string getGlslHeader() const;
virtual std::string getPredicateEvaluationGlslString() const;
virtual void setupShader(tgt::Shader* shader) const;
IntProperty p_bit;
protected:
const std::string _bitUniformName;
};
}
#endif // POINTPREDICATE_H__
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
//
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "pointpredicatehistogram.h"
#include "core/tools/stringutils.h"
namespace campvis {
const std::string PointPredicateHistogram::loggerCat_ = "CAMPVis.modules.advancedusvis.PointPredicateHistogram";;
PointPredicateHistogram::PointPredicateHistogram() {
}
PointPredicateHistogram::~PointPredicateHistogram() {
}
void PointPredicateHistogram::addPredicate(AbstractPointPredicate* predicateToAdd) {
predicateToAdd->p_importance.setValue(_predicates.empty() ? 1.f : 0.f);
predicateToAdd->s_configurationChanged.connect(this, &PointPredicateHistogram::onPredicateConfigurationChanged);
predicateToAdd->s_enabledChanged.connect(this, &PointPredicateHistogram::onPredicateEnabledChanged);
_predicates.push_back(predicateToAdd);
s_headerChanged();
}
void PointPredicateHistogram::removePredicate(size_t i) {
tgtAssert(i < _predicates.size(), "Index out of bounds!");
_predicates[i]->s_configurationChanged.disconnect(this);
_predicates[i]->s_enabledChanged.disconnect(this);
_predicates[i]->deinit();
delete _predicates[i];
_predicates.erase(_predicates.begin() + i);
s_headerChanged();
}
void PointPredicateHistogram::resetPredicates() {
float imp = 1.f / _predicates.size();
for (size_t i = 0; i < _predicates.size(); ++i) {
_predicates[i]->p_importance.setValue(imp);
_predicates[i]->p_color.setValue(tgt::vec2(0.f));
}
s_configurationChanged();
}
std::vector<AbstractPointPredicate*>& PointPredicateHistogram::getPredicates() {
return _predicates;
}
std::string PointPredicateHistogram::getGlslHeader() const {
std::string toReturn;
for (size_t i = 0; i < _predicates.size(); ++i) {
toReturn += _predicates[i]->getGlslHeader();
}
toReturn +=
"vec4 performPredicateBasedShading(in float intensity, in float gradientMagnitude, in float gradientAngle, float viewAngle, in float snr, in float vesselness, in float confidence, in uint label) {\n"
" float impCount = 0.0;\n"
" float hueCount = 0.0;\n"
" vec4 impSum = vec4(0.0, 0.0, 0.0, 1.0);\n";
for (size_t i = 0; i < _predicates.size(); ++i) {
if (_predicates[i]->isEnabled()) {
toReturn +=
" if " + _predicates[i]->getPredicateEvaluationGlslString() + " {\n"
" float imp = pow(" + _predicates[i]->getImportanceUniformName() + " * " + StringUtils::toString(_predicates.size()) + ", 2.0);\n"
" impSum.x += " + _predicates[i]->getColorUniformName() + ".x * " + _predicates[i]->getColorUniformName() + ".y * imp;\n"
" impSum.y += " + _predicates[i]->getColorUniformName() + ".y * imp;\n"
" impSum.z += " + _predicates[i]->getIntensityHackUniformName() + ";\n"
" impSum.a += 1.0;\n"
" hueCount += " + _predicates[i]->getColorUniformName() + ".y * imp;\n"
" impCount += imp;\n"
" }\n";
}
}
toReturn +=
" if (impCount > 0.0) {\n"
" impSum.x /= hueCount;\n"
" impSum.y /= impCount;\n"
" impSum.a = impCount / impSum.a;\n"
" }\n"
" else\n"
" impSum = vec4(0.0);\n"
" return impSum;\n"
"}\n\n";
toReturn +=
"uint computePredicateBitfield(in float intensity, in float gradientMagnitude, in float gradientAngle, float viewAngle, in float snr, in float vesselness, in float confidence, in uint label) {\n"
" uint toReturn = 0U;\n";
for (size_t i = 0; i < _predicates.size(); ++i) {
toReturn +=
" if " + _predicates[i]->getPredicateEvaluationGlslString() + " {\n"
" toReturn = bitfieldInsert(toReturn, 0xFFFFFFFF, " + StringUtils::toString(i) + ", 1);\n"
" }\n";
}
toReturn +=
" return toReturn;\n"
"}\n\n";
return toReturn;
}
void PointPredicateHistogram::setupRenderShader(tgt::Shader* shader) const {
for (size_t i = 0; i < _predicates.size(); ++i) {
//if (_predicates[i]->isEnabled())
_predicates[i]->setupShader(shader);
}
}
void PointPredicateHistogram::onPredicateConfigurationChanged() {
s_configurationChanged();
}
void PointPredicateHistogram::onPredicateEnabledChanged() {
s_headerChanged();
}
void PointPredicateHistogram::lock() {
for (size_t i = 0; i < _predicates.size(); ++i)
_predicates[i]->lockAllProperties();