visualizationprocessor.cpp 8.11 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-2015, 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 Universitaet Muenchen
//      Boltzmannstr. 3, 85748 Garching b. Muenchen, 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 "visualizationprocessor.h"

27
#include "cgt/textureunit.h"
28
#include "core/datastructures/imagedata.h"
Jakob Weiss's avatar
Jakob Weiss committed
29
30
#include "core/datastructures/renderdata.h"
#include "core/datastructures/imagerepresentationgl.h"
31

schultezub's avatar
schultezub committed
32
namespace campvis {
schultezub's avatar
schultezub committed
33

34
35
36
37
    const std::string VisualizationProcessor::loggerCat_ = "CAMPVis.core.datastructures.VisualizationProcessor";

// ================================================================================================

38
    VisualizationProcessor::VisualizationProcessor(IVec2Property* viewportSizeProp)
schultezub's avatar
schultezub committed
39
        : AbstractProcessor()
40
        , p_lqMode("LqMode", "Low Quality Mode", false)
41
        , _fbo(0)
42
        , _viewportSizeProperty(viewportSizeProp)
schultezub's avatar
schultezub committed
43
    {
44
45
46
47
        if (_viewportSizeProperty) {
            _viewportSizeProperty->s_changed.connect<VisualizationProcessor>(this, &VisualizationProcessor::onPropertyChanged);
            setPropertyInvalidationLevel(*_viewportSizeProperty, INVALID_RESULT);
        }
schultezub's avatar
schultezub committed
48
49
50
51
52
    }

    VisualizationProcessor::~VisualizationProcessor() {
    }

53
54
    void VisualizationProcessor::init() {
        AbstractProcessor::init();
55

56
        cgtAssert(_viewportSizeProperty != 0, "The pointer to the viewport size property must not be 0!");
57
        addProperty(p_lqMode);
58

59
        _fbo = new cgt::FramebufferObject();
60
61
62
    }

    void VisualizationProcessor::deinit() {
63
64
65
66
67
        if (_viewportSizeProperty) {
            _viewportSizeProperty->s_changed.disconnect(this);
            _viewportSizeProperty = nullptr;
        }

68
69
70
71
        delete _fbo;
        AbstractProcessor::deinit();
    }

Jakob Weiss's avatar
Jakob Weiss committed
72
    void VisualizationProcessor::createAndAttachTexture(GLint internalFormat, GLenum attachment, ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) {
73
        cgtAssert(_fbo->isActive(), "Trying to attach a texture while FBO is not bound!");
74

75
        // acquire a new TextureUnit, so that we don't mess with other currently bound textures during texture upload...
76
        cgt::TextureUnit rtUnit;
77
78
79
80
81
        rtUnit.activate();

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

82
        // Check the render data if we can reuse a texture
Jakob Weiss's avatar
Jakob Weiss committed
83
        cgt::Texture* tex = nullptr;
84
        if (renderData) {
85
            // check if we can get a GL representation of the desired texture
Jakob Weiss's avatar
Jakob Weiss committed
86
            ImageRepresentationGL* glRep;
Jakob Weiss's avatar
Jakob Weiss committed
87
            if (attachment == GL_DEPTH_ATTACHMENT) {
Jakob Weiss's avatar
Jakob Weiss committed
88
89
                if(auto id = (*renderData)->getDepthTexture())
                    glRep = const_cast<ImageRepresentationGL*>(id->getRepresentation<ImageRepresentationGL>(false));
Jakob Weiss's avatar
Jakob Weiss committed
90
91
            }
            else {
92
                if(auto id =(*renderData)->getColorTexture(_fbo->getNumColorAttachments())) //_fbo->getNumColorAttachments() is the index of the texture that is to be created
Jakob Weiss's avatar
Jakob Weiss committed
93
                    glRep = const_cast<ImageRepresentationGL*>(id->getRepresentation<ImageRepresentationGL>(false));
Jakob Weiss's avatar
Jakob Weiss committed
94
95
            }
            
96
            // check if the texture is compatible with what we want, and in that case detach from the old RenderTargetData
Jakob Weiss's avatar
Jakob Weiss committed
97
98
99
100
101
102
103
            if (glRep) {
                tex = const_cast<cgt::Texture*>(glRep->getTexture());
                if (tex->getType() != GL_TEXTURE_2D || tex->getDimensions() != getRenderTargetSize()
                    || tex->getInternalFormat() != internalFormat)
                    tex = nullptr;
                else {
                    // somehow detach the cgt::Texture from the ImageRepresentationGL
104
105
                    // yes this is horrible - however, we know that renderData has write access, ergo
                    // we can safely do this const_cast
Jakob Weiss's avatar
Jakob Weiss committed
106
107
108
109
110
111
                    const_cast<ImageData*>(glRep->getParent())->removeRepresentationUnsafe<ImageRepresentationGL>();
                }

            }
        }

112
        // if we could not get the texture from a previous render target, create a new one
Jakob Weiss's avatar
Jakob Weiss committed
113
114
115
116
        if (!tex) {
            // create texture
            tex = new cgt::Texture(GL_TEXTURE_2D, getRenderTargetSize(), internalFormat, cgt::Texture::LINEAR);
        }
117
        tex->setWrapping(cgt::Texture::CLAMP_TO_EDGE);
118
119
120
121
122

        // attach texture to FBO
        _fbo->attachTexture(tex, attachment);
    }

Jakob Weiss's avatar
Jakob Weiss committed
123
    void VisualizationProcessor::createAndAttachTexture(GLint internalFormat, ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) {
124
125
        GLenum attachment = 0;
        switch(internalFormat) {
126
            case GL_R32F:
127
128
129
130
131
132
133
134
            case GL_RGB:
            case GL_RGB16F_ARB:
            case GL_RGBA:
            case GL_RGBA8:
            case GL_RGBA16:
            case GL_RGBA16F:
            case GL_RGBA32F:
                if (_fbo->getNumColorAttachments() >= static_cast<size_t>(GpuCaps.getMaxColorAttachments())) {
135
                    cgtAssert(false, "Tried to attach more color textures to FBO than supported!");
136
137
138
139
140
141
142
143
144
145
146
                    LWARNING("Tried to attach more color textures to FBO than supported, aborted.");
                    return;
                }
                attachment = static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + _fbo->getNumColorAttachments());
                break;

            case GL_DEPTH_COMPONENT16:
            case GL_DEPTH_COMPONENT24:
#ifdef GL_DEPTH_COMPONENT32F
            case GL_DEPTH_COMPONENT32F:
#endif
147
                cgtAssert(_fbo->getDepthAttachment() == 0, "Tried to attach more than one depth texture.");
148
149
150
151
                attachment = GL_DEPTH_ATTACHMENT;
                break;

            default:
152
                cgtAssert(false, "Unknown internal format!");
153
154
155
156
        }
        createAndAttachTexture(internalFormat, attachment);
    }

157
    cgt::ivec2 VisualizationProcessor::getEffectiveViewportSize() const {
158
159
160
        return (p_lqMode.getValue() ? _viewportSizeProperty->getValue() / 2 : _viewportSizeProperty->getValue());
    }

161
162
    cgt::ivec3 VisualizationProcessor::getRenderTargetSize() const {
        return cgt::ivec3(getEffectiveViewportSize(), 1);
163
164
    }

Jakob Weiss's avatar
Jakob Weiss committed
165
166
    void VisualizationProcessor::createAndAttachColorTexture(ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) {
        createAndAttachTexture(GL_RGBA8, renderData);
167
168
    }

Jakob Weiss's avatar
Jakob Weiss committed
169
170
    void VisualizationProcessor::createAndAttachDepthTexture(ScopedTypedData<RenderData, true>* renderData /*= nullptr*/) {
        createAndAttachTexture(GL_DEPTH_COMPONENT24, renderData);
171
172
    }

173
    void VisualizationProcessor::setViewportSizeProperty(IVec2Property* viewportSizeProp) {
174
        cgtAssert(viewportSizeProp != nullptr, "Pointer must not be nullptr.");
175

176
        if (_viewportSizeProperty != nullptr) {
177
            _viewportSizeProperty->s_changed.disconnect(this);
178
179
        }

180
181
        _viewportSizeProperty = viewportSizeProp;
        _viewportSizeProperty->s_changed.connect<VisualizationProcessor>(this, &VisualizationProcessor::onPropertyChanged);
182
        setPropertyInvalidationLevel(*viewportSizeProp, INVALID_RESULT);
183
        invalidate(INVALID_RESULT);
184
185
    }

schultezub's avatar
schultezub committed
186
}