Commit c6be1715 authored by Simon Boyé's avatar Simon Boyé

Vitelotte: Worked on Editor example.

parent 9f3d1183
......@@ -19,10 +19,10 @@ const vec3 basis[3] = vec3[3](
void main()
{
for(int i=0; i<3; ++i)
{
gl_Position = gl_in[i].gl_Position;
gl_PrimitiveID = gl_PrimitiveIDIn;
for(int i=0; i<3; ++i)
{
gl_Position = gl_in[i].gl_Position;
gl_PrimitiveID = gl_PrimitiveIDIn;
linearBasis = basis[i];
position = position_obj[i];//gl_in[i].gl_Position.xy;
for(int j=0; j<3; ++j)
......
......@@ -205,7 +205,6 @@ VGMeshRendererWireframeShader::
}
template < class _Mesh >
inline void VGMeshRenderer<_Mesh>::initialize(Mesh* _mesh)
{
......@@ -214,6 +213,7 @@ inline void VGMeshRenderer<_Mesh>::initialize(Mesh* _mesh)
setMesh(_mesh);
}
template < class _Mesh >
inline void VGMeshRenderer<_Mesh>::updateMesh()
{
......@@ -309,6 +309,7 @@ inline void VGMeshRenderer<_Mesh>::updateMesh()
PATATE_ASSERT_NO_GL_ERROR();
}
template < class _Mesh >
inline void VGMeshRenderer<_Mesh>::renderTriangles(
VGMeshRendererShader& shaders, bool _singular)
......@@ -356,6 +357,7 @@ inline void VGMeshRenderer<_Mesh>::renderTriangles(
PATATE_ASSERT_NO_GL_ERROR();
}
template < class _Mesh >
inline typename VGMeshRenderer<_Mesh>::NodeValue
VGMeshRenderer<_Mesh>::nodeValue(Node node) const
......@@ -365,6 +367,7 @@ VGMeshRenderer<_Mesh>::nodeValue(Node node) const
return NodeValue(0, 0, 0, 1); // FIXME: Make this class work for Chan != 4
}
template < class _Mesh >
inline void VGMeshRenderer<_Mesh>::render(VGMeshRendererShader &shaders)
{
......@@ -374,6 +377,7 @@ inline void VGMeshRenderer<_Mesh>::render(VGMeshRendererShader &shaders)
}
}
template < class _Mesh >
template < typename T >
void VGMeshRenderer<_Mesh>::createAndUploadBuffer(
......
......@@ -8,6 +8,8 @@ from datetime import datetime
argparser = ArgumentParser(description='Convert a set of shaders into cpp source code')
argparser.add_argument('-e', '--extern', default=False, action='store_true',
help="Declare variables with external linkage.")
argparser.add_argument('-o', '--output', default='-',
help="Write the output to the file output, or stdout if omitted or output is '-'.")
argparser.add_argument('-n', '--namespace', default='',
......@@ -26,14 +28,19 @@ print(file=out)
if namespaces:
for ns in namespaces:
print("namespace {}".format(ns), file=out)
print("{", file=out)
if ns != '':
print("namespace {}".format(ns), file=out)
print("{", file=out)
print(file=out)
for shader_file in options.shaders:
with open(shader_file) as shader:
var_name = sub(r'\W', '_', basename(shader_file), flags=ASCII)
print('static const char* {} ='.format(var_name), file=out)
if options.extern:
print('extern const char* {};'.format(var_name), file=out)
print('const char* {} ='.format(var_name), file=out)
else:
print('static const char* {} ='.format(var_name), file=out)
for line in shader:
print('\t"{}\\n"'.format(line.rstrip()), file=out)
print('\t"";', file=out)
......@@ -41,7 +48,8 @@ for shader_file in options.shaders:
if namespaces:
for ns in namespaces:
print("}", file=out)
if ns != '':
print("}", file=out)
print(file=out)
......
......@@ -25,14 +25,36 @@ include_directories(
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(vitelotte_editor_SHADERS
shaders/vert_points.glsl
shaders/geom_points.glsl
shaders/frag_points.glsl
shaders/vert_lines.glsl
shaders/geom_lines.glsl
shaders/frag_lines.glsl
)
set(vitelotte_editor_SRCS
document.cpp
orthographicCamera.cpp
shaders.cpp
glPointRenderer.cpp
glLineRenderer.cpp
valueEditor.cpp
editor.cpp
main.cpp
)
add_custom_command(
OUTPUT ${PROJECT_SOURCE_DIR}/shaders.cpp
COMMAND python3 ${PROJECT_SOURCE_DIR}/../../../bin/shader2cpp -o shaders.cpp -e ${vitelotte_editor_SHADERS}
DEPENDS ${vitelotte_editor_SHADERS}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
VERBATIM
)
#set_source_files_properties(glLineRenderer.cpp
# OBJECT_DEPENDS ${PROJECT_SOURCE_DIR}/shaders.hpp)
add_executable(editor
${vitelotte_editor_SRCS}
)
......
......@@ -5,6 +5,75 @@
#include "document.h"
MeshSelection::MeshSelection()
: m_type(SelectionNone),
m_index(-1)
{}
MeshSelection::MeshSelection(Mesh::Vertex v)
: m_type(v.isValid()? SelectionVertex: SelectionNone),
m_index(v.idx())
{}
MeshSelection::MeshSelection(Mesh::Edge e)
: m_type(e.isValid()? SelectionEdge: SelectionNone),
m_index(e.idx())
{}
bool MeshSelection::operator==(const MeshSelection& other) const
{
return m_type == other.type() && m_index == other.m_index;
}
bool MeshSelection::operator!=(const MeshSelection& other) const
{
return !(*this == other);
}
MeshSelection::SelectionType MeshSelection::type() const
{
return m_type;
}
bool MeshSelection::isNone() const
{
return type() == SelectionNone;
}
bool MeshSelection::isVertex() const
{
return type() == SelectionVertex;
}
bool MeshSelection::isEdge() const
{
return type() == SelectionEdge;
}
Mesh::Vertex MeshSelection::vertex() const
{
assert(isVertex());
return Mesh::Vertex(m_index);
}
Mesh::Edge MeshSelection::edge() const
{
assert(isEdge());
return Mesh::Edge(m_index);
}
Document::Document(QObject *parent)
: QObject(parent), m_fvSolver(&m_solvedMesh), m_undoStack(new QUndoStack(this))
{
......@@ -29,23 +98,60 @@ void Document::updateBoundingBox()
}
Document::Mesh::Edge Document::selectedEdge() const
MeshSelection Document::selection() const
{
return m_selectedEdge;
return m_selection;
}
void Document::setSelectedEdge(Mesh::Edge e)
void Document::setSelection(MeshSelection selection)
{
assert(!e.isValid() || m_mesh.isValid(e));
if(e != m_selectedEdge)
assert(isSelectionValid(selection));
if(selection != m_selection)
{
m_selectedEdge = e;
emit selectedEdgeChanged();
m_selection = selection;
emit selectionChanged();
}
}
bool Document::isSelectionValid(MeshSelection selection)
{
return selection.isNone() ||
(selection.isVertex() && mesh().isValid(selection.vertex())) ||
(selection.isEdge() && mesh().isValid(selection.edge()));
}
float Document::vertexSqrDist(Mesh::Vertex v, const Eigen::Vector2f& p) const
{
Eigen::Vector2f vp = m_mesh.position(v);
return (vp - p).squaredNorm();
}
Mesh::Vertex Document::closestVertex(const Eigen::Vector2f& p,
float* sqrDist) const
{
Mesh::VertexIterator vit = m_mesh.verticesBegin();
Mesh::Vertex closest = *vit;
float dist = vertexSqrDist(*vit, p);
for(++vit; vit != m_mesh.verticesEnd(); ++vit)
{
float vdist = vertexSqrDist(*vit, p);
if(vdist < dist)
{
dist = vdist;
closest = *vit;
}
}
if(sqrDist) *sqrDist = dist;
return closest;
}
float Document::edgeSqrDist(Mesh::Edge e, const Eigen::Vector2f& p) const
{
Eigen::Vector2f p0 = m_mesh.position(m_mesh.vertex(e, 0));
......@@ -66,7 +172,8 @@ float Document::edgeSqrDist(Mesh::Edge e, const Eigen::Vector2f& p) const
}
Document::Mesh::Edge Document::closestEdge(const Eigen::Vector2f& p) const
Document::Mesh::Edge Document::closestEdge(const Eigen::Vector2f& p,
float *sqrDist) const
{
Mesh::EdgeIterator eit = m_mesh.edgesBegin();
Mesh::Edge closest = *eit;
......@@ -82,6 +189,7 @@ Document::Mesh::Edge Document::closestEdge(const Eigen::Vector2f& p) const
}
}
if(sqrDist) *sqrDist = dist;
return closest;
}
......@@ -236,7 +344,7 @@ void Document::loadMesh(const std::string& filename)
m_mesh.setAttributes(Mesh::FV);
updateBoundingBox();
setSelectedEdge(Mesh::Edge());
setSelection(MeshSelection());
solve();
}
......
......@@ -11,12 +11,47 @@
#include "Patate/vitelotte.h"
typedef Vitelotte::VGMesh<float> Mesh;
class MeshSelection
{
public:
enum SelectionType
{
SelectionNone,
SelectionVertex,
SelectionEdge
};
public:
MeshSelection();
MeshSelection(Mesh::Vertex v);
MeshSelection(Mesh::Edge e);
bool operator==(const MeshSelection& other) const;
bool operator!=(const MeshSelection& other) const;
SelectionType type() const;
bool isNone() const;
bool isVertex() const;
bool isEdge() const;
Mesh::Vertex vertex() const;
Mesh::Edge edge() const;
private:
SelectionType m_type;
int m_index;
};
class Document : public QObject
{
Q_OBJECT
public:
typedef Vitelotte::VGMesh<float> Mesh;
typedef ::Mesh Mesh;
typedef Vitelotte::FVElementBuilder<Mesh> FVElement;
typedef Vitelotte::FemSolver<Mesh, FVElement> FVSolver;
typedef Eigen::AlignedBox2f BoundingBox;
......@@ -41,11 +76,15 @@ public:
const BoundingBox& boundingBox() const;
void updateBoundingBox();
Mesh::Edge selectedEdge() const;
void setSelectedEdge(Mesh::Edge e);
MeshSelection selection() const;
void setSelection(MeshSelection selection);
bool isSelectionValid(MeshSelection selection);
float vertexSqrDist(Mesh::Vertex v, const Eigen::Vector2f& p) const;
Mesh::Vertex closestVertex(const Eigen::Vector2f& p, float* sqrDist=0) const;
float edgeSqrDist(Mesh::Edge e, const Eigen::Vector2f& p) const;
Mesh::Edge closestEdge(const Eigen::Vector2f& p) const;
Mesh::Edge closestEdge(const Eigen::Vector2f& p, float* sqrDist=0) const;
void solve();
......@@ -77,7 +116,7 @@ public slots:
signals:
void selectedEdgeChanged();
void selectionChanged();
void meshUpdated();
......@@ -86,7 +125,7 @@ private:
Mesh m_solvedMesh;
BoundingBox m_bb;
Mesh::Edge m_selectedEdge;
MeshSelection m_selection;
FVSolver m_fvSolver;
......
......@@ -79,6 +79,8 @@ void Editor::setDocument(Document* document)
updateBuffers();
connect(m_document, SIGNAL(meshUpdated()), this, SLOT(updateBuffers()));
connect(m_document, SIGNAL(selectionChanged()),
this, SLOT(updateSelection()));
}
}
......@@ -91,6 +93,52 @@ void Editor::updateBuffers()
}
void Editor::updateSelection()
{
assert(m_document);
MeshSelection sel = m_document->selection();
m_pointRenderer.clear();
m_lineRenderer.clear();
if(sel.isVertex())
{
Mesh::Vertex v = sel.vertex();
Eigen::Vector3f p; p << mesh().position(v), 0;
float innerRadius = 3;
float outerRadius = innerRadius + 1.5;
Eigen::Vector4f innerColor(1., 1., 1., 1.);
Eigen::Vector4f outerColor(0., 0., 0., 1.);
m_pointRenderer.addPoint(p, outerRadius, outerColor);
m_pointRenderer.addPoint(p, innerRadius, innerColor);
}
else if(sel.isEdge())
{
Mesh::Edge e = sel.edge();
Eigen::Vector3f p0; p0 << mesh().position(mesh().vertex(e, 0)), 0;
Eigen::Vector3f p1; p1 << mesh().position(mesh().vertex(e, 1)), 0;
float innerWidth = 1.5;
float outerWidth = 4.5;
Eigen::Vector4f innerColor(1., 1., 1., 1.);
Eigen::Vector4f outerColor(0., 0., 0., 1.);
m_lineRenderer.addPoint(p0, outerWidth, outerColor);
m_lineRenderer.addPoint(p1, outerWidth, outerColor);
m_lineRenderer.endLine();
m_lineRenderer.addPoint(p0, innerWidth, innerColor);
m_lineRenderer.addPoint(p1, innerWidth, innerColor);
m_lineRenderer.endLine();
}
m_pointRenderer.upload();
m_lineRenderer.upload();
updateGL();
}
void Editor::initializeGL()
{
std::cout << "OpenGL Vendor: " << glGetString(GL_VENDOR) << "\n";
......@@ -157,6 +205,10 @@ void Editor::paintGL()
m_wireframeShader.setWireframeColor(Eigen::Vector4f(.5, .5, .5, 1.));
m_wireframeShader.setZoom(width() / m_camera.getViewBox().sizes()(0));
m_renderer.render(m_wireframeShader);
Eigen::Vector2f viewportSize(width(), height());
m_lineRenderer.render(m_wireframeShader.viewMatrix(), viewportSize);
m_pointRenderer.render(m_wireframeShader.viewMatrix(), viewportSize);
}
}
......@@ -168,30 +220,21 @@ void Editor::mousePressEvent(QMouseEvent* event)
Eigen::Vector2f norm = screenToNormalized(event->localPos());
Eigen::Vector2f cam = m_camera.normalizedToCamera(norm);
Mesh::Edge sel = m_document->closestEdge(cam);
m_document->setSelectedEdge(sel);
// Mesh& m = m_document->mesh();
// Mesh::Halfedge h0 = m.halfedge(sel, 0);
// Mesh::Halfedge h1 = m.halfedge(sel, 1);
// Mesh::Node* nodes[6] =
// {
// &m.vertexValueNode(h0), &m.vertexFromValueNode(h0), &m.edgeValueNode(h0),
// &m.vertexValueNode(h1), &m.vertexFromValueNode(h1), &m.edgeValueNode(h1)
// };
// for(int i=0; i<6; ++i)
// {
// if(!nodes[i]->isValid())
// *nodes[i] = m.addNode();
// m.nodeValue(*nodes[i]) = (Eigen::Vector4f() <<
// Eigen::Vector3f::Random() / 2 + Eigen::Vector3f::Constant(.5),
// 1).finished();
// }
// m_document->solve();
// updateBuffers();
// update();
float selDist = 8 * m_camera.getViewBox().sizes()(0) / width();
float vSqrDist;
Mesh::Vertex vSel = m_document->closestVertex(cam, &vSqrDist);
float eSqrDist;
Mesh::Edge eSel = m_document->closestEdge(cam, &eSqrDist);
if(vSqrDist < selDist*selDist)
m_document->setSelection(MeshSelection(vSel));
else if(eSqrDist < selDist*selDist)
m_document->setSelection(MeshSelection(eSel));
else
m_document->setSelection(MeshSelection());
}
if(!m_drag && event->button() == Qt::MidButton)
{
......
......@@ -15,6 +15,8 @@
#include "Patate/vitelotte_gl.h"
#include "orthographicCamera.h"
#include "glPointRenderer.h"
#include "glLineRenderer.h"
class QMouseEvent;
......@@ -50,6 +52,7 @@ public slots:
void centerView();
void setDocument(Document* document);
void updateBuffers();
void updateSelection();
public:
virtual void initializeGL();
......@@ -79,6 +82,10 @@ private:
Renderer m_renderer;
Vitelotte::VGMeshRendererDefaultShader m_defaultShader;
Vitelotte::VGMeshRendererWireframeShader m_wireframeShader;
GLPointRenderer m_pointRenderer;
GLLineRenderer m_lineRenderer;
};
......
#include <GL/glew.h>
#include "glLineRenderer.h"
extern const char* vert_lines_glsl;
extern const char* geom_lines_glsl;
extern const char* frag_lines_glsl;
GLLineRenderer::GLLineRenderer()
: m_defaultWidth(1), m_defaultColor(0, 0, 0, 1),
m_startNewLine(true), m_vao(0), m_buffer(0)
{
}
float GLLineRenderer::defaultWidth() const
{
return m_defaultWidth;
}
void GLLineRenderer::setDefaultWidth(float defaultWidth)
{
m_defaultWidth = defaultWidth;
}
const Eigen::Vector4f& GLLineRenderer::defaultColor() const
{
return m_defaultColor;
}
void GLLineRenderer::setDefaultColor(const Eigen::Vector4f& defaultColor)
{
m_defaultColor = defaultColor;
}
void GLLineRenderer::clear()
{
m_startNewLine = true;
m_points.clear();
m_firsts.clear();
m_sizes.clear();
}
void GLLineRenderer::addPoint(const Eigen::Vector3f& pos, float width,
const Eigen::Vector4f& color)
{
if(m_startNewLine)
{
m_startNewLine = false;
m_firsts.push_back(m_points.size());
m_sizes.push_back(0);
}
Point point;
point.pos = pos;
point.width = width >= 0? width: m_defaultWidth;
point.color = color != Eigen::Vector4f::Constant(-1)? color: m_defaultColor;
m_points.push_back(point);
++m_sizes.back();
}
void GLLineRenderer::endLine()
{
m_startNewLine = true;
}
void GLLineRenderer::upload()
{
PATATE_ASSERT_NO_GL_ERROR();
if(m_shader.status() == Patate::Shader::Uninitialized)
{
m_shader.create();
bool bRes = true;
bRes &= m_shader.addShader(GL_VERTEX_SHADER,
vert_lines_glsl);
bRes &= m_shader.addShader(GL_GEOMETRY_SHADER,
geom_lines_glsl);
bRes &= m_shader.addShader(GL_FRAGMENT_SHADER,
frag_lines_glsl);
bRes &= m_shader.finalize();
assert(bRes);
m_positionLoc = glGetAttribLocation(m_shader.getShaderId(), "vx_position");
m_colorLoc = glGetAttribLocation(m_shader.getShaderId(), "vx_color");
m_viewMatrixLoc = m_shader.getUniformLocation("viewMatrix");
m_viewportSizeLoc = m_shader.getUniformLocation("viewportSize");
}
if(!m_vao)
glGenVertexArrays(1, &m_vao);
if(!m_buffer)
glGenBuffers(1, &m_buffer);
glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
glBufferData(GL_ARRAY_BUFFER, m_points.size() * sizeof(Point),
&m_points[0], GL_DYNAMIC_DRAW);
PATATE_ASSERT_NO_GL_ERROR();
}
void GLLineRenderer::render(const Eigen::Matrix4f& viewMatrix,
const Eigen::Vector2f& viewportSize)
{
PATATE_ASSERT_NO_GL_ERROR();
if(m_sizes.empty())
return;
m_shader.use();
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_buffer);
if(m_positionLoc >= 0)
{
glEnableVertexAttribArray(m_positionLoc);
glVertexAttribPointer(m_positionLoc, 4, GL_FLOAT, false,
sizeof(Point), 0);
}
if(m_colorLoc >= 0)
{
glEnableVertexAttribArray(m_colorLoc);
glVertexAttribPointer(m_colorLoc, 4, GL_FLOAT, false,
sizeof(Point), (void*)(4 * sizeof(float)));
}
if(m_viewMatrixLoc >= 0)
glUniformMatrix4fv(m_viewMatrixLoc, 1, false, viewMatrix.data());
if(m_viewportSizeLoc >= 0)
glUniform2fv(m_viewportSizeLoc, 1, viewportSize.data());
glMultiDrawArrays(GL_LINE_STRIP, &m_firsts[0], &m_sizes[0], m_sizes.size());
if(m_positionLoc >= 0)
glDisableVertexAttribArray(m_positionLoc);
if(m_colorLoc >= 0)
glDisableVertexAttribArray(m_colorLoc);
PATATE_ASSERT_NO_GL_ERROR();
}
#ifndef GL_LINE_RENDERER
#define GL_LINE_RENDERER
#include <vector>
#include <Eigen/Dense>
#include "Patate/common/gl_utils/shader.h"
class GLLineRenderer
{
public:
struct Point
{
Eigen::Vector3f pos;
float width;
Eigen::Vector4f color;
};
public:
GLLineRenderer();
float defaultWidth() const;
void setDefaultWidth(float defaultWidth);