Commit 71cf711c authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge

Merge branch 'columbia-fixes' into 'development'

Columbia fixes

See merge request !96
parents 2b581529 32bfe6a0
......@@ -117,6 +117,7 @@ IF(CAMPVIS_GROUP_SOURCE_FILES)
ENDIF()
IF(CAMPVIS_DEPLOY_SHADERS)
LIST(APPEND CampvisShaderDirectories "application/data")
LIST(APPEND CampvisShaderDirectories "application/glsl")
LIST(APPEND CampvisShaderDirectories "core/glsl")
......
......@@ -155,7 +155,7 @@ namespace campvis {
// load textureData from file
tgt::TextureReaderTga trt;
_errorTexture = trt.loadTexture(CAMPVIS_SOURCE_DIR "/application/data/no_input.tga", tgt::Texture::LINEAR);
_errorTexture = trt.loadTexture(ShdrMgr.completePath("application/data/no_input.tga"), tgt::Texture::LINEAR);
#ifdef CAMPVIS_HAS_SCRIPTING
......
......@@ -64,21 +64,19 @@ namespace campvis {
}
FaceGeometry* FaceGeometry::clone() const {
return new FaceGeometry(_vertices, _textureCoordinates, _colors, _normals);
FaceGeometry* toReturn = new FaceGeometry(_vertices, _textureCoordinates, _colors, _normals);
toReturn->setPickingInformation(_pickingInformation);
return toReturn;
}
size_t FaceGeometry::getLocalMemoryFootprint() const {
size_t sum = 0;
if (_verticesBuffer != 0)
sum += sizeof(tgt::BufferObject);
if (_texCoordsBuffer != 0)
sum += sizeof(tgt::BufferObject);
if (_colorsBuffer != 0)
sum += sizeof(tgt::BufferObject);
if (_normalsBuffer != 0)
sum += sizeof(tgt::BufferObject);
for (size_t i = 0; i < NUM_BUFFERS; ++i) {
if (_buffers[i] != nullptr)
sum += sizeof(tgt::BufferObject);
}
return sizeof(*this) + sum + (sizeof(tgt::vec3) * (_vertices.size() + _textureCoordinates.size() + _normals.size())) + (sizeof(tgt::vec4) * _colors.size());
return sizeof(*this) + sum + (sizeof(tgt::vec3) * (_vertices.size() + _textureCoordinates.size() + _normals.size())) + (sizeof(tgt::vec4) * (_colors.size() + _pickingInformation.size()));
}
size_t FaceGeometry::size() const {
......@@ -101,6 +99,16 @@ namespace campvis {
return _textureCoordinates;
}
const std::vector<tgt::col4>& FaceGeometry::getPickingInformation() const {
return _pickingInformation;
}
void FaceGeometry::setPickingInformation(const std::vector<tgt::col4>& pickingInformation) {
tgtAssert(pickingInformation.size() == 0 || pickingInformation.size() == _vertices.size(), "Number of picking informations does not match number of vertices!");
_pickingInformation = pickingInformation;
_buffersDirty = true;
}
const tgt::vec3& FaceGeometry::getFaceNormal() const {
return _faceNormal;
}
......@@ -124,6 +132,8 @@ namespace campvis {
vao.setVertexAttributePointer(2, _colorsBuffer);
if (_normalsBuffer)
vao.setVertexAttributePointer(3, _normalsBuffer);
if (_pickingBuffer)
vao.setVertexAttributePointer(4, _pickingBuffer);
LGL_ERROR;
glDrawArrays(mode, 0, static_cast<GLsizei>(_vertices.size()));
......@@ -150,6 +160,10 @@ namespace campvis {
_normalsBuffer = new tgt::BufferObject(tgt::BufferObject::ARRAY_BUFFER, tgt::BufferObject::USAGE_STATIC_DRAW);
_normalsBuffer->data(&_normals.front(), _normals.size() * sizeof(tgt::vec3), tgt::BufferObject::FLOAT, 3);
}
if (! _pickingInformation.empty()) {
_pickingBuffer = new tgt::BufferObject(tgt::BufferObject::ARRAY_BUFFER, tgt::BufferObject::USAGE_STATIC_DRAW);
_pickingBuffer->data(&_pickingInformation.front(), _pickingInformation.size() * sizeof(tgt::col4), tgt::BufferObject::UNSIGNED_BYTE, 4);
}
}
catch (tgt::Exception& e) {
LERROR("Error creating OpenGL Buffer objects: " << e.what());
......@@ -177,6 +191,7 @@ namespace campvis {
std::vector<tgt::vec3> verts, texCoords, norms;
std::vector<tgt::vec4> cols;
std::vector<tgt::col4> picks;
size_t lastIndex = _vertices.size() - 1;
float lastDistance = distanceToPlane(_vertices.back(), p, pNormal, epsilon);
......@@ -195,6 +210,8 @@ namespace campvis {
cols.push_back(tgt::mix(_colors[lastIndex], _colors[i], t));
if (!_normals.empty())
norms.push_back(tgt::mix(_normals[lastIndex], _normals[i], t));
if (!_pickingInformation.empty())
picks.push_back(_pickingInformation[i]);
}
// case 2: last vertex inside, this vertex outside clip region => clip
else if (lastDistance <= 0 && currrentDistance > 0) {
......@@ -207,6 +224,8 @@ namespace campvis {
cols.push_back(tgt::mix(_colors[lastIndex], _colors[i], t));
if (!_normals.empty())
norms.push_back(tgt::mix(_normals[lastIndex], _normals[i], t));
if (!_pickingInformation.empty())
picks.push_back(_pickingInformation[lastIndex]);
}
// case 1.2 + case 3: current vertix in front of plane => keep
......@@ -218,13 +237,17 @@ namespace campvis {
cols.push_back(_colors[i]);
if (!_normals.empty())
norms.push_back(_normals[i]);
if (!_pickingInformation.empty())
picks.push_back(_pickingInformation[i]);
}
lastIndex = i;
lastDistance = currrentDistance;
}
return FaceGeometry(verts, texCoords, cols, norms);
FaceGeometry toReturn(verts, texCoords, cols, norms);
toReturn.setPickingInformation(picks);
return toReturn;
}
tgt::Bounds FaceGeometry::getWorldBounds() const {
......@@ -238,6 +261,10 @@ namespace campvis {
return ! _textureCoordinates.empty();
}
bool FaceGeometry::hasPickingInformation() const {
return !_pickingInformation.empty();
}
void FaceGeometry::applyTransformationToVertices(const tgt::mat4& t) {
for (size_t i = 0; i < _vertices.size(); ++i) {
tgt::vec4 tmp = t * tgt::vec4(_vertices[i], 1.f);
......@@ -247,4 +274,5 @@ namespace campvis {
_buffersDirty = true;
}
}
\ No newline at end of file
......@@ -105,6 +105,18 @@ namespace campvis {
* \return _textureCoordinates
*/
const std::vector<tgt::vec3>& getTextureCoordinates() const;
/**
* The list of picking information colors, may be empty.
* \return _pickingInformation
*/
const std::vector<tgt::col4>& getPickingInformation() const;
/**
* Sets the picking information of this geometry to \a pickingInformation
* \param pickingInformation The new list of picking information for this geometry
*/
void setPickingInformation(const std::vector<tgt::col4>& pickingInformation);
/**
* The normal vector of this face.
......@@ -134,6 +146,8 @@ namespace campvis {
virtual tgt::Bounds getWorldBounds() const;
/// \see GeometryData::hasTextureCoordinates
virtual bool hasTextureCoordinates() const;
/// \see GeometryData::hasPickingInformation
virtual bool hasPickingInformation() const;
/// \see GeometryData::applyTransformationToVertices
virtual void applyTransformationToVertices(const tgt::mat4& t);
......@@ -149,6 +163,8 @@ namespace campvis {
std::vector<tgt::vec4> _colors; ///< The list of vertex colors, may be empty.
std::vector<tgt::vec3> _normals; ///< The list of vertex normals, may be empty.
std::vector<tgt::col4> _pickingInformation; ///< The list of picking information colors, max be empty.
tgt::vec3 _faceNormal; ///< The normal vector of this face.
static const std::string loggerCat_;
......
......@@ -70,7 +70,7 @@ namespace campvis {
* \return _data, may be 0, GenericPointerData has ownership
*/
const T* getData() const {
return _data;
return _data.get();
};
/**
......@@ -78,7 +78,7 @@ namespace campvis {
* \return _data, may be 0, GenericPointerData has ownership
*/
T* getData() {
return _data;
return _data.get();
};
/**
......
......@@ -37,20 +37,22 @@ namespace campvis {
GeometryData::GeometryData()
: AbstractData()
, _buffersDirty(true)
, _verticesBuffer(0)
, _texCoordsBuffer(0)
, _colorsBuffer(0)
, _normalsBuffer(0)
, _verticesBuffer(nullptr)
, _texCoordsBuffer(nullptr)
, _colorsBuffer(nullptr)
, _normalsBuffer(nullptr)
, _pickingBuffer(nullptr)
{
}
GeometryData::GeometryData(const GeometryData& rhs)
: AbstractData(rhs)
, _buffersDirty(true)
, _verticesBuffer(0)
, _texCoordsBuffer(0)
, _colorsBuffer(0)
, _normalsBuffer(0)
, _verticesBuffer(nullptr)
, _texCoordsBuffer(nullptr)
, _colorsBuffer(nullptr)
, _normalsBuffer(nullptr)
, _pickingBuffer(nullptr)
{
}
......@@ -74,21 +76,23 @@ namespace campvis {
void GeometryData::deleteBuffers() const {
for (int i = 0; i < NUM_BUFFERS; ++i) {
delete _buffers[i];
_buffers[i] = 0;
_buffers[i] = nullptr;
}
}
size_t GeometryData::getVideoMemoryFootprint() const {
size_t sum = 0;
if (_verticesBuffer != 0)
if (_verticesBuffer != nullptr)
sum += _verticesBuffer->getBufferSize();
if (_texCoordsBuffer != 0)
if (_texCoordsBuffer != nullptr)
sum += _texCoordsBuffer->getBufferSize();
if (_colorsBuffer != 0)
if (_colorsBuffer != nullptr)
sum += _colorsBuffer->getBufferSize();
if (_normalsBuffer != 0)
if (_normalsBuffer != nullptr)
sum += _normalsBuffer->getBufferSize();
if (_pickingBuffer != nullptr)
sum += _pickingBuffer->getBufferSize();
return sum;
}
......@@ -109,4 +113,8 @@ namespace campvis {
return _normalsBuffer;
}
const tgt::BufferObject* GeometryData::getPickingBuffer() const {
return _pickingBuffer;
}
}
\ No newline at end of file
......@@ -36,6 +36,7 @@ namespace tgt {
}
namespace campvis {
/**
* Abstract base class for geometry data in CAMPVis.
*
......@@ -91,12 +92,19 @@ namespace campvis {
*/
virtual tgt::Bounds getWorldBounds() const = 0;
/**
* Returns whether the geometry has texture coordinates.
* \return True if this geometry sets texture coordinates during rendering.
*/
virtual bool hasTextureCoordinates() const = 0;
/**
* Returns whether this geometry has picking information.
* \return True if this geometry sets picking information during rendering.
*/
virtual bool hasPickingInformation() const = 0;
/**
* Applies the transformation matrix \a t to each vertex of this geometry.
* \param t Transformation matrix to apply
......@@ -131,6 +139,13 @@ namespace campvis {
*/
const tgt::BufferObject* getNormalsBuffer() const;
/**
* Returns the Pointer to the OpenGL Buffer with the vertex normals.
* May be 0 if none are present or not yet created.
* \return _normalsBuffer
*/
const tgt::BufferObject* getPickingBuffer() const;
/// \see AbstractData::getVideoMemoryFootprint()
virtual size_t getVideoMemoryFootprint() const;
......@@ -140,10 +155,11 @@ namespace campvis {
*/
void deleteBuffers() const;
// mutable to support const lazy initialization
mutable bool _buffersDirty; ///< Flag whether the buffers are dirty (i.e. need to be (re)initialized)
enum { NUM_BUFFERS = 4 }; ///< Number of buffers in _buffers array
enum { NUM_BUFFERS = 5 }; ///< Number of buffers in _buffers array
union {
struct {
......@@ -151,6 +167,7 @@ namespace campvis {
mutable tgt::BufferObject* _texCoordsBuffer; ///< Pointer to the OpenGL Buffer with the vertex texture coordinates
mutable tgt::BufferObject* _colorsBuffer; ///< Pointer to the OpenGL Buffer with the vertex colors
mutable tgt::BufferObject* _normalsBuffer; ///< Pointer to the OpenGL Buffer with the vertex normals
mutable tgt::BufferObject* _pickingBuffer; ///< Pointer to the OpenGL Buffer with the picking information
};
mutable tgt::BufferObject* _buffers[NUM_BUFFERS]; ///< Array of all buffers
......@@ -163,4 +180,75 @@ namespace campvis {
}
/*
=== This is a draft for a new, generic GeometryData class design that manages arbitrary OpenGL buffers ====
class CAMPVIS_CORE_API GeometryDataBase {
public:
/// Enumeration for defining semantics of stored buffer data
enum ElementSemantic {
VERTEX = 0, ///< Vextex data
TEXTURE_COORDINATE = 1, ///< Texture coordinate data
COLOR = 2, ///< Color data
NORMAL = 3, ///< Normal data
PICKING_INFORMATION = 4 ///< Picking information
};
/// Enumeration for defining the host data type of the element
enum ElementHostType {
UINT8,
UINT16,
UINT32,
FLOAT,
VEC2,
VEC3,
VEC4
};
};
template<GeometryDataBase::ElementSemantic SEMANTIC>
struct GeometryDataTraits {};
template<>
struct GeometryDataTraits<GeometryDataBase::VERTEX> {
typedef tgt::vec3 HostType;
};
class CAMPVIS_CORE_API DraftNewGeometryData {
public:
template<GeometryDataBase::ElementSemantic SEMANTIC>
const std::vector<typename GeometryDataTraits<SEMANTIC>::HostType>* getElementData() const;
template<GeometryDataBase::ElementSemantic SEMANTIC>
void setElementData(std::vector<typename GeometryDataTraits<SEMANTIC>::HostType>* elementData);
protected:
std::vector<void*> _elementPointers;
};
template<GeometryDataBase::ElementSemantic SEMANTIC>
const std::vector<typename GeometryDataTraits<SEMANTIC>::HostType>* GeometryData::getElementData() const {
if (_elementPointers.size() >= SEMANTIC) {
return static_cast< std::vector<typename GeometryDataTraits<SEMANTIC>::HostType>* >(_elementPointers[SEMANTIC]);
}
return nullptr;
}
template<GeometryDataBase::ElementSemantic SEMANTIC>
void GeometryData::setElementData(std::vector<typename GeometryDataTraits<SEMANTIC>::HostType>* elementData) {
if (_elementPointers.size() < SEMANTIC + 1)
_elementPointers.resize(SEMANTIC, nullptr);
void* oldPtr = _elementPointers[SEMANTIC];
if (oldPtr != elementData)
delete static_cast< std::vector<typename GeometryDataTraits<SEMANTIC>::HostType>* >(oldPtr);
_elementPointers[SEMANTIC] = elementData;
}
*/
#endif // GEOMETRYDATA_H__
......@@ -114,6 +114,15 @@ namespace campvis {
return true;
}
bool GeometryDataCollection::hasPickingInformation() const {
for (size_t i = 0; i < _geometries.size(); ++i) {
if (! _geometries[i]->hasPickingInformation())
return false;
}
return true;
}
void GeometryDataCollection::applyTransformationToVertices(const tgt::mat4& t) {
for (size_t i = 0; i < _geometries.size(); ++i)
_geometries[i]->applyTransformationToVertices(t);
......@@ -136,5 +145,4 @@ namespace campvis {
return sum;
}
}
\ No newline at end of file
......@@ -109,6 +109,12 @@ namespace campvis {
*/
virtual bool hasTextureCoordinates() const;
/**
* Returns whether all geometries of the collection have picking information.
* \return True if all geometries of the collection set picking information during rendering.
*/
virtual bool hasPickingInformation() const;
/**
* Applies the transformation matrix \a t to each vertex of this geometry.
* \param t Transformation matrix to apply
......
......@@ -26,6 +26,8 @@
#define IMAGEDATA_H__
#include <tbb/concurrent_vector.h>
#include <tbb/spin_mutex.h>
#include "tgt/logmanager.h"
#include "tgt/vector.h"
......@@ -195,6 +197,9 @@ namespace campvis {
const size_t _numElements; ///< number of elements (= tgt::hmul(size))
ImageMappingInformation _mappingInformation; ///< Mapping information of this image
/// Mutex protecting the representation conversions to ensure that there is only one conversion happening at a time.
mutable tbb::spin_mutex _conversionMutex;
static const std::string loggerCat_;
};
......@@ -212,6 +217,15 @@ namespace campvis {
// no representation found, create a new one
if (performConversion) {
tbb::spin_mutex::scoped_lock lock(_conversionMutex);
// in the meantime, there something might have changed, so check again whether there is a new rep.
for (tbb::concurrent_vector<const AbstractImageRepresentation*>::const_iterator it = _representations.begin(); it != _representations.end(); ++it) {
if (const T* tester = dynamic_cast<const T*>(*it)) {
return tester;
}
}
return tryPerformConversion<T>();
}
......@@ -220,18 +234,16 @@ namespace campvis {
template<typename T>
const T* campvis::ImageData::tryPerformConversion() const {
// TODO: Currently, we do not check, for multiple parallel conversions into the same
// target type. This does not harm thread-safety but may lead to multiple
// representations of the same type for a single image.
for (tbb::concurrent_vector<const AbstractImageRepresentation*>::const_iterator it = _representations.begin(); it != _representations.end(); ++it) {
const T* tester = ImageRepresentationConverter::getRef().tryConvertFrom<T>(*it);
if (tester != 0) {
//LDEBUG("Performed a image representation conversion from " + std::string(typeid(**it).name()) + " to " + std::string(typeid(T).name()) + ".");
return tester;
}
}
// could not create a suitable representation
LWARNING("Could not create a " + std::string(typeid(T*).name()) + " representation.");
LWARNING("Could not create a " + std::string(typeid(T).name()) + " representation.");
return 0;
}
......
......@@ -84,6 +84,7 @@ namespace campvis {
_textureCoordinates = rhs._textureCoordinates;
_colors = rhs._colors;
_normals = rhs._normals;
_pickingInformation = rhs._pickingInformation;
// delete old VBOs and null pointers
deleteIndicesBuffer();
......@@ -91,23 +92,28 @@ namespace campvis {
return *this;
}
const std::vector<tgt::col4>& IndexedMeshGeometry::getPickingInformation() const {
return _pickingInformation;
}
void IndexedMeshGeometry::setPickingInformation(const std::vector<tgt::col4>& pickingInformation) {
tgtAssert(pickingInformation.size() == 0 || pickingInformation.size() == _vertices.size(), "Number of picking informations does not match number of vertices!");
_pickingInformation = pickingInformation;
_buffersDirty = true;
}
IndexedMeshGeometry* IndexedMeshGeometry::clone() const {
return new IndexedMeshGeometry(_indices, _vertices, _textureCoordinates, _colors, _normals);
IndexedMeshGeometry* toReturn = new IndexedMeshGeometry(_indices, _vertices, _textureCoordinates, _colors, _normals);
toReturn->setPickingInformation(_pickingInformation);
return toReturn;
}
size_t IndexedMeshGeometry::getLocalMemoryFootprint() const {
size_t sum = 0;
if (_indicesBuffer != 0)
sum += sizeof(tgt::BufferObject);
if (_verticesBuffer != 0)
sum += sizeof(tgt::BufferObject);
if (_texCoordsBuffer != 0)
sum += sizeof(tgt::BufferObject);
if (_colorsBuffer != 0)
sum += sizeof(tgt::BufferObject);
if (_normalsBuffer != 0)
sum += sizeof(tgt::BufferObject);
for (size_t i = 0; i < NUM_BUFFERS; ++i) {
if (_buffers[i] != nullptr)
sum += sizeof(tgt::BufferObject);
}
return sizeof(*this) + sum + (sizeof(size_t) * _indices.size()) + (sizeof(tgt::vec3) * (_vertices.size() + _textureCoordinates.size() + _normals.size())) + (sizeof(tgt::vec4) * _colors.size());
}
......@@ -136,6 +142,8 @@ namespace campvis {
vao.setVertexAttributePointer(2, _colorsBuffer);
if (_normalsBuffer)
vao.setVertexAttributePointer(3, _normalsBuffer);
if (_pickingBuffer)
vao.setVertexAttributePointer(4, _pickingBuffer);
vao.bindIndexBuffer(_indicesBuffer);
glDrawElements(mode, static_cast<GLsizei>(_indices.size()), GL_UNSIGNED_SHORT, 0);
......@@ -166,6 +174,10 @@ namespace campvis {
_normalsBuffer = new tgt::BufferObject(tgt::BufferObject::ARRAY_BUFFER, tgt::BufferObject::USAGE_STATIC_DRAW);
_normalsBuffer->data(&_normals.front(), _normals.size() * sizeof(tgt::vec3), tgt::BufferObject::FLOAT, 3);
}
if (! _pickingInformation.empty()) {
_pickingBuffer = new tgt::BufferObject(tgt::BufferObject::ARRAY_BUFFER, tgt::BufferObject::USAGE_STATIC_DRAW);
_pickingBuffer->data(&_pickingInformation.front(), _pickingInformation.size() * sizeof(tgt::col4), tgt::BufferObject::UNSIGNED_BYTE, 4);
}
}
catch (tgt::Exception& e) {
LERROR("Error creating OpenGL Buffer objects: " << e.what());
......@@ -194,6 +206,10 @@ namespace campvis {
return ! _textureCoordinates.empty();
}
bool IndexedMeshGeometry::hasPickingInformation() const {
return _pickingInformation.empty();
}
void IndexedMeshGeometry::applyTransformationToVertices(const tgt::mat4& t) {
for (size_t i = 0; i < _vertices.size(); ++i) {
tgt::vec4 tmp = t * tgt::vec4(_vertices[i], 1.f);
......@@ -203,5 +219,4 @@ namespace campvis {
_buffersDirty = true;
}
}
\ No newline at end of file
......@@ -22,8 +22,8 @@
//
// ================================================================================================
#ifndef INDEXEDIndexedMeshGeometry_H__
#define INDEXEDIndexedMeshGeometry_H__
#ifndef INDEXEDMESHGEOMETRY_H__
#define INDEXEDMESHGEOMETRY_H__
#include "tgt/bounds.h"
#include "tgt/vector.h"
......@@ -79,6 +79,20 @@ namespace campvis {
*/
IndexedMeshGeometry& operator=(const IndexedMeshGeometry& rhs);
/**
* The list of picking information colors, may be empty.
* \return _pickingInformation
*/
const std::vector<tgt::col4>& getPickingInformation() const;
/**
<