eepgenerator.cpp 8.89 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// ================================================================================================
// 
// This file is part of the TUMVis Visualization Framework.
// 
// If not explicitly stated otherwise: Copyright (C) 2012, all rights reserved,
//      Christian Schulte zu Berge (christian.szb@in.tum.de)
//      Chair for Computer Aided Medical Procedures
//      Technische Universitt Mnchen
//      Boltzmannstr. 3, 85748 Garching b. Mnchen, Germany
// 
// 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.
// 
// ================================================================================================

29
30
31
32
33
34
35
36
37
#include "eepgenerator.h"

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

#include "core/datastructures/imagedatagl.h"
#include "core/datastructures/imagedatarendertarget.h"
38
#include "core/datastructures/meshgeometry.h"
39
#include "core/pipeline/processordecoratormasking.h"
40
41
42
43
44
45

namespace TUMVis {
    const std::string EEPGenerator::loggerCat_ = "TUMVis.modules.vis.EEPGenerator";

    EEPGenerator::EEPGenerator(GenericProperty<tgt::ivec2>& canvasSize)
        : VisualizationProcessor(canvasSize)
schultezub's avatar
schultezub committed
46
47
48
49
50
        , _sourceImageID("sourceImageID", "Input Image", "", DataNameProperty::READ)
        , _geometryID("geometryID", "Input Geometry ID", "proxygeometry", DataNameProperty::READ)
        , _mirrorID("mirrorID", "Input Mirror ID", "mirror", DataNameProperty::READ)
        , _entryImageID("entryImageID", "Output Entry Points Image", "eep.entry", DataNameProperty::WRITE)
        , _exitImageID("exitImageID", "Output Exit Points Image", "eep.exit", DataNameProperty::WRITE)
51
        , _camera("camera", "Camera")
52
        , _enableMirror("enableMirror", "Enable Virtual Mirror Feature", false)
53
54
        , _shader(0)
    {
55
56
        addDecorator(new ProcessorDecoratorMasking());

57
        addProperty(&_sourceImageID);
schultezub's avatar
schultezub committed
58
        addProperty(&_geometryID);
59
        addProperty(&_mirrorID);
60
61
62
        addProperty(&_entryImageID);
        addProperty(&_exitImageID);
        addProperty(&_camera);
63
        addProperty(&_enableMirror);
64
65

        decoratePropertyCollection(this);
66
67
68
69
70
71
72
73
    }

    EEPGenerator::~EEPGenerator() {

    }

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

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

    void EEPGenerator::process(DataContainer& data) {
        DataContainer::ScopedTypedData<ImageDataGL> img(data, _sourceImageID.getValue());
89
        DataContainer::ScopedTypedData<MeshGeometry> proxyGeometry(data, _geometryID.getValue());
90

91
        if (img != 0 && proxyGeometry != 0 && _shader != 0) {
92
            if (img->getDimensionality() == 3) {
schultezub's avatar
schultezub committed
93
94
95
96
97
                if (_invalidationLevel.isInvalidShader()) {
                    _shader->setHeaders(generateHeader());
                    _shader->rebuild();
                }

98
99
                tgt::Bounds volumeExtent = img->getWorldBounds();
                tgt::Bounds textureBounds(tgt::vec3(0.f), tgt::vec3(1.f));
100

101
102
103
104
                // clip proxy geometry against near-plane to support camera in volume
                // FIXME:   In some cases, the near plane is not rendered correctly...
                float nearPlaneDistToOrigin = tgt::dot(_camera.getValue().getPosition(), -_camera.getValue().getLook()) - _camera.getValue().getNearDist() - .001f;
                MeshGeometry clipped = proxyGeometry->clipAgainstPlane(nearPlaneDistToOrigin, -_camera.getValue().getLook(), true, 0.02f);
105

106
                // start render setup
107
108
                glPushAttrib(GL_ALL_ATTRIB_BITS);
                _shader->activate();
109

110
                // setup virtual mirror if necessary
schultezub's avatar
schultezub committed
111
                tgt::mat4 mirrorMatrix = tgt::mat4::identity;
112
                if (_enableMirror.getValue()) {
schultezub's avatar
schultezub committed
113
114
115
116
117
118
119
120
                    DataContainer::ScopedTypedData<FaceGeometry> mirrorGeometry(data, _mirrorID.getValue());
                    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 
121
                        mirrorMatrix = tgt::transpose(tgt::mat4(
schultezub's avatar
schultezub committed
122
123
124
                            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, 
125
                            2*n.x*k      , 2*n.y*k      , 2*n.z*k      , 1));
schultezub's avatar
schultezub committed
126

127
                        // TODO: double check, whether matrix transpose is necessary
schultezub's avatar
schultezub committed
128
129
130
131
                    }
                    else {
                        LERROR("No suitable virtual mirror geometry found.");
                    }
132
                }
schultezub's avatar
schultezub committed
133

134
                decorateRenderProlog(data, _shader);
135
                
136
137
                _shader->setIgnoreUniformLocationError(true);
                _shader->setUniform("_viewportSizeRCP", 1.f / tgt::vec2(_renderTargetSize.getValue()));
138
139
140
                _shader->setUniform("_modelMatrix", mirrorMatrix);
                _shader->setUniform("_projectionMatrix", _camera.getValue().getProjectionMatrix());
                _shader->setUniform("_viewMatrix", _camera.getValue().getViewMatrix());
141
                _shader->setIgnoreUniformLocationError(false);
142

143
                glEnable(GL_CULL_FACE);
144
                glEnable(GL_DEPTH_TEST);
145
146

                // create entry points texture
147
                ImageDataRenderTarget* entrypoints = new ImageDataRenderTarget(tgt::svec3(_renderTargetSize.getValue(), 1), GL_RGBA16);
148
149
                entrypoints->activate();

150
151
                glDepthFunc(GL_LESS);
                glClearDepth(1.0f);
152
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
153
                glCullFace(_enableMirror.getValue() ? GL_FRONT : GL_BACK);
154
                clipped.render();
155
156
157
158

                entrypoints->deactivate();

                // create exit points texture
159
                ImageDataRenderTarget* exitpoints = new ImageDataRenderTarget(tgt::svec3(_renderTargetSize.getValue(), 1), GL_RGBA16);
160
161
                exitpoints->activate();

162
163
                glDepthFunc(GL_GREATER);
                glClearDepth(0.0f);
164
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
165
                glCullFace(_enableMirror.getValue() ? GL_BACK : GL_FRONT);
166
                clipped.render();
167
168
169

                exitpoints->deactivate();

170
                decorateRenderEpilog(_shader);
171
172
                _shader->deactivate();
                glPopAttrib();
schultezub's avatar
schultezub committed
173
                LGL_ERROR;
174
175
176

                data.addData(_entryImageID.getValue(), entrypoints);
                data.addData(_exitImageID.getValue(), exitpoints);
177
178
                _entryImageID.issueWrite();
                _exitImageID.issueWrite();
179
180
181
182
183
184
            }
            else {
                LERROR("Input image must have dimensionality of 3.");
            }
        }
        else {
185
            LERROR("No suitable input image or proxy geometry found.");
186
187
188
189
190
        }

        _invalidationLevel.setValid();
    }

schultezub's avatar
schultezub committed
191
    std::string EEPGenerator::generateHeader() const {
192
        return getDecoratedHeader();
schultezub's avatar
schultezub committed
193
194
    }

195
}