Commit a634042c authored by Christian Schulte zu Berge's avatar Christian Schulte zu Berge
Browse files

Cleaned up and slightly revised GeometryData API. Cleared the way for...

Cleaned up and slightly revised GeometryData API. Cleared the way for non-value semantics. Introducing GeometryDataFactory, a collection of static methods to create standard geometric primitives.
parent 6b394e72
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "core/datastructures/renderdata.h" #include "core/datastructures/renderdata.h"
#include "core/datastructures/imagerepresentationgl.h" #include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/facegeometry.h" #include "core/datastructures/facegeometry.h"
#include "core/datastructures/geometrydatafactory.h"
#include "core/tools/job.h" #include "core/tools/job.h"
#include "core/classification/tfgeometry1d.h" #include "core/classification/tfgeometry1d.h"
#include "core/classification/geometry1dtransferfunction.h" #include "core/classification/geometry1dtransferfunction.h"
...@@ -194,20 +195,9 @@ namespace campvis { ...@@ -194,20 +195,9 @@ namespace campvis {
} }
void DataContainerInspectorCanvas::createQuad() { void DataContainerInspectorCanvas::createQuad() {
std::vector<tgt::vec3> vertices, texCorods;
vertices.push_back(tgt::vec3( 0.f, 0.f, 0.f));
vertices.push_back(tgt::vec3(1.f, 0.f, 0.f));
vertices.push_back(tgt::vec3(1.f, 1.f, 0.f));
vertices.push_back(tgt::vec3( 0.f, 1.f, 0.f));
texCorods.push_back(tgt::vec3(0.f, 1.f, 0.f));
texCorods.push_back(tgt::vec3(1.f, 1.f, 0.f));
texCorods.push_back(tgt::vec3(1.f, 0.f, 0.f));
texCorods.push_back(tgt::vec3(0.f, 0.f, 0.f));
delete _quad; delete _quad;
_quad = new FaceGeometry(vertices, texCorods); _quad = 0;
_quad->createGLBuffers(); _quad = GeometryDataFactory::createQuad(tgt::vec3(0.f), tgt::vec3(1.f), tgt::vec3(0.f), tgt::vec3(1.f));
} }
void DataContainerInspectorCanvas::repaint() { void DataContainerInspectorCanvas::repaint() {
......
...@@ -39,6 +39,13 @@ namespace campvis { ...@@ -39,6 +39,13 @@ namespace campvis {
const std::string FaceGeometry::loggerCat_ = "CAMPVis.core.datastructures.FaceGeometry"; const std::string FaceGeometry::loggerCat_ = "CAMPVis.core.datastructures.FaceGeometry";
FaceGeometry::FaceGeometry()
: GeometryData()
, _faceNormal(0.f)
{
}
FaceGeometry::FaceGeometry(const std::vector<tgt::vec3>& vertices, const std::vector<tgt::vec3>& textureCoordinates /*= std::vector<tgt::vec3>()*/, const std::vector<tgt::vec4>& colors /*= std::vector<tgt::vec4>()*/, const std::vector<tgt::vec3>& normals /*= std::vector<tgt::vec3>() */) FaceGeometry::FaceGeometry(const std::vector<tgt::vec3>& vertices, const std::vector<tgt::vec3>& textureCoordinates /*= std::vector<tgt::vec3>()*/, const std::vector<tgt::vec4>& colors /*= std::vector<tgt::vec4>()*/, const std::vector<tgt::vec3>& normals /*= std::vector<tgt::vec3>() */)
: GeometryData() : GeometryData()
, _vertices(vertices) , _vertices(vertices)
...@@ -105,7 +112,7 @@ namespace campvis { ...@@ -105,7 +112,7 @@ namespace campvis {
void FaceGeometry::render(GLenum mode) const { void FaceGeometry::render(GLenum mode) const {
createGLBuffers(); createGLBuffers();
if (! _buffersInitialized) { if (_buffersDirty) {
LERROR("Cannot render without initialized OpenGL buffers."); LERROR("Cannot render without initialized OpenGL buffers.");
return; return;
} }
...@@ -126,9 +133,9 @@ namespace campvis { ...@@ -126,9 +133,9 @@ namespace campvis {
} }
void FaceGeometry::createGLBuffers() const { void FaceGeometry::createGLBuffers() const {
GeometryData::createGLBuffers(); if (_buffersDirty) {
deleteBuffers();
if (! _buffersInitialized) {
try { try {
_verticesBuffer = new tgt::BufferObject(tgt::BufferObject::ARRAY_BUFFER, tgt::BufferObject::USAGE_STATIC_DRAW); _verticesBuffer = new tgt::BufferObject(tgt::BufferObject::ARRAY_BUFFER, tgt::BufferObject::USAGE_STATIC_DRAW);
_verticesBuffer->data(&_vertices.front(), _vertices.size() * sizeof(tgt::vec3), tgt::BufferObject::FLOAT, 3); _verticesBuffer->data(&_vertices.front(), _vertices.size() * sizeof(tgt::vec3), tgt::BufferObject::FLOAT, 3);
...@@ -148,12 +155,12 @@ namespace campvis { ...@@ -148,12 +155,12 @@ namespace campvis {
} }
catch (tgt::Exception& e) { catch (tgt::Exception& e) {
LERROR("Error creating OpenGL Buffer objects: " << e.what()); LERROR("Error creating OpenGL Buffer objects: " << e.what());
_buffersInitialized = false; _buffersDirty = true;
return; return;
} }
LGL_ERROR; LGL_ERROR;
_buffersInitialized = true; _buffersDirty = false;
} }
} }
...@@ -167,7 +174,7 @@ namespace campvis { ...@@ -167,7 +174,7 @@ namespace campvis {
} }
} }
campvis::FaceGeometry FaceGeometry::clipAgainstPlane(float p, const tgt::vec3& pNormal, float epsilon /*= 1e-8f*/) const { campvis::FaceGeometry FaceGeometry::clipAgainstPlane(float p, const tgt::vec3& pNormal, float epsilon /*= 1e-4f*/) const {
tgtAssert(epsilon >= 0, "Epsilon must be positive."); tgtAssert(epsilon >= 0, "Epsilon must be positive.");
std::vector<tgt::vec3> verts, texCoords, norms; std::vector<tgt::vec3> verts, texCoords, norms;
......
...@@ -48,13 +48,16 @@ namespace campvis { ...@@ -48,13 +48,16 @@ namespace campvis {
* *
* \note This class expects all vertices lying within one plane. Everything other that that * \note This class expects all vertices lying within one plane. Everything other that that
* leads to undefined behavior. * leads to undefined behavior.
* \note Like all Geometry classes FaceGeometry has value-sematics: Once created, the
* vertices/colors/etc. cannot be altered anymore.
*/ */
class FaceGeometry : public GeometryData { class FaceGeometry : public GeometryData {
public: public:
/** /**
* Creates a new FaceGeometry. * Creates a new empty FaceGeometry.
*/
explicit FaceGeometry();
/**
* Creates a new FaceGeometry initialized from the given data.
* \param vertices The list of the vertex positions of the face. * \param vertices The list of the vertex positions of the face.
* \param textureCoordinates The list of vertex texture coordinates, may be empty. * \param textureCoordinates The list of vertex texture coordinates, may be empty.
* \param colors The list of vertex colors, may be empty. * \param colors The list of vertex colors, may be empty.
...@@ -68,7 +71,7 @@ namespace campvis { ...@@ -68,7 +71,7 @@ namespace campvis {
); );
/** /**
* Destructor, deletes VBOs/VAO if necessary. Hence, needs a valid OpenGL context * Destructor, deletes VBOs/VAO if necessary.
*/ */
virtual ~FaceGeometry(); virtual ~FaceGeometry();
...@@ -131,18 +134,18 @@ namespace campvis { ...@@ -131,18 +134,18 @@ namespace campvis {
* \param mode OpenGL rendering mode for this face * \param mode OpenGL rendering mode for this face
*/ */
virtual void render(GLenum mode) const; virtual void render(GLenum mode) const;
/**
* Creates the OpenGL VBOs and the VAO for this face's geometry.
* Must be called from a valid OpenGL context.
*/
virtual void createGLBuffers() const;
/// \see GeometryData::getWorldBounds /// \see GeometryData::getWorldBounds
virtual tgt::Bounds getWorldBounds() const; virtual tgt::Bounds getWorldBounds() const;
protected: protected:
/**
* Creates the OpenGL VBOs and the VAO for this face's geometry.
* Must be called from a valid OpenGL context.
*/
void createGLBuffers() const;
std::vector<tgt::vec3> _vertices; ///< The list of the vertex positions of the face. std::vector<tgt::vec3> _vertices; ///< The list of the vertex positions of the face.
std::vector<tgt::vec3> _textureCoordinates; ///< The list of vertex texture coordinates, may be empty. std::vector<tgt::vec3> _textureCoordinates; ///< The list of vertex texture coordinates, may be empty.
std::vector<tgt::vec4> _colors; ///< The list of vertex colors, may be empty. std::vector<tgt::vec4> _colors; ///< The list of vertex colors, may be empty.
......
...@@ -29,27 +29,29 @@ ...@@ -29,27 +29,29 @@
#include "geometrydata.h" #include "geometrydata.h"
#include "tgt/buffer.h" #include "tgt/buffer.h"
#include "tgt/vertexarrayobject.h" #include "tgt/logmanager.h"
#include "tgt/glcontextmanager.h" #include "tgt/glcontextmanager.h"
#include "tgt/vertexarrayobject.h"
#include "core/tools/opengljobprocessor.h" #include "core/tools/opengljobprocessor.h"
namespace campvis { namespace campvis {
const std::string GeometryData::loggerCat_ = "CAMPVis.core.datastructures.GeometryData";;
GeometryData::GeometryData() GeometryData::GeometryData()
: AbstractData() : AbstractData()
, _buffersInitialized(false) , _buffersDirty(true)
, _verticesBuffer(0) , _verticesBuffer(0)
, _texCoordsBuffer(0) , _texCoordsBuffer(0)
, _colorsBuffer(0) , _colorsBuffer(0)
, _normalsBuffer(0) , _normalsBuffer(0)
, _context(0)
{ {
} }
GeometryData::GeometryData(const GeometryData& rhs) GeometryData::GeometryData(const GeometryData& rhs)
: AbstractData(rhs) : AbstractData(rhs)
, _buffersInitialized(false) , _buffersDirty(true)
, _verticesBuffer(0) , _verticesBuffer(0)
, _texCoordsBuffer(0) , _texCoordsBuffer(0)
, _colorsBuffer(0) , _colorsBuffer(0)
...@@ -59,12 +61,7 @@ namespace campvis { ...@@ -59,12 +61,7 @@ namespace campvis {
} }
GeometryData::~GeometryData() { GeometryData::~GeometryData() {
if (_buffersInitialized) { deleteBuffers();
delete _verticesBuffer;
delete _texCoordsBuffer;
delete _colorsBuffer;
delete _normalsBuffer;
}
} }
GeometryData& GeometryData::operator=(const GeometryData& rhs) { GeometryData& GeometryData::operator=(const GeometryData& rhs) {
...@@ -74,25 +71,16 @@ namespace campvis { ...@@ -74,25 +71,16 @@ namespace campvis {
AbstractData::operator=(rhs); AbstractData::operator=(rhs);
// delete old VBOs and null pointers // delete old VBOs and null pointers
if (_buffersInitialized) { deleteBuffers();
delete _verticesBuffer;
delete _texCoordsBuffer;
delete _colorsBuffer;
delete _normalsBuffer;
}
_verticesBuffer = 0;
_texCoordsBuffer = 0;
_colorsBuffer = 0;
_normalsBuffer = 0;
_buffersInitialized = false;
return *this; return *this;
} }
void GeometryData::deleteBuffers(std::vector<tgt::BufferObject*> buffers) { void GeometryData::deleteBuffers() const {
for (std::vector<tgt::BufferObject*>::iterator it = buffers.begin(); it != buffers.end(); ++it) for (int i = 0; i < NUM_BUFFERS; ++i) {
delete *it; delete _buffers[i];
_buffers[i] = 0;
}
} }
size_t GeometryData::getVideoMemoryFootprint() const { size_t GeometryData::getVideoMemoryFootprint() const {
...@@ -110,11 +98,6 @@ namespace campvis { ...@@ -110,11 +98,6 @@ namespace campvis {
return sum; return sum;
} }
void GeometryData::createGLBuffers() const {
if (! _buffersInitialized)
_context = tgt::GlContextManager::getRef().getCurrentContext();
}
const tgt::BufferObject* GeometryData::getVerticesBuffer() const { const tgt::BufferObject* GeometryData::getVerticesBuffer() const {
return _verticesBuffer; return _verticesBuffer;
} }
......
...@@ -42,30 +42,48 @@ namespace tgt { ...@@ -42,30 +42,48 @@ namespace tgt {
namespace campvis { namespace campvis {
/** /**
* Abstract base class for data handled by a DataHandle and stored in a DataContainer. * Abstract base class for geometry data in CAMPVis.
* *
* \todo * GeometryData consists of a set of vertices (vec3) and optionally colors (vec4), texture
*/ * coordinates (vec3) and/or normals (vec3) for each vertex.
* GeometryData stores the geometry on the CPU side (local RAM) and takes care of transparently
* mapping it into GPU memory in order to render it using OpenGL. The mapping of vertex
* information to OpenGL vertex attributes is as follows:
* - Vertex positions: Vertex attribute 0
* - Vertex texture coordinates: Vertex attribute 1
* - Vertex colors: Vertex attribute 2
* - Vertex normals: Vertex attribute 3
*
*/
class GeometryData : public AbstractData, public IHasWorldBounds { class GeometryData : public AbstractData, public IHasWorldBounds {
public: public:
GeometryData(); /**
* Constructor
* \param vertexFeatures List of features present for each vertex
*/
explicit GeometryData();
/**
* Copy constructor
* \param rhs GeometryData to copy
*/
GeometryData(const GeometryData& rhs); GeometryData(const GeometryData& rhs);
/** /**
* Destructor, deletes VBOs/VAO if necessary. Hence, needs a valid OpenGL context * Destructor, deletes VBOs/VAO if necessary.
*/ */
virtual ~GeometryData(); virtual ~GeometryData();
/**
* Assignment operator.
* \param rhs GeometryData to assign to this.
* \return *this after assignment
*/
GeometryData& operator=(const GeometryData& rhs); GeometryData& operator=(const GeometryData& rhs);
static void deleteBuffers(std::vector<tgt::BufferObject*> buffers); /// \see AbstractData::clone()
virtual AbstractData* clone() const = 0; virtual AbstractData* clone() const = 0;
/// \see AbstractData::getVideoMemoryFootprint()
virtual size_t getVideoMemoryFootprint() const;
/** /**
* Renders this GeometryData. * Renders this GeometryData.
* Must be called from a valid OpenGL context. * Must be called from a valid OpenGL context.
...@@ -79,39 +97,61 @@ namespace campvis { ...@@ -79,39 +97,61 @@ namespace campvis {
virtual tgt::Bounds getWorldBounds() const = 0; virtual tgt::Bounds getWorldBounds() const = 0;
/** /**
* Creates the OpenGL VBOs and the VAO for this geometry. * Returns the Pointer to the OpenGL Buffer with the vertex positions.
* Must be called from a valid OpenGL context. * May be 0 if not yet created.
* \note When overwriting this method, make sure to call base class method first! * \return _verticesBuffer
*/ */
virtual void createGLBuffers() const;
const tgt::BufferObject* getVerticesBuffer() const; const tgt::BufferObject* getVerticesBuffer() const;
/**
* Returns the Pointer to the OpenGL Buffer with the vertex texture coordinates.
* May be 0 if none are present or not yet created.
* \return _texCoordsBuffer
*/
const tgt::BufferObject* getTextureCoordinatesBuffer() const; const tgt::BufferObject* getTextureCoordinatesBuffer() const;
/**
* Returns the Pointer to the OpenGL Buffer with the vertex colors.
* May be 0 if none are present or not yet created.
* \return _colorsBuffer
*/
const tgt::BufferObject* getColorsBuffer() const; const tgt::BufferObject* getColorsBuffer() 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* getNormalsBuffer() const; const tgt::BufferObject* getNormalsBuffer() const;
/// \see AbstractData::getVideoMemoryFootprint()
virtual size_t getVideoMemoryFootprint() const;
protected: protected:
/**
* Deletes all OpenGL BufferObjects.
*/
void deleteBuffers() const;
// mutable to support const lazy initialization // mutable to support const lazy initialization
mutable bool _buffersInitialized; mutable bool _buffersDirty; ///< Flag whether the buffers are dirty (i.e. need to be (re)initialized)
enum { NUM_BUFFERS = 4 }; enum { NUM_BUFFERS = 4 }; ///< Number of buffers in _buffers array
union { union {
struct { struct {
mutable tgt::BufferObject* _verticesBuffer; mutable tgt::BufferObject* _verticesBuffer; ///< Pointer to the OpenGL Buffer with the vertex positions
mutable tgt::BufferObject* _texCoordsBuffer; mutable tgt::BufferObject* _texCoordsBuffer; ///< Pointer to the OpenGL Buffer with the vertex texture coordinates
mutable tgt::BufferObject* _colorsBuffer; mutable tgt::BufferObject* _colorsBuffer; ///< Pointer to the OpenGL Buffer with the vertex colors
mutable tgt::BufferObject* _normalsBuffer; mutable tgt::BufferObject* _normalsBuffer; ///< Pointer to the OpenGL Buffer with the vertex normals
}; };
mutable tgt::BufferObject* _buffers[NUM_BUFFERS]; mutable tgt::BufferObject* _buffers[NUM_BUFFERS]; ///< Array of all buffers
}; };
private: private:
mutable tgt::GLCanvas* _context; ///< OpenGL context the buffers were created in (so that they can be deleted correctly)
static const std::string loggerCat_;
}; };
} }
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universität München
// Boltzmannstr. 3, 85748 Garching b. München, Germany
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
//
// The licensing of this softare is not yet resolved. Until then, redistribution in source or
// binary forms outside the CAMP chair is not permitted, unless explicitly stated in legal form.
// However, the names of the original authors and the above copyright notice must retain in its
// original state in any case.
//
// Legal disclaimer provided by the BSD license:
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// ================================================================================================
#include "geometrydatafactory.h"
#include "tgt/assert.h"
namespace campvis {
FaceGeometry* GeometryDataFactory::createQuad(const tgt::vec3& llf, const tgt::vec3& urb, const tgt::vec3& texLlf, const tgt::vec3& texUrb) {
std::vector<tgt::vec3> vertices, texCorods;
vertices.push_back(tgt::vec3(llf.x, llf.y, llf.z));
vertices.push_back(tgt::vec3(urb.x, llf.y, llf.z));
vertices.push_back(tgt::vec3(urb.x, urb.y, llf.z));
vertices.push_back(tgt::vec3(llf.x, urb.y, llf.z));
texCorods.push_back(tgt::vec3(texLlf.x, texLlf.y, texLlf.z));
texCorods.push_back(tgt::vec3(texUrb.x, texLlf.y, texLlf.z));
texCorods.push_back(tgt::vec3(texUrb.x, texUrb.y, texLlf.z));
texCorods.push_back(tgt::vec3(texLlf.x, texUrb.y, texLlf.z));
return new FaceGeometry(vertices, texCorods);
}
MeshGeometry* GeometryDataFactory::createCube(const tgt::Bounds& bounds, const tgt::Bounds& texBounds) {
const tgt::vec3& llf = bounds.getLLF();
const tgt::vec3& urb = bounds.getURB();
const tgt::vec3& tLlf = texBounds.getLLF();
const tgt::vec3& tUrb = texBounds.getURB();
// not the most elegant method, but it works...
std::vector<tgt::vec3> vertices, texCoords;
std::vector<FaceGeometry> faces;
// front
texCoords.push_back(tgt::vec3(tLlf.x, tUrb.y, tLlf.z));
vertices.push_back(tgt::vec3(llf.x, urb.y, llf.z));
texCoords.push_back(tgt::vec3(tUrb.x, tUrb.y, tLlf.z));
vertices.push_back(tgt::vec3(urb.x, urb.y, llf.z));
texCoords.push_back(tgt::vec3(tUrb.x, tLlf.y, tLlf.z));
vertices.push_back(tgt::vec3(urb.x, llf.y, llf.z));
texCoords.push_back(tgt::vec3(tLlf.x, tLlf.y, tLlf.z));
vertices.push_back(tgt::vec3(llf.x, llf.y, llf.z));
faces.push_back(FaceGeometry(vertices, texCoords));
vertices.clear();
texCoords.clear();
// right
texCoords.push_back(tgt::vec3(tUrb.x, tUrb.y, tLlf.z));
vertices.push_back(tgt::vec3(urb.x, urb.y, llf.z));
texCoords.push_back(tgt::vec3(tUrb.x, tUrb.y, tUrb.z));
vertices.push_back(tgt::vec3(urb.x, urb.y, urb.z));
texCoords.push_back(tgt::vec3(tUrb.x, tLlf.y, tUrb.z));
vertices.push_back(tgt::vec3(urb.x, llf.y, urb.z));
texCoords.push_back(tgt::vec3(tUrb.x, tLlf.y, tLlf.z));
vertices.push_back(tgt::vec3(urb.x, llf.y, llf.z));
faces.push_back(FaceGeometry(vertices, texCoords));
vertices.clear();
texCoords.clear();
// top
texCoords.push_back(tgt::vec3(tLlf.x, tUrb.y, tUrb.z));
vertices.push_back(tgt::vec3(llf.x, urb.y, urb.z));
texCoords.push_back(tgt::vec3(tUrb.x, tUrb.y, tUrb.z));
vertices.push_back(tgt::vec3(urb.x, urb.y, urb.z));
texCoords.push_back(tgt::vec3(tUrb.x, tUrb.y, tLlf.z));
vertices.push_back(tgt::vec3(urb.x, urb.y, llf.z));
texCoords.push_back(tgt::vec3(tLlf.x, tUrb.y, tLlf.z));
vertices.push_back(tgt::vec3(llf.x, urb.y, llf.z));
faces.push_back(FaceGeometry(vertices, texCoords));
vertices.clear();
texCoords.clear();
// left
texCoords.push_back(tgt::vec3(tLlf.x, tUrb.y, tUrb.z));
vertices.push_back(tgt::vec3(llf.x, urb.y, urb.z));
texCoords.push_back(tgt::vec3(tLlf.x, tUrb.y, tLlf.z));
vertices.push_back(tgt::vec3(llf.x, urb.y, llf.z));