From b3d48995469563ab25d48cf0a9e54d5238e1d975 Mon Sep 17 00:00:00 2001 From: ccolin Date: Sun, 3 Oct 2021 11:43:55 +0200 Subject: [PATCH] use an element buffer for rendering --- src/main.cpp | 6 ++-- src/mesh_processor.cpp | 19 ---------- src/mesh_processor.h | 6 +--- src/mesh_view.cpp | 81 ++++++++++++++++++++++++++++-------------- src/mesh_view.h | 12 ++++--- src/mesh_viewer.cpp | 8 ++--- src/mesh_viewer.h | 6 ++-- src/my_mesh.h | 6 ++-- src/util.h | 30 ++++++++++++---- 9 files changed, 99 insertions(+), 75 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index af3bb07..d9eddf4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,7 +21,7 @@ int main(int argc, char *argv[]) { QObject::connect(mesh_viewer, &MeshViewer::initialized, [&]() { 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, [&](const QString &path) { if (mesh_processor) { - mesh_viewer->removeMesh(mesh_processor->mesh); + mesh_viewer->removeMesh(*mesh_processor); delete mesh_processor; } mesh_processor = new MeshProcessor(path); - mesh_viewer->addMesh(mesh_processor->mesh); + mesh_viewer->addMesh(*mesh_processor); }); main_window.show(); return app.exec(); diff --git a/src/mesh_processor.cpp b/src/mesh_processor.cpp index 670b377..9e58898 100644 --- a/src/mesh_processor.cpp +++ b/src/mesh_processor.cpp @@ -28,30 +28,11 @@ MeshProcessor::MeshProcessor(const QString &path) { qWarning() << "Failed to read" << path; return; } - for (const VertexHandle &vh : mesh.vertices()) { - mesh.set_color(vh, MyMesh::Color(0, 0, 0)); - } holes = findHoles(mesh); - highlightHoles(); 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) { mesh.request_vertex_status(); mesh.request_edge_status(); diff --git a/src/mesh_processor.h b/src/mesh_processor.h index 14106d4..0e31e69 100644 --- a/src/mesh_processor.h +++ b/src/mesh_processor.h @@ -10,17 +10,13 @@ class MeshProcessor : public QObject { Q_OBJECT - std::vector holes; - - // friend class MeshProcessorPainter; - public: MyMesh mesh; + std::vector holes; MeshProcessor(const QString &path); public slots: - void highlightHoles(); void fillHoles(); }; diff --git a/src/mesh_view.cpp b/src/mesh_view.cpp index e6d96a5..eef51d2 100644 --- a/src/mesh_view.cpp +++ b/src/mesh_view.cpp @@ -1,32 +1,49 @@ #include "mesh_view.h" +#include "util.h" #include #include -MeshView::MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program) - : buffer(QOpenGLBuffer::VertexBuffer), - nverts(mesh.n_faces() * 3), - mesh(mesh) { - QVector verts(nverts * 6); +MeshView::MeshView(const MeshProcessor &mesh_processor, QOpenGLShaderProgram &program) + :vertex_buffer(QOpenGLBuffer::VertexBuffer), + index_buffer(QOpenGLBuffer::IndexBuffer), + n_faces(mesh_processor.mesh.n_faces()), + n_vertices(mesh_processor.mesh.n_vertices()), + mesh_processor(mesh_processor) { + const MyMesh &mesh = mesh_processor.mesh; + QVector vertices(n_vertices * 6); size_t i = 0; - for (const FaceHandle face : mesh.faces()) { - for (const VertexHandle vec : mesh.fv_range(face)) { - verts[6*i + 0] = mesh.point(vec)[0]; - verts[6*i + 1] = mesh.point(vec)[1]; - verts[6*i + 2] = mesh.point(vec)[2]; - verts[6*i + 3] = mesh.color.red(); - verts[6*i + 4] = mesh.color.green(); - verts[6*i + 5] = mesh.color.blue(); - i++; - } - } + for (const VertexHandle it : mesh.vertices()) { + vertices[6*i + 0] = mesh.point(it)[0]; + vertices[6*i + 1] = mesh.point(it)[1]; + vertices[6*i + 2] = mesh.point(it)[2]; + vertices[6*i + 3] = mesh.color.red(); + vertices[6*i + 4] = mesh.color.green(); + vertices[6*i + 5] = mesh.color.blue(); + i++; + } + QVector 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(); {QOpenGLVertexArrayObject::Binder binder(&vao); - buffer.create(); - buffer.bind(); - buffer.setUsagePattern(QOpenGLBuffer::StreamDraw); - buffer.allocate(verts.constData(), nverts * 6 * sizeof (GLfloat)); + vertex_buffer.create(); + vertex_buffer.bind(); + vertex_buffer.setUsagePattern(QOpenGLBuffer::StreamDraw); + 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.enableAttributeArray("pos"); 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() { + vertex_buffer.destroy(); + index_buffer.destroy(); vao.destroy(); - buffer.destroy(); } void MeshView::paint(QOpenGLShaderProgram &program) { + const MyMesh &mesh = mesh_processor.mesh; QOpenGLContext *ctx = QOpenGLContext::currentContext(); QOpenGLExtraFunctions *glf = ctx->extraFunctions(); @@ -56,15 +75,25 @@ void MeshView::paint(QOpenGLShaderProgram &program) { /* Mesh */ glf->glEnable(GL_POLYGON_OFFSET_FILL); glf->glPolygonOffset(1.0, 2); - glf->glDrawArrays(GL_TRIANGLES, 0, nverts); - glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glf->glDrawElements(GL_TRIANGLES, n_faces * 3, GL_UNSIGNED_INT, 0); glf->glDisable(GL_POLYGON_OFFSET_FILL); /* Wireframe */ - program.setUniformValue("wireframe", 1); - glf->glDrawArrays(GL_TRIANGLES, 0, nverts); - glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glf21->glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 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("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)); } } diff --git a/src/mesh_view.h b/src/mesh_view.h index 47000c1..f092874 100644 --- a/src/mesh_view.h +++ b/src/mesh_view.h @@ -1,7 +1,7 @@ #ifndef MESH_VIEW_H #define MESH_VIEW_H -#include "my_mesh.h" +#include "mesh_processor.h" #include #include #include @@ -10,13 +10,15 @@ class MeshView { QOpenGLVertexArrayObject vao; - QOpenGLBuffer buffer; - size_t nverts; + QOpenGLBuffer vertex_buffer; + QOpenGLBuffer index_buffer; + unsigned n_faces; + unsigned n_vertices; public: - const MyMesh &mesh; + const MeshProcessor &mesh_processor; - MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program); + MeshView(const MeshProcessor &mesh_processor, QOpenGLShaderProgram &program); ~MeshView(); void paint(QOpenGLShaderProgram &program); }; diff --git a/src/mesh_viewer.cpp b/src/mesh_viewer.cpp index d8ee361..f875a59 100644 --- a/src/mesh_viewer.cpp +++ b/src/mesh_viewer.cpp @@ -83,19 +83,19 @@ void MeshViewer::paintGL() { } -void MeshViewer::addMesh(const MyMesh &mesh) { +void MeshViewer::addMesh(const MeshProcessor &mesh_processor) { Q_ASSERT(isValid()); makeCurrent(); - meshes.emplace_back(mesh, program); + meshes.emplace_back(mesh_processor, program); doneCurrent(); update(); } -void MeshViewer::removeMesh(const MyMesh &mesh) { +void MeshViewer::removeMesh(const MeshProcessor &mesh_processor) { makeCurrent(); meshes.remove_if([&](const MeshView &mv) { - return &mv.mesh == &mesh; + return &mv.mesh_processor == &mesh_processor; }); doneCurrent(); update(); diff --git a/src/mesh_viewer.h b/src/mesh_viewer.h index 3c7a94f..4aeef11 100644 --- a/src/mesh_viewer.h +++ b/src/mesh_viewer.h @@ -2,7 +2,7 @@ #define MESH_VIEWER_H #define GL_GLEXT_PROTOTYPES -#include "my_mesh.h" +#include "mesh_processor.h" #include "mesh_view.h" #include #include @@ -39,8 +39,8 @@ public: void paintGL() override; public slots: - void addMesh(const MyMesh &mesh); - void removeMesh(const MyMesh &mesh); + void addMesh(const MeshProcessor &mesh); + void removeMesh(const MeshProcessor &mesh); protected: virtual void mousePressEvent(QMouseEvent *e); diff --git a/src/my_mesh.h b/src/my_mesh.h index 3b196c3..c6931d2 100644 --- a/src/my_mesh.h +++ b/src/my_mesh.h @@ -2,21 +2,21 @@ #define MY_MESH_H #include -#include +#include #include #include #include struct MyTraits : public OpenMesh::DefaultTraits { - VertexAttributes(OpenMesh::Attributes::Normal | OpenMesh::Attributes::Color); + VertexAttributes(OpenMesh::Attributes::Normal); HalfedgeAttributes(OpenMesh::Attributes::PrevHalfedge); FaceAttributes(OpenMesh::Attributes::Normal); EdgeAttributes(OpenMesh::Attributes::Color); typedef OpenMesh::Vec3f Color; }; -class MyMesh : public OpenMesh::PolyMesh_ArrayKernelT { +class MyMesh : public OpenMesh::TriMesh_ArrayKernelT { public: QMatrix4x4 transform; QColor color; diff --git a/src/util.h b/src/util.h index d346abb..7cccf89 100644 --- a/src/util.h +++ b/src/util.h @@ -1,23 +1,39 @@ #ifndef UTIL_H #define UTIL_H -#include "my_mesh.h" - +template class HalfedgeLoopRange { - MyMesh &mesh; - const HalfedgeHandle &start; + Mesh &mesh; + const typename Mesh::HalfedgeHandle &start; public: - HalfedgeLoopRange(MyMesh &mesh, const HalfedgeHandle &start) + HalfedgeLoopRange(Mesh &mesh, const typename Mesh::HalfedgeHandle &start) :mesh(mesh), start(start) {} - MyMesh::HalfedgeLoopIter begin() { + typename Mesh::HalfedgeLoopIter begin() { return mesh.hl_begin(start); } - MyMesh::HalfedgeLoopIter end() { + typename Mesh::HalfedgeLoopIter end() { return mesh.hl_end(start); } }; +template +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 \ No newline at end of file