SelectionManagerMeshFaces.cpp 8.12 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
#include "SelectionManagerMeshFaces.h"
#include <GLViewer.h>




const char* SelectionManagerMeshFaces::s_DisplayShaderVSH =
    "#version 330\n"

    "uniform mat4 u_ModelViewMatrix;"
    "uniform mat4 u_ProjectionMatrix;"

13
    "in vec3 vertexPosition;"
14

15
    "flat out int id;"
16 17 18

    "void main()"
    "{"
19
    "    id = gl_VertexID / 3;"
20
    "    gl_Position = u_ProjectionMatrix * u_ModelViewMatrix * vec4(vertexPosition,1.0f);"
21 22 23 24 25 26
    "}";

const char* SelectionManagerMeshFaces::s_DisplayShaderGSH =
    "#version 330\n"
    "#extension GL_EXT_geometry_shader4 : enable\n"

27 28
    "layout( triangles ) in;"
    "layout( triangle_strip, max_vertices = 3 ) out;"
29 30 31

    "uniform sampler2D u_SelectionTexture;"

32
    "flat in int id[];"
33 34 35 36

    "void main()"
    "{"
    "   ivec2 bufferSize = textureSize( u_SelectionTexture, 0 );"
37 38
    "   float screenX = float( id[0] % bufferSize.x ) + 0.5;"
    "   float screenY = float( id[0] / bufferSize.x ) + 0.5;"
39 40 41 42 43 44 45
    "   vec2 texCoords = vec2(screenX,screenY) / vec2(bufferSize);"

    "   float selectionMask = texture(u_SelectionTexture,texCoords).x;"
    "   if( selectionMask > 0.5 )"
    "   {"
    "       gl_Position = gl_PositionIn[0];"
    "       EmitVertex();"
46 47 48 49 50 51 52

    "       gl_Position = gl_PositionIn[1];"
    "       EmitVertex();"

    "       gl_Position = gl_PositionIn[2];"
    "       EmitVertex();"

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
    "       EndPrimitive();"
    "   }"
    "}";

const char* SelectionManagerMeshFaces::s_DisplayShaderFSH =
    "#version 330\n"

    "uniform vec4 u_Color;"

    "void main()"
    "{"
    "   gl_FragColor = u_Color;"
    "}";


const char* SelectionManagerMeshFaces::s_SelectionShaderVSH =
    "#version 330\n"

    "in vec3 vertexPosition;"
72
    "flat out int id;"
73 74 75

    "void main()"
    "{"
76
    "    id = gl_VertexID / 3;"
77
    "    gl_Position = vec4( vertexPosition, 1.0 );"
78 79 80 81 82
    "}";

const char* SelectionManagerMeshFaces::s_SelectionShaderGSH =
    "#version 330\n"
    "#extension GL_EXT_geometry_shader4 : enable\n"
83
    "#extension GL_EXT_gpu_shader4 : enable\n"
84 85 86 87

    "layout( triangles ) in;"
    "layout( points, max_vertices = 1 ) out;"

88
    "uniform ivec2 u_OutBufferSize;"
89

90
    "flat in int id[];"
91 92 93 94 95 96

    "vec3 getClippingCoordinates( vec3 );"
    "bool isInsideViewport( vec3 );"
    "bool isInsideSelectionArea( vec3 );"
    "bool passCullingTest( vec3, vec3 );"
    "bool passOcclusionTest( vec3 );"
97 98 99

    "void main()"
    "{"
100 101 102 103 104 105 106 107 108 109 110 111 112
    "    vec3 v0 = gl_PositionIn[0].xyz;"
    "    vec3 v1 = gl_PositionIn[1].xyz;"
    "    vec3 v2 = gl_PositionIn[2].xyz;"

    "    vec3 faceNor = cross( v1-v0, v2-v0 );"
    "    vec3 bary = (v0 + v1 + v2) / 3.0;"
    "    vec3 baryClip = getClippingCoordinates( bary );"

    "    if( isInsideViewport(baryClip)       &&"
    "        isInsideSelectionArea(baryClip)  &&"
    "        passCullingTest(bary,faceNor)    &&"
    "        passOcclusionTest(bary)          )"
    "    {"
113 114
    "        float screenX = float( id[0] % u_OutBufferSize.x ) + 0.5;"
    "        float screenY = float( id[0] / u_OutBufferSize.x ) + 0.5;"
115 116 117 118 119

    "        gl_Position = vec4( 2.0 * screenX/float(u_OutBufferSize.x) - 1.0, 2.0 * screenY/float(u_OutBufferSize.y) - 1.0, 0.0, 1.0 );"
    "        EmitVertex();"
    "        EndPrimitive();"
    "    }"
120 121 122 123 124 125 126 127 128
    "}";

const char* SelectionManagerMeshFaces::s_SelectionShaderFSH =
    "#version 330\n"

    "uniform float u_SelectionStateUpdateValue; /* 0.0: erase, 1.0: set */"

    "void main()"
    "{"
129
    "   gl_FragColor = vec4( u_SelectionStateUpdateValue );"
130 131 132 133
    "}";


SelectionManagerMeshFaces::SelectionManagerMeshFaces( GPU::VBO &meshVBO,
134 135
                                                      const std::string& posAttribName,
                                                      bool useIndices) :
136
    FaceSelectionManager(),
137
    m_MeshVBO( meshVBO ),
138 139
    m_PosAttribName( posAttribName ),
    m_UseIndices( useIndices )
140 141 142 143 144 145 146 147
{
    GPU::CreateShaderFromSources(
        m_DisplayShader,
        s_DisplayShaderVSH,
        s_DisplayShaderGSH,
        s_DisplayShaderFSH
    );

148
    if( m_MeshVBO.Indices() && useIndices )
149 150 151
        m_NFaces = m_MeshVBO.Indices()->BufferSize() / 3;
    else
        m_NFaces = m_MeshVBO.Attrib(posAttribName)->BufferSize() / 3;
152

153 154
    m_FrameBufferWidth  = (unsigned int) std::sqrt( m_NFaces );
    m_FrameBufferHeight = (unsigned int) std::ceil( (float)m_NFaces / m_FrameBufferWidth );
155 156 157 158 159 160 161 162
}


void SelectionManagerMeshFaces::onRecompilingSelectionShader( SelectionTool *tool )
{
    GPU::CreateShaderFromSources(
        m_SelectionShader,
        s_SelectionShaderVSH,
163 164
        s_SelectionShaderGSH + tool->getSelectionShaderFunctions(),
        s_SelectionShaderFSH
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
    );
}


void SelectionManagerMeshFaces::onUpdatingSelection( SelectionTool *tool )
{
    // Save the OpenGL states.

    GLfloat clearColor[4];
    glGetFloatv( GL_COLOR_CLEAR_VALUE, clearColor );

    // Perform the rendering pass that computes the selection state of each vertex.

    if( !m_SelectionTexture.IsInstantiated() )
    {
        GLenum formats[] = { GL_R8, GL_RGB8, GL_NONE };
        m_SelectionTexture.Create( formats, m_FrameBufferWidth, m_FrameBufferHeight );
        m_SelectionTexture.SetBaseAndMaxLevels( 0 );
        m_SelectionTexture.SetFiltering( GL_NEAREST );

        m_SelectionOutBuffer.Create( m_FrameBufferWidth, m_FrameBufferHeight );
        m_SelectionOutBuffer.Attach( GL_COLOR_ATTACHMENT0, m_SelectionTexture );
    }

    // Perform the rendering pass that computes the selection state of each vertex.

    m_SelectionOutBuffer.Bind();

    tool->initSelectionShader( m_SelectionShader );

    GLuint outBufferSize[2] = { m_SelectionOutBuffer.Width(), m_SelectionOutBuffer.Height() };
    m_SelectionShader.SetUniform( "u_OutBufferSize", outBufferSize );

    GLfloat updateValue = tool->selectionMode()==SelectionTool::SELECTION_MODE_REMOVE?  0.0f  :  1.0f;
    m_SelectionShader.SetUniform( "u_SelectionStateUpdateValue", &updateValue );

    m_MeshVBO.SetShader( &m_SelectionShader );
    m_MeshVBO.SetShaderAttribBinding( "vertexPosition", m_PosAttribName );

    //glNormal3f( 0.0f, 0.0f, 0.0f );
    //m_IsNormalLoaded?  m_VBO.Normal.Enable()  :  m_VBO.Normal.Disable();

    glPointSize( 1.0f );
208 209 210 211
    if( m_MeshVBO.Indices()  &&  m_UseIndices )
        m_MeshVBO.DrawElements( GL_TRIANGLES );
    else
        m_MeshVBO.DrawArrays( GL_TRIANGLES );
212 213 214 215 216 217 218 219 220 221 222
    glFlush();

    m_SelectionOutBuffer.Unbind();


    // Restore the OpenGL states.

    glClearColor( clearColor[0], clearColor[1], clearColor[2], clearColor[3] );
}


223 224
void SelectionManagerMeshFaces::onDisplay( GLViewer *viewer,
                                           const QMatrix4x4 &localTransfo )
225 226 227 228
{
    // Display selected vertices.
    if( m_SelectionTexture.IsInstantiated() )
    {
229
        m_DisplayShader.SetUniform( "u_ModelViewMatrix", (viewer->viewMatrix()*localTransfo).data() );
230
        m_DisplayShader.SetUniform( "u_ProjectionMatrix", viewer->projectionMatrix().data() );
231
        GLfloat pointColor[4] = { 1.0f, 0.0f, 0.0f, 0.375f };
232 233 234 235 236 237
        m_DisplayShader.SetUniform( "u_Color", pointColor );

        m_DisplayShader.RemoveAllSamplerBindings();
        m_DisplayShader.SetSamplerBinding( "u_SelectionTexture", m_SelectionTexture );

        m_MeshVBO.SetShader( &m_DisplayShader );
238 239 240 241 242 243 244 245 246
        m_MeshVBO.SetShaderAttribBinding( "vertexPosition", m_PosAttribName );

        glPolygonMode( GL_FRONT, GL_LINE );
        glLineWidth( 1.0f );
        m_MeshVBO.DrawArrays( GL_TRIANGLES );

        glEnable( GL_BLEND );
        glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
        glPolygonMode( GL_FRONT, GL_FILL );
247 248 249 250 251

        if( m_MeshVBO.Indices()  &&  m_UseIndices )
            m_MeshVBO.DrawElements( GL_TRIANGLES );
        else
            m_MeshVBO.DrawArrays( GL_TRIANGLES );
252

253
        glDisable( GL_BLEND );
254 255 256 257 258 259 260 261 262 263 264
    }
}


void SelectionManagerMeshFaces::clearSelection()
{
    m_SelectionOutBuffer.Release();
    m_SelectionTexture  .Release();
}


265
bool SelectionManagerMeshFaces::getSelectionMask( std::vector<uint8_t> &mask )
266
{
267 268 269 270 271 272 273 274 275
    if( m_SelectionTexture.IsInstantiated() )
    {
        mask.resize( m_SelectionOutBuffer.Width() * m_SelectionOutBuffer.Height() );
        m_SelectionOutBuffer.DumpTo( GL_COLOR_ATTACHMENT0, mask.data(), GL_RED, GL_UNSIGNED_BYTE );
        mask.resize( m_NFaces );
        return true;
    }
    else
        return false;
276
}