use an element buffer for rendering

This commit is contained in:
ccolin 2021-10-03 11:43:55 +02:00
parent e56eed0a16
commit b3d4899546
9 changed files with 99 additions and 75 deletions

View File

@ -21,7 +21,7 @@ int main(int argc, char *argv[]) {
QObject::connect(mesh_viewer, &MeshViewer::initialized, QObject::connect(mesh_viewer, &MeshViewer::initialized,
[&]() { [&]() {
if (mesh_processor) { if (mesh_processor) {
mesh_viewer->addMesh(mesh_processor->mesh); mesh_viewer->addMesh(*mesh_processor);
} }
}); });
@ -34,11 +34,11 @@ int main(int argc, char *argv[]) {
QObject::connect(&main_window, &MainWindow::open, QObject::connect(&main_window, &MainWindow::open,
[&](const QString &path) { [&](const QString &path) {
if (mesh_processor) { if (mesh_processor) {
mesh_viewer->removeMesh(mesh_processor->mesh); mesh_viewer->removeMesh(*mesh_processor);
delete mesh_processor; delete mesh_processor;
} }
mesh_processor = new MeshProcessor(path); mesh_processor = new MeshProcessor(path);
mesh_viewer->addMesh(mesh_processor->mesh); mesh_viewer->addMesh(*mesh_processor);
}); });
main_window.show(); main_window.show();
return app.exec(); return app.exec();

View File

@ -28,30 +28,11 @@ MeshProcessor::MeshProcessor(const QString &path) {
qWarning() << "Failed to read" << path; qWarning() << "Failed to read" << path;
return; return;
} }
for (const VertexHandle &vh : mesh.vertices()) {
mesh.set_color(vh, MyMesh::Color(0, 0, 0));
}
holes = findHoles(mesh); holes = findHoles(mesh);
highlightHoles();
fillHoles(); fillHoles();
} }
static void setHoleBoundaryColor(MyMesh &mesh,
const HalfedgeHandle &hole,
MyMesh::Color color) {
for (HalfedgeHandle it : HalfedgeLoopRange(mesh, hole)) {
mesh.set_color(mesh.to_vertex_handle(it), color);
}
}
void MeshProcessor::highlightHoles() {
for (auto hole : holes) {
setHoleBoundaryColor(mesh, hole, {1, 0, 0});
}
}
void fillHoleDumb(MyMesh &mesh, HalfedgeHandle &hole) { void fillHoleDumb(MyMesh &mesh, HalfedgeHandle &hole) {
mesh.request_vertex_status(); mesh.request_vertex_status();
mesh.request_edge_status(); mesh.request_edge_status();

View File

@ -10,17 +10,13 @@
class MeshProcessor : public QObject { class MeshProcessor : public QObject {
Q_OBJECT Q_OBJECT
std::vector<HalfedgeHandle> holes;
// friend class MeshProcessorPainter;
public: public:
MyMesh mesh; MyMesh mesh;
std::vector<HalfedgeHandle> holes;
MeshProcessor(const QString &path); MeshProcessor(const QString &path);
public slots: public slots:
void highlightHoles();
void fillHoles(); void fillHoles();
}; };

View File

@ -1,32 +1,49 @@
#include "mesh_view.h" #include "mesh_view.h"
#include "util.h"
#include <QOpenGLContext> #include <QOpenGLContext>
#include <QOpenGLFunctions_2_1> #include <QOpenGLFunctions_2_1>
MeshView::MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program) MeshView::MeshView(const MeshProcessor &mesh_processor, QOpenGLShaderProgram &program)
: buffer(QOpenGLBuffer::VertexBuffer), :vertex_buffer(QOpenGLBuffer::VertexBuffer),
nverts(mesh.n_faces() * 3), index_buffer(QOpenGLBuffer::IndexBuffer),
mesh(mesh) { n_faces(mesh_processor.mesh.n_faces()),
QVector<GLfloat> verts(nverts * 6); n_vertices(mesh_processor.mesh.n_vertices()),
mesh_processor(mesh_processor) {
const MyMesh &mesh = mesh_processor.mesh;
QVector<GLfloat> vertices(n_vertices * 6);
size_t i = 0; size_t i = 0;
for (const FaceHandle face : mesh.faces()) { for (const VertexHandle it : mesh.vertices()) {
for (const VertexHandle vec : mesh.fv_range(face)) { vertices[6*i + 0] = mesh.point(it)[0];
verts[6*i + 0] = mesh.point(vec)[0]; vertices[6*i + 1] = mesh.point(it)[1];
verts[6*i + 1] = mesh.point(vec)[1]; vertices[6*i + 2] = mesh.point(it)[2];
verts[6*i + 2] = mesh.point(vec)[2]; vertices[6*i + 3] = mesh.color.red();
verts[6*i + 3] = mesh.color.red(); vertices[6*i + 4] = mesh.color.green();
verts[6*i + 4] = mesh.color.green(); vertices[6*i + 5] = mesh.color.blue();
verts[6*i + 5] = mesh.color.blue();
i++; i++;
} }
QVector<GLuint> indices(n_faces * 3);
i = 0;
for (const FaceHandle it : mesh.faces()) {
MyMesh::ConstFaceVertexIter it2 = mesh.cfv_begin(it);
indices[3 * i + 0] = it2->idx();
++it2;
indices[3 * i + 1] = it2->idx();
++it2;
indices[3 * i + 2] = it2->idx();
i++;
} }
vao.create(); vao.create();
{QOpenGLVertexArrayObject::Binder binder(&vao); {QOpenGLVertexArrayObject::Binder binder(&vao);
buffer.create(); vertex_buffer.create();
buffer.bind(); vertex_buffer.bind();
buffer.setUsagePattern(QOpenGLBuffer::StreamDraw); vertex_buffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
buffer.allocate(verts.constData(), nverts * 6 * sizeof (GLfloat)); vertex_buffer.allocate(vertices.constData(), n_vertices * 6 * sizeof (GLfloat));
index_buffer.create();
index_buffer.bind();
index_buffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
index_buffer.allocate(indices.constData(), n_faces * 3 * sizeof (GLuint));
program.setAttributeBuffer("pos", GL_FLOAT, 0, 3, 6 * sizeof (GLfloat)); program.setAttributeBuffer("pos", GL_FLOAT, 0, 3, 6 * sizeof (GLfloat));
program.enableAttributeArray("pos"); program.enableAttributeArray("pos");
program.setAttributeBuffer("col", GL_FLOAT, 3 * sizeof (GLfloat), 3, 6 * sizeof (GLfloat)); program.setAttributeBuffer("col", GL_FLOAT, 3 * sizeof (GLfloat), 3, 6 * sizeof (GLfloat));
@ -36,12 +53,14 @@ MeshView::MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program)
MeshView::~MeshView() { MeshView::~MeshView() {
vertex_buffer.destroy();
index_buffer.destroy();
vao.destroy(); vao.destroy();
buffer.destroy();
} }
void MeshView::paint(QOpenGLShaderProgram &program) { void MeshView::paint(QOpenGLShaderProgram &program) {
const MyMesh &mesh = mesh_processor.mesh;
QOpenGLContext *ctx = QOpenGLContext::currentContext(); QOpenGLContext *ctx = QOpenGLContext::currentContext();
QOpenGLExtraFunctions *glf = ctx->extraFunctions(); QOpenGLExtraFunctions *glf = ctx->extraFunctions();
@ -56,15 +75,25 @@ void MeshView::paint(QOpenGLShaderProgram &program) {
/* Mesh */ /* Mesh */
glf->glEnable(GL_POLYGON_OFFSET_FILL); glf->glEnable(GL_POLYGON_OFFSET_FILL);
glf->glPolygonOffset(1.0, 2); glf->glPolygonOffset(1.0, 2);
glf->glDrawArrays(GL_TRIANGLES, 0, nverts); glf->glDrawElements(GL_TRIANGLES, n_faces * 3, GL_UNSIGNED_INT, 0);
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glf->glDisable(GL_POLYGON_OFFSET_FILL); glf->glDisable(GL_POLYGON_OFFSET_FILL);
/* Wireframe */ /* Wireframe */
program.setUniformValue("wireframe", 1); glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glf->glDrawArrays(GL_TRIANGLES, 0, nverts);
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glf->glLineWidth(2); glf->glLineWidth(2);
program.setUniformValue("wireframe", 1);
glf->glDrawElements(GL_TRIANGLES, n_faces * 3, GL_UNSIGNED_INT, 0);
glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
program.setUniformValue("wireframe", 0); program.setUniformValue("wireframe", 0);
// program.setUniformValue("wf_col", QVector3D(1, 0, 1));
// for (HalfedgeHandle hole : mesh_processor.holes) {
// for (HalfedgeHandle it : ConstHalfedgeLoopRange(mesh, hole)) {
// int v0 = mesh.from_vertex_handle(it).idx();
// int v1 = mesh.to_vertex_handle(it).idx();
// glf->glDrawArrays(GL_LINES, std::min(v0, v1), std::max(v0, v1));
// }
// }
// program.setUniformValue("wf_col", QVector3D(0, 0, 0));
} }
} }

View File

@ -1,7 +1,7 @@
#ifndef MESH_VIEW_H #ifndef MESH_VIEW_H
#define MESH_VIEW_H #define MESH_VIEW_H
#include "my_mesh.h" #include "mesh_processor.h"
#include <QOpenGLExtraFunctions> #include <QOpenGLExtraFunctions>
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject> #include <QOpenGLVertexArrayObject>
@ -10,13 +10,15 @@
class MeshView { class MeshView {
QOpenGLVertexArrayObject vao; QOpenGLVertexArrayObject vao;
QOpenGLBuffer buffer; QOpenGLBuffer vertex_buffer;
size_t nverts; QOpenGLBuffer index_buffer;
unsigned n_faces;
unsigned n_vertices;
public: public:
const MyMesh &mesh; const MeshProcessor &mesh_processor;
MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program); MeshView(const MeshProcessor &mesh_processor, QOpenGLShaderProgram &program);
~MeshView(); ~MeshView();
void paint(QOpenGLShaderProgram &program); void paint(QOpenGLShaderProgram &program);
}; };

View File

@ -83,19 +83,19 @@ void MeshViewer::paintGL() {
} }
void MeshViewer::addMesh(const MyMesh &mesh) { void MeshViewer::addMesh(const MeshProcessor &mesh_processor) {
Q_ASSERT(isValid()); Q_ASSERT(isValid());
makeCurrent(); makeCurrent();
meshes.emplace_back(mesh, program); meshes.emplace_back(mesh_processor, program);
doneCurrent(); doneCurrent();
update(); update();
} }
void MeshViewer::removeMesh(const MyMesh &mesh) { void MeshViewer::removeMesh(const MeshProcessor &mesh_processor) {
makeCurrent(); makeCurrent();
meshes.remove_if([&](const MeshView &mv) { meshes.remove_if([&](const MeshView &mv) {
return &mv.mesh == &mesh; return &mv.mesh_processor == &mesh_processor;
}); });
doneCurrent(); doneCurrent();
update(); update();

View File

@ -2,7 +2,7 @@
#define MESH_VIEWER_H #define MESH_VIEWER_H
#define GL_GLEXT_PROTOTYPES #define GL_GLEXT_PROTOTYPES
#include "my_mesh.h" #include "mesh_processor.h"
#include "mesh_view.h" #include "mesh_view.h"
#include <list> #include <list>
#include <QMatrix4x4> #include <QMatrix4x4>
@ -39,8 +39,8 @@ public:
void paintGL() override; void paintGL() override;
public slots: public slots:
void addMesh(const MyMesh &mesh); void addMesh(const MeshProcessor &mesh);
void removeMesh(const MyMesh &mesh); void removeMesh(const MeshProcessor &mesh);
protected: protected:
virtual void mousePressEvent(QMouseEvent *e); virtual void mousePressEvent(QMouseEvent *e);

View File

@ -2,21 +2,21 @@
#define MY_MESH_H #define MY_MESH_H
#include <OpenMesh/Core/IO/MeshIO.hh> #include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh> #include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh>
#include <OpenMesh/Core/Geometry/VectorT.hh> #include <OpenMesh/Core/Geometry/VectorT.hh>
#include <QMatrix4x4> #include <QMatrix4x4>
#include <QColor> #include <QColor>
struct MyTraits : public OpenMesh::DefaultTraits { struct MyTraits : public OpenMesh::DefaultTraits {
VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Color); VertexAttributes(OpenMesh::Attributes::Normal);
HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge); HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge);
FaceAttributes(OpenMesh::Attributes::Normal); FaceAttributes(OpenMesh::Attributes::Normal);
EdgeAttributes(OpenMesh::Attributes::Color); EdgeAttributes(OpenMesh::Attributes::Color);
typedef OpenMesh::Vec3f Color; typedef OpenMesh::Vec3f Color;
}; };
class MyMesh : public OpenMesh::PolyMesh_ArrayKernelT<MyTraits> { class MyMesh : public OpenMesh::TriMesh_ArrayKernelT<MyTraits> {
public: public:
QMatrix4x4 transform; QMatrix4x4 transform;
QColor color; QColor color;

View File

@ -1,23 +1,39 @@
#ifndef UTIL_H #ifndef UTIL_H
#define UTIL_H #define UTIL_H
#include "my_mesh.h"
template <typename Mesh>
class HalfedgeLoopRange { class HalfedgeLoopRange {
MyMesh &mesh; Mesh &mesh;
const HalfedgeHandle &start; const typename Mesh::HalfedgeHandle &start;
public: public:
HalfedgeLoopRange(MyMesh &mesh, const HalfedgeHandle &start) HalfedgeLoopRange(Mesh &mesh, const typename Mesh::HalfedgeHandle &start)
:mesh(mesh), start(start) {} :mesh(mesh), start(start) {}
MyMesh::HalfedgeLoopIter begin() { typename Mesh::HalfedgeLoopIter begin() {
return mesh.hl_begin(start); return mesh.hl_begin(start);
} }
MyMesh::HalfedgeLoopIter end() { typename Mesh::HalfedgeLoopIter end() {
return mesh.hl_end(start); return mesh.hl_end(start);
} }
}; };
template <typename Mesh>
class ConstHalfedgeLoopRange {
Mesh &mesh;
const typename Mesh::HalfedgeHandle &start;
public:
ConstHalfedgeLoopRange(Mesh &mesh, const typename Mesh::HalfedgeHandle &start)
:mesh(mesh), start(start) {}
typename Mesh::HalfedgeLoopIter begin() {
return mesh.chl_begin(start);
}
typename Mesh::HalfedgeLoopIter end() {
return mesh.chl_end(start);
}
};
#endif #endif