2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

eepgenerator.cpp 10.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-2014, 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
// 
// ================================================================================================

25
26
27
28
29
30
31
#include "eepgenerator.h"

#include "tgt/glmath.h"
#include "tgt/logmanager.h"
#include "tgt/shadermanager.h"
#include "tgt/textureunit.h"

32
33
#include "core/datastructures/imagedata.h"
#include "core/datastructures/imagerepresentationgl.h"
34
#include "core/datastructures/renderdata.h"
35
#include "core/datastructures/renderdata.h"
36
#include "core/datastructures/meshgeometry.h"
37
#include "core/pipeline/processordecoratormasking.h"
38

schultezub's avatar
schultezub committed
39
40
namespace campvis {
    const std::string EEPGenerator::loggerCat_ = "CAMPVis.modules.vis.EEPGenerator";
41

42
43
    EEPGenerator::EEPGenerator(IVec2Property* viewportSizeProp)
        : VisualizationProcessor(viewportSizeProp)
44
        , p_sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ)
45
        , p_geometryID("geometryID", "Input Proxy Geometry ID", "proxygeometry", DataNameProperty::READ)
46
        , p_geometryImageId("GeometryImageId", "Rendered Geometry to Integrate (optional)", "", DataNameProperty::READ)
47
48
49
        , p_entryImageID("entryImageID", "Output Entry Points Image", "eep.entry", DataNameProperty::WRITE)
        , p_exitImageID("exitImageID", "Output Exit Points Image", "eep.exit", DataNameProperty::WRITE)
        , p_camera("camera", "Camera")
50
        , p_enableMirror("enableMirror", "Enable Virtual Mirror Feature", false)
51
        , p_mirrorID("mirrorID", "Input Mirror ID", "", DataNameProperty::READ)
52
53
        , _shader(0)
    {
54
55
        addDecorator(new ProcessorDecoratorMasking());

56
57
58
59
60
61
        addProperty(p_sourceImageID);
        addProperty(p_geometryID);
        addProperty(p_geometryImageId);
        addProperty(p_entryImageID);
        addProperty(p_exitImageID);
        addProperty(p_camera);
62

63
64
        addProperty(p_enableMirror, INVALID_RESULT | INVALID_PROPERTIES);
        addProperty(p_mirrorID);
65
        p_mirrorID.setVisible(false);
66
67

        decoratePropertyCollection(this);
68
69
70
71
72
73
74
75
    }

    EEPGenerator::~EEPGenerator() {

    }

    void EEPGenerator::init() {
        VisualizationProcessor::init();
76
        _shader = ShdrMgr.load("core/glsl/passthrough.vert", "modules/vis/glsl/eepgenerator.frag", generateHeader());
77
78
79
80
        if (_shader != 0) {
            _shader->setAttributeLocation(0, "in_Position");
            _shader->setAttributeLocation(1, "in_TexCoord");
        }
81
82
83
84
    }

    void EEPGenerator::deinit() {
        ShdrMgr.dispose(_shader);
schultezub's avatar
schultezub committed
85
        _shader = 0;
86
87
88
        VisualizationProcessor::deinit();
    }

89
    void EEPGenerator::updateResult(DataContainer& data) {
90
        ImageRepresentationGL::ScopedRepresentation img(data, p_sourceImageID.getValue());
91
        ScopedTypedData<MeshGeometry> proxyGeometry(data, p_geometryID.getValue());
92

93
        if (img != 0 && proxyGeometry != 0 && _shader != 0) {
94
            if (img->getDimensionality() == 3) {
95
                ScopedTypedData<RenderData> geometryImage(data, p_geometryImageId.getValue());
96

97
                tgt::Bounds textureBounds(tgt::vec3(0.f), tgt::vec3(1.f));
98

99
100
                // clip proxy geometry against near-plane to support camera in volume
                // FIXME:   In some cases, the near plane is not rendered correctly...
schultezub's avatar
schultezub committed
101
                float nearPlaneDistToOrigin = tgt::dot(p_camera.getValue().getPosition(), -p_camera.getValue().getLook()) - p_camera.getValue().getNearDist() - .002f;
102
                MeshGeometry clipped = proxyGeometry->clipAgainstPlane(nearPlaneDistToOrigin, -p_camera.getValue().getLook(), true, 0.02f);
103

104
                // start render setup
105
                _shader->activate();
106

107
                // setup virtual mirror if necessary
schultezub's avatar
schultezub committed
108
                tgt::mat4 mirrorMatrix = tgt::mat4::identity;
109
                if (p_enableMirror.getValue()) {
110
                    ScopedTypedData<FaceGeometry> mirrorGeometry(data, p_mirrorID.getValue());
schultezub's avatar
schultezub committed
111
112
113
114
115
116
117
                    if (mirrorGeometry && mirrorGeometry->size() > 0) {
                        const tgt::vec3& p = mirrorGeometry->getVertices()[0];
                        tgt::vec3 n = tgt::normalize(tgt::cross(mirrorGeometry->getVertices()[1] - mirrorGeometry->getVertices()[0], mirrorGeometry->getVertices()[2] - mirrorGeometry->getVertices()[0]));
                        float k = tgt::dot(p, n);

                        // mirror matrix sponsored by:
                        // Jiang 
118
                        mirrorMatrix = tgt::transpose(tgt::mat4(
schultezub's avatar
schultezub committed
119
120
121
                            1 - 2*n.x*n.x, -2*n.y*n.x   , -2*n.z*n.x   , 0, 
                            -2*n.x*n.y   , 1 - 2*n.y*n.y, -2*n.z*n.y   , 0, 
                            -2*n.x*n.z   , -2*n.y*n.z   , 1 - 2*n.z*n.z, 0, 
122
                            2*n.x*k      , 2*n.y*k      , 2*n.z*k      , 1));
schultezub's avatar
schultezub committed
123
124
125
126
                    }
                    else {
                        LERROR("No suitable virtual mirror geometry found.");
                    }
127
                }
128
                
schultezub's avatar
schultezub committed
129
130
131
                const tgt::Camera& cam = p_camera.getValue();
                tgt::TextureUnit geometryDepthUnit, entryDepthUnit;

132
                _shader->setIgnoreUniformLocationError(true);
133
                _shader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(getEffectiveViewportSize()));
134
                _shader->setUniform("_modelMatrix", mirrorMatrix);
135
136
137
138
                _shader->setUniform("_projectionMatrix", cam.getProjectionMatrix());
                _shader->setUniform("_viewMatrix", cam.getViewMatrix());

                if (geometryImage != 0) {
139
                    geometryImage->bindDepthTexture(_shader, geometryDepthUnit, "_geometryDepthTexture", "_geometryDepthTexParams");
140
141
142
143
144
145
146
147
148
149
150
151
152

                    _shader->setUniform("_integrateGeometry", true);
                    _shader->setUniform("_near", cam.getNearDist());
                    _shader->setUniform("_far", cam.getFarDist());

                    tgt::mat4 inverseView = tgt::mat4::identity;
                    if (cam.getViewMatrix().invert(inverseView))
                        _shader->setUniform("_inverseViewMatrix", inverseView);

                    tgt::mat4 inverseProjection = tgt::mat4::identity;
                    if (cam.getProjectionMatrix().invert(inverseProjection))
                        _shader->setUniform("_inverseProjectionMatrix", inverseProjection);

153
                    _shader->setUniform("_volumeWorldToTexture", img->getParent()->getMappingInformation().getWorldToTextureMatrix());
154
155
156
157
158
                }
                else {
                    _shader->setUniform("_integrateGeometry", false);
                }

159
                _shader->setIgnoreUniformLocationError(false);
160

161
162
                FramebufferActivationGuard fag(this);
                decorateRenderProlog(data, _shader);
163
                glEnable(GL_CULL_FACE);
164
                glEnable(GL_DEPTH_TEST);
165
166

                // create entry points texture
167
168
                createAndAttachTexture(GL_RGBA16);
                createAndAttachDepthTexture();
169
                _shader->setUniform("_isEntrypoint", true);
170

171
172
                glDepthFunc(GL_LESS);
                glClearDepth(1.0f);
173
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
174
                glCullFace(p_enableMirror.getValue() ? GL_FRONT : GL_BACK);
175
                clipped.render(GL_POLYGON);
176

177
                RenderData* entrypoints = new RenderData(_fbo);
178
                _fbo->detachAll();
179
180

                // create exit points texture
181
182
                createAndAttachTexture(GL_RGBA16);
                createAndAttachDepthTexture();
183
184
185
                _shader->setUniform("_isEntrypoint", false);

                if (geometryImage != 0) {
186
                    entrypoints->bindDepthTexture(_shader, entryDepthUnit, "_entryDepthTexture", "_entryDepthTexParams");
187
                }
188

189
190
                glDepthFunc(GL_GREATER);
                glClearDepth(0.0f);
191
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
192
                glCullFace(p_enableMirror.getValue() ? GL_BACK : GL_FRONT);
193
                clipped.render(GL_POLYGON);
194

195
                RenderData* exitpoints = new RenderData(_fbo);
196
                decorateRenderEpilog(_shader);
197
                _shader->deactivate();
198
199
200
201
202
203
204

                glDepthFunc(GL_LESS);
                glClearDepth(1.0f);
                glCullFace(GL_BACK);
                glDisable(GL_CULL_FACE);
                glDisable(GL_DEPTH_TEST);

schultezub's avatar
schultezub committed
205
                LGL_ERROR;
206

207
208
                data.addData(p_entryImageID.getValue(), entrypoints);
                data.addData(p_exitImageID.getValue(), exitpoints);
209
210
211
212
213
214
            }
            else {
                LERROR("Input image must have dimensionality of 3.");
            }
        }
        else {
215
            LERROR("No suitable input image or proxy geometry found.");
216
217
218
        }
    }

schultezub's avatar
schultezub committed
219
    std::string EEPGenerator::generateHeader() const {
220
        return getDecoratedHeader();
schultezub's avatar
schultezub committed
221
222
    }

223
    void EEPGenerator::updateProperties(DataContainer& dataContainer) {
224
225
226
        p_mirrorID.setVisible(p_enableMirror.getValue());
    }

227
228
229
230
231
    void EEPGenerator::updateShader() {
        _shader->setHeaders(generateHeader());
        _shader->rebuild();
    }

232
}