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,
[&]() {
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();

View File

@ -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();

View File

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

View File

@ -1,32 +1,49 @@
#include "mesh_view.h"
#include "util.h"
#include <QOpenGLContext>
#include <QOpenGLFunctions_2_1>
MeshView::MeshView(const MyMesh &mesh, QOpenGLShaderProgram &program)
: buffer(QOpenGLBuffer::VertexBuffer),
nverts(mesh.n_faces() * 3),
mesh(mesh) {
QVector<GLfloat> 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<GLfloat> 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<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();
{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));
}
}

View File

@ -1,7 +1,7 @@
#ifndef MESH_VIEW_H
#define MESH_VIEW_H
#include "my_mesh.h"
#include "mesh_processor.h"
#include <QOpenGLExtraFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
@ -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);
};

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());
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();

View File

@ -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 <list>
#include <QMatrix4x4>
@ -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);

View File

@ -2,21 +2,21 @@
#define MY_MESH_H
#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 <QMatrix4x4>
#include <QColor>
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<MyTraits> {
class MyMesh : public OpenMesh::TriMesh_ArrayKernelT<MyTraits> {
public:
QMatrix4x4 transform;
QColor color;

View File

@ -1,23 +1,39 @@
#ifndef UTIL_H
#define UTIL_H
#include "my_mesh.h"
template <typename Mesh>
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 <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