slicerenderer3d.cpp 6.83 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// ================================================================================================
// 
// 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.
// 
// ================================================================================================

#include "slicerenderer3d.h"
#include "tgt/bounds.h"
#include "tgt/logmanager.h"
#include "tgt/shadermanager.h"
#include "tgt/textureunit.h"

#include "core/datastructures/imagedata.h"
37
38
#include "core/datastructures/imagerepresentationgl.h"
#include "core/datastructures/imagerepresentationrendertarget.h"
39

40
41
42
43
44
45
46
47
48
49
#include "core/datastructures/meshgeometry.h"
#include "core/datastructures/facegeometry.h"

#include "core/classification/simpletransferfunction.h"

#include "core/tools/quadrenderer.h"

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

50
    SliceRenderer3D::SliceRenderer3D(IVec2Property& canvasSize)
51
52
53
54
55
56
57
58
59
60
        : VisualizationProcessor(canvasSize)
        , p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ)
        , p_targetImageID("targetImageID", "Output Image", "", DataNameProperty::WRITE)
        , p_camera("Camera", "Camera")
        , p_sliceNumber("sliceNumber", "Slice Number", 0, 0, 0)
        , p_transferFunction("transferFunction", "Transfer Function", new SimpleTransferFunction(256))
        , _shader(0)
    {
        addProperty(&p_sourceImageID);
        addProperty(&p_targetImageID);
schultezub's avatar
schultezub committed
61
        addProperty(&p_camera);
62
63
64
65
66
67
68
69
70
71
72
        addProperty(&p_sliceNumber);
        addProperty(&p_transferFunction);
    }

    SliceRenderer3D::~SliceRenderer3D() {

    }

    void SliceRenderer3D::init() {
        VisualizationProcessor::init();
        _shader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "modules/vis/glsl/slicerenderer3d.frag", "", false);
73
74
        _shader->setAttributeLocation(0, "in_Position");
        _shader->setAttributeLocation(1, "in_TexCoord");
75
76
77
78
79
80
81
82
    }

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

    void SliceRenderer3D::process(DataContainer& data) {
83
        ImageRepresentationGL::ScopedRepresentation img(data, p_sourceImageID.getValue());
84
85
86

        if (img != 0) {
            if (img->getDimensionality() == 3) {
87
                updateProperties(img->getParent());
88
89
90
91
92
93
94
                const tgt::Camera& cam = p_camera.getValue();
                const tgt::svec3& imgSize = img->getSize();

                // 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. :)
95
                tgt::Bounds volumeExtent = img->getParent()->getWorldBounds();
96
97
98
                MeshGeometry cube = MeshGeometry::createCube(volumeExtent, tgt::Bounds(tgt::vec3(0.f), tgt::vec3(1.f)));

                tgt::vec3 normal(0.f, 0.f, 1.f);
99
                float p = img->getParent()->getMappingInformation().getOffset().z + (p_sliceNumber.getValue() * img->getParent()->getMappingInformation().getVoxelSize().z);
100
101
102
103
                MeshGeometry clipped = cube.clipAgainstPlane(p, normal, true);
                FaceGeometry slice = clipped.getFaces().back(); // the last face is the closing face


104
                std::pair<ImageData*, ImageRepresentationRenderTarget*> rt = ImageRepresentationRenderTarget::createWithImageData(_renderTargetSize.getValue());
105

schultezub's avatar
schultezub committed
106
                glEnable(GL_DEPTH_TEST);
107
108
109
110
111
112
113
                _shader->activate();

                _shader->setIgnoreUniformLocationError(true);
                _shader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(_renderTargetSize.getValue()));
                _shader->setUniform("_projectionMatrix", cam.getProjectionMatrix());
                _shader->setUniform("_viewMatrix", cam.getViewMatrix());

schultezub's avatar
schultezub committed
114
115
116
                tgt::mat4 trafoMatrix = tgt::mat4::createScale(tgt::vec3(-1.f, 1.f, -1.f));
                _shader->setUniform("_modelMatrix", trafoMatrix);

117
118
119
120
                tgt::TextureUnit inputUnit, tfUnit;
                img->bind(_shader, inputUnit);
                p_transferFunction.getTF()->bind(_shader, tfUnit);

121
                rt.second->activate();
122
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
123
                slice.render(GL_POLYGON);
124
                rt.second->deactivate();
125
126
127

                _shader->deactivate();
                tgt::TextureUnit::setZeroUnit();
128
                glDisable(GL_DEPTH_TEST);
129

130
                data.addData(p_targetImageID.getValue(), rt.first);
131
132
133
134
135
136
137
138
139
140
                p_targetImageID.issueWrite();
            }
            else {
                LERROR("Input image must have dimensionality of 3.");
            }
        }
        else {
            LERROR("No suitable input image found.");
        }

141
        validate(INVALID_RESULT);
142
143
144
145
146
    }

    void SliceRenderer3D::updateProperties(const ImageData* img) {
        const tgt::svec3& imgSize = img->getSize();
        if (p_sliceNumber.getMaxValue() != imgSize.z - 1){
147
            p_sliceNumber.setMaxValue(static_cast<int>(imgSize.z) - 1);
148
149
150
151
        }
    }

}