sliceextractor.cpp 13.5 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
42
43
44
45
46
    static const GenericOption<SliceExtractor::SliceOrientation> compositingOptions[3] = {
        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", compositingOptions, 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.loadSeparate("core/glsl/passthrough.vert", "modules/vis/glsl/sliceextractor.frag", "", false);
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);
    }

schultezub's avatar
schultezub committed
94
    void SliceExtractor::process(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
                // prepare OpenGL
schultezub's avatar
schultezub committed
151
                _shader->activate();
152
                decorateRenderProlog(data, _shader);
153
                tgt::TextureUnit inputUnit, tfUnit;
154
                img->bind(_shader, inputUnit);
155
                p_transferFunction.getTF()->bind(_shader, tfUnit);
156

157
                _shader->setUniform("_texCoordsMatrix", texCoordsMatrix);
158
                _shader->setUniform("_modelMatrix", modelMatrix);
159
                _shader->setUniform("_useTexturing", true);
160
161
162
163
164

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

                // render slice markers
schultezub's avatar
schultezub committed
169
170
                // 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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
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
                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;
                        modelMatrix.t13 *= (ratioRatio > 1) ? 1.f : ratioRatio;
                        _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;
                }

238
                decorateRenderEpilog(_shader);
schultezub's avatar
schultezub committed
239
                _shader->deactivate();
240
                tgt::TextureUnit::setZeroUnit();
schultezub's avatar
schultezub committed
241

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

252
        validate(INVALID_RESULT);
schultezub's avatar
schultezub committed
253
    }
254

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

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

        validate(AbstractProcessor::INVALID_PROPERTIES);
273
274
    }

275
276
277
    void SliceExtractor::updateBorderGeometry() {
    }

schultezub's avatar
schultezub committed
278
}