Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

datacontainerinspectorcanvas.cpp 27.2 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, 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
schultezub's avatar
schultezub committed
10
// For a full list of authors and contributors, please refer to the file "AUTHORS.txt".
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 
// 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 "datacontainerinspectorcanvas.h"

#include "tgt/assert.h"
#include "tgt/shadermanager.h"
34
35
#include "tgt/textureunit.h"

36
37
#include "core/datastructures/datacontainer.h"
#include "core/datastructures/datahandle.h"
38
#include "core/datastructures/renderdata.h"
39
#include "core/datastructures/imagerepresentationgl.h"
40
#include "core/datastructures/facegeometry.h"
41
#include "core/datastructures/geometrydatafactory.h"
42
#include "core/tools/job.h"
43
44
#include "core/classification/tfgeometry1d.h"
#include "core/classification/geometry1dtransferfunction.h"
45

46
47
#include "datacontainerinspectorwidget.h"

48
49
#include "ext/tgt/navigation/trackball.h"

50

schultezub's avatar
schultezub committed
51
namespace campvis {
52
53
54

    DataContainerInspectorCanvas::DataContainerInspectorCanvas(QWidget* parent /*= 0*/) 
        : tgt::QtThreadedCanvas("DataContainer Inspector", tgt::ivec2(640, 480), tgt::GLCanvas::RGBA_BUFFER, parent, true)
55
        , p_currentSlice("CurrentSlice", "Slice", -1, -1, -1)
56
        , p_meshSolidColor("MeshSolidColor", "Mesh Solid Color", tgt::vec4(50.f, 70.0f, 50.0f, 255.f), tgt::vec4(0.0f), tgt::vec4(255.0f))
57
        , p_transferFunction("TransferFunction", "Transfer Function", new Geometry1DTransferFunction(256, tgt::vec2(0.f, 1.f)))
58
59
        , _dataContainer(0)
        , _paintShader(0)
60
        , _quad(0)
61
62
63
64
        , _numTiles(0, 0)
        , _quadSize(0, 0)
        , _selectedTexture(0)
        , _renderFullscreen(false)
65
        , _currentSlice(-1)
66
        , _color(0.0f, 0.0f, 0.0f, 0.0f)
67
        , _meshGeomTexturesDirty(false)
68
    {
69
        static_cast<Geometry1DTransferFunction*>(p_transferFunction.getTF())->addGeometry(TFGeometry1D::createQuad(tgt::vec2(0.f, 1.f), tgt::col4(0, 0, 0, 255), tgt::col4(255, 255, 255, 255)));
70
71
72
73
74
75
76
77
78
79

        makeCurrent();
        // Init GLEW for this context
        GLenum err = glewInit();
        if (err != GLEW_OK) {
            // Problem: glewInit failed, something is seriously wrong.
            tgtAssert(false, "glewInit failed");
            std::cerr << "glewInit failed, error: " << glewGetErrorString(err) << std::endl;
            exit(EXIT_FAILURE);
        }
80
        
81
82
        addProperty(&p_currentSlice);
        addProperty(&p_transferFunction);
83
        addProperty(&p_meshSolidColor);
84
85
86
87
88
89
    }

    DataContainerInspectorCanvas::~DataContainerInspectorCanvas() {

    }

90
    void DataContainerInspectorCanvas::init(DataContainerInspectorWidget* _pWidget) {
schultezub's avatar
schultezub committed
91
92
        initAllProperties();

93
        _widget = _pWidget;
94

95
96
        GLJobProc.registerContext(this);
        _paintShader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "application/glsl/datacontainerinspector.frag", "", false);
97
        _geometryRenderingShader = ShdrMgr.loadSeparate("core/glsl/passthrough.vert", "modules/vis/glsl/geometryrenderer.frag", "", false);
98

99
100
        _paintShader->setAttributeLocation(0, "in_Position");
        _paintShader->setAttributeLocation(1, "in_TexCoords");
101

102
103
        createQuad();

104
        // set this as painter to get notified when window size changes
105
        setPainter(this, false);
106
        getEventHandler()->addEventListenerToFront(this);
107
108
109

        _frameBuffer = new tgt::FramebufferObject();
        _depthBuffer = new tgt::Texture(0, tgt::ivec3(width(), height(), 1), GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, GL_FLOAT, tgt::Texture::LINEAR);		//, _renderingWndSize(tgt::ivec2(400, 100))
110
111
112
    }

    void DataContainerInspectorCanvas::deinit() {
schultezub's avatar
schultezub committed
113
114
        deinitAllProperties();

115
116
117
118
        if (_dataContainer != 0) {
            _dataContainer->s_dataAdded.disconnect(this);
        }

119
        _handles.clear();
120
        GLJobProc.deregisterContext(this);
121
        ShdrMgr.dispose(_paintShader);
122
        ShdrMgr.dispose(_geometryRenderingShader);
123
        delete _quad;
124
125
        delete _frameBuffer;
        delete _depthBuffer;
mostajab's avatar
mostajab committed
126
127
128
129

        resetContent();
    }

130
    void DataContainerInspectorCanvas::resetContent() {
mostajab's avatar
mostajab committed
131
132
133
        /// Clear the textures Array and geometry textures indicies array
        _textures.clear();

134
        /// Clear the trackball navigation event listener array
mostajab's avatar
mostajab committed
135
        /// - First delete the data that it contains
136
137
138
139
140
        std::vector<TrackballNavigationEventListener*>::iterator trackballNavEHIterator = _trackballEHs.begin();
        for(; trackballNavEHIterator != _trackballEHs.end(); trackballNavEHIterator++) {
            delete (*trackballNavEHIterator);
        }
        _trackballEHs.clear();
mostajab's avatar
mostajab committed
141
142
143
144

        /// Clear the Camera properties related to the trackballs array
        /// - First delete the data that it contains
        std::vector<campvis::CameraProperty*>::iterator camPropertyIterator = _trackballCameraProperties.begin();
145
146
147
        for(; camPropertyIterator != _trackballCameraProperties.end(); camPropertyIterator++) {
            delete (*camPropertyIterator);
        }
mostajab's avatar
mostajab committed
148
149
        _trackballCameraProperties.clear();

150
151
152
153
154
        std::vector<GeometryTextureInfo>::iterator geomTexInfoIter = _geomTextureInfos.begin();
        for(; geomTexInfoIter != _geomTextureInfos.end(); geomTexInfoIter++) {
            (*geomTexInfoIter).destroy();
        }
        _geomTextureInfos.clear();
155
156
157
158
159
160
161
162
    }

    QSize DataContainerInspectorCanvas::sizeHint() const {
        return QSize(640, 480);
    }


    void DataContainerInspectorCanvas::paint() {
163
164

        /// if the window is resized, change the depth buffer size, also!
165
        if(!_depthBuffer || _depthBuffer->getWidth() != width() || _depthBuffer->getHeight() != height()) {
166
167
168
            delete _depthBuffer;
            _depthBuffer = new tgt::Texture(0, tgt::ivec3(width(), height(), 1), GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT24, GL_FLOAT, tgt::Texture::LINEAR);		//, _renderingWndSize(tgt::ivec2(400, 100))
            _texturesDirty = true;
169
        }
170
        
171

172
        LGL_ERROR;
173
        tbb::mutex::scoped_lock lock(_localMutex);
174
175
176
        if (_texturesDirty)
            updateTextures();

177
178
        if (_textures.empty())
            return;
179
180

        glPushAttrib(GL_ALL_ATTRIB_BITS);
181
        glViewport(0, 0, size_.x, size_.y);
182
183
184
185
186
        glClearColor(0.7f, 0.7f, 0.7f, 1.f);
        glClear(GL_COLOR_BUFFER_BIT);
        LGL_ERROR;

        // update layout dimensions
187
188
        _numTiles.x = ceil(sqrt(static_cast<float>(_textures.size())));
        _numTiles.y = ceil(static_cast<float>(_textures.size()) / _numTiles.x);
189
        _quadSize = size_ / _numTiles;
190
191
192
193
194
195

        _paintShader->activate();

        tgt::mat4 projection = tgt::mat4::createOrtho(0, size_.x, 0, size_.y, -1, 1);
        _paintShader->setUniform("_projectionMatrix", projection);

196
197
        tgt::TextureUnit tfUnit, unit2d, unit3d;
        p_transferFunction.getTF()->bind(_paintShader, tfUnit);
198
199
        _paintShader->setUniform("_texture2d", unit2d.getUnitNumber());
        _paintShader->setUniform("_texture3d", unit3d.getUnitNumber());
200

201
202
203
204
205
206
207
208
209
210
        for (int y = 0; y < _numTiles.y; ++y) {
            for (int x = 0; x < _numTiles.x; ++x) {
                int index = (_numTiles.x * y) + x;
                if (index >= static_cast<int>(_textures.size()))
                    break;

                tgt::mat4 scaleMatrix = tgt::mat4::createScale(tgt::vec3(_quadSize, 1.f));
                tgt::mat4 translation = tgt::mat4::createTranslation(tgt::vec3(_quadSize.x * x, _quadSize.y * y, 0.f));
                _paintShader->setUniform("_modelMatrix", translation * scaleMatrix);
                paintTexture(_textures[index], unit2d, unit3d);
211
212
213
            }
        }

214
        _paintShader->deactivate();
215
216
217
218
        LGL_ERROR;
        glPopAttrib();
    }

219
    void DataContainerInspectorCanvas::paintMeshGeomTextures() {
220
221
222
        LGL_ERROR;
        tbb::mutex::scoped_lock lock(_localMutex);
        if (_meshGeomTexturesDirty)
223
            updateMeshGeomRenderedTextures();
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266

        if (_textures.empty())
            return;

        glPushAttrib(GL_ALL_ATTRIB_BITS);
        glViewport(0, 0, size_.x, size_.y);
        glClearColor(0.7f, 0.7f, 0.7f, 1.f);
        glClear(GL_COLOR_BUFFER_BIT);
        LGL_ERROR;

        // update layout dimensions
        _numTiles.x = ceil(sqrt(static_cast<float>(_textures.size())));
        _numTiles.y = ceil(static_cast<float>(_textures.size()) / _numTiles.x);
        _quadSize = size_ / _numTiles;

        _paintShader->activate();

        tgt::mat4 projection = tgt::mat4::createOrtho(0, size_.x, 0, size_.y, -1, 1);
        _paintShader->setUniform("_projectionMatrix", projection);

        tgt::TextureUnit tfUnit, unit2d, unit3d;
        p_transferFunction.getTF()->bind(_paintShader, tfUnit);
        _paintShader->setUniform("_texture2d", unit2d.getUnitNumber());
        _paintShader->setUniform("_texture3d", unit3d.getUnitNumber());

        for (int y = 0; y < _numTiles.y; ++y) {
            for (int x = 0; x < _numTiles.x; ++x) {
                int index = (_numTiles.x * y) + x;
                if (index >= static_cast<int>(_textures.size()))
                    break;

                tgt::mat4 scaleMatrix = tgt::mat4::createScale(tgt::vec3(_quadSize, 1.f));
                tgt::mat4 translation = tgt::mat4::createTranslation(tgt::vec3(_quadSize.x * x, _quadSize.y * y, 0.f));
                _paintShader->setUniform("_modelMatrix", translation * scaleMatrix);
                paintTexture(_textures[index], unit2d, unit3d);
            }
        }

        _paintShader->deactivate();
        LGL_ERROR;
        glPopAttrib();
    }

267
    void DataContainerInspectorCanvas::paintTexture(const tgt::Texture* texture, const tgt::TextureUnit& unit2d, const tgt::TextureUnit& unit3d) {
268
269

        _paintShader->setIgnoreUniformLocationError(true);
270
271
272
273
        if (texture->getDimensions().z == 1) {
            unit2d.activate();
            texture->bind();
            _paintShader->setUniform("_is3d", false);
274
            _paintShader->setUniform("_isDepthTexture", texture->isDepthTexture());
275
276
277
            _paintShader->setUniform("_2dTextureParams._size", tgt::vec2(texture->getDimensions().xy()));
            _paintShader->setUniform("_2dTextureParams._sizeRCP", tgt::vec2(1.f) / tgt::vec2(texture->getDimensions().xy()));
            _paintShader->setUniform("_2dTextureParams._numChannels", static_cast<int>(texture->getNumChannels()));
278
279
        }
        else {
280
281
282
            // clamp current slice to texture size, since this can't be done in event handler:
            _currentSlice = tgt::clamp(_currentSlice, -1, texture->getDimensions().z);

283
284
285
            unit3d.activate();
            texture->bind();
            _paintShader->setUniform("_is3d", true);
286
            _paintShader->setUniform("_sliceNumber", p_currentSlice.getValue());
287
288
289
            _paintShader->setUniform("_3dTextureParams._size", tgt::vec3(texture->getDimensions()));
            _paintShader->setUniform("_3dTextureParams._sizeRCP", tgt::vec3(1.f) / tgt::vec3(texture->getDimensions()));
            _paintShader->setUniform("_3dTextureParams._numChannels", static_cast<int>(texture->getNumChannels()));
290
        }
291
292
        _paintShader->setIgnoreUniformLocationError(false);

293
        _quad->render(GL_POLYGON);
294
295
296
        LGL_ERROR;
    }

297
    void DataContainerInspectorCanvas::drawGeomteryData(const campvis::GeometryData* mg, tgt::Texture* colorBuffer, const int& trackballndx) {
298
        LGL_ERROR;
mostajab's avatar
mostajab committed
299
        
300
301
        glPushAttrib(GL_ALL_ATTRIB_BITS);
        
mostajab's avatar
mostajab committed
302
303
        /// Activate the shader for geometry Rendering.
        _geometryRenderingShader->activate();
304
        LGL_ERROR;
305
306
307
308
309
310
311
312
        _geometryRenderingShader->setIgnoreUniformLocationError(true);
        LGL_ERROR;
        
        _trackballEHs[trackballndx]->setSceneBounds(mg->getWorldBounds());
        
        _geometryRenderingShader->setUniform("_projectionMatrix", _trackballEHs[trackballndx]->getTrackball()->getCamera()->getProjectionMatrix()/*_trackballCameraProperty->getValue().getProjectionMatrix()*/);
        LGL_ERROR;
        _geometryRenderingShader->setUniform("_viewMatrix", _trackballEHs[trackballndx]->getTrackball()->getCamera()->getViewMatrix());
313
314
        LGL_ERROR;

mostajab's avatar
mostajab committed
315
        // The color that will be used for rendering the object
316
317
318
319
320
        tgt::Vector4<float> meshColor = static_cast<tgt::Vector4<float>>(p_meshSolidColor.getValue());
        meshColor.r /= 255.0f;
        meshColor.g /= 255.0f;
        meshColor.b /= 255.0f;
        meshColor.a /= 255.0f;
321
        _geometryRenderingShader->setUniform("_color", meshColor);
322
323
        
        LGL_ERROR;
324
325
326
327
328
        _geometryRenderingShader->setIgnoreUniformLocationError(false);
                        LGL_ERROR;
        
        _frameBuffer->activate();
        LGL_ERROR;
329

330
331
        // Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
332

333
        colorBuffer->uploadTexture();
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
        colorBuffer->setWrapping(tgt::Texture::CLAMP_TO_EDGE);

        _depthBuffer->uploadTexture();
        _depthBuffer->setWrapping(tgt::Texture::CLAMP_TO_EDGE);
        LGL_ERROR;
        
        _frameBuffer->attachTexture(colorBuffer, GL_COLOR_ATTACHMENT0);
        _frameBuffer->attachTexture(_depthBuffer, GL_DEPTH_ATTACHMENT);
        _frameBuffer->isComplete();
        LGL_ERROR;

        glViewport(0, 0, width(), height());
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);
        glClearDepth(1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        LGL_ERROR;
351

352
        
mostajab's avatar
mostajab committed
353
        // render the geometry into a polygon mesh.
354
        glPolygonMode(GL_FRONT, GL_POLYGON);
355
        mg->render(GL_POLYGON);
356

357

mostajab's avatar
mostajab committed
358
        // change the color to white for the wireframe.
359
        _geometryRenderingShader->setUniform("_color", 1.0f, 1.0f, 1.0f, 1.0f);
mostajab's avatar
mostajab committed
360
361

        // Render wireframe around the geometry.
362
363
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        mg->render(GL_POLYGON);
mostajab's avatar
mostajab committed
364
             
365
366
        LGL_ERROR;

367
        colorBuffer->downloadTexture();
368

369
370
        _frameBuffer->deactivate();
        LGL_ERROR;
371

372
        _geometryRenderingShader->deactivate();
373
374

        glPopAttrib();
375
376
377
    }

    void DataContainerInspectorCanvas::invalidate() {
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
378
379
380
        // only if inited
        if (_quad != 0 && _paintShader != 0)
            GLJobProc.enqueueJob(this, makeJobOnHeap(this, &DataContainerInspectorCanvas::paint), OpenGLJobProcessor::PaintJob);
381
382
    }

383
    void DataContainerInspectorCanvas::invalidateMeshGeomTextures() {
384
385
        // only if inited
        if (_quad != 0 && _paintShader != 0)
386
            GLJobProc.enqueueJob(this, makeJobOnHeap(this, &DataContainerInspectorCanvas::paintMeshGeomTextures), OpenGLJobProcessor::PaintJob);
387
388
    }

389
    void DataContainerInspectorCanvas::createQuad() {
390
        delete _quad;
391
392
        _quad = 0;
        _quad = GeometryDataFactory::createQuad(tgt::vec3(0.f), tgt::vec3(1.f), tgt::vec3(0.f), tgt::vec3(1.f));
393
394
    }

395
396
397
398
    void DataContainerInspectorCanvas::repaint() {
        invalidate();
    }

399
    void DataContainerInspectorCanvas::sizeChanged(const tgt::ivec2& size) {
400
401
402
        invalidate();
    }

403
404
405
406
407
408
409
410
411
    void DataContainerInspectorCanvas::mouseDoubleClickEvent(tgt::MouseEvent* e) {
        if (_renderFullscreen) {
            _renderFullscreen = false;
        }
        else {
            tgt::ivec2 selectedIndex(e->x() / _quadSize.x, e->y() / _quadSize.y);
            _selectedTexture = (selectedIndex.y * _numTiles.x) + selectedIndex.x;
            _renderFullscreen = true;
        }
412
        e->ignore();
413
414
415
        invalidate();
    }

416
417
    void DataContainerInspectorCanvas::mouseMoveEvent(tgt::MouseEvent* e)
    {
418
        if(e->button() == tgt::MouseEvent::MOUSE_BUTTON_LEFT) {
419
420
421
422
423
424
425
426
427
428
            tgt::MouseEvent* me = static_cast<tgt::MouseEvent*>(e);

            tgt::MouseEvent adjustedMe(
                me->x(),
                me->y(),
                me->action(),
                me->modifiers(),
                me->button(),
                me->viewport() 
                );
429

430
431
432
            
            if(_selectedTrackball >= 0) {
                _trackballEHs[_selectedTrackball]->onEvent(&adjustedMe);
433

434
435
436
                _meshGeomTexturesDirty = true;
                invalidateMeshGeomTextures();
            }
437
            
438
        }
439
        else if(e->button() == tgt::MouseEvent::MOUSE_BUTTON_RIGHT) {
440
441
442
443
444
445
446
447
448
449
            tgt::ivec2 dimCanvas = tgt::ivec2(_quadSize.x * _numTiles.x, _quadSize.y * _numTiles.y);    
            if(e->x() >= dimCanvas.x || e->y() >= dimCanvas.y || e->x() < 0 || e->y() < 0)
                return;

            int texIndx = (e->y() / _quadSize.y) * _numTiles.x + (e->x() / _quadSize.x);
            const tgt::Texture* texturePtr = _textures[texIndx];
            const int texWidth  = texturePtr->getWidth();
            const int texHeight = texturePtr->getHeight();
            int cursorPosX = static_cast<int>(static_cast<float>(e->x() % _quadSize.x) / _quadSize.x * texWidth);
            int cursorPosY = static_cast<int>(static_cast<float>(e->y() % _quadSize.y) / _quadSize.y * texHeight);
450

451
452
453
454
455
456
457
458
459
            float f = 0.0;
            if(_textures[texIndx]->isDepthTexture()) {
                _depth = _textures[texIndx]->depthAsFloat(cursorPosX, texHeight - cursorPosY - 1);
                _widget->updateDepth();
            }
            else {
                _color = _textures[texIndx]->texelAsFloat(cursorPosX, texHeight - cursorPosY - 1);
                _widget->updateColor();
            }      
460
        }
461
462
    }

463
464
465
466
467
468
469
470
471
472
473
474
    void DataContainerInspectorCanvas::wheelEvent(tgt::MouseEvent* e) {
        if (_renderFullscreen) {
            switch (e->button()) {
                case tgt::MouseEvent::MOUSE_WHEEL_UP:
                    ++_currentSlice; // we cant clamp the value here to the number of slices - we do this during rendering
                    e->ignore();
                    break;
                case tgt::MouseEvent::MOUSE_WHEEL_DOWN:
                    if (_currentSlice >= -1)
                        --_currentSlice;
                    e->ignore();
                    break;
475
476
                default:
                    break;
477
478
479
480
481
            }
            invalidate();
        }
    }

482
    void DataContainerInspectorCanvas::mousePressEvent(tgt::MouseEvent* e) {
483
484
485
        tgt::ivec2 selectedIndex(e->x() / _quadSize.x, e->y() / _quadSize.y);
        _selectedTrackball = -1;
        std::vector<GeometryTextureInfo>::iterator geomTexInfoIter = _geomTextureInfos.begin();
486

487
488
489
        switch (e->button()) {
        case tgt::MouseEvent::MOUSE_BUTTON_LEFT:
            _selectedTexture = (selectedIndex.y * _numTiles.x) + selectedIndex.x;
490
                
491
492
493
494
            for(; geomTexInfoIter != _geomTextureInfos.end(); geomTexInfoIter++) {
                if((*geomTexInfoIter)._trackballIndx == _selectedTexture) {
                    _selectedTrackball = (*geomTexInfoIter)._trackballIndx;
                    break;
495
                }
496
            }
497

498
499
500
            if(_selectedTrackball >= 0)
                _trackballEHs[_selectedTrackball]->getTrackball()->mousePressEvent(e);
                break;
501
                
502
503
504
            default:
                break;
        }
505
506
507
508
509
510
    }

    void DataContainerInspectorCanvas::mouseReleaseEvent(tgt::MouseEvent* e) {
        if (_renderFullscreen) {
            switch (e->button()) {
            case tgt::MouseEvent::MOUSE_BUTTON_LEFT:
511
                if(_selectedTrackball >= 0)
512
                _trackballEHs[_selectedTrackball]->getTrackball()->mouseReleaseEvent(e);
513
514
515
516
517
518
519
520
                    break;
                
                default:
                    break;
            }
        }
    }

521
522
523
524
525
526
527
528
529
530
531
532
533
    void DataContainerInspectorCanvas::onDataContainerChanged(const QString& key, QtDataHandle dh) {
        {
            tbb::mutex::scoped_lock lock(_localMutex);

            // check whether DataHandle is already existing
            std::map<QString, QtDataHandle>::iterator lb = _handles.lower_bound(key);
            if (lb == _handles.end() || lb->first != key) {
                // not existant -> do nothing
            }
            else {
                // existant -> replace
                lb->second = QtDataHandle(dh);
                // update _textures array
534
                _texturesDirty = true;
535
536
            }
        }
537
538
539

        if (_texturesDirty)
            invalidate();
540
541
542
543
544
545
546
547
548
    }

    void DataContainerInspectorCanvas::setDataHandles(const std::vector< std::pair<QString, QtDataHandle> >& handles) {
        {
            tbb::mutex::scoped_lock lock(_localMutex);
            _handles.clear();
            for (std::vector< std::pair<QString, QtDataHandle> >::const_iterator it = handles.begin(); it != handles.end(); ++it)
                _handles.insert(*it);

549
            _texturesDirty = true;
550
551
552
553
554
        }

        invalidate();
    }

555
    const tgt::Color& DataContainerInspectorCanvas::getCapturedColor() {
556
557
        return _color;
    }
558

559
    const float& DataContainerInspectorCanvas::getCapturedDepth() {
560
561
562
        return _depth;
    }

563
    void DataContainerInspectorCanvas::updateTextures() {
564

mostajab's avatar
mostajab committed
565
566
        /// Reset the content of the Canvas.
        resetContent();
567

568
        /// Calculate the maximum slices of the textures and fill the textures array
569
        int maxSlices = 1;
570
        unsigned int nMeshGeometry = 0;
571
572
        for (std::map<QString, QtDataHandle>::iterator it = _handles.begin(); it != _handles.end(); ++it) {
            if (const ImageData* img = dynamic_cast<const ImageData*>(it->second.getData())) {
573
                if (const ImageRepresentationGL* imgGL = img->getRepresentation<ImageRepresentationGL>()) {
574
                    _textures.push_back(imgGL->getTexture());
575
                    maxSlices = std::max(maxSlices, imgGL->getTexture()->getDimensions().z);
576
577
                }
            }
578
579
580
            else if (const RenderData* rd = dynamic_cast<const RenderData*>(it->second.getData())) {
                for (size_t i = 0; i < rd->getNumColorTextures(); ++i) {
                    const ImageRepresentationGL* imgGL = rd->getColorTexture(i)->getRepresentation<ImageRepresentationGL>();
581
                    if (imgGL) {
582
                        imgGL->downloadTexture();
583
                        _textures.push_back(imgGL->getTexture());
584
                    }
585
586
587
                }
                if (rd->hasDepthTexture()) {
                    const ImageRepresentationGL* imgGL = rd->getDepthTexture()->getRepresentation<ImageRepresentationGL>();
588
                    if (imgGL) {
589
                        imgGL->downloadTexture();
590
                        _textures.push_back(imgGL->getTexture());
591
                    }
592
593
594

                }
            }
595
            else if(const campvis::GeometryData* gd = dynamic_cast<const campvis::GeometryData*>(it->second.getData())) {
596
                
597
                LGL_ERROR;
598

599
600
601
602
603
604
                GeometryTextureInfo geomTexInfo;
                geomTexInfo._geomData = it->second;
                geomTexInfo._trackballIndx = nMeshGeometry;
                              
                campvis::CameraProperty* cameraProperty = new CameraProperty("camera", "Camera");
                _trackballCameraProperties.push_back(cameraProperty);
605

mostajab's avatar
mostajab committed
606
                /// re-initialize the trackball navigation event listener to reset the object's pose
607
608
609
610
                TrackballNavigationEventListener* trackballEH = new TrackballNavigationEventListener(cameraProperty, new IVec2Property("QuadSize", "Size", tgt::ivec2(width(), height()), tgt::ivec2(0), tgt::ivec2(1024)) );
                float dist = 3 * fabs(gd->getWorldBounds().getLLF().z - gd->getWorldBounds().getURB().z);
                trackballEH->reinitializeCamera(gd->getWorldBounds());
                trackballEH->getTrackball()->moveCameraBackward(dist);
mostajab's avatar
mostajab committed
611
                LGL_ERROR;
612
                                
mostajab's avatar
mostajab committed
613
                /// store the trackball in the vector
614
615
                _trackballEHs.push_back(trackballEH);
                
mostajab's avatar
mostajab committed
616
                /// create color buffer and depth buffer.
617
                tgt::Texture* colorBuffer = new tgt::Texture(0, tgt::ivec3(width(), height(), 1), GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR);
618

mostajab's avatar
mostajab committed
619
                /// Render the object on the buffers.
620
                glewExperimental = true;
621
                drawGeomteryData(gd, colorBuffer, nMeshGeometry++);
mostajab's avatar
mostajab committed
622

623
624
                geomTexInfo._texture = colorBuffer;

mostajab's avatar
mostajab committed
625
                /// Store the buffers into array.
626
627
                _geomTextureInfos.push_back(geomTexInfo);
                
mostajab's avatar
mostajab committed
628
629

                /// Store the rendered texture in textures.
630
631
                _textures.push_back(colorBuffer);
            }
632
        }
633
634
635
636

        if (maxSlices == 1)
            maxSlices = -1;
        p_currentSlice.setMaxValue(maxSlices);
637
        _meshGeomTexturesDirty = false;
638
        _texturesDirty = false;
639
640
    }

641
    void DataContainerInspectorCanvas::updateMeshGeomRenderedTextures() {
642
        
643
644
645
        std::vector<GeometryTextureInfo>::iterator geomTexInfosIter = _geomTextureInfos.begin();
        for(;geomTexInfosIter != _geomTextureInfos.end(); geomTexInfosIter++) {
            drawGeomteryData(dynamic_cast<const campvis::GeometryData*>((*geomTexInfosIter)._geomData.getData()), (*geomTexInfosIter)._texture, (*geomTexInfosIter)._trackballIndx);
646
        }
647

648
        _meshGeomTexturesDirty = false;
649
650
651
652
653
654
    }

    void DataContainerInspectorCanvas::onPropertyChanged(const AbstractProperty* prop) {
        HasPropertyCollection::onPropertyChanged(prop);
        invalidate();

655
656
        /// if the Mesh Solid Color property is changed, update the mesh's color
        const std::string propertyName = (prop)->getName();
657
        if(propertyName == "MeshSolidColor") {
658
659
660
            _meshGeomTexturesDirty = true;
            invalidateMeshGeomTextures();
        }        
661
    }
662
}