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

Merge branch 'emptyspaceskipping' of /mnt/bigone/git/repositories/berge/campvis into development

parents 1f2404a4 d8464aea
......@@ -64,9 +64,14 @@ namespace campvis {
* Destructor, make sure to delete the OpenGL texture beforehand by calling deinit() with a valid OpenGL context!
*/
virtual ~GenericGeometryTransferFunction();
/**
* Initializes the Shader, hence, this methods has to be called from a thread with a valid OpenGL context!
*/
virtual void initShader();
/**
* Deletes the OpenGL texture, hence, this methods has to be called from a thread with a valid OpenGL context!
* Deletes the OpenGL texture and shader, hence, this methods has to be called from a thread with a valid OpenGL context!
*/
virtual void deinit();
......@@ -107,6 +112,7 @@ namespace campvis {
std::vector<T*> _geometries; ///< The list of transfer function geometries.
tgt::FramebufferObject* _fbo; ///< The FBO used for render into texture.
tgt::Shader* _shader; ///< Shader for rendering the TF into a texture
};
// ================================================================================================
......@@ -115,20 +121,36 @@ namespace campvis {
campvis::GenericGeometryTransferFunction<T>::GenericGeometryTransferFunction(const tgt::vec3& size, const tgt::vec2& intensityDomain /*= tgt::vec2(0.f, 1.f)*/)
: AbstractTransferFunction(size, intensityDomain)
, _fbo(0)
, _shader(0)
{
}
template<class T>
campvis::GenericGeometryTransferFunction<T>::~GenericGeometryTransferFunction() {
for (typename std::vector<T*>::iterator it = _geometries.begin(); it != _geometries.end(); ++it) {
(*it)->s_changed.disconnect(this);
delete *it;
}
template<class T>
void campvis::GenericGeometryTransferFunction<T>::initShader() {
_shader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "core/glsl/passthrough.frag", "", false);
if (_shader != 0) {
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
_shader->setAttributeLocation(2, "in_Color");
}
else {
LERROR("Could not create Shader for Rendering the TF into the lookup texture!");
}
}
template<class T>
void campvis::GenericGeometryTransferFunction<T>::deinit() {
for (typename std::vector<T*>::iterator it = _geometries.begin(); it != _geometries.end(); ++it) {
(*it)->s_changed.disconnect(this);
delete *it;
}
_geometries.clear();
if (_fbo != 0) {
_fbo->activate();
_fbo->detachAll();
......@@ -137,6 +159,8 @@ namespace campvis {
_fbo = 0;
}
ShdrMgr.dispose(_shader);
_shader = 0;
AbstractTransferFunction::deinit();
}
......@@ -183,6 +207,10 @@ namespace campvis {
template<class T>
void campvis::GenericGeometryTransferFunction<T>::createTexture() {
if (_shader == 0) {
initShader();
}
// acqiure a new TextureUnit, so that we don't mess with other currently bound textures during texture upload...
tgt::TextureUnit tfUnit;
tfUnit.activate();
......@@ -218,33 +246,20 @@ namespace campvis {
LGL_ERROR;
// render TF geometries into texture
glPushAttrib(GL_ALL_ATTRIB_BITS);
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, _texture->getWidth(), _texture->getHeight());
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, 1, 0, 1, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
_shader->activate();
_shader->setUniform("_projectionMatrix", tgt::mat4::createOrtho(0, 1, 0, 1, -1, 1));
LGL_ERROR;
for (typename std::vector<T*>::const_iterator it = _geometries.begin(); it != _geometries.end(); ++it) {
(*it)->render();
}
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
LGL_ERROR;
// deactivate FBO
// deactivate Shader and FBO
_shader->deactivate();
_fbo->deactivate();
LGL_ERROR;
......
......@@ -33,6 +33,8 @@
#include "tgt/texture.h"
#include "tgt/tgt_math.h"
#include "core/datastructures/facegeometry.h"
#include <algorithm>
namespace campvis {
......@@ -86,19 +88,20 @@ namespace campvis {
if (_keyPoints.size() < 2)
return;
glBegin(GL_QUADS);
std::vector<KeyPoint>::const_iterator a = _keyPoints.begin();
std::vector<KeyPoint>::const_iterator b = _keyPoints.begin()+1;
for (/* already inited */; b != _keyPoints.end(); ++a, ++b) {
glColor4ubv(a->_color.elem);
glVertex2f(a->_position, 0.f);
glVertex2f(a->_position, 1.f);
// TODO: regenerating these buffers each time is slow as hell
std::vector<tgt::vec3> vertices;
std::vector<tgt::vec4> colors;
glColor4ubv(b->_color.elem);
glVertex2f(b->_position, 1.f);
glVertex2f(b->_position, 0.f);
for (std::vector<KeyPoint>::const_iterator a = _keyPoints.begin(); a != _keyPoints.end(); ++a) {
vertices.push_back(tgt::vec3(a->_position, 0.f, 0.f));
vertices.push_back(tgt::vec3(a->_position, 1.f, 0.f));
colors.push_back(tgt::vec4(a->_color) / 255.f);
colors.push_back(tgt::vec4(a->_color) / 255.f);
}
glEnd();
FaceGeometry fg(vertices, vertices, colors);
fg.render(GL_TRIANGLE_STRIP);
}
TFGeometry1D* TFGeometry1D::createQuad(const tgt::vec2& interval, const tgt::col4& leftColor, const tgt::vec4& rightColor) {
tgtAssert(interval.x >= 0.f && interval.y <= 1.f, "Interval out of bounds");
......
// ================================================================================================
//
// 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.
//
// ================================================================================================
in vec4 ex_Color; ///< incoming color
out vec4 out_Color;
void main() {
out_Color = ex_Color;
}
......@@ -65,7 +65,8 @@ namespace campvis {
VALID = 0, ///< Valid
INVALID_RESULT = 1 << 0, ///< Need to rerun the process() method
INVALID_SHADER = 1 << 1, ///< Need to recompile the shader
INVALID_PROPERTIES = 1 << 2 ///< Need to update the properties
INVALID_PROPERTIES = 1 << 2, ///< Need to update the properties
FIRST_FREE_TO_USE_INVALIDATION_LEVEL = 1 << 3
};
/// Current state of a processor in terms of stability.
......
......@@ -58,7 +58,7 @@ namespace campvis {
return _invalidationLevel;
}
void AbstractProperty::setInvalidationLevel(AbstractProcessor::InvalidationLevel il) {
void AbstractProperty::setInvalidationLevel(int il) {
_invalidationLevel = il;
}
......
......@@ -96,7 +96,7 @@ namespace campvis {
* Sets the invalidation level that this property triggers.
* \param il New invalidation level that this property triggers.
*/
void setInvalidationLevel(AbstractProcessor::InvalidationLevel il);
void setInvalidationLevel(int il);
/**
* Returns whether this proberty shall be visible in the GUI.
......
// ================================================================================================
//
// 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 "volumebricking.h"
#include "tgt/assert.h"
#include "tgt/glmath.h"
#include "tgt/texture.h"
#include "tgt/textureunit.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
#define DIV_CEIL(x,y) ((x) > 0) ? (1 + ((x) - 1)/(y)) : ((x) / (y))
namespace campvis {
BinaryBrickedVolume::BinaryBrickedVolume(const ImageData* referenceImage, size_t brickSize)
: _referenceImage(referenceImage)
, _brickSize(brickSize)
, _bricks(0)
{
tgtAssert(_referenceImage != 0, "Reference Image must not be 0!");
// perform ceiling integer division:
_dimBricks = referenceImage->getSize();
for (int i = 0; i < 3; ++i)
_dimBricks.elem[i] = DIV_CEIL(_dimBricks.elem[i], _brickSize);
// since we will pack eight values along the x axis into one byte, the _dimBricks.x must be congruent 0 mod 8.
if (_dimBricks.x % 8 != 0)
_dimBricks.x += 8 - (_dimBricks.x % 8);
_numBrickIndices = tgt::hmul(_dimBricks);
_dimPackedBricks = _dimBricks;
_dimPackedBricks.x = _dimPackedBricks.x / 8;
_numElementsInBricksArray = tgt::hmul(_dimPackedBricks);
_bricks = new uint8_t[_numElementsInBricksArray];
memset(_bricks, 0, _numElementsInBricksArray);
}
BinaryBrickedVolume::~BinaryBrickedVolume() {
delete _bricks;
}
std::vector<tgt::svec3> BinaryBrickedVolume::getAllVoxelsForBrick(size_t brickIndex) const {
tgt::ivec3 refImageSize = _referenceImage->getSize();
std::vector<tgt::svec3> toReturn;
toReturn.reserve((_brickSize+2) * (_brickSize+2) * (_brickSize+2));
// traverse each dimension, check that voxel is within reference image size
tgt::ivec3 startVoxel = indexToBrick(brickIndex) * _brickSize;
for (int x = -1; x < static_cast<int>(_brickSize + 1); ++x) {
int xx = startVoxel.x + x;
if (xx < 0)
continue;
else if (xx >= refImageSize.x)
break;
for (int y = -1; y < static_cast<int>(_brickSize + 1); ++y) {
int yy = startVoxel.y + y;
if (yy < 0)
continue;
else if (yy >= refImageSize.y)
break;
for (int z = -1; z < static_cast<int>(_brickSize + 1); ++z) {
int zz = startVoxel.z + z;
if (zz < 0)
continue;
else if (zz >= refImageSize.z)
break;
toReturn.push_back(tgt::svec3(xx, yy, zz));
}
}
}
return toReturn;
}
tgt::svec3 BinaryBrickedVolume::indexToBrick(size_t brickIndex) const {
size_t z = brickIndex / (_dimBricks.x * _dimBricks.y);
size_t y = (brickIndex % (_dimBricks.x * _dimBricks.y)) / _dimBricks.x;
size_t x = brickIndex % _dimBricks.x;
return tgt::svec3(x, y, z);
}
size_t BinaryBrickedVolume::brickToIndex(const tgt::svec3& brick) const {
return brick.x + (_dimBricks.x * brick.y) + (_dimBricks.x * _dimBricks.y * brick.z);
}
bool BinaryBrickedVolume::getValueForIndex(size_t brickIndex) const {
size_t byte = brickIndex / 8;
size_t bit = brickIndex % 8;
tgtAssert(brickIndex < _numElementsInBricksArray, "Brick brickIndex out of bounds!");
return (_bricks[byte] & (1 << bit)) != 0;
}
void BinaryBrickedVolume::setValueForIndex(size_t brickIndex, bool value) {
size_t byte = brickIndex / 8;
size_t bit = brickIndex % 8;
tgtAssert(byte < _numElementsInBricksArray, "Brick brickIndex out of bounds!");
if (value)
_bricks[byte] |= (1 << bit);
else
_bricks[byte] &= ~(1 << bit);
}
tgt::Texture* BinaryBrickedVolume::exportToImageData() const {
tgt::Texture* toReturn = new tgt::Texture(_bricks, _dimPackedBricks, GL_RED_INTEGER, GL_R8UI, GL_UNSIGNED_BYTE, tgt::Texture::NEAREST);
LGL_ERROR;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
tgt::TextureUnit tempUnit;
tempUnit.activate();
toReturn->bind();
toReturn->uploadTexture();
LGL_ERROR;
toReturn->setWrapping(tgt::Texture::CLAMP);
toReturn->setPixelData(0);
tgt::TextureUnit::setZeroUnit();
LGL_ERROR;
return toReturn;
// uint8_t* copy = new uint8_t[_numElementsInBricksArray];
// memcpy(copy, _bricks, _numElementsInBricksArray);
//
// ImageData* toReturn = new ImageData(_referenceImage->getDimensionality(), _dimPackedBricks, 1);
// GenericImageRepresentationLocal<uint8_t, 1>::create(toReturn, copy);
// return toReturn;
}
const tgt::svec3& BinaryBrickedVolume::getNumBricks() const {
return _dimBricks;
}
size_t BinaryBrickedVolume::getNumBrickIndices() const {
return _numBrickIndices;
}
size_t BinaryBrickedVolume::getBrickSize() const {
return _brickSize;
}
}
\ No newline at end of file
#ifndef VOLUMEBRICKING_H__
#define VOLUMEBRICKING_H__
#include "tgt/vector.h"
#include "core/datastructures/imagedata.h"
#include <vector>
namespace tgt {
class Texture;
}
namespace campvis {
class BinaryBrickedVolume {
public:
BinaryBrickedVolume(const ImageData* referenceImage, size_t brickSize);
~BinaryBrickedVolume();
/**
* Gets the number of bricks in each dimension.
* \return _dimBricks
*/
const tgt::svec3& getNumBricks() const;
/**
* Gets the number of brick indices (= hmul(_dimBricks)).
* \return _numBrickIndices
*/
size_t getNumBrickIndices() const;
/**
* Gets the number of voxels a brick is covering in each dimension.
* \return _brickSize
*/
size_t getBrickSize() const;
/**
* Returns the boolean value for the brick with index \a brickIndex.
* \param brickIndex Lookup brick index
* \return The boolean value for the brick with index \a brickIndex.
*/
bool getValueForIndex(size_t brickIndex) const;
/**
* Sets the boolean value for the brick with index \a brickIndex to \a value.
* \param brickIndex Lookup brick index
* \param value The new boolean value for this brick.
*/
void setValueForIndex(size_t brickIndex, bool value);
/**
* Return a vector of all voxels positions in the reference image that are in the brick with the index \a brickIndex.
* \param brickIndex Lookup brick index.
* \return A vector of all voxels positions in the reference image that are in the brick with the index \a brickIndex.
*/
std::vector<tgt::svec3> getAllVoxelsForBrick(size_t brickIndex) const;
tgt::Texture* exportToImageData() const;
private:
/**
* Returns the brick coordinates for the brick with index \a brickIndex.
* \param brickIndex The Brick index to look up
* \return The corresponding 3D brick coordinates.
*/
tgt::svec3 indexToBrick(size_t brickIndex) const;
/**
* Transforms brick coordinates to the corresponding index.
* \param brick Brick coordinates.
* \return The corresponding index in if all bricks are in contiguous storage.
*/
size_t brickToIndex(const tgt::svec3& brick) const;
const ImageData* _referenceImage; ///< the reference image
size_t _brickSize; ///< number of voxels a brick is covering in each dimension
tgt::svec3 _dimBricks; ///< number of bricks in each dimension
size_t _numBrickIndices; ///< number of brick indices (= hmul(_dimPackedBricks))
uint8_t* _bricks; ///< the densly packed bricks
tgt::svec3 _dimPackedBricks; ///< number of elements when bricks are tightly packed
size_t _numElementsInBricksArray; ///< number of elements in _bricks
};
}
#endif // VOLUMEBRICKING_H__
......@@ -219,6 +219,7 @@ int Texture::calcNumChannels(GLint format) {
case 1:
case GL_COLOR_INDEX:
case GL_RED:
case GL_RED_INTEGER:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
......
// ================================================================================================
//
// 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 Universitt Mnchen
// Boltzmannstr. 3, 85748 Garching b. Mnchen, 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.
//
// ================================================================================================
layout(location = 0) out vec4 out_Color; ///< outgoing fragment color
layout(location = 1) out vec4 out_FHP; ///< outgoing fragment first hitpoint
layout(location = 2) out vec4 out_FHN; ///< outgoing fragment first hit normal
#include "tools/gradient.frag"
#include "tools/raycasting.frag"
#include "tools/shading.frag"
#include "tools/texture2d.frag"
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"
uniform vec2 _viewportSizeRCP;
uniform float _jitterStepSizeMultiplier;
// ray entry points
uniform sampler2D _entryPoints;
uniform sampler2D _entryPointsDepth;
uniform TextureParameters2D _entryParams;
// ray exit points
uniform sampler2D _exitPoints;
uniform sampler2D _exitPointsDepth;
uniform TextureParameters2D _exitParams;
// DRR volume
uniform sampler3D _volume;
uniform TextureParameters3D _volumeTextureParams;
// Transfer function
uniform sampler1D _transferFunction;
uniform TFParameters1D _transferFunctionParams;
// BBV Lookup volume
uniform usampler3D _bbvTexture;
uniform TextureParameters3D _bbvTextureParams;
uniform int _bbvBrickSize;
uniform bool _hasBbv;
uniform LightSource _lightSource;
uniform vec3 _cameraPosition;
uniform float _samplingStepSize;
#ifdef INTERSECTION_REFINEMENT
bool _inVoid = false;
#endif
#ifdef ENABLE_SHADOWING
uniform float _shadowIntensity;
#endif
const float positiveInfinity = 1.0 / 0.0;
// TODO: copy+paste from Voreen - eliminate or improve.
const float SAMPLING_BASE_INTERVAL_RCP = 200.0;
ivec3 voxelToBrick(in vec3 voxel) {
return ivec3(floor(voxel / _bbvBrickSize));
}
// samplePosition is in texture coordiantes [0, 1]
bool lookupInBbv(in vec3 samplePosition) {
ivec3 byte = voxelToBrick(samplePosition * _volumeTextureParams._size);