Starting from 2021-07-01, all LRZ GitLab users will be required to explicitly accept the GitLab Terms of Service. Please see the detailed information at https://doku.lrz.de/display/PUBLIC/GitLab and make sure that your projects conform to the requirements.

Commit 2c4854f4 authored by schultezub's avatar schultezub
Browse files

plenty of work on TUMVis

git-svn-id: https://camplinux.in.tum.de/svn/campvis/trunk@163 bb408c1c-ae56-11e1-83d9-df6b3e0c105e
parent ecfc27df
......@@ -4,15 +4,26 @@ INCLUDE(../cmake/commonconf.cmake)
MESSAGE(STATUS "Configuring TUMVis Core")
SET(TUMVIS_CORE_SOURCES
application/tumvis.cpp
application/tumvispainter.cpp
FILE(GLOB TUMVIS_CORE_SOURCES
application/*.cpp
datastructures/*.cpp
)
SET(TUMVIS_CORE_HEADERS
application/tumvispainter.h
FILE(GLOB TUMVIS_CORE_HEADERS
application/*.h
datastructures/*.h
)
#SET(TUMVIS_CORE_SOURCES
# application/tumvis.cpp
# application/tumvispainter.cpp
# datastructures/
#)
#SET(TUMVIS_CORE_HEADERS
# application/tumvispainter.h
#)
#
# Qt related stuff:
#
......
......@@ -6,13 +6,20 @@
using namespace TUMVis;
/**
* TUMVis main function, application entry point
*
* \param argc number of passed arguments
* \param argv vector of arguments
* \return 0 if program exited successfully
**/
int main(int argc, char** argv) {
tgt::QtApplication* app = new tgt::QtApplication(argc, argv);
tgt::QtCanvas* canvas = new tgt::QtCanvas("TUMVis");
app->addCanvas(canvas);
app->init();
app->init();
tgt::Camera camera;
canvas->setCamera(&camera);
......
......@@ -16,7 +16,7 @@ namespace TUMVis {
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
getCamera()->look();
glColor3f(1.f, 0.f, 0.f);
tgt::Sphere sphere(1.f, 64, 32);
tgt::Sphere sphere(_size, 64, 32);
sphere.render();
}
......@@ -25,6 +25,7 @@ namespace TUMVis {
getCanvas()->getGLFocus();
}
glViewport(0, 0, size.x, size.y);
getCamera()->setRatio((float) size.x/size.y);
}
void TumVisPainter::init() {
......
#include "tgt/logmanager.h"
#include "tgt/glcanvas.h"
#include "tgt/painter.h"
#include "tgt/event/eventhandler.h"
namespace TUMVis {
/**
* Painter class for TUMVis
*
**/
* \todo
*/
class TumVisPainter : public tgt::Painter {
public:
TumVisPainter(tgt::GLCanvas* canvas);
......@@ -17,6 +20,8 @@ namespace TUMVis {
private:
static const std::string loggerCat_;
float _size;
};
}
#ifndef abstractdata_h__
#define abstractdata_h__
#include <set>
namespace TUMVis {
class DataHandle;
/**
* Abstract base class for data handled by a DataHandle and stored in a DataContainer.
*
* \todo
*/
class AbstractData {
public:
AbstractData();
virtual ~AbstractData() {};
virtual AbstractData* clone() const = 0;
protected:
};
}
#endif // abstractdata_h__
#include "datacontainer.h"
namespace TUMVis {
const std::string DataContainer::loggerCat_ = "TUMVis.core.datastructures.DataContainer";
DataContainer::DataContainer() {
}
DataContainer::~DataContainer() {
// remove ownership op all owned DataHandles
for (std::map<std::string, const DataHandle*>::iterator it = _handles.begin(); it != _handles.end(); ++it) {
DataHandle::removeOwner(it->second, this);
}
_handles.clear();
}
const DataHandle* DataContainer::addData(const std::string& name, AbstractData* data) {
DataHandle* dh = new DataHandle(this, data);
_handles.insert(std::make_pair(name, dh));
return dh;
}
void DataContainer::addDataHandle(const std::string& name, const DataHandle* dh) {
_handles.insert(std::make_pair(name, dh));
DataHandle::addOwner(dh, this);
}
bool DataContainer::hasData(const std::string& name) const {
return (_handles.find(name) != _handles.end());
}
const DataHandle* DataContainer::getData(const std::string& name) const {
std::map<std::string, const DataHandle*>::const_iterator it = _handles.find(name);
if (it == _handles.end())
return 0;
else
return it->second;
}
}
\ No newline at end of file
#include "datastructures/abstractdata.h"
#include "datastructures/datahandle.h"
#include <string>
#include <map>
namespace TUMVis {
/**
* A DataContainer manages instances of AbstractData and offers access to them via string identifiers (names/keys).
* Therefore, it stores them in DataHandles which take ownership of the AbstractData instance. Hence,
* as soon as an AbstractData instance is added to a DataContainer via DataContainer::addData(), its
* lifetime is managed by the wrapping DataHandle instance.
* Because the DataHandles are stored as const handles, the underlying data cannot be changed anymore. This
* also ensures (hopefully) that nobody can do messy things, such as adding the same AbstractData instance
* twice to a DataContainer (which would really mess up the lifetime management!).
*
* \todo If the original data changes, the other objects accessing that very DataHandle might want to
* get notified of the change. Hence, some observer pattern might be useful.
*/
class DataContainer {
public:
/**
* Creates a new empty DataContainer
*/
DataContainer();
/**
* Destructor of the DataContainer. Will disconnect all DataHandles from this container.
*/
~DataContainer();
/**
* Adds the given AbstractData instance \a data, accessible by the key \name, to this DataContainer.
* In doing so, the DataContainer (respectively the created DataHandle) takes ownership of \a data
* and will manage its lifetime. So don't even dare to delete \a data yourself!
*
* \param name Key for accessing the DataHandle within this DataContainer
* \param data DataHandle to add.
* \return The DataHandle which was created for \a data.
*/
const DataHandle* addData(const std::string& name, AbstractData* data);
/**
* Adds the given DataHandle \a data, accessible by the key \name, to this DataContainer.
* Already existing DataHandles with the same key will be removed from this DataContainer.
*
* \param name Key for accessing the DataHandle within this DataContainer
* \param data DataHandle to add.
*/
void addDataHandle(const std::string& name, const DataHandle* dh);
/**
* Checks whether this DataContainer contains a DataHandle with the given name.
*
* \param name Key of the DataHandle to search for
* \return true, if this DataContainer contains a DataHandle with the given name.
*/
bool hasData(const std::string& name) const;
/**
* Returns the DataHandle with the given name from this container.
* If no such DataHandle exists, this method returns 0.
*
* \param name Key of the DataHandle to search for
* \return The stored DataHandle with the given name, 0 if no such DataHandle exists.
*/
const DataHandle* getData(const std::string& name) const;
private:
std::map<std::string, const DataHandle*> _handles;
static const std::string loggerCat_;
};
}
#include "datahandle.h"
namespace TUMVis {
const std::string DataHandle::loggerCat_ = "TUMVis.core.datastructures.DataHandle";
DataHandle::DataHandle(const DataContainer* owner, AbstractData* data)
: _data(data)
{
addOwner(this, owner);
}
DataHandle::DataHandle(const DataHandle& /*rhs*/) {
// IMHO a DataHandle does not need a copy-constructor - in particular it could be a bad idea to use
// one, because it does not exactly what you expect. If you really need a copy-constructor, please
// make sure to implement it correctly. From my current point of view, you at least need to clone
// _data but then you still don't know anything about any owners of the new DataHandle.
LERROR("Do you really want to use the copy-constructor? If so, please implement it yourself, but beware: This might be dangerous...");
}
DataHandle& DataHandle::operator=(const DataHandle& /*rhs*/) {
// IMHO a DataHandle does not need an assignment-operator - in particular it could be a bad idea to use
// one, because it does not exactly what you expect. If you really need an assignment-operator, please
// make sure to implement it correctly.
LERROR("Do you really want to use the assignment-operator? If so, please implement it yourself, but beware: This might be dangerous...");
return *this; //< of course this is evil - just want to make the compiler happy...
}
DataHandle::~DataHandle() {
delete _data;
}
void DataHandle::addOwner(const DataHandle* handle, const DataContainer* owner) {
handle->_owners.insert(owner);
}
void DataHandle::removeOwner(const DataHandle* handle, const DataContainer* owner) {
handle->_owners.erase(owner);
if (handle->_owners.empty()) {
delete handle;
}
}
const AbstractData* DataHandle::getData() const {
return _data;
}
AbstractData* DataHandle::getData() {
return _data;
}
}
\ No newline at end of file
#ifndef datahandle_h__
#define datahandle_h__
#include "tgt/logmanager.h"
#include "datastructures/abstractdata.h"
#include <string>
#include <set>
namespace TUMVis {
class DataContainer;
/**
* A DataHandle is responsible to manage the lifetime of an AbstractData instance.
* Therefore, it holds a pointer to the managed data object as well as a set of pointers to the
* DataContainer instances containing this very DataHandle. Each DataContainer is responsible for
* registering itsself as owner of its DataHandles (via DataHandle::addOwner()). When removing a
* DataHandle from a container, make sure to deregister via DataHandle::removeOwner().
*
* \note For clarity: A DataHandle can have multiple owners, as soon as the owner count drops
* to 0 it will be destroyed. Also remember that a DataHandle takes ownership of the
* given AbstractData instance. So do not delete it once it has been assigned to a
* DataHandle (respectively DataContainer).
*
* \todo
*/
class DataHandle {
// DataContainer is the only class allowed to access the private constructor and ownership modification methods.
friend class DataContainer;
public:
/**
* Destructor, will delete the managed AbstractData.
*/
virtual ~DataHandle();
/**
* Grants const access to the managed AbstractData instance.
* \return _data;
*/
const AbstractData* getData() const;
/**
* Grants access to the managed AbstractData instance.
* \return _data;
*/
AbstractData* getData();
private:
/**
* Creates a new DataHandle for \a data and takes its ownership in terms of lifetime management.
* The DataContainer \a owner will automatically be added to the set of owners of this DataHandle, so
* it is NOT needed to call DataHandle::addOwner().
*
* \param owner Initial owner of this DataHandle (usually the DataContainer creating the handle)
* \param data AbstractData instance to manage
*/
DataHandle(const DataContainer* owner, AbstractData* data);
/**
* DO NOT USE - it is private on purpose!
*
* IMHO a DataHandle does not need a copy-constructor - in particular it could be a bad idea to use
* one, because it does not exactly what you expect. If you really need a copy-constructor, please
* make sure to implement it correctly.
*/
DataHandle(const DataHandle& rhs);
/**
* DO NOT USE - it is private on purpose!
*
* IMHO a DataHandle does not need an assignment-operator - in particular it could be a bad idea to use
* one, because it does not exactly what you expect. If you really need an assignment-operator, please
* make sure to implement it correctly.
*/
DataHandle& operator=(const DataHandle& rhs);
/**
* Registers \a owner as owner of the DataHandle \a handle.
* \param handle DataHandle that gets another ownership.
* \param owner Owner that shall be added to the owner list of \a handle.
*/
static void addOwner(const DataHandle* handle, const DataContainer* owner);
/**
* Removes \a owner from the owner list of \a handle. If afterwards the number of owners is 0, \a handle will be deleted.
* \param handle DataHandle of which to remove the ownership.
* \param owner Owner that shall be removed from the owner list of \a handle.
*/
static void removeOwner(const DataHandle* handle, const DataContainer* owner);
AbstractData* _data; ///< managed data
mutable std::set<const DataContainer*> _owners; ///< set of owners of this DataHandle
static const std::string loggerCat_;
};
}
#endif // datahandle_h__
\ No newline at end of file
#include "imagedata.h"
namespace TUMVis {
const std::string ImageData::loggerCat_ = "TUMVis.core.datastructures.ImageData";
ImageData::ImageData(size_t dimensionality, const tgt::svec3& size)
: _dimensionality(dimensionality)
, _size(size)
{
}
ImageData::~ImageData() {
}
size_t ImageData::getDimensionality() const {
return _dimensionality;
}
const tgt::svec3& ImageData::getSize() const {
return _size;
}
const ImageMappingInformation& ImageData::getMappingInformation() const {
return _mappingInformation;
}
ImageMappingInformation& ImageData::getMappingInformation() {
return _mappingInformation;
}
}
\ No newline at end of file
#ifndef imagedata_h__
#define imagedata_h__
#include "datastructures/abstractdata.h"
#include "datastructures/imagemapping.h"
#include "tgt/vector.h"
namespace TUMVis {
/**
* Stores basic information about one (semantic) image of arbitrary dimension.
* Different representations (e.g. local memory, OpenGL texture, OpenCL buffer) are
* to be defined by inheritance.
*
* \todo
*/
class ImageData : public AbstractData {
public:
ImageData(size_t dimensionality, const tgt::svec3& size);
virtual ~ImageData();
/**
* Dimensionality of this image.
* \return _dimensionality
*/
size_t getDimensionality() const;
/**
* Size of this image (number of elements per dimension).
* \return _size
*/
const tgt::svec3& getSize() const;
/**
* Mapping information of this image
* \return _mappingInformation
*/
const ImageMappingInformation& getMappingInformation() const;
/**
* Mapping information of this image
* \return _mappingInformation
*/
ImageMappingInformation& getMappingInformation();
/**
* Returns the subimage of this image given by \a llf and \a urb.
* TODO: Check whether it is necessary to adjust image mapping!
*
* \param llf Lower-Left-Front coordinates of subimage
* \param urb Upper-Right-Back coordinates of subimage
* \return An image containing the subimage of this with the given coordinates.
*/
virtual ImageData* getSubImage(const tgt::svec3& llf, const tgt::svec3& urb) = 0;
private:
size_t _dimensionality; ///< Dimensionality of this image
tgt::svec3 _size; ///< Size of this image (number of elements per dimension)
ImageMappingInformation _mappingInformation; ///< Mapping information of this image
static const std::string loggerCat_;
};
}
#endif // imagedata_h__
#ifndef imagedata_h__
#define imagedata_h__
#include "tgt/vector.h"
#include "datastructures/imagedata.h"
#include "tools/endianhelper.h"
#include "tools/typetraits.h"
#include <fstream>
#include <string>
namespace TUMVis {
/**
* Subclass of ImageData offering access to image data stored in binary form on the local harddisk.
*
* \todo
*/
template<typename T>
class ImageDataDisk : public ImageData {
public:
/**
* Creates a new ImageData disk representation.
*
* \param url Path to file with raw data
* \param dimensionality Dimensionality of data
* \param size Size of this image (number of elements per dimension)
* \param offset Offset of first data element in file (in bytes)
* \param endianness Endianess of data
* \param stride Number of _elemments_ _between_ adjacent elements for each dimension (\see ImageDataDisk::_stride).
*/
ImageDataDisk(
const std::string& url,
size_t dimensionality,
const tgt::vec3& size,
size_t offset = 0,
EndianHelper::Endianness endianness = EndianHelper::LITTLE_ENDIAN,
const tgt::svec3& stride = tgt::svec2::zero
);
/**
* Destructor
*/
virtual ~ImageDataDisk() {};
/**
* \see ImageData::getSubImage
*/
virtual ImageDataDisk<T>* getSubImage(const tgt::vec3& llf, const tgt::vec3& urb);
/**
* Downloads the whole image data to local memory.
* \return Pointer to the image data in the local memory.
*/
T* getImageData() const;
private:
/**
* Calculates the canonical stride for the given image size.
* \param size Image size (number of elements per dimension).
* \return (0, size.x, size.x * size.y)
*/
tgt::svec3 getCanonicStride(const tgt::svec3& size) const;
std::string _url; ///< path to file with raw data
size_t _offset; ///< offset of first data element in file (in bytes)
EndianHelper::Endianness _endianess; ///< endianess of data
/**
* Number of _elemments_ _between_ adjacent elements for each dimension.
* If the stride is 0 for a dimension, the elements are assumed to be tightly packed, hence for
* the x-dimension 0, for the y-dimension _size.x and for the z-dimension (_size.x * _size.y).
**/
tgt::svec3 _stride;
};
// - Template implementation ----------------------------------------------------------------------
template<typename T>
TUMVis::ImageDataDisk<T>::ImageDataDisk(const std::string& url, size_t dimensionality, const tgt::vec3& size, size_t offset /*= 0*/, EndianHelper::Endianness endianness /*= false*/, const tgt::svec3& stride /*= tgt::svec2::zero */)
: ImageData(dimensionality, size)
, _url(url)
, _offset(offset)
, _endianess(endianness)
, _stride(stride)
{
}
template<typename T>
ImageDataDisk<T>* TUMVis::ImageDataDisk<T>::getSubImage(const tgt::vec3& llf, const tgt::vec3& urb) {
tgtAssert(tgt::hand(tgt::lessThan(llf, urb)), "Coordinates in LLF must be componentwise smaller than the ones in URB!");
tgt::svec3 newSize = urb - llf;
if (newSize == _size) {
// nothing has changed, just provide a copy:
return new ImageDataDisk<T>(_url, _dimensionality, newSize, _offset, _isBigEndian, _stride);
}
size_t newOffset = _offset + TypeTraits<T>::numBytes * llf.x;