use an element buffer for rendering
This commit is contained in:
parent
e56eed0a16
commit
b3d4899546
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
30
src/util.h
30
src/util.h
@ -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
|
Loading…
Reference in New Issue
Block a user