volumeexplorer.cpp 24 KB
Newer Older
schultezub's avatar
schultezub committed
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,
schultezub's avatar
schultezub committed
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
// 
schultezub's avatar
schultezub committed
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
schultezub's avatar
schultezub committed
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.
schultezub's avatar
schultezub committed
22
23
24
25
// 
// ================================================================================================

#include "volumeexplorer.h"
26
27
28
#include "cgt/logmanager.h"
#include "cgt/shadermanager.h"
#include "cgt/textureunit.h"
schultezub's avatar
schultezub committed
29

schultezub's avatar
schultezub committed
30
#include "core/datastructures/facegeometry.h"
31
#include "core/datastructures/geometrydatafactory.h"
32
#include "core/datastructures/renderdata.h"
schultezub's avatar
schultezub committed
33
34

#include "core/classification/simpletransferfunction.h"
35
#include "core/pipeline/processordecoratorbackground.h"
schultezub's avatar
schultezub committed
36
#include "core/tools/quadrenderer.h"
schultezub's avatar
schultezub committed
37
38

namespace campvis {
39
40
41
42
43
44
45
    static const GenericOption<VolumeExplorer::Views> largeViewOptions[4] = {
        GenericOption<VolumeExplorer::Views>("z", "XY Plane", VolumeExplorer::XY_PLANE),
        GenericOption<VolumeExplorer::Views>("y", "XZ Plane", VolumeExplorer::XZ_PLANE),
        GenericOption<VolumeExplorer::Views>("x", "YZ Plane", VolumeExplorer::YZ_PLANE),
        GenericOption<VolumeExplorer::Views>("volume", "Volume", VolumeExplorer::VOLUME)
    };

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

48
    VolumeExplorer::VolumeExplorer(IVec2Property* viewportSizeProp, SliceRenderProcessor* sliceRenderer, RaycastingProcessor* raycaster)
49
        : VisualizationProcessor(viewportSizeProp)
50
        , p_inputVolume("InputVolume", "Input Volume", "", DataNameProperty::READ)
schultezub's avatar
schultezub committed
51
        , p_outputImage("OutputImage", "Output Image", "ve.output", DataNameProperty::WRITE)
52
        , p_largeView("LargeView", "Large View Selection", largeViewOptions, 4)
53
        , p_enableScribbling("EnableScribbling", "Enable Scribbling in Slice Views", false)
54
55
        , p_seProperties("SliceExtractorProperties", "Slice Extractor Properties")
        , p_vrProperties("VolumeRendererProperties", "Volume Renderer Properties")
56
57
        , _shader(nullptr)
        , _quad(nullptr)
58
        , _tcp(viewportSizeProp)
59
        , _raycaster(viewportSizeProp, raycaster)
60
        , _sliceRenderer(sliceRenderer)
61
62
        , p_smallRenderSize("SmallRenderSize", "Small Render Size", cgt::ivec2(32), cgt::ivec2(0), cgt::ivec2(10000), cgt::ivec2(1))
        , p_largeRenderSize("LargeRenderSize", "Large Render Size", cgt::ivec2(32), cgt::ivec2(0), cgt::ivec2(10000), cgt::ivec2(1))
63
64
65
66
        , _xSliceHandler(&_sliceRenderer->p_xSliceNumber)
        , _ySliceHandler(&_sliceRenderer->p_ySliceNumber)
        , _zSliceHandler(&_sliceRenderer->p_zSliceNumber)
        , _windowingHandler(nullptr)
67
        , _mousePressedInRaycaster(false)
68
69
70
        , _viewUnderEvent(VOLUME)
        , _eventPositionOffset(0)
        , _eventViewportSize(0)
71
        , _scribblePointer(nullptr)
72
        , _cachedImageSize(0)
schultezub's avatar
schultezub committed
73
    {
74
75
        cgtAssert(raycaster != nullptr, "Raycasting Processor must not be 0.");
        cgtAssert(_sliceRenderer != nullptr, "Slice Rendering Processor must not be 0.");
76

77
        p_largeView.selectByOption(VOLUME);
Hossain Mahmud's avatar
Hossain Mahmud committed
78
79
        
        VolumeRenderer* test = dynamic_cast<VolumeRenderer*> (ProcessorFactory::getRef().createProcessor("VolumeRenderer", viewportSizeProp));
80

81
        addProperty(p_inputVolume, INVALID_PROPERTIES | CAMERA_INVALID);
82
        addProperty(p_outputImage);
83
        addProperty(p_largeView, LARGE_VIEW_INVALID | CAMERA_INVALID | SLICES_INVALID | VR_INVALID | INVALID_RESULT);
84
        addProperty(p_enableScribbling, VALID);
schultezub's avatar
schultezub committed
85

86
87
88
        addDecorator(new ProcessorDecoratorBackground());
        decoratePropertyCollection(this);
        
89
90
91
92
93
94
95
96
        p_seProperties.addPropertyCollection(*_sliceRenderer);
        _sliceRenderer->p_lqMode.setVisible(false);
        _sliceRenderer->p_sourceImageID.setVisible(false);
        _sliceRenderer->p_targetImageID.setVisible(false);
        _sliceRenderer->p_sliceOrientation.setVisible(false);
        _sliceRenderer->p_xSliceColor.setVisible(false);
        _sliceRenderer->p_ySliceColor.setVisible(false);
        _sliceRenderer->p_zSliceColor.setVisible(false);
97
        addProperty(p_seProperties, VALID);
98
99
100
101
102

        p_vrProperties.addPropertyCollection(_raycaster);
        _raycaster.p_lqMode.setVisible(false);
        _raycaster.p_inputVolume.setVisible(false);
        _raycaster.p_outputImage.setVisible(false);
103
        addProperty(p_vrProperties, VALID);
schultezub's avatar
schultezub committed
104

105
        p_inputVolume.addSharedProperty(&_tcp.p_image);
schultezub's avatar
schultezub committed
106
        p_inputVolume.addSharedProperty(&_raycaster.p_inputVolume);
107
        p_inputVolume.addSharedProperty(&_sliceRenderer->p_sourceImageID);
schultezub's avatar
schultezub committed
108

Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
109
110
        _tcp.p_cameraId.addSharedProperty(&_raycaster.p_camera);

111
        _tcp.setViewportSizeProperty(&p_largeRenderSize);
112
113
        _sliceRenderer->setViewportSizeProperty(&p_smallRenderSize);
        _raycaster.setViewportSizeProperty(&p_largeRenderSize);
114

115
116
        addProperty(p_smallRenderSize, VALID);
        addProperty(p_largeRenderSize, VALID);
117
118

        // Event-Handlers
119
        _tcp.addLqModeProcessor(&_raycaster);
120
121
122
123

        if (TransferFunctionProperty* tester = dynamic_cast<TransferFunctionProperty*>(_sliceRenderer->getProperty("TransferFunction"))) {
        	_windowingHandler.setTransferFunctionProperty(tester);
        }
schultezub's avatar
schultezub committed
124
125
126
127
128
129
130
    }

    VolumeExplorer::~VolumeExplorer() {
    }

    void VolumeExplorer::init() {
        VisualizationProcessor::init();
131
        _tcp.init();
schultezub's avatar
schultezub committed
132
        _raycaster.init();
133
        _sliceRenderer->init();
schultezub's avatar
schultezub committed
134

135
        _shader = ShdrMgr.load("core/glsl/passthrough.vert", "modules/vis/glsl/volumeexplorer.frag", "");
schultezub's avatar
schultezub committed
136
137
138
        _shader->setAttributeLocation(0, "in_Position");
        _shader->setAttributeLocation(1, "in_TexCoord");

139
        _tcp.s_invalidated.connect(this, &VolumeExplorer::onProcessorInvalidated);
140
        _sliceRenderer->s_invalidated.connect(this, &VolumeExplorer::onProcessorInvalidated);
schultezub's avatar
schultezub committed
141
142
        _raycaster.s_invalidated.connect(this, &VolumeExplorer::onProcessorInvalidated);

143
        _quad = GeometryDataFactory::createQuad(cgt::vec3(0.f), cgt::vec3(1.f), cgt::vec3(0.f), cgt::vec3(1.f));
144
        
145
        // force recalculation of p_smallRenderSize and p_largeRenderSize
146
        onPropertyChanged(_viewportSizeProperty);
schultezub's avatar
schultezub committed
147
148
149
    }

    void VolumeExplorer::deinit() {
150
        _tcp.deinit();
schultezub's avatar
schultezub committed
151
        _raycaster.deinit();
152
        _sliceRenderer->deinit();
schultezub's avatar
schultezub committed
153
        VisualizationProcessor::deinit();
schultezub's avatar
schultezub committed
154
155
        ShdrMgr.dispose(_shader);
        delete _quad;
schultezub's avatar
schultezub committed
156
157
    }

158
    void VolumeExplorer::updateResult(DataContainer& data) {
schultezub's avatar
schultezub committed
159
        // launch sub-renderers if necessary
160
161
162
163
164
165
        if (getInvalidationLevel() & LARGE_VIEW_INVALID) {
            switch (p_largeView.getOptionValue()) {
                case XY_PLANE: // fallthrough
                case XZ_PLANE: // fallthrough
                case YZ_PLANE:
                    _raycaster.setViewportSizeProperty(&p_smallRenderSize);
166
                    _tcp.setViewportSizeProperty(&p_smallRenderSize);
167
168
169
                    break;
                case VOLUME:
                    _raycaster.setViewportSizeProperty(&p_largeRenderSize);
170
                    _tcp.setViewportSizeProperty(&p_largeRenderSize);
171
172
                    break;
            }
173
            validate(LARGE_VIEW_INVALID);
174
        }
175
        if (getInvalidationLevel() & SCRIBBLE_INVALID) {
176
177
            std::vector<cgt::vec3> vertices;
            std::vector<cgt::vec4> colors;
178
179

            for (size_t i = 0; i < _yesScribbles.size(); ++i) {
180
181
                vertices.push_back(cgt::vec3(_yesScribbles[i]));
                colors.push_back(cgt::vec4(.2f, .8f, 0.f, 1.f));
182
183
            }
            for (size_t i = 0; i < _noScribbles.size(); ++i) {
184
185
                vertices.push_back(cgt::vec3(_noScribbles[i]));
                colors.push_back(cgt::vec4(.85f, .2f, 0.f, 1.f));
186
187
            }

188
            FaceGeometry* g = new FaceGeometry(vertices, std::vector<cgt::vec3>(), colors);
189
190
191
192
193
194
195
            data.addData(p_outputImage.getValue() + ".scribbles", g);
            validate(SCRIBBLE_INVALID);

            // force update of slice renderer if necessary
            if (! (getInvalidationLevel() & VR_INVALID))
                invalidate(SLICES_INVALID);
        }
196
197
198
199
200
201

        if (getInvalidationLevel() & CAMERA_INVALID) {
            _tcp.process(data);
            _raycaster.process(data);
        }
        else if (getInvalidationLevel() & VR_INVALID) {
schultezub's avatar
schultezub committed
202
203
            _raycaster.process(data);
        }
204

schultezub's avatar
schultezub committed
205
        if (getInvalidationLevel() & SLICES_INVALID) {
206
207
            _sliceRenderer->setViewportSizeProperty(p_largeView.getOptionValue() == YZ_PLANE ? &p_largeRenderSize : &p_smallRenderSize);
            _sliceRenderer->p_sliceOrientation.selectByOption(SliceRenderProcessor::YZ_PLANE);
208
209
            _sliceRenderer->p_targetImageID.setValue(p_outputImage.getValue() + ".xSlice");
            _sliceRenderer->process(data);
schultezub's avatar
schultezub committed
210

211
212
            _sliceRenderer->setViewportSizeProperty(p_largeView.getOptionValue() == XZ_PLANE ? &p_largeRenderSize : &p_smallRenderSize);
            _sliceRenderer->p_sliceOrientation.selectByOption(SliceRenderProcessor::XZ_PLANE);
213
214
            _sliceRenderer->p_targetImageID.setValue(p_outputImage.getValue() + ".ySlice");
            _sliceRenderer->process(data);
schultezub's avatar
schultezub committed
215

216
217
            _sliceRenderer->setViewportSizeProperty(p_largeView.getOptionValue() == XY_PLANE ? &p_largeRenderSize : &p_smallRenderSize);
            _sliceRenderer->p_sliceOrientation.selectByOption(SliceRenderProcessor::XY_PLANE);
218
219
            _sliceRenderer->p_targetImageID.setValue(p_outputImage.getValue() + ".zSlice");
            _sliceRenderer->process(data);
schultezub's avatar
schultezub committed
220
221
222
223
224
        }

        // compose rendering
        composeFinalRendering(data);

225
        validate(INVALID_RESULT | CAMERA_INVALID | VR_INVALID | SLICES_INVALID);
schultezub's avatar
schultezub committed
226
227
228
    }

    void VolumeExplorer::onPropertyChanged(const AbstractProperty* prop) {
229
        if (prop == _viewportSizeProperty) {
230
231
            p_smallRenderSize.setValue(cgt::ivec2(_viewportSizeProperty->getValue().y / 3, _viewportSizeProperty->getValue().y / 3));
            p_largeRenderSize.setValue(cgt::ivec2(_viewportSizeProperty->getValue().x - _viewportSizeProperty->getValue().y / 3, _viewportSizeProperty->getValue().y));
schultezub's avatar
schultezub committed
232
233
        }
        if (prop == &p_outputImage) {
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
234
            _tcp.p_cameraId.setValue(p_outputImage.getValue() + ".camera");
schultezub's avatar
schultezub committed
235
            _raycaster.p_outputImage.setValue(p_outputImage.getValue() + ".raycaster");
236
            _sliceRenderer->p_geometryID.setValue(p_outputImage.getValue() + ".scribbles");
schultezub's avatar
schultezub committed
237
238
        }
        if (prop == &p_inputVolume) {
239
            invalidate(VR_INVALID | SLICES_INVALID);
schultezub's avatar
schultezub committed
240
        }
241
242
        if (prop == &p_enableScribbling) {
            if (p_enableScribbling.getValue() == true) {
243
244
                _sliceRenderer->s_scribblePainted.connect(this, &VolumeExplorer::onSliceExtractorScribblePainted);
                _sliceRenderer->p_geometryID.setValue(p_outputImage.getValue() + ".scribbles");
245
246
            }
            else {
247
248
                _sliceRenderer->s_scribblePainted.disconnect(this);
                _sliceRenderer->p_geometryID.setValue("");
249
250
251
            }
        }

schultezub's avatar
schultezub committed
252
253
254
255
        VisualizationProcessor::onPropertyChanged(prop);
    }

    void VolumeExplorer::composeFinalRendering(DataContainer& data) {
256
257
258
259
        ScopedTypedData<RenderData> vrImage(data, p_outputImage.getValue() + ".raycaster");
        ScopedTypedData<RenderData> xSliceImage(data, p_outputImage.getValue() + ".xSlice");
        ScopedTypedData<RenderData> ySliceImage(data, p_outputImage.getValue() + ".ySlice");
        ScopedTypedData<RenderData> zSliceImage(data, p_outputImage.getValue() + ".zSlice");
schultezub's avatar
schultezub committed
260
261
262
263

        if (vrImage == 0 && xSliceImage == 0 && ySliceImage == 0 && zSliceImage == 0)
            return;

264
        FramebufferActivationGuard fag(this);
265
266
267
        createAndAttachColorTexture();
        createAndAttachDepthTexture();

268
        cgt::TextureUnit colorUnit, depthUnit;
schultezub's avatar
schultezub committed
269
270
        _shader->activate();

271
272
273
        cgt::vec2 rts(_viewportSizeProperty->getValue());
        cgt::vec2 vrs(p_largeRenderSize.getValue());
        cgt::vec2 srs(p_smallRenderSize.getValue());
schultezub's avatar
schultezub committed
274

275
        _shader->setUniform("_projectionMatrix", cgt::mat4::createOrtho(0, rts.x, rts.y, 0, -1, 1));
schultezub's avatar
schultezub committed
276
277
278
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        if (vrImage != 0) {
279
280
281
            decorateRenderProlog(data, _shader);
            _shader->setUniform("_renderBackground", true);

schultezub's avatar
schultezub committed
282
            vrImage->bind(_shader, colorUnit, depthUnit);
283
284
            switch (p_largeView.getOptionValue()) {
                case XY_PLANE:
285
286
                    _shader->setUniform("_modelMatrix", cgt::mat4::createScale(cgt::vec3(srs.x, srs.y, .5f)));
                    _shader->setUniform("_viewMatrix", cgt::mat4::createTranslation(cgt::vec3(0.f, 2.f * srs.y, 0.f)));
287
288
                    break;
                case XZ_PLANE:
289
290
                    _shader->setUniform("_modelMatrix", cgt::mat4::createScale(cgt::vec3(srs.x, srs.y, .5f)));
                    _shader->setUniform("_viewMatrix", cgt::mat4::createTranslation(cgt::vec3(0.f, srs.y, 0.f)));
291
292
                    break;
                case YZ_PLANE:
293
294
                    _shader->setUniform("_modelMatrix", cgt::mat4::createScale(cgt::vec3(srs.x, srs.y, .5f)));
                    _shader->setUniform("_viewMatrix", cgt::mat4::createTranslation(cgt::vec3(0.f, 0.f, 0.f)));
295
296
                    break;
                case VOLUME:
297
298
                    _shader->setUniform("_modelMatrix", cgt::mat4::createScale(cgt::vec3(vrs.x, vrs.y, .5f)));
                    _shader->setUniform("_viewMatrix", cgt::mat4::createTranslation(cgt::vec3(srs.x, 0.f, 0.f)));
299
300
                    break;
            }
301
            _quad->render(GL_TRIANGLE_FAN);
302
303
304

            _shader->setUniform("_renderBackground", false);
            decorateRenderEpilog(_shader);
schultezub's avatar
schultezub committed
305
        }
306
307
        if (zSliceImage != 0) {
            zSliceImage->bind(_shader, colorUnit, depthUnit);
308
            if (p_largeView.getOptionValue() == XY_PLANE) {
309
310
                _shader->setUniform("_modelMatrix", cgt::mat4::createScale(cgt::vec3(vrs.x, vrs.y, .5f)));
                _shader->setUniform("_viewMatrix", cgt::mat4::createTranslation(cgt::vec3(srs.x, 0.f, 0.f)));
311
312
            }
            else {
313
314
                _shader->setUniform("_modelMatrix", cgt::mat4::createScale(cgt::vec3(srs.x, srs.y, .5f)));
                _shader->setUniform("_viewMatrix", cgt::mat4::createTranslation(cgt::vec3(0.f, 2.f * srs.y, 0.f)));
315
            }
316
            _quad->render(GL_TRIANGLE_FAN);
schultezub's avatar
schultezub committed
317
318
319
        }
        if (ySliceImage != 0) {
            ySliceImage->bind(_shader, colorUnit, depthUnit);
320
            if (p_largeView.getOptionValue() == XZ_PLANE) {
321
322
                _shader->setUniform("_modelMatrix", cgt::mat4::createScale(cgt::vec3(vrs.x, vrs.y, .5f)));
                _shader->setUniform("_viewMatrix", cgt::mat4::createTranslation(cgt::vec3(srs.x, 0.f, 0.f)));
323
324
            }
            else {
325
326
                _shader->setUniform("_modelMatrix", cgt::mat4::createScale(cgt::vec3(srs.x, srs.y, .5f)));
                _shader->setUniform("_viewMatrix", cgt::mat4::createTranslation(cgt::vec3(0.f, srs.y, 0.f)));
327
            }
328
            _quad->render(GL_TRIANGLE_FAN);
schultezub's avatar
schultezub committed
329
        }
330
331
        if (xSliceImage != 0) {
            xSliceImage->bind(_shader, colorUnit, depthUnit);
332
            if (p_largeView.getOptionValue() == YZ_PLANE) {
333
334
                _shader->setUniform("_modelMatrix", cgt::mat4::createScale(cgt::vec3(vrs.x, vrs.y, .5f)));
                _shader->setUniform("_viewMatrix", cgt::mat4::createTranslation(cgt::vec3(srs.x, 0.f, 0.f)));
335
336
            }
            else {
337
338
                _shader->setUniform("_modelMatrix", cgt::mat4::createScale(cgt::vec3(srs.x, srs.y, .5f)));
                _shader->setUniform("_viewMatrix", cgt::mat4::createTranslation(cgt::vec3(0.f, 0.f, 0.f)));
339
            }
340
            _quad->render(GL_TRIANGLE_FAN);
schultezub's avatar
schultezub committed
341
342
343
        }

        _shader->deactivate();
344
        cgt::TextureUnit::setZeroUnit();
schultezub's avatar
schultezub committed
345
346
        LGL_ERROR;

347
        data.addData(p_outputImage.getValue(), new RenderData(_fbo));
schultezub's avatar
schultezub committed
348
349
350
    }

    void VolumeExplorer::onProcessorInvalidated(AbstractProcessor* processor) {
351
352
353
        // make sure to only invalidate ourself if the invalidation is not triggered by us
        // => the _locked state is a trustworthy source for this information :)
        if (! isLocked()) {
354
355
356
            if (processor == &_tcp) {
                invalidate(CAMERA_INVALID);
            }
357
358
359
            if (processor == &_raycaster) {
                invalidate(VR_INVALID);
            }
360
            if (processor == _sliceRenderer) {
361
362
363
364
                invalidate(SLICES_INVALID);
            }

            invalidate(AbstractProcessor::INVALID_RESULT);
schultezub's avatar
schultezub committed
365
366
367
        }
    }

368
    void VolumeExplorer::updateProperties(DataContainer& dc) {
369
        ScopedTypedData<ImageData> img(dc, p_inputVolume.getValue());
370
        static_cast<TransferFunctionProperty*>(_raycaster.getNestedProperty("RaycasterProps::TransferFunction"))->setImageHandle(img.getDataHandle());
371

372
        if (img != 0 && _cachedImageSize != cgt::ivec3(img->getSize())) {
373
374
375
376
            _cachedImageSize = img->getSize();
            if (_sliceRenderer->p_xSliceNumber.getMaxValue() != _cachedImageSize.x - 1){
                _sliceRenderer->p_xSliceNumber.setMaxValue(_cachedImageSize.x - 1);
                _sliceRenderer->p_xSliceNumber.setValue(_cachedImageSize.x / 2);
377
            }
378
379
380
            if (_sliceRenderer->p_ySliceNumber.getMaxValue() != _cachedImageSize.y - 1){
                _sliceRenderer->p_ySliceNumber.setMaxValue(_cachedImageSize.y - 1);
                _sliceRenderer->p_ySliceNumber.setValue(_cachedImageSize.y / 2);
381
            }
382
383
384
            if (_sliceRenderer->p_zSliceNumber.getMaxValue() != _cachedImageSize.z - 1){
                _sliceRenderer->p_zSliceNumber.setMaxValue(_cachedImageSize.z - 1);
                _sliceRenderer->p_zSliceNumber.setValue(_cachedImageSize.z / 2);
385
386
            }
        }
387
388
    }

389
    void VolumeExplorer::onEvent(cgt::Event* e) {
Hossain Mahmud's avatar
Hossain Mahmud committed
390
        // forward the event to the corresponding event listeners depending on the mouse position
391
392
        if (typeid(*e) == typeid(cgt::MouseEvent)) {
            cgt::MouseEvent* me = static_cast<cgt::MouseEvent*>(e);
393

394
395
            // if the mouse was pressed, we need to cache the view parameters of the view underneath
            // the pointer, so that we can adjust the MouseEvents to the corresponding subviews.
396
            if (me->action() == cgt::MouseEvent::PRESSED || (!_mousePressedInRaycaster && me->action() == cgt::MouseEvent::WHEEL)) {
397
398
                if (me->x() <= p_smallRenderSize.getValue().x) {
                    if (me->y() <= p_smallRenderSize.getValue().y) {
399
                        _eventPositionOffset = cgt::ivec2(0, 0);
400
401
                        _eventViewportSize = p_smallRenderSize.getValue();
                        _viewUnderEvent = (p_largeView.getOptionValue() == XY_PLANE) ? VOLUME : XY_PLANE;
402
                    }
403
                    else if (me->y() <= 2*p_smallRenderSize.getValue().y) {
404
                        _eventPositionOffset = cgt::ivec2(0, -p_smallRenderSize.getValue().y);
405
406
                        _eventViewportSize = p_smallRenderSize.getValue();
                        _viewUnderEvent = (p_largeView.getOptionValue() == XZ_PLANE) ? VOLUME : XZ_PLANE;
407
408
                    }
                    else {
409
                        _eventPositionOffset = cgt::ivec2(0, -2 * p_smallRenderSize.getValue().y);
410
411
                        _eventViewportSize = p_smallRenderSize.getValue();
                        _viewUnderEvent = (p_largeView.getOptionValue() == YZ_PLANE) ? VOLUME : YZ_PLANE;
412
413
                    }
                }
414
                else {
415
                    _eventPositionOffset = cgt::ivec2(- p_smallRenderSize.getValue().x, 0);
416
417
                    _eventViewportSize = p_largeRenderSize.getValue();
                    _viewUnderEvent = p_largeView.getOptionValue();
418
419
                }
            }
420
421

            // create a new MouseEvent for the corresponding subview
422
            cgt::MouseEvent adjustedMe(me->x() + _eventPositionOffset.x, me->y() + _eventPositionOffset.y,
423
424
425
426
                me->action(), me->modifiers(), me->button(),
                _eventViewportSize);

            // now divert the new MouseEvent to the corresponding handler
427
            if (me->action() == cgt::MouseEvent::DOUBLECLICK) {
428
429
430
                p_largeView.selectByOption(_viewUnderEvent);
            }
            else if (_mousePressedInRaycaster || _viewUnderEvent == VOLUME) {
431
                // raycasting trackball navigation
432
                if (me->action() == cgt::MouseEvent::PRESSED)
433
                    _mousePressedInRaycaster = true;
434
                else if (me->action() == cgt::MouseEvent::RELEASED)
435
                    _mousePressedInRaycaster = false;
436
                _tcp.onEvent(&adjustedMe);
437
            }
438
            else if (me->action() == cgt::MouseEvent::WHEEL) {
439
440
441
442
443
444
445
446
447
448
449
                // Mouse wheel has changed -> cycle slices
                if (_viewUnderEvent == XY_PLANE) {
                    _zSliceHandler.onEvent(e);
                }
                else if (_viewUnderEvent == XZ_PLANE) {
                    _ySliceHandler.onEvent(e);
                }
                else {
                    _xSliceHandler.onEvent(e);
                }
            }
450
            else if (p_enableScribbling.getValue() && (me->modifiers() & cgt::Event::CTRL || me->modifiers() & cgt::Event::ALT)) {
451
                // CTRL pressed -> forward to SliceExtractor's scribbling
452
453
454
                if (me->action() == cgt::MouseEvent::PRESSED) {
                    _scribblePointer = (me->modifiers() & cgt::Event::CTRL) ? &_yesScribbles : &_noScribbles;
                    if (! (me->modifiers() & cgt::Event::SHIFT))
455
456
                        _scribblePointer->clear();
                }
457
                else if (_scribblePointer != nullptr && me->action() == cgt::MouseEvent::RELEASED) {
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
                    _scribblePointer = nullptr;
                }

                // lock this processor, so that the slice orientation's setting does not change
                AbstractProcessor::ScopedLock lock(this);

                if (_viewUnderEvent == XY_PLANE) {
                    _sliceRenderer->p_sliceOrientation.selectByOption(SliceExtractor::XY_PLANE);
                }
                else if (_viewUnderEvent == XZ_PLANE) {
                    _sliceRenderer->p_sliceOrientation.selectByOption(SliceExtractor::XZ_PLANE);
                }
                else {
                    _sliceRenderer->p_sliceOrientation.selectByOption(SliceExtractor::YZ_PLANE);
                }
                _sliceRenderer->onEvent(&adjustedMe);
            }
            else {
                // adjust slice TF windowing
                _windowingHandler.onEvent(&adjustedMe);
            }
479
        }
schultezub's avatar
schultezub committed
480
481
    }

482
    void VolumeExplorer::onSliceExtractorScribblePainted(cgt::vec3 voxel) {
483
484
485
486
487
        if (_scribblePointer != nullptr) {
            _scribblePointer->push_back(voxel);
            invalidate(INVALID_RESULT | SCRIBBLE_INVALID);
        }
    }
schultezub's avatar
schultezub committed
488

489
490
491
492
493
494
495
496
    VolumeRenderer* VolumeExplorer::getVolumeRenderer() {
        return &_raycaster;
    }

    SliceRenderProcessor* VolumeExplorer::getSliceRenderer() {
        return _sliceRenderer;
    }

497
}