Commit 6b4b3468 authored by Frédéric Larue's avatar Frédéric Larue
Browse files

Selection mechanism modified in order to enable real-time feedback while using circular brush.

parent 8b23f2c9
......@@ -9,41 +9,51 @@
class SelectionManager
{
using ListenerList = QVector< RealTimeSelectionListener* >;
SelectableEntity m_SelectableEntity;
ListenerList m_RealTimeSelectionListeners;
public:
virtual ~SelectionManager() {}
virtual SelectableEntity selectableEntity() const = 0;
virtual void onRecompilingSelectionShader( SelectionTool *tool ) = 0;
virtual void onUpdatingSelection( SelectionTool *tool ) = 0;
virtual void onDisplay( GLViewer *viewer,
const QMatrix4x4 &localTransfo ) = 0;
virtual void clearSelection() {};
virtual bool getSelectionMask( std::vector<uint8_t> &mask ) = 0;
inline SelectionManager( SelectableEntity selectableEntity ) : m_SelectableEntity( selectableEntity ) {}
virtual ~SelectionManager() {}
inline SelectableEntity selectableEntity() const { return m_SelectableEntity; }
virtual void onRecompilingSelectionShader( SelectionTool *tool ) = 0;
virtual void onUpdatingSelection( SelectionTool *tool ) = 0;
virtual void onDisplay( GLViewer *viewer,
const QMatrix4x4 &localTransfo ) = 0;
virtual void clearSelection() {}
virtual bool getSelectionMask( std::vector<uint8_t> &mask ) = 0;
inline void addRealTimeListener( RealTimeSelectionListener* l ) { m_RealTimeSelectionListeners.push_back( l ); }
inline bool isRealTimeSelectionEnabled() const { return !m_RealTimeSelectionListeners.isEmpty(); }
inline ListenerList& realTimeListeners() { return m_RealTimeSelectionListeners; }
};
class TexelSelectionManager : public SelectionManager
{
public:
virtual ~TexelSelectionManager() {}
SelectableEntity selectableEntity() const { return SELECTABLE_ENTITY_TEXEL; }
inline TexelSelectionManager() : SelectionManager(SELECTABLE_ENTITY_TEXEL) {}
virtual ~TexelSelectionManager() {}
};
class VertexSelectionManager : public SelectionManager
{
public:
virtual ~VertexSelectionManager() {}
SelectableEntity selectableEntity() const { return SELECTABLE_ENTITY_VERTEX; }
inline VertexSelectionManager() : SelectionManager(SELECTABLE_ENTITY_VERTEX) {}
virtual ~VertexSelectionManager() {}
};
class FaceSelectionManager : public SelectionManager
{
public:
virtual ~FaceSelectionManager() {}
SelectableEntity selectableEntity() const { return SELECTABLE_ENTITY_FACE; }
inline FaceSelectionManager() : SelectionManager(SELECTABLE_ENTITY_FACE) {}
virtual ~FaceSelectionManager() {}
};
......
......@@ -75,6 +75,8 @@ const char* SelectionManagerMeshTexels::s_SelectionShaderFSH =
const char* SelectionManagerMeshTexels::s_RealTimeSelectionShaderFSH =
"#version 330\n"
"uniform float u_SelectionStateUpdateValue; /* 0.0: erase, 1.0: set */"
"in vec3 vertex;"
"out vec4 selectionState;"
......@@ -82,15 +84,17 @@ const char* SelectionManagerMeshTexels::s_RealTimeSelectionShaderFSH =
"bool isInsideViewport( vec3 );"
"bool isInsideSelectionArea( vec3 );"
"bool passOcclusionTest( vec3 );"
"float squareDistanceToCursor();"
"float squareDistanceToBrush();"
"vec2 toBrushCenter();"
"void main()"
"{"
" float sgn = sign( u_SelectionStateUpdateValue - 0.5 );"
" vec3 clipCoord = getClippingCoordinates( vertex );"
" if( isInsideViewport(clipCoord) && isInsideSelectionArea(clipCoord) && passOcclusionTest(vertex) )"
" selectionState = vec4( 1.1968268412*exp(-4.5*squareDistanceToCursor()) );"
" selectionState = vec4( toBrushCenter(), sgn*squareDistanceToBrush(), 1.0 );"
" else"
" selectionState = vec4( 0.0 );"
" selectionState = vec4( 0.0, 0.0, sgn, 1.0 );"
"}";
void SelectionManagerMeshTexels::initTexture()
......@@ -98,8 +102,9 @@ void SelectionManagerMeshTexels::initTexture()
if( m_Texture.IsInstantiated() )
return;
GLenum formats[] = { GL_R8, GL_RGB8, GL_NONE };
m_Texture.Create( formats, m_ImageWidth, m_ImageHeight );
GLenum formats[] = { GL_R8, GL_RGB8, GL_NONE,
GL_RGB32F, GL_NONE };
m_Texture.Create( isRealTimeSelectionEnabled()? formats+3 : formats, m_ImageWidth, m_ImageHeight );
m_Texture.SetFiltering( GL_NEAREST );
m_Texture.SetBaseAndMaxLevels( 0 );
m_Texture.SetWrapST( GL_CLAMP_TO_EDGE );
......@@ -115,6 +120,10 @@ void SelectionManagerMeshTexels::initTexture()
fbuffer.Unbind();
glClearColor( clearColor[0], clearColor[1], clearColor[2], clearColor[3] );
m_Buffer.Create( m_ImageWidth, m_ImageHeight );
m_Buffer.Attach( GL_COLOR_ATTACHMENT0, &m_Texture );
}
......@@ -143,7 +152,7 @@ void SelectionManagerMeshTexels::onRecompilingSelectionShader( SelectionTool *to
GPU::CreateShaderFromSources(
m_SelectionShader,
s_SelectionShaderVSH,
s_SelectionShaderFSH + tool->getSelectionShaderFunctions()
(isRealTimeSelectionEnabled()? s_RealTimeSelectionShaderFSH : s_SelectionShaderFSH) + tool->getSelectionShaderFunctions()
);
}
......@@ -156,9 +165,7 @@ void SelectionManagerMeshTexels::onUpdatingSelection( SelectionTool *tool )
GLfloat updateValue = tool->selectionMode()==SelectionTool::SELECTION_MODE_REMOVE? 0.0f : 1.0f;
m_SelectionShader.SetUniform( "u_SelectionStateUpdateValue", &updateValue );
GPU::FrameBuffer fbo( m_ImageWidth, m_ImageHeight );
fbo.Attach( GL_COLOR_ATTACHMENT0, &m_Texture );
fbo.Bind();
m_Buffer.Bind();
m_MeshVBO.SetShader( &m_SelectionShader );
m_MeshVBO.SetShaderAttribBinding( "vertexPosition" , m_PosAttribName );
......@@ -170,14 +177,19 @@ void SelectionManagerMeshTexels::onUpdatingSelection( SelectionTool *tool )
m_MeshVBO.DrawArrays( GL_TRIANGLES );
glFlush();
fbo.Unbind();
m_Buffer.Unbind();
// Trigger listeners, if any.
for( auto l : realTimeListeners() )
l->texelSelectionTriggered( m_Texture );
}
void SelectionManagerMeshTexels::onDisplay( GLViewer *viewer,
const QMatrix4x4 &localTransfo )
{
if( !m_Texture.IsInstantiated() )
if( !m_Texture.IsInstantiated() || isRealTimeSelectionEnabled() )
return;
// Save previous OpenGL state.
......
......@@ -25,6 +25,7 @@ class SelectionManagerMeshTexels : public TexelSelectionManager
int m_ImageWidth;
int m_ImageHeight;
GPU::Texture2D m_Texture;
GPU::FrameBuffer m_Buffer;
void initTexture();
......
......@@ -217,6 +217,11 @@ void SelectionManagerMeshVertices::onUpdatingSelection( SelectionTool *tool )
glClearColor( clearColor[0], clearColor[1], clearColor[2], clearColor[3] );
// Trigger listeners, if any.
for( auto l : realTimeListeners() )
l->vertexSelectionTriggered( m_SelectionTexture );
#if 0
// Dump the result of the packing rendering pass.
......
......@@ -21,7 +21,8 @@ std::string SelectionTool::getSelectionShaderFunctions()
"uniform mat4 u_CameraFullTransform;"
"uniform vec3 u_CameraLocation;"
"float _squareDistanceToCursor = 0.0;"
"vec2 _toBrushCenter = vec2(0.0);"
"float _squareDistanceToBrush = 0.0;"
"vec3 getClippingCoordinates( vec3 objCoordVertex )"
"{"
......@@ -50,9 +51,14 @@ std::string SelectionTool::getSelectionShaderFunctions()
" return textureProj( u_DepthBuffer, projVert ) > 0.5;"
"}"
"float squareDistanceToCursor()"
"float squareDistanceToBrush()"
"{"
" return _squareDistanceToCursor;"
" return _squareDistanceToBrush;"
"}"
"vec2 toBrushCenter()"
"{"
" return _toBrushCenter;"
"}";
}
......
......@@ -112,6 +112,15 @@ public:
};
class RealTimeSelectionListener
{
public:
virtual void texelSelectionTriggered ( GPU::Texture2D &selectionTexture ) {}
virtual void vertexSelectionTriggered( GPU::Texture2D &selectionTexture ) {}
virtual void faceSelectionTriggered ( GPU::Texture2D &selectionTexture ) {}
};
#endif // SELECTIONTOOL_H
......@@ -59,6 +59,7 @@ void SelectionToolDisk::updateCircleVertices()
std::string SelectionToolDisk::getSelectionShaderFunctions()
{
return SelectionTool::getSelectionShaderFunctions() +
"uniform vec2 u_DiskCenter;"
"uniform vec2 u_DiskAxis;"
"uniform float u_DiskAxisLen;"
......@@ -68,9 +69,9 @@ std::string SelectionToolDisk::getSelectionShaderFunctions()
"{"
" vec2 toCenter = clipCoordVertex.xy*u_DiskRadiusInv - u_DiskCenter;"
" float distAlongAxis = dot( toCenter, u_DiskAxis );"
" vec2 toSegmentClosestPoint = toCenter - max( min(distAlongAxis,u_DiskAxisLen), 0.0 )*u_DiskAxis;"
" _squareDistanceToCursor = dot( toSegmentClosestPoint, toSegmentClosestPoint );"
" return _squareDistanceToCursor <= 1.0;"
" _toBrushCenter = max( min(distAlongAxis,u_DiskAxisLen), 0.0 )*u_DiskAxis - toCenter;"
" _squareDistanceToBrush = dot( _toBrushCenter, _toBrushCenter );"
" return _squareDistanceToBrush <= 1.0;"
"}";
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment