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

Introducing MprRenderer processor together with MprDemo pipeline to show its usage.

The MprRenderer renders MPRs of single images by specifying a clipping plane using normal vector and distance to origin.
parent d3d09ca9
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, 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.
//
// ================================================================================================
in vec3 ex_TexCoord;
out vec4 out_Color;
#include "tools/texture3d.frag"
#include "tools/transferfunction.frag"
uniform sampler3D _texture;
uniform TextureParameters3D _textureParams;
uniform sampler1D _transferFunction;
uniform TFParameters1D _transferFunctionParams;
void main() {
out_Color = vec4(0.0, 0.0, 0.0, 0.0);
vec3 samplePos = (_textureParams._worldToTextureMatrix * vec4(ex_TexCoord, 1.0)).xyz;
if (all(greaterThanEqual(samplePos, vec3(0.0))) && all(lessThan(samplePos, vec3(1.0)))) {
vec4 color = texture(_texture, samplePos);
if (_textureParams._numChannels == 1) {
out_Color = lookupTF(_transferFunction, _transferFunctionParams, color.r);
}
else if (_textureParams._numChannels == 3) {
out_Color = vec4(abs(color.rgb), 1.0);
}
else if (_textureParams._numChannels == 4) {
out_Color = (abs(color) - vec4(_transferFunctionParams._intensityDomain.x)) / (_transferFunctionParams._intensityDomain.y - _transferFunctionParams._intensityDomain.x);
}
}
else {
discard;
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, 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 "mprdemo.h"
#include "tgt/event/keyevent.h"
#include "core/datastructures/imagedata.h"
#include "core/classification/geometry1dtransferfunction.h"
#include "core/classification/tfgeometry1d.h"
namespace campvis {
MprDemo::MprDemo(DataContainer* dc)
: AutoEvaluationPipeline(dc)
, _camera("camera", "Camera")
, _lsp()
, _imageReader()
, _mprRenderer(&_canvasSize)
, _compositor(&_canvasSize)
, _trackballEH(0)
{
addProperty(_camera);
_trackballEH = new TrackballNavigationEventListener(&_camera, &_canvasSize);
addEventListenerToBack(_trackballEH);
addProcessor(&_lsp);
addProcessor(&_imageReader);
addProcessor(&_mprRenderer);
addProcessor(&_compositor);
}
MprDemo::~MprDemo() {
delete _trackballEH;
}
void MprDemo::init() {
AutoEvaluationPipeline::init();
_imageReader.s_validated.connect(this, &MprDemo::onProcessorValidated);
_camera.addSharedProperty(&_mprRenderer.p_camera);
_mprRenderer.p_targetImageID.setValue("MPR");
_mprRenderer.p_targetImageID.addSharedProperty(&_compositor.p_firstImageId);
_compositor.p_compositingMethod.selectByOption(RenderTargetCompositor::CompositingModeFirst);
_compositor.p_targetImageId.setValue("final");
_renderTargetID.setValue("final");
_imageReader.p_url.setValue(CAMPVIS_SOURCE_DIR "/modules/vis/sampledata/smallHeart.mhd");
_imageReader.p_targetImageID.setValue("reader.output");
_imageReader.p_targetImageID.addSharedProperty(&_mprRenderer.p_sourceImageID);
Geometry1DTransferFunction* tf = new Geometry1DTransferFunction(128, tgt::vec2(0.f, .08f));
tf->addGeometry(TFGeometry1D::createQuad(tgt::vec2(0.f, 1.f), tgt::col4(0, 0, 0, 255), tgt::col4(255, 255, 255, 255)));
_mprRenderer.p_transferFunction.replaceTF(tf);
}
void MprDemo::deinit() {
_canvasSize.s_changed.disconnect(this);
AutoEvaluationPipeline::deinit();
}
void MprDemo::onProcessorValidated(AbstractProcessor* processor) {
if (processor == &_imageReader) {
// update camera
ScopedTypedData<ImageData> img(*_data, _imageReader.p_targetImageID.getValue());
if (img != 0) {
_trackballEH->reinitializeCamera(img);
}
}
}
}
\ No newline at end of file
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, 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 MPRDEMO_H__
#define MPRDEMO_H__
#include "core/eventhandlers/trackballnavigationeventlistener.h"
#include "core/pipeline/autoevaluationpipeline.h"
#include "core/properties/cameraproperty.h"
#include "modules/base/processors/lightsourceprovider.h"
#include "modules/io/processors/mhdimagereader.h"
#include "modules/vis/processors/mprrenderer.h"
#include "modules/vis/processors/rendertargetcompositor.h"
namespace campvis {
class MprDemo : public AutoEvaluationPipeline {
public:
/**
* Creates a AutoEvaluationPipeline.
*/
MprDemo(DataContainer* dc);
/**
* Virtual Destructor
**/
virtual ~MprDemo();
/// \see AutoEvaluationPipeline::init()
virtual void init();
/// \see AutoEvaluationPipeline::deinit()
virtual void deinit();
/// \see AbstractPipeline::getName()
virtual const std::string getName() const { return getId(); };
static const std::string getId() { return "MprDemo"; };
protected:
/**
* Slot getting called when one of the observed processors got validated.
* Updates the camera properties, when the input image has changed.
* \param processor The processor that emitted the signal
*/
virtual void onProcessorValidated(AbstractProcessor* processor);
CameraProperty _camera;
LightSourceProvider _lsp;
MhdImageReader _imageReader;
MprRenderer _mprRenderer;
RenderTargetCompositor _compositor;
TrackballNavigationEventListener* _trackballEH;
};
}
#endif // MPRDEMO_H__
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, 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 "mprrenderer.h"
#include "tgt/bounds.h"
#include "tgt/logmanager.h"
#include "tgt/shadermanager.h"
#include "tgt/textureunit.h"
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/renderdata.h"
#include "core/datastructures/meshgeometry.h"
#include "core/datastructures/facegeometry.h"
#include "core/datastructures/geometrydatafactory.h"
#include "core/classification/simpletransferfunction.h"
#include "core/tools/quadrenderer.h"
namespace campvis {
const std::string MprRenderer::loggerCat_ = "CAMPVis.modules.vis.MprRenderer";
MprRenderer::MprRenderer(IVec2Property* viewportSizeProp)
: VisualizationProcessor(viewportSizeProp)
, p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ)
, p_targetImageID("targetImageID", "Output Image", "", DataNameProperty::WRITE)
, p_camera("Camera", "Camera")
, p_planeNormal("PlaneNormal", "Clipping Plane Normal", tgt::vec3(0.f, 0.f, 1.f), tgt::vec3(-1.f), tgt::vec3(1.f), tgt::vec3(.1f), tgt::ivec3(2))
, p_planeDistance("PlaneDistance", "Clipping Plane Distance", 0.f, -1000.f, 1000.f, 1.f, 1)
, p_planeSize("PlaneSize", "Clipping Plane Size", 100.f, 0.f, 1000.f, 1.f, 1)
, p_relativeToImageCenter("RelativeToImageCenter", "Construct Plane Relative to Image Center", true)
, p_transferFunction("transferFunction", "Transfer Function", new SimpleTransferFunction(256))
, _shader(nullptr)
{
addProperty(p_sourceImageID, INVALID_RESULT | INVALID_PROPERTIES);
addProperty(p_targetImageID);
addProperty(p_camera);
addProperty(p_planeNormal);
addProperty(p_planeDistance);
addProperty(p_planeSize);
addProperty(p_relativeToImageCenter);
addProperty(p_transferFunction);
}
MprRenderer::~MprRenderer() {
}
void MprRenderer::init() {
VisualizationProcessor::init();
_shader = ShdrMgr.load("core/glsl/passthrough.vert", "modules/vis/glsl/mprrenderer.frag", "");
_shader->setAttributeLocation(0, "in_Position");
_shader->setAttributeLocation(1, "in_TexCoord");
}
void MprRenderer::deinit() {
VisualizationProcessor::deinit();
ShdrMgr.dispose(_shader);
}
void MprRenderer::updateResult(DataContainer& data) {
ImageRepresentationGL::ScopedRepresentation img(data, p_sourceImageID.getValue());
if (img != 0) {
if (img->getDimensionality() == 3) {
const tgt::Camera& cam = p_camera.getValue();
// Construct the clipping plane in world coordinates
tgt::vec3 n = tgt::normalize(p_planeNormal.getValue());
tgt::vec3 temp(1.0, 0.0, 0.0);
if (abs(tgt::dot(temp, n) > 0.9))
temp = tgt::vec3(0.0, 1.0, 0.0);
tgt::vec3 inPlaneA = tgt::normalize(tgt::cross(n, temp)) * 0.5f * p_planeSize.getValue();
tgt::vec3 inPlaneB = tgt::normalize(tgt::cross(n, inPlaneA)) * 0.5f * p_planeSize.getValue();
tgt::vec3 base = (n * -p_planeDistance.getValue());
// move to image center if wanted
if (p_relativeToImageCenter.getValue())
base += img->getParent()->getWorldBounds().center();
// construct the four vertices
std::vector<tgt::vec3> vertices;
vertices.push_back(base + inPlaneA + inPlaneB);
vertices.push_back(base - inPlaneA + inPlaneB);
vertices.push_back(base - inPlaneA - inPlaneB);
vertices.push_back(base + inPlaneA - inPlaneB);
FaceGeometry slice(vertices, vertices);
// perform the rendering
glEnable(GL_DEPTH_TEST);
_shader->activate();
_shader->setIgnoreUniformLocationError(true);
_shader->setUniform("_projectionMatrix", cam.getProjectionMatrix());
_shader->setUniform("_viewMatrix", cam.getViewMatrix());
tgt::TextureUnit inputUnit, tfUnit;
img->bind(_shader, inputUnit);
p_transferFunction.getTF()->bind(_shader, tfUnit);
FramebufferActivationGuard fag(this);
createAndAttachColorTexture();
createAndAttachDepthTexture();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
slice.render(GL_POLYGON);
_shader->deactivate();
tgt::TextureUnit::setZeroUnit();
glDisable(GL_DEPTH_TEST);
data.addData(p_targetImageID.getValue(), new RenderData(_fbo));
}
else {
LERROR("Input image must have dimensionality of 3.");
}
}
else {
LERROR("No suitable input image found.");
}
validate(INVALID_RESULT);
}
void MprRenderer::updateProperties(DataContainer& dc) {
ScopedTypedData<ImageData> img(dc, p_sourceImageID.getValue());
if (img != 0) {
p_transferFunction.setVisible(img->getNumChannels() == 1);
}
p_transferFunction.setImageHandle(img.getDataHandle());
validate(AbstractProcessor::INVALID_PROPERTIES);
}
}
// ================================================================================================
//
// This file is part of the CAMPVis Software Framework.
//
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
// Christian Schulte zu Berge <christian.szb@in.tum.de>
// Chair for Computer Aided Medical Procedures
// Technische Universitaet Muenchen
// Boltzmannstr. 3, 85748 Garching b. Muenchen, 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 MPRRENDERER_H__
#define MPRRENDERER_H__
#include <string>
#include "core/pipeline/visualizationprocessor.h"
#include "core/properties/allproperties.h"
namespace tgt {
class Shader;
}
namespace campvis {
class ImageData;
/**
* Extracts arbitrary MPRs from images using a single clip plane.
*/
class MprRenderer : public VisualizationProcessor {
public:
/**
* Constructs a new MprRenderer Processor
**/
MprRenderer(IVec2Property* viewportSizeProp);
/**
* Destructor
**/
virtual ~MprRenderer();
/// \see AbstractProcessor::init
virtual void init();
/// \see AbstractProcessor::deinit
virtual void deinit();
/// \see AbstractProcessor::getName()
virtual const std::string getName() const { return "MprRenderer"; };
/// \see AbstractProcessor::getDescription()
virtual const std::string getDescription() const { return "Extracts arbitrary MPRs from images using a single clip plane."; };
/// \see AbstractProcessor::getAuthor()
virtual const std::string getAuthor() const { return "Christian Schulte zu Berge <christian.szb@in.tum.de>"; };
/// \see AbstractProcessor::getProcessorState()
virtual ProcessorState getProcessorState() const { return AbstractProcessor::EXPERIMENTAL; };
DataNameProperty p_sourceImageID; ///< image ID for input image
DataNameProperty p_targetImageID; ///< image ID for output image
CameraProperty p_camera;
Vec3Property p_planeNormal; ///< Clipping plane normal
FloatProperty p_planeDistance; ///< Clipping plane distance
FloatProperty p_planeSize; ///< Size of clipping plane
BoolProperty p_relativeToImageCenter; ///< Flag whether to construct image plane relative to image center
TransferFunctionProperty p_transferFunction; ///< Transfer function
protected:
/// \see AbstractProcessor::updateResult
virtual void updateResult(DataContainer& dataContainer);
/// \see AbstractProcessor::updateProperties
virtual void updateProperties(DataContainer& dataContainer);
tgt::Shader* _shader; ///< Shader for slice rendering
static const std::string loggerCat_;
};
}
#endif // MPRRENDERER_H__
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment