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;
in vec3 ex_TexCoord; ///< incoming texture coordinate