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

Commit 099ffa57 authored by schultezub's avatar schultezub
Browse files

started implementing more sophisticated transfer functions

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@303 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent 2944a868
// ================================================================================================
//
// This file is part of the TUMVis Visualization Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge (christian.szb@in.tum.de)
// Chair for Computer Aided Medical Procedures
// Technische Universitt Mnchen
// Boltzmannstr. 3, 85748 Garching b. Mnchen, Germany
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#include "geometrytransferfunction.h"
#include "tgt/assert.h"
#include "tgt/logmanager.h"
#include "tgt/shadermanager.h"
#include "tgt/texture.h"
#include "tgt/textureunit.h"
#include "core/classification/tfgeometry.h"
namespace TUMVis {
const std::string GeometryTransferFunction::loggerCat_ = "TUMVis.core.classification.GeometryTransferFunction";
GeometryTransferFunction::GeometryTransferFunction(size_t size, const tgt::vec2& intensityDomain /*= tgt::vec2(0.f, 1.f)*/)
: AbstractTransferFunction(tgt::svec3(size, 1, 1), intensityDomain)
{
}
GeometryTransferFunction::~GeometryTransferFunction() {
}
size_t GeometryTransferFunction::getDimensionality() const {
return 1;
}
void GeometryTransferFunction::createTexture() {
delete _texture;
GLenum dataType = GL_UNSIGNED_BYTE;
_texture = new tgt::Texture(_size, GL_RGBA, dataType, tgt::Texture::LINEAR);
_texture->setWrapping(tgt::Texture::CLAMP);
GLubyte* ptr = _texture->getPixelData();
memset(ptr, 0, _texture->getArraySize());
for (std::vector<TFGeometry*>::const_iterator it = _geometries.begin(); it != _geometries.end(); ++it) {
(*it)->rasterize(*_texture);
}
_texture->uploadTexture();
_dirty = false;
}
const std::vector<TFGeometry*>& GeometryTransferFunction::getGeometries() const {
return _geometries;
}
void GeometryTransferFunction::addGeometry(TFGeometry* geometry) {
{
tbb::mutex::scoped_lock lock(_localMutex);
_geometries.push_back(geometry);
}
_dirty = true;
s_changed();
}
}
\ No newline at end of file
// ================================================================================================
//
// This file is part of the TUMVis Visualization Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, 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
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#ifndef GEOMETRYTRANSFERFUNCTION_H__
#define GEOMETRYTRANSFERFUNCTION_H__
#include "core/classification/abstracttransferfunction.h"
#include <vector>
namespace TUMVis {
class TFGeometry;
/**
* A 1D transfer function built from multiple geometries.
*/
class GeometryTransferFunction : public AbstractTransferFunction {
public:
/**
* Creates a new GeometryTransferFunction.
* \param size Size of the transfer function texture
* \param intensityDomain Intensity Domain where the transfer function is mapped to during classification
*/
GeometryTransferFunction(size_t size, const tgt::vec2& intensityDomain = tgt::vec2(0.f, 1.f));
/**
* Destructor, make sure to delete the OpenGL texture beforehand by calling deinit() with a valid OpenGL context!
*/
virtual ~GeometryTransferFunction();
/**
* Returns the dimensionality of the transfer function.
* \return The dimensionality of the transfer function.
*/
virtual size_t getDimensionality() const;
/**
* Gets the list of transfer function geometries.
* \return _geometries
*/
const std::vector<TFGeometry*>& getGeometries() const;
/**
* Adds the given TF geometry to this transfer function.
* \param geometry TF geometry to add
*/
void addGeometry(TFGeometry* geometry);
protected:
/**
* Creates the texture and uploads it to OpenGL.
* Gets called by bind() with the local mutex already acquired.
*/
virtual void createTexture();
std::vector<TFGeometry*> _geometries; ///< The list of transfer function geometries.
static const std::string loggerCat_;
};
}
#endif // GEOMETRYTRANSFERFUNCTION_H__
// ================================================================================================
//
// This file is part of the TUMVis Visualization Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, 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
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#include "tfgeometry.h"
#include "tgt/assert.h"
#include "tgt/texture.h"
#include "tgt/tgt_math.h"
#include <algorithm>
namespace {
tgt::col4 toCol(const tgt::vec4& c) {
return tgt::col4(
static_cast<uint8_t>(255 * c.r),
static_cast<uint8_t>(255 * c.g),
static_cast<uint8_t>(255 * c.b),
static_cast<uint8_t>(255 * c.a));
}
tgt::vec4 toVec(const tgt::col4& c) {
return tgt::vec4(
static_cast<float>(c.r) / 255.f,
static_cast<float>(c.g) / 255.f,
static_cast<float>(c.b) / 255.f,
static_cast<float>(c.a) / 255.f);
}
}
namespace TUMVis {
bool operator< (const TFGeometry::KeyPoint& left, const TFGeometry::KeyPoint& right) {
return left._position < right._position;
}
TFGeometry::TFGeometry(const std::vector<KeyPoint>& keyPoints)
: _keyPoints(keyPoints)
{
std::sort(_keyPoints.begin(), _keyPoints.end());
}
TFGeometry::~TFGeometry() {
}
void TFGeometry::rasterize(tgt::Texture& texture) const {
if (_keyPoints.size() < 2)
return;
int width = texture.getWidth();
float rcpWidth = 1.f / static_cast<float>(width);
// _keyPoints has at least 2 items
std::vector<KeyPoint>::const_iterator start = _keyPoints.begin();
std::vector<KeyPoint>::const_iterator end = _keyPoints.begin()+1;
for (/* already inited */; end != _keyPoints.end(); ++start, ++end) {
size_t startIndex = static_cast<size_t>(tgt::round(start->_position * width));
size_t endIndex = static_cast<size_t>(tgt::round(end->_position * width));
float dist = end->_position - start->_position;
tgt::vec4 startColor = toVec(start->_color);
tgt::vec4 endColor = toVec(end->_color);
for (size_t i = startIndex; i < endIndex; ++i) {
tgt::vec4 result = toVec(texture.texel<tgt::col4>(i));
tgt::vec4 color = tgt::mix(startColor, endColor, tgt::clamp((static_cast<float>(i) * rcpWidth - start->_position) / dist, 0.f, 1.f));
result = tgt::vec4(tgt::mix(color.xyz(), result.xyz(), result.a), result.a + (1.f - result.a) * color.a);
texture.texel<tgt::col4>(i) = toCol(result);
}
}
}
TFGeometry* TFGeometry::createQuad(const tgt::vec2& interval, const tgt::col4& leftColor, const tgt::vec4 rightColor) {
tgtAssert(interval.x >= 0.f && interval.y <= 1.f, "Interval out of bounds");
std::vector<KeyPoint> keyPoints;
keyPoints.push_back(KeyPoint(interval.x, leftColor));
keyPoints.push_back(KeyPoint(interval.y, rightColor));
return new TFGeometry(keyPoints);
}
}
\ No newline at end of file
// ================================================================================================
//
// This file is part of the TUMVis Visualization Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, 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
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#ifndef TFGEOMETRY_H__
#define TFGEOMETRY_H__
#include "tgt/vector.h"
#include <vector>
namespace tgt {
class Texture;
}
namespace TUMVis {
/**
* Defines a single shape for the GeometryTransferFunction class.
* TFGeometry is defined by a sorted list of KeyPoints, each having a position and a color.
*/
class TFGeometry {
public:
struct KeyPoint {
KeyPoint(float position, const tgt::col4& color)
: _position(position)
, _color(color)
{};
float _position;
tgt::col4 _color;
};
/**
* Creates a new TFGeometry
* \param Bounds Bounds of the position of the geometry in texture coordinates.
*/
TFGeometry(const std::vector<KeyPoint>& keyPoints);
/**
* Virtual destructor
*/
virtual ~TFGeometry();
/**
* Rasterizes this transfer function geometry into the given texture
* \param texture Texture to rasterize this geometry into.
*/
void rasterize(tgt::Texture& texture) const;
/**
* Creates a simple quad geometry for the given interval.
* A quad geometry consists of two KeyPoints.
* \param interval Interval the geometry resides in
* \param leftColor Color for left KeyPoint
* \param rightColor Color for right KeyPoint
* \return A TFGeometry modelling a quad with two KeyPoints.
*/
static TFGeometry* createQuad(const tgt::vec2& interval, const tgt::col4& leftColor, const tgt::vec4 rightColor);
protected:
std::vector<KeyPoint> _keyPoints; ///< vector of KeyPoints, KeyPoints are sorted by x-coordinate of the position
};
// ================================================================================================
/**
* Less operator for sorting KeyPoints by their position.
* \param left Left KeyPoint to compare
* \param right RightKeyPoint to compare
* \return left._position < right._position
*/
bool operator< (const TFGeometry::KeyPoint& left, const TFGeometry::KeyPoint& right);
}
#endif // TFGEOMETRY_H__
......@@ -57,4 +57,12 @@ namespace TUMVis {
_transferFunction->deinit();
}
void TransferFunctionProperty::replaceTF(AbstractTransferFunction* tf) {
tgtAssert(tf != 0, "Transfer function must not be 0.");
s_BeforeTFReplace(_transferFunction);
delete _transferFunction;
_transferFunction = tf;
s_AfterTFReplace(_transferFunction);
}
}
......@@ -64,12 +64,23 @@ namespace TUMVis {
*/
AbstractTransferFunction* getTF();
/**
* Replaces the transfer function with \a tf.
* \note First triggers s_BeforeTFReplace, then deletes the current TF, replaces it with
* \a tf and finally triffers s_AfterTFReplace.
* \param tf The new transfer function for this property.
*/
void replaceTF(AbstractTransferFunction* tf);
/**
* Slot being called when \a _transferFunction has changed.
*/
void onTFChanged();
sigslot::signal1<AbstractTransferFunction*> s_BeforeTFReplace;
sigslot::signal1<AbstractTransferFunction*> s_AfterTFReplace;
protected:
AbstractTransferFunction* _transferFunction; ///< Transfer function of this property
......
......@@ -32,6 +32,8 @@
#include "tgt/glcontext.h"
#include "tgt/qt/qtcontextmanager.h"
#include "core/datastructures/imagedataconverter.h"
#include "core/classification/geometrytransferfunction.h"
#include "core/classification/tfgeometry.h"
namespace TUMVis {
......@@ -87,6 +89,11 @@ namespace TUMVis {
_dvrNormal._targetImageID.setValue("drr.output");
_dvrNormal._sourceImageID.setValue("eep.input");
GeometryTransferFunction* dvrTF = new GeometryTransferFunction(128, tgt::vec2(0.f, .05f));
dvrTF->addGeometry(TFGeometry::createQuad(tgt::vec2(.4f, .42f), tgt::col4(255, 0, 0, 255), tgt::col4(255, 0, 0, 255)));
dvrTF->addGeometry(TFGeometry::createQuad(tgt::vec2(.45f, .5f), tgt::col4(0, 255, 0, 255), tgt::col4(0, 255, 0, 255)));
_dvrNormal._transferFunction.replaceTF(dvrTF);
_dvrVM._targetImageID.setValue("dvr.output");
_dvrVM._sourceImageID.setValue("eep.input");
......
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