Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit 9130371f authored by schultezub's avatar schultezub
Browse files

One huge commit including:

Major revisions to the class layout / data structure:
 * Introduced ImageDataConverter interface (still not really happy with the design)
 * Removed support for Int64 and double images from WeaklyTypedPointer
 * Added ImageDataGL::bind()
 * AbstractProcessor::init() method, gets called by AbstractPipeline::init()
 * added VisualizationProcessor

Updated/New processors:
 * fixed MhdImageReader
 * SliceExtractor stub for very simple slice rendering

Various fixes:
 * DataContaier: managing of DataHandle ownership
 * GenericImageDataLocal::getSubImage()
 * ImageDataRenderTarget bindings
 * GenericProperty
 * linking issues with StringUtils

Hence, all this enables the first usable implementation of a specific pipeline:
The SliceVis pipeline combines MhdImageReader and SliceExtractor for a very simple 2D slice rendering

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@188 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent aeacb03d
......@@ -17,7 +17,11 @@ FILE(GLOB TUMVIS_CORE_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
eventhandlers/*.h
pipeline/*.h
properties/*.h
tools/*.h
tools/*.h
glsl/*.vert
glsl/*.frag
glsl/tools/*.vert
glsl/tools/*.frag
)
#SET(TUMVIS_CORE_SOURCES
......
#include "abstractdata.h"
namespace TUMVis {
AbstractData::AbstractData() {
}
AbstractData::~AbstractData() {
}
}
\ No newline at end of file
#ifndef abstractdata_h__
#define abstractdata_h__
#include <set>
#ifndef ABSTRACTDATA_H__
#define ABSTRACTDATA_H__
namespace TUMVis {
......@@ -14,8 +12,9 @@ namespace TUMVis {
*/
class AbstractData {
public:
AbstractData() {};
virtual ~AbstractData() {};
AbstractData();
virtual ~AbstractData();
virtual AbstractData* clone() const = 0;
......@@ -25,4 +24,4 @@ namespace TUMVis {
}
#endif // abstractdata_h__
#endif // ABSTRACTDATA_H__
\ No newline at end of file
......@@ -17,14 +17,20 @@ namespace TUMVis {
const DataHandle* DataContainer::addData(const std::string& name, AbstractData* data) {
DataHandle* dh = new DataHandle(this, data);
tbb::spin_mutex::scoped_lock lock(_localMutex);
_handles.insert(std::make_pair(name, dh));
addDataHandle(name, dh);
return dh;
}
void DataContainer::addDataHandle(const std::string& name, const DataHandle* dh) {
tbb::spin_mutex::scoped_lock lock(_localMutex);
_handles.insert(std::make_pair(name, dh));
std::map<std::string, const DataHandle*>::iterator it = _handles.lower_bound(name);
if (it != _handles.end() && it->first == name) {
DataHandle::removeOwner(it->second, this);
it->second = dh;
}
else {
_handles.insert(it, std::make_pair(name, dh));
}
DataHandle::addOwner(dh, this);
}
......
......@@ -96,7 +96,9 @@ namespace TUMVis {
template<typename T>
const T* TUMVis::DataContainer::getTypedData(const std::string& name) const {
const DataHandle* dh = getData(name);
return dynamic_cast<const T*>(dh);
if (dh != 0)
return dynamic_cast<const T*>(dh->getData());
return 0;
}
}
......
#include "datahandle.h"
#include "tgt/assert.h"
#include "tgt/logmanager.h"
namespace TUMVis {
const std::string DataHandle::loggerCat_ = "TUMVis.core.datastructures.DataHandle";
......@@ -8,10 +9,12 @@ namespace TUMVis {
DataHandle::DataHandle(const DataContainer* owner, AbstractData* data)
: _data(data)
{
LDEBUG("DataHandle()");
addOwner(this, owner);
}
DataHandle::~DataHandle() {
LDEBUG("~DataHandle()");
delete _data;
}
......@@ -25,8 +28,10 @@ namespace TUMVis {
void DataHandle::removeOwner(const DataHandle* handle, const DataContainer* owner) {
tgtAssert(handle != 0, "Handle must not be 0!");
tgtAssert(owner != 0, "Owning DataContainer must not be 0!");
tbb::spin_mutex::scoped_lock lock(handle->_localMutex);
handle->_owners.erase(owner);
{
tbb::spin_mutex::scoped_lock lock(handle->_localMutex);
handle->_owners.erase(owner);
}
if (handle->_owners.empty()) {
delete handle;
}
......
......@@ -45,6 +45,8 @@ namespace TUMVis {
/// \see ImageData::getSubImage
virtual ThisType* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const;
virtual const WeaklyTypedPointer getWeaklyTypedPointer() const;
/// \see ImageDataLocal::getElementNormalized
virtual float getElementNormalized(const tgt::svec3& position, size_t channel) const;
......@@ -146,29 +148,41 @@ namespace TUMVis {
template<typename BASETYPE, size_t NUMCHANNELS>
GenericImageDataLocal<BASETYPE, NUMCHANNELS>* TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const {
tgtAssert(tgt::hand(tgt::lessThan(llf, urb)), "Coordinates in LLF must be component-wise smaller than the ones in URB!");
tgtAssert(tgt::hor(tgt::lessThan(llf, urb)), "Coordinates in LLF must be component-wise smaller than the ones in URB!");
tgt::svec3 newSize = urb - llf;
tgt::svec3 newSize = urb - llf + tgt::svec3(1);
if (newSize == _size) {
// nothing has changed, just provide a copy:
return clone();
}
tgt::bvec3 tmp(tgt::greaterThan(newSize, tgt::svec3(1)));
size_t newDimensionality = 0;
for (size_t i = 0; i < 3; ++i) {
if (tmp[i] == true)
++newDimensionality;
}
size_t numBytesPerElement = sizeof(ElementType);
size_t numElements = tgt::hmul(_size);
ElementType* newData = new ElementType[numElements];
// slice image data into new array
size_t index = 0;
for (size_t z = llf.z; z < urb.z; ++z) {
for (size_t y = llf.y; y < urb.y; ++y) {
for (size_t z = llf.z; z <= urb.z; ++z) {
for (size_t y = llf.y; y <= urb.y; ++y) {
size_t offset = llf.x + (y * _size.x) + (z * _size.y * _size.x);
memcpy(newData + index, _data + offset, newSize.x * numBytesPerElement);
index += newSize.x;
}
}
return new ThisType(_dimensionality, newSize, newData);
return new ThisType(newDimensionality, newSize, newData);
}
template<typename BASETYPE, size_t NUMCHANNELS>
const WeaklyTypedPointer TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getWeaklyTypedPointer() const {
return WeaklyTypedPointer(TypeTraits<BASETYPE, NUMCHANNELS>::weaklyTypedPointerBaseType, NUMCHANNELS, _data);
}
template<typename BASETYPE, size_t NUMCHANNELS>
......
#include "imagedataconverter.h"
namespace TUMVis {
const std::string ImageDataConverter::loggerCat_ = "TUMVis.core.datastructures.ImageDataConverter";
template<>
TUMVis::ImageDataLocal* ImageDataConverter::convert(const ImageDataDisk* source) {
WeaklyTypedPointer wtp = source->getImageData();
#define DISPATCH_CONVERSION(numChannels) \
if (source->getNumChannels() == (numChannels)) { \
switch (wtp._baseType) { \
case WeaklyTypedPointer::UINT8: \
return convertToGenericLocal<uint8_t, (numChannels)>(source); \
case WeaklyTypedPointer::INT8: \
return convertToGenericLocal<int8_t, (numChannels)>(source); \
case WeaklyTypedPointer::UINT16: \
return convertToGenericLocal<uint16_t, (numChannels)>(source); \
case WeaklyTypedPointer::INT16: \
return convertToGenericLocal<int16_t, (numChannels)>(source); \
case WeaklyTypedPointer::UINT32: \
return convertToGenericLocal<uint32_t, (numChannels)>(source); \
case WeaklyTypedPointer::INT32: \
return convertToGenericLocal<int32_t, (numChannels)>(source); \
case WeaklyTypedPointer::FLOAT: \
return convertToGenericLocal<float, (numChannels)>(source); \
default: \
tgtAssert(false, "Should not reach this - wrong base data type!"); \
return 0; \
} \
}
DISPATCH_CONVERSION(1)
else DISPATCH_CONVERSION(2)
else DISPATCH_CONVERSION(3)
else DISPATCH_CONVERSION(4)
else {
tgtAssert(false, "Should not reach this - wrong number of channel!");
return 0;
}
}
template<>
TUMVis::ImageDataGL* ImageDataConverter::convert(const ImageDataDisk* source) {
WeaklyTypedPointer wtp = source->getImageData();
ImageDataGL* toReturn = new ImageDataGL(source->getDimensionality(), source->getSize(), wtp);
delete wtp._pointer;
return toReturn;
}
template<>
TUMVis::ImageDataGL* ImageDataConverter::convert(const ImageDataLocal* source) {
return new ImageDataGL(source->getDimensionality(), source->getSize(), source->getWeaklyTypedPointer());
}
}
\ No newline at end of file
#ifndef IMAGEDATACONVERTER_H__
#define IMAGEDATACONVERTER_H__
#include "core/datastructures/imagedatadisk.h"
#include "core/datastructures/imagedatalocal.h"
#include "core/datastructures/genericimagedatalocal.h"
#include "core/datastructures/imagedatagl.h"
#include <string>
namespace TUMVis {
/**
* Static class offering conversion between differen ImageData types
*/
struct ImageDataConverter {
public:
template<class TO>
static TO* tryConvert(const ImageData* source);
template<class FROM, class TO>
static TO* convert(const FROM* source);
protected:
template<typename BASETYPE, size_t NUMCHANNELS>
static GenericImageDataLocal<BASETYPE, NUMCHANNELS>* convertToGenericLocal(const ImageDataDisk* source);
static const std::string loggerCat_;
};
template<class FROM, class TO>
TO* TUMVis::ImageDataConverter::convert(const FROM* source) {
tgtAssert(false, "Conversion not implemented.");
return 0;
}
template<class TO>
TO* TUMVis::ImageDataConverter::tryConvert(const ImageData* source) {
// test source image type via dynamic cast
if (const ImageDataDisk* tester = dynamic_cast<const ImageDataDisk*>(source)) {
return convert<ImageDataDisk, TO>(tester);
}
if (const ImageDataLocal* tester = dynamic_cast<const ImageDataLocal*>(source)) {
return convert<ImageDataLocal, TO>(tester);
}
return 0;
}
template<>
TUMVis::ImageDataLocal* ImageDataConverter::convert(const ImageDataDisk* source);
template<>
TUMVis::ImageDataGL* ImageDataConverter::convert(const ImageDataDisk* source);
template<>
TUMVis::ImageDataGL* ImageDataConverter::convert(const ImageDataLocal* source);
template<typename BASETYPE, size_t NUMCHANNELS>
TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>* TUMVis::ImageDataConverter::convertToGenericLocal(const ImageDataDisk* source) {
if (TypeTraits<BASETYPE, NUMCHANNELS>::basetypeSize != WeaklyTypedPointer::numBytes(source->getBaseType())) {
LERROR("Basetype size does not match.");
return 0;
}
if (NUMCHANNELS != source->getNumChannels()) {
LERROR("Number of channels does not match.");
return 0;
}
// TODO: check (un)signed int/float?
WeaklyTypedPointer wtp = source->getImageData();
return new GenericImageDataLocal<BASETYPE, NUMCHANNELS>(
source->getDimensionality(),
source->getSize(),
reinterpret_cast<typename TypeTraits<BASETYPE, NUMCHANNELS>::ElementType*>(wtp._pointer));
}
}
#endif // IMAGEDATACONVERTER_H__
#include "imagedatadisk.h"
#include "tgt/filesystem.h"
namespace TUMVis {
const std::string ImageDataDisk::loggerCat_ = "TUMVis.core.datastructures.ImageDataDisk";
......@@ -15,7 +16,6 @@ namespace TUMVis {
}
ImageDataDisk::~ImageDataDisk() {
}
ImageDataDisk* ImageDataDisk::getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const {
......@@ -141,21 +141,6 @@ namespace TUMVis {
break;
}
case WeaklyTypedPointer::UINT64:
case WeaklyTypedPointer::INT64: {
int64_t* tmp = reinterpret_cast<int64_t*>(data);
for (size_t i = 0; i < numElements; ++i)
tmp[i] = EndianHelper::swapEndian(tmp[i]);
break;
}
case WeaklyTypedPointer::DOUBLE: {
double* tmp = reinterpret_cast<double*>(data);
for (size_t i = 0; i < numElements; ++i)
tmp[i] = EndianHelper::swapEndian(tmp[i]);
break;
}
default:
tgtAssert(false, "Should not reach this!");
LERROR("Tried to swap endianess with unsupported number of bytes per element (" << numBytesPerElement << ")");
......@@ -180,4 +165,13 @@ namespace TUMVis {
ImageDataDisk* ImageDataDisk::clone() const {
return new ImageDataDisk(_url, _dimensionality, _size, _type, _numChannels, _offset, _endianess, _stride);
}
WeaklyTypedPointer::BaseType ImageDataDisk::getBaseType() const {
return _type;
}
size_t ImageDataDisk::getNumChannels() const {
return _numChannels;
}
}
\ No newline at end of file
......@@ -65,6 +65,19 @@ namespace TUMVis {
*/
WeaklyTypedPointer getImageData() const;
/**
* Returns the base type of the data
* \return _type
*/
WeaklyTypedPointer::BaseType getBaseType() const;
/**
* Returns the number of channels per element
* \return _numChannels
*/
size_t getNumChannels() const;
private:
/**
* Calculates the canonical stride for the given image size.
......
#include "imagedatagl.h"
#include "tgt/assert.h"
#include "tgt/shadermanager.h"
#include "tgt/tgt_gl.h"
namespace TUMVis {
......@@ -61,4 +62,20 @@ namespace TUMVis {
LGL_ERROR;
}
void ImageDataGL::bind() const {
_texture->bind();
}
void ImageDataGL::bind(const tgt::TextureUnit& texUnit) const {
texUnit.activate();
_texture->bind();
}
void ImageDataGL::bind(tgt::Shader* shader, const tgt::TextureUnit& texUnit, const std::string& texUniform /*= "_texture"*/, const std::string& textureParametersUniform /*= "_textureParameters"*/) const {
bind(texUnit);
shader->setUniform(texUniform, texUnit.getUnitNumber());
shader->setUniform(textureParametersUniform + "._size", tgt::vec2(_size.xy()));
shader->setUniform(textureParametersUniform + "._sizeRCP", tgt::vec2(1.f) / tgt::vec2(_size.xy()));
}
}
\ No newline at end of file
#ifndef IMAGEDATAGL_H__
#define IMAGEDATAGL_H__
#include "tgt/tgt_gl.h"
#include "tgt/texture.h"
#include "tgt/textureunit.h"
#include "tgt/vector.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/genericimagedatalocal.h"
#include "core/tools/weaklytypedpointer.h"
namespace tgt {
class Shader;
}
namespace TUMVis {
/**
......@@ -54,6 +60,24 @@ namespace TUMVis {
virtual ImageDataGL* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const;
/**
* Binds the texture without activating a texture unit.
*/
void bind() const;
/**
* Activates the texture unit \a texUnit and binds the texture.
* \param texUnit Texture unit to activate
*/
void bind(const tgt::TextureUnit& texUnit) const;
void bind(
tgt::Shader* shader,
const tgt::TextureUnit& texUnit,
const std::string& texUniform = "_texture",
const std::string& textureParametersUniform = "_textureParameters") const;
protected:
/**
......
......@@ -44,6 +44,8 @@ namespace TUMVis {
*/
virtual ImageDataLocal* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const = 0;
virtual const WeaklyTypedPointer getWeaklyTypedPointer() const = 0;
/**
* Returns the normalized value of the element at the given position and channel.
* - for \em unsigned integer types, the value range is mapped linearly to [0.0;1.0]
......
......@@ -43,6 +43,9 @@ namespace TUMVis {
case GL_RGBA:
_colorTexture = new tgt::Texture(0, _size, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR);
break;
case GL_RGBA8:
_colorTexture = new tgt::Texture(0, _size, GL_RGBA, GL_RGBA8, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR);
break;
case GL_RGBA16:
_colorTexture = new tgt::Texture(0, _size, GL_RGBA, GL_RGBA16, GL_UNSIGNED_SHORT, tgt::Texture::LINEAR);
break;
......@@ -110,8 +113,8 @@ namespace TUMVis {
_colorTexture->bind();
}
void ImageDataRenderTarget::bindColorTexture(GLint texUnit) const {
glActiveTexture(texUnit);
void ImageDataRenderTarget::bindColorTexture(const tgt::TextureUnit& texUnit) const {
texUnit.activate();
_colorTexture->bind();
}
......@@ -119,16 +122,16 @@ namespace TUMVis {
_depthTexture->bind();
}
void ImageDataRenderTarget::bindDepthTexture(GLint texUnit) const {
glActiveTexture(texUnit);
void ImageDataRenderTarget::bindDepthTexture(const tgt::TextureUnit& texUnit) const {
texUnit.activate();
_depthTexture->bind();
}
void ImageDataRenderTarget::bind(tgt::Shader* shader, GLint colorTexUnit /*= GL_TEXTURE0*/, GLint depthTexUnit /*= GL_TEXTURE1*/, const std::string& colorTexUniform /*= "_colorTexture"*/, const std::string& depthTexUniform /*= "_depthTexture"*/, const std::string& textureParametersUniform /*= "_textureParameters"*/) const {
void ImageDataRenderTarget::bind(tgt::Shader* shader, const tgt::TextureUnit& colorTexUnit, const tgt::TextureUnit& depthTexUnit, const std::string& colorTexUniform /*= "_colorTexture"*/, const std::string& depthTexUniform /*= "_depthTexture"*/, const std::string& textureParametersUniform /*= "_textureParameters"*/) const {
bindColorTexture(colorTexUnit);
bindDepthTexture(depthTexUnit);
shader->setUniform(colorTexUniform, colorTexUnit - GL_TEXTURE0);
shader->setUniform(depthTexUniform, depthTexUnit - GL_TEXTURE0);
shader->setUniform(colorTexUniform, colorTexUnit.getUnitNumber());
shader->setUniform(depthTexUniform, depthTexUnit.getUnitNumber());
shader->setUniform(textureParametersUniform + "._size", tgt::vec2(_size.xy()));
shader->setUniform(textureParametersUniform + "._sizeRCP", tgt::vec2(1.f) / tgt::vec2(_size.xy()));
}
......
......@@ -3,6 +3,7 @@
#include "tgt/framebufferobject.h"
#include "tgt/texture.h"
#include "tgt/textureunit.h"
#include "tgt/vector.h"
#include "core/datastructures/imagedata.h"
......@@ -73,18 +74,18 @@ namespace TUMVis {
* Activates the texture unit \a texUnit and binds the color texture.
* \param texUnit Texture unit to activate
*/
void bindColorTexture(GLint texUnit) const;
void bindColorTexture(const tgt::TextureUnit& texUnit) const;
/**
* Activates the texture unit \a texUnit and binds the depth texture.
* \param texUnit Texture unit to activate
*/
void bindDepthTexture(GLint texUnit) const;
void bindDepthTexture(const tgt::TextureUnit& texUnit) const;
void bind(
tgt::Shader* shader,
GLint colorTexUnit = GL_TEXTURE0,
GLint depthTexUnit = GL_TEXTURE1,
const tgt::TextureUnit& colorTexUnit,
const tgt::TextureUnit& depthTexUnit,
const std::string& colorTexUniform = "_colorTexture",
const std::string& depthTexUniform = "_depthTexture",
const std::string& textureParametersUniform = "_textureParameters") const;
......
#include "abstractpipeline.h"
#include "tgt/exception.h"
namespace TUMVis {
const std::string AbstractPipeline::loggerCat_ = "TUMVis.core.datastructures.AbstractPipeline";
......@@ -16,9 +17,14 @@ namespace TUMVis {
void AbstractPipeline::init() {
// initialize all processors:
// for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
// (*it)->initGL();
// }
for (std::vector<AbstractProcessor*>::iterator it = _processors.begin(); it != _processors.end(); ++it) {
try {
(*it)->init();
}
catch (tgt::Exception& e) {
LERROR("Caught Exception during initialization of processor: " << e.what());
}
}
}
}
......@@ -6,7 +6,6 @@ namespace TUMVis {
AbstractProcessor::AbstractProcessor() {
}
AbstractProcessor::~AbstractProcessor() {
......@@ -34,4 +33,8 @@ namespace TUMVis {
return _properties;
}
void AbstractProcessor::init() {
}
}
......@@ -44,7 +44,7 @@ namespace TUMVis {
*
* \sa AbstractPipeline
*/