The expiration time for new job artifacts in CI/CD pipelines is now 30 days (GitLab default). Previously generated artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

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

Cleaned up AdvOptimizedRaycaster implementation.

parent 277bea82
......@@ -56,6 +56,7 @@ namespace campvis {
}
void VisualizationProcessor::deinit() {
_viewportSizeProperty->s_changed.disconnect(this);
_viewportSizeProperty->s_changed.disconnect(this);
delete _fbo;
AbstractProcessor::deinit();
......
......@@ -131,6 +131,7 @@ namespace campvis {
void HasPropertyCollection::deinitAllProperties() {
for (PropertyCollection::iterator it = _properties.begin(); it != _properties.end(); ++it) {
(*it)->deinit();
(*it)->s_changed.disconnect(this);
}
}
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, 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".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "VoxelTextureMipMapping.h"
#include "tgt/shadermanager.h"
#include "tgt/textureunit.h"
#include "tgt/tgt_gl.h"
#include "core/datastructures/geometrydatafactory.h"
#define VOXEL_DEPTH_MIPMAPPING 32
namespace campvis {
VoxelTexMipMapGenerator::VoxelTexMipMapGenerator() {
_quad = GeometryDataFactory::createQuad(tgt::vec3(0.f), tgt::vec3(1.f), tgt::vec3(1.f, 1.f, 0.f), tgt::vec3(0.f, 0.f, 0.f));
_shader = ShdrMgr.loadWithCustomGlslVersion("core/glsl/passthrough.vert", "", "modules/vis/advraycaster/glsl/MipmapVoxelTexture.frag", "", "330");
}
void VoxelTexMipMapGenerator::init() {
}
unsigned int VoxelTexMipMapGenerator::computeMaxLevel(unsigned int resolutionX, unsigned int resolutionY) {
unsigned int count = 0;
unsigned int resolution = std::max(resolutionX, resolutionY);
while(resolution){
resolution /= 2;
count++;
}
return count-1;
}
void VoxelTexMipMapGenerator::attachMipmapsTo(tgt::Texture* texture, unsigned int resolutionX, unsigned int resolutionY) {
unsigned int maxLevel = computeMaxLevel(resolutionX, resolutionY);
LGL_ERROR;
// attach mipmap levels to this voxel texture
glBindTexture(GL_TEXTURE_2D, texture->getId());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
LGL_ERROR;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
LGL_ERROR;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
LGL_ERROR;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel);
LGL_ERROR;
int div = 2;
for(unsigned int level = 1; level <= maxLevel; level++){
#if (VOXEL_DEPTH_MIPMAPPING == 8)
glTexImage2D(GL_TEXTURE_2D, level, GL_R32UI, resolutionX/div, resolutionY/div, 0, GL_RED_INTEGER_EXT, GL_UNSIGNED_BYTE, 0);
#else if (VOXEL_DEPTH_MIPMAPPING == 32)
glTexImage2D(GL_TEXTURE_2D, level, GL_R32UI, resolutionX/div, resolutionY/div, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, 0);
#endif
div = div << 1;
LGL_ERROR;
}
}
void VoxelTexMipMapGenerator::renderMipmapsFor(tgt::Texture* texture, unsigned int resolutionX, unsigned int resolutionY, unsigned int voxelSize) {
glPushAttrib(GL_ALL_ATTRIB_BITS);
LGL_ERROR;
unsigned int maxLevel = computeMaxLevel(resolutionX, resolutionY);
tgt::FramebufferObject frameBuffer;
LGL_ERROR;
/// Activate the shader for geometry Rendering.
_shader->activate();
tgt::TextureUnit bbvUnit;
bbvUnit.activate();
texture->bind();
LGL_ERROR;
_shader->setIgnoreUniformLocationError(true);
_shader->setUniform("_voxelTexture", bbvUnit.getUnitNumber());
LGL_ERROR;
_shader->setUniform("_voxelTextureParams._size", tgt::vec2(static_cast<float>(texture->getDimensions().r), static_cast<float>(texture->getDimensions().g)));
LGL_ERROR;
_shader->setUniform("_voxelTextureParams._sizeRCP", tgt::vec3(1.f) / tgt::vec3(texture->getDimensions()));
LGL_ERROR;
_shader->setUniform("_voxelTextureParams._numChannels", static_cast<int>(1));
LGL_ERROR;
_shader->setIgnoreUniformLocationError(false);
LGL_ERROR;
frameBuffer.activate();
// Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(unsigned int i = 0; i < maxLevel; i++){
// Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
tgt::mat4 projection = tgt::mat4::createOrtho(0, 1, 0, 1, -1, 1);
_shader->setUniform("_projectionMatrix", projection);
_shader->setUniform("_level", static_cast<int>(i));
float invResXFloat = static_cast<float>( 1.0/(resolutionX/pow(2.0,double(i))) );
float invResYFloat = static_cast<float>( 1.0/(resolutionY/pow(2.0,double(i))) );
_shader->setUniform("_inverseTexSizeX", static_cast<float>(invResXFloat));
_shader->setUniform("_inverseTexSizeY", static_cast<float>(invResYFloat));
LGL_ERROR;
glViewport(0, 0, static_cast<GLsizei>(resolutionX/pow(2.0,double(i+1))), static_cast<GLsizei>(resolutionY/pow(2.0,double(i+1))));
frameBuffer.attachTexture(texture, GL_COLOR_ATTACHMENT0, i+1, 0);
frameBuffer.isComplete();
LGL_ERROR;
_quad->render(GL_POLYGON);
LGL_ERROR;
}
_shader->deactivate();
frameBuffer.deactivate();
glPopAttrib();
LGL_ERROR;
}
VoxelTexMipMapGenerator::~VoxelTexMipMapGenerator() {
ShdrMgr.dispose(_shader);
delete _quad;
}
}
\ No newline at end of file
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, 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".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#include "rendervolumevoxelizing.h"
#include "tgt/assert.h"
#include "tgt/glmath.h"
#include "tgt/texture.h"
#include "tgt/textureunit.h"
#include "tgt/tgt_gl.h"
#include "core/datastructures/genericimagerepresentationlocal.h"
#define DIV_CEIL(x,y) ((x) > 0) ? (1 + ((x) - 1)/(y)) : ((x) / (y))
namespace campvis {
VoxelizedRenderVolume::VoxelizedRenderVolume(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:
// z is not considered.
_dimBricks = referenceImage->getSize();
for (int i = 0; i < 2; ++i)
_dimBricks.elem[i] = DIV_CEIL(_dimBricks.elem[i], _brickSize);
// set the depth of the bricks
_brickDepth = _dimBricks.z / VOXEL_DEPTH;
// since the texture is a 2D texture and the elements store the depth will pack VOXEL_DEPTH number of values along the z axis into one block, the _dimBricks.z is
_dimBricks.z = VOXEL_DEPTH;
_numBrickIndices = tgt::hmul(_dimBricks);
_dimPackedBricks = _dimBricks;
_dimPackedBricks.z = _dimPackedBricks.z / VOXEL_DEPTH;
_numElementsInBricksArray = tgt::hmul(_dimPackedBricks);
#if (VOXEL_DEPTH == 8)
_bricks = new uint8_t[_numElementsInBricksArray];
memset(_bricks, 0, _numElementsInBricksArray);
#else if(VOXEL_DEPTH == 32)
_bricks = new uint32_t[_numElementsInBricksArray];
memset(_bricks, 0, 4 * _numElementsInBricksArray);
#endif
}
VoxelizedRenderVolume::~VoxelizedRenderVolume() {
delete _bricks;
}
std::vector<tgt::svec3> VoxelizedRenderVolume::getAllVoxelsForBrick(size_t brickIndex) const {
tgt::ivec3 refImageSize = _referenceImage->getSize();
std::vector<tgt::svec3> toReturn;
toReturn.reserve((_brickSize+2) * (_brickSize+2) * (_brickDepth+2));
// traverse each dimension, check that voxel is within reference image size
tgt::ivec3 startVoxel = indexToBrick(brickIndex);
startVoxel.x *= _brickSize;
startVoxel.y *= _brickSize;
startVoxel.z *= _brickDepth;
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>(_brickDepth + 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 VoxelizedRenderVolume::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 * _dimBricks.y)) % _dimBricks.x;
return tgt::svec3(x, y, z);
}
size_t VoxelizedRenderVolume::brickToIndex(const tgt::svec3& brick) const {
return brick.x + (_dimBricks.x * brick.y) + (_dimBricks.x * _dimBricks.y * brick.z);
}
bool VoxelizedRenderVolume::getValueForIndex(size_t brickIndex) const {
size_t byte = brickIndex % (_dimBricks.x * _dimBricks.y);
size_t bit = brickIndex / (_dimBricks.x * _dimBricks.y);
tgtAssert(byte < _numElementsInBricksArray, "Brick brickIndex out of bounds!");
return (_bricks[byte] & (1 << bit)) != 0;
}
void VoxelizedRenderVolume::setValueForIndex(size_t brickIndex, bool value) {
size_t byte = brickIndex % (_dimBricks.x * _dimBricks.y);
size_t bit = brickIndex / (_dimBricks.x * _dimBricks.y);
tgtAssert(byte < _numElementsInBricksArray, "Brick brickIndex out of bounds!");
#if (VOXEL_DEPTH == 8)
if (value)
_bricks[byte] |= static_cast<uint8_t>(1 << bit);
else
_bricks[byte] &= static_cast<uint8_t>(~(1 << bit));
#else if(VOXEL_DEPTH == 32)
if (value)
_bricks[byte] |= static_cast<uint32_t>(1 << bit);
else
_bricks[byte] &= static_cast<uint32_t>(~(1 << bit));
#endif
}
tgt::Texture* VoxelizedRenderVolume::createEmptyImageData() const {
#if(VOXEL_DEPTH == 8)
tgt::Texture* toReturn = new tgt::Texture(0, _dimPackedBricks, GL_RED_INTEGER, GL_R32UI, GL_UNSIGNED_BYTE, tgt::Texture::NEAREST);
#else if(VOXEL_DEPTH == 32)
tgt::Texture* toReturn = new tgt::Texture(0, _dimPackedBricks, GL_RED_INTEGER, GL_R32UI, GL_UNSIGNED_INT, tgt::Texture::NEAREST);
#endif
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);
LGL_ERROR;
return toReturn;
}
tgt::Texture* VoxelizedRenderVolume::exportToImageData() const {
#if(VOXEL_DEPTH == 8)
tgt::Texture* toReturn = new tgt::Texture(_bricks, _dimPackedBricks, GL_RED_INTEGER, GL_R32UI, GL_UNSIGNED_BYTE, tgt::Texture::NEAREST);
#else if(VOXEL_DEPTH == 32)
tgt::Texture* toReturn = new tgt::Texture((GLubyte*)_bricks, _dimPackedBricks, GL_RED_INTEGER, GL_R32UI, GL_UNSIGNED_INT, tgt::Texture::NEAREST);
#endif
LGL_ERROR;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
tgt::TextureUnit tempUnit;
tempUnit.activate();
toReturn->bind();
toReturn->uploadTexture();
LGL_ERROR;
toReturn->setWrapping(tgt::Texture::CLAMP);
LGL_ERROR;
return toReturn;
}
const tgt::svec3& VoxelizedRenderVolume::getNumBricks() const {
return _dimBricks;
}
size_t VoxelizedRenderVolume::getNumBrickIndices() const {
return _numBrickIndices;
}
size_t VoxelizedRenderVolume::getBrickSize() const {
return _brickSize;
}
size_t VoxelizedRenderVolume::getBrickDepth() const {
return _brickDepth;
}
int VoxelizedRenderVolume::getMaxDim() const {
return std::max(_dimPackedBricks.x, _dimPackedBricks.y);
}
int VoxelizedRenderVolume::getWidth() {
return _dimPackedBricks.x;
}
int VoxelizedRenderVolume::getHeight() {
return _dimPackedBricks.y;
}
}
\ No newline at end of file
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, 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".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
#ifndef VOLUMEVOXELIZING_H__
#define VOLUMEVOXELIZING_H__
#include "tgt/vector.h"
#include "core/datastructures/imagedata.h"
#include <vector>
#define VOXEL_DEPTH 32
namespace tgt {
class Texture;
}
namespace campvis {
class VoxelizedRenderVolume {
public:
VoxelizedRenderVolume(const ImageData* referenceImage, size_t brickSize);
~VoxelizedRenderVolume();
/**
* 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 its width and height.
* \return _brickSize
*/
size_t getBrickSize() const;
/**
* Gets the number of voxels a brick is covering in its depth.
* \return _brickDepth
*/
size_t getBrickDepth() const;
/**
* Gets the maximum value in the dimensions of the voxelized volume.
* \return maximum between the
*/
int getMaxDim() const;
int getWidth();
int getHeight();
/**
* 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;
/**
* Create an empty texture and return it.
* \return the created empty image.
*/
tgt::Texture* createEmptyImageData() const;
/**
* Create a texture and fill it with data in _bricks array and returns it.
* \return the texture filled with _bricks data.
*/
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 x, y dimension
size_t _brickDepth; ///< number of voxel a brick is covering in its depth dimension
tgt::svec3 _dimBricks; ///< number of bricks in each dimension
size_t _numBrickIndices; ///< number of brick indices (= hmul(_dimPackedBricks))
#if(VOXEL_DEPTH == 8)
uint8_t* _bricks; ///< the densly packed bricks
#else if(VOXEL_DEPTH == 32)
uint32_t* _bricks; ///< the densly packed bricks
#endif
float* _maxVals; ///< Array of maximum values in a brick
float* _minVals; ///< Array of minimum values in a brick
tgt::svec3 _dimPackedBricks; ///< number of elements when bricks are tightly packed
size_t _numElementsInBricksArray; ///< number of elements in _bricks
};
}
#endif // VOLUMEVOXELIZING_H__
......@@ -58,10 +58,8 @@ uniform TFParameters1D _transferFunctionParams;
// BBV Lookup volume
uniform usampler2D _vvTexture;
uniform TextureParameters2D _vvTextureParams;
uniform int _vvVoxelSize;
uniform int _vvVoxelDepth;
uniform bool _hasVv;
uniform int _vvMaxMipMapLevel;
......
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2013, 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".
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// ================================================================================================
subroutine void ComputationRoutineType();
subroutine uniform ComputationRoutineType ComputationRoutine;