11.3.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

slicerenderer3d.cpp 6.11 KB
Newer Older
1 2 3 4
// ================================================================================================
// 
// This file is part of the CAMPVis Software Framework.
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2014, all rights reserved,
6 7
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
//      Chair for Computer Aided Medical Procedures
8 9
//      Technische Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, Germany
10
// 
11 12
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
// 
13 14 15 16
// 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
17
// 
18 19 20 21
// 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.
22 23 24 25
// 
// ================================================================================================

#include "slicerenderer3d.h"
26 27 28 29
#include "cgt/bounds.h"
#include "cgt/logmanager.h"
#include "cgt/shadermanager.h"
#include "cgt/textureunit.h"
30

31
#include "core/datastructures/cameradata.h"
32
#include "core/datastructures/imagedata.h"
33
#include "core/datastructures/imagerepresentationgl.h"
34
#include "core/datastructures/renderdata.h"
35

36 37
#include "core/datastructures/meshgeometry.h"
#include "core/datastructures/facegeometry.h"
38
#include "core/datastructures/geometrydatafactory.h"
39 40 41 42 43 44 45 46

#include "core/classification/simpletransferfunction.h"

#include "core/tools/quadrenderer.h"

namespace campvis {
    const std::string SliceRenderer3D::loggerCat_ = "CAMPVis.modules.vis.SliceRenderer3D";

47 48
    SliceRenderer3D::SliceRenderer3D(IVec2Property* viewportSizeProp)
        : VisualizationProcessor(viewportSizeProp)
49
        , p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ)
50
        , p_camera("Camera", "Camera ID", "camera", DataNameProperty::READ)
51 52 53 54 55
        , p_targetImageID("targetImageID", "Output Image", "", DataNameProperty::WRITE)
        , p_sliceNumber("sliceNumber", "Slice Number", 0, 0, 0)
        , p_transferFunction("transferFunction", "Transfer Function", new SimpleTransferFunction(256))
        , _shader(0)
    {
56 57
        addProperty(p_sourceImageID, INVALID_RESULT | INVALID_PROPERTIES);
        addProperty(p_camera);
58
        addProperty(p_targetImageID);
59 60
        addProperty(p_sliceNumber);
        addProperty(p_transferFunction);
61 62 63 64 65 66 67 68
    }

    SliceRenderer3D::~SliceRenderer3D() {

    }

    void SliceRenderer3D::init() {
        VisualizationProcessor::init();
69
        _shader = ShdrMgr.load("core/glsl/passthrough.vert", "modules/vis/glsl/slicerenderer3d.frag", "");
70 71 72 73 74 75 76
    }

    void SliceRenderer3D::deinit() {
        VisualizationProcessor::deinit();
        ShdrMgr.dispose(_shader);
    }

77
    void SliceRenderer3D::updateResult(DataContainer& data) {
78
        ImageRepresentationGL::ScopedRepresentation img(data, p_sourceImageID.getValue());
79
        ScopedTypedData<CameraData> camera(data, p_camera.getValue());
80

81
        if (img != nullptr && camera != nullptr) {
82
            if (img->getDimensionality() == 3) {
83
                const cgt::Camera& cam = camera->getCamera();
84 85 86 87 88

                // Creating the slice proxy geometry works as follows:
                // Create the cube proxy geometry for the volume, then clip the cube against the slice plane.
                // The closing face is the slice proxy geometry.
                // This is probably not the fastest, but an elegant solution, which also supports arbitrary slice orientations. :)
89
                cgt::Bounds volumeExtent = img->getParent()->getWorldBounds();
90
                std::unique_ptr<MeshGeometry> cube = GeometryDataFactory::createCube(volumeExtent, cgt::Bounds(cgt::vec3(0.f), cgt::vec3(1.f)));
91

92
                cgt::vec3 normal(0.f, 0.f, 1.f);
93
                float p = img->getParent()->getMappingInformation().getOffset().z + (p_sliceNumber.getValue() * img->getParent()->getMappingInformation().getVoxelSize().z);
94 95
                MeshGeometry clipped = cube->clipAgainstPlane(p, normal, true);
                const FaceGeometry& slice = clipped.getFaces().back(); // the last face is the closing face
96

schultezub's avatar
schultezub committed
97
                glEnable(GL_DEPTH_TEST);
98 99 100
                _shader->activate();

                _shader->setIgnoreUniformLocationError(true);
101
                _shader->setUniform("_viewportSizeRCP", 1.f / cgt::vec2(getEffectiveViewportSize()));
102 103 104
                _shader->setUniform("_projectionMatrix", cam.getProjectionMatrix());
                _shader->setUniform("_viewMatrix", cam.getViewMatrix());

105
                cgt::TextureUnit inputUnit, tfUnit;
106 107 108
                img->bind(_shader, inputUnit);
                p_transferFunction.getTF()->bind(_shader, tfUnit);

109 110 111
                FramebufferActivationGuard fag(this);
                createAndAttachColorTexture();
                createAndAttachDepthTexture();
112
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
113
                slice.render(GL_TRIANGLE_FAN);
114 115

                _shader->deactivate();
116
                cgt::TextureUnit::setZeroUnit();
117
                glDisable(GL_DEPTH_TEST);
118

119
                data.addData(p_targetImageID.getValue(), new RenderData(_fbo));
120 121 122 123 124 125
            }
            else {
                LERROR("Input image must have dimensionality of 3.");
            }
        }
        else {
126
            LDEBUG("No suitable input image found.");
127 128 129
        }
    }

130
    void SliceRenderer3D::updateProperties(DataContainer& dc) {
131
        ScopedTypedData<ImageData> img(dc, p_sourceImageID.getValue());
132 133

        if (img != 0) {
134
            const cgt::svec3& imgSize = img->getSize();
135
            if (p_sliceNumber.getMaxValue() != static_cast<int>(imgSize.z) - 1){
136 137
                p_sliceNumber.setMaxValue(static_cast<int>(imgSize.z) - 1);
            }
138 139 140 141
        }
    }

}