datacontainerinspectorcanvas.cpp 26.6 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
25
26
27
28
// 
// ================================================================================================

#include "datacontainerinspectorcanvas.h"

#include "tgt/assert.h"
#include "tgt/shadermanager.h"
29
30
#include "tgt/textureunit.h"

31
32
#include "core/datastructures/datacontainer.h"
#include "core/datastructures/datahandle.h"
33
#include "core/datastructures/renderdata.h"
34
#include "core/datastructures/imagerepresentationgl.h"
35
#include "core/datastructures/facegeometry.h"
36
#include "core/datastructures/geometrydatafactory.h"
37
#include "core/tools/job.h"
38
39
#include "core/classification/tfgeometry1d.h"
#include "core/classification/geometry1dtransferfunction.h"
40

41
42
#include "datacontainerinspectorwidget.h"

43
44
#include "ext/tgt/navigation/trackball.h"

45

schultezub's avatar
schultezub committed
46
namespace campvis {
47
48
49

    DataContainerInspectorCanvas::DataContainerInspectorCanvas(QWidget* parent /*= 0*/) 
        : tgt::QtThreadedCanvas("DataContainer Inspector", tgt::ivec2(640, 480), tgt::GLCanvas::RGBA_BUFFER, parent, true)
50
        , p_currentSlice("CurrentSlice", "Slice", -1, -1, -1)
51
        , p_meshSolidColor("MeshSolidColor", "Mesh Solid Color", tgt::vec4(.5f, .75f, .5f, 1), tgt::vec4(0.0f), tgt::vec4(1.0f))
52
        , p_transferFunction("TransferFunction", "Transfer Function", new Geometry1DTransferFunction(256, tgt::vec2(0.f, 1.f)))
53
54
        , _dataContainer(0)
        , _paintShader(0)
55
        , _quad(0)
56
57
58
59
        , _numTiles(0, 0)
        , _quadSize(0, 0)
        , _selectedTexture(0)
        , _renderFullscreen(false)
60
        , _currentSlice(-1)
61
        , _color(0.0f, 0.0f, 0.0f, 0.0f)
62
        , _meshGeomTexturesDirty(false)
63
    {
64
        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)));
65
66
67
68
69
70
71
72
73
74

        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);
        }
75
        
76
77
        addProperty(&p_currentSlice);
        addProperty(&p_transferFunction);
78
        addProperty(&p_meshSolidColor);
79
80
81
82
83
84
    }

    DataContainerInspectorCanvas::~DataContainerInspectorCanvas() {

    }

85
    void DataContainerInspectorCanvas::init(DataContainerInspectorWidget* _pWidget) {
schultezub's avatar
schultezub committed
86
87
        initAllProperties();

88
        _widget = _pWidget;
89

90
        GLJobProc.registerContext(this);
91
92
        _paintShader = ShdrMgr.load("core/glsl/passthrough.vert", "application/glsl/datacontainerinspector.frag", "");
        _geometryRenderingShader = ShdrMgr.load("core/glsl/passthrough.vert", "application/glsl/datacontainerinspector_geometryrenderer.frag", "");
93

94
95
        _paintShader->setAttributeLocation(0, "in_Position");
        _paintShader->setAttributeLocation(1, "in_TexCoords");
96

97
98
        createQuad();

99
        // set this as painter to get notified when window size changes
100
        setPainter(this, false);
101
        getEventHandler()->addEventListenerToFront(this);
102
103
104

        _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))
105
106
107
    }

    void DataContainerInspectorCanvas::deinit() {
schultezub's avatar
schultezub committed
108
109
        deinitAllProperties();

110
111
112
113
        if (_dataContainer != 0) {
            _dataContainer->s_dataAdded.disconnect(this);
        }

114
        _handles.clear();
115
        GLJobProc.deregisterContext(this);
116
        ShdrMgr.dispose(_paintShader);
117
        ShdrMgr.dispose(_geometryRenderingShader);
118
        delete _quad;
119
120
        delete _frameBuffer;
        delete _depthBuffer;
mostajab's avatar
mostajab committed
121
122
123
124

        resetContent();
    }

125
    void DataContainerInspectorCanvas::resetContent() {
mostajab's avatar
mostajab committed
126
127
128
        /// Clear the textures Array and geometry textures indicies array
        _textures.clear();

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

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

145
146
147
148
149
        std::vector<GeometryTextureInfo>::iterator geomTexInfoIter = _geomTextureInfos.begin();
        for(; geomTexInfoIter != _geomTextureInfos.end(); geomTexInfoIter++) {
            (*geomTexInfoIter).destroy();
        }
        _geomTextureInfos.clear();
150
151
152
153
154
155
156
157
    }

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


    void DataContainerInspectorCanvas::paint() {
158
159

        /// if the window is resized, change the depth buffer size, also!
160
        if(!_depthBuffer || _depthBuffer->getWidth() != width() || _depthBuffer->getHeight() != height()) {
161
162
163
            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;
164
        }
165
        
166

167
        LGL_ERROR;
168
        tbb::mutex::scoped_lock lock(_localMutex);
169
170
171
        if (_texturesDirty)
            updateTextures();

172
173
        if (_textures.empty())
            return;
174
175

        glPushAttrib(GL_ALL_ATTRIB_BITS);
176
        glViewport(0, 0, size_.x, size_.y);
177
178
179
180
181
        glClearColor(0.7f, 0.7f, 0.7f, 1.f);
        glClear(GL_COLOR_BUFFER_BIT);
        LGL_ERROR;

        // update layout dimensions
182
183
        _numTiles.x = ceil(sqrt(static_cast<float>(_textures.size())));
        _numTiles.y = ceil(static_cast<float>(_textures.size()) / _numTiles.x);
184
        _quadSize = size_ / _numTiles;
185
186
187
188
189
190

        _paintShader->activate();

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

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

196
197
198
199
200
201
202
203
204
205
        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);
206
207
208
            }
        }

209
        _paintShader->deactivate();
210
211
212
213
        LGL_ERROR;
        glPopAttrib();
    }

214
    void DataContainerInspectorCanvas::paintMeshGeomTextures() {
215
216
217
        LGL_ERROR;
        tbb::mutex::scoped_lock lock(_localMutex);
        if (_meshGeomTexturesDirty)
218
            updateMeshGeomRenderedTextures();
219
220
221
222
223
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

        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();
    }

262
    void DataContainerInspectorCanvas::paintTexture(const tgt::Texture* texture, const tgt::TextureUnit& unit2d, const tgt::TextureUnit& unit3d) {
263
264

        _paintShader->setIgnoreUniformLocationError(true);
265
266
267
268
        if (texture->getDimensions().z == 1) {
            unit2d.activate();
            texture->bind();
            _paintShader->setUniform("_is3d", false);
269
            _paintShader->setUniform("_isDepthTexture", texture->isDepthTexture());
270
271
272
            _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()));
273
274
        }
        else {
275
276
277
            // clamp current slice to texture size, since this can't be done in event handler:
            _currentSlice = tgt::clamp(_currentSlice, -1, texture->getDimensions().z);

278
279
280
            unit3d.activate();
            texture->bind();
            _paintShader->setUniform("_is3d", true);
281
            _paintShader->setUniform("_sliceNumber", p_currentSlice.getValue());
282
283
284
            _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()));
285
        }
286
287
        _paintShader->setIgnoreUniformLocationError(false);

288
        _quad->render(GL_POLYGON);
289
290
291
        LGL_ERROR;
    }

292
293
294
    void DataContainerInspectorCanvas::drawGeomteryData(const campvis::GeometryData* mg, tgt::Texture* colorBuffer, const int& trackballndx) {
        glPushAttrib(GL_ALL_ATTRIB_BITS);
        
mostajab's avatar
mostajab committed
295
296
        /// Activate the shader for geometry Rendering.
        _geometryRenderingShader->activate();
297
298
299
300
301
302
        _geometryRenderingShader->setIgnoreUniformLocationError(true);
        
        _trackballEHs[trackballndx]->setSceneBounds(mg->getWorldBounds());
        
        _geometryRenderingShader->setUniform("_projectionMatrix", _trackballEHs[trackballndx]->getTrackball()->getCamera()->getProjectionMatrix()/*_trackballCameraProperty->getValue().getProjectionMatrix()*/);
        _geometryRenderingShader->setUniform("_viewMatrix", _trackballEHs[trackballndx]->getTrackball()->getCamera()->getViewMatrix());
303

mostajab's avatar
mostajab committed
304
        // The color that will be used for rendering the object
305
        _geometryRenderingShader->setUniform("_color", p_meshSolidColor.getValue());
306
307
308
309
310
        _geometryRenderingShader->setIgnoreUniformLocationError(false);
        
        _frameBuffer->activate();
        // Set OpenGL pixel alignment to 1 to avoid problems with NPOT textures
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
311

312
        colorBuffer->uploadTexture();
313
314
315
316
317
318
319
320
321
322
323
324
325
326
        colorBuffer->setWrapping(tgt::Texture::CLAMP_TO_EDGE);

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

        glViewport(0, 0, width(), height());
        glEnable(GL_DEPTH_TEST);
        glDepthFunc(GL_LESS);
        glClearDepth(1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
327
        
mostajab's avatar
mostajab committed
328
        // render the geometry into a polygon mesh.
329
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
330
        mg->render(GL_POLYGON);
331

332

mostajab's avatar
mostajab committed
333
        // change the color to white for the wireframe.
334
        _geometryRenderingShader->setUniform("_color", 1.0f, 1.0f, 1.0f, 1.0f);
mostajab's avatar
mostajab committed
335
336

        // Render wireframe around the geometry.
337
338
339
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        mg->render(GL_POLYGON);

340
341
342
        colorBuffer->downloadTexture();
        _frameBuffer->deactivate();
        _geometryRenderingShader->deactivate();
343
344

        glPopAttrib();
345
        LGL_ERROR;
346
347
348
    }

    void DataContainerInspectorCanvas::invalidate() {
Christian Schulte zu Berge's avatar
Christian Schulte zu Berge committed
349
350
351
        // only if inited
        if (_quad != 0 && _paintShader != 0)
            GLJobProc.enqueueJob(this, makeJobOnHeap(this, &DataContainerInspectorCanvas::paint), OpenGLJobProcessor::PaintJob);
352
353
    }

354
    void DataContainerInspectorCanvas::invalidateMeshGeomTextures() {
355
356
        // only if inited
        if (_quad != 0 && _paintShader != 0)
357
            GLJobProc.enqueueJob(this, makeJobOnHeap(this, &DataContainerInspectorCanvas::paintMeshGeomTextures), OpenGLJobProcessor::PaintJob);
358
359
    }

360
    void DataContainerInspectorCanvas::createQuad() {
361
        delete _quad;
362
        _quad = 0;
363
        _quad = GeometryDataFactory::createQuad(tgt::vec3(0.f), tgt::vec3(1.f), tgt::vec3(0.f, 1.f, 0.f), tgt::vec3(1.f, 0.f, 0.f));
364
365
    }

366
367
368
369
    void DataContainerInspectorCanvas::repaint() {
        invalidate();
    }

370
    void DataContainerInspectorCanvas::sizeChanged(const tgt::ivec2& size) {
371
372
373
        invalidate();
    }

374
375
376
377
378
379
380
381
382
    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;
        }
383
        e->ignore();
384
385
386
        invalidate();
    }

387
388
    void DataContainerInspectorCanvas::mouseMoveEvent(tgt::MouseEvent* e)
    {
389
        if (e->button() == tgt::MouseEvent::MOUSE_BUTTON_LEFT) {
390
391
392
393
394
395
396
397
398
399
            tgt::MouseEvent* me = static_cast<tgt::MouseEvent*>(e);

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

401
402
403
            
            if(_selectedTrackball >= 0) {
                _trackballEHs[_selectedTrackball]->onEvent(&adjustedMe);
404

405
406
407
                _meshGeomTexturesDirty = true;
                invalidateMeshGeomTextures();
            }
408
            
409
        }
410
411

        {
412
413
414
415
416
417
418
419
420
421
            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);
422

423
424
425
426
427
428
            float f = 0.0;
            if(_textures[texIndx]->isDepthTexture()) {
                _depth = _textures[texIndx]->depthAsFloat(cursorPosX, texHeight - cursorPosY - 1);
                _widget->updateDepth();
            }
            else {
429
430
431
432
433
434
435
436
437
438
                if (_textures[texIndx]->getDimensions().z != 1) {
                    if (p_currentSlice.getValue() >= 0 && p_currentSlice.getValue() < _textures[texIndx]->getDimensions().z) {
                        _color = _textures[texIndx]->texelAsFloat(cursorPosX, texHeight - cursorPosY - 1, p_currentSlice.getValue());
                        _widget->updateColor();
                    }
                }
                else if (_textures[texIndx]->getDimensions().y != 1) {
                    _color = _textures[texIndx]->texelAsFloat(cursorPosX, texHeight - cursorPosY - 1);
                    _widget->updateColor();
                }
439
            }      
440
        }
441
442
    }

443
444
445
446
447
448
449
450
451
452
453
454
    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;
455
456
                default:
                    break;
457
458
459
460
461
            }
            invalidate();
        }
    }

462
    void DataContainerInspectorCanvas::mousePressEvent(tgt::MouseEvent* e) {
463
464
465
        tgt::ivec2 selectedIndex(e->x() / _quadSize.x, e->y() / _quadSize.y);
        _selectedTrackball = -1;
        std::vector<GeometryTextureInfo>::iterator geomTexInfoIter = _geomTextureInfos.begin();
466

467
468
469
        switch (e->button()) {
        case tgt::MouseEvent::MOUSE_BUTTON_LEFT:
            _selectedTexture = (selectedIndex.y * _numTiles.x) + selectedIndex.x;
470
                
471
472
473
474
            for(; geomTexInfoIter != _geomTextureInfos.end(); geomTexInfoIter++) {
                if((*geomTexInfoIter)._trackballIndx == _selectedTexture) {
                    _selectedTrackball = (*geomTexInfoIter)._trackballIndx;
                    break;
475
                }
476
            }
477

478
479
480
            if(_selectedTrackball >= 0)
                _trackballEHs[_selectedTrackball]->getTrackball()->mousePressEvent(e);
                break;
481
                
482
483
484
            default:
                break;
        }
485
486
487
488
489
490
    }

    void DataContainerInspectorCanvas::mouseReleaseEvent(tgt::MouseEvent* e) {
        if (_renderFullscreen) {
            switch (e->button()) {
            case tgt::MouseEvent::MOUSE_BUTTON_LEFT:
491
                if(_selectedTrackball >= 0)
492
                _trackballEHs[_selectedTrackball]->getTrackball()->mouseReleaseEvent(e);
493
494
495
496
497
498
499
500
                    break;
                
                default:
                    break;
            }
        }
    }

501
502
503
504
505
506
507
508
509
510
511
512
513
    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
514
                _texturesDirty = true;
515
516
            }
        }
517
518
519

        if (_texturesDirty)
            invalidate();
520
521
522
523
524
525
526
527
528
    }

    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);

529
            _texturesDirty = true;
530
531
532
533
534
        }

        invalidate();
    }

535
    const tgt::Color& DataContainerInspectorCanvas::getCapturedColor() {
536
537
        return _color;
    }
538

539
    const float& DataContainerInspectorCanvas::getCapturedDepth() {
540
541
542
        return _depth;
    }

543
    void DataContainerInspectorCanvas::updateTextures() {
544

mostajab's avatar
mostajab committed
545
546
        /// Reset the content of the Canvas.
        resetContent();
547

548
        /// Calculate the maximum slices of the textures and fill the textures array
549
        int maxSlices = 1;
550
        unsigned int nMeshGeometry = 0;
551
552
        for (std::map<QString, QtDataHandle>::iterator it = _handles.begin(); it != _handles.end(); ++it) {
            if (const ImageData* img = dynamic_cast<const ImageData*>(it->second.getData())) {
553
                if (const ImageRepresentationGL* imgGL = img->getRepresentation<ImageRepresentationGL>()) {
554
                    imgGL->downloadTexture();
555
                    _textures.push_back(imgGL->getTexture());
556
                    maxSlices = std::max(maxSlices, imgGL->getTexture()->getDimensions().z);
557
558
                }
            }
559
560
561
            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>();
562
                    if (imgGL) {
563
                        imgGL->downloadTexture();
564
                        _textures.push_back(imgGL->getTexture());
565
                    }
566
567
568
                }
                if (rd->hasDepthTexture()) {
                    const ImageRepresentationGL* imgGL = rd->getDepthTexture()->getRepresentation<ImageRepresentationGL>();
569
                    if (imgGL) {
570
                        imgGL->downloadTexture();
571
                        _textures.push_back(imgGL->getTexture());
572
                    }
573
574
575

                }
            }
576
            else if(const campvis::GeometryData* gd = dynamic_cast<const campvis::GeometryData*>(it->second.getData())) {
577
                
578
                LGL_ERROR;
579

580
581
582
583
584
585
                GeometryTextureInfo geomTexInfo;
                geomTexInfo._geomData = it->second;
                geomTexInfo._trackballIndx = nMeshGeometry;
                              
                campvis::CameraProperty* cameraProperty = new CameraProperty("camera", "Camera");
                _trackballCameraProperties.push_back(cameraProperty);
586

mostajab's avatar
mostajab committed
587
                /// re-initialize the trackball navigation event listener to reset the object's pose
588
589
590
591
                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
592
                LGL_ERROR;
593
                                
mostajab's avatar
mostajab committed
594
                /// store the trackball in the vector
595
596
                _trackballEHs.push_back(trackballEH);
                
mostajab's avatar
mostajab committed
597
                /// create color buffer and depth buffer.
598
                tgt::Texture* colorBuffer = new tgt::Texture(0, tgt::ivec3(width(), height(), 1), GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tgt::Texture::LINEAR);
599

mostajab's avatar
mostajab committed
600
                /// Render the object on the buffers.
601
                glewExperimental = true;
602
                drawGeomteryData(gd, colorBuffer, nMeshGeometry++);
mostajab's avatar
mostajab committed
603

604
605
                geomTexInfo._texture = colorBuffer;

mostajab's avatar
mostajab committed
606
                /// Store the buffers into array.
607
608
                _geomTextureInfos.push_back(geomTexInfo);
                
mostajab's avatar
mostajab committed
609
610

                /// Store the rendered texture in textures.
611
612
                _textures.push_back(colorBuffer);
            }
613
        }
614
615
616
617

        if (maxSlices == 1)
            maxSlices = -1;
        p_currentSlice.setMaxValue(maxSlices);
618
        _meshGeomTexturesDirty = false;
619
        _texturesDirty = false;
620
621
    }

622
    void DataContainerInspectorCanvas::updateMeshGeomRenderedTextures() {
623
        
624
625
626
        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);
627
        }
628

629
        _meshGeomTexturesDirty = false;
630
631
632
633
634
    }

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

635
636
        /// if the Mesh Solid Color property is changed, update the mesh's color
        const std::string propertyName = (prop)->getName();
637
        if(propertyName == "MeshSolidColor") {
638
639
640
            _meshGeomTexturesDirty = true;
            invalidateMeshGeomTextures();
        }        
641
    }
642
}