sliceextractor.cpp 13.7 KB
Newer Older
1
2
// ================================================================================================
// 
schultezub's avatar
schultezub committed
3
// This file is part of the CAMPVis Software Framework.
4
// 
5
// If not explicitly stated otherwise: Copyright (C) 2012-2013, all rights reserved,
schultezub's avatar
schultezub committed
6
//      Christian Schulte zu Berge <christian.szb@in.tum.de>
7
//      Chair for Computer Aided Medical Procedures
8
9
//      Technische Universität München
//      Boltzmannstr. 3, 85748 Garching b. München, Germany
10
// 
schultezub's avatar
schultezub committed
11
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
12
// 
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
// 
// ================================================================================================

schultezub's avatar
schultezub committed
25
26
#include "sliceextractor.h"
#include "tgt/logmanager.h"
27
#include "tgt/shadermanager.h"
schultezub's avatar
schultezub committed
28
#include "tgt/textureunit.h"
29

30
#include "core/datastructures/facegeometry.h"
schultezub's avatar
schultezub committed
31
#include "core/datastructures/imagedata.h"
32
#include "core/datastructures/imagerepresentationgl.h"
33
#include "core/datastructures/renderdata.h"
34
#include "core/pipeline/processordecoratorbackground.h"
schultezub's avatar
schultezub committed
35

36
37
#include "core/classification/simpletransferfunction.h"

38
39
#include "core/tools/quadrenderer.h"

schultezub's avatar
schultezub committed
40
namespace campvis {
41
    static const GenericOption<SliceExtractor::SliceOrientation> sliceOrientationOptions[3] = {
42
43
44
45
46
        GenericOption<SliceExtractor::SliceOrientation>("z", "XY Plane", SliceExtractor::XY_PLANE),
        GenericOption<SliceExtractor::SliceOrientation>("y", "XZ Plane", SliceExtractor::XZ_PLANE),
        GenericOption<SliceExtractor::SliceOrientation>("x", "YZ Plane", SliceExtractor::YZ_PLANE)
    };

schultezub's avatar
schultezub committed
47
    const std::string SliceExtractor::loggerCat_ = "CAMPVis.modules.vis.SliceExtractor";
schultezub's avatar
schultezub committed
48

49
50
    SliceExtractor::SliceExtractor(IVec2Property* viewportSizeProp)
        : VisualizationProcessor(viewportSizeProp)
51
        , p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ, AbstractProcessor::INVALID_RESULT | AbstractProcessor::INVALID_PROPERTIES)
52
        , p_targetImageID("targetImageID", "Output Image", "", DataNameProperty::WRITE)
53
        , p_sliceOrientation("SliceOrientation", "Slice Orientation", sliceOrientationOptions, 3)
54
        , p_xSliceNumber("XSliceNumber", "X Slice Number", 0, 0, 0)
55
        , p_xSliceColor("XSliceColor", "X Slice Color", tgt::vec4(1.f, 0.f, 0.f, 1.f), tgt::vec4(0.f), tgt::vec4(1.f))
56
        , p_ySliceNumber("YSliceNumber", "Y Slice Number", 0, 0, 0)
57
        , p_ySliceColor("YSliceColor", "Y Slice Color", tgt::vec4(0.f, 1.f, 0.f, 1.f), tgt::vec4(0.f), tgt::vec4(1.f))
58
        , p_zSliceNumber("ZSliceNumber", "Z Slice Number", 0, 0, 0)
59
        , p_zSliceColor("ZSliceColor", "Z Slice Color", tgt::vec4(0.f, 0.f, 1.f, 1.f), tgt::vec4(0.f), tgt::vec4(1.f))
60
        , p_transferFunction("transferFunction", "Transfer Function", new SimpleTransferFunction(256))
schultezub's avatar
schultezub committed
61
        , _shader(0)
schultezub's avatar
schultezub committed
62
    {
63
64
        addProperty(&p_sourceImageID);
        addProperty(&p_targetImageID);
65
66
        addProperty(&p_sliceOrientation);
        addProperty(&p_xSliceNumber);
67
        addProperty(&p_xSliceColor);
68
        addProperty(&p_ySliceNumber);
69
        addProperty(&p_ySliceColor);
70
        addProperty(&p_zSliceNumber);
71
        addProperty(&p_zSliceColor);
72
        addProperty(&p_transferFunction);
73
74
75

        //addDecorator(new ProcessorDecoratorBackground());
        decoratePropertyCollection(this);
schultezub's avatar
schultezub committed
76
77
78
79
80
81
    }

    SliceExtractor::~SliceExtractor() {

    }

schultezub's avatar
schultezub committed
82
    void SliceExtractor::init() {
schultezub's avatar
schultezub committed
83
        VisualizationProcessor::init();
84
        _shader = ShdrMgr.load("core/glsl/passthrough.vert", "modules/vis/glsl/sliceextractor.frag", "");
85
86
        _shader->setAttributeLocation(0, "in_Position");
        _shader->setAttributeLocation(1, "in_TexCoord");
schultezub's avatar
schultezub committed
87
88
    }

89
    void SliceExtractor::deinit() {
schultezub's avatar
schultezub committed
90
        VisualizationProcessor::deinit();
91
92
93
        ShdrMgr.dispose(_shader);
    }

94
    void SliceExtractor::updateResult(DataContainer& data) {
95
        ImageRepresentationGL::ScopedRepresentation img(data, p_sourceImageID.getValue());
schultezub's avatar
schultezub committed
96
97
98

        if (img != 0) {
            if (img->getDimensionality() == 3) {
99
                tgt::vec3 imgSize(img->getSize());
schultezub's avatar
schultezub committed
100

101
102
103
                // current slices in texture coordinates
                tgt::vec3 sliceTexCoord = tgt::vec3(.5f + p_xSliceNumber.getValue(), .5f + p_ySliceNumber.getValue(), .5f + p_zSliceNumber.getValue()) / imgSize;
                // texture coordinate transformation matrix (will be configured later)
104
                tgt::mat4 texCoordsMatrix = tgt::mat4::zero;
105

106
                float renderTargetRatio = static_cast<float>(getEffectiveViewportSize().x) / static_cast<float>(getEffectiveViewportSize().y);
107
                float sliceRatio = 1.f;
108

109
                switch (p_sliceOrientation.getValue()) {
110
                    case XY_PLANE:
schultezub's avatar
schultezub committed
111
                        // keep texture coordinates for x,y, shift z coordinates to slice value
112
113
114
115
116
117
118
119
120
121
                        texCoordsMatrix.t00 = 1.f;
                        texCoordsMatrix.t11 = 1.f;
                        texCoordsMatrix.t22 = 1.f;
                        texCoordsMatrix.t23 = sliceTexCoord.z;
                        sliceRatio = 
                              (static_cast<float>(imgSize.x) * img.getImageData()->getMappingInformation().getVoxelSize().x)
                            / (static_cast<float>(imgSize.y) * img.getImageData()->getMappingInformation().getVoxelSize().y);
                        break;

                    case XZ_PLANE:
schultezub's avatar
schultezub committed
122
                        // permute y and z coordinates, shift y to slice 
123
124
125
126
127
128
129
130
131
132
133
                        texCoordsMatrix.t00 = 1.f;
                        texCoordsMatrix.t12 = 1.f;
                        texCoordsMatrix.t21 = 1.f;
                        texCoordsMatrix.t33 = 1.f;
                        texCoordsMatrix.t13 = sliceTexCoord.y;
                        sliceRatio = 
                               (static_cast<float>(imgSize.x) * img.getImageData()->getMappingInformation().getVoxelSize().x) 
                             / (static_cast<float>(imgSize.z) * img.getImageData()->getMappingInformation().getVoxelSize().z);
                        break;

                    case YZ_PLANE:
schultezub's avatar
schultezub committed
134
                        // permute x,y and z coordinates, shift x to slice
135
136
137
138
139
140
141
142
143
                        texCoordsMatrix.t02 = 1.f; 
                        texCoordsMatrix.t10 = 1.f;
                        texCoordsMatrix.t21 = 1.f;
                        texCoordsMatrix.t33 = 1.f;
                        texCoordsMatrix.t03 = sliceTexCoord.x;
                        sliceRatio = 
                              (static_cast<float>(imgSize.y) * img.getImageData()->getMappingInformation().getVoxelSize().y)
                            / (static_cast<float>(imgSize.z) * img.getImageData()->getMappingInformation().getVoxelSize().z);
                        break;
144
                }
145
                
146
                // configure model matrix so that slices are rendered with correct aspect ratio
147
148
                float ratioRatio = sliceRatio / renderTargetRatio;
                tgt::mat4 modelMatrix = (ratioRatio > 1) ? tgt::mat4::createScale(tgt::vec3(1.f, 1.f / ratioRatio, 1.f)) : tgt::mat4::createScale(tgt::vec3(ratioRatio, 1.f, 1.f));
149

150
151
152
                if (p_sliceOrientation.getValue() == XY_PLANE)
                    modelMatrix.t11 *= -1;

153
                // prepare OpenGL
schultezub's avatar
schultezub committed
154
                _shader->activate();
155
                decorateRenderProlog(data, _shader);
156
                tgt::TextureUnit inputUnit, tfUnit;
157
                img->bind(_shader, inputUnit);
158
                p_transferFunction.getTF()->bind(_shader, tfUnit);
159

160
                _shader->setUniform("_texCoordsMatrix", texCoordsMatrix);
161
                _shader->setUniform("_modelMatrix", modelMatrix);
162
                _shader->setUniform("_useTexturing", true);
163
164
165
166
167

                // render slice
                FramebufferActivationGuard fag(this);
                createAndAttachColorTexture();
                createAndAttachDepthTexture();
schultezub's avatar
schultezub committed
168
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
169
                QuadRdr.renderQuad();
170
171

                // render slice markers
schultezub's avatar
schultezub committed
172
173
                // for each slice render a bounding box (GL_LINE_LOOP) in slice color and horizontal/vertical
                // lines (GL_LINE_STRIP) as reference for the other axis-aligned slices
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
                glLineWidth(2.f);
                _shader->setUniform("_useTexturing", false);
                switch (p_sliceOrientation.getValue()) {
                    case XY_PLANE:
                        _shader->setUniform("_color", p_zSliceColor.getValue());
                        QuadRdr.renderQuad(GL_LINE_LOOP);

                        modelMatrix.t00 = 0.f;
                        modelMatrix.t03 = 2.f * sliceTexCoord.x - 1.f;
                        modelMatrix.t03 *= (ratioRatio > 1) ? 1.f : ratioRatio;
                        _shader->setUniform("_modelMatrix", modelMatrix);
                        _shader->setUniform("_color", p_xSliceColor.getValue());
                        QuadRdr.renderQuad(GL_LINE_STRIP);

                        modelMatrix.t00 = (ratioRatio > 1) ? 1.f : ratioRatio;
                        modelMatrix.t11 = 0.f;
                        modelMatrix.t03 = 0.f;
                        modelMatrix.t13 = 2.f * sliceTexCoord.y - 1.f;
192
                        modelMatrix.t13 *= (ratioRatio > 1) ? -1.f / ratioRatio : -1.f;
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
                        _shader->setUniform("_modelMatrix", modelMatrix);
                        _shader->setUniform("_color", p_ySliceColor.getValue());
                        QuadRdr.renderQuad(GL_LINE_STRIP);
                        break;

                    case XZ_PLANE:
                        _shader->setUniform("_color", p_ySliceColor.getValue());
                        QuadRdr.renderQuad(GL_LINE_LOOP);

                        modelMatrix.t00 = 0.f;
                        modelMatrix.t03 = 2.f * sliceTexCoord.x - 1.f;
                        modelMatrix.t03 *= (ratioRatio > 1) ? 1.f : ratioRatio;
                        _shader->setUniform("_modelMatrix", modelMatrix);
                        _shader->setUniform("_color", p_xSliceColor.getValue());
                        QuadRdr.renderQuad(GL_LINE_STRIP);

                        modelMatrix.t00 = (ratioRatio > 1) ? 1.f : ratioRatio;
                        modelMatrix.t11 = 0.f;
                        modelMatrix.t03 = 0.f;
                        modelMatrix.t13 = 2.f * sliceTexCoord.z - 1.f;
                        modelMatrix.t13 *= (ratioRatio > 1) ? 1.f / ratioRatio : 1.f;
                        _shader->setUniform("_modelMatrix", modelMatrix);
                        _shader->setUniform("_color", p_zSliceColor.getValue());
                        QuadRdr.renderQuad(GL_LINE_STRIP);
                        break;

                    case YZ_PLANE:
                        _shader->setUniform("_color", p_xSliceColor.getValue());
                        QuadRdr.renderQuad(GL_LINE_LOOP);

                        modelMatrix.t00 = 0.f;
                        modelMatrix.t03 = 2.f * sliceTexCoord.y - 1.f;
                        modelMatrix.t03 *= (ratioRatio > 1) ? 1.f : ratioRatio;
                        _shader->setUniform("_modelMatrix", modelMatrix);
                        _shader->setUniform("_color", p_ySliceColor.getValue());
                        QuadRdr.renderQuad(GL_LINE_STRIP);

                        modelMatrix.t00 = (ratioRatio > 1) ? 1.f : ratioRatio;
                        modelMatrix.t11 = 0.f;
                        modelMatrix.t03 = 0.f;
                        modelMatrix.t13 = 2.f * sliceTexCoord.z - 1.f;
                        modelMatrix.t13 *= (ratioRatio > 1) ? 1.f / ratioRatio : 1.f;
                        _shader->setUniform("_modelMatrix", modelMatrix);
                        _shader->setUniform("_color", p_zSliceColor.getValue());
                        QuadRdr.renderQuad(GL_LINE_STRIP);
                        break;
                }

241
                decorateRenderEpilog(_shader);
schultezub's avatar
schultezub committed
242
                _shader->deactivate();
243
                tgt::TextureUnit::setZeroUnit();
schultezub's avatar
schultezub committed
244

245
                data.addData(p_targetImageID.getValue(), new RenderData(_fbo));
schultezub's avatar
schultezub committed
246
247
248
249
250
251
252
253
            }
            else {
                LERROR("Input image must have dimensionality of 3.");
            }
        }
        else {
            LERROR("No suitable input image found.");
        }
254

255
        validate(INVALID_RESULT);
schultezub's avatar
schultezub committed
256
    }
257

258
    void SliceExtractor::updateProperties(DataContainer& dc) {
259
        ScopedTypedData<ImageData> img(dc, p_sourceImageID.getValue());
260
        p_transferFunction.setImageHandle(img.getDataHandle());
261
262

        if (img != 0) {
263
264
265
            tgt::ivec3 imgSize = img->getSize();
            if (p_xSliceNumber.getMaxValue() != imgSize.x - 1){
                p_xSliceNumber.setMaxValue(imgSize.x - 1);
266
            }
267
268
            if (p_ySliceNumber.getMaxValue() != imgSize.y - 1){
                p_ySliceNumber.setMaxValue(imgSize.y - 1);
269
            }
270
271
            if (p_zSliceNumber.getMaxValue() != imgSize.z - 1){
                p_zSliceNumber.setMaxValue(imgSize.z - 1);
272
            }
273
        }
274
275

        validate(AbstractProcessor::INVALID_PROPERTIES);
276
277
    }

278
279
280
    void SliceExtractor::updateBorderGeometry() {
    }

schultezub's avatar
schultezub committed
281
}