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() {
}
}