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} ...@@ -17,7 +17,11 @@ FILE(GLOB TUMVIS_CORE_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
eventhandlers/*.h eventhandlers/*.h
pipeline/*.h pipeline/*.h
properties/*.h properties/*.h
tools/*.h tools/*.h
glsl/*.vert
glsl/*.frag
glsl/tools/*.vert
glsl/tools/*.frag
) )
#SET(TUMVIS_CORE_SOURCES #SET(TUMVIS_CORE_SOURCES
......
#include "abstractdata.h"
namespace TUMVis {
AbstractData::AbstractData() {
}
AbstractData::~AbstractData() {
}
}
\ No newline at end of file
#ifndef abstractdata_h__ #ifndef ABSTRACTDATA_H__
#define abstractdata_h__ #define ABSTRACTDATA_H__
#include <set>
namespace TUMVis { namespace TUMVis {
...@@ -14,8 +12,9 @@ namespace TUMVis { ...@@ -14,8 +12,9 @@ namespace TUMVis {
*/ */
class AbstractData { class AbstractData {
public: public:
AbstractData() {}; AbstractData();
virtual ~AbstractData() {};
virtual ~AbstractData();
virtual AbstractData* clone() const = 0; virtual AbstractData* clone() const = 0;
...@@ -25,4 +24,4 @@ namespace TUMVis { ...@@ -25,4 +24,4 @@ namespace TUMVis {
} }
#endif // abstractdata_h__ #endif // ABSTRACTDATA_H__
\ No newline at end of file
...@@ -17,14 +17,20 @@ namespace TUMVis { ...@@ -17,14 +17,20 @@ namespace TUMVis {
const DataHandle* DataContainer::addData(const std::string& name, AbstractData* data) { const DataHandle* DataContainer::addData(const std::string& name, AbstractData* data) {
DataHandle* dh = new DataHandle(this, data); DataHandle* dh = new DataHandle(this, data);
tbb::spin_mutex::scoped_lock lock(_localMutex); addDataHandle(name, dh);
_handles.insert(std::make_pair(name, dh));
return dh; return dh;
} }
void DataContainer::addDataHandle(const std::string& name, const DataHandle* dh) { void DataContainer::addDataHandle(const std::string& name, const DataHandle* dh) {
tbb::spin_mutex::scoped_lock lock(_localMutex); 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); DataHandle::addOwner(dh, this);
} }
......
...@@ -96,7 +96,9 @@ namespace TUMVis { ...@@ -96,7 +96,9 @@ namespace TUMVis {
template<typename T> template<typename T>
const T* TUMVis::DataContainer::getTypedData(const std::string& name) const { const T* TUMVis::DataContainer::getTypedData(const std::string& name) const {
const DataHandle* dh = getData(name); 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 "datahandle.h"
#include "tgt/assert.h" #include "tgt/assert.h"
#include "tgt/logmanager.h"
namespace TUMVis { namespace TUMVis {
const std::string DataHandle::loggerCat_ = "TUMVis.core.datastructures.DataHandle"; const std::string DataHandle::loggerCat_ = "TUMVis.core.datastructures.DataHandle";
...@@ -8,10 +9,12 @@ namespace TUMVis { ...@@ -8,10 +9,12 @@ namespace TUMVis {
DataHandle::DataHandle(const DataContainer* owner, AbstractData* data) DataHandle::DataHandle(const DataContainer* owner, AbstractData* data)
: _data(data) : _data(data)
{ {
LDEBUG("DataHandle()");
addOwner(this, owner); addOwner(this, owner);
} }
DataHandle::~DataHandle() { DataHandle::~DataHandle() {
LDEBUG("~DataHandle()");
delete _data; delete _data;
} }
...@@ -25,8 +28,10 @@ namespace TUMVis { ...@@ -25,8 +28,10 @@ namespace TUMVis {
void DataHandle::removeOwner(const DataHandle* handle, const DataContainer* owner) { void DataHandle::removeOwner(const DataHandle* handle, const DataContainer* owner) {
tgtAssert(handle != 0, "Handle must not be 0!"); tgtAssert(handle != 0, "Handle must not be 0!");
tgtAssert(owner != 0, "Owning DataContainer 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()) { if (handle->_owners.empty()) {
delete handle; delete handle;
} }
......
...@@ -45,6 +45,8 @@ namespace TUMVis { ...@@ -45,6 +45,8 @@ namespace TUMVis {
/// \see ImageData::getSubImage /// \see ImageData::getSubImage
virtual ThisType* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const; virtual ThisType* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const;
virtual const WeaklyTypedPointer getWeaklyTypedPointer() const;
/// \see ImageDataLocal::getElementNormalized /// \see ImageDataLocal::getElementNormalized
virtual float getElementNormalized(const tgt::svec3& position, size_t channel) const; virtual float getElementNormalized(const tgt::svec3& position, size_t channel) const;
...@@ -146,29 +148,41 @@ namespace TUMVis { ...@@ -146,29 +148,41 @@ namespace TUMVis {
template<typename BASETYPE, size_t NUMCHANNELS> template<typename BASETYPE, size_t NUMCHANNELS>
GenericImageDataLocal<BASETYPE, NUMCHANNELS>* TUMVis::GenericImageDataLocal<BASETYPE, NUMCHANNELS>::getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const { 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) { if (newSize == _size) {
// nothing has changed, just provide a copy: // nothing has changed, just provide a copy:
return clone(); 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 numBytesPerElement = sizeof(ElementType);
size_t numElements = tgt::hmul(_size); size_t numElements = tgt::hmul(_size);
ElementType* newData = new ElementType[numElements]; ElementType* newData = new ElementType[numElements];
// slice image data into new array // slice image data into new array
size_t index = 0; size_t index = 0;
for (size_t z = llf.z; z < urb.z; ++z) { for (size_t z = llf.z; z <= urb.z; ++z) {
for (size_t y = llf.y; y < urb.y; ++y) { for (size_t y = llf.y; y <= urb.y; ++y) {
size_t offset = llf.x + (y * _size.x) + (z * _size.y * _size.x); size_t offset = llf.x + (y * _size.x) + (z * _size.y * _size.x);
memcpy(newData + index, _data + offset, newSize.x * numBytesPerElement); memcpy(newData + index, _data + offset, newSize.x * numBytesPerElement);
index += newSize.x; 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> 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 "imagedatadisk.h"
#include "tgt/filesystem.h"
namespace TUMVis { namespace TUMVis {
const std::string ImageDataDisk::loggerCat_ = "TUMVis.core.datastructures.ImageDataDisk"; const std::string ImageDataDisk::loggerCat_ = "TUMVis.core.datastructures.ImageDataDisk";
...@@ -15,7 +16,6 @@ namespace TUMVis { ...@@ -15,7 +16,6 @@ namespace TUMVis {
} }
ImageDataDisk::~ImageDataDisk() { ImageDataDisk::~ImageDataDisk() {
} }
ImageDataDisk* ImageDataDisk::getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const { ImageDataDisk* ImageDataDisk::getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const {
...@@ -141,21 +141,6 @@ namespace TUMVis { ...@@ -141,21 +141,6 @@ namespace TUMVis {
break; 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: default:
tgtAssert(false, "Should not reach this!"); tgtAssert(false, "Should not reach this!");
LERROR("Tried to swap endianess with unsupported number of bytes per element (" << numBytesPerElement << ")"); LERROR("Tried to swap endianess with unsupported number of bytes per element (" << numBytesPerElement << ")");
...@@ -180,4 +165,13 @@ namespace TUMVis { ...@@ -180,4 +165,13 @@ namespace TUMVis {
ImageDataDisk* ImageDataDisk::clone() const { ImageDataDisk* ImageDataDisk::clone() const {
return new ImageDataDisk(_url, _dimensionality, _size, _type, _numChannels, _offset, _endianess, _stride); 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 { ...@@ -65,6 +65,19 @@ namespace TUMVis {
*/ */
WeaklyTypedPointer getImageData() const; 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: private:
/** /**
* Calculates the canonical stride for the given image size. * Calculates the canonical stride for the given image size.
......
#include "imagedatagl.h" #include "imagedatagl.h"
#include "tgt/assert.h" #include "tgt/assert.h"
#include "tgt/shadermanager.h"
#include "tgt/tgt_gl.h" #include "tgt/tgt_gl.h"
namespace TUMVis { namespace TUMVis {
...@@ -61,4 +62,20 @@ namespace TUMVis { ...@@ -61,4 +62,20 @@ namespace TUMVis {
LGL_ERROR; 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__ #ifndef IMAGEDATAGL_H__
#define IMAGEDATAGL_H__ #define IMAGEDATAGL_H__
#include "tgt/tgt_gl.h"
#include "tgt/texture.h" #include "tgt/texture.h"
#include "tgt/textureunit.h"
#include "tgt/vector.h" #include "tgt/vector.h"
#include "core/datastructures/imagedata.h" #include "core/datastructures/imagedata.h"
#include "core/datastructures/genericimagedatalocal.h" #include "core/datastructures/genericimagedatalocal.h"
#include "core/tools/weaklytypedpointer.h" #include "core/tools/weaklytypedpointer.h"
namespace tgt {
class Shader;
}
namespace TUMVis { namespace TUMVis {
/** /**
...@@ -54,6 +60,24 @@ namespace TUMVis { ...@@ -54,6 +60,24 @@ namespace TUMVis {
virtual ImageDataGL* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const; 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: protected:
/** /**
......
...@@ -44,6 +44,8 @@ namespace TUMVis { ...@@ -44,6 +44,8 @@ namespace TUMVis {
*/ */
virtual ImageDataLocal* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) const = 0; 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. * 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] * - for \em unsigned integer types, the value range is mapped linearly to [0.0;1.0]
......
...@@ -43,6 +43,9 @@ namespace TUMVis { ...@@ -43,6 +43,9 @@ namespace TUMVis {
case GL_RGBA: case GL_RGBA:
_colorTexture = new tgt::Texture(0, _size, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR); _colorTexture = new tgt::Texture(0, _size, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR);
break; break;